diff --git a/.gitignore b/.gitignore index bcc46c701..d6fb385f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,33 +1,2 @@ -Procfile -.env -dist/ -build/ -venv/ -venv -API/__pycache__ -API/Classes/__pycache__ -API/Classes/Base/__pycache__ -API/Classes/Case/__pycache__ -API/Routes/__pycache__ - -API/Routes/Upload/__pycache__ -API/Routes/DataFile/__pycache__ -API/Routes/Case/__pycache__ - -WebAPP/SOLVERs/GLPK -WebAPP/SOLVERs/COIN-OR -WebAPP/SOLVERs/_GLPK -WebAPP/SOLVERs/_COIN-OR - -WebAPP/DataStorage/* -!WebAPP/DataStorage/Parameters.json -!WebAPP/DataStorage/Variables.json - -WebAPP/References/jqwidgets_licenced -WebAPP/References/jqwidgets_free -WebAPP/References/jqwidgets/jqx-all-unlisenced.js -WebAPP/References/wijmoFULL/ -WebAPP/References/wijmoOLD/ -WebAPP/References/wijmo/DistributionKey.txt -WebAPP/References/wijmo/licence.js -app.spec +.idea +WebAPP/DataStorage/* \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml deleted file mode 100644 index b9af69451..000000000 --- a/.readthedocs.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 - -build: - os: ubuntu-22.04 - tools: - python: "3.10" - -sphinx: - configuration: docs/source/conf.py - -python: - install: - - requirements: docs/requirementsrtd.txt diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 0249686ea..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal" - }, - { - "name": "Python: Flask", - "type": "python", - "request": "launch", - "module": "flask", - "env": { - "FLASK_APP": "API/app.py", - "FLASK_RUN_PORT": "5002", - "FLASK_ENV": "development", - "FLASK_DEBUG": "1" - }, - "args": [ - "run", - //"--no-debugger", - "--no-reload" - ], - "jinja": true - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 202b6927a..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "python.pythonPath": "venv\\Scripts\\python.exe", - "git.ignoreLimitWarning": true -} \ No newline at end of file diff --git a/API/Classes/Case/OsemosysClass.py b/API/Classes/Case/OsemosysClass.py index f6f895986..ec1157c4b 100644 --- a/API/Classes/Case/OsemosysClass.py +++ b/API/Classes/Case/OsemosysClass.py @@ -57,8 +57,8 @@ def __init__(self, case): #self.cbcFolder = Path(Config.SOLVERs_FOLDER,'COIN-OR', 'Cbc-master-win64-msvc16-md', 'bin') else: - self.glpkFolder = Path(Config.SOLVERs_FOLDER, 'GLPK','glpk-4.65', 'w64') - self.cbcFolder = Path(Config.SOLVERs_FOLDER,'COIN-OR', 'Cbc-2.10-osx10.15-x86_64-gcc9', 'bin') + self.glpkFolder = Path(Config.SOLVERs_FOLDER, 'GLPK','glpk', 'w64') + self.cbcFolder = Path(Config.SOLVERs_FOLDER,'COIN-OR', 'Cbc', 'bin') self.resultsPath = Path(Config.DATA_STORAGE,case,'res') self.viewFolderPath = Path(Config.DATA_STORAGE,case,'view') diff --git a/API/app.py b/API/app.py index d2a976325..6208a5116 100644 --- a/API/app.py +++ b/API/app.py @@ -116,16 +116,13 @@ def setSession(): import mimetypes mimetypes.add_type('application/javascript', '.js') port = int(os.environ.get("PORT", 5002)) - print("PORTTTTTTTTTTT") - if Config.HEROKU_DEPLOY == 0: - #localhost - #app.run(host='127.0.0.1', port=port, debug=True) - #waitress server - #prod server - from waitress import serve - serve(app, host='127.0.0.1', port=port) - else: - #HEROKU - app.run(host='0.0.0.0', port=port, debug=True) - #app.run(host='127.0.0.1', port=port, debug=True) + + print(f"--- Starting App on Port {port} ---") + + # For Podman/Docker, we MUST listen on 0.0.0.0, not 127.0.0.1 + # We can detect if we are in a container, or just default to 0.0.0.0 + from waitress import serve + + print("Serving on 0.0.0.0 (Container Friendly)") + serve(app, host='0.0.0.0', port=port) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..223f9351c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# Use a lightweight Python base image +FROM python:3.10-slim + +# Prevent Python from writing pyc files to disc +ENV PYTHONDONTWRITEBYTECODE=1 +# Prevent Python from buffering stdout and stderr +ENV PYTHONUNBUFFERED=1 + +# Set the working directory inside the container +WORKDIR /app + +# Install system-level solvers (GLPK and CBC) +RUN apt-get update && apt-get install -y \ + glpk-utils \ + coinor-cbc \ + && rm -rf /var/lib/apt/lists/* + +# Copy the requirements file first (to leverage caching) +COPY requirements.txt . + +# Install dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy the rest of the application code +# This assumes 'WebAPP', 'Classes', and 'Routes' are in the same folder as Dockerfile +COPY . . +RUN chmod -R +x /app/WebAPP/SOLVERs +# Expose the port the app runs on +EXPOSE 5002 + +# Define the command to run the application +CMD ["python", "API/app.py"] \ No newline at end of file diff --git a/README.md b/README.md index 001bb8b91..5616aedc1 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,38 @@ This repository contains the user interface for the Open Source Energy Modelling 4. The App will open automatically once the installation is complete. If not, search on the Windows Taskbar for ‘’MUIO’’ and open the App. 5. You will see the MUIO in a new window. +## Installation Guide for MacOS and Linux +1. Clone the repository. + ``` + git clone https://github.com/junohBede/MUIO.git + ``` +2. Create conda environment with using the command below. If you do not have conda installed in your machine, refer to this [link.](www.anaconda.com/docs/getting-started/miniconda/install) +3. Activate conda environment with the command below. + ``` + conda activate muio + ``` +4. Replace folder “MUIO/WebAPP/SOLVERs/COIN-OR/Cbc” contents from [here.](https://github.com/coin-or/Cbc/releases/tag/releases%2F2.10.12) +5. Run `python API/app.py` in terminal. (Make sure that your current working directory is not MUIO, before running the command.) +6. Open web browser to open web app [http://127.0.0.1:5002/#/](http://127.0.0.1:5002/#/) + +## Installation Guide using Docker +**Docker** is an open platform that allows developers to automate the deployment of application inside containers. You can find more information within this [link.](https://docs.docker.com/get-started/docker-overview/) +1. Clone the repository. + ``` + git clone https://github.com/junohBede/MUIO.git + ``` +2. Build Docker image using Dockerfile of the repository. + ``` + docker build -t muio . + ``` +3. Run Docker container, with opening ports for web app. + ``` + docker run -dt -p 5002:5002 --name muio muio + ``` +4. Open web browser to open web app [http://127.0.0.1:5002/#/](http://127.0.0.1:5002/#/) + ## Questions and Issues For troubleshooting model-related issues and discussions, please visit the [Energy Modelling Community Discussion Forum](https://forum.u4ria.org/). -If you encounter bugs or have new feature ideas, please submit them to the repository's issue tracker. We encourage contributions and discussions to further develop MUIO. +If you encounter bugs or have new feature ideas, please submit them to the repository's issue tracker. We encourage contributions and discussions to further develop MUIO. \ No newline at end of file diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/LICENSE new file mode 100644 index 000000000..0a8206ba8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/LICENSE @@ -0,0 +1,245 @@ +Eclipse Public License - v 2.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE (“AGREEMENT”). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + “Contribution” means: + + a) in the case of the initial Contributor, the initial content Distributed + under this Agreement, and + b) in the case of each subsequent Contributor: + i) changes to the Program, and + ii) additions to the Program; + where such changes and/or additions to the Program originate from and + are Distributed by that particular Contributor. A Contribution + “originates” from a Contributor if it was added to the Program by such + Contributor itself or anyone acting on such Contributor's behalf. + Contributions do not include changes or additions to the Program that + are not Modified Works. “Contributor” means any person or entity that + Distributes the Program. + + “Licensed Patents” mean patent claims licensable by a Contributor which are + necessarily infringed by the use or sale of its Contribution alone or when + combined with the Program. + + “Program” means the Contributions Distributed in accordance with this + Agreement. + + “Recipient” means anyone who receives the Program under this Agreement or + any Secondary License (as applicable), including Contributors. + + “Derivative Works” shall mean any work, whether in Source Code or other + form, that is based on (or derived from) the Program and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. + + “Modified Works” shall mean any work in Source Code or other form that + results from an addition to, deletion from, or modification of the contents + of the Program, including, for purposes of clarity any new file in Source + Code form that contains any contents of the Program. Modified Works shall + not include works that contain only declarations, interfaces, types, + classes, structures, or files of the Program solely in each case in order + to link to, bind by name, or subclass the Program or Modified Works + thereof. + + “Distribute” means the acts of a) distributing or b) making available in + any manner that enables the transfer of a copy. + + “Source Code” means the form of a Program preferred for making + modifications, including but not limited to software source code, + documentation source, and configuration files. + + “Secondary License” means either the GNU General Public License, Version + 2.0, or any later versions of that license, including any exceptions or + additional permissions as identified by the initial Contributor. + +2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free copyright license to + reproduce, prepare Derivative Works of, publicly display, publicly perform, + Distribute and sublicense the Contribution of such Contributor, if any, and + such Derivative Works. + + b) Subject to the terms of this Agreement, each Contributor hereby grants + Recipient a non-exclusive, worldwide, royalty-free patent license under + Licensed Patents to make, use, sell, offer to sell, import and otherwise + transfer the Contribution of such Contributor, if any, in Source Code or + other form. This patent license shall apply to the combination of the + Contribution and the Program if, at the time the Contribution is added by + the Contributor, such addition of the Contribution causes such combination + to be covered by the Licensed Patents. The patent license shall not apply + to any other combinations which include the Contribution. No hardware per + se is licensed hereunder. + + c) Recipient understands that although each Contributor grants the licenses + to its Contributions set forth herein, no assurances are provided by any + Contributor that the Program does not infringe the patent or other + intellectual property rights of any other entity. Each Contributor + disclaims any liability to Recipient for claims brought by any other entity + based on infringement of intellectual property rights or otherwise. As a + condition to exercising the rights and licenses granted hereunder, each + Recipient hereby assumes sole responsibility to secure any other + intellectual property rights needed, if any. For example, if a third party + patent license is required to allow Recipient to Distribute the Program, it + is Recipient's responsibility to acquire that license before distributing + the Program. + + d) Each Contributor represents that to its knowledge it has sufficient + copyright rights in its Contribution, if any, to grant the copyright + license set forth in this Agreement. + + e) Notwithstanding the terms of any Secondary License, no Contributor makes + additional grants to any Recipient (other than those set forth in this + Agreement) as a result of such Recipient's receipt of the Program under the + terms of a Secondary License (if permitted under the terms of Section 3). + +3. REQUIREMENTS + +3.1 If a Contributor Distributes the Program in any form, then: + + a) the Program must also be made available as Source Code, in accordance + with section 3.2, and the Contributor must accompany the Program with a + statement that the Source Code for the Program is available under this + Agreement, and informs Recipients how to obtain it in a reasonable manner + on or through a medium customarily used for software exchange; and + + b) the Contributor may Distribute the Program under a license different + than this Agreement, provided that such license: + + i) effectively disclaims on behalf of all other Contributors all + warranties and conditions, express and implied, including warranties or + conditions of title and non-infringement, and implied warranties or + conditions of merchantability and fitness for a particular purpose; + + ii) effectively excludes on behalf of all other Contributors all + liability for damages, including direct, indirect, special, incidental + and consequential damages, such as lost profits; + + iii) does not attempt to limit or alter the recipients' rights in the + Source Code under section 3.2; and + + iv) requires any subsequent distribution of the Program by any party to + be under a license that satisfies the requirements of this section 3. + +3.2 When the Program is Distributed as Source Code: + + a) it must be made available under this Agreement, or if the Program (i) + is combined with other material in a separate file or files made available + under a Secondary License, and (ii) the initial Contributor attached to + the Source Code the notice described in Exhibit A of this Agreement, then + the Program may be made available under the terms of such Secondary + Licenses, and + + b) a copy of this Agreement must be included with each copy of the + Program. + +3.3 Contributors may not remove or alter any copyright, patent, trademark, +attribution notices, disclaimers of warranty, or limitations of liability +(‘notices’) contained within the Program from any copy of the Program which +they Distribute, provided that Contributors may add their own appropriate +notices. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, +if a Contributor includes the Program in a commercial product offering, such +Contributor (“Commercial Contributor”) hereby agrees to defend and indemnify +every other Contributor (“Indemnified Contributor”) against any losses, +damages and costs (collectively “Losses”) arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such Commercial +Contributor in connection with its distribution of the Program in a commercial +product offering. The obligations in this section do not apply to any claims +or Losses relating to any actual or alleged intellectual property +infringement. In order to qualify, an Indemnified Contributor must: a) +promptly notify the Commercial Contributor in writing of such claim, and b) +allow the Commercial Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement negotiations. The +Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If +that Commercial Contributor then makes performance claims, or offers +warranties related to Product X, those performance claims and warranties are +such Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a +court requires any other Contributor to pay any damages as a result, the +Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED +BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN “AS IS” BASIS, WITHOUT +WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, +WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely +responsible for determining the appropriateness of using and distributing the +Program and assumes all risks associated with its exercise of rights under +this Agreement, including but not limited to the risks and costs of program +errors, compliance with applicable laws, damage to or loss of data, programs +or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT PERMITTED +BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY +LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED +HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent +necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to +time. No one other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement Steward. The +Eclipse Foundation may assign the responsibility to serve as the Agreement +Steward to a suitable separate entity. Each new version of the Agreement will +be given a distinguishing version number. The Program (including +Contributions) may always be Distributed subject to the version of the +Agreement under which it was received. In addition, after a new version of the +Agreement is published, Contributor may elect to Distribute the Program +(including its Contributions) under the new version. + +Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any Contributor under +this Agreement, whether expressly, by implication, estoppel or otherwise. All +rights in the Program not expressly granted under this Agreement are reserved. +Nothing in this Agreement is intended to be enforceable by any entity that is +not a Contributor or Recipient. No third-party beneficiary rights are created +under this Agreement. + diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/README.md b/WebAPP/SOLVERs/COIN-OR/Cbc/README.md new file mode 100644 index 000000000..e39ea56a8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/README.md @@ -0,0 +1,699 @@ +# Cbc 2.10.12 + +[![A COIN-OR Project](https://coin-or.github.io/coin-or-badge.png)](https://www.coin-or.org) + +Projects such as this one are maintained by a small group of volunteers under +the auspices of the non-profit [COIN-OR Foundation](https://www.coin-or.org) +and we need your help! Please consider [sponsoring our +activities](https://github.com/sponsors/coin-or) or [volunteering](mailto:volunteer@coin-or.org) to help! + +[![Latest Release](https://img.shields.io/github/v/release/coin-or/Cbc?sort=semver)](https://github.com/coin-or/Cbc/releases) + +_This file is auto-generated from [config.yml](.coin-or/config.yml) using the +[generate_readme](.coin-or/generate_readme) script. +To make changes, please edit [config.yml](.coin-or/config.yml) or the generation scripts +[here](.coin-or/generate_readme) and [here](https://github.com/coin-or/coinbrew/blob/master/scripts/generate_readme)._ + +Cbc (*C*oin-or *b*ranch and *c*ut) is an open-source mixed integer linear programming solver written in C++. +It can be used as a callable library or using a stand-alone executable. +It can be used in a wide variety of ways through various modeling systems, packages, etc. + * Stand-alone modeling languages and systems + * AIMMS (via the [AIMMSlinks](https://github.com/coin-or/AIMMSlinks) project), + * AMPL (natively), + * [CMPL](https://github.com/coin-or/Cmpl), + * GAMS (through the [GAMSlinks](https://github.com/coin-or/GAMSlinks) project), + * Mathematica, + * Matlab (https://inverseproblem.co.nz/OPTI/) + * [MiniZinc](http://www.minizinc.org/), + * MPL (through the [CoinMP](https://github.com/coin-or/CoinMP) project), + * R (https://rdrr.io/github/yuehmeir2/myFormAssembler/man/cbc.html) + * Python-based modeling languages and extensions + * [cbcpy](https://pypi.org/project/cbcpy). + * [cvxpy](https://github.com/cvxpy/cvxpy) + * [CyLP](https://github.com/coin-or/CyLP), + * [Google's or-tools](https://developers.google.com/optimization), + * [PuLP](https://github.com/coin-or/PuLP)/[DiPPy](https://github.com/coin-or/Dip), + * [python-mip](https://github.com/coin-or/python-mip), + * [yaposib](https://github.com/coin-or/yaposib) + * Extensions in other languages + * [JuMP](https://github.com/JuliaOpt/JuMP.jl) (Julia), + * [rust-lp-modeler](https://github.com/jcavat/rust-lp-modeler) (Rust) + * [good_lp](https://github.com/rust-or/good_lp) (Rust) + * Spreadsheet extensions + * [OpenSolver for Excel](http://opensolver.org) + * [OpenSolver for Google Sheets](https://opensolver.org/opensolver-for-google-sheets/) + +Binaries for most platforms are available for download from +[Bintray](https://bintray.com/coin-or/download/Cbc). AMPL also provides +stand-alone [Cbc +executables](http://ampl.com/products/solvers/open-source/#cbc) that can be +used with (or without) AMPL. Julia provides a wide range of +[binaries](https://github.com/JuliaBinaryWrappers/Cbc_jll.jl/releases). +Alternatives include [conda](https://github.com/conda-forge/coin-or-cbc-feedstock) and +your favorite package manager, as detailed [below](https://github.com/coin-or/Cbc#binaries). + +Cbc is developed by John Forrest, now retired from IBM Research, and others. +The project is currently managed by John Forrest, [Ted +Ralphs](http://coral.ie.lehigh.edu/~ted/), [Stefan +Vigerske](https://github.com/svigerske), [Haroldo Gambini +Santos](https://github.com/h-g-s), and the rest of the Cbc team. + +Cbc is written in C++ and is released as open source under the [Eclipse Public License 2.0](http://www.opensource.org/licenses/EPL-2.0). + +It is distributed under the auspices of the [COIN-OR Foundation](https://www.coin-or.org). + +The Cbc development site is https://github.com/coin-or/Cbc. + +## CITE + +Code: [![DOI](https://zenodo.org/badge/173509563.svg)](https://zenodo.org/badge/latestdoi/173509563) + +## CURRENT BUILD STATUS + +[![Windows Builds](https://github.com/coin-or/Cbc/actions/workflows/windows-ci.yml/badge.svg?branch=releases/2.10.12)](https://github.com/coin-or/Cbc/actions/workflows/windows-ci.yml?query=branch%3Areleases/2.10.12) + +[![Linux and MacOS Builds](https://github.com/coin-or/Cbc/actions/workflows/linux-ci.yml/badge.svg?branch=releases/2.10.12)](https://github.com/coin-or/Cbc/actions/workflows/linux-ci.yml?query=branch%3Areleases/2.10.12) + +## DOWNLOAD + +What follows is a quick start guide for obtaining or building +Cbc on common platforms. More detailed information is +available [here](https://coin-or.github.io/user_introduction.html). + +### Docker image + +There is a Docker image that provides Cbc, as well as other projects +in the [COIN-OR Optimization +Suite](https://github.com/coin-or/COIN-OR-OptimizationSuite) [here](https://hub.docker.com/repository/docker/coinor/coin-or-optimization-suite) + +### Binaries + +For newer releases, binaries will be made available as assets attached to +releases in Github +[here](https://github.com/coin-or/Cbc/releases). Older binaries +are archived as part of Cbc +[here](https://www.coin-or.org/download/binary/Cbc). + + * *Linux* (see https://repology.org/project/coin-or-cbc/versions for a complete listing): + * arch: + ``` + $ sudo pacman -S coin-or-cbc + ``` + * Debian/Ubuntu: + ``` + $ sudo apt-get install coinor-cbc coinor-libcbc-dev + ``` + * Fedora/Redhat/CentOS: + ``` + $ sudo yum install coin-or-Cbc coin-or-Cbc-devel + ``` + * freebsd: + ``` + $ sudo pkg install math/cbc + ``` + * linuxbrew: + ``` + $ brew install cbc + ``` + * *Windows*: The easiest way to get Cbc on Windows is to download an archive as described above. + * *Mac OS X*: The easiest way to get Cbc on Mac OS X is through [Homebrew](https://brew.sh). + ``` + $ brew tap coin-or-tools/coinor + $ brew install coin-or-tools/coinor/cbc + ``` + +* *conda* (cross-platform, no Windows for now): + ``` + $ conda install coin-or-cbc + ``` + +Due to license incompatibilities, pre-compiled binaries lack some +functionality. If binaries are not available for your platform for the latest +version and you would like to request them to be built and posted, feel free +to let us know on the mailing list. + +### Source + +Source code can be obtained either by + + * Downloading a snapshot of the source code for the latest release version of Cbc from the + [releases](https://github.com/coin-or/Cbc/releases) page, + * Cloning this repository from [Github](https://github.com/coin-or/Cbc), or + * Using the [coinbrew](https://github.com/coin-or/coinbrew) script to get the project and all dependencies (recommended, see below). + +### Dependencies + +Cbc has a number of dependencies, which are detailed in +[config.yml](.coin-or/config.yml). Dependencies on other COIN-OR projects are +automatically downloaded when obtaining the source with `coinbrew`. For some +of the remaining third-party dependencies, automatic download scripts and +build wrappers are provided (and will also be automatically run for required +and recommended dependencies), while other libraries that are aeasy to obtain +must be installed using an appropriate package manager (or may come with your +OS by default). + +## BUILDING from source + +These quick start instructions assume you are in a bash shell. + +### Using `coinbrew` + +To download and build Cbc from source, execute the +following on the command line. +``` +wget https://raw.githubusercontent.com/coin-or/coinbrew/master/coinbrew +chmod u+x coinbrew +./coinbrew fetch Cbc@2.10.12 +./coinbrew build Cbc +``` +For more detailed instructions on coinbrew, see https://coin-or.github.io/coinbrew. +The `coinbrew` script will fetch the additional projects specified in the Dependencies section of [config.yml](.coin-or/config.yml). + +### Without `coinbrew` (Expert users) + + * Download the source code, e.g., by cloning the git repo https://github.com/coin-or/Cbc + * Download and install the source code for the dependencies listed in [config.yml](.coin-or/config.yml) + * Build the code as follows (make sure to set PKG_CONFIG_PTH to install directory for dependencies). + +``` +./configure -C +make +make test +make install +``` + +### With Microsoft Visual Studio + +For Microsoft Visual C++ users, there are project files for version 10 +available in the `MSVisualStudio` directory. First, obtain the source code +using either a Windows git client or download a snapshot. In MSVC++ Version +10, open the solution file (this should be converted to whatever version of +MSVC+ you are using) and build the Cbc project. The code should build out of +the box with default settings. + +It is also possible to build Cbc with the Visual Studio compiler from the +command line using the procedure for Unix-like environments, using the Msys2 +shell or CYGWIN. This is the recommended and best-supported way of building +Cbc in Windows from source. To do so, make sure the `cl` compiler is in your +path and add `--enable-msvc to build command of `coinbrew`. + +If you want to build a *parallel version* of CBC using Visual Studio you can +following instructions: (thanks to Tobias Stengel and Alexis Guigue). + +Assumptions: + +- A VS solution with all necessary projects (libCbc, libClp, libCbcSolver, + libCgl, libCoinUtils, libOsi, libOsiCbc, libOsiClp). The project files can + be found inside the `MSVisualStudio` folders. + +Steps (based on VS 2013): + +1. for each of the lib* projects do: + add `CBC_THREAD` under Properties -> Configuration Properties -> C/C++ -> + Preprocessor -> Preprocessor Definitions (a subset of the lib* projects may + be sufficient, but it doesn't hurt to do it for all) + +2. Link against a pthreads library. + [PThreadsWin32](https://www.sourceware.org/pthreads-win32/) works (even in + 64 bits systems) and is distributed under the LGPL. If you decide to use + the precompiled binaries: both pthreadVC2 and pthreadVS2 seem to work. + Otherwise: third party VS project files for pthreads4win can be found on + github. + + Note: If you use C++/Cli, make sure that no callback (eventHandlers, custom + cut generators, custom heuristics, ...) contains managed code. Otherwise + your code will crash at runtime with AssembyNotFoundExceptions inside the + native threads created by Cbc. Even if not, problems with the GC are + likely. + +3. If you link statically against pthreads4win, you have to define + PTW32_STATIC_LIB when building your program/Cbc (e.g. via Properties -> + C/C++/Preprocessor -> Preprocessor Definitions) AND - only if you build + pthreads yourself - when building pthreads. Linking pthreads dynamically + works without additional preprocessor definitions. + +4. pass `-threads yourNumber` to `CbcMain1` + +## Doxygen Documentation + +If you have `Doxygen` available, you can build a HTML documentation by typing + +`make doxydoc` + +in the build directory. If Cbc was built via `coinbrew`, then the build +directory will be `./build/Cbc/2.10.12` by default. The doxygen documentation main file +is found at `/doxydoc/html/index.html`. + +If you don't have `doxygen` installed locally, you can use also find the +documentation [here](http://coin-or.github.io/Cbc/Doxygen). + +## DOCUMENTATION + + * [User's Guide](https://coin-or.github.io/Cbc) (from 2005) + * Source code [examples](examples) + * [Cbc command-line guide](https://github.com/coin-or/COIN-OR-OptimizationSuite/raw/master/Installer/files/doc/cbcCommandLine.pdf) + + +## Project Links + + * [Code of Conduct](https://www.coin-or.org/code-of-conduct/) + * [COIN-OR Web Site](http://www.coin-or.org/) + * [COIN-OR general discussion forum](https://github.com/orgs/coin-or/discussions) + * [Cbc Discussion forum](https://github.com/coin-or/Cbc/discussions) + * [Report a bug](https://github.com/coin-or/Cbc/issues/new) + * [Doxygen generated documentation](http://coin-or.github.io/Cbc/Doxygen) + +## CHANGELOG + + * Release 3.0 (in preparation) + * Added possibility for incomplete MIP start files. + The filename suffix indicates which values Cbc should choose for + missing variables (see change r2549) + * Larger renovation of the build system and a changed directory structure. + As a consequence, a monolithic build of Cbc, which builds Cbc with + all its dependencies in one run of configure and make is no longer + possible. Dependencies should now be build and installed before + building Cbc. + - Removed svn:externals. Dependencies (CoinUtils, Osi, Clp, Cgl, etc) + now need to be build and installed in advance, either manually or + by using coinbrew. + - When using a GCC-compatible compiler, the Cbc interface + functions are now declared with `visibility(default)`-attribute, + thus building Cbc with `-fvisibility=hidden` still produces a + usable library. + - When using a MSVC-compatible compiler, Cbc interface functions + are now declared with `dllimport`-attribute, so that a Cbc C++ DLL + can be used. + - Under Windows/Msys2, DLLs are now build by default. + - Cygwin and MSys1 are no longer supported. + - pkg-config is now mandatory. On Windows, make sure to use a + pkg-config version that produces Unix-style paths. + - `*_addlibs` files have been removed, pkg-config should be used instead. + - Script `compile` is now used to wrap around calls of cl/icl/ifort + and translate GCC-style compiler flags to MSVC style. + - Header files are now installed in the better named + `$prefix/include/coin-or` instead of `$prefix/include/coin`. + - The default for `--prefix` is no longer the build directory, but + the autotools-default, probably `/usr/local`. + - `--enable-debug` does not imply `--disable-shared` anymore. + - Removed `--enable-debug-cbc`, use `--enable-debug` instead. + - Removed configure variables OPT/DBG_C/CXXFLAGS. Use C/CXXFLAGS instead. + - Silent build output is now enabled by default, use configure + flag `--disable-silent-rules` or call make with `V=1` to disable. + - Also for static builds, PIC objects are now generated by default, + use `--without-pic` to disable. + - The `--with-*-incdir` and `--with-*-lib` configure flags have been + replaced by corresponding `--with-*-cflags` and `--with-*-lflags` + flags. Note that the include directories need to be specified + via `-I` in `--with-*-cflags`. + * `--enable-cbc-parallel` is now enabled by default if a pthread library + is found. Use `--disable-cbc-parallel` to disable. + * Added a conflict graph infrastructure and conflict-based routines: + - `CglCliqueStrengthening`: preprocessing routine applied on set packing constraints. + - `CglBKClique`: clique cut separator based on an improved version of Bron-Kerbosch algorithm. + - `CglOddWheel`: odd-cycle separator with a lifting routine. + - New parameters in the command line: + - `cgraph`: sets the use of conflict graph-based routines (CglBKClique, CglOddWheel and CliqueStrengthening) - "off"=turns these routines off, "on"=turns these routines on, "clq"=turns these routines off and enables the cut separator of CglClique - default="on" + - `clqstr`: sets the use of the preprocessing routine based on clique strengthening (CglCliqueStrengthening) - "off"=turn off this routine, "before"=perform clique strengthening before initial solve, "after"=perform clique strengthening after initial solve - default="after". + - `clique`: sets the use of CglBKClique (on, root, ifmove, forceOn, onglobal) - default="ifmove". + - `bkpivot`: pivoting strategy used by Bron-Kerbosch algorithm in CglBKClique - 0=off, 1=random, 2=degree, 3=weight, 4=modified degree, 5=modified weight, 6=modified degree + modified weight - default=3. + - `bkmaxcalls`: maximum number of recursive calls that can be made by Bron-Kerbosch algorithm in CglBKClique - default=1000. + - `bkclqext`: strategy used to extend violated cliques found by CglBKClique - 0=off, 1=random, 2=degree, 3=modified degree, 4=reduced cost(inversely proportional), 5=reduced cost(inversely proportional) + modified degree - default = 4. + - `oddwheel`: sets the use of CglOddWheel (on, root, ifmove, forceOn, onglobal) - default = ifmove. + - `oddwext`: strategy used to search for wheel centers for the cuts found by CglOddWheel - 0=off, 1=one variable, 2=clique - default=2. + - CglClique was replaced by CglBKClique as the default clique separator in CbcSolver.cpp. + + * Release 2.10.10 + * Fix for accidental introduction of private symbol into public header. + + * Release 2.10.9 + * Improvements to symmetry handling. + * Maintenance release to push out accumulates patches. + + * Release 2.10.8 + * Re-generate binaries due to mistake in Github Actions configuration and + incorporate new release of Cgl. + + * Release 2.10.7 + * Fix a bug that would cause the unit test not to run correctly if the + MIPLIB3 project was not present + + * Release 2.10.6 + * Accumulated fixes related to build, test, and CI. + + * Release 2.10.5 + * Revert fix that stopped Clp when timelimit reached, as that lead to + all cleanup solves afterwards to stop without proper finishing and + giving wrong results + + * Release 2.10.4 + * Allow .lp files to be read from stdin. + * Fix parsing of optional arguments to AMPL interface. + * More bugfixes. + + * Release 2.10.3 + * Improve performance of some primal heuristics, incl. feasibility pump, + by making integer slacks continuous + * Added additional timelimit checks + * Fixed initialization of Cbc_clone result + * Additional bugfixes + + * Release 2.10.2 + * Bugfixes + + * Release 2.10.1 + * Fixed Cbc_clone in C interface + * Fixed CbcMain1() call in examples/driver3.cpp + * Fixed possible issue with MIPstart if presolve added variables + * More minor bugfixes + + * Release 2.10.0 + * Improved handling of SOS, starting point, and symmetries + * Improved performance of primal heuristics regarding the handling of + implicit integer variables + * Mini-B&B is now disabled when solving with multiple threads + * Changed default value for zero half cuts parameter from off to ifmove + * Added CbcModel::postProcessedSolver() to obtained LP after presolve + * New option `PrepNames` to indicate whether column names should be + kept in the pre-processed model + * New option `sosPrioritize` to determine how to prioritize SOS + * Added new event `generatedCuts` + * CbcSolver can now read compressed .lp files (GZIP, BZIP2) + * New functions in the C interface: Cbc_readLp, Cbc_writeLp, + Cbc_addCol, Cbc_addRow, Cbc_getNumIntegers, Cbc_bestSolution, + Cbc_getObjValue, Cbc_getRowNz, Cbc_getRowIndices, Cbc_getRowCoeffs, + Cbc_getRowRHS, Cbc_getRowSense, Cbc_getColNz, Cbc_getColIndices, + Cbc_getColCoeffs, Cbc_getReducedCost, Cbc_numberSavedSolutions, + Cbc_savedSolution, Cbc_savedSolutionObj, Cbc_setMIPStart, + Cbc_setMIPStartI, Cbc_addCutCallback, Osi_getNumCols, Osi_getColName, + Osi_getColLower, Osi_getColUpper, Osi_isInteger, Osi_getNumRows, + Osi_getRowNz, Osi_getRowIndices, Osi_getRowCoeffs, Osi_getRowRHS, + Osi_getRowSense, Osi_getColSolution, OsiCuts_addRowCut, + Cbc_getAllowableGap, Cbc_setAllowableGap, Cbc_getAllowableFractionGap, + Cbc_setAllowableFractionGap, Cbc_getAllowablePercentageGap, + Cbc_setAllowablePercentageGap, Cbc_getCutoff, Cbc_setCutoff, + Cbc_getMaximumNodes, Cbc_setMaximumNodes, Cbc_getMaximumSolutions, + Cbc_setMaximumSolutions, Cbc_getLogLevel, Cbc_setLogLevel, + Cbc_getMaximumSeconds, Cbc_setMaximumSeconds + * New action `guess` checks properties of the model to decide the best + parameters for solving the LP relaxation. + * New example inc.cpp to illustrate solution callback + * New example driver5.cpp to illustrate user-defined branching rule + * New example clpdriver.cpp to illustrate use of ClpEventHandler + * Added support for using OsiHiGHS with CbcGeneric + * Added MSVC 14 project files + * Bugfixes + + * Release 2.9.10 + * Fix a numerical issue + * Fix some memory leaks + * Fix issue when root node is obviously infeasible + * Performance improvements for mini-B&B + * Fix name of bound in final message + * Fix names in preprocessed problem + + * Release 2.9.9 + + * Fixes for SOS2 + * Updates to mipstart + * Switching to new build system + * Updates for CI + + * Release 2.9.8 + + * Update to most current releases of dependencies + * Small bug fixes + * Add support for automatic build and test with Travis and Appveyor + + * Release 2.9.7 + + * Small bug fixes + * Option to switch to line buffered output + + * Release 2.9.6 + + * Small bug fixes + + * Release 2.9.5 + + * Small bug fixes + + * Release 2.9.4 + + * Small fixes for stability + * Fixes for Doygen documentation generation + + * Release 2.9.3 + + * Minor bug fixes + + * Release 2.9.2 + + * Fix for proper installation with `DESTDIR` + + * Release 2.9.1 + + * Fix for dependency linking + * Minor bug fixes + + * Release 2.9.0 + + * Introduced specialized branching methods for dealing with "big Ms". + * Introduced new methods for dealing with symmetry (requires installation of [nauty](http://pallini.di.uniroma1.it/)) + * Introduction of conflict cuts (off by default, turn on with `-constraint conflict`) + + * Release 2.8.13 + + * Improved message handling + * Miscellaneous bug fixes. + + * Release 2.8.12 + + * Update for dependencies. + + * Release 2.8.11 + + * Major overhaul of C interface + * Fixes to SOS + * Miscellaneous bug fixes + + * Release 2.8.10 + + * More changes related to thread safety. + * Fix bug in build system with Visual Studio compiler. + * Miscellaneous bug fixes. + + * Release 2.8.9 + + * Attempt to make Cbc thread safe. + * Add parallel examples. + * Add CbcSolverUsefulInfo. + * Bug fixes. + + * Release 2.8.8 + + * Added example to show how to use Cbc with installed libraries in MSVC++ + * Fixed inconsistency in addition of libCbcSolver to dependencies in + {{{cbc_addlibs.txt}}}. + + * Release 2.8.7 + + * Changed so that Doxygen builds LaTex + * Fixes for build system + + * Release 2.8.6 + + * Added option to explicitly link dependencies to comply with packaging + requirements on Fedora and Debian, as well as allow building of MinGW + DLLs. + + * Release 2.8.5 + + * Minor fixes to build system + + * Release 2.8.4 + + * Small bug fixes + * Upgrades to build system + + * Release 2.8.3: + + * Fix for handling SOS. + + * Release 2.8.2: + + * Fixed recognition of Glpk source in main configure. + * Minor bug fixes in CoinUtils, Clp, and Cbc. + + * Release 2.8.1: + + * Minor bug fixes + + * Release 2.8.0: + + * Introduced new secondaryStatus 8 to indicate that solving stopped due to + an iteration limit. + * Solution pool is now accessible via the command line and the CbcMain* + interface. + * New mipstart option to read an initial feasible solution from a file. + Only values for discrete variables need to be provided. + + * Added Proximity Search heuristic by Fischetti and Monaci (off by + default): The simplest way to switch it on using stand-alone version is + `-proximity on`. + + Proximity Search is the new "No-Neighborhood Search" 0-1 MIP refinement + heuristic recently proposed by Fischetti and Monaci (2012). The idea is + to define a sub-MIP without additional constraints but with a modified + objective function intended to attract the search in the proximity of the + incumbent. The approach works well for 0-1 MIPs whose solution landscape + is not too irregular (meaning the there is reasonable probability of + finding an improved solution by flipping a small number of binary + variables), in particular when it is applied to the first heuristic + solutions found at the root node. + + * An implementation of Zero-Half-Cuts by Alberto Caprara is now available. + By default, these cuts are off. To use add to your command line + -zerohalfCuts root (or other options) or just -zero. So far, they may + help only on a small subset of problems and may need some tuning. + + The implementation of these cuts is described in G. Andreello, A. + Caprara, and M. Fischetti "Embedding Cuts in a Branch and Cut Framework: + a Computational Study with {0,1/2}-Cuts" INFORMS Journal on Computing + 19(2), 229-238, 2007 http://dx.doi.org/10.1287/ijoc.1050.0162 + + * An alternative implementation of a reduce and split cut generator by + Giacomo Nannicini is now available. By default, these cuts are off. To + use add to your command line -reduce2AndSplitCuts root (or other + options). + + The implementation of these cuts is described in G. Cornuejols and G. + Nannicini "Practical strategies for generating rank-1 split cuts in + mixed-integer linear programming" Mathematical Programming Computation + 3(4), 281-318, 2011 http://dx.doi.org/10.1007/s12532-011-0028-6 + + * An alternative robust implementation of a Gomory cut generator by Giacomo + Nannicini is now available. By default, these cuts are off. To use add to + your command line -GMI root (or other options). + + The implementation of these cuts is described in G. Cornuejols, F. + Margot, and G. Nannicini "On the safety of Gomory cut generators" + http://faculty.sutd.edu.sg/~nannicini/index.php?page=publications + + * To encourage the use of some of the more exotic/expensive cut generators + a parameter -slowcutpasses has been added. The idea is that the code does + these cuts just a few times - less than the more usual cuts. The default + is 10. The cut generators identified by "may be slow" at present are just + Lift and project and ReduceAndSplit (both versions). + + * Allow initialization of random seed by user. Pseudo-random numbers are + used in Cbc and Clp. In Clp they are used to break ties in degenerate + problems, while in Cbc heuristics such as the Feasibility Pump use them + to decide whether to round up or down. So if a different pseudo-random + seed is given to Clp then you may get a different continuous optimum and + so different cuts and heuristic solutions. This can be switched on by + setting randomSeed for Clp and/or randomCbcSeed for Cbc. The special + value of 0 tells code to use time of day for initial seed. + + * Building on this idea, Andrea Lodi, Matteo Fischetti, Michele Monaci, + Domenico Salvagnin, Yuji Shinano, and Andrea Tramontani suggest that this + idea be improved by running at the root node with multiple copies of + solver, each with its own different seed and then passing in the + solutions and cuts so that the main solver has a richer set of solutions + and possibly stronger cuts. This is switched on by setting + -multipleRootPasses. These can also be done in parallel. + + * Few changes to presolve for special variables and badly scaled problems + (in CoinUtils). + + * New option -extraVariables which switches on a trivial + re-formulation that introduces extra integer variables to group together + variables with same cost. + + * For some problems, cut generators and general branching work better if + the problem would be infeasible if the cost is too high. If the new + option -constraintFromCutoff is set, the objective function is added as a + constraint which rhs is set to the current cutoff value (objective value + of best known solution). + + * Release 2.7.8: + + * Change message when LP simplex iteration limit is hit from "Exiting on + maximum nodes" to "Exiting on maximum number of iterations" + * Fix for using overlapping SOS. + * Fixes in buildsystem. + + * Release 2.7.7: + + * Fix to report interruption on user event if SIGINT is received by + CbcSolver. model->status() should now be 5 if this event happened. Added + method CbcModel::sayEventHappened() to make cbc stop due to an 'user + event'. + + * Other minor fixes. + + * Release 2.7.6: + + * Fixes to build system. + + * Other minor fixes. + + * Release 2.7.5: + + * Fixes to get AMPL interface working again. + + * More fixes to MSVC++ files. + + * Release 2.7.4: + + * Minor bugfixes. + + * Release 2.7.3: + + * Minor bugfixes. + + * Fixes to MSVC++ files. + + * Release 2.7.2: + + * Allow row/column names for GMPL models. + + * Added CbcModel::haveMultiThreadSupport() to indicate whether Cbc library + has been compiled with multithread support. + + * Added CbcModel::waitingForMiniBranchAndBound() to indicate whether + sub-MIP heuristic is currently running. + + * Cbc shell should work with readline if configured with + `--enable-gnu-packages`. + + * Support for compressed input files (.gz, .bz2) is now enabled by default. + + * Fix problems with relative gap tolerance > 100% and further bugs. + + * Fixes for MSVC++ Version 9 files. + + * Minor fixes in buildsystem; update to BuildTools 0.7.1. + + * Release 2.7.1: + + * Fixes to MSVC++ files + + * Release 2.7.0: + + * License has been changed to the EPL. + + * Support for MSVC++ version 10 added. + + * Support for BuildTools version 0.7 to incorporate recent enhancements, + including proper library versioning in Linux, prohibiting installation of + private headers, etc. + + * Updated externals to new stable versions of dependent projects. + + * Improvements to heuristics. + + * New options for cut generation. + + * Improved reporting of results. + diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/bin/cbc b/WebAPP/SOLVERs/COIN-OR/Cbc/bin/cbc new file mode 100755 index 000000000..db1ac08e3 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/bin/cbc differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/bin/clp b/WebAPP/SOLVERs/COIN-OR/Cbc/bin/clp new file mode 100755 index 000000000..c141b5629 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/bin/clp differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchActual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchActual.hpp new file mode 100644 index 000000000..0ffbd7b8e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchActual.hpp @@ -0,0 +1,26 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcBranchActual_H +#define CbcBranchActual_H + +#include "CbcBranchBase.hpp" +#include "CoinPackedMatrix.hpp" +#include "CbcClique.hpp" +#include "CbcSOS.hpp" +#include "CbcSimpleInteger.hpp" +#include "CbcNWay.hpp" +#include "CbcSimpleIntegerPseudoCost.hpp" +#include "CbcBranchDefaultDecision.hpp" +#include "CbcFollowOn.hpp" +#include "CbcFixVariable.hpp" +#include "CbcDummyBranchingObject.hpp" +#include "CbcGeneral.hpp" +#include "CbcGeneralDepth.hpp" +#include "CbcSubProblem.hpp" +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchAllDifferent.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchAllDifferent.hpp new file mode 100644 index 000000000..2c9315d2d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchAllDifferent.hpp @@ -0,0 +1,61 @@ +// $Id$ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/13/2009-- carved out of CbcBranchCut + +#ifndef CbcBranchAllDifferent_H +#define CbcBranchAllDifferent_H + +#include "CbcBranchBase.hpp" +#include "OsiRowCut.hpp" +#include "CoinPackedMatrix.hpp" +#include "CbcBranchCut.hpp" + +/** Define a branch class that branches so that it is only satsified if all + members have different values + So cut is x <= y-1 or x >= y+1 +*/ + +class CbcBranchAllDifferent : public CbcBranchCut { + +public: + // Default Constructor + CbcBranchAllDifferent(); + + /** Useful constructor - passed set of integer variables which must all be different + */ + CbcBranchAllDifferent(CbcModel *model, int number, const int *which); + + // Copy constructor + CbcBranchAllDifferent(const CbcBranchAllDifferent &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcBranchAllDifferent &operator=(const CbcBranchAllDifferent &rhs); + + // Destructor + ~CbcBranchAllDifferent(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + +protected: + /// data + + /// Number of entries + int numberInSet_; + /// Which variables + int *which_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchBase.hpp new file mode 100644 index 000000000..51b9530a2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchBase.hpp @@ -0,0 +1,79 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcBranchBase_H +#define CbcBranchBase_H + +#include +#include +#include "OsiBranchingObject.hpp" + +enum CbcRangeCompare { + CbcRangeSame, + CbcRangeDisjoint, + CbcRangeSubset, + CbcRangeSuperset, + CbcRangeOverlap +}; + +#include "CbcObject.hpp" +#include "CbcBranchingObject.hpp" +#include "CbcBranchDecision.hpp" +#include "CbcConsequence.hpp" +#include "CbcObjectUpdateData.hpp" + +//############################################################################## + +/** Compare two ranges. The two bounds arrays are both of size two and + describe closed intervals. Return the appropriate CbcRangeCompare value + (first argument being the sub/superset if that's the case). In case of + overlap (and if \c replaceIfOverlap is true) replace the content of thisBd + with the intersection of the ranges. +*/ +static inline CbcRangeCompare +CbcCompareRanges(double *thisBd, const double *otherBd, + const bool replaceIfOverlap) +{ + const double lbDiff = thisBd[0] - otherBd[0]; + if (lbDiff < 0) { // lb of this < lb of other + if (thisBd[1] >= otherBd[1]) { // ub of this >= ub of other + return CbcRangeSuperset; + } else if (thisBd[1] < otherBd[0]) { + return CbcRangeDisjoint; + } else { + // overlap + if (replaceIfOverlap) { + thisBd[0] = otherBd[0]; + } + return CbcRangeOverlap; + } + } else if (lbDiff > 0) { // lb of this > lb of other + if (thisBd[1] <= otherBd[1]) { // ub of this <= ub of other + return CbcRangeSubset; + } else if (thisBd[0] > otherBd[1]) { + return CbcRangeDisjoint; + } else { + // overlap + if (replaceIfOverlap) { + thisBd[1] = otherBd[1]; + } + return CbcRangeOverlap; + } + } else { // lb of this == lb of other + if (thisBd[1] == otherBd[1]) { + return CbcRangeSame; + } + return thisBd[1] < otherBd[1] ? CbcRangeSubset : CbcRangeSuperset; + } + + return CbcRangeSame; // fake return +} + +//############################################################################# + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchCut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchCut.hpp new file mode 100644 index 000000000..bb75b76b7 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchCut.hpp @@ -0,0 +1,182 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcBranchCut_H +#define CbcBranchCut_H + +#include "CbcBranchBase.hpp" +#include "OsiRowCut.hpp" +#include "CoinPackedMatrix.hpp" + +/** Define a cut branching class. + At present empty - all stuff in descendants +*/ + +class CbcBranchCut : public CbcObject { + +public: + // Default Constructor + CbcBranchCut(); + + /** In to maintain normal methods + */ + CbcBranchCut(CbcModel *model); + // Copy constructor + CbcBranchCut(const CbcBranchCut &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcBranchCut &operator=(const CbcBranchCut &rhs); + + // Destructor + ~CbcBranchCut(); + + /// Infeasibility + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /** Set bounds to contain the current solution. + + More precisely, for the variable associated with this object, take the + value given in the current solution, force it within the current bounds + if required, then set the bounds to fix the variable at the integer + nearest the solution value. + + At present this will do nothing + */ + virtual void feasibleRegion(); + + /** \brief Return true if branch created by object should fix variables + */ + virtual bool boundBranch() const; + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in the good direction. + + The preferred branching object will force the variable to be +/-1 from + its current value, depending on the reduced cost and objective sense. If + movement in the direction which improves the objective is impossible due + to bounds on the variable, the branching object will move in the other + direction. If no movement is possible, the method returns NULL. + + Only the bounds on this variable are considered when determining if the new + point is feasible. + + At present this does nothing + */ + virtual CbcBranchingObject *preferredNewFeasible() const; + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in a bad direction. + + As for preferredNewFeasible(), but the preferred branching object will + force movement in a direction that degrades the objective. + + At present this does nothing + */ + virtual CbcBranchingObject *notPreferredNewFeasible() const; + + using CbcObject::resetBounds; + /** Reset original upper and lower bound values from the solver. + + Handy for updating bounds held in this object after bounds held in the + solver have been tightened. + */ + virtual void resetBounds(); + +protected: + /// data +}; +/** Cut branching object + + This object can specify a two-way branch in terms of two cuts +*/ + +class CbcCutBranchingObject : public CbcBranchingObject { + +public: + /// Default constructor + CbcCutBranchingObject(); + + /** Create a cut branching object + + Cut down will applied on way=-1, up on way==1 + Assumed down will be first so way_ set to -1 + */ + CbcCutBranchingObject(CbcModel *model, OsiRowCut &down, OsiRowCut &up, bool canFix); + + /// Copy constructor + CbcCutBranchingObject(const CbcCutBranchingObject &); + + /// Assignment operator + CbcCutBranchingObject &operator=(const CbcCutBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcCutBranchingObject(); + + using CbcBranchingObject::branch; + /** \brief Sets the bounds for variables or adds a cut depending on the + current arm of the branch and advances the object state to the next arm. + Returns change in guessed objective on next branch + */ + virtual double branch(); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** \brief Return true if branch should fix variables + */ + virtual bool boundBranch() const; + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return CutBranchingObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +protected: + /// Cut for the down arm (way_ = -1) + OsiRowCut down_; + /// Cut for the up arm (way_ = 1) + OsiRowCut up_; + /// True if one way can fix variables + bool canFix_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDecision.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDecision.hpp new file mode 100644 index 000000000..72785a134 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDecision.hpp @@ -0,0 +1,135 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/12/2009 carved from CbcBranchBase + +#ifndef CbcBranchDecision_H +#define CbcBranchDecision_H + +#include "CbcBranchBase.hpp" + +/** Abstract branching decision base class + + In the abstract, an CbcBranchDecision object is expected to be able to + compare two possible branching choices. + + The #betterBranch() method is the crucial routine. It is expected to be able + to compare two \link CbcBranchingObject CbcBranchingObjects \endlink. + + See CbcObject for an overview of the three classes (CbcObject, + CbcBranchingObject, and CbcBranchDecision) which make up cbc's branching + model. +*/ +class CbcModel; +class OsiChooseVariable; + +class CbcBranchDecision { +public: + /// Default Constructor + CbcBranchDecision(); + + // Copy constructor + CbcBranchDecision(const CbcBranchDecision &); + + /// Destructor + virtual ~CbcBranchDecision(); + + /// Clone + virtual CbcBranchDecision *clone() const = 0; + + /// Initialize e.g. before starting to choose a branch at a node + virtual void initialize(CbcModel *model) = 0; + + /** \brief Compare two branching objects. Return nonzero if branching + using \p thisOne is better than branching using \p bestSoFar. + + If \p bestSoFar is NULL, the routine should return a nonzero value. + This routine is used only after strong branching. + Either this or bestBranch is used depending which user wants. + + */ + + virtual int + betterBranch(CbcBranchingObject *thisOne, + CbcBranchingObject *bestSoFar, + double changeUp, int numberInfeasibilitiesUp, + double changeDown, int numberInfeasibilitiesDown) + = 0; + + /** \brief Compare N branching objects. Return index of best + and sets way of branching in chosen object. + + Either this or betterBranch is used depending which user wants. + */ + + virtual int + bestBranch(CbcBranchingObject **objects, int numberObjects, int numberUnsatisfied, + double *changeUp, int *numberInfeasibilitiesUp, + double *changeDown, int *numberInfeasibilitiesDown, + double objectiveValue); + + /** Says whether this method can handle both methods - + 1 better, 2 best, 3 both */ + virtual int whichMethod() + { + return 2; + } + + /** Saves a clone of current branching object. Can be used to update + information on object causing branch - after branch */ + virtual void saveBranchingObject(OsiBranchingObject *) {} + /** Pass in information on branch just done. + assumes object can get information from solver */ + virtual void updateInformation(OsiSolverInterface *, + const CbcNode *) {} + /** Sets or gets best criterion so far */ + virtual void setBestCriterion(double) {} + virtual double getBestCriterion() const + { + return 0.0; + } + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + /// Model + inline CbcModel *cbcModel() const + { + return model_; + } + /* If chooseMethod_ id non-null then the rest is fairly pointless + as choosemethod_ will be doing all work + This comment makes more sense if you realise that there's a conversion in + process from the Cbc branching classes to Osi branching classes. The test + for use of the Osi branching classes is CbcModel::branchingMethod_ + non-null (i.e., it points to one of these CbcBranchDecision objects) and + that branch decision object has an OsiChooseVariable method set. In which + case, we'll use it, rather than the choose[*]Variable methods defined in + CbcNode. + */ + + OsiChooseVariable *chooseMethod() const + { + return chooseMethod_; + } + /// Set (clone) chooseMethod + void setChooseMethod(const OsiChooseVariable &method); + +protected: + // Clone of branching object + CbcBranchingObject *object_; + /// Pointer to model + CbcModel *model_; + /* If chooseMethod_ id non-null then the rest is fairly pointless + as choosemethod_ will be doing all work + */ + OsiChooseVariable *chooseMethod_; + +private: + /// Assignment is illegal + CbcBranchDecision &operator=(const CbcBranchDecision &rhs); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDefaultDecision.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDefaultDecision.hpp new file mode 100644 index 000000000..b93e48a05 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDefaultDecision.hpp @@ -0,0 +1,101 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcBranchDefaultDecision_H +#define CbcBranchDefaultDecision_H + +#include "CbcBranchBase.hpp" +/** Branching decision default class + + This class implements a simple default algorithm + (betterBranch()) for choosing a branching variable. +*/ + +class CbcBranchDefaultDecision : public CbcBranchDecision { +public: + // Default Constructor + CbcBranchDefaultDecision(); + + // Copy constructor + CbcBranchDefaultDecision(const CbcBranchDefaultDecision &); + + virtual ~CbcBranchDefaultDecision(); + + /// Clone + virtual CbcBranchDecision *clone() const; + + /// Initialize, e.g. before the start of branch selection at a node + virtual void initialize(CbcModel *model); + + /** \brief Compare two branching objects. Return nonzero if \p thisOne is + better than \p bestSoFar. + + The routine compares branches using the values supplied in \p numInfUp and + \p numInfDn until a solution is found by search, after which it uses the + values supplied in \p changeUp and \p changeDn. The best branching object + seen so far and the associated parameter values are remembered in the + \c CbcBranchDefaultDecision object. The nonzero return value is +1 if the + up branch is preferred, -1 if the down branch is preferred. + + As the names imply, the assumption is that the values supplied for + \p numInfUp and \p numInfDn will be the number of infeasibilities reported + by the branching object, and \p changeUp and \p changeDn will be the + estimated change in objective. Other measures can be used if desired. + + Because an \c CbcBranchDefaultDecision object remembers the current best + branching candidate (#bestObject_) as well as the values used in the + comparison, the parameter \p bestSoFar is redundant, hence unused. + */ + virtual int betterBranch(CbcBranchingObject *thisOne, + CbcBranchingObject *bestSoFar, + double changeUp, int numInfUp, + double changeDn, int numInfDn); + /** Sets or gets best criterion so far */ + virtual void setBestCriterion(double value); + virtual double getBestCriterion() const; + + /** \brief Compare N branching objects. Return index of best + and sets way of branching in chosen object. + + This routine is used only after strong branching. + */ + + virtual int + bestBranch(CbcBranchingObject **objects, int numberObjects, int numberUnsatisfied, + double *changeUp, int *numberInfeasibilitiesUp, + double *changeDown, int *numberInfeasibilitiesDown, + double objectiveValue); + +private: + /// Illegal Assignment operator + CbcBranchDefaultDecision &operator=(const CbcBranchDefaultDecision &rhs); + + /// data + + /// "best" so far + double bestCriterion_; + + /// Change up for best + double bestChangeUp_; + + /// Number of infeasibilities for up + int bestNumberUp_; + + /// Change down for best + double bestChangeDown_; + + /// Pointer to best branching object + CbcBranchingObject *bestObject_; + + /// Number of infeasibilities for down + int bestNumberDown_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDynamic.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDynamic.hpp new file mode 100644 index 000000000..726f8ad92 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchDynamic.hpp @@ -0,0 +1,210 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcBranchDynamic_H +#define CbcBranchDynamic_H + +#include "CoinPackedMatrix.hpp" +#include "CbcSimpleIntegerDynamicPseudoCost.hpp" +#include "CbcBranchActual.hpp" + +/** Branching decision dynamic class + + This class implements a simple algorithm + (betterBranch()) for choosing a branching variable when dynamic pseudo costs. +*/ + +class CbcBranchDynamicDecision : public CbcBranchDecision { +public: + // Default Constructor + CbcBranchDynamicDecision(); + + // Copy constructor + CbcBranchDynamicDecision(const CbcBranchDynamicDecision &); + + virtual ~CbcBranchDynamicDecision(); + + /// Clone + virtual CbcBranchDecision *clone() const; + + /// Initialize, e.g. before the start of branch selection at a node + virtual void initialize(CbcModel *model); + + /** \brief Compare two branching objects. Return nonzero if \p thisOne is + better than \p bestSoFar. + + The routine compares branches using the values supplied in \p numInfUp and + \p numInfDn until a solution is found by search, after which it uses the + values supplied in \p changeUp and \p changeDn. The best branching object + seen so far and the associated parameter values are remembered in the + \c CbcBranchDynamicDecision object. The nonzero return value is +1 if the + up branch is preferred, -1 if the down branch is preferred. + + As the names imply, the assumption is that the values supplied for + \p numInfUp and \p numInfDn will be the number of infeasibilities reported + by the branching object, and \p changeUp and \p changeDn will be the + estimated change in objective. Other measures can be used if desired. + + Because an \c CbcBranchDynamicDecision object remembers the current best + branching candidate (#bestObject_) as well as the values used in the + comparison, the parameter \p bestSoFar is redundant, hence unused. + */ + virtual int betterBranch(CbcBranchingObject *thisOne, + CbcBranchingObject *bestSoFar, + double changeUp, int numInfUp, + double changeDn, int numInfDn); + /** Sets or gets best criterion so far */ + virtual void setBestCriterion(double value); + virtual double getBestCriterion() const; + /** Says whether this method can handle both methods - + 1 better, 2 best, 3 both */ + virtual int whichMethod() + { + return 3; + } + + /** Saves a clone of current branching object. Can be used to update + information on object causing branch - after branch */ + virtual void saveBranchingObject(OsiBranchingObject *object); + /** Pass in information on branch just done. + assumes object can get information from solver */ + virtual void updateInformation(OsiSolverInterface *solver, + const CbcNode *node); + +private: + /// Illegal Assignment operator + CbcBranchDynamicDecision &operator=(const CbcBranchDynamicDecision &rhs); + + /// data + + /// "best" so far + double bestCriterion_; + + /// Change up for best + double bestChangeUp_; + + /// Number of infeasibilities for up + int bestNumberUp_; + + /// Change down for best + double bestChangeDown_; + + /// Number of infeasibilities for down + int bestNumberDown_; + + /// Pointer to best branching object + CbcBranchingObject *bestObject_; +}; +/** Simple branching object for an integer variable with pseudo costs + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class CbcDynamicPseudoCostBranchingObject : public CbcIntegerBranchingObject { + +public: + /// Default constructor + CbcDynamicPseudoCostBranchingObject(); + + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be is lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + CbcDynamicPseudoCostBranchingObject(CbcModel *model, int variable, + int way, double value, + CbcSimpleIntegerDynamicPseudoCost *object); + + /** Create a degenerate branch object + + Specifies a `one-way branch'. Calling branch() for this object will + always result in lowerValue <= x <= upperValue. Used to fix a variable + when lowerValue = upperValue. + */ + + CbcDynamicPseudoCostBranchingObject(CbcModel *model, int variable, int way, + double lowerValue, double upperValue); + + /// Copy constructor + CbcDynamicPseudoCostBranchingObject(const CbcDynamicPseudoCostBranchingObject &); + + /// Assignment operator + CbcDynamicPseudoCostBranchingObject &operator=(const CbcDynamicPseudoCostBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcDynamicPseudoCostBranchingObject(); + + /// Does part of constructor + void fillPart(int variable, + int way, double value, + CbcSimpleIntegerDynamicPseudoCost *object); + + using CbcBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + This version also changes guessed objective value + */ + virtual double branch(); + + /** Some branchingObjects may claim to be able to skip + strong branching. If so they have to fill in CbcStrongInfo. + The object mention in incoming CbcStrongInfo must match. + Returns nonzero if skip is wanted */ + virtual int fillStrongInfo(CbcStrongInfo &info); + + /// Change in guessed + inline double changeInGuessed() const + { + return changeInGuessed_; + } + /// Set change in guessed + inline void setChangeInGuessed(double value) + { + changeInGuessed_ = value; + } + /// Return object + inline CbcSimpleIntegerDynamicPseudoCost *object() const + { + return object_; + } + /// Set object + inline void setObject(CbcSimpleIntegerDynamicPseudoCost *object) + { + object_ = object; + } + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return DynamicPseudoCostBranchObj; + } + + // LL: compareOriginalObject and compareBranchingObject are inherited from + // CbcIntegerBranchingObject thus need not be declared/defined here. After + // all, this kind of branching object is simply using pseudocosts to make + // decisions, but once the decisions are made they are the same kind as in + // the underlying class. + +protected: + /// Change in guessed objective value for next branch + double changeInGuessed_; + /// Pointer back to object + CbcSimpleIntegerDynamicPseudoCost *object_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchLotsize.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchLotsize.hpp new file mode 100644 index 000000000..8b106a9e1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchLotsize.hpp @@ -0,0 +1,249 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcBranchLotsize_H +#define CbcBranchLotsize_H + +#include "CbcBranchBase.hpp" +/** Lotsize class */ + +class CbcLotsize : public CbcObject { + +public: + // Default Constructor + CbcLotsize(); + + /* Useful constructor - passed model index. + Also passed valid values - if range then pairs + */ + CbcLotsize(CbcModel *model, int iColumn, + int numberPoints, const double *points, bool range = false); + + // Copy constructor + CbcLotsize(const CbcLotsize &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcLotsize &operator=(const CbcLotsize &rhs); + + // Destructor + ~CbcLotsize(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /** Set bounds to contain the current solution. + + More precisely, for the variable associated with this object, take the + value given in the current solution, force it within the current bounds + if required, then set the bounds to fix the variable at the integer + nearest the solution value. + */ + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in the good direction. + + The preferred branching object will force the variable to be +/-1 from + its current value, depending on the reduced cost and objective sense. If + movement in the direction which improves the objective is impossible due + to bounds on the variable, the branching object will move in the other + direction. If no movement is possible, the method returns NULL. + + Only the bounds on this variable are considered when determining if the new + point is feasible. + */ + virtual CbcBranchingObject *preferredNewFeasible() const; + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in a bad direction. + + As for preferredNewFeasible(), but the preferred branching object will + force movement in a direction that degrades the objective. + */ + virtual CbcBranchingObject *notPreferredNewFeasible() const; + + /** Reset original upper and lower bound values from the solver. + + Handy for updating bounds held in this object after bounds held in the + solver have been tightened. + */ + virtual void resetBounds(const OsiSolverInterface *solver); + + /** Finds range of interest so value is feasible in range range_ or infeasible + between hi[range_] and lo[range_+1]. Returns true if feasible. + */ + bool findRange(double value) const; + + /** Returns floor and ceiling + */ + virtual void floorCeiling(double &floorLotsize, double &ceilingLotsize, double value, + double tolerance) const; + + /// Model column number + inline int modelSequence() const + { + return columnNumber_; + } + /// Set model column number + inline void setModelSequence(int value) + { + columnNumber_ = value; + } + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + /// Original variable bounds + inline double originalLowerBound() const + { + return bound_[0]; + } + inline double originalUpperBound() const + { + return bound_[rangeType_ * numberRanges_ - 1]; + } + /// Type - 1 points, 2 ranges + inline int rangeType() const + { + return rangeType_; + } + /// Number of points + inline int numberRanges() const + { + return numberRanges_; + } + /// Ranges + inline double *bound() const + { + return bound_; + } + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return false; + } + +private: + /// Just for debug (CBC_PRINT defined in CbcBranchLotsize.cpp) + void printLotsize(double value, bool condition, int type) const; + +protected: + /// data + + /// Column number in model + int columnNumber_; + /// Type - 1 points, 2 ranges + int rangeType_; + /// Number of points + int numberRanges_; + // largest gap + double largestGap_; + /// Ranges + double *bound_; + /// Current range + mutable int range_; +}; + +/** Lotsize branching object + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class CbcLotsizeBranchingObject : public CbcBranchingObject { + +public: + /// Default constructor + CbcLotsizeBranchingObject(); + + /** Create a lotsize floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be is lb <= x <= valid range below(x*), the other valid range above(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + CbcLotsizeBranchingObject(CbcModel *model, int variable, + int way, double value, const CbcLotsize *lotsize); + + /** Create a degenerate branch object + + Specifies a `one-way branch'. Calling branch() for this object will + always result in lowerValue <= x <= upperValue. Used to fix in valid range + */ + + CbcLotsizeBranchingObject(CbcModel *model, int variable, int way, + double lowerValue, double upperValue); + + /// Copy constructor + CbcLotsizeBranchingObject(const CbcLotsizeBranchingObject &); + + /// Assignment operator + CbcLotsizeBranchingObject &operator=(const CbcLotsizeBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcLotsizeBranchingObject(); + + using CbcBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + */ + virtual double branch(); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return LotsizeBranchObj; + } + + // LL: compareOriginalObject can be inherited from the CbcBranchingObject + // since variable_ uniquely defines the lot sizing object. + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +protected: + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchToFixLots.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchToFixLots.hpp new file mode 100644 index 000000000..5e10addbd --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchToFixLots.hpp @@ -0,0 +1,94 @@ +// $Id$ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/13/2009-- carved out of CbcBranchCut + +#ifndef CbcBranchToFixLots_H +#define CbcBranchToFixLots_H + +#include "CbcBranchCut.hpp" +#include "CbcBranchBase.hpp" +#include "OsiRowCut.hpp" +#include "CoinPackedMatrix.hpp" + +/** Define a branch class that branches so that one way variables are fixed + while the other way cuts off that solution. + a) On reduced cost + b) When enough ==1 or <=1 rows have been satisfied (not fixed - satisfied) +*/ + +class CbcBranchToFixLots : public CbcBranchCut { + +public: + // Default Constructor + CbcBranchToFixLots(); + + /** Useful constructor - passed reduced cost tolerance and fraction we would like fixed. + Also depth level to do at. + Also passed number of 1 rows which when clean triggers fix + Always does if all 1 rows cleaned up and number>0 or if fraction columns reached + Also whether to create branch if can't reach fraction. + */ + CbcBranchToFixLots(CbcModel *model, double djTolerance, + double fractionFixed, int depth, + int numberClean = 0, + const char *mark = NULL, + bool alwaysCreate = false); + + // Copy constructor + CbcBranchToFixLots(const CbcBranchToFixLots &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcBranchToFixLots &operator=(const CbcBranchToFixLots &rhs); + + // Destructor + ~CbcBranchToFixLots(); + + /** Does a lot of the work, + Returns 0 if no good, 1 if dj, 2 if clean, 3 if both + FIXME: should use enum or equivalent to make these numbers clearer. + */ + int shallWe() const; + + /// Infeasibility for an integer variable - large is 0.5, but also can be infinity when known infeasible. + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return true; + } + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns); + +protected: + /// data + + /// Reduced cost tolerance i.e. dj has to be >= this before fixed + double djTolerance_; + /// We only need to make sure this fraction fixed + double fractionFixed_; + /// Never fix ones marked here + char *mark_; + /// Matrix by row + CoinPackedMatrix matrixByRow_; + /// Do if depth multiple of this + int depth_; + /// number of ==1 rows which need to be clean + int numberClean_; + /// If true then always create branch + bool alwaysCreate_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchingObject.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchingObject.hpp new file mode 100644 index 000000000..681f43e54 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcBranchingObject.hpp @@ -0,0 +1,245 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/12/2009 carved from CbcBranchBase + +#ifndef CbcBranchingObject_H +#define CbcBranchingObject_H + +#include +#include +#include "CbcBranchBase.hpp" +#include "OsiBranchingObject.hpp" + +// The types of objects that will be derived from this class. +enum CbcBranchObjType { + SimpleIntegerBranchObj = 100, + SimpleIntegerDynamicPseudoCostBranchObj = 101, + CliqueBranchObj = 102, + LongCliqueBranchObj = 103, + SoSBranchObj = 104, + NWayBranchObj = 105, + FollowOnBranchObj = 106, + DummyBranchObj = 107, + GeneralDepthBranchObj = 108, + OneGeneralBranchingObj = 110, + CutBranchingObj = 200, + LotsizeBranchObj = 300, + DynamicPseudoCostBranchObj = 400 +}; + +/** \brief Abstract branching object base class + Now just difference with OsiBranchingObject + + In the abstract, an CbcBranchingObject contains instructions for how to + branch. We want an abstract class so that we can describe how to branch on + simple objects (e.g., integers) and more exotic objects + (e.g., cliques or hyperplanes). + + The #branch() method is the crucial routine: it is expected to be able to + step through a set of branch arms, executing the actions required to create + each subproblem in turn. The base class is primarily virtual to allow for + a wide range of problem modifications. + + See CbcObject for an overview of the three classes (CbcObject, + CbcBranchingObject, and CbcBranchDecision) which make up cbc's branching + model. +*/ + +class CbcBranchingObject : public OsiBranchingObject { + +public: + /// Default Constructor + CbcBranchingObject(); + + /// Constructor + CbcBranchingObject(CbcModel *model, int variable, int way, double value); + + /// Copy constructor + CbcBranchingObject(const CbcBranchingObject &); + + /// Assignment operator + CbcBranchingObject &operator=(const CbcBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const = 0; + + /// Destructor + virtual ~CbcBranchingObject(); + + /** Some branchingObjects may claim to be able to skip + strong branching. If so they have to fill in CbcStrongInfo. + The object mention in incoming CbcStrongInfo must match. + Returns nonzero if skip is wanted */ + virtual int fillStrongInfo(CbcStrongInfo &) + { + return 0; + } + /// Reset number of branches left to original + inline void resetNumberBranchesLeft() + { + branchIndex_ = 0; + } + /// Set number of branches to do + inline void setNumberBranches(int value) + { + branchIndex_ = 0; + numberBranches_ = value; + } + + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. Mainly for diagnostics, whether it is true branch or + strong branching is also passed. + Returns change in guessed objective on next branch + */ + virtual double branch() = 0; + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. Mainly for diagnostics, whether it is true branch or + strong branching is also passed. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface *) + { + return branch(); + } + /** Update bounds in solver as in 'branch' and update given bounds. + branchState is -1 for 'down' +1 for 'up' */ + virtual void fix(OsiSolverInterface *, + double *, double *, + int) const {} + + /** Change (tighten) bounds in object to reflect bounds in solver. + Return true if now fixed */ + virtual bool tighten(OsiSolverInterface *) { return false; } + + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch() + { + assert(branchIndex_ > 0); + branchIndex_--; + way_ = -way_; + } + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print() const {} + + /** \brief Index identifying the associated CbcObject within its class. + + The name is misleading, and typically the index will not refer + directly to a variable. + Rather, it identifies an CbcObject within the class of similar + CbcObjects + + E.g., for an CbcSimpleInteger, variable() is the index of the + integer variable in the set of integer variables (not the index of + the variable in the set of all variables). + */ + inline int variable() const + { + return variable_; + } + + /** Get the state of the branching object + + Returns a code indicating the active arm of the branching object. + The precise meaning is defined in the derived class. + + \sa #way_ + */ + inline int way() const + { + return way_; + } + + /** Set the state of the branching object. + + See #way() + */ + inline void way(int way) + { + way_ = way; + } + + /// update model + inline void setModel(CbcModel *model) + { + model_ = model; + } + /// Return model + inline CbcModel *model() const + { + return model_; + } + + /// Return pointer back to object which created + inline CbcObject *object() const + { + return originalCbcObject_; + } + /// Set pointer back to object which created + inline void setOriginalObject(CbcObject *object) + { + originalCbcObject_ = object; + } + + // Methods used in heuristics + + /** Return the type (an integer identifier) of \c this. + See definition of CbcBranchObjType above for possibilities + */ + + virtual CbcBranchObjType type() const = 0; + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const + { + const CbcBranchingObject *br = dynamic_cast< const CbcBranchingObject * >(brObj); + return variable() - br->variable(); + } + + /** Compare the \c this with \c brObj. \c this and \c brObj must be of the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false) = 0; + +protected: + /// The model that owns this branching object + CbcModel *model_; + /// Pointer back to object which created + CbcObject *originalCbcObject_; + + /// Branching variable (0 is first integer) + int variable_; + // was - Way to branch - -1 down (first), 1 up, -2 down (second), 2 up (second) + /** The state of the branching object. + + Specifies the active arm of the branching object. Coded as -1 to take + the `down' arm, +1 for the `up' arm. `Down' and `up' are defined based on + the natural meaning (floor and ceiling, respectively) for a simple integer. + The precise meaning is defined in the derived class. + */ + int way_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcClique.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcClique.hpp new file mode 100644 index 000000000..4eb20a716 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcClique.hpp @@ -0,0 +1,309 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/9/2009-- carved out of CbcBranchActual + +#ifndef CbcClique_H +#define CbcClique_H + +/** \brief Branching object for cliques + + A clique is defined to be a set of binary variables where fixing any one + variable to its `strong' value fixes all other variables. An example is the + most common SOS1 construction: a set of binary variables x_j s.t. SUM{j} + x_j = 1. Setting any one variable to 1 forces all other variables to 0. + (See comments for CbcSOS below.) + + Other configurations are possible, however: Consider x1-x2+x3 <= 0. + Setting x1 (x3) to 1 forces x2 to 1 and x3 (x1) to 0. Setting x2 to 0 + forces x1 and x3 to 0. + + The proper point of view to take when interpreting CbcClique is + `generalisation of SOS1 on binary variables.' To get into the proper frame + of mind, here's an example. + + Consider the following sequence, where x_j = (1-y_j): + \verbatim + x1 + x2 + x3 <= 1 all strong at 1 + x1 - y2 + x3 <= 0 y2 strong at 0; x1, x3 strong at 1 + -y1 - y2 + x3 <= -1 y1, y2 strong at 0, x3 strong at 1 + -y1 - y2 - y3 <= -2 all strong at 0 + \endverbatim + The first line is a standard SOS1 on binary variables. + + Variables with +1 coefficients are `SOS-style' and variables with -1 + coefficients are `non-SOS-style'. So #numberNonSOSMembers_ simply tells you + how many variables have -1 coefficients. The implicit rhs for a clique is + 1-numberNonSOSMembers_. +*/ +class CbcClique : public CbcObject { + +public: + /// Default Constructor + CbcClique(); + + /** Useful constructor (which are integer indices) slack can denote a slack + in set. If type == NULL then as if 1 + */ + CbcClique(CbcModel *model, int cliqueType, int numberMembers, + const int *which, const char *type, + int identifier, int slack = -1); + + /// Copy constructor + CbcClique(const CbcClique &); + + /// Clone + virtual CbcObject *clone() const; + + /// Assignment operator + CbcClique &operator=(const CbcClique &rhs); + + /// Destructor + virtual ~CbcClique(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// Number of members + inline int numberMembers() const + { + return numberMembers_; + } + /** \brief Number of variables with -1 coefficient + + Number of non-SOS members, i.e., fixing to zero is strong. + See comments at head of class, and comments for #type_. + */ + inline int numberNonSOSMembers() const + { + return numberNonSOSMembers_; + } + + /// Members (indices in range 0 ... numberIntegers_-1) + inline const int *members() const + { + return members_; + } + + /*! \brief Type of each member, i.e., which way is strong. + + This also specifies whether a variable has a +1 or -1 coefficient. + - 0 => -1 coefficient, 0 is strong value + - 1 => +1 coefficient, 1 is strong value + If unspecified, all coefficients are assumed to be positive. + + Indexed as 0 .. numberMembers_-1 + */ + inline char type(int index) const + { + if (type_) + return type_[index]; + else + return 1; + } + + /// Clique type: 0 is <=, 1 is == + inline int cliqueType() const + { + return cliqueType_; + } + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns); + +protected: + /// data + /// Number of members + int numberMembers_; + + /// Number of Non SOS members i.e. fixing to zero is strong + int numberNonSOSMembers_; + + /// Members (indices in range 0 ... numberIntegers_-1) + int *members_; + + /** \brief Strong value for each member. + + This also specifies whether a variable has a +1 or -1 coefficient. + - 0 => -1 coefficient, 0 is strong value + - 1 => +1 coefficient, 1 is strong value + If unspecified, all coefficients are assumed to be positive. + + Indexed as 0 .. numberMembers_-1 + */ + char *type_; + + /** \brief Clique type + + 0 defines a <= relation, 1 an equality. The assumed value of the rhs is + numberNonSOSMembers_+1. (See comments for the class.) + */ + int cliqueType_; + + /** \brief Slack variable for the clique + + Identifies the slack variable for the clique (typically added to convert + a <= relation to an equality). Value is sequence number within clique + menbers. + */ + int slack_; +}; + +/** Branching object for unordered cliques + + Intended for cliques which are long enough to make it worthwhile + but <= 64 members. There will also be ones for long cliques. + + Variable_ is the clique id number (redundant, as the object also holds a + pointer to the clique. + */ +class CbcCliqueBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcCliqueBranchingObject(); + + // Useful constructor + CbcCliqueBranchingObject(CbcModel *model, const CbcClique *clique, + int way, + int numberOnDownSide, const int *down, + int numberOnUpSide, const int *up); + + // Copy constructor + CbcCliqueBranchingObject(const CbcCliqueBranchingObject &); + + // Assignment operator + CbcCliqueBranchingObject &operator=(const CbcCliqueBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcCliqueBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return CliqueBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be of the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +private: + /// data + const CbcClique *clique_; + /// downMask - bit set to fix to weak bounds, not set to leave unfixed + unsigned int downMask_[2]; + /// upMask - bit set to fix to weak bounds, not set to leave unfixed + unsigned int upMask_[2]; +}; + +/** Unordered Clique Branching Object class. + These are for cliques which are > 64 members + Variable is number of clique. + */ +class CbcLongCliqueBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcLongCliqueBranchingObject(); + + // Useful constructor + CbcLongCliqueBranchingObject(CbcModel *model, const CbcClique *clique, + int way, + int numberOnDownSide, const int *down, + int numberOnUpSide, const int *up); + + // Copy constructor + CbcLongCliqueBranchingObject(const CbcLongCliqueBranchingObject &); + + // Assignment operator + CbcLongCliqueBranchingObject &operator=(const CbcLongCliqueBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcLongCliqueBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return LongCliqueBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +private: + /// data + const CbcClique *clique_; + /// downMask - bit set to fix to weak bounds, not set to leave unfixed + unsigned int *downMask_; + /// upMask - bit set to fix to weak bounds, not set to leave unfixed + unsigned int *upMask_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompare.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompare.hpp new file mode 100644 index 000000000..b0e47e090 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompare.hpp @@ -0,0 +1,46 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcCompare_H +#define CbcCompare_H + +class CbcCompareBase; + +class CbcCompare { +public: + CbcCompareBase *test_; + // Default Constructor + CbcCompare() + { + test_ = NULL; + } + + virtual ~CbcCompare() {} + + bool operator()(CbcNode *x, CbcNode *y) + { + return test_->test(x, y); + } + bool compareNodes(CbcNode *x, CbcNode *y) + { + return test_->test(x, y); + } + /// This is alternate test function + inline bool alternateTest(CbcNode *x, CbcNode *y) + { + return test_->alternateTest(x, y); + } + + /// return comparison object + inline CbcCompareBase *comparisonObject() const + { + return test_; + } +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareActual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareActual.hpp new file mode 100644 index 000000000..696f05d8e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareActual.hpp @@ -0,0 +1,16 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcCompareActual_H +#define CbcCompareActual_H +#include "CbcNode.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCompare.hpp" +#include "CbcCompareDepth.hpp" +#include "CbcCompareDefault.hpp" +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareBase.hpp new file mode 100644 index 000000000..b748f6b1a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareBase.hpp @@ -0,0 +1,155 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcCompareBase_H +#define CbcCompareBase_H + +//############################################################################# +/* These are alternative strategies for node traversal. + They can take data etc for fine tuning + + At present the node list is stored as a heap and the "test" + comparison function returns true if node y is better than node x. + + This is rather inflexible so if the comparison functions wants + it can signal to use alternative criterion on a complete pass + throgh tree. + +*/ +#include "CbcNode.hpp" +#include "CbcConfig.h" + +class CbcModel; +class CbcTree; +class CbcCompareBase { +public: + // Default Constructor + CbcCompareBase() + { + test_ = NULL; + threaded_ = false; + } + + /*! \brief Reconsider behaviour after discovering a new solution. + + This allows any method to change its behaviour. It is called + after each solution. + + The method should return true if changes are made which will + alter the evaluation criteria applied to a node. (So that in + cases where the search tree is sorted, it can be properly + rebuilt.) + */ + virtual bool newSolution(CbcModel *) { return (false); } + + /*! \brief Reconsider behaviour after discovering a new solution. + + This allows any method to change its behaviour. It is called + after each solution. + + The method should return true if changes are made which will + alter the evaluation criteria applied to a node. (So that in + cases where the search tree is sorted, it can be properly + rebuilt.) + */ + virtual bool newSolution(CbcModel *, + double, + int) { return (false); } + + // This allows any method to change behavior as it is called + // after every 1000 nodes. + // Return true if want tree re-sorted + virtual bool every1000Nodes(CbcModel *, int) + { + return false; + } + + /** Returns true if wants code to do scan with alternate criterion + NOTE - this is temporarily disabled + */ + virtual bool fullScan() const + { + return false; + } + + virtual ~CbcCompareBase() {} + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + + // Copy constructor + CbcCompareBase(const CbcCompareBase &rhs) + { + test_ = rhs.test_; + threaded_ = rhs.threaded_; + } + + // Assignment operator + CbcCompareBase &operator=(const CbcCompareBase &rhs) + { + if (this != &rhs) { + test_ = rhs.test_; + threaded_ = rhs.threaded_; + } + return *this; + } + + /// Clone + virtual CbcCompareBase *clone() const + { + abort(); + return NULL; + } + + /// This is test function + virtual bool test(CbcNode *, CbcNode *) + { + return true; + } + + /// This is alternate test function + virtual bool alternateTest(CbcNode *x, CbcNode *y) + { + return test(x, y); + } + + bool operator()(CbcNode *x, CbcNode *y) + { + return test(x, y); + } + /// Further test if everything else equal + inline bool equalityTest(CbcNode *x, CbcNode *y) const + { + assert(x); + assert(y); + if (!threaded_) { + CbcNodeInfo *infoX = x->nodeInfo(); + assert(infoX); + int nodeNumberX = infoX->nodeNumber(); + CbcNodeInfo *infoY = y->nodeInfo(); + assert(infoY); + int nodeNumberY = infoY->nodeNumber(); + assert(nodeNumberX != nodeNumberY); + return (nodeNumberX > nodeNumberY); + } else { + assert(x->nodeNumber() != y->nodeNumber()); + return (x->nodeNumber() > y->nodeNumber()); + } + } + /// Say threaded + inline void sayThreaded() + { + threaded_ = true; + } + +protected: + CbcCompareBase *test_; + // If not threaded we can use better way to break ties + bool threaded_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDefault.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDefault.hpp new file mode 100644 index 000000000..26c2d18f4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDefault.hpp @@ -0,0 +1,129 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/25/09 carved out of CbcCompareActual + +#ifndef CbcCompareDefault_H +#define CbcCompareDefault_H + +//############################################################################# +/* These are alternative strategies for node traversal. + They can take data etc for fine tuning + + At present the node list is stored as a heap and the "test" + comparison function returns true if node y is better than node x. + +*/ +#include "CbcNode.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCompare.hpp" + +class CbcModel; + +/* This is an example of a more complex rule with data + It is default after first solution + If weight is 0.0 then it is computed to hit first solution + less 5% +*/ +class CbcCompareDefault : public CbcCompareBase { +public: + /// Default Constructor + CbcCompareDefault(); + /// Constructor with weight + CbcCompareDefault(double weight); + + /// Copy constructor + CbcCompareDefault(const CbcCompareDefault &rhs); + + /// Assignment operator + CbcCompareDefault &operator=(const CbcCompareDefault &rhs); + + /// Clone + virtual CbcCompareBase *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + ~CbcCompareDefault(); + /* This returns true if weighted value of node y is less than + weighted value of node x */ + virtual bool test(CbcNode *x, CbcNode *y); + + using CbcCompareBase::newSolution; + /// This allows method to change behavior as it is called + /// after each solution + virtual bool newSolution(CbcModel *model, + double objectiveAtContinuous, + int numberInfeasibilitiesAtContinuous); + /// This allows method to change behavior + /// Return true if want tree re-sorted + virtual bool every1000Nodes(CbcModel *model, int numberNodes); + + /* if weight == -1.0 then fewest infeasibilities (before solution) + if -2.0 then do breadth first just for first 1000 nodes + if -3.0 then depth first before solution + */ + inline double getWeight() const + { + return weight_; + } + inline void setWeight(double weight) + { + weight_ = weight; + } + /// Cutoff + inline double getCutoff() const + { + return cutoff_; + } + inline void setCutoff(double cutoff) + { + cutoff_ = cutoff; + } + /// Best possible solution + inline double getBestPossible() const + { + return bestPossible_; + } + inline void setBestPossible(double bestPossible) + { + bestPossible_ = bestPossible; + } + /// Depth above which want to explore first + inline void setBreadthDepth(int value) + { + breadthDepth_ = value; + } + /// Start dive + void startDive(CbcModel *model); + /// Clean up diving (i.e. switch off or prepare) + void cleanDive(); + +protected: + /// Weight for each infeasibility + double weight_; + /// Weight for each infeasibility - computed from solution + double saveWeight_; + /// Cutoff + double cutoff_; + /// Best possible solution + double bestPossible_; + /// Number of solutions + int numberSolutions_; + /// Tree size (at last check) + int treeSize_; + /// Depth above which want to explore first + int breadthDepth_; + /// Chosen node from estimated (-1 is off) + int startNodeNumber_; + /// Node number when dive started + int afterNodeNumber_; + /// Indicates doing setup for diving + bool setupForDiving_; +}; + +#endif //CbcCompareDefault_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDepth.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDepth.hpp new file mode 100644 index 000000000..22d9f6bb7 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareDepth.hpp @@ -0,0 +1,48 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/24/09 carved out of CbcCompareActual + +#ifndef CbcCompareDepth_H +#define CbcCompareDepth_H + +//############################################################################# +/* These are alternative strategies for node traversal. + They can take data etc for fine tuning + + At present the node list is stored as a heap and the "test" + comparison function returns true if node y is better than node x. + +*/ +#include "CbcNode.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCompare.hpp" +class CbcModel; +// This is default before first solution +class CbcCompareDepth : public CbcCompareBase { +public: + // Default Constructor + CbcCompareDepth(); + + ~CbcCompareDepth(); + // Copy constructor + CbcCompareDepth(const CbcCompareDepth &rhs); + + // Assignment operator + CbcCompareDepth &operator=(const CbcCompareDepth &rhs); + + /// Clone + virtual CbcCompareBase *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + // This returns true if the depth of node y is greater than depth of node x + virtual bool test(CbcNode *x, CbcNode *y); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareEstimate.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareEstimate.hpp new file mode 100644 index 000000000..520c1a6a0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareEstimate.hpp @@ -0,0 +1,48 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/25/09 carved out of CbcCompareActual + +#ifndef CbcCompareEstimate_H +#define CbcCompareEstimate_H + +//############################################################################# +/* These are alternative strategies for node traversal. + They can take data etc for fine tuning + + At present the node list is stored as a heap and the "test" + comparison function returns true if node y is better than node x. + +*/ +#include "CbcNode.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCompare.hpp" +class CbcModel; + +/* This is when rounding is being done +*/ +class CbcCompareEstimate : public CbcCompareBase { +public: + // Default Constructor + CbcCompareEstimate(); + ~CbcCompareEstimate(); + // Copy constructor + CbcCompareEstimate(const CbcCompareEstimate &rhs); + + // Assignment operator + CbcCompareEstimate &operator=(const CbcCompareEstimate &rhs); + + /// Clone + virtual CbcCompareBase *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + virtual bool test(CbcNode *x, CbcNode *y); +}; + +#endif //CbcCompareEstimate_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareObjective.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareObjective.hpp new file mode 100644 index 000000000..1f0958214 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCompareObjective.hpp @@ -0,0 +1,50 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/25/09 carved out of CbcCompareActual + +#ifndef CbcCompareObjective_H +#define CbcCompareObjective_H + +//############################################################################# +/* These are alternative strategies for node traversal. + They can take data etc for fine tuning + + At present the node list is stored as a heap and the "test" + comparison function returns true if node y is better than node x. + +*/ +#include "CbcNode.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCompare.hpp" + +class CbcModel; + +class CbcCompareObjective : public CbcCompareBase { +public: + // Default Constructor + CbcCompareObjective(); + + virtual ~CbcCompareObjective(); + // Copy constructor + CbcCompareObjective(const CbcCompareObjective &rhs); + + // Assignment operator + CbcCompareObjective &operator=(const CbcCompareObjective &rhs); + + /// Clone + virtual CbcCompareBase *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /* This returns true if objective value of node y is less than + objective value of node x */ + virtual bool test(CbcNode *x, CbcNode *y); +}; + +#endif //CbcCompareObjective_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConfig.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConfig.h new file mode 100644 index 000000000..e23f4d147 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConfig.h @@ -0,0 +1,18 @@ +/* src/config_cbc.h. Generated by configure. */ +/* src/config_cbc.h.in. */ + +#ifndef CBC_VERSION + +/* Version number of project */ +#define CBC_VERSION "2.10.12" + +/* Major Version number of project */ +#define CBC_VERSION_MAJOR 2 + +/* Minor Version number of project */ +#define CBC_VERSION_MINOR 10 + +/* Release Version number of project */ +#define CBC_VERSION_RELEASE 12 + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConsequence.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConsequence.hpp new file mode 100644 index 000000000..31c1dcade --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcConsequence.hpp @@ -0,0 +1,50 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/12/2009 carved from CbcBranchBase + +#ifndef CbcConsequence_H +#define CbcConsequence_H + +class OsiSolverInterface; + +/** Abstract base class for consequent bounds. + When a variable is branched on it normally interacts with other variables by + means of equations. There are cases where we want to step outside LP and do something + more directly e.g. fix bounds. This class is for that. + + At present it need not be virtual as only instance is CbcFixVariable, but ... + + */ + +class CbcConsequence { + +public: + // Default Constructor + CbcConsequence(); + + // Copy constructor + CbcConsequence(const CbcConsequence &rhs); + + // Assignment operator + CbcConsequence &operator=(const CbcConsequence &rhs); + + /// Clone + virtual CbcConsequence *clone() const = 0; + + /// Destructor + virtual ~CbcConsequence(); + + /** Apply to an LP solver. Action depends on state + */ + virtual void applyToSolver(OsiSolverInterface *solver, int state) const = 0; + +protected: +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCountRowCut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCountRowCut.hpp new file mode 100644 index 000000000..fde55d47b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCountRowCut.hpp @@ -0,0 +1,176 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcCountRowCut_H +#define CbcCountRowCut_H + +class OsiCuts; +class OsiRowCut; +class CbcNodeInfo; + +//############################################################################# +/** \brief OsiRowCut augmented with bookkeeping + + CbcCountRowCut is an OsiRowCut object augmented with bookkeeping + information: a reference count and information that specifies the + the generator that created the cut and the node to which it's associated. + + The general principles for handling the reference count are as follows: +
    +
  • Once it's determined how the node will branch, increment the + reference count under the assumption that all children will use + all cuts currently tight at the node and will survive to be placed + in the search tree. +
  • As this assumption is proven incorrect (a cut becomes loose, or a + child is fathomed), decrement the reference count accordingly. +
+ When all possible uses of a cut have been demonstrated to be unnecessary, + the reference count (#numberPointingToThis_) will fall to zero. The + CbcCountRowCut object (and its included OsiRowCut object) are then deleted. +*/ + +class CbcCountRowCut : public OsiRowCut { + +public: + /** @name Constructors & destructors */ + //@{ + + /// Default Constructor + CbcCountRowCut(); + + /// `Copy' constructor using an OsiRowCut + CbcCountRowCut(const OsiRowCut &); + + /// `Copy' constructor using an OsiRowCut and an CbcNodeInfo + CbcCountRowCut(const OsiRowCut &, CbcNodeInfo *, int whichOne, + int whichGenerator = -1, int numberPointingToThis = 0); + + /** Destructor + + \note The destructor will reach out (via #owner_) and NULL the + reference to the cut in the owner's + \link CbcNodeInfo::cuts_ cuts_ \endlink list. + */ + virtual ~CbcCountRowCut(); + //@} + + /// Increment the number of references + void increment(int change = 1); + + /// Decrement the number of references and return the number left. + int decrement(int change = 1); + + /** \brief Set the information associating this cut with a node + + An CbcNodeInfo object and an index in the cut set of the node. + For locally valid cuts, the node will be the search tree node where the + cut was generated. For globally valid cuts, it's the node where the cut + was activated. + */ + void setInfo(CbcNodeInfo *, int whichOne); + + /// Number of other CbcNodeInfo objects pointing to this row cut + inline int numberPointingToThis() + { + return numberPointingToThis_; + } + + /// Which generator for cuts - as user order + inline int whichCutGenerator() const + { + return whichCutGenerator_; + } + + /// Returns true if can drop cut if slack basic + bool canDropCut(const OsiSolverInterface *solver, int row) const; + +#ifdef CHECK_CUT_COUNTS + // Just for printing sanity checks + int tempNumber_; +#endif + +private: + /// Standard copy is illegal (reference counts would be incorrect) + CbcCountRowCut(const CbcCountRowCut &); + + /// Standard assignment is illegal (reference counts would be incorrect) + CbcCountRowCut &operator=(const CbcCountRowCut &rhs); + + /// Backward pointer to owning CbcNodeInfo + CbcNodeInfo *owner_; + + /// Index of cut in owner's cut set + /// (\link CbcNodeInfo::cuts_ cuts_ \endlink). + int ownerCut_; + + /// Number of other CbcNodeInfo objects pointing to this cut + int numberPointingToThis_; + + /** Which generator created this cut + (add 10000 if globally valid) + if -1 then from global cut pool + -2 cut branch + -3 unknown + */ + int whichCutGenerator_; +}; +/** + Really for Conflict cuts to - + a) stop duplicates + b) allow half baked cuts + The whichRow_ field in OsiRowCut2 is used for a type + 0 - normal + 1 - processed cut (conflict) + 2 - unprocessed cut i.e. dual ray computation +*/ +// for hashing +typedef struct { + int index, next; +} CoinHashLink; +class CbcRowCuts { +public: + CbcRowCuts(int initialMaxSize = 0, int hashMultiplier = 4); + ~CbcRowCuts(); + CbcRowCuts(const CbcRowCuts &rhs); + CbcRowCuts &operator=(const CbcRowCuts &rhs); + inline OsiRowCut2 *cut(int sequence) const + { + return rowCut_[sequence]; + } + inline int numberCuts() const + { + return numberCuts_; + } + inline int sizeRowCuts() const + { + return numberCuts_; + } + inline OsiRowCut *rowCutPtr(int sequence) + { + return rowCut_[sequence]; + } + void eraseRowCut(int sequence); + // Return 0 if added, 1 if not, -1 if not added because of space + int addCutIfNotDuplicate(const OsiRowCut &cut, int whichType = 0); + // Return 0 if added, 1 if not, -1 if not added because of space + int addCutIfNotDuplicateWhenGreedy(const OsiRowCut &cut, int whichType = 0); + // Add in cuts as normal cuts (and delete) + void addCuts(OsiCuts &cs); + // Truncate + void truncate(int numberAfter); + +private: + OsiRowCut2 **rowCut_; + /// Hash table + CoinHashLink *hash_; + int size_; + int hashMultiplier_; + int numberCuts_; + int lastHash_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutGenerator.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutGenerator.hpp new file mode 100644 index 000000000..b7ba48e09 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutGenerator.hpp @@ -0,0 +1,550 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcCutGenerator_H +#define CbcCutGenerator_H + +#include "OsiSolverInterface.hpp" +#include "OsiCuts.hpp" +#include "CglCutGenerator.hpp" +#include "CbcCutModifier.hpp" + +class CbcModel; +class OsiRowCut; +class OsiRowCutDebugger; + +//############################################################################# + +/** Interface between Cbc and Cut Generation Library. + + \c CbcCutGenerator is intended to provide an intelligent interface between + Cbc and the cutting plane algorithms in the CGL. A \c CbcCutGenerator is + bound to a \c CglCutGenerator and to an \c CbcModel. It contains parameters + which control when and how the \c generateCuts method of the + \c CglCutGenerator will be called. + + The builtin decision criteria available to use when deciding whether to + generate cuts are limited: every X nodes, when a solution is found, + and when a subproblem is found to be infeasible. The idea is that the class + will grow more intelligent with time. + + \todo Add a pointer to function member which will allow a client to install + their own decision algorithm to decide whether or not to call the CGL + \p generateCuts method. Create a default decision method that looks + at the builtin criteria. + + \todo It strikes me as not good that generateCuts contains code specific to + individual CGL algorithms. Another set of pointer to function members, + so that the client can specify the cut generation method as well as + pre- and post-generation methods? Taken a bit further, should this + class contain a bunch of pointer to function members, one for each + of the places where the cut generator might be referenced? + Initialization, root node, search tree node, discovery of solution, + and termination all come to mind. Initialization and termination would + also be useful for instrumenting cbc. +*/ + +class CbcCutGenerator { + +public: + /** \name Generate Cuts */ + //@{ + /** Generate cuts for the client model. + + Evaluate the state of the client model and decide whether to generate cuts. + The generated cuts are inserted into and returned in the collection of cuts + \p cs. + + If \p fullScan is !=0, the generator is obliged to call the CGL + \c generateCuts routine. Otherwise, it is free to make a local decision. + Negative fullScan says things like at integer solution + The current implementation uses \c whenCutGenerator_ to decide. + + The routine returns true if reoptimisation is needed (because the state of + the solver interface has been modified). + + If node then can find out depth + */ + bool generateCuts(OsiCuts &cs, int fullScan, OsiSolverInterface *solver, + CbcNode *node); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CbcCutGenerator(); + + /// Normal constructor + CbcCutGenerator(CbcModel *model, CglCutGenerator *generator, + int howOften = 1, const char *name = NULL, + bool normal = true, bool atSolution = false, + bool infeasible = false, int howOftenInsub = -100, + int whatDepth = -1, int whatDepthInSub = -1, int switchOffIfLessThan = 0); + + /// Copy constructor + CbcCutGenerator(const CbcCutGenerator &); + + /// Assignment operator + CbcCutGenerator &operator=(const CbcCutGenerator &rhs); + + /// Destructor + ~CbcCutGenerator(); + //@} + + /**@name Gets and sets */ + //@{ + /** Set the client model. + + In addition to setting the client model, refreshModel also calls + the \c refreshSolver method of the CglCutGenerator object. + */ + void refreshModel(CbcModel *model); + + /// return name of generator + inline const char *cutGeneratorName() const + { + return generatorName_; + } + + /// Create C++ lines to show how to tune + void generateTuning(FILE *fp); + /** Set the cut generation interval + + Set the number of nodes evaluated between calls to the Cgl object's + \p generateCuts routine. + + If \p value is positive, cuts will always be generated at the specified + interval. + If \p value is negative, cuts will initially be generated at the specified + interval, but Cbc may adjust the value depending on the success of cuts + produced by this generator. + + A value of -100 disables the generator, while a value of -99 means + just at root. + */ + void setHowOften(int value); + + /// Get the cut generation interval. + inline int howOften() const + { + return whenCutGenerator_; + } + /// Get the cut generation interval.in sub tree + inline int howOftenInSub() const + { + return whenCutGeneratorInSub_; + } + /// Get level of cut inaccuracy (0 means exact e.g. cliques) + inline int inaccuracy() const + { + return inaccuracy_; + } + /// Set level of cut inaccuracy (0 means exact e.g. cliques) + inline void setInaccuracy(int level) + { + inaccuracy_ = level; + } + + /** Set the cut generation depth + + Set the depth criterion for calls to the Cgl object's + \p generateCuts routine. Only active if > 0. + + If whenCutGenerator is positive and this is positive then this overrides. + If whenCutGenerator is -1 then this is used as criterion if any cuts + were generated at root node. + If whenCutGenerator is anything else this is ignored. + */ + void setWhatDepth(int value); + /// Set the cut generation depth in sub tree + void setWhatDepthInSub(int value); + /// Get the cut generation depth criterion. + inline int whatDepth() const + { + return depthCutGenerator_; + } + /// Get the cut generation depth criterion.in sub tree + inline int whatDepthInSub() const + { + return depthCutGeneratorInSub_; + } + /// Set maximum number of times to enter + inline void setMaximumTries(int value) + { + maximumTries_ = value; + } + /// Get maximum number of times to enter + inline int maximumTries() const + { + return maximumTries_; + } + + /// Get switches + inline int switches() const + { + return switches_; + } + /// Set switches (for copying from virgin state) + inline void setSwitches(int value) + { + switches_ = value; + } + /// Get whether the cut generator should be called in the normal place + inline bool normal() const + { + return (switches_ & 1) != 0; + } + /// Set whether the cut generator should be called in the normal place + inline void setNormal(bool value) + { + switches_ &= ~1; + switches_ |= value ? 1 : 0; + } + /// Get whether the cut generator should be called when a solution is found + inline bool atSolution() const + { + return (switches_ & 2) != 0; + } + /// Set whether the cut generator should be called when a solution is found + inline void setAtSolution(bool value) + { + switches_ &= ~2; + switches_ |= value ? 2 : 0; + } + /** Get whether the cut generator should be called when the subproblem is + found to be infeasible. + */ + inline bool whenInfeasible() const + { + return (switches_ & 4) != 0; + } + /** Set whether the cut generator should be called when the subproblem is + found to be infeasible. + */ + inline void setWhenInfeasible(bool value) + { + switches_ &= ~4; + switches_ |= value ? 4 : 0; + } + /// Get whether the cut generator is being timed + inline bool timing() const + { + return (switches_ & 64) != 0; + } + /// Set whether the cut generator is being timed + inline void setTiming(bool value) + { + switches_ &= ~64; + switches_ |= value ? 64 : 0; + timeInCutGenerator_ = 0.0; + } + /// Return time taken in cut generator + inline double timeInCutGenerator() const + { + return timeInCutGenerator_; + } + inline void incrementTimeInCutGenerator(double value) + { + timeInCutGenerator_ += value; + } + /// Get the \c CglCutGenerator corresponding to this \c CbcCutGenerator. + inline CglCutGenerator *generator() const + { + return generator_; + } + /// Number times cut generator entered + inline int numberTimesEntered() const + { + return numberTimes_; + } + inline void setNumberTimesEntered(int value) + { + numberTimes_ = value; + } + inline void incrementNumberTimesEntered(int value = 1) + { + numberTimes_ += value; + } + /// Total number of cuts added + inline int numberCutsInTotal() const + { + return numberCuts_; + } + inline void setNumberCutsInTotal(int value) + { + numberCuts_ = value; + } + inline void incrementNumberCutsInTotal(int value = 1) + { + numberCuts_ += value; + } + /// Total number of elements added + inline int numberElementsInTotal() const + { + return numberElements_; + } + inline void setNumberElementsInTotal(int value) + { + numberElements_ = value; + } + inline void incrementNumberElementsInTotal(int value = 1) + { + numberElements_ += value; + } + /// Total number of column cuts + inline int numberColumnCuts() const + { + return numberColumnCuts_; + } + inline void setNumberColumnCuts(int value) + { + numberColumnCuts_ = value; + } + inline void incrementNumberColumnCuts(int value = 1) + { + numberColumnCuts_ += value; + } + /// Total number of cuts active after (at end of n cut passes at each node) + inline int numberCutsActive() const + { + return numberCutsActive_; + } + inline void setNumberCutsActive(int value) + { + numberCutsActive_ = value; + } + inline void incrementNumberCutsActive(int value = 1) + { + numberCutsActive_ += value; + } + inline void setSwitchOffIfLessThan(int value) + { + switchOffIfLessThan_ = value; + } + inline int switchOffIfLessThan() const + { + return switchOffIfLessThan_; + } + /// Say if optimal basis needed + inline bool needsOptimalBasis() const + { + return (switches_ & 128) != 0; + } + /// Set if optimal basis needed + inline void setNeedsOptimalBasis(bool yesNo) + { + switches_ &= ~128; + switches_ |= yesNo ? 128 : 0; + } + /// Whether generator MUST be called again if any cuts (i.e. ignore break from loop) + inline bool mustCallAgain() const + { + return (switches_ & 8) != 0; + } + /// Set whether generator MUST be called again if any cuts (i.e. ignore break from loop) + inline void setMustCallAgain(bool yesNo) + { + switches_ &= ~8; + switches_ |= yesNo ? 8 : 0; + } + /// Whether generator switched off for moment + inline bool switchedOff() const + { + return (switches_ & 16) != 0; + } + /// Set whether generator switched off for moment + inline void setSwitchedOff(bool yesNo) + { + switches_ &= ~16; + switches_ |= yesNo ? 16 : 0; + } + /// Whether last round of cuts did little + inline bool ineffectualCuts() const + { + return (switches_ & 512) != 0; + } + /// Set whether last round of cuts did little + inline void setIneffectualCuts(bool yesNo) + { + switches_ &= ~512; + switches_ |= yesNo ? 512 : 0; + } + /// Whether to use if any cuts generated + inline bool whetherToUse() const + { + return (switches_ & 1024) != 0; + } + /// Set whether to use if any cuts generated + inline void setWhetherToUse(bool yesNo) + { + switches_ &= ~1024; + switches_ |= yesNo ? 1024 : 0; + } + /// Whether in must call again mode (or after others) + inline bool whetherInMustCallAgainMode() const + { + return (switches_ & 2048) != 0; + } + /// Set whether in must call again mode (or after others) + inline void setWhetherInMustCallAgainMode(bool yesNo) + { + switches_ &= ~2048; + switches_ |= yesNo ? 2048 : 0; + } + /// Whether to call at end + inline bool whetherCallAtEnd() const + { + return (switches_ & 4096) != 0; + } + /// Set whether to call at end + inline void setWhetherCallAtEnd(bool yesNo) + { + switches_ &= ~4096; + switches_ |= yesNo ? 4096 : 0; + } + /// Whether needs refresh on copy + inline bool needsRefresh() const + { + return (switches_ & 8192) != 0; + } + /// Set whether needs refresh on copy + inline void setNeedsRefresh(bool yesNo) + { + switches_ &= ~8192; + switches_ |= yesNo ? 8192 : 0; + } + /// Number of cuts generated at root + inline int numberCutsAtRoot() const + { + return numberCutsAtRoot_; + } + inline void setNumberCutsAtRoot(int value) + { + numberCutsAtRoot_ = value; + } + /// Number of cuts active at root + inline int numberActiveCutsAtRoot() const + { + return numberActiveCutsAtRoot_; + } + inline void setNumberActiveCutsAtRoot(int value) + { + numberActiveCutsAtRoot_ = value; + } + /// Number of short cuts at root + inline int numberShortCutsAtRoot() const + { + return numberShortCutsAtRoot_; + } + inline void setNumberShortCutsAtRoot(int value) + { + numberShortCutsAtRoot_ = value; + } + /// Set model + inline void setModel(CbcModel *model) + { + model_ = model; + } + /// Whether global cuts at root + inline bool globalCutsAtRoot() const + { + return (switches_ & 32) != 0; + } + /// Set whether global cuts at root + inline void setGlobalCutsAtRoot(bool yesNo) + { + switches_ &= ~32; + switches_ |= yesNo ? 32 : 0; + } + /// Whether global cuts + inline bool globalCuts() const + { + return (switches_ & 256) != 0; + } + /// Set whether global cuts + inline void setGlobalCuts(bool yesNo) + { + switches_ &= ~256; + switches_ |= yesNo ? 256 : 0; + } + /// Add in statistics from other + void addStatistics(const CbcCutGenerator *other); + /// Scale back statistics by factor + void scaleBackStatistics(int factor); + //@} + +private: + /**@name Private gets and sets */ + //@{ + //@} + /// Saved cuts + OsiCuts savedCuts_; + /// Time in cut generator + double timeInCutGenerator_; + /// The client model + CbcModel *model_; + + // The CglCutGenerator object + CglCutGenerator *generator_; + + /// Name of generator + char *generatorName_; + + /** Number of nodes between calls to the CglCutGenerator::generateCuts + routine. + */ + int whenCutGenerator_; + /** Number of nodes between calls to the CglCutGenerator::generateCuts + routine in sub tree. + */ + int whenCutGeneratorInSub_; + /** If first pass at root produces fewer than this cuts then switch off + */ + int switchOffIfLessThan_; + + /** Depth at which to call the CglCutGenerator::generateCuts + routine (If >0 then overrides when and is called if depth%depthCutGenerator==0). + */ + int depthCutGenerator_; + + /** Depth at which to call the CglCutGenerator::generateCuts + routine (If >0 then overrides when and is called if depth%depthCutGenerator==0). + In sub tree. + */ + int depthCutGeneratorInSub_; + + /// Level of cut inaccuracy (0 means exact e.g. cliques) + int inaccuracy_; + /// Number times cut generator entered + int numberTimes_; + /// Total number of cuts added + int numberCuts_; + /// Total number of elements added + int numberElements_; + /// Total number of column cuts added + int numberColumnCuts_; + /// Total number of cuts active after (at end of n cut passes at each node) + int numberCutsActive_; + /// Number of cuts generated at root + int numberCutsAtRoot_; + /// Number of cuts active at root + int numberActiveCutsAtRoot_; + /// Number of short cuts at root + int numberShortCutsAtRoot_; + /// Switches - see gets and sets + int switches_; + /// Maximum number of times to enter + int maximumTries_; +}; + +// How often to do if mostly switched off (A) +#define SCANCUTS 1000 +// How often to do if mostly switched off (probing B) +#define SCANCUTS_PROBING 1000 + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutModifier.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutModifier.hpp new file mode 100644 index 000000000..e3649782f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutModifier.hpp @@ -0,0 +1,59 @@ +// $Id$ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/25/09 carved out of CbcCutGenerator + +#ifndef CbcCutModifier_H +#define CbcCutModifier_H + +#include "OsiSolverInterface.hpp" +#include "OsiCuts.hpp" +#include "CglCutGenerator.hpp" + +class CbcModel; +class OsiRowCut; +class OsiRowCutDebugger; +/** Abstract cut modifier base class + + In exotic circumstances - cuts may need to be modified + a) strengthened - changed + b) weakened - changed + c) deleted - set to NULL + d) unchanged +*/ + +class CbcCutModifier { +public: + /// Default Constructor + CbcCutModifier(); + + // Copy constructor + CbcCutModifier(const CbcCutModifier &); + + /// Destructor + virtual ~CbcCutModifier(); + + /// Assignment + CbcCutModifier &operator=(const CbcCutModifier &rhs); + /// Clone + virtual CbcCutModifier *clone() const = 0; + + /** Returns + 0 unchanged + 1 strengthened + 2 weakened + 3 deleted + */ + virtual int modify(const OsiSolverInterface *solver, OsiRowCut &cut) = 0; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + +protected: +}; + +#endif //CbcCutModifier_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutSubsetModifier.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutSubsetModifier.hpp new file mode 100644 index 000000000..d1f0882d4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcCutSubsetModifier.hpp @@ -0,0 +1,69 @@ +// $Id$ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +//Edwin 11/25/09 carved out of CbcCutGenerator + +#ifndef CbcCutSubsetModifier_H +#define CbcCutSubsetModifier_H + +#include "OsiSolverInterface.hpp" +#include "OsiCuts.hpp" +#include "CglCutGenerator.hpp" +#include "CbcCutModifier.hpp" + +class CbcModel; +class OsiRowCut; +class OsiRowCutDebugger; +/** Simple cut modifier base class + + In exotic circumstances - cuts may need to be modified + a) strengthened - changed + b) weakened - changed + c) deleted - set to NULL + d) unchanged + + initially get rid of cuts with variables >= k + could weaken +*/ + +class CbcCutSubsetModifier : public CbcCutModifier { +public: + /// Default Constructor + CbcCutSubsetModifier(); + + /// Useful Constructor + CbcCutSubsetModifier(int firstOdd); + + // Copy constructor + CbcCutSubsetModifier(const CbcCutSubsetModifier &); + + /// Destructor + virtual ~CbcCutSubsetModifier(); + + /// Assignment + CbcCutSubsetModifier &operator=(const CbcCutSubsetModifier &rhs); + /// Clone + virtual CbcCutModifier *clone() const; + + /** Returns + 0 unchanged + 1 strengthened + 2 weakened + 3 deleted + */ + virtual int modify(const OsiSolverInterface *solver, OsiRowCut &cut); + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + +protected: + /// data + /// First odd variable + int firstOdd_; +}; + +#endif //CbcCutSubsetModifier_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcDummyBranchingObject.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcDummyBranchingObject.hpp new file mode 100644 index 000000000..1897aa5b8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcDummyBranchingObject.hpp @@ -0,0 +1,83 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcDummyBranchingObject_H +#define CbcDummyBranchingObject_H + +#include "CbcBranchBase.hpp" +/** Dummy branching object + + This object specifies a one-way dummy branch. + This is so one can carry on branching even when it looks feasible +*/ + +class CbcDummyBranchingObject : public CbcBranchingObject { + +public: + /// Default constructor + CbcDummyBranchingObject(CbcModel *model = NULL); + + /// Copy constructor + CbcDummyBranchingObject(const CbcDummyBranchingObject &); + + /// Assignment operator + CbcDummyBranchingObject &operator=(const CbcDummyBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcDummyBranchingObject(); + + using CbcBranchingObject::branch; + /** \brief Dummy branch + */ + virtual double branch(); + +#ifdef JJF_ZERO + // No need to override. Default works fine. + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch(); +#endif + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return DummyBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcEventHandler.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcEventHandler.hpp new file mode 100644 index 000000000..0871ab0ea --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcEventHandler.hpp @@ -0,0 +1,250 @@ +/* + Copyright (C) 2006, International Business Machines Corporation and others. + All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). + + $Id$ +*/ + +#ifndef CbcEventHandler_H +#define CbcEventHandler_H + +/*! \file CbcEventHandler.hpp + \brief Event handling for cbc + + This file contains the declaration of CbcEventHandler, used for event + handling in cbc. + + The central method is CbcEventHandler::event(). The default semantics of + this call are `ask for the action to take in reponse to this event'. The + call is made at the point in the code where the event occurs (e.g., + when a solution is found, or when a node is added to or removed from the + search tree). The return value specifies the action to perform in response + to the event (e.g., continue, or stop). + + This is a lazy class. Initially, it knows nothing about specific events, + and returns dfltAction_ for any event. This makes for a trivial constructor + and fast startup. The only place where the list of known events or actions + is hardwired is in the enum definitions for CbcEvent and CbcAction, + respectively. + + At the first call to setAction, a map is created to hold (Event,Action) + pairs, and this map will be consulted ever after. Events not in the map + will still return the default value. + + For serious extensions, derive a subclass and replace event() with a + function that suits you better. The function has access to the CbcModel + via a pointer held in the CbcEventHandler object, and can do as much + thinking as it likes before returning an answer. You can also print as + much information as you want. The model is held as a const, however, so + you can't alter reality. + + The design of the class deliberately matches ClpEventHandler, so that other + solvers can participate in cbc without breaking the patterns set by + clp-specific code. + +*/ + +#include +#include + +/* May well already be declared, but can't hurt. */ + +class CbcModel; + +/* + cvs/svn: $Id$ +*/ + +/*! \class CbcEventHandler + \brief Base class for Cbc event handling. + + Up front: We're not talking about unanticipated events here. We're talking + about anticipated events, in the sense that the code is going to make a call + to event() and is prepared to obey the return value that it receives. + + The general pattern for usage is as follows: +
    +
  1. Create a CbcEventHandler object. This will be initialised with a set + of default actions for every recognised event. + +
  2. Attach the event handler to the CbcModel object. + +
  3. When execution reaches the point where an event occurs, call the + event handler as CbcEventHandler::event(the event). The return value + will specify what the code should do in response to the event. +
+ + The return value associated with an event can be changed at any time. +*/ + +class CbcEventHandler { + +public: + /*! \brief Events known to cbc */ + + enum CbcEvent { /*! Processing of the current node is complete. */ + node = 200, + /*! A tree status interval has arrived. */ + treeStatus, + /*! A solution has been found. */ + solution, + /*! A heuristic solution has been found. */ + heuristicSolution, + /*! A solution will be found unless user takes action (first check). */ + beforeSolution1, + /*! A solution will be found unless user takes action (thorough check). */ + beforeSolution2, + /*! After failed heuristic. */ + afterHeuristic, + /*! On entry to small branch and bound. */ + smallBranchAndBound, + /*! After a pass of heuristic. */ + heuristicPass, + /*! When converting constraints to cuts. */ + convertToCuts, + /*! Having generated cuts, allows user to think. */ + generatedCuts, + /*! End of search. */ + endSearch, + /*! Just before starting branching i.e. after root cuts. */ + afterRootCuts + }; + + /*! \brief Action codes returned by the event handler. + + Specific values are chosen to match ClpEventHandler return codes. + */ + + enum CbcAction { /*! Continue --- no action required. */ + noAction = -1, + /*! Stop --- abort the current run at the next opportunity. */ + stop = 0, + /*! Restart --- restart branch-and-cut search; do not undo root node + processing. + */ + restart, + /*! RestartRoot --- undo root node and start branch-and-cut afresh. */ + restartRoot, + /*! Add special cuts. */ + addCuts, + /*! Pretend solution never happened. */ + killSolution, + /*! Take action on modified data. */ + takeAction + + }; + + /*! \brief Data type for event/action pairs */ + + typedef std::map< CbcEvent, CbcAction > eaMapPair; + + /*! \name Event Processing */ + //@{ + + /*! \brief Return the action to be taken for an event. + + Return the action that should be taken in response to the event passed as + the parameter. The default implementation simply reads a return code + from a map. + */ + virtual CbcAction event(CbcEvent whichEvent); + + /*! \brief Return the action to be taken for an event - and modify data. + + Return the action that should be taken in response to the event passed as + the parameter. The default implementation simply reads a return code + from a map. + */ + virtual CbcAction event(CbcEvent whichEvent, void *data); + + //@} + + /*! \name Constructors and destructors */ + //@{ + + /*! \brief Default constructor. */ + + CbcEventHandler(CbcModel *model = 0 /* was NULL but 4.6 complains */); + + /*! \brief Copy constructor. */ + + CbcEventHandler(const CbcEventHandler &orig); + + /*! \brief Assignment. */ + + CbcEventHandler &operator=(const CbcEventHandler &rhs); + + /*! \brief Clone (virtual) constructor. */ + + virtual CbcEventHandler *clone() const; + + /*! \brief Destructor. */ + + virtual ~CbcEventHandler(); + + //@} + + /*! \name Set/Get methods */ + //@{ + + /*! \brief Set model. */ + + inline void setModel(CbcModel *model) + { + model_ = model; + } + + /*! \brief Get model. */ + + inline const CbcModel *getModel() const + { + return model_; + } + + /*! \brief Set the default action */ + + inline void setDfltAction(CbcAction action) + { + dfltAction_ = action; + } + + /*! \brief Set the action code associated with an event */ + + inline void setAction(CbcEvent event, CbcAction action) + { + if (eaMap_ == 0) { + eaMap_ = new eaMapPair; + } + (*eaMap_)[event] = action; + } + + //@} + +protected: + /*! \name Data members + + Protected (as opposed to private) to allow access by derived classes. + */ + //@{ + + /*! \brief Pointer to associated CbcModel */ + + CbcModel *model_; + + /*! \brief Default action */ + + CbcAction dfltAction_; + + /*! \brief Pointer to a map that holds non-default event/action pairs */ + + eaMapPair *eaMap_; + + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathom.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathom.hpp new file mode 100644 index 000000000..e2c666372 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathom.hpp @@ -0,0 +1,136 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcFathom_H +#define CbcFathom_H +#include "CbcConfig.h" + +/* + This file contains two classes, CbcFathom and CbcOsiSolver. It's unclear why + they're in the same file. CbcOsiSolver is a base class for CbcLinked. + + --lh, 071031 -- +*/ + +class CbcModel; + +//############################################################################# +/** Fathom base class. + + The idea is that after some branching the problem will be effectively smaller than + the original problem and maybe there will be a more specialized technique which can completely + fathom this branch quickly. + + One method is to presolve the problem to give a much smaller new problem and then do branch + and cut on that. Another might be dynamic programming. + + */ + +class CbcFathom { +public: + // Default Constructor + CbcFathom(); + + // Constructor with model - assumed before cuts + CbcFathom(CbcModel &model); + + virtual ~CbcFathom(); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + /// Clone + virtual CbcFathom *clone() const = 0; + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model) = 0; + + /** returns 0 if no fathoming attempted, 1 fully fathomed, + 2 incomplete search, 3 incomplete search but treat as complete. + If solution then newSolution will not be NULL and + will be freed by CbcModel. It is expected that the solution is better + than best so far but CbcModel will double check. + + If returns 3 then of course there is no guarantee of global optimum + */ + virtual int fathom(double *&newSolution) = 0; + + // Is this method possible + inline bool possible() const + { + return possible_; + } + +protected: + /// Model + CbcModel *model_; + /// Possible - if this method of fathoming can be used + bool possible_; + +private: + /// Illegal Assignment operator + CbcFathom &operator=(const CbcFathom &rhs); +}; + +#include "OsiClpSolverInterface.hpp" + +//############################################################################# + +/** + +This is for codes where solver needs to know about CbcModel + Seems to provide only one value-added feature, a CbcModel object. + +*/ + +class CbcOsiSolver : public OsiClpSolverInterface { + +public: + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + CbcOsiSolver(); + + /// Clone + virtual OsiSolverInterface *clone(bool copyData = true) const; + + /// Copy constructor + CbcOsiSolver(const CbcOsiSolver &); + + /// Assignment operator + CbcOsiSolver &operator=(const CbcOsiSolver &rhs); + + /// Destructor + virtual ~CbcOsiSolver(); + + //@} + + /**@name Sets and Gets */ + //@{ + /// Set Cbc Model + inline void setCbcModel(CbcModel *model) + { + cbcModel_ = model; + } + /// Return Cbc Model + inline CbcModel *cbcModel() const + { + return cbcModel_; + } + //@} + + //--------------------------------------------------------------------------- + +protected: + /**@name Private member data */ + //@{ + /// Pointer back to CbcModel + CbcModel *cbcModel_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathomDynamicProgramming.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathomDynamicProgramming.hpp new file mode 100644 index 000000000..7e6535e9f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFathomDynamicProgramming.hpp @@ -0,0 +1,177 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcFathomDynamicProgramming_H +#define CbcFathomDynamicProgramming_H + +#include "CbcFathom.hpp" + +//############################################################################# +/** FathomDynamicProgramming class. + + The idea is that after some branching the problem will be effectively smaller than + the original problem and maybe there will be a more specialized technique which can completely + fathom this branch quickly. + + This is a dynamic programming implementation which is very fast for some + specialized problems. It expects small integral rhs, an all integer problem + and positive integral coefficients. At present it can not do general set covering + problems just set partitioning. It can find multiple optima for various rhs + combinations. + + The main limiting factor is size of state space. Each 1 rhs doubles the size of the problem. + 2 or 3 rhs quadruples, 4,5,6,7 by 8 etc. + */ + +class CbcFathomDynamicProgramming : public CbcFathom { +public: + // Default Constructor + CbcFathomDynamicProgramming(); + + // Constructor with model - assumed before cuts + CbcFathomDynamicProgramming(CbcModel &model); + // Copy constructor + CbcFathomDynamicProgramming(const CbcFathomDynamicProgramming &rhs); + + virtual ~CbcFathomDynamicProgramming(); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + /// Clone + virtual CbcFathom *clone() const; + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /** returns 0 if no fathoming attempted, 1 fully fathomed , + 2 incomplete search, 3 incomplete search but treat as complete. + If solution then newSolution will not be NULL and + will be freed by CbcModel. It is expected that the solution is better + than best so far but CbcModel will double check. + + If returns 3 then of course there is no guarantee of global optimum + */ + virtual int fathom(double *&newSolution); + + /// Maximum size allowed + inline int maximumSize() const + { + return maximumSizeAllowed_; + } + inline void setMaximumSize(int value) + { + maximumSizeAllowed_ = value; + } + /// Returns type of algorithm and sets up arrays + int checkPossible(int allowableSize = 0); + // set algorithm + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + /** Tries a column + returns true if was used in making any changes. + */ + bool tryColumn(int numberElements, const int *rows, + const double *coefficients, double cost, + int upper = COIN_INT_MAX); + /// Returns cost array + inline const double *cost() const + { + return cost_; + } + /// Returns back array + inline const int *back() const + { + return back_; + } + /// Gets bit pattern for target result + inline int target() const + { + return target_; + } + /// Sets bit pattern for target result + inline void setTarget(int value) + { + target_ = value; + } + +private: + /// Does deleteions + void gutsOfDelete(); + + /** Adds one attempt of one column of type 0, + returns true if was used in making any changes + */ + bool addOneColumn0(int numberElements, const int *rows, + double cost); + /** Adds one attempt of one column of type 1, + returns true if was used in making any changes. + At present the user has to call it once for each possible value + */ + bool addOneColumn1(int numberElements, const int *rows, + const int *coefficients, double cost); + /** Adds one attempt of one column of type 1, + returns true if was used in making any changes. + At present the user has to call it once for each possible value. + This version is when there are enough 1 rhs to do faster + */ + bool addOneColumn1A(int numberElements, const int *rows, + const int *coefficients, double cost); + /// Gets bit pattern from original column + int bitPattern(int numberElements, const int *rows, + const int *coefficients); + /// Gets bit pattern from original column + int bitPattern(int numberElements, const int *rows, + const double *coefficients); + /// Fills in original column (dense) from bit pattern - returning number nonzero + int decodeBitPattern(int bitPattern, int *values, int numberRows); + +protected: + /// Size of states (power of 2 unless just one constraint) + int size_; + /** Type - 0 coefficients and rhs all 1, + 1 - coefficients > 1 or rhs > 1 + */ + int type_; + /// Space for states + double *cost_; + /// Which state produced this cheapest one + int *back_; + /// Some rows may be satisified so we need a lookup + int *lookup_; + /// Space for sorted indices + int *indices_; + /// Number of active rows + int numberActive_; + /// Maximum size allowed + int maximumSizeAllowed_; + /// Start bit for each active row + int *startBit_; + /// Number bits for each active row + int *numberBits_; + /// Effective rhs + int *rhs_; + /// Space for sorted coefficients + int *coefficients_; + /// Target pattern + int target_; + /// Number of Non 1 rhs + int numberNonOne_; + /// Current bit pattern + int bitPattern_; + /// Current algorithm + int algorithm_; + +private: + /// Illegal Assignment operator + CbcFathomDynamicProgramming &operator=(const CbcFathomDynamicProgramming &rhs); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFeasibilityBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFeasibilityBase.hpp new file mode 100644 index 000000000..7f7a4f25d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFeasibilityBase.hpp @@ -0,0 +1,60 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcFeasibilityBase_H +#define CbcFeasibilityBase_H + +//############################################################################# +/* There are cases where the user wants to control how CBC sees the problems feasibility. + The user may want to examine the problem and say : + a) The default looks OK + b) Pretend this problem is Integer feasible + c) Pretend this problem is infeasible even though it looks feasible + + This simple class allows user to do that. + +*/ + +class CbcModel; +class CbcFeasibilityBase { +public: + // Default Constructor + CbcFeasibilityBase() {} + + /** + On input mode: + 0 - called after a solve but before any cuts + -1 - called after strong branching + Returns : + 0 - no opinion + -1 pretend infeasible + 1 pretend integer solution + */ + virtual int feasible(CbcModel *, int) + { + return 0; + } + + virtual ~CbcFeasibilityBase() {} + + // Copy constructor + CbcFeasibilityBase(const CbcFeasibilityBase &) {} + + // Assignment operator + CbcFeasibilityBase &operator=(const CbcFeasibilityBase &) + { + return *this; + } + + /// Clone + virtual CbcFeasibilityBase *clone() const + { + return new CbcFeasibilityBase(*this); + } +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFixVariable.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFixVariable.hpp new file mode 100644 index 000000000..d3db46efc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFixVariable.hpp @@ -0,0 +1,68 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcFixVariable_H +#define CbcFixVariable_H + +#include "CbcBranchBase.hpp" +/** Class for consequent bounds. + When a variable is branched on it normally interacts with other variables by + means of equations. There are cases where we want to step outside LP and do something + more directly e.g. fix bounds. This class is for that. + + A state of -9999 means at LB, +9999 means at UB, + others mean if fixed to that value. + + */ + +class CbcFixVariable : public CbcConsequence { + +public: + // Default Constructor + CbcFixVariable(); + + // One useful Constructor + CbcFixVariable(int numberStates, const int *states, const int *numberNewLower, const int **newLowerValue, + const int **lowerColumn, + const int *numberNewUpper, const int **newUpperValue, + const int **upperColumn); + + // Copy constructor + CbcFixVariable(const CbcFixVariable &rhs); + + // Assignment operator + CbcFixVariable &operator=(const CbcFixVariable &rhs); + + /// Clone + virtual CbcConsequence *clone() const; + + /// Destructor + virtual ~CbcFixVariable(); + + /** Apply to an LP solver. Action depends on state + */ + virtual void applyToSolver(OsiSolverInterface *solver, int state) const; + +protected: + /// Number of states + int numberStates_; + /// Values of integers for various states + int *states_; + /// Start of information for each state (setting new lower) + int *startLower_; + /// Start of information for each state (setting new upper) + int *startUpper_; + /// For each variable new bounds + double *newBound_; + /// Variable + int *variable_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFollowOn.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFollowOn.hpp new file mode 100644 index 000000000..6f68d7da2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFollowOn.hpp @@ -0,0 +1,207 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcFollowOn_H +#define CbcFollowOn_H + +#include "CbcBranchBase.hpp" +#include "OsiRowCut.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinPackedMatrix.hpp" + +/** Define a follow on class. + The idea of this is that in air-crew scheduling problems crew may fly in on flight A + and out on flight B or on some other flight. A useful branch is one which on one side + fixes all which go out on flight B to 0, while the other branch fixes all those that do NOT + go out on flight B to 0. + + This branching rule should be in addition to normal rules and have a high priority. +*/ + +class CbcFollowOn : public CbcObject { + +public: + // Default Constructor + CbcFollowOn(); + + /** Useful constructor + */ + CbcFollowOn(CbcModel *model); + + // Copy constructor + CbcFollowOn(const CbcFollowOn &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcFollowOn &operator=(const CbcFollowOn &rhs); + + // Destructor + ~CbcFollowOn(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// As some computation is needed in more than one place - returns row + virtual int gutsOfFollowOn(int &otherRow, int &preferredWay) const; + +protected: + /// data + /// Matrix + CoinPackedMatrix matrix_; + /// Matrix by row + CoinPackedMatrix matrixByRow_; + /// Possible rhs (if 0 then not possible) + int *rhs_; +}; + +/** General Branching Object class. + Each way fixes some variables to lower bound + */ +class CbcFixingBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcFixingBranchingObject(); + + // Useful constructor + CbcFixingBranchingObject(CbcModel *model, + int way, + int numberOnDownSide, const int *down, + int numberOnUpSide, const int *up); + + // Copy constructor + CbcFixingBranchingObject(const CbcFixingBranchingObject &); + + // Assignment operator + CbcFixingBranchingObject &operator=(const CbcFixingBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcFixingBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + +#ifdef JJF_ZERO + // No need to override. Default works fine. + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch(); +#endif + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return FollowOnBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +private: + /// data + /// Number on down list + int numberDown_; + /// Number on up list + int numberUp_; + /// downList - variables to fix to lb on down branch + int *downList_; + /// upList - variables to fix to lb on up branch + int *upList_; +}; + +/** Define an idiotic idea class. + The idea of this is that we take some integer variables away from integer and + sum them with some randomness to get signed sum close to 0.5. We then can + branch to exclude that gap. + + This branching rule should be in addition to normal rules and have a high priority. +*/ + +class CbcIdiotBranch : public CbcObject { + +public: + // Default Constructor + CbcIdiotBranch(); + + /** Useful constructor + */ + CbcIdiotBranch(CbcModel *model); + + // Copy constructor + CbcIdiotBranch(const CbcIdiotBranch &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcIdiotBranch &operator=(const CbcIdiotBranch &rhs); + + // Destructor + ~CbcIdiotBranch(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// Initialize for branching + virtual void initializeForBranching(CbcModel *); + +protected: + /// Build "cut" + OsiRowCut buildCut(const OsiBranchingInformation *info, int type, int &preferredWay) const; + /// data + /// Thread specific random number generator + mutable CoinThreadRandom randomNumberGenerator_; + /// Saved version of thread specific random number generator + mutable CoinThreadRandom savedRandomNumberGenerator_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFullNodeInfo.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFullNodeInfo.hpp new file mode 100644 index 000000000..1846d9b44 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcFullNodeInfo.hpp @@ -0,0 +1,171 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/24/09 carved from CbcNode + +#ifndef CbcFullNodeInfo_H +#define CbcFullNodeInfo_H + +#include +#include + +#include "CoinWarmStartBasis.hpp" +#include "CoinSearchTree.hpp" +#include "CbcBranchBase.hpp" +#include "CbcNodeInfo.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiCuts; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinWarmStartBasis; +class CbcCountRowCut; +class CbcModel; +class CbcNode; +class CbcSubProblem; +class CbcGeneralBranchingObject; + +//############################################################################# +/** Information required to recreate the subproblem at this node + + When a subproblem is initially created, it is represented by a CbcNode + object and an attached CbcNodeInfo object. + + The CbcNode contains information needed while the subproblem remains live. + The CbcNode is deleted when the last branch arm has been evaluated. + + The CbcNodeInfo contains information required to maintain the branch-and-cut + search tree structure (links and reference counts) and to recreate the + subproblem for this node (basis, variable bounds, cutting planes). A + CbcNodeInfo object remains in existence until all nodes have been pruned from + the subtree rooted at this node. + + The principle used to maintain the reference count is that the reference + count is always the sum of all potential and actual children of the node. + Specifically, +
    +
  • Once it's determined how the node will branch, the reference count + is set to the number of potential children (i.e., the number + of arms of the branch). +
  • As each child is created by CbcNode::branch() (converting a potential + child to the active subproblem), the reference count is decremented. +
  • If the child survives and will become a node in the search tree + (converting the active subproblem into an actual child), increment the + reference count. +
+ Notice that the active subproblem lives in a sort of limbo, neither a + potential or an actual node in the branch-and-cut tree. + + CbcNodeInfo objects come in two flavours. A CbcFullNodeInfo object contains + a full record of the information required to recreate a subproblem. + A CbcPartialNodeInfo object expresses this information in terms of + differences from the parent. +*/ + +/** \brief Holds complete information for recreating a subproblem. + + A CbcFullNodeInfo object contains all necessary information (bounds, basis, + and cuts) required to recreate a subproblem. + + \todo While there's no explicit statement, the code often makes the implicit + assumption that an CbcFullNodeInfo structure will appear only at the + root node of the search tree. Things will break if this assumption + is violated. +*/ + +class CbcFullNodeInfo : public CbcNodeInfo { + +public: + /** \brief Modify model according to information at node + + The routine modifies the model according to bound information at node, + creates a new basis according to information at node, but with the size + passed in through basis, and adds any cuts to the addCuts array. + + \note The basis passed in via basis is solely a vehicle for passing in + the desired basis size. It will be deleted and a new basis returned. + */ + virtual void applyToModel(CbcModel *model, CoinWarmStartBasis *&basis, + CbcCountRowCut **addCuts, + int ¤tNumberCuts) const; + + /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) + virtual int applyBounds(int iColumn, double &lower, double &upper, int force); + + /** Builds up row basis backwards (until original model). + Returns NULL or previous one to apply . + Depends on Free being 0 and impossible for cuts + */ + virtual CbcNodeInfo *buildRowBasis(CoinWarmStartBasis &basis) const; + // Default Constructor + CbcFullNodeInfo(); + + /** Constructor from continuous or satisfied + */ + CbcFullNodeInfo(CbcModel *model, + int numberRowsAtContinuous); + + // Copy constructor + CbcFullNodeInfo(const CbcFullNodeInfo &); + + // Destructor + ~CbcFullNodeInfo(); + + /// Clone + virtual CbcNodeInfo *clone() const; + /// Lower bounds + inline const double *lower() const + { + return lower_; + } + /// Set a bound + inline void setColLower(int sequence, double value) + { + lower_[sequence] = value; + } + /// Mutable lower bounds + inline double *mutableLower() const + { + return lower_; + } + /// Upper bounds + inline const double *upper() const + { + return upper_; + } + /// Set a bound + inline void setColUpper(int sequence, double value) + { + upper_[sequence] = value; + } + /// Mutable upper bounds + inline double *mutableUpper() const + { + return upper_; + } + +protected: + // Data + /** Full basis + + This MUST BE A POINTER to avoid cutting extra information in derived + warm start classes. + */ + CoinWarmStartBasis *basis_; + int numberIntegers_; + // Bounds stored in full + double *lower_; + double *upper_; + +private: + /// Illegal Assignment operator + CbcFullNodeInfo &operator=(const CbcFullNodeInfo &rhs); +}; +#endif //CbcFullNodeInfo_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneral.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneral.hpp new file mode 100644 index 000000000..74f5936c6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneral.hpp @@ -0,0 +1,60 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcGeneral_H +#define CbcGeneral_H + +#include "CbcBranchBase.hpp" +/** Define a catch all class. + This will create a list of subproblems +*/ + +class CbcGeneral : public CbcObject { + +public: + // Default Constructor + CbcGeneral(); + + /** Useful constructor + Just needs to point to model. + */ + CbcGeneral(CbcModel *model); + + // Copy constructor + CbcGeneral(const CbcGeneral &); + + /// Clone + virtual CbcObject *clone() const = 0; + + // Assignment operator + CbcGeneral &operator=(const CbcGeneral &rhs); + + // Destructor + ~CbcGeneral(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion() = 0; + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns) = 0; + +protected: + /// data +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneralDepth.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneralDepth.hpp new file mode 100644 index 000000000..18d41c804 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcGeneralDepth.hpp @@ -0,0 +1,289 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcGeneralDepth_H +#define CbcGeneralDepth_H + +#include "CbcGeneral.hpp" +#include "CbcBranchBase.hpp" +#include "CbcSubProblem.hpp" + +#ifdef COIN_HAS_CLP + +/** Define a catch all class. + This will create a list of subproblems using partial evaluation +*/ +#include "ClpSimplex.hpp" +#include "ClpNode.hpp" + +class CbcGeneralDepth : public CbcGeneral { + +public: + // Default Constructor + CbcGeneralDepth(); + + /** Useful constructor + Just needs to point to model. + Initial version does evaluation to depth N + This is stored in CbcModel but may be + better here + */ + CbcGeneralDepth(CbcModel *model, int maximumDepth); + + // Copy constructor + CbcGeneralDepth(const CbcGeneralDepth &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcGeneralDepth &operator=(const CbcGeneralDepth &rhs); + + // Destructor + ~CbcGeneralDepth(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// Return maximum number of nodes + inline int maximumNodes() const + { + return maximumNodes_; + } + /// Get maximum depth + inline int maximumDepth() const + { + return maximumDepth_; + } + /// Set maximum depth + inline void setMaximumDepth(int value) + { + maximumDepth_ = value; + } + /// Return number of nodes + inline int numberNodes() const + { + return numberNodes_; + } + /// Get which solution + inline int whichSolution() const + { + return whichSolution_; + } + /// Get ClpNode info + inline ClpNode *nodeInfo(int which) + { + return nodeInfo_->nodeInfo_[which]; + } + + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns); + +protected: + /// data + /// Maximum depth + int maximumDepth_; + /// Maximum nodes + int maximumNodes_; + /// Which node has solution (or -1) + mutable int whichSolution_; + /// Number of valid nodes (including whichSolution_) + mutable int numberNodes_; + /// For solving nodes + mutable ClpNodeStuff *nodeInfo_; +}; +/** Branching object for general objects + + */ +class CbcNode; +class CbcGeneralBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcGeneralBranchingObject(); + + // Useful constructor + CbcGeneralBranchingObject(CbcModel *model); + + // Copy constructor + CbcGeneralBranchingObject(const CbcGeneralBranchingObject &); + + // Assignment operator + CbcGeneralBranchingObject &operator=(const CbcGeneralBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcGeneralBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + /** Double checks in case node can change its mind! + Can change objective etc */ + virtual void checkIsCutoff(double cutoff); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + /// Fill in current objective etc + void state(double &objectiveValue, double &sumInfeasibilities, + int &numberUnsatisfied, int which) const; + /// Set CbcNode + inline void setNode(CbcNode *node) + { + node_ = node; + } + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return GeneralDepthBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + /// Number of subproblems + inline int numberSubProblems() const + { + return numberSubProblems_; + } + /// Decrement number left and return number + inline int decrementNumberLeft() + { + numberSubLeft_--; + return numberSubLeft_; + } + /// Which node we want to use + inline int whichNode() const + { + return whichNode_; + } + /// Set which node we want to use + inline void setWhichNode(int value) + { + whichNode_ = value; + } + // Sub problem + const CbcSubProblem *subProblem(int which) const + { + return subProblems_ + which; + } + +public: + /// data + // Sub problems + CbcSubProblem *subProblems_; + /// Node + CbcNode *node_; + /// Number of subproblems + int numberSubProblems_; + /// Number of subproblems left + int numberSubLeft_; + /// Which node we want to use (-1 for default) + int whichNode_; + /// Number of rows + int numberRows_; +}; +/** Branching object for general objects - just one + + */ +class CbcOneGeneralBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcOneGeneralBranchingObject(); + + // Useful constructor + CbcOneGeneralBranchingObject(CbcModel *model, + CbcGeneralBranchingObject *object, + int whichOne); + + // Copy constructor + CbcOneGeneralBranchingObject(const CbcOneGeneralBranchingObject &); + + // Assignment operator + CbcOneGeneralBranchingObject &operator=(const CbcOneGeneralBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcOneGeneralBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + /** Double checks in case node can change its mind! + Can change objective etc */ + virtual void checkIsCutoff(double cutoff); + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return OneGeneralBranchingObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +public: + /// data + /// Object + CbcGeneralBranchingObject *object_; + /// Which one + int whichOne_; +}; +#endif //COIN_HAS_CLP +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristic.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristic.hpp new file mode 100644 index 000000000..d55fa802f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristic.hpp @@ -0,0 +1,735 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristic_H +#define CbcHeuristic_H + +#include +#include +#include "CoinPackedMatrix.hpp" +#include "OsiCuts.hpp" +#include "CoinHelperFunctions.hpp" +#include "OsiBranchingObject.hpp" +#include "CbcModel.hpp" + +class OsiSolverInterface; + +class CbcModel; +#ifdef COIN_HAS_CLP +#include "OsiClpSolverInterface.hpp" +#endif +//############################################################################# + +class CbcHeuristicNodeList; +class CbcBranchingObject; + +/** A class describing the branching decisions that were made to get + to the node where a heuristic was invoked from */ + +class CbcHeuristicNode { +private: + void gutsOfConstructor(CbcModel &model); + CbcHeuristicNode(); + CbcHeuristicNode &operator=(const CbcHeuristicNode &); + +private: + /// The number of branching decisions made + int numObjects_; + /** The indices of the branching objects. Note: an index may be + listed multiple times. E.g., a general integer variable that has + been branched on multiple times. */ + CbcBranchingObject **brObj_; + +public: + CbcHeuristicNode(CbcModel &model); + + CbcHeuristicNode(const CbcHeuristicNode &rhs); + ~CbcHeuristicNode(); + double distance(const CbcHeuristicNode *node) const; + double minDistance(const CbcHeuristicNodeList &nodeList) const; + bool minDistanceIsSmall(const CbcHeuristicNodeList &nodeList, + const double threshold) const; + double avgDistance(const CbcHeuristicNodeList &nodeList) const; +}; + +class CbcHeuristicNodeList { +private: + void gutsOfDelete(); + void gutsOfCopy(const CbcHeuristicNodeList &rhs); + +private: + std::vector< CbcHeuristicNode * > nodes_; + +public: + CbcHeuristicNodeList() {} + CbcHeuristicNodeList(const CbcHeuristicNodeList &rhs); + CbcHeuristicNodeList &operator=(const CbcHeuristicNodeList &rhs); + ~CbcHeuristicNodeList(); + + void append(CbcHeuristicNode *&node); + void append(const CbcHeuristicNodeList &nodes); + inline const CbcHeuristicNode *node(int i) const + { + return nodes_[i]; + } + inline int size() const + { + return static_cast< int >(nodes_.size()); + } +}; + +//############################################################################# +/** Heuristic base class */ + +class CbcHeuristic { +private: + void gutsOfDelete() {} + void gutsOfCopy(const CbcHeuristic &rhs); + +public: + // Default Constructor + CbcHeuristic(); + + // Constructor with model - assumed before cuts + CbcHeuristic(CbcModel &model); + + // Copy constructor + CbcHeuristic(const CbcHeuristic &); + + virtual ~CbcHeuristic(); + + /// Clone + virtual CbcHeuristic *clone() const = 0; + + /// Assignment operator + CbcHeuristic &operator=(const CbcHeuristic &rhs); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model) = 0; + + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value + This is called after cuts have been added - so can not add cuts + */ + virtual int solution(double &objectiveValue, + double *newSolution) + = 0; + + /** returns 0 if no solution, 1 if valid solution, -1 if just + returning an estimate of best possible solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if nonzero code) + This is called at same time as cut generators - so can add cuts + Default is do nothing + */ + virtual int solution2(double & /*objectiveValue*/, + double * /*newSolution*/, + OsiCuts & /*cs*/) + { + return 0; + } + + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate() {} + + /** Sets "when" flag - 0 off, 1 at root, 2 other than root, 3 always. + If 10 added then don't worry if validate says there are funny objects + as user knows it will be fine + */ + inline void setWhen(int value) + { + when_ = value; + } + /// Gets "when" flag - 0 off, 1 at root, 2 other than root, 3 always + inline int when() const + { + return when_; + } + + /// Sets number of nodes in subtree (default 200) + inline void setNumberNodes(int value) + { + numberNodes_ = value; + } + /// Gets number of nodes in a subtree (default 200) + inline int numberNodes() const + { + return numberNodes_; + } + /** Switches (does not apply equally to all heuristics) + 1 bit - stop once allowable gap on objective reached + 2 bit - always do given number of passes + 4 bit - weaken cutoff by 5% every 50 passes? + 8 bit - if has cutoff and suminf bobbling for 20 passes then + first try halving distance to best possible then + try keep halving distance to known cutoff + 16 bit - needs new solution to run + 1024 bit - stop all heuristics on max time + */ + inline void setSwitches(int value) + { + switches_ = value; + } + /** Switches (does not apply equally to all heuristics) + 1 bit - stop once allowable gap on objective reached + 2 bit - always do given number of passes + 4 bit - weaken cutoff by 5% every 50 passes? + 8 bit - if has cutoff and suminf bobbling for 20 passes then + first try halving distance to best possible then + try keep halving distance to known cutoff + 16 bit - needs new solution to run + 1024 bit - stop all heuristics on max time + 65536 bit and above used for temporary communication + */ + inline int switches() const + { + return switches_; + } + /// Whether to exit at once on gap + bool exitNow(double bestObjective) const; + /// Sets feasibility pump options (-1 is off) + inline void setFeasibilityPumpOptions(int value) + { + feasibilityPumpOptions_ = value; + } + /// Gets feasibility pump options (-1 is off) + inline int feasibilityPumpOptions() const + { + return feasibilityPumpOptions_; + } + /// Just set model - do not do anything else + inline void setModelOnly(CbcModel *model) + { + model_ = model; + } + + /// Sets fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound (default 1.0) + inline void setFractionSmall(double value) + { + fractionSmall_ = value; + } + /// Gets fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound (default 1.0) + inline double fractionSmall() const + { + return fractionSmall_; + } + /// Get how many solutions the heuristic thought it got + inline int numberSolutionsFound() const + { + return numberSolutionsFound_; + } + /// Increment how many solutions the heuristic thought it got + inline void incrementNumberSolutionsFound() + { + numberSolutionsFound_++; + } + + /** Do mini branch and bound - return + 0 not finished - no solution + 1 not finished - solution + 2 finished - no solution + 3 finished - solution + (could add global cut if finished) + -1 returned on size + -2 time or user event + */ + int smallBranchAndBound(OsiSolverInterface *solver, int numberNodes, + double *newSolution, double &newSolutionValue, + double cutoff, std::string name) const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + /// Create C++ lines to get to current state - does work for base class + void generateCpp(FILE *fp, const char *heuristic); + /// Returns true if can deal with "odd" problems e.g. sos type 2 + virtual bool canDealWithOdd() const + { + return false; + } + /// return name of heuristic + inline const char *heuristicName() const + { + return heuristicName_.c_str(); + } + /// set name of heuristic + inline void setHeuristicName(const char *name) + { + heuristicName_ = name; + } + /// Set random number generator seed + void setSeed(int value); + /// Get random number generator seed + int getSeed() const; + /// Sets decay factor (for howOften) on failure + inline void setDecayFactor(double value) + { + decayFactor_ = value; + } + /// Set input solution + void setInputSolution(const double *solution, double objValue); + /* Runs if bit set + 0 - before cuts at root node (or from doHeuristics) + 1 - during cuts at root + 2 - after root node cuts + 3 - after cuts at other nodes + 4 - during cuts at other nodes + 8 added if previous heuristic in loop found solution + */ + inline void setWhereFrom(int value) + { + whereFrom_ = value; + } + inline int whereFrom() const + { + return whereFrom_; + } + /** Upto this depth we call the tree shallow and the heuristic can be called + multiple times. That is, the test whether the current node is far from + the others where the jeuristic was invoked will not be done, only the + frequency will be tested. After that depth the heuristic will can be + invoked only once per node, right before branching. That's when it'll be + tested whether the heur should run at all. */ + inline void setShallowDepth(int value) + { + shallowDepth_ = value; + } + /** How often to invoke the heuristics in the shallow part of the tree */ + inline void setHowOftenShallow(int value) + { + howOftenShallow_ = value; + } + /** How "far" should this node be from every other where the heuristic was + run in order to allow the heuristic to run in this node, too. Currently + this is tested, but we may switch to avgDistanceToRun_ in the future. */ + inline void setMinDistanceToRun(int value) + { + minDistanceToRun_ = value; + } + + /** Check whether the heuristic should run at all + 0 - before cuts at root node (or from doHeuristics) + 1 - during cuts at root + 2 - after root node cuts + 3 - after cuts at other nodes + 4 - during cuts at other nodes + 8 added if previous heuristic in loop found solution + */ + virtual bool shouldHeurRun(int whereFrom); + /** Check whether the heuristic should run this time */ + bool shouldHeurRun_randomChoice(); + void debugNodes(); + void printDistanceToNodes(); + /// how many times the heuristic has actually run + inline int numRuns() const + { + return numRuns_; + } + + /// How many times the heuristic could run + inline int numCouldRun() const + { + return numCouldRun_; + } + /// Return objective function value with sign corrected + inline double trueObjValue(double value) const + { + return (model_->moreSpecialOptions2()&67108864)==0 ? value : -value; + } + /// Is it integer for heuristics? +#ifdef COIN_HAS_CLP + inline bool isHeuristicInteger(const OsiSolverInterface *solver, int iColumn) const + { + const OsiClpSolverInterface *clpSolver + = dynamic_cast< const OsiClpSolverInterface * >(solver); + if (clpSolver) + return clpSolver->isHeuristicInteger(iColumn); + else + return solver->isInteger(iColumn); + } +#else + inline bool isHeuristicInteger(const OsiSolverInterface *solver, int iColumn) + { + return solver->isInteger(iColumn); + } +#endif + /*! \brief Clone, but ... + + If type is + - 0 clone the solver for the model, + - 1 clone the continuous solver for the model + - Add 2 to say without integer variables which are at low priority + - Add 4 to say quite likely infeasible so give up easily (clp only). + */ + OsiSolverInterface *cloneBut(int type); + +protected: + /// Model + CbcModel *model_; + /// When flag - 0 off, 1 at root, 2 other than root, 3 always + int when_; + /// Number of nodes in any sub tree + int numberNodes_; + /** Feasibility pump options , -1 is off + >=0 for feasibility pump itself + -2 quick proximity search + -3 longer proximity search + */ + int feasibilityPumpOptions_; + /// Fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound + mutable double fractionSmall_; + /// Thread specific random number generator + CoinThreadRandom randomNumberGenerator_; + /// Name for printing + std::string heuristicName_; + + /// How often to do (code can change) + mutable int howOften_; + /// How much to increase how often + double decayFactor_; + /** Switches (does not apply equally to all heuristics) + 1 bit - stop once allowable gap on objective reached + 2 bit - always do given number of passes + 4 bit - weaken cutoff by 5% every 50 passes? + 8 bit - if has cutoff and suminf bobbling for 20 passes then + first try halving distance to best possible then + try keep halving distance to known cutoff + 16 bit - needs new solution to run + 1024 bit - stop all heuristics on max time + */ + mutable int switches_; + /* Runs if bit set + 0 - before cuts at root node (or from doHeuristics) + 1 - during cuts at root + 2 - after root node cuts + 3 - after cuts at other nodes + 4 - during cuts at other nodes + 8 added if previous heuristic in loop found solution + */ + int whereFrom_; + /** Upto this depth we call the tree shallow and the heuristic can be called + multiple times. That is, the test whether the current node is far from + the others where the jeuristic was invoked will not be done, only the + frequency will be tested. After that depth the heuristic will can be + invoked only once per node, right before branching. That's when it'll be + tested whether the heur should run at all. */ + int shallowDepth_; + /** How often to invoke the heuristics in the shallow part of the tree */ + int howOftenShallow_; + /** How many invocations happened within the same node when in a shallow + part of the tree. */ + int numInvocationsInShallow_; + /** How many invocations happened when in the deep part of the tree. For + every node we count only one invocation. */ + int numInvocationsInDeep_; + /** After how many deep invocations was the heuristic run last time */ + int lastRunDeep_; + /// how many times the heuristic has actually run + int numRuns_; + /** How "far" should this node be from every other where the heuristic was + run in order to allow the heuristic to run in this node, too. Currently + this is tested, but we may switch to avgDistanceToRun_ in the future. */ + int minDistanceToRun_; + + /// The description of the nodes where this heuristic has been applied + CbcHeuristicNodeList runNodes_; + + /// How many times the heuristic could run + int numCouldRun_; + + /// How many solutions the heuristic thought it got + int numberSolutionsFound_; + + /// How many nodes the heuristic did this go + mutable int numberNodesDone_; + + // Input solution - so can be used as seed + double *inputSolution_; + +#ifdef JJF_ZERO + /// Lower bounds of last node where the heuristic found a solution + double *lowerBoundLastNode_; + /// Upper bounds of last node where the heuristic found a solution + double *upperBoundLastNode_; +#endif +}; +/** Rounding class + */ + +class CbcRounding : public CbcHeuristic { +public: + // Default Constructor + CbcRounding(); + + // Constructor with model - assumed before cuts + CbcRounding(CbcModel &model); + + // Copy constructor + CbcRounding(const CbcRounding &); + + // Destructor + ~CbcRounding(); + + /// Assignment operator + CbcRounding &operator=(const CbcRounding &rhs); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + Use solutionValue rather than solvers one + */ + virtual int solution(double &objectiveValue, + double *newSolution, + double solutionValue); + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + + /// Set seed + void setSeed(int value) + { + seed_ = value; + } + /** Check whether the heuristic should run at all + 0 - before cuts at root node (or from doHeuristics) + 1 - during cuts at root + 2 - after root node cuts + 3 - after cuts at other nodes + 4 - during cuts at other nodes + 8 added if previous heuristic in loop found solution + */ + virtual bool shouldHeurRun(int whereFrom); + +protected: + // Data + + // Original matrix by column + CoinPackedMatrix matrix_; + + // Original matrix by + CoinPackedMatrix matrixByRow_; + + // Down locks + unsigned short *down_; + + // Up locks + unsigned short *up_; + + // Equality locks + unsigned short *equal_; + + // Seed for random stuff + int seed_; +}; + +/** Partial solution class + If user knows a partial solution this tries to get an integer solution + it uses hotstart information + */ + +class CbcHeuristicPartial : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicPartial(); + + /** Constructor with model - assumed before cuts + Fixes all variables with priority <= given + and does given number of nodes + */ + CbcHeuristicPartial(CbcModel &model, int fixPriority = 10000, int numberNodes = 200); + + // Copy constructor + CbcHeuristicPartial(const CbcHeuristicPartial &); + + // Destructor + ~CbcHeuristicPartial(); + + /// Assignment operator + CbcHeuristicPartial &operator=(const CbcHeuristicPartial &rhs); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + + /// Set priority level + void setFixPriority(int value) + { + fixPriority_ = value; + } + + /** Check whether the heuristic should run at all */ + virtual bool shouldHeurRun(int whereFrom); + +protected: + // Data + + // All variables with abs priority <= this will be fixed + int fixPriority_; +}; + +/** heuristic - just picks up any good solution + found by solver - see OsiBabSolver + */ + +class CbcSerendipity : public CbcHeuristic { +public: + // Default Constructor + CbcSerendipity(); + + /* Constructor with model + */ + CbcSerendipity(CbcModel &model); + + // Copy constructor + CbcSerendipity(const CbcSerendipity &); + + // Destructor + ~CbcSerendipity(); + + /// Assignment operator + CbcSerendipity &operator=(const CbcSerendipity &rhs); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// update model + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + We leave all variables which are at one at this node of the + tree to that value and will + initially set all others to zero. We then sort all variables in order of their cost + divided by the number of entries in rows which are not yet covered. We randomize that + value a bit so that ties will be broken in different ways on different runs of the heuristic. + We then choose the best one and set it to one and repeat the exercise. + + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + +protected: +}; + +/** Just One class - this chooses one at random + */ + +class CbcHeuristicJustOne : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicJustOne(); + + // Constructor with model - assumed before cuts + CbcHeuristicJustOne(CbcModel &model); + + // Copy constructor + CbcHeuristicJustOne(const CbcHeuristicJustOne &); + + // Destructor + ~CbcHeuristicJustOne(); + + /// Clone + virtual CbcHeuristicJustOne *clone() const; + + /// Assignment operator + CbcHeuristicJustOne &operator=(const CbcHeuristicJustOne &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + This does Fractional Diving + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + This is dummy as never called + */ + virtual bool selectVariableToBranch(OsiSolverInterface * /*solver*/, + const double * /*newSolution*/, + int & /*bestColumn*/, + int & /*bestRound*/) + { + return true; + } + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + /// Adds an heuristic with probability + void addHeuristic(const CbcHeuristic *heuristic, double probability); + /// Normalize probabilities + void normalizeProbabilities(); + +protected: + // Data + + // Probability of running a heuristic + double *probabilities_; + + // Heuristics + CbcHeuristic **heuristic_; + + // Number of heuristics + int numberHeuristics_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDINS.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDINS.hpp new file mode 100644 index 000000000..7b91648ed --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDINS.hpp @@ -0,0 +1,98 @@ +// $Id$ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// edwin 12/5/09 carved out of CbcHeuristicRINS + +#ifndef CbcHeuristicDINS_H +#define CbcHeuristicDINS_H + +#include "CbcHeuristic.hpp" + +class CbcHeuristicDINS : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicDINS(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicDINS(CbcModel &model); + + // Copy constructor + CbcHeuristicDINS(const CbcHeuristicDINS &); + + // Destructor + ~CbcHeuristicDINS(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicDINS &operator=(const CbcHeuristicDINS &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This does Relaxation Induced Neighborhood Search + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// This version fixes stuff and does IP + int solutionFix(double &objectiveValue, + double *newSolution, + const int *keep); + + /// Sets how often to do it + inline void setHowOften(int value) + { + howOften_ = value; + } + /// Sets maximum number of solutions kept + inline void setMaximumKeep(int value) + { + maximumKeepSolutions_ = value; + } + /// Sets tightness of extra constraint + inline void setConstraint(int value) + { + localSpace_ = value; + } + +protected: + // Data + + /// Number of solutions so we can do something at solution + int numberSolutions_; + /// How often to do (code can change) + int howOften_; + /// Number of successes + int numberSuccesses_; + /// Number of tries + int numberTries_; + /// Maximum number of solutions to keep + int maximumKeepSolutions_; + /// Number of solutions kept + int numberKeptSolutions_; + /// Number of integer variables + int numberIntegers_; + /// Local parameter + int localSpace_; + /// Values of integer variables + int **values_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDW.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDW.hpp new file mode 100644 index 000000000..d4ce51498 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDW.hpp @@ -0,0 +1,374 @@ +// $Id: CbcHeuristicDW.hpp 1899 2013-04-09 18:12:08Z stefan $ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDW_H +#define CbcHeuristicDW_H + +#include "CbcHeuristic.hpp" + +/** + This is unlike the other heuristics in that it is very very compute intensive. + It tries to find a DW structure and use that + */ + +class CbcHeuristicDW : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicDW(); + + /* Constructor with model - assumed before cuts + */ + CbcHeuristicDW(CbcModel &model, int keepContinuous = 0); + + /* Constructor with model - assumed before cuts + */ + CbcHeuristicDW(CbcModel &model, + int callBack(CbcHeuristicDW *currentHeuristic, + CbcModel *thisModel, + int whereFrom), + int keepContinuous = 0); + + // Copy constructor + CbcHeuristicDW(const CbcHeuristicDW &); + + // Destructor + ~CbcHeuristicDW(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicDW &operator=(const CbcHeuristicDW &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This does Relaxation Induced Neighborhood Search + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /** Return number of blocks + <=0 - no usable structure */ + inline int numberBlocks() const + { + return numberBlocks_; + } + /// Pass in a solution + void passInSolution(const double *solution); + /// Pass in continuous solution + void passInContinuousSolution(const double *solution); + /** DW Proposal actions + fullDWEverySoOften - + 0 - off + k - every k times solution gets better + */ + void setProposalActions(int fullDWEverySoOften); + /// Objective value when whichDw created + double objectiveValueWhen(int whichDW) const; + /// Number of columns in DW + int numberColumnsDW(int whichDW) const; + /// Solver + inline OsiSolverInterface *solver() const + { + return solver_; + } + /// DW model (user must delete) + OsiSolverInterface *DWModel(int whichDW) const; + /// Best objective value + inline double bestObjective() const + { + return bestObjective_; + } + /// Best solution found so far + inline const double *bestSolution() const + { + return bestSolution_; + } + /// Continuous solution + inline const double *continuousSolution() const + { + return continuousSolution_; + } + /// Reduced costs of fixed solution + inline const double *fixedDj() const + { + return fixedDj_; + } + /// Objective at which DW updated + inline const double *objectiveDW() const + { + return objectiveDW_; + } + /// Number of times we have added to DW model + inline int numberDWTimes() const + { + return numberDWTimes_; + } + /// Number of columns in DW + inline const int *numberColumnsDW() const + { + return numberColumnsDW_; + } + /// Set number of passes + inline void setNumberPasses(int value) + { + numberPasses_ = value; + } + /// Set number of passes without better solution + inline void setNumberBadPasses(int value) + { + numberBadPasses_ = value; + } + /// Set number free integers needed (Base value) + inline void setNumberNeeded(int value) + { + nNeededBase_ = value; + } + /// Get number free integers needed (Base value) + inline int getNumberNeeded() const + { + return nNeededBase_; + } + /// Set number free integers needed (Current value) + inline void setCurrentNumberNeeded(int value) + { + nNeeded_ = value; + } + /// Get number free integers needed (Current value) + inline int getCurrentNumberNeeded() const + { + return nNeeded_; + } + /// Set number nodes (could be done in callback) (Base value) + inline void setNumberNodes(int value) + { + nNodesBase_ = value; + } + /// Get number nodes (could be done in callback) (Base value) + inline int getNumberNodes() const + { + return nNodesBase_; + } + /// Set number nodes (could be done in callback) (Current value) + inline void setCurrentNumberNodes(int value) + { + nNodes_ = value; + } + /// Get number nodes (could be done in callback) (Current value) + inline int getCurrentNumberNodes() const + { + return nNodes_; + } + /// Set target objective + inline void setTargetObjective(double value) + { + targetObjective_ = value; + } + /// Sets how often to do it + inline void setHowOften(int value) + { + howOften_ = value; + } + /// Block for every row + inline const int *whichRowBlock() const + { + return whichRowBlock_; + } + /// Block for every column + inline const int *whichColumnBlock() const + { + return whichColumnBlock_; + } + /// Initial Lower bounds + inline double *initialLower() const + { + return saveLower_; + } + /// Initial Upper bounds + inline double *initialUpper() const + { + return saveUpper_; + } + /// Local integer arrays (each numberBlocks_ long) + inline int *intArrays() const + { + return intArray_; + } + /// Local double arrays (each numberBlocks_ long) + inline double *doubleArrays() const + { + return doubleArray_; + } + /// Phase of solution + inline int phase() const + { + return phase_; + } + /// Pass number + inline int pass() const + { + return pass_; + } + /// Which columns are in block + inline const int *columnsInBlock() const + { + return columnsInBlock_; + } + /// Starts for columnsInBlock + inline const int *startColumnBlock() const + { + return startColumnBlock_; + } + /// Number of integer variables in each block + inline const int *intsInBlock() const + { + return intsInBlock_; + } + /// Objective value (could also check validity) + double objectiveValue(const double *solution); + +private: + /// Guts of copy + void gutsOfCopy(const CbcHeuristicDW &rhs); + /// Guts of delete + void gutsOfDelete(); + /// Set default values + void setDefaults(); + /// Find structure + void findStructure(); + /// Set up DW structure + void setupDWStructures(); + /// Add DW proposals + int addDW(const double *solution, int numberBlocksUsed, + const int *whichBlocks); + +protected: + typedef int (*heuristicCallBack)(CbcHeuristicDW *, CbcModel *, int); + // Data + /// Target objective + double targetObjective_; + /// Best objective value + double bestObjective_; + /// Objective value last time + double lastObjective_; + /** Call back + whereFrom - + 0 - after blocks found but before data setup + 1 - after blocks sorted but before used + 2 - just before normal branch and bound + 3 - after DW has been updated + 4 - if better solution found + 5 - every time a block might be used + next few for adjustment of nNeeded etc + 6 - complete search done - no solution + 7 - stopped on nodes - no improvement + 8 - improving (same as 4 but after nNeeded changed + Pointers to local data given by following pointers + */ + heuristicCallBack functionPointer_; + /// Local integer arrays (each numberBlocks_ long) + int *intArray_; + /// Local double arrays (each numberBlocks_ long) + double *doubleArray_; + /// Base solver + OsiSolverInterface *solver_; + /// DW solver + OsiSolverInterface *dwSolver_; + /// Best solution found so far + double *bestSolution_; + /// Continuous solution + double *continuousSolution_; + /// Reduced costs of fixed solution + double *fixedDj_; + /// Original lower bounds + double *saveLower_; + /// Original Upper bounds + double *saveUpper_; + /// random numbers for master rows + double *random_; + /// Weights for each proposal + double *weights_; + /// Objective at which DW updated + double *objectiveDW_; + /// Number of columns in each DW + int *numberColumnsDW_; + /// Block for every row + int *whichRowBlock_; + /// Block for every column + int *whichColumnBlock_; + /// Block number for each proposal + int *dwBlock_; + /// Points back to master rows + int *backwardRow_; + /// Which rows are in blocke + int *rowsInBlock_; + /// Which columns are in block + int *columnsInBlock_; + /// Starts for rowsInBlock + int *startRowBlock_; + /// Starts for columnsInBlock + int *startColumnBlock_; + /// Number of integer variables in each block + int *intsInBlock_; + /// Bits set for 1 integers in each block + unsigned int *fingerPrint_; + /// Affinity each block has for other (will be triangular?) + unsigned short *affinity_; + /** DW Proposal actions + fullDWEverySoOften - + 0 - off + k - every k times solution gets better + */ + int fullDWEverySoOften_; + /// Number of passes + int numberPasses_; + /// How often to do (code can change) + int howOften_; + /// Current maximum number of DW proposals + int maximumDW_; + /// Number of DW proposals + int numberDW_; + /// Number of times we have added to DW model + int numberDWTimes_; + /// Number of unsigned ints needed for each block of fingerPrint + int sizeFingerPrint_; + /// Number of columns in master + int numberMasterColumns_; + /// Number of rows in master + int numberMasterRows_; + /// Number of blocks + int numberBlocks_; + /// Action on decomposition - 1 keep continuous, 0 don't + int keepContinuous_; + /// Phase of solution + int phase_; + /// Pass number + int pass_; + /// Base number of integers needed + int nNeededBase_; + /// Base number of nodes needed + int nNodesBase_; + /// Base number of integers needed + int nNeeded_; + /// Base number of nodes needed + int nNodes_; + /// Number of passes without better solution + int numberBadPasses_; + // 0 - fine, 1 can't be better, 2 max node + int solveState_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDive.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDive.hpp new file mode 100644 index 000000000..026e2414d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDive.hpp @@ -0,0 +1,198 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDive_H +#define CbcHeuristicDive_H + +#include "CbcHeuristic.hpp" +class CbcSubProblem; +class OsiRowCut; +struct PseudoReducedCost { + int var; + double pseudoRedCost; +}; + +/** Dive class + */ + +class CbcHeuristicDive : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicDive(); + + // Constructor with model - assumed before cuts + CbcHeuristicDive(CbcModel &model); + + // Copy constructor + CbcHeuristicDive(const CbcHeuristicDive &); + + // Destructor + ~CbcHeuristicDive(); + + /// Clone + virtual CbcHeuristicDive *clone() const = 0; + + /// Assignment operator + CbcHeuristicDive &operator=(const CbcHeuristicDive &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + + /// Create C++ lines to get to current state - does work for base class + void generateCpp(FILE *fp, const char *heuristic); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + // REMLOVE using CbcHeuristic::solution ; + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + This does Fractional Diving + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// inner part of dive + int solution(double &objectiveValue, int &numberNodes, + int &numberCuts, OsiRowCut **cuts, + CbcSubProblem **&nodes, + double *newSolution); + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + also returns list of nodes + This does Fractional Diving + */ + int fathom(CbcModel *model, int &numberNodes, CbcSubProblem **&nodes); + + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + + /// Sets priorities if any + void setPriorities(); + + /// Select candidate binary variables for fixing + void selectBinaryVariables(); + + /// Set percentage of integer variables to fix at bounds + void setPercentageToFix(double value) + { + percentageToFix_ = value; + } + + /// Set maximum number of iterations + void setMaxIterations(int value) + { + maxIterations_ = value; + } + + /// Set maximum number of simplex iterations + void setMaxSimplexIterations(int value) + { + maxSimplexIterations_ = value; + } + /// Get maximum number of simplex iterations + inline int maxSimplexIterations() const + { + return maxSimplexIterations_; + } + + /// Set maximum number of simplex iterations at root node + void setMaxSimplexIterationsAtRoot(int value) + { + maxSimplexIterationsAtRoot_ = value; + } + + /// Set maximum time allowed + void setMaxTime(double value) + { + maxTime_ = value; + } + + /// Tests if the heuristic can run + virtual bool canHeuristicRun(); + + /** Selects the next variable to branch on + Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound) + = 0; + /** Initializes any data which is going to be used repeatedly + in selectVariableToBranch */ + virtual void initializeData() {} + + /// Perform reduced cost fixing on integer variables + int reducedCostFix(OsiSolverInterface *solver); + /// Fix other variables at bounds + virtual int fixOtherVariables(OsiSolverInterface *solver, + const double *solution, + PseudoReducedCost *candidate, + const double *random); + +protected: + // Data + + // Original matrix by column + CoinPackedMatrix matrix_; + + // Original matrix by + CoinPackedMatrix matrixByRow_; + + // Down locks + unsigned short *downLocks_; + + // Up locks + unsigned short *upLocks_; + + /// Extra down array (number Integers long) + double *downArray_; + + /// Extra up array (number Integers long) + double *upArray_; + + /// Array of priorities + typedef struct { + unsigned int direction : 3; // 0 bit off, 1 bit (0 down first, 1 up first) 2 bit non zero don't try other way + unsigned int priority : 29; + } PriorityType; + PriorityType *priority_; + // Indexes of binary variables with 0 objective coefficient + // and in variable bound constraints + std::vector< int > binVarIndex_; + + // Indexes of variable bound rows for each binary variable + std::vector< int > vbRowIndex_; + + // Percentage of integer variables to fix at bounds + double percentageToFix_; + + // Maximum time allowed + double maxTime_; + + // Small objective (i.e. treat zero objective as this) + double smallObjective_; + + // Maximum number of major iterations + int maxIterations_; + + // Maximum number of simplex iterations + int maxSimplexIterations_; + + // Maximum number of simplex iterations at root node + int maxSimplexIterationsAtRoot_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveCoefficient.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveCoefficient.hpp new file mode 100644 index 000000000..b47af6727 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveCoefficient.hpp @@ -0,0 +1,52 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDiveCoefficient_H +#define CbcHeuristicDiveCoefficient_H + +#include "CbcHeuristicDive.hpp" + +/** DiveCoefficient class + */ + +class CbcHeuristicDiveCoefficient : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDiveCoefficient(); + + // Constructor with model - assumed before cuts + CbcHeuristicDiveCoefficient(CbcModel &model); + + // Copy constructor + CbcHeuristicDiveCoefficient(const CbcHeuristicDiveCoefficient &); + + // Destructor + ~CbcHeuristicDiveCoefficient(); + + /// Clone + virtual CbcHeuristicDiveCoefficient *clone() const; + + /// Assignment operator + CbcHeuristicDiveCoefficient &operator=(const CbcHeuristicDiveCoefficient &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveFractional.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveFractional.hpp new file mode 100644 index 000000000..fcdf45ea7 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveFractional.hpp @@ -0,0 +1,52 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDiveFractional_H +#define CbcHeuristicDiveFractional_H + +#include "CbcHeuristicDive.hpp" + +/** DiveFractional class + */ + +class CbcHeuristicDiveFractional : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDiveFractional(); + + // Constructor with model - assumed before cuts + CbcHeuristicDiveFractional(CbcModel &model); + + // Copy constructor + CbcHeuristicDiveFractional(const CbcHeuristicDiveFractional &); + + // Destructor + ~CbcHeuristicDiveFractional(); + + /// Clone + virtual CbcHeuristicDiveFractional *clone() const; + + /// Assignment operator + CbcHeuristicDiveFractional &operator=(const CbcHeuristicDiveFractional &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveGuided.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveGuided.hpp new file mode 100644 index 000000000..07ac54626 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveGuided.hpp @@ -0,0 +1,55 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDiveGuided_H +#define CbcHeuristicDiveGuided_H + +#include "CbcHeuristicDive.hpp" + +/** DiveGuided class + */ + +class CbcHeuristicDiveGuided : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDiveGuided(); + + // Constructor with model - assumed before cuts + CbcHeuristicDiveGuided(CbcModel &model); + + // Copy constructor + CbcHeuristicDiveGuided(const CbcHeuristicDiveGuided &); + + // Destructor + ~CbcHeuristicDiveGuided(); + + /// Clone + virtual CbcHeuristicDiveGuided *clone() const; + + /// Assignment operator + CbcHeuristicDiveGuided &operator=(const CbcHeuristicDiveGuided &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Tests if the heuristic can run + virtual bool canHeuristicRun(); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveLineSearch.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveLineSearch.hpp new file mode 100644 index 000000000..438d41898 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveLineSearch.hpp @@ -0,0 +1,52 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDiveLineSearch_H +#define CbcHeuristicDiveLineSearch_H + +#include "CbcHeuristicDive.hpp" + +/** DiveLineSearch class + */ + +class CbcHeuristicDiveLineSearch : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDiveLineSearch(); + + // Constructor with model - assumed before cuts + CbcHeuristicDiveLineSearch(CbcModel &model); + + // Copy constructor + CbcHeuristicDiveLineSearch(const CbcHeuristicDiveLineSearch &); + + // Destructor + ~CbcHeuristicDiveLineSearch(); + + /// Clone + virtual CbcHeuristicDiveLineSearch *clone() const; + + /// Assignment operator + CbcHeuristicDiveLineSearch &operator=(const CbcHeuristicDiveLineSearch &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDivePseudoCost.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDivePseudoCost.hpp new file mode 100644 index 000000000..75e6a1c18 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDivePseudoCost.hpp @@ -0,0 +1,60 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDivePseudoCost_H +#define CbcHeuristicDivePseudoCost_H + +#include "CbcHeuristicDive.hpp" + +/** DivePseudoCost class + */ + +class CbcHeuristicDivePseudoCost : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDivePseudoCost(); + + // Constructor with model - assumed before cuts + CbcHeuristicDivePseudoCost(CbcModel &model); + + // Copy constructor + CbcHeuristicDivePseudoCost(const CbcHeuristicDivePseudoCost &); + + // Destructor + ~CbcHeuristicDivePseudoCost(); + + /// Clone + virtual CbcHeuristicDivePseudoCost *clone() const; + + /// Assignment operator + CbcHeuristicDivePseudoCost &operator=(const CbcHeuristicDivePseudoCost &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); + /** Initializes any data which is going to be used repeatedly + in selectVariableToBranch */ + virtual void initializeData(); + /// Fix other variables at bounds + virtual int fixOtherVariables(OsiSolverInterface *solver, + const double *solution, + PseudoReducedCost *candidate, + const double *random); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveVectorLength.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveVectorLength.hpp new file mode 100644 index 000000000..1ecf97a78 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicDiveVectorLength.hpp @@ -0,0 +1,52 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicDiveVectorLength_H +#define CbcHeuristicDiveVectorLength_H + +#include "CbcHeuristicDive.hpp" + +/** DiveVectorLength class + */ + +class CbcHeuristicDiveVectorLength : public CbcHeuristicDive { +public: + // Default Constructor + CbcHeuristicDiveVectorLength(); + + // Constructor with model - assumed before cuts + CbcHeuristicDiveVectorLength(CbcModel &model); + + // Copy constructor + CbcHeuristicDiveVectorLength(const CbcHeuristicDiveVectorLength &); + + // Destructor + ~CbcHeuristicDiveVectorLength(); + + /// Clone + virtual CbcHeuristicDiveVectorLength *clone() const; + + /// Assignment operator + CbcHeuristicDiveVectorLength &operator=(const CbcHeuristicDiveVectorLength &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Selects the next variable to branch on + /** Returns true if all the fractional variables can be trivially + rounded. Returns false, if there is at least one fractional variable + that is not trivially roundable. In this case, the bestColumn + returned will not be trivially roundable. + */ + virtual bool selectVariableToBranch(OsiSolverInterface *solver, + const double *newSolution, + int &bestColumn, + int &bestRound); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicFPump.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicFPump.hpp new file mode 100644 index 000000000..b6707d5a6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicFPump.hpp @@ -0,0 +1,375 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicFeasibilityPump_H +#define CbcHeuristicFeasibilityPump_H + +#include "CbcHeuristic.hpp" +#include "OsiClpSolverInterface.hpp" + +/** Feasibility Pump class + */ + +class CbcHeuristicFPump : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicFPump(); + + // Constructor with model - assumed before cuts + CbcHeuristicFPump(CbcModel &model, + double downValue = 0.5, bool roundExpensive = false); + + // Copy constructor + CbcHeuristicFPump(const CbcHeuristicFPump &); + + // Destructor + ~CbcHeuristicFPump(); + + /// Assignment operator + CbcHeuristicFPump &operator=(const CbcHeuristicFPump &rhs); + /// Clone + virtual CbcHeuristic *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts. + + It may make sense for user to call this outside Branch and Cut to + get solution. Or normally is just at root node. + + * new meanings for when_ - on first try then set back to 1 + 11 - at end fix all integers at same bound throughout + 12 - also fix all integers staying at same internal integral value throughout + 13 - also fix all continuous variables staying at same bound throughout + 14 - also fix all continuous variables staying at same internal value throughout + 15 - as 13 but no internal integers + And beyond that, it's apparently possible for the range to be between 21 + and 25, in which case it's reduced on entry to solution() to be between + 11 and 15 and allSlack is set to true. Then, if we're not processing + general integers, we'll use an all-slack basis to solve ... what? Don't + see that yet. + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /** If general integers then adds variables to turn into binaries round + solution + */ + int solutionGeneral(double &objectiveValue, double *newSolution, + int maxAround = 1, bool fixSatisfied = false); + /// Set maximum Time (default off) - also sets starttime to current + void setMaximumTime(double value); + /// Get maximum Time (default 0.0 == time limit off) + inline double maximumTime() const + { + return maximumTime_; + } + /// Set fake cutoff (default COIN_DBL_MAX == off) + inline void setFakeCutoff(double value) + { + fakeCutoff_ = value; + } + /// Get fake cutoff (default 0.0 == off) + inline double fakeCutoff() const + { + return fakeCutoff_; + } + /// Set absolute increment (default 0.0 == off) + inline void setAbsoluteIncrement(double value) + { + absoluteIncrement_ = value; + } + /// Get absolute increment (default 0.0 == off) + inline double absoluteIncrement() const + { + return absoluteIncrement_; + } + /// Set relative increment (default 0.0 == off) + inline void setRelativeIncrement(double value) + { + relativeIncrement_ = value; + } + /// Get relative increment (default 0.0 == off) + inline double relativeIncrement() const + { + return relativeIncrement_; + } + /// Set default rounding (default 0.5) + inline void setDefaultRounding(double value) + { + defaultRounding_ = value; + } + /// Get default rounding (default 0.5) + inline double defaultRounding() const + { + return defaultRounding_; + } + /// Set initial weight (default 0.0 == off) + inline void setInitialWeight(double value) + { + initialWeight_ = value; + } + /// Get initial weight (default 0.0 == off) + inline double initialWeight() const + { + return initialWeight_; + } + /// Set weight factor (default 0.1) + inline void setWeightFactor(double value) + { + weightFactor_ = value; + } + /// Get weight factor (default 0.1) + inline double weightFactor() const + { + return weightFactor_; + } + /// Set threshold cost for using original cost - even on continuous (default infinity) + inline void setArtificialCost(double value) + { + artificialCost_ = value; + } + /// Get threshold cost for using original cost - even on continuous (default infinity) + inline double artificialCost() const + { + return artificialCost_; + } + /// Get iteration to size ratio + inline double iterationRatio() const + { + return iterationRatio_; + } + /// Set iteration to size ratio + inline void setIterationRatio(double value) + { + iterationRatio_ = value; + } + /// Set maximum passes (default 100) + inline void setMaximumPasses(int value) + { + maximumPasses_ = value; + } + /// Get maximum passes (default 100) + inline int maximumPasses() const + { + return maximumPasses_; + } + /// Set maximum retries (default 1) + inline void setMaximumRetries(int value) + { + maximumRetries_ = value; + } + /// Get maximum retries (default 1) + inline int maximumRetries() const + { + return maximumRetries_; + } + /** Set use of multiple solutions and solves + 0 - do not reuse solves, do not accumulate integer solutions for local search + 1 - do not reuse solves, accumulate integer solutions for local search + 2 - reuse solves, do not accumulate integer solutions for local search + 3 - reuse solves, accumulate integer solutions for local search + If we add 4 then use second form of problem (with extra rows and variables for general integers) + At some point (date?), I added + + And then there are a few bit fields: + 4 - something about general integers + So my (lh) guess for 4 was at least in the ballpark, but I'll have to + rethink 8 entirely (and it may well not mean the same thing as it did + when I added that comment. + 8 - determines whether we process general integers + + And on 090831, John added + + If we add 4 then use second form of problem (with extra rows and + variables for general integers) + If we add 8 then can run after initial cuts (if no solution) + */ + inline void setAccumulate(int value) + { + accumulate_ = value; + } + /// Get accumulation option + inline int accumulate() const + { + return accumulate_; + } + /** Set whether to fix variables on known solution + 0 - do not fix + 1 - fix integers on reduced costs + 2 - fix integers on reduced costs but only on entry + */ + inline void setFixOnReducedCosts(int value) + { + fixOnReducedCosts_ = value; + } + /// Get reduced cost option + inline int fixOnReducedCosts() const + { + return fixOnReducedCosts_; + } + /** Set reduced cost multiplier + 1.0 as normal + <1.0 (x) - pretend gap is x* actual gap - just for fixing + */ + inline void setReducedCostMultiplier(double value) + { + reducedCostMultiplier_ = value; + } + /// Get reduced cost multiplier + inline double reducedCostMultiplier() const + { + return reducedCostMultiplier_; + } + +protected: + // Data + /// Start time + double startTime_; + /// Maximum Cpu seconds + double maximumTime_; + /** Fake cutoff value. + If set then better of real cutoff and this used to add a constraint + */ + double fakeCutoff_; + /// If positive carry on after solution expecting gain of at least this + double absoluteIncrement_; + /// If positive carry on after solution expecting gain of at least this times objective + double relativeIncrement_; + /// Default is round up if > this + double defaultRounding_; + /// Initial weight for true objective + double initialWeight_; + /// Factor for decreasing weight + double weightFactor_; + /// Threshold cost for using original cost - even on continuous + double artificialCost_; + /** If iterationRatio >0 use instead of maximumPasses_ + test is iterations > ratio*(2*nrow+ncol) */ + double iterationRatio_; + /** Reduced cost multiplier + 1.0 as normal + <1.0 (x) - pretend gap is x* actual gap - just for fixing + */ + double reducedCostMultiplier_; + /// Maximum number of passes + int maximumPasses_; + /** Maximum number of retries if we find a solution. + If negative we clean out used array + */ + int maximumRetries_; + /** Set use of multiple solutions and solves + 0 - do not reuse solves, do not accumulate integer solutions for local search + 1 - do not reuse solves, accumulate integer solutions for local search + 2 - reuse solves, do not accumulate integer solutions for local search + 3 - reuse solves, accumulate integer solutions for local search + If we add 4 then use second form of problem (with extra rows and variables for general integers) + If we do not accumulate solutions then no mini branch and bounds will be done + reuse - refers to initial solve after adding in new "cut" + If we add 8 then can run after initial cuts (if no solution) + 16 - extra rounding + 32,64,128 - create binaries for general + */ + int accumulate_; + /** Set whether to fix variables on known solution + 0 - do not fix + 1 - fix integers on reduced costs + 2 - fix integers on reduced costs but only on entry + */ + int fixOnReducedCosts_; + /// If true round to expensive + bool roundExpensive_; + +private: + /** Rounds solution - down if < downValue + If roundExpensive then always to more expnsive. + returns 0 if current is solution + */ + int rounds(OsiSolverInterface *solver, double *solution, + /*const double * objective, */ + int numberIntegers, const int *integerVariable, + /*char * pumpPrint,*/ int passNumber, + /*bool roundExpensive=false,*/ + double downValue = 0.5, int *flip = 0); + /// Does real work + int solutionInternal(double &objectiveValue, double *newSolution); + /* note for eagle eyed readers. + when_ can now be exotic - + <=10 normal + */ +}; + +#ifdef COIN_HAS_CLP + +class CbcDisasterHandler : public OsiClpDisasterHandler { +public: + /**@name Virtual methods that the derived classe should provide. + */ + //@{ +#ifdef JJF_ZERO + /// Into simplex + virtual void intoSimplex(); + /// Checks if disaster + virtual bool check() const; + /// saves information for next attempt + virtual void saveInfo(); +#endif + /// Type of disaster 0 can fix, 1 abort + virtual int typeOfDisaster(); + //@} + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CbcDisasterHandler(CbcModel *model = NULL); + /** Destructor */ + virtual ~CbcDisasterHandler(); + // Copy + CbcDisasterHandler(const CbcDisasterHandler &); + // Assignment + CbcDisasterHandler &operator=(const CbcDisasterHandler &); + /// Clone + virtual ClpDisasterHandler *clone() const; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setCbcModel(CbcModel *model); + /// Get model + inline CbcModel *cbcModel() const + { + return cbcModel_; + } + + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to model + CbcModel *cbcModel_; + + //@} +}; +#endif + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicGreedy.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicGreedy.hpp new file mode 100644 index 000000000..bf6e69fb4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicGreedy.hpp @@ -0,0 +1,289 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicGreedy_H +#define CbcHeuristicGreedy_H + +#include "CbcHeuristic.hpp" +/** Greedy heuristic classes + */ + +class CbcHeuristicGreedyCover : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicGreedyCover(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicGreedyCover(CbcModel &model); + + // Copy constructor + CbcHeuristicGreedyCover(const CbcHeuristicGreedyCover &); + + // Destructor + ~CbcHeuristicGreedyCover(); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Assignment operator + CbcHeuristicGreedyCover &operator=(const CbcHeuristicGreedyCover &rhs); + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + We leave all variables which are at one at this node of the + tree to that value and will + initially set all others to zero. We then sort all variables in order of their cost + divided by the number of entries in rows which are not yet covered. We randomize that + value a bit so that ties will be broken in different ways on different runs of the heuristic. + We then choose the best one and set it to one and repeat the exercise. + + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + /* Algorithm + 0 - use current upper bounds + 1 - use original upper bounds + If 10 added perturb ratios more + if 100 added round up all >=0.5 + */ + inline int algorithm() const + { + return algorithm_; + } + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + // Only do this many times + inline int numberTimes() const + { + return numberTimes_; + } + inline void setNumberTimes(int value) + { + numberTimes_ = value; + } + +protected: + /// Guts of constructor from a CbcModel + void gutsOfConstructor(CbcModel *model); + // Data + + // Original matrix by column + CoinPackedMatrix matrix_; + // original number of rows + int originalNumberRows_; + /* Algorithm + 0 - use current upper bounds + 1 - use original upper bounds + If 10 added perturb ratios more + */ + int algorithm_; + /// Do this many times + int numberTimes_; +}; + +class CbcHeuristicGreedyEquality : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicGreedyEquality(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicGreedyEquality(CbcModel &model); + + // Copy constructor + CbcHeuristicGreedyEquality(const CbcHeuristicGreedyEquality &); + + // Destructor + ~CbcHeuristicGreedyEquality(); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Assignment operator + CbcHeuristicGreedyEquality &operator=(const CbcHeuristicGreedyEquality &rhs); + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + We leave all variables which are at one at this node of the + tree to that value and will + initially set all others to zero. We then sort all variables in order of their cost + divided by the number of entries in rows which are not yet covered. We randomize that + value a bit so that ties will be broken in different ways on different runs of the heuristic. + We then choose the best one and set it to one and repeat the exercise. + + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + /* Algorithm + 0 - use current upper bounds + 1 - use original upper bounds + If 10 added perturb ratios more + if 100 added round up all >=0.5 + */ + inline int algorithm() const + { + return algorithm_; + } + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + // Fraction of rhs to cover before branch and cut + inline void setFraction(double value) + { + fraction_ = value; + } + inline double fraction() const + { + return fraction_; + } + // Only do this many times + inline int numberTimes() const + { + return numberTimes_; + } + inline void setNumberTimes(int value) + { + numberTimes_ = value; + } + +protected: + /// Guts of constructor from a CbcModel + void gutsOfConstructor(CbcModel *model); + // Data + + // Original matrix by column + CoinPackedMatrix matrix_; + // Fraction of rhs to cover before branch and cut + double fraction_; + // original number of rows + int originalNumberRows_; + /* Algorithm + 0 - use current upper bounds + 1 - use original upper bounds + If 10 added perturb ratios more + */ + int algorithm_; + /// Do this many times + int numberTimes_; +}; + +/** Greedy heuristic for SOS and L rows (and positive elements) + */ + +class CbcHeuristicGreedySOS : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicGreedySOS(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicGreedySOS(CbcModel &model); + + // Copy constructor + CbcHeuristicGreedySOS(const CbcHeuristicGreedySOS &); + + // Destructor + ~CbcHeuristicGreedySOS(); + + /// Clone + virtual CbcHeuristic *clone() const; + /// Assignment operator + CbcHeuristicGreedySOS &operator=(const CbcHeuristicGreedySOS &rhs); + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + We leave all variables which are at one at this node of the + tree to that value and will + initially set all others to zero. We then sort all variables in order of their cost + divided by the number of entries in rows which are not yet covered. We randomize that + value a bit so that ties will be broken in different ways on different runs of the heuristic. + We then choose the best one and set it to one and repeat the exercise. + + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Validate model i.e. sets when_ to 0 if necessary (may be NULL) + virtual void validate(); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + /* Algorithm + Bits + 1 bit - use current model, otherwise original + 2 - use current solution as starting point, otherwise pure greedy + 4 - as 2 but use merit not merit/size + 8 - use duals to modify greedy + 16 - use duals on GUB/SOS in special way + */ + inline int algorithm() const + { + return algorithm_; + } + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + // Only do this many times + inline int numberTimes() const + { + return numberTimes_; + } + inline void setNumberTimes(int value) + { + numberTimes_ = value; + } + +protected: + /// Guts of constructor from a CbcModel + void gutsOfConstructor(CbcModel *model); + // Data + + // Original RHS - if -1.0 then SOS otherwise <= value + double *originalRhs_; + // Original matrix by column + CoinPackedMatrix matrix_; + // original number of rows + int originalNumberRows_; + /* Algorithm + */ + int algorithm_; + /// Do this many times + int numberTimes_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicLocal.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicLocal.hpp new file mode 100644 index 000000000..8db39db91 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicLocal.hpp @@ -0,0 +1,276 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicLocal_H +#define CbcHeuristicLocal_H + +#include "CbcHeuristic.hpp" +/** LocalSearch class + */ + +class CbcHeuristicLocal : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicLocal(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicLocal(CbcModel &model); + + // Copy constructor + CbcHeuristicLocal(const CbcHeuristicLocal &); + + // Destructor + ~CbcHeuristicLocal(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicLocal &operator=(const CbcHeuristicLocal &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This is called after cuts have been added - so can not add cuts + First tries setting a variable to better value. If feasible then + tries setting others. If not feasible then tries swaps + + ******** + + This first version does not do LP's and does swaps of two integer + variables. Later versions could do Lps. + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// This version fixes stuff and does IP + int solutionFix(double &objectiveValue, + double *newSolution, + const int *keep); + + /// Sets type of search + inline void setSearchType(int value) + { + swap_ = value; + } + /// Used array so we can set + inline int *used() const + { + return used_; + } + +protected: + // Data + + // Original matrix by column + CoinPackedMatrix matrix_; + + // Number of solutions so we only do after new solution + int numberSolutions_; + // Type of search 0=normal, 1=BAB + int swap_; + /// Whether a variable has been in a solution (also when) + int *used_; +}; + +/** Proximity Search class + */ +class CbcHeuristicFPump; +class CbcHeuristicProximity : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicProximity(); + + /* Constructor with model - assumed before cuts + */ + CbcHeuristicProximity(CbcModel &model); + + // Copy constructor + CbcHeuristicProximity(const CbcHeuristicProximity &); + + // Destructor + ~CbcHeuristicProximity(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicProximity &operator=(const CbcHeuristicProximity &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Set extra increment + inline void setIncrement(double value) + { + increment_ = value; + } + /// Used array so we can set + inline int *used() const + { + return used_; + } + +protected: + // Data + /// Increment to use if no change + double increment_; + /// Copy of Feasibility pump + CbcHeuristicFPump *feasibilityPump_; + /// Number of solutions so we only do after new solution + int numberSolutions_; + /// Whether a variable has been in a solution (also when) + int *used_; +}; + +/** Naive class + a) Fix all ints as close to zero as possible + b) Fix all ints with nonzero costs and < large to zero + c) Put bounds round continuous and UIs and maximize + */ + +class CbcHeuristicNaive : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicNaive(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicNaive(CbcModel &model); + + // Copy constructor + CbcHeuristicNaive(const CbcHeuristicNaive &); + + // Destructor + ~CbcHeuristicNaive(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicNaive &operator=(const CbcHeuristicNaive &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + */ + virtual int solution(double &objectiveValue, + double *newSolution); + + /// Sets large cost value + inline void setLargeValue(double value) + { + large_ = value; + } + /// Gets large cost value + inline double largeValue() const + { + return large_; + } + +protected: + /// Data + /// Large value + double large_; +}; + +/** Crossover Search class + */ + +class CbcHeuristicCrossover : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicCrossover(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicCrossover(CbcModel &model); + + // Copy constructor + CbcHeuristicCrossover(const CbcHeuristicCrossover &); + + // Destructor + ~CbcHeuristicCrossover(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicCrossover &operator=(const CbcHeuristicCrossover &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Fix variables if agree in useNumber_ solutions + when_ 0 off, 1 only at new solutions, 2 also every now and then + add 10 to make only if agree at lower bound + */ + virtual int solution(double &objectiveValue, + double *newSolution); + + /// Sets number of solutions to use + inline void setNumberSolutions(int value) + { + if (value > 0 && value <= 10) + useNumber_ = value; + } + +protected: + // Data + /// Attempts + std::vector< double > attempts_; + /// Random numbers to stop same search happening + double random_[10]; + /// Number of solutions so we only do after new solution + int numberSolutions_; + /// Number of solutions to use + int useNumber_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicPivotAndFix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicPivotAndFix.hpp new file mode 100644 index 000000000..9044f6cd1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicPivotAndFix.hpp @@ -0,0 +1,58 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicPivotAndFix_H +#define CbcHeuristicPivotAndFix_H + +#include "CbcHeuristic.hpp" +/** LocalSearch class + */ + +class CbcHeuristicPivotAndFix : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicPivotAndFix(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicPivotAndFix(CbcModel &model); + + // Copy constructor + CbcHeuristicPivotAndFix(const CbcHeuristicPivotAndFix &); + + // Destructor + ~CbcHeuristicPivotAndFix(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicPivotAndFix &operator=(const CbcHeuristicPivotAndFix &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + needs comments + */ + virtual int solution(double &objectiveValue, + double *newSolution); + +protected: +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRENS.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRENS.hpp new file mode 100644 index 000000000..9422f26ca --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRENS.hpp @@ -0,0 +1,79 @@ +// $Id$ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// edwin 12/5/09 carved out of CbcHeuristicRINS + +#ifndef CbcHeuristicRENS_H +#define CbcHeuristicRENS_H + +#include "CbcHeuristic.hpp" + +/** LocalSearch class + */ + +class CbcHeuristicRENS : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicRENS(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicRENS(CbcModel &model); + + // Copy constructor + CbcHeuristicRENS(const CbcHeuristicRENS &); + + // Destructor + ~CbcHeuristicRENS(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicRENS &operator=(const CbcHeuristicRENS &rhs); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This does Relaxation Extension Neighborhood Search + Does not run if when_<2 and a solution exists + */ + virtual int solution(double &objectiveValue, + double *newSolution); + + /// Set type + inline void setRensType(int value) + { + rensType_ = value; + } + +protected: + // Data + /// Number of tries + int numberTries_; + /** Type + 0 - fix at LB + 1 - fix on dj + 2 - fix at UB as well + 3 - fix on 0.01*average dj + add 16 to allow two tries + 32 - if solution exists use to keep more variables + 64 - if priorities keep high priority + 128 - if priorities keep low priority + */ + int rensType_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRINS.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRINS.hpp new file mode 100644 index 000000000..7e7c4f046 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRINS.hpp @@ -0,0 +1,106 @@ +/* $Id$ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicRINS_H +#define CbcHeuristicRINS_H + +#include "CbcHeuristic.hpp" +// for backward compatibility include 3 other headers +#include "CbcHeuristicRENS.hpp" +#include "CbcHeuristicDINS.hpp" +#include "CbcHeuristicVND.hpp" +/** LocalSearch class + */ + +class CbcHeuristicRINS : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicRINS(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicRINS(CbcModel &model); + + // Copy constructor + CbcHeuristicRINS(const CbcHeuristicRINS &); + + // Destructor + ~CbcHeuristicRINS(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicRINS &operator=(const CbcHeuristicRINS &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This does Relaxation Induced Neighborhood Search + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// This version fixes stuff and does IP + int solutionFix(double &objectiveValue, + double *newSolution, + const int *keep); + + /// Sets how often to do it + inline void setHowOften(int value) + { + howOften_ = value; + } + /// Used array so we can set + inline char *used() const + { + return used_; + } + /// Resets lastNode + inline void setLastNode(int value) + { + lastNode_ = value; + } + /// Resets number of solutions + inline void setSolutionCount(int value) + { + numberSolutions_ = value; + } + +protected: + // Data + + /// Number of solutions so we can do something at solution + int numberSolutions_; + /// How often to do (code can change) + int howOften_; + /// Number of successes + int numberSuccesses_; + /// Number of tries + int numberTries_; + /** State of fixing continuous variables - + 0 - not tried + +n - this divisor makes small enough + -n - this divisor still not small enough + */ + int stateOfFixing_; + /// Node when last done + int lastNode_; + /// Whether a variable has been in a solution + char *used_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRandRound.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRandRound.hpp new file mode 100644 index 000000000..c6b85a927 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicRandRound.hpp @@ -0,0 +1,58 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcHeuristicRandRound_H +#define CbcHeuristicRandRound_H + +#include "CbcHeuristic.hpp" +/** LocalSearch class + */ + +class CbcHeuristicRandRound : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicRandRound(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicRandRound(CbcModel &model); + + // Copy constructor + CbcHeuristicRandRound(const CbcHeuristicRandRound &); + + // Destructor + ~CbcHeuristicRandRound(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicRandRound &operator=(const CbcHeuristicRandRound &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + needs comments + */ + virtual int solution(double &objectiveValue, + double *newSolution); + +protected: +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicVND.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicVND.hpp new file mode 100644 index 000000000..85e0a4c55 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcHeuristicVND.hpp @@ -0,0 +1,95 @@ +// $Id$ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// edwin 12/5/09 carved out of CbcHeuristicRINS + +#ifndef CbcHeuristicVND_H +#define CbcHeuristicVND_H + +#include "CbcHeuristic.hpp" + +/** LocalSearch class + */ + +class CbcHeuristicVND : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicVND(); + + /* Constructor with model - assumed before cuts + Initial version does not do Lps + */ + CbcHeuristicVND(CbcModel &model); + + // Copy constructor + CbcHeuristicVND(const CbcHeuristicVND &); + + // Destructor + ~CbcHeuristicVND(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// Assignment operator + CbcHeuristicVND &operator=(const CbcHeuristicVND &rhs); + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + + /// update model (This is needed if cliques update matrix etc) + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + This does Relaxation Induced Neighborhood Search + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// This version fixes stuff and does IP + int solutionFix(double &objectiveValue, + double *newSolution, + const int *keep); + + /// Sets how often to do it + inline void setHowOften(int value) + { + howOften_ = value; + } + /// base solution array so we can set + inline double *baseSolution() const + { + return baseSolution_; + } + +protected: + // Data + + /// Number of solutions so we can do something at solution + int numberSolutions_; + /// How often to do (code can change) + int howOften_; + /// Number of successes + int numberSuccesses_; + /// Number of tries + int numberTries_; + /// Node when last done + int lastNode_; + /// Step size for decomposition + int stepSize_; + int k_; + int kmax_; + int nDifferent_; + /// Base solution + double *baseSolution_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcLinked.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcLinked.hpp new file mode 100644 index 000000000..1d14bb467 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcLinked.hpp @@ -0,0 +1,1443 @@ +/* $Id$ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglLinked_H +#define CglLinked_H +/* THIS CONTAINS STUFF THAT SHOULD BE IN + OsiSolverLink + OsiBranchLink + CglTemporary +*/ +#include "CoinModel.hpp" +#include "OsiClpSolverInterface.hpp" +#include "OsiChooseVariable.hpp" +#include "CbcFathom.hpp" +class CbcModel; +class CoinPackedMatrix; +class OsiLinkedBound; +class OsiObject; +class CglStored; +class CglTemporary; +/** + +This is to allow the user to replace initialSolve and resolve +This version changes coefficients +*/ + +class OsiSolverLink : public CbcOsiSolver { + +public: + //--------------------------------------------------------------------------- + /**@name Solve methods */ + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + + /// Resolve an LP relaxation after problem modification + virtual void resolve(); + + /** + Problem specific + Returns -1 if node fathomed and no solution + 0 if did nothing + 1 if node fathomed and solution + allFixed is true if all LinkedBound variables are fixed + */ + virtual int fathom(bool allFixed); + /** Solves nonlinear problem from CoinModel using SLP - may be used as crash + for other algorithms when number of iterations small. + Also exits if all problematical variables are changing + less than deltaTolerance + Returns solution array + */ + double *nonlinearSLP(int numberPasses, double deltaTolerance); + /** Solve linearized quadratic objective branch and bound. + Return cutoff and OA cut + */ + double linearizedBAB(CglStored *cut); + /** Solves nonlinear problem from CoinModel using SLP - and then tries to get + heuristic solution + Returns solution array + mode - + 0 just get continuous + 1 round and try normal bab + 2 use defaultBound_ to bound integer variables near current solution + */ + double *heuristicSolution(int numberPasses, double deltaTolerance, int mode); + + /// Do OA cuts + int doAOCuts(CglTemporary *cutGen, const double *solution, const double *solution2); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiSolverLink(); + + /** This creates from a coinModel object + + if errors.then number of sets is -1 + + This creates linked ordered sets information. It assumes - + + for product terms syntax is yy*f(zz) + also just f(zz) is allowed + and even a constant + + modelObject not const as may be changed as part of process. + */ + OsiSolverLink(CoinModel &modelObject); + // Other way with existing object + void load(CoinModel &modelObject, bool tightenBounds = false, int logLevel = 1); + /// Clone + virtual OsiSolverInterface *clone(bool copyData = true) const; + + /// Copy constructor + OsiSolverLink(const OsiSolverLink &); + + /// Assignment operator + OsiSolverLink &operator=(const OsiSolverLink &rhs); + + /// Destructor + virtual ~OsiSolverLink(); + + //@} + + /**@name Sets and Gets */ + //@{ + /// Add a bound modifier + void addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, int whichVariableAffected, + double multiplier = 1.0); + /// Update coefficients - returns number updated if in updating mode + int updateCoefficients(ClpSimplex *solver, CoinPackedMatrix *matrix); + /// Analyze constraints to see which are convex (quadratic) + void analyzeObjects(); + /// Add reformulated bilinear constraints + void addTighterConstraints(); + /// Objective value of best solution found internally + inline double bestObjectiveValue() const + { + return bestObjectiveValue_; + } + /// Set objective value of best solution found internally + inline void setBestObjectiveValue(double value) + { + bestObjectiveValue_ = value; + } + /// Best solution found internally + inline const double *bestSolution() const + { + return bestSolution_; + } + /// Set best solution found internally + void setBestSolution(const double *solution, int numberColumns); + /// Set special options + inline void setSpecialOptions2(int value) + { + specialOptions2_ = value; + } + /// Say convex (should work it out) - if convex false then strictly concave + void sayConvex(bool convex); + /// Get special options + inline int specialOptions2() const + { + return specialOptions2_; + } + /** Clean copy of matrix + So we can add rows + */ + CoinPackedMatrix *cleanMatrix() const + { + return matrix_; + } + /** Row copy of matrix + Just genuine columns and rows + Linear part + */ + CoinPackedMatrix *originalRowCopy() const + { + return originalRowCopy_; + } + /// Copy of quadratic model if one + ClpSimplex *quadraticModel() const + { + return quadraticModel_; + } + /// Gets correct form for a quadratic row - user to delete + CoinPackedMatrix *quadraticRow(int rowNumber, double *linear) const; + /// Default meshSize + inline double defaultMeshSize() const + { + return defaultMeshSize_; + } + inline void setDefaultMeshSize(double value) + { + defaultMeshSize_ = value; + } + /// Default maximumbound + inline double defaultBound() const + { + return defaultBound_; + } + inline void setDefaultBound(double value) + { + defaultBound_ = value; + } + /// Set integer priority + inline void setIntegerPriority(int value) + { + integerPriority_ = value; + } + /// Get integer priority + inline int integerPriority() const + { + return integerPriority_; + } + /// Objective transfer variable if one + inline int objectiveVariable() const + { + return objectiveVariable_; + } + /// Set biLinear priority + inline void setBiLinearPriority(int value) + { + biLinearPriority_ = value; + } + /// Get biLinear priority + inline int biLinearPriority() const + { + return biLinearPriority_; + } + /// Return CoinModel + inline const CoinModel *coinModel() const + { + return &coinModel_; + } + /// Set all biLinear priorities on x-x variables + void setBiLinearPriorities(int value, double meshSize = 1.0); + /** Set options and priority on all or some biLinear variables + 1 - on I-I + 2 - on I-x + 4 - on x-x + or combinations. + -1 means leave (for priority value and strategy value) + */ + void setBranchingStrategyOnVariables(int strategyValue, int priorityValue = -1, + int mode = 7); + /// Set all mesh sizes on x-x variables + void setMeshSizes(double value); + /** Two tier integer problem where when set of variables with priority + less than this are fixed the problem becomes an easier integer problem + */ + void setFixedPriority(int priorityValue); + //@} + + //--------------------------------------------------------------------------- + +protected: + /**@name functions */ + //@{ + /// Do real work of initialize + //void initialize(ClpSimplex * & solver, OsiObject ** & object) const; + /// Do real work of delete + void gutsOfDestructor(bool justNullify = false); + /// Do real work of copy + void gutsOfCopy(const OsiSolverLink &rhs); + //@} + + /**@name Private member data */ + //@{ + /** Clean copy of matrix + Marked coefficients will be multiplied by L or U + */ + CoinPackedMatrix *matrix_; + /** Row copy of matrix + Just genuine columns and rows + */ + CoinPackedMatrix *originalRowCopy_; + /// Copy of quadratic model if one + ClpSimplex *quadraticModel_; + /// Number of rows with nonLinearities + int numberNonLinearRows_; + /// Starts of lists + int *startNonLinear_; + /// Row number for a list + int *rowNonLinear_; + /** Indicator whether is convex, concave or neither + -1 concave, 0 neither, +1 convex + */ + int *convex_; + /// Indices in a list/row + int *whichNonLinear_; + /// Model in CoinModel format + CoinModel coinModel_; + /// Number of variables in tightening phase + int numberVariables_; + /// Information + OsiLinkedBound *info_; + /** + 0 bit (1) - call fathom (may do mini B&B) + 1 bit (2) - quadratic only in objective (add OA cuts) + 2 bit (4) - convex + 3 bit (8) - try adding OA cuts + 4 bit (16) - add linearized constraints + */ + int specialOptions2_; + /// Objective transfer row if one + int objectiveRow_; + /// Objective transfer variable if one + int objectiveVariable_; + /// Objective value of best solution found internally + double bestObjectiveValue_; + /// Default mesh + double defaultMeshSize_; + /// Default maximum bound + double defaultBound_; + /// Best solution found internally + double *bestSolution_; + /// Priority for integers + int integerPriority_; + /// Priority for bilinear + int biLinearPriority_; + /// Number of variables which when fixed help + int numberFix_; + /// list of fixed variables + int *fixVariables_; + //@} +}; +/** + List of bounds which depend on other bounds +*/ + +class OsiLinkedBound { + +public: + //--------------------------------------------------------------------------- + /**@name Action methods */ + //@{ + /// Update other bounds + void updateBounds(ClpSimplex *solver); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiLinkedBound(); + /// Useful Constructor + OsiLinkedBound(OsiSolverInterface *model, int variable, + int numberAffected, const int *positionL, + const int *positionU, const double *multiplier); + + /// Copy constructor + OsiLinkedBound(const OsiLinkedBound &); + + /// Assignment operator + OsiLinkedBound &operator=(const OsiLinkedBound &rhs); + + /// Destructor + ~OsiLinkedBound(); + + //@} + + /**@name Sets and Gets */ + //@{ + /// Get variable + inline int variable() const + { + return variable_; + } + /// Add a bound modifier + void addBoundModifier(bool upperBoundAffected, bool useUpperBound, int whichVariable, + double multiplier = 1.0); + //@} + +protected: + typedef struct { + double multiplier; // to use in computation + int affected; // variable or element affected + /* + 0 - LB of variable affected + 1 - UB of variable affected + 2 - element in position (affected) affected + */ + unsigned char affect; + unsigned char ubUsed; // nonzero if UB of this variable is used + /* + 0 - use x*multiplier + 1 - use multiplier/x + 2 - if UB use min of current upper and x*multiplier, if LB use max of current lower and x*multiplier + */ + unsigned char type; // type of computation + } boundElementAction; + + /**@name Private member data */ + //@{ + /// Pointer back to model + OsiSolverInterface *model_; + /// Variable + int variable_; + /// Number of variables/elements affected + int numberAffected_; + /// Maximum number of variables/elements affected + int maximumAffected_; + /// Actions + boundElementAction *affected_; + //@} +}; +#include "CbcHeuristic.hpp" +/** heuristic - just picks up any good solution + */ + +class CbcHeuristicDynamic3 : public CbcHeuristic { +public: + // Default Constructor + CbcHeuristicDynamic3(); + + /* Constructor with model + */ + CbcHeuristicDynamic3(CbcModel &model); + + // Copy constructor + CbcHeuristicDynamic3(const CbcHeuristicDynamic3 &); + + // Destructor + ~CbcHeuristicDynamic3(); + + /// Clone + virtual CbcHeuristic *clone() const; + + /// update model + virtual void setModel(CbcModel *model); + + using CbcHeuristic::solution; + /** returns 0 if no solution, 1 if valid solution. + Sets solution values if good, sets objective value (only if good) + We leave all variables which are at one at this node of the + tree to that value and will + initially set all others to zero. We then sort all variables in order of their cost + divided by the number of entries in rows which are not yet covered. We randomize that + value a bit so that ties will be broken in different ways on different runs of the heuristic. + We then choose the best one and set it to one and repeat the exercise. + + */ + virtual int solution(double &objectiveValue, + double *newSolution); + /// Resets stuff if model changes + virtual void resetModel(CbcModel *model); + /// Returns true if can deal with "odd" problems e.g. sos type 2 + virtual bool canDealWithOdd() const + { + return true; + } + +private: + /// Illegal Assignment operator + CbcHeuristicDynamic3 &operator=(const CbcHeuristicDynamic3 &rhs); +}; + +#include "OsiBranchingObject.hpp" + +/** Define Special Linked Ordered Sets. + +*/ +class CoinWarmStartBasis; + +class OsiOldLink : public OsiSOS { + +public: + // Default Constructor + OsiOldLink(); + + /** Useful constructor - A valid solution is if all variables are zero + apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through + numberInSet-1. The length of weights array is numberInSet. + For this constructor the variables in matrix are the numberInSet*numberLink + starting at first. If weights null then 0,1,2.. + */ + OsiOldLink(const OsiSolverInterface *solver, int numberMembers, + int numberLinks, int first, + const double *weights, int setNumber); + /** Useful constructor - A valid solution is if all variables are zero + apart from k*numberLink to (k+1)*numberLink-1 where k is 0 through + numberInSet-1. The length of weights array is numberInSet. + For this constructor the variables are given by list - grouped. + If weights null then 0,1,2.. + */ + OsiOldLink(const OsiSolverInterface *solver, int numberMembers, + int numberLinks, int typeSOS, const int *which, + const double *weights, int setNumber); + + // Copy constructor + OsiOldLink(const OsiOldLink &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiOldLink &operator=(const OsiOldLink &rhs); + + // Destructor + virtual ~OsiOldLink(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + /// Redoes data when sequence numbers change + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + /// Number of links for each member + inline int numberLinks() const + { + return numberLinks_; + } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return false; + } + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const + { + return false; + } + +protected: + /// data + + /// Number of links + int numberLinks_; +}; +/** Branching object for Linked ordered sets + + */ +class OsiOldLinkBranchingObject : public OsiSOSBranchingObject { + +public: + // Default Constructor + OsiOldLinkBranchingObject(); + + // Useful constructor + OsiOldLinkBranchingObject(OsiSolverInterface *solver, const OsiOldLink *originalObject, + int way, + double separator); + + // Copy constructor + OsiOldLinkBranchingObject(const OsiOldLinkBranchingObject &); + + // Assignment operator + OsiOldLinkBranchingObject &operator=(const OsiOldLinkBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + // Destructor + virtual ~OsiOldLinkBranchingObject(); + + using OsiBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + +private: + /// data +}; +/** Define data for one link + +*/ + +class OsiOneLink { + +public: + // Default Constructor + OsiOneLink(); + + /** Useful constructor - + + */ + OsiOneLink(const OsiSolverInterface *solver, int xRow, int xColumn, int xyRow, + const char *functionString); + + // Copy constructor + OsiOneLink(const OsiOneLink &); + + // Assignment operator + OsiOneLink &operator=(const OsiOneLink &rhs); + + // Destructor + virtual ~OsiOneLink(); + + /// data + + /// Row which defines x (if -1 then no x) + int xRow_; + /// Column which defines x + int xColumn_; + /// Output row + int xyRow; + /// Function + std::string function_; +}; +/** Define Special Linked Ordered Sets. New style + + members and weights may be stored in SOS object + + This is for y and x*f(y) and z*g(y) etc + +*/ + +class OsiLink : public OsiSOS { + +public: + // Default Constructor + OsiLink(); + + /** Useful constructor - + + */ + OsiLink(const OsiSolverInterface *solver, int yRow, + int yColumn, double meshSize); + + // Copy constructor + OsiLink(const OsiLink &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiLink &operator=(const OsiLink &rhs); + + // Destructor + virtual ~OsiLink(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + /// Redoes data when sequence numbers change + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + /// Number of links for each member + inline int numberLinks() const + { + return numberLinks_; + } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return false; + } + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const + { + return false; + } + +protected: + /// data + /// Current increment for y points + double meshSize_; + /// Links + OsiOneLink *data_; + /// Number of links + int numberLinks_; + /// Row which defines y + int yRow_; + /// Column which defines y + int yColumn_; +}; +/** Branching object for Linked ordered sets + + */ +class OsiLinkBranchingObject : public OsiTwoWayBranchingObject { + +public: + // Default Constructor + OsiLinkBranchingObject(); + + // Useful constructor + OsiLinkBranchingObject(OsiSolverInterface *solver, const OsiLink *originalObject, + int way, + double separator); + + // Copy constructor + OsiLinkBranchingObject(const OsiLinkBranchingObject &); + + // Assignment operator + OsiLinkBranchingObject &operator=(const OsiLinkBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + // Destructor + virtual ~OsiLinkBranchingObject(); + + using OsiBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + +private: + /// data +}; +/** Define BiLinear objects + + This models x*y where one or both are integer + +*/ + +class OsiBiLinear : public OsiObject2 { + +public: + // Default Constructor + OsiBiLinear(); + + /** Useful constructor - + This Adds in rows and variables to construct valid Linked Ordered Set + Adds extra constraints to match other x/y + So note not const solver + */ + OsiBiLinear(OsiSolverInterface *solver, int xColumn, + int yColumn, int xyRow, double coefficient, + double xMesh, double yMesh, + int numberExistingObjects = 0, const OsiObject **objects = NULL); + + /** Useful constructor - + This Adds in rows and variables to construct valid Linked Ordered Set + Adds extra constraints to match other x/y + So note not const model + */ + OsiBiLinear(CoinModel *coinModel, int xColumn, + int yColumn, int xyRow, double coefficient, + double xMesh, double yMesh, + int numberExistingObjects = 0, const OsiObject **objects = NULL); + + // Copy constructor + OsiBiLinear(const OsiBiLinear &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiBiLinear &operator=(const OsiBiLinear &rhs); + + // Destructor + virtual ~OsiBiLinear(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + /// Redoes data when sequence numbers change + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + // This does NOT set mutable stuff + virtual double checkInfeasibility(const OsiBranchingInformation *info) const; + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return false; + } + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const + { + return (branchingStrategy_ & 4) != 0; + } + /// X column + inline int xColumn() const + { + return xColumn_; + } + /// Y column + inline int yColumn() const + { + return yColumn_; + } + /// X row + inline int xRow() const + { + return xRow_; + } + /// Y row + inline int yRow() const + { + return yRow_; + } + /// XY row + inline int xyRow() const + { + return xyRow_; + } + /// Coefficient + inline double coefficient() const + { + return coefficient_; + } + /// Set coefficient + inline void setCoefficient(double value) + { + coefficient_ = value; + } + /// First lambda (of 4) + inline int firstLambda() const + { + return firstLambda_; + } + /// X satisfied if less than this away from mesh + inline double xSatisfied() const + { + return xSatisfied_; + } + inline void setXSatisfied(double value) + { + xSatisfied_ = value; + } + /// Y satisfied if less than this away from mesh + inline double ySatisfied() const + { + return ySatisfied_; + } + inline void setYSatisfied(double value) + { + ySatisfied_ = value; + } + /// X other satisfied if less than this away from mesh + inline double xOtherSatisfied() const + { + return xOtherSatisfied_; + } + inline void setXOtherSatisfied(double value) + { + xOtherSatisfied_ = value; + } + /// Y other satisfied if less than this away from mesh + inline double yOtherSatisfied() const + { + return yOtherSatisfied_; + } + inline void setYOtherSatisfied(double value) + { + yOtherSatisfied_ = value; + } + /// X meshSize + inline double xMeshSize() const + { + return xMeshSize_; + } + inline void setXMeshSize(double value) + { + xMeshSize_ = value; + } + /// Y meshSize + inline double yMeshSize() const + { + return yMeshSize_; + } + inline void setYMeshSize(double value) + { + yMeshSize_ = value; + } + /// XY satisfied if two version differ by less than this + inline double xySatisfied() const + { + return xySatisfied_; + } + inline void setXYSatisfied(double value) + { + xySatisfied_ = value; + } + /// Set sizes and other stuff + void setMeshSizes(const OsiSolverInterface *solver, double x, double y); + /** branching strategy etc + bottom 2 bits + 0 branch on either, 1 branch on x, 2 branch on y + next bit + 4 set to say don't update coefficients + next bit + 8 set to say don't use in feasible region + next bit + 16 set to say - Always satisfied !! + */ + inline int branchingStrategy() const + { + return branchingStrategy_; + } + inline void setBranchingStrategy(int value) + { + branchingStrategy_ = value; + } + /** Simple quadratic bound marker. + 0 no + 1 L if coefficient pos, G if negative i.e. value is ub on xy + 2 G if coefficient pos, L if negative i.e. value is lb on xy + 3 E + If bound then real coefficient is 1.0 and coefficient_ is bound + */ + inline int boundType() const + { + return boundType_; + } + inline void setBoundType(int value) + { + boundType_ = value; + } + /// Does work of branching + void newBounds(OsiSolverInterface *solver, int way, short xOrY, double separator) const; + /// Updates coefficients - returns number updated + int updateCoefficients(const double *lower, const double *upper, double *objective, + CoinPackedMatrix *matrix, CoinWarmStartBasis *basis) const; + /// Returns true value of single xyRow coefficient + double xyCoefficient(const double *solution) const; + /// Get LU coefficients from matrix + void getCoefficients(const OsiSolverInterface *solver, double xB[2], double yB[2], double xybar[4]) const; + /// Compute lambdas (third entry in each .B is current value) (nonzero if bad) + double computeLambdas(const double xB[3], const double yB[3], const double xybar[4], double lambda[4]) const; + /// Adds in data for extra row with variable coefficients + void addExtraRow(int row, double multiplier); + /// Sets infeasibility and other when pseudo shadow prices + void getPseudoShadow(const OsiBranchingInformation *info); + /// Gets sum of movements to correct value + double getMovement(const OsiBranchingInformation *info); + +protected: + /// Compute lambdas if coefficients not changing + void computeLambdas(const OsiSolverInterface *solver, double lambda[4]) const; + /// data + + /// Coefficient + double coefficient_; + /// x mesh + double xMeshSize_; + /// y mesh + double yMeshSize_; + /// x satisfied if less than this away from mesh + double xSatisfied_; + /// y satisfied if less than this away from mesh + double ySatisfied_; + /// X other satisfied if less than this away from mesh + double xOtherSatisfied_; + /// Y other satisfied if less than this away from mesh + double yOtherSatisfied_; + /// xy satisfied if less than this away from true + double xySatisfied_; + /// value of x or y to branch about + mutable double xyBranchValue_; + /// x column + int xColumn_; + /// y column + int yColumn_; + /// First lambda (of 4) + int firstLambda_; + /** branching strategy etc + bottom 2 bits + 0 branch on either, 1 branch on x, 2 branch on y + next bit + 4 set to say don't update coefficients + next bit + 8 set to say don't use in feasible region + next bit + 16 set to say - Always satisfied !! + */ + int branchingStrategy_; + /** Simple quadratic bound marker. + 0 no + 1 L if coefficient pos, G if negative i.e. value is ub on xy + 2 G if coefficient pos, L if negative i.e. value is lb on xy + 3 E + If bound then real coefficient is 1.0 and coefficient_ is bound + */ + int boundType_; + /// x row + int xRow_; + /// y row (-1 if x*x) + int yRow_; + /// Output row + int xyRow_; + /// Convexity row + int convexity_; + /// Number of extra rows (coefficients to be modified) + int numberExtraRows_; + /// Multiplier for coefficient on row + double *multiplier_; + /// Row number + int *extraRow_; + /// Which chosen -1 none, 0 x, 1 y + mutable short chosen_; +}; +/** Branching object for BiLinear objects + + */ +class OsiBiLinearBranchingObject : public OsiTwoWayBranchingObject { + +public: + // Default Constructor + OsiBiLinearBranchingObject(); + + // Useful constructor + OsiBiLinearBranchingObject(OsiSolverInterface *solver, const OsiBiLinear *originalObject, + int way, + double separator, int chosen); + + // Copy constructor + OsiBiLinearBranchingObject(const OsiBiLinearBranchingObject &); + + // Assignment operator + OsiBiLinearBranchingObject &operator=(const OsiBiLinearBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + // Destructor + virtual ~OsiBiLinearBranchingObject(); + + using OsiBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const; + +protected: + /// data + /// 1 means branch on x, 2 branch on y + short chosen_; +}; +/** Define Continuous BiLinear objects for an == bound + + This models x*y = b where both are continuous + +*/ + +class OsiBiLinearEquality : public OsiBiLinear { + +public: + // Default Constructor + OsiBiLinearEquality(); + + /** Useful constructor - + This Adds in rows and variables to construct Ordered Set + for x*y = b + So note not const solver + */ + OsiBiLinearEquality(OsiSolverInterface *solver, int xColumn, + int yColumn, int xyRow, double rhs, + double xMesh); + + // Copy constructor + OsiBiLinearEquality(const OsiBiLinearEquality &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiBiLinearEquality &operator=(const OsiBiLinearEquality &rhs); + + // Destructor + virtual ~OsiBiLinearEquality(); + + /// Possible improvement + virtual double improvement(const OsiSolverInterface *solver) const; + /** change grid + if type 0 then use solution and make finer + if 1 then back to original + returns mesh size + */ + double newGrid(OsiSolverInterface *solver, int type) const; + /// Number of points + inline int numberPoints() const + { + return numberPoints_; + } + inline void setNumberPoints(int value) + { + numberPoints_ = value; + } + +protected: + /// Number of points + int numberPoints_; +}; +/// Define a single integer class - but one where you keep branching until fixed even if satisfied + +class OsiSimpleFixedInteger : public OsiSimpleInteger { + +public: + /// Default Constructor + OsiSimpleFixedInteger(); + + /// Useful constructor - passed solver index + OsiSimpleFixedInteger(const OsiSolverInterface *solver, int iColumn); + + /// Useful constructor - passed solver index and original bounds + OsiSimpleFixedInteger(int iColumn, double lower, double upper); + + /// Useful constructor - passed simple integer + OsiSimpleFixedInteger(const OsiSimpleInteger &); + + /// Copy constructor + OsiSimpleFixedInteger(const OsiSimpleFixedInteger &); + + /// Clone + virtual OsiObject *clone() const; + + /// Assignment operator + OsiSimpleFixedInteger &operator=(const OsiSimpleFixedInteger &rhs); + + /// Destructor + virtual ~OsiSimpleFixedInteger(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + +protected: + /// data +}; +/** Define a single variable class which is involved with OsiBiLinear objects. + This is used so can make better decision on where to branch as it can look at + all objects. + + This version sees if it can re-use code from OsiSimpleInteger + even if not an integer variable. If not then need to duplicate code. +*/ + +class OsiUsesBiLinear : public OsiSimpleInteger { + +public: + /// Default Constructor + OsiUsesBiLinear(); + + /// Useful constructor - passed solver index + OsiUsesBiLinear(const OsiSolverInterface *solver, int iColumn, int type); + + /// Useful constructor - passed solver index and original bounds + OsiUsesBiLinear(int iColumn, double lower, double upper, int type); + + /// Useful constructor - passed simple integer + OsiUsesBiLinear(const OsiSimpleInteger &rhs, int type); + + /// Copy constructor + OsiUsesBiLinear(const OsiUsesBiLinear &rhs); + + /// Clone + virtual OsiObject *clone() const; + + /// Assignment operator + OsiUsesBiLinear &operator=(const OsiUsesBiLinear &rhs); + + /// Destructor + virtual ~OsiUsesBiLinear(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current value. + + Given an current value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /// Add all bi-linear objects + void addBiLinearObjects(OsiSolverLink *solver); + +protected: + /// data + /// Number of bilinear objects (maybe could be more general) + int numberBiLinear_; + /// Type of variable - 0 continuous, 1 integer + int type_; + /// Objects + OsiObject **objects_; +}; +/** This class chooses a variable to branch on + + This is just as OsiChooseStrong but it fakes it so only + first so many are looked at in this phase + +*/ + +class OsiChooseStrongSubset : public OsiChooseStrong { + +public: + /// Default Constructor + OsiChooseStrongSubset(); + + /// Constructor from solver (so we can set up arrays etc) + OsiChooseStrongSubset(const OsiSolverInterface *solver); + + /// Copy constructor + OsiChooseStrongSubset(const OsiChooseStrongSubset &); + + /// Assignment operator + OsiChooseStrongSubset &operator=(const OsiChooseStrongSubset &rhs); + + /// Clone + virtual OsiChooseVariable *clone() const; + + /// Destructor + virtual ~OsiChooseStrongSubset(); + + /** Sets up strong list and clears all if initialize is true. + Returns number of infeasibilities. + If returns -1 then has worked out node is infeasible! + */ + virtual int setupList(OsiBranchingInformation *info, bool initialize); + /** Choose a variable + Returns - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + If fixVariables is true then 2,3,4 are all really same as problem changed + */ + virtual int chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables); + + /// Number of objects to use + inline int numberObjectsToUse() const + { + return numberObjectsToUse_; + } + /// Set number of objects to use + inline void setNumberObjectsToUse(int value) + { + numberObjectsToUse_ = value; + } + +protected: + // Data + /// Number of objects to be used (and set in solver) + int numberObjectsToUse_; +}; + +#include + +#include "CglStored.hpp" + +class CoinWarmStartBasis; +/** Stored Temporary Cut Generator Class - destroyed after first use */ +class CglTemporary : public CglStored { + +public: + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Stored cuts for the model of the + solver interface, si. + + Insert the generated cuts into OsiCut, cs. + + This generator just looks at previously stored cuts + and inserts any that are violated by enough + */ + virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglTemporary(); + + /// Copy constructor + CglTemporary(const CglTemporary &rhs); + + /// Clone + virtual CglCutGenerator *clone() const; + + /// Assignment operator + CglTemporary & + operator=(const CglTemporary &rhs); + + /// Destructor + virtual ~CglTemporary(); + //@} + +private: + // Private member methods + + // Private member data +}; +//############################################################################# + +/** + +This is to allow the user to replace initialSolve and resolve +*/ + +class OsiSolverLinearizedQuadratic : public OsiClpSolverInterface { + +public: + //--------------------------------------------------------------------------- + /**@name Solve methods */ + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiSolverLinearizedQuadratic(); + /// Useful constructor (solution should be good) + OsiSolverLinearizedQuadratic(ClpSimplex *quadraticModel); + /// Clone + virtual OsiSolverInterface *clone(bool copyData = true) const; + + /// Copy constructor + OsiSolverLinearizedQuadratic(const OsiSolverLinearizedQuadratic &); + + /// Assignment operator + OsiSolverLinearizedQuadratic &operator=(const OsiSolverLinearizedQuadratic &rhs); + + /// Destructor + virtual ~OsiSolverLinearizedQuadratic(); + + //@} + + /**@name Sets and Gets */ + //@{ + /// Objective value of best solution found internally + inline double bestObjectiveValue() const + { + return bestObjectiveValue_; + } + /// Best solution found internally + const double *bestSolution() const + { + return bestSolution_; + } + /// Set special options + inline void setSpecialOptions3(int value) + { + specialOptions3_ = value; + } + /// Get special options + inline int specialOptions3() const + { + return specialOptions3_; + } + /// Copy of quadratic model if one + ClpSimplex *quadraticModel() const + { + return quadraticModel_; + } + //@} + + //--------------------------------------------------------------------------- + +protected: + /**@name functions */ + //@{ + + /**@name Private member data */ + //@{ + /// Objective value of best solution found internally + double bestObjectiveValue_; + /// Copy of quadratic model if one + ClpSimplex *quadraticModel_; + /// Best solution found internally + double *bestSolution_; + /** + 0 bit (1) - don't do mini B&B + 1 bit (2) - quadratic only in objective + */ + int specialOptions3_; + //@} +}; +class ClpSimplex; +/** Return an approximate solution to a CoinModel. + Lots of bounds may be odd to force a solution. + mode = 0 just tries to get a continuous solution +*/ +ClpSimplex *approximateSolution(CoinModel &coinModel, + int numberPasses, double deltaTolerance, + int mode = 0); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMessage.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMessage.hpp new file mode 100644 index 000000000..86d278507 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMessage.hpp @@ -0,0 +1,94 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcMessage_H +#define CbcMessage_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +/** This deals with Cbc messages (as against Clp messages etc). + CoinMessageHandler.hpp is the general part of message handling. + All it has are enum's for the various messages. + CbcMessage.cpp has text in various languages. + + It is trivial to use the .hpp and .cpp file as a basis for + messages for other components. + */ + +#include "CoinMessageHandler.hpp" +enum CBC_Message { + CBC_END_GOOD, + CBC_MAXNODES, + CBC_MAXTIME, + CBC_MAXSOLS, + CBC_EVENT, + CBC_MAXITERS, + CBC_SOLUTION, + CBC_END_SOLUTION, + CBC_SOLUTION2, + CBC_END, + CBC_INFEAS, + CBC_STRONG, + CBC_SOLINDIVIDUAL, + CBC_INTEGERINCREMENT, + CBC_STATUS, + CBC_GAP, + CBC_ROUNDING, + CBC_TREE_SOL, + CBC_ROOT, + CBC_GENERATOR, + CBC_BRANCH, + CBC_STRONGSOL, + CBC_NOINT, + CBC_VUB_PASS, + CBC_VUB_END, + CBC_NOTFEAS1, + CBC_NOTFEAS2, + CBC_NOTFEAS3, + CBC_CUTOFF_WARNING1, + CBC_ITERATE_STRONG, + CBC_PRIORITY, + CBC_WARNING_STRONG, + CBC_START_SUB, + CBC_END_SUB, + CBC_THREAD_STATS, + CBC_CUTS_STATS, + CBC_STRONG_STATS, + CBC_UNBOUNDED, + CBC_OTHER_STATS, + CBC_HEURISTICS_OFF, + CBC_STATUS2, + CBC_FPUMP1, + CBC_FPUMP2, + CBC_STATUS3, + CBC_OTHER_STATS2, + CBC_RELAXED1, + CBC_RELAXED2, + CBC_RESTART, + CBC_GENERAL, + CBC_ROOT_DETAIL, +#ifndef NO_FATHOM_PRINT + CBC_FATHOM_CHANGE, +#endif + CBC_DUMMY_END +}; + +class CbcMessage : public CoinMessages { + +public: + /**@name Constructors etc */ + //@{ + /** Constructor */ + CbcMessage(Language language = us_en); + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMipStartIO.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMipStartIO.hpp new file mode 100644 index 000000000..4aa122b07 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcMipStartIO.hpp @@ -0,0 +1,29 @@ +#ifndef MIPSTARTIO_HPP_INCLUDED +#define MIPSTARTIO_HPP_INCLUDED + +#include +#include +#include +class CbcModel; + +class OsiSolverInterface; + +/* tries to read mipstart (solution file) from + fileName, filling colValues and obj + returns 0 with success, + 1 otherwise */ +int readMIPStart(CbcModel *model, const char *fileName, + std::vector< std::pair< std::string, double > > &colValues, + double &solObj); + +/* from a partial list of variables tries to fill the + remaining variable values */ +int computeCompleteSolution(CbcModel *model, + const std::vector< std::string > colNames, + const std::vector< std::pair< std::string, double > > &colValues, + double *sol, double &obj); + +#endif // MIPSTARTIO_HPP_INCLUDED + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcModel.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcModel.hpp new file mode 100644 index 000000000..96e6ead6d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcModel.hpp @@ -0,0 +1,3296 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcModel_H +#define CbcModel_H +#include +#include +#include "CoinMessageHandler.hpp" +#include "OsiSolverInterface.hpp" +#include "OsiBranchingObject.hpp" +#include "OsiCuts.hpp" +#include "CoinWarmStartBasis.hpp" +#include "CbcCompareBase.hpp" +#include "CbcCountRowCut.hpp" +#include "CbcMessage.hpp" +#include "CbcEventHandler.hpp" +#include "ClpDualRowPivot.hpp" + +class CbcCutGenerator; +class CbcBaseModel; +class OsiRowCut; +class OsiBabSolver; +class OsiRowCutDebugger; +class CglCutGenerator; +class CglStored; +class CbcCutModifier; +class CglTreeProbingInfo; +class CbcHeuristic; +class OsiObject; +class CbcThread; +class CbcTree; +class CbcStrategy; +class CbcSymmetry; +class CbcFeasibilityBase; +class CbcStatistics; +class CbcFullNodeInfo; +class CbcEventHandler; +class CglPreProcess; +class OsiClpSolverInterface; +class ClpNodeStuff; + +// #define CBC_CHECK_BASIS 1 + +//############################################################################# + +/** Simple Branch and bound class + + The initialSolve() method solves the initial LP relaxation of the MIP + problem. The branchAndBound() method can then be called to finish using + a branch and cut algorithm. + +

Search Tree Traversal

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

Row (Constraint) Cut Handling

+ + For a typical subproblem, the sequence of events is as follows: +
    +
  • The subproblem is rebuilt for further evaluation: One result of a + call to addCuts() is a traversal of ancestors, leaving a list of all + cuts used in the ancestors in #addedCuts_. This list is then scanned + to construct a basis that includes only tight cuts. Entries for + loose cuts are set to NULL. +
  • The subproblem is evaluated: One result of a call to solveWithCuts() + is the return of a set of newly generated cuts for the subproblem. + #addedCuts_ is also kept up-to-date as old cuts become loose. +
  • The subproblem is stored for further processing: A call to + CbcNodeInfo::addCuts() adds the newly generated cuts to the + CbcNodeInfo object associated with this node. +
+ See CbcCountRowCut for details of the bookkeeping associated with cut + management. +*/ + +class CbcModel { + +public: + enum CbcIntParam { + /** The maximum number of nodes before terminating */ + CbcMaxNumNode = 0, + /** The maximum number of solutions before terminating */ + CbcMaxNumSol, + /** Fathoming discipline + + Controls objective function comparisons for purposes of fathoming by bound + or determining monotonic variables. + + If 1, action is taken only when the current objective is strictly worse + than the target. Implementation is handled by adding a small tolerance to + the target. + */ + CbcFathomDiscipline, + /** Adjusts printout + 1 does different node message with number unsatisfied on last branch + */ + CbcPrinting, + /** Number of branches (may be more than number of nodes as may + include strong branching) */ + CbcNumberBranches, + /** Just a marker, so that a static sized array can store parameters. */ + CbcLastIntParam + }; + + enum CbcDblParam { + /** The maximum amount the value of an integer variable can vary from + integer and still be considered feasible. */ + CbcIntegerTolerance = 0, + /** The objective is assumed to worsen by this amount for each + integer infeasibility. */ + CbcInfeasibilityWeight, + /** The amount by which to tighten the objective function cutoff when + a new solution is discovered. */ + CbcCutoffIncrement, + /** Stop when the gap between the objective value of the best known solution + and the best bound on the objective of any solution is less than this. + + This is an absolute value. Conversion from a percentage is left to the + client. + */ + CbcAllowableGap, + /** Stop when the gap between the objective value of the best known solution + and the best bound on the objective of any solution is less than this + fraction of of the absolute value of best known solution. + + Code stops if either this test or CbcAllowableGap test succeeds + */ + CbcAllowableFractionGap, + /** \brief The maximum number of seconds before terminating. + A double should be adequate! */ + CbcMaximumSeconds, + /// Cutoff - stored for speed + CbcCurrentCutoff, + /// Optimization direction - stored for speed + CbcOptimizationDirection, + /// Current objective value + CbcCurrentObjectiveValue, + /// Current minimization objective value + CbcCurrentMinimizationObjectiveValue, + /** \brief The time at start of model. + So that other pieces of code can access */ + CbcStartSeconds, + /** Stop doing heuristics when the gap between the objective value of the + best known solution and the best bound on the objective of any solution + is less than this. + + This is an absolute value. Conversion from a percentage is left to the + client. + */ + CbcHeuristicGap, + /** Stop doing heuristics when the gap between the objective value of the + best known solution and the best bound on the objective of any solution + is less than this fraction of of the absolute value of best known + solution. + + Code stops if either this test or CbcAllowableGap test succeeds + */ + CbcHeuristicFractionGap, + /// Smallest non-zero change on a branch + CbcSmallestChange, + /// Sum of non-zero changes on a branch + CbcSumChange, + /// Largest non-zero change on a branch + CbcLargestChange, + /// Small non-zero change on a branch to be used as guess + CbcSmallChange, + /** Just a marker, so that a static sized array can store parameters. */ + CbcLastDblParam + }; + + //--------------------------------------------------------------------------- + +public: + ///@name Solve methods + //@{ + /** \brief Solve the initial LP relaxation + + Invoke the solver's %initialSolve() method. + */ + void initialSolve(); + + /** \brief Invoke the branch \& cut algorithm + + The method assumes that initialSolve() has been called to solve the + LP relaxation. It processes the root node, then proceeds to explore the + branch & cut search tree. The search ends when the tree is exhausted or + one of several execution limits is reached. + If doStatistics is 1 summary statistics are printed + if 2 then also the path to best solution (if found by branching) + if 3 then also one line per node + */ + void branchAndBound(int doStatistics = 0); + +private: + /** \brief Evaluate a subproblem using cutting planes and heuristics + + The method invokes a main loop which generates cuts, applies heuristics, + and reoptimises using the solver's native %resolve() method. + It returns true if the subproblem remains feasible at the end of the + evaluation. + */ + bool solveWithCuts(OsiCuts &cuts, int numberTries, CbcNode *node); + /** Generate one round of cuts - serial mode + returns - + 0 - normal + 1 - must keep going + 2 - set numberTries to zero + -1 - infeasible + */ + int serialCuts(OsiCuts &cuts, CbcNode *node, OsiCuts &slackCuts, int lastNumberCuts); + /** Generate one round of cuts - parallel mode + returns - + 0 - normal + 1 - must keep going + 2 - set numberTries to zero + -1 - infeasible + */ + int parallelCuts(CbcBaseModel *master, OsiCuts &cuts, CbcNode *node, OsiCuts &slackCuts, int lastNumberCuts); + /** Input one node output N nodes to put on tree and optional solution update + This should be able to operate in parallel so is given a solver and is const(ish) + However we will need to keep an array of solver_ and bases and more + status is 0 for normal, 1 if solution + Calling code should always push nodes back on tree + */ + CbcNode **solveOneNode(int whichSolver, CbcNode *node, + int &numberNodesOutput, int &status); + /// Update size of whichGenerator + void resizeWhichGenerator(int numberNow, int numberAfter); + +public: +#ifdef CBC_KEEP_DEPRECATED + // See if anyone is using these any more!! + /** \brief create a clean model from partially fixed problem + + The method creates a new model with given bounds and with no tree. + */ + CbcModel *cleanModel(const double *lower, const double *upper); + /** \brief Invoke the branch \& cut algorithm on partially fixed problem + + The method presolves the given model and does branch and cut. The search + ends when the tree is exhausted or maximum nodes is reached. + + If better solution found then it is saved. + + Returns 0 if search completed and solution, 1 if not completed and solution, + 2 if completed and no solution, 3 if not completed and no solution. + + Normally okay to do cleanModel immediately followed by subBranchandBound + (== other form of subBranchAndBound) + but may need to get at model for advanced features. + + Deletes model2 + */ + int subBranchAndBound(CbcModel *model2, + CbcModel *presolvedModel, + int maximumNodes); + /** \brief Invoke the branch \& cut algorithm on partially fixed problem + + The method creates a new model with given bounds, presolves it + then proceeds to explore the branch & cut search tree. The search + ends when the tree is exhausted or maximum nodes is reached. + + If better solution found then it is saved. + + Returns 0 if search completed and solution, 1 if not completed and solution, + 2 if completed and no solution, 3 if not completed and no solution. + + This is just subModel immediately followed by other version of + subBranchandBound. + + */ + int subBranchAndBound(const double *lower, const double *upper, + int maximumNodes); + + /** \brief Process root node and return a strengthened model + + The method assumes that initialSolve() has been called to solve the + LP relaxation. It processes the root node and then returns a pointer + to the strengthened model (or NULL if infeasible) + */ + OsiSolverInterface *strengthenedModel(); + /** preProcess problem - replacing solver + If makeEquality true then <= cliques converted to ==. + Presolve will be done numberPasses times. + + Returns NULL if infeasible + + If makeEquality is 1 add slacks to get cliques, + if 2 add slacks to get sos (but only if looks plausible) and keep sos info + */ + CglPreProcess *preProcess(int makeEquality = 0, int numberPasses = 5, + int tuning = 5); + /** Does postprocessing - original solver back. + User has to delete process */ + void postProcess(CglPreProcess *process); +#endif + /// Returns CglPreProcess used before branch and bound + inline CglPreProcess *preProcess() const + { + return preProcess_; + } + /// Set CglPreProcess used before branch and bound + inline void setPreProcess(CglPreProcess *preProcess) + { + preProcess_ = preProcess; + } + /// Adds an update information object + void addUpdateInformation(const CbcObjectUpdateData &data); + /** Do one node - broken out for clarity? + also for parallel (when baseModel!=this) + Returns 1 if solution found + node NULL on return if no branches left + newNode NULL if no new node created + */ + int doOneNode(CbcModel *baseModel, CbcNode *&node, CbcNode *&newNode); + +public: + /** \brief Reoptimise an LP relaxation + + Invoke the solver's %resolve() method. + whereFrom - + 0 - initial continuous + 1 - resolve on branch (before new cuts) + 2 - after new cuts + 3 - obsolete code or something modified problem in unexpected way + 10 - after strong branching has fixed variables at root + 11 - after strong branching has fixed variables in tree + + returns 1 feasible, 0 infeasible, -1 feasible but skip cuts + */ + int resolve(CbcNodeInfo *parent, int whereFrom, + double *saveSolution = NULL, + double *saveLower = NULL, + double *saveUpper = NULL); + /// Make given rows (L or G) into global cuts and remove from lp + void makeGlobalCuts(int numberRows, const int *which); + /// Make given cut into a global cut + int makeGlobalCut(const OsiRowCut *cut); + /// Make given cut into a global cut + int makeGlobalCut(const OsiRowCut &cut); + /// Make given column cut into a global cut + void makeGlobalCut(const OsiColCut *cut); + /// Make given column cut into a global cut + void makeGlobalCut(const OsiColCut &cut); + /// Make partial cut into a global cut and save + void makePartialCut(const OsiRowCut *cut, const OsiSolverInterface *solver = NULL); + /// Make partial cuts into global cuts + void makeGlobalCuts(); + /// Which cut generator generated this cut + inline const int *whichGenerator() const + { + return whichGenerator_; + } + //@} + + /** \name Presolve methods */ + //@{ + + /** Identify cliques and construct corresponding objects. + + Find cliques with size in the range + [\p atLeastThisMany, \p lessThanThis] and construct corresponding + CbcClique objects. + If \p makeEquality is true then a new model may be returned if + modifications had to be made, otherwise \c this is returned. + If the problem is infeasible #numberObjects_ is set to -1. + A client must use deleteObjects() before a second call to findCliques(). + If priorities exist, clique priority is set to the default. + */ + CbcModel *findCliques(bool makeEquality, int atLeastThisMany, + int lessThanThis, int defaultValue = 1000); + + /** Do integer presolve, creating a new (presolved) model. + + Returns the new model, or NULL if feasibility is lost. + If weak is true then just does a normal presolve + + \todo It remains to work out the cleanest way of getting a solution to + the original problem at the end. So this is very preliminary. + */ + CbcModel *integerPresolve(bool weak = false); + + /** Do integer presolve, modifying the current model. + + Returns true if the model remains feasible after presolve. + */ + bool integerPresolveThisModel(OsiSolverInterface *originalSolver, bool weak = false); + + /// Put back information into the original model after integer presolve. + void originalModel(CbcModel *presolvedModel, bool weak); + + /** \brief For variables involved in VUB constraints, see if we can tighten + bounds by solving lp's + + Returns false if feasibility is lost. + If CglProbing is available, it will be tried as well to see if it can + tighten bounds. + This routine is just a front end for tightenVubs(int,const int*,double). + + If type = -1 all variables are processed (could be very slow). + If type = 0 only variables involved in VUBs are processed. + If type = n > 0, only the n most expensive VUB variables + are processed, where it is assumed that x is at its maximum so delta + would have to go to 1 (if x not at bound). + + If \p allowMultipleBinary is true, then a VUB constraint is a row with + one continuous variable and any number of binary variables. + + If useCutoff < 1.0e30, the original objective is installed as a + constraint with \p useCutoff as a bound. + */ + bool tightenVubs(int type, bool allowMultipleBinary = false, + double useCutoff = 1.0e50); + + /** \brief For variables involved in VUB constraints, see if we can tighten + bounds by solving lp's + + This version is just handed a list of variables to be processed. + */ + bool tightenVubs(int numberVubs, const int *which, + double useCutoff = 1.0e50); + /** + Analyze problem to find a minimum change in the objective function. + */ + void analyzeObjective(); + /** Returns postProcessed solution in solver(called from event handler) + Normally used for integer solution (not really tested otherwise) + solutionType 1 is best integer so far, 0 is current solution + (may not be integer) */ + const OsiSolverInterface *postProcessedSolver(int solutionType = 1); + + /** + Add additional integers. + */ + void AddIntegers(); + /** + Save copy of the model. + */ + void saveModel(OsiSolverInterface *saveSolver, double *checkCutoffForRestart, bool *feasible); + /** + Flip direction of optimization on all models + */ + void flipModel(); + /** + Clean model i.e. make SOS/integer variables exactly at bound if needed. + Only if moreSpecialOptions2_ 15 bit set (32768) as there is a small + overhead (more2 in standalone cbc). + Fine tuning can be done in configure with -DCLEAN_INTEGER_VARIABLES + and -DZERO_ODD_TOLERANCE=1.0e-nn + If CLEAN_INTEGER_VARIABLES not defined then cleaning is only done for + SOS variables. + If ZERO_ODD_TOLERANCE not defined then 1.0e-14 used. You can define as + 0.0 if you are paranoid. + Returns number of variables forced out + cleanVariables array will be used if exists + */ + int cleanBounds(OsiSolverInterface *solver, char *cleanVariables); + /// Sets up cleanVariables array (i.e. ones to be careful about) + char *setupCleanVariables(); + //@} + + /** \name Object manipulation routines + + See OsiObject for an explanation of `object' in the context of CbcModel. + */ + //@{ + + /// Get the number of objects + inline int numberObjects() const + { + return numberObjects_; + } + /// Set the number of objects + inline void setNumberObjects(int number) + { + numberObjects_ = number; + } + + /// Get the array of objects + inline OsiObject **objects() const + { + return object_; + } + + /// Get the specified object + const inline OsiObject *object(int which) const + { + return object_[which]; + } + /// Get the specified object + inline OsiObject *modifiableObject(int which) const + { + return object_[which]; + } + + void setOptionalInteger(int index); + + /// Delete all object information (and just back to integers if true) + void deleteObjects(bool findIntegers = true); + + /** Add in object information. + + Objects are cloned; the owner can delete the originals. + */ + void addObjects(int numberObjects, OsiObject **objects); + + /** Add in object information. + + Objects are cloned; the owner can delete the originals. + */ + void addObjects(int numberObjects, CbcObject **objects); + + /// Ensure attached objects point to this model. + void synchronizeModel(); + + /** \brief Identify integer variables and create corresponding objects. + + Record integer variables and create an CbcSimpleInteger object for each + one. + If \p startAgain is true, a new scan is forced, overwriting any existing + integer variable information. + If type > 0 then 1==PseudoCost, 2 new ones low priority + */ + + void findIntegers(bool startAgain, int type = 0); + /** Add SOS info to solver - + Overwrites SOS information in solver with information + in CbcModel. Has no effect with some solvers. + Also updates integer info. */ + void addSOSEtcToSolver(); + +#ifdef SWITCH_VARIABLES + /// Convert Dynamic to Switching + int findSwitching(); + /// Fix associated variables + int fixAssociated(OsiSolverInterface *solver, int cleanBasis); + /// Debug associated variables + int checkAssociated(const OsiSolverInterface *solver, + const double *solution, int printLevel); +#endif + //@} + + //--------------------------------------------------------------------------- + + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false if the value of the parameter is out of range. + + The get methods return the value of the parameter. + + */ + //@{ + /// Set an integer parameter + inline bool setIntParam(CbcIntParam key, int value) + { + intParam_[key] = value; + return true; + } + /// Set a double parameter + inline bool setDblParam(CbcDblParam key, double value) + { + dblParam_[key] = value; + return true; + } + /// Get an integer parameter + inline int getIntParam(CbcIntParam key) const + { + return intParam_[key]; + } + /// Get a double parameter + inline double getDblParam(CbcDblParam key) const + { + return dblParam_[key]; + } + /*! \brief Set cutoff bound on the objective function. + + When using strict comparison, the bound is adjusted by a tolerance to + avoid accidentally cutting off the optimal solution. + */ + void setCutoff(double value); + + /// Get the cutoff bound on the objective function - always as minimize + inline double getCutoff() const + { //double value ; + //solver_->getDblParam(OsiDualObjectiveLimit,value) ; + //assert( dblParam_[CbcCurrentCutoff]== value * solver_->getObjSense()); + return dblParam_[CbcCurrentCutoff]; + } + + /// Set the \link CbcModel::CbcMaxNumNode maximum node limit \endlink + inline bool setMaximumNodes(int value) + { + return setIntParam(CbcMaxNumNode, value); + } + + /// Get the \link CbcModel::CbcMaxNumNode maximum node limit \endlink + inline int getMaximumNodes() const + { + return getIntParam(CbcMaxNumNode); + } + + /** Set the + \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink + desired. + */ + inline bool setMaximumSolutions(int value) + { + return setIntParam(CbcMaxNumSol, value); + } + /** Get the + \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink + desired. + */ + inline int getMaximumSolutions() const + { + return getIntParam(CbcMaxNumSol); + } + /// Set the printing mode + inline bool setPrintingMode(int value) + { + return setIntParam(CbcPrinting, value); + } + + /// Get the printing mode + inline int getPrintingMode() const + { + return getIntParam(CbcPrinting); + } + + /** Set the + \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink + desired. + */ + inline bool setMaximumSeconds(double value) + { + return setDblParam(CbcMaximumSeconds, value); + } + /** Get the + \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink + desired. + */ + inline double getMaximumSeconds() const + { + return getDblParam(CbcMaximumSeconds); + } + /// Current time since start of branchAndbound + double getCurrentSeconds() const; + + /// Return true if maximum time reached + bool maximumSecondsReached() const; + + /** Set the + \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink + */ + inline bool setIntegerTolerance(double value) + { + return setDblParam(CbcIntegerTolerance, value); + } + /** Get the + \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink + */ + inline double getIntegerTolerance() const + { + return getDblParam(CbcIntegerTolerance); + } + + /** Set the + \link CbcModel::CbcInfeasibilityWeight + weight per integer infeasibility \endlink + */ + inline bool setInfeasibilityWeight(double value) + { + return setDblParam(CbcInfeasibilityWeight, value); + } + /** Get the + \link CbcModel::CbcInfeasibilityWeight + weight per integer infeasibility \endlink + */ + inline double getInfeasibilityWeight() const + { + return getDblParam(CbcInfeasibilityWeight); + } + + /** Set the \link CbcModel::CbcAllowableGap allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline bool setAllowableGap(double value) + { + return setDblParam(CbcAllowableGap, value); + } + /** Get the \link CbcModel::CbcAllowableGap allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline double getAllowableGap() const + { + return getDblParam(CbcAllowableGap); + } + + /** Set the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline bool setAllowableFractionGap(double value) + { + return setDblParam(CbcAllowableFractionGap, value); + } + /** Get the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline double getAllowableFractionGap() const + { + return getDblParam(CbcAllowableFractionGap); + } + /** Set the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline bool setAllowablePercentageGap(double value) + { + return setDblParam(CbcAllowableFractionGap, value * 0.01); + } + /** Get the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink + between the best known solution and the best possible solution. + */ + inline double getAllowablePercentageGap() const + { + return 100.0 * getDblParam(CbcAllowableFractionGap); + } + /** Set the \link CbcModel::CbcHeuristicGap heuristic gap \endlink + between the best known solution and the best possible solution. + */ + inline bool setHeuristicGap(double value) + { + return setDblParam(CbcHeuristicGap, value); + } + /** Get the \link CbcModel::CbcHeuristicGap heuristic gap \endlink + between the best known solution and the best possible solution. + */ + inline double getHeuristicGap() const + { + return getDblParam(CbcHeuristicGap); + } + + /** Set the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink + between the best known solution and the best possible solution. + */ + inline bool setHeuristicFractionGap(double value) + { + return setDblParam(CbcHeuristicFractionGap, value); + } + /** Get the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink + between the best known solution and the best possible solution. + */ + inline double getHeuristicFractionGap() const + { + return getDblParam(CbcHeuristicFractionGap); + } + /** Set the + \link CbcModel::CbcCutoffIncrement \endlink + desired. + */ + inline bool setCutoffIncrement(double value) + { + return setDblParam(CbcCutoffIncrement, value); + } + /** Get the + \link CbcModel::CbcCutoffIncrement \endlink + desired. + */ + inline double getCutoffIncrement() const + { + return getDblParam(CbcCutoffIncrement); + } + /// See if can stop on gap + bool canStopOnGap() const; + + /** Pass in target solution and optional priorities. + If priorities then >0 means only branch if incorrect + while <0 means branch even if correct. +1 or -1 are + highest priority */ + void setHotstartSolution(const double *solution, const int *priorities = NULL); + + /// Set the minimum drop to continue cuts + inline void setMinimumDrop(double value) + { + minimumDrop_ = value; + } + /// Get the minimum drop to continue cuts + inline double getMinimumDrop() const + { + return minimumDrop_; + } + + /** Set the maximum number of cut passes at root node (default 20) + Minimum drop can also be used for fine tuning */ + inline void setMaximumCutPassesAtRoot(int value) + { + maximumCutPassesAtRoot_ = value; + } + /** Get the maximum number of cut passes at root node */ + inline int getMaximumCutPassesAtRoot() const + { + return maximumCutPassesAtRoot_; + } + + /** Set the maximum number of cut passes at other nodes (default 10) + Minimum drop can also be used for fine tuning */ + inline void setMaximumCutPasses(int value) + { + maximumCutPasses_ = value; + } + /** Get the maximum number of cut passes at other nodes (default 10) */ + inline int getMaximumCutPasses() const + { + return maximumCutPasses_; + } + /** Get current cut pass number in this round of cuts. + (1 is first pass) */ + inline int getCurrentPassNumber() const + { + return currentPassNumber_; + } + /** Set current cut pass number in this round of cuts. + (1 is first pass) */ + inline void setCurrentPassNumber(int value) + { + currentPassNumber_ = value; + } + + /** Set the maximum number of candidates to be evaluated for strong + branching. + + A value of 0 disables strong branching. + */ + void setNumberStrong(int number); + /** Get the maximum number of candidates to be evaluated for strong + branching. + */ + inline int numberStrong() const + { + return numberStrong_; + } + /** Set global preferred way to branch + -1 down, +1 up, 0 no preference */ + inline void setPreferredWay(int value) + { + preferredWay_ = value; + } + /** Get the preferred way to branch (default 0) */ + inline int getPreferredWay() const + { + return preferredWay_; + } + /// Get at which depths to do cuts + inline int whenCuts() const + { + return whenCuts_; + } + /// Set at which depths to do cuts + inline void setWhenCuts(int value) + { + whenCuts_ = value; + } + /** Return true if we want to do cuts + If allowForTopOfTree zero then just does on multiples of depth + if 1 then allows for doing at top of tree + if 2 then says if cuts allowed anywhere apart from root + */ + bool doCutsNow(int allowForTopOfTree) const; + + /** Set the number of branches before pseudo costs believed + in dynamic strong branching. + + A value of 0 disables dynamic strong branching. + */ + void setNumberBeforeTrust(int number); + /** get the number of branches before pseudo costs believed + in dynamic strong branching. */ + inline int numberBeforeTrust() const + { + return numberBeforeTrust_; + } + /** Set the number of variables for which to compute penalties + in dynamic strong branching. + + A value of 0 disables penalties. + */ + void setNumberPenalties(int number); + /** get the number of variables for which to compute penalties + in dynamic strong branching. */ + inline int numberPenalties() const + { + return numberPenalties_; + } + /// Pointer to top of tree + inline const CbcFullNodeInfo *topOfTree() const + { + return topOfTree_; + } + /// Number of analyze iterations to do + inline void setNumberAnalyzeIterations(int number) + { + numberAnalyzeIterations_ = number; + } + inline int numberAnalyzeIterations() const + { + return numberAnalyzeIterations_; + } + /** Get scale factor to make penalties match strong. + Should/will be computed */ + inline double penaltyScaleFactor() const + { + return penaltyScaleFactor_; + } + /** Set scale factor to make penalties match strong. + Should/will be computed */ + void setPenaltyScaleFactor(double value); + /** Problem type as set by user or found by analysis. This will be extended + 0 - not known + 1 - Set partitioning <= + 2 - Set partitioning == + 3 - Set covering + 4 - all +- 1 or all +1 and odd + */ + void inline setProblemType(int number) + { + problemType_ = number; + } + inline int problemType() const + { + return problemType_; + } + /// Current depth + inline int currentDepth() const + { + return currentDepth_; + } + + /// Set how often to scan global cuts + void setHowOftenGlobalScan(int number); + /// Get how often to scan global cuts + inline int howOftenGlobalScan() const + { + return howOftenGlobalScan_; + } + /// Original columns as created by integerPresolve or preprocessing + inline int *originalColumns() const + { + return originalColumns_; + } + /// Set original columns as created by preprocessing + void setOriginalColumns(const int *originalColumns, + int numberGood = COIN_INT_MAX); + /// Create conflict cut (well - most of) + OsiRowCut *conflictCut(const OsiSolverInterface *solver, bool &localCuts); + + /** Set the print frequency. + + Controls the number of nodes evaluated between status prints. + If number <=0 the print frequency is set to 100 nodes for large + problems, 1000 for small problems. + Print frequency has very slight overhead if small. + */ + inline void setPrintFrequency(int number) + { + printFrequency_ = number; + } + /// Get the print frequency + inline int printFrequency() const + { + return printFrequency_; + } + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there a numerical difficulties? + bool isAbandoned() const; + /// Is optimality proven? + bool isProvenOptimal() const; + /// Is infeasiblity proven (or none better than cutoff)? + bool isProvenInfeasible() const; + /// Was continuous solution unbounded + bool isContinuousUnbounded() const; + /// Was continuous solution unbounded + bool isProvenDualInfeasible() const; + /// Node limit reached? + bool isNodeLimitReached() const; + /// Time limit reached? + bool isSecondsLimitReached() const; + /// Solution limit reached? + bool isSolutionLimitReached() const; + /// Get how many iterations it took to solve the problem. + inline int getIterationCount() const + { + return numberIterations_; + } + /// Increment how many iterations it took to solve the problem. + inline void incrementIterationCount(int value) + { + numberIterations_ += value; + } + /// Get how many Nodes it took to solve the problem (including those in complete fathoming B&B inside CLP). + inline int getNodeCount() const + { + return numberNodes_; + } + /// Increment how many nodes it took to solve the problem. + inline void incrementNodeCount(int value) + { + numberNodes_ += value; + } + /// Get how many Nodes were enumerated in complete fathoming B&B inside CLP + inline int getExtraNodeCount() const + { + return numberExtraNodes_; + } + /// Get how many times complete fathoming B&B was done + inline int getFathomCount() const + { + return numberFathoms_; + } + /** Final status of problem + Some of these can be found out by is...... functions + -1 before branchAndBound + 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found + (or check value of best solution) + 1 stopped - on maxnodes, maxsols, maxtime + 2 difficulties so run was abandoned + (5 event user programmed event occurred) + */ + inline int status() const + { + return status_; + } + inline void setProblemStatus(int value) + { + status_ = value; + } + /** Secondary status of problem + -1 unset (status_ will also be -1) + 0 search completed with solution + 1 linear relaxation not feasible (or worse than cutoff) + 2 stopped on gap + 3 stopped on nodes + 4 stopped on time + 5 stopped on user event + 6 stopped on solutions + 7 linear relaxation unbounded + 8 stopped on iteration limit + */ + inline int secondaryStatus() const + { + return secondaryStatus_; + } + inline void setSecondaryStatus(int value) + { + secondaryStatus_ = value; + } + /// Are there numerical difficulties (for initialSolve) ? + bool isInitialSolveAbandoned() const; + /// Is optimality proven (for initialSolve) ? + bool isInitialSolveProvenOptimal() const; + /// Is primal infeasiblity proven (for initialSolve) ? + bool isInitialSolveProvenPrimalInfeasible() const; + /// Is dual infeasiblity proven (for initialSolve) ? + bool isInitialSolveProvenDualInfeasible() const; + + //@} + + //--------------------------------------------------------------------------- + /**@name Problem information methods + + These methods call the solver's query routines to return + information about the problem referred to by the current object. + Querying a problem that has no data associated with it result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. + + Const pointers returned from any data-query method are valid as + long as the data is unchanged and the solver is not called. + */ + //@{ + /// Number of rows in continuous (root) problem. + inline int numberRowsAtContinuous() const + { + return numberRowsAtContinuous_; + } + + /// Get number of columns + inline int getNumCols() const + { + return solver_->getNumCols(); + } + + /// Get number of rows + inline int getNumRows() const + { + return solver_->getNumRows(); + } + + /// Get number of nonzero elements + inline CoinBigIndex getNumElements() const + { + return solver_->getNumElements(); + } + + /// Number of integers in problem + inline int numberIntegers() const + { + return numberIntegers_; + } + // Integer variables + inline const int *integerVariable() const + { + return integerVariable_; + } + /// Whether or not integer + inline char integerType(int i) const + { + assert(integerInfo_); + assert(integerInfo_[i] == 0 || integerInfo_[i] == 1); + return integerInfo_[i]; + } + /// Whether or not integer + inline const char *integerType() const + { + return integerInfo_; + } + + /// Get pointer to array[getNumCols()] of column lower bounds + inline const double *getColLower() const + { + return solver_->getColLower(); + } + + /// Get pointer to array[getNumCols()] of column upper bounds + inline const double *getColUpper() const + { + return solver_->getColUpper(); + } + + /** Get pointer to array[getNumRows()] of row constraint senses. +
    +
  • 'L': <= constraint +
  • 'E': = constraint +
  • 'G': >= constraint +
  • 'R': ranged constraint +
  • 'N': free constraint +
+ */ + inline const char *getRowSense() const + { + return solver_->getRowSense(); + } + + /** Get pointer to array[getNumRows()] of rows right-hand sides +
    +
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] +
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0 +
+ */ + inline const double *getRightHandSide() const + { + return solver_->getRightHandSide(); + } + + /** Get pointer to array[getNumRows()] of row ranges. +
    +
  • if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] +
  • if rowsense()[i] != 'R' then + rowrange()[i] is 0.0 +
+ */ + inline const double *getRowRange() const + { + return solver_->getRowRange(); + } + + /// Get pointer to array[getNumRows()] of row lower bounds + inline const double *getRowLower() const + { + return solver_->getRowLower(); + } + + /// Get pointer to array[getNumRows()] of row upper bounds + inline const double *getRowUpper() const + { + return solver_->getRowUpper(); + } + + /// Get pointer to array[getNumCols()] of objective function coefficients + inline const double *getObjCoefficients() const + { + return solver_->getObjCoefficients(); + } + + /// Get objective function sense (1 for min (default), -1 for max) + inline double getObjSense() const + { + //assert (dblParam_[CbcOptimizationDirection]== solver_->getObjSense()); + return dblParam_[CbcOptimizationDirection]; + } + + /// Return true if variable is continuous + inline bool isContinuous(int colIndex) const + { + return solver_->isContinuous(colIndex); + } + + /// Return true if variable is binary + inline bool isBinary(int colIndex) const + { + return solver_->isBinary(colIndex); + } + + /** Return true if column is integer. + Note: This function returns true if the the column + is binary or a general integer. + */ + inline bool isInteger(int colIndex) const + { + return solver_->isInteger(colIndex); + } + + /// Return true if variable is general integer + inline bool isIntegerNonBinary(int colIndex) const + { + return solver_->isIntegerNonBinary(colIndex); + } + + /// Return true if variable is binary and not fixed at either bound + inline bool isFreeBinary(int colIndex) const + { + return solver_->isFreeBinary(colIndex); + } + + /// Get pointer to row-wise copy of matrix + inline const CoinPackedMatrix *getMatrixByRow() const + { + return solver_->getMatrixByRow(); + } + + /// Get pointer to column-wise copy of matrix + inline const CoinPackedMatrix *getMatrixByCol() const + { + return solver_->getMatrixByCol(); + } + + /// Get solver's value for infinity + inline double getInfinity() const + { + return solver_->getInfinity(); + } + /// Get pointer to array[getNumCols()] (for speed) of column lower bounds + inline const double *getCbcColLower() const + { + return cbcColLower_; + } + /// Get pointer to array[getNumCols()] (for speed) of column upper bounds + inline const double *getCbcColUpper() const + { + return cbcColUpper_; + } + /// Get pointer to array[getNumRows()] (for speed) of row lower bounds + inline const double *getCbcRowLower() const + { + return cbcRowLower_; + } + /// Get pointer to array[getNumRows()] (for speed) of row upper bounds + inline const double *getCbcRowUpper() const + { + return cbcRowUpper_; + } + /// Get pointer to array[getNumCols()] (for speed) of primal solution vector + inline const double *getCbcColSolution() const + { + return cbcColSolution_; + } + /// Get pointer to array[getNumRows()] (for speed) of dual prices + inline const double *getCbcRowPrice() const + { + return cbcRowPrice_; + } + /// Get a pointer to array[getNumCols()] (for speed) of reduced costs + inline const double *getCbcReducedCost() const + { + return cbcReducedCost_; + } + /// Get pointer to array[getNumRows()] (for speed) of row activity levels. + inline const double *getCbcRowActivity() const + { + return cbcRowActivity_; + } + //@} + + /**@name Methods related to querying the solution */ + //@{ + /// Holds solution at continuous (after cuts if branchAndBound called) + inline double *continuousSolution() const + { + return continuousSolution_; + } + /** Array marked whenever a solution is found if non-zero. + Code marks if heuristic returns better so heuristic + need only mark if it wants to on solutions which + are worse than current */ + inline int *usedInSolution() const + { + return usedInSolution_; + } + /// Increases usedInSolution for nonzeros + void incrementUsed(const double *solution); + /// Record a new incumbent solution and update objectiveValue + void setBestSolution(CBC_Message how, + double &objectiveValue, const double *solution, + int fixVariables = 0); + /// Just update objectiveValue + void setBestObjectiveValue(double objectiveValue); + /// Deals with event handler and solution + CbcEventHandler::CbcAction dealWithEventHandler(CbcEventHandler::CbcEvent event, + double objValue, + const double *solution); + + /** Call this to really test if a valid solution can be feasible + Solution is number columns in size. + If fixVariables true then bounds of continuous solver updated. + Returns objective value (worse than cutoff if not feasible) + Previously computed objective value is now passed in (in case user does not do solve) + virtual so user can override + */ + virtual double checkSolution(double cutoff, double *solution, + int fixVariables, double originalObjValue); + /** Test the current solution for feasiblility. + + Scan all objects for indications of infeasibility. This is broken down + into simple integer infeasibility (\p numberIntegerInfeasibilities) + and all other reports of infeasibility (\p numberObjectInfeasibilities). + */ + bool feasibleSolution(int &numberIntegerInfeasibilities, + int &numberObjectInfeasibilities) const; + + /** Solution to the most recent lp relaxation. + + The solver's solution to the most recent lp relaxation. + */ + + inline double *currentSolution() const + { + return currentSolution_; + } + /** For testing infeasibilities - will point to + currentSolution_ or solver-->getColSolution() + */ + inline const double *testSolution() const + { + return testSolution_; + } + inline void setTestSolution(const double *solution) + { + testSolution_ = solution; + } + /// Make sure region there and optionally copy solution + void reserveCurrentSolution(const double *solution = NULL); + + /// Get pointer to array[getNumCols()] of primal solution vector + inline const double *getColSolution() const + { + return solver_->getColSolution(); + } + + /// Get pointer to array[getNumRows()] of dual prices + inline const double *getRowPrice() const + { + return solver_->getRowPrice(); + } + + /// Get a pointer to array[getNumCols()] of reduced costs + inline const double *getReducedCost() const + { + return solver_->getReducedCost(); + } + + /// Get pointer to array[getNumRows()] of row activity levels. + inline const double *getRowActivity() const + { + return solver_->getRowActivity(); + } + /// Return true if model flipped to make minimize (for printing) + inline bool modelFlipped() const + { + return (moreSpecialOptions2_&67108864)!=0; + } + /// Return objective function value with sign corrected + inline double trueObjValue(double value) const + { + return (moreSpecialOptions2_&67108864)==0 ? value : -value; + } + inline double trueBestObjValue() const + { + return (moreSpecialOptions2_&67108864)==0 ? bestObjective_ : -bestObjective_; + } + /// Return cutoff value with sign corrected + inline double trueCutoff() const + { + return (moreSpecialOptions2_&67108864)==0 ? + dblParam_[CbcCurrentCutoff] : -dblParam_[CbcCurrentCutoff]; + } + + /// Get current objective function value + inline double getCurrentObjValue() const + { + return dblParam_[CbcCurrentObjectiveValue]; + } + /// Get current minimization objective function value + inline double getCurrentMinimizationObjValue() const + { + return dblParam_[CbcCurrentMinimizationObjectiveValue]; + } + + /// Get best objective function value as minimization + inline double getMinimizationObjValue() const + { + return bestObjective_; + } + /// Set best objective function value as minimization + inline void setMinimizationObjValue(double value) + { + bestObjective_ = value; + } + + /// Get best objective function value + inline double getObjValue() const + { + return bestObjective_ * solver_->getObjSense(); + } + /** Get best possible objective function value. + This is better of best possible left on tree + and best solution found. + If called from within branch and cut may be optimistic. + */ + double getBestPossibleObjValue() const; + /// Set best objective function value + inline void setObjValue(double value) + { + bestObjective_ = value * solver_->getObjSense(); + } + /// Get solver objective function value (as minimization) + inline double getSolverObjValue() const + { + return solver_->getObjValue() * solver_->getObjSense(); + } + + /** The best solution to the integer programming problem. + + The best solution to the integer programming problem found during + the search. If no solution is found, the method returns null. + */ + + inline double *bestSolution() const + { + return bestSolution_; + } + /** User callable setBestSolution. + If check false does not check valid + If true then sees if feasible and warns if objective value + worse than given (so just set to COIN_DBL_MAX if you don't care). + If check true then does not save solution if not feasible + */ + void setBestSolution(const double *solution, int numberColumns, + double objectiveValue, bool check = false); + + /// Get number of solutions + inline int getSolutionCount() const + { + return numberSolutions_; + } + + /// Set number of solutions (so heuristics will be different) + inline void setSolutionCount(int value) + { + numberSolutions_ = value; + } + /// Number of saved solutions (including best) + int numberSavedSolutions() const; + /// Maximum number of extra saved solutions + inline int maximumSavedSolutions() const + { + return maximumSavedSolutions_; + } + /// Set maximum number of extra saved solutions + void setMaximumSavedSolutions(int value); + /// Return a saved solution (0==best) - NULL if off end + const double *savedSolution(int which) const; + /// Return a saved solution objective (0==best) - COIN_DBL_MAX if off end + double savedSolutionObjective(int which) const; + /// Delete a saved solution and move others up + void deleteSavedSolution(int which); + + /** Current phase (so heuristics etc etc can find out). + 0 - initial solve + 1 - solve with cuts at root + 2 - solve with cuts + 3 - other e.g. strong branching + 4 - trying to validate a solution + 5 - at end of search + */ + inline int phase() const + { + return phase_; + } + + /// Get number of heuristic solutions + inline int getNumberHeuristicSolutions() const + { + return numberHeuristicSolutions_; + } + /// Set number of heuristic solutions + inline void setNumberHeuristicSolutions(int value) + { + numberHeuristicSolutions_ = value; + } + + /// Set objective function sense (1 for min (default), -1 for max,) + inline void setObjSense(double s) + { + dblParam_[CbcOptimizationDirection] = s; + solver_->setObjSense(s); + } + + /// Value of objective at continuous + inline double getContinuousObjective() const + { + return originalContinuousObjective_; + } + inline void setContinuousObjective(double value) + { + originalContinuousObjective_ = value; + } + /// Number of infeasibilities at continuous + inline int getContinuousInfeasibilities() const + { + return continuousInfeasibilities_; + } + inline void setContinuousInfeasibilities(int value) + { + continuousInfeasibilities_ = value; + } + /// Value of objective after root node cuts added + inline double rootObjectiveAfterCuts() const + { + return continuousObjective_; + } + /// Sum of Changes to objective by first solve + inline double sumChangeObjective() const + { + return sumChangeObjective1_; + } + /** Number of times global cuts violated. When global cut pool then this + should be kept for each cut and type of cut */ + inline int numberGlobalViolations() const + { + return numberGlobalViolations_; + } + inline void clearNumberGlobalViolations() + { + numberGlobalViolations_ = 0; + } + /// Whether to force a resolve after takeOffCuts + inline bool resolveAfterTakeOffCuts() const + { + return resolveAfterTakeOffCuts_; + } + inline void setResolveAfterTakeOffCuts(bool yesNo) + { + resolveAfterTakeOffCuts_ = yesNo; + } + /// Maximum number of rows + inline int maximumRows() const + { + return maximumRows_; + } + /// Work basis for temporary use + inline CoinWarmStartBasis &workingBasis() + { + return workingBasis_; + } + /// Get number of "iterations" to stop after + inline int getStopNumberIterations() const + { + return stopNumberIterations_; + } + /// Set number of "iterations" to stop after + inline void setStopNumberIterations(int value) + { + stopNumberIterations_ = value; + } + /// A pointer to model from CbcHeuristic + inline CbcModel *heuristicModel() const + { + return heuristicModel_; + } + /// Set a pointer to model from CbcHeuristic + inline void setHeuristicModel(CbcModel *model) + { + heuristicModel_ = model; + } + //@} + + /** \name Node selection */ + //@{ + // Comparison functions (which may be overridden by inheritance) + inline CbcCompareBase *nodeComparison() const + { + return nodeCompare_; + } + void setNodeComparison(CbcCompareBase *compare); + void setNodeComparison(CbcCompareBase &compare); + //@} + + /** \name Problem feasibility checking */ + //@{ + // Feasibility functions (which may be overridden by inheritance) + inline CbcFeasibilityBase *problemFeasibility() const + { + return problemFeasibility_; + } + void setProblemFeasibility(CbcFeasibilityBase *feasibility); + void setProblemFeasibility(CbcFeasibilityBase &feasibility); + //@} + + /** \name Tree methods and subtree methods */ + //@{ + /// Tree method e.g. heap (which may be overridden by inheritance) + inline CbcTree *tree() const + { + return tree_; + } + /// For modifying tree handling (original is cloned) + void passInTreeHandler(CbcTree &tree); + /** For passing in an CbcModel to do a sub Tree (with derived tree handlers). + Passed in model must exist for duration of branch and bound + */ + void passInSubTreeModel(CbcModel &model); + /** For retrieving a copy of subtree model with given OsiSolver. + If no subtree model will use self (up to user to reset cutoff etc). + If solver NULL uses current + */ + CbcModel *subTreeModel(OsiSolverInterface *solver = NULL) const; + /// Returns number of times any subtree stopped on nodes, time etc + inline int numberStoppedSubTrees() const + { + return numberStoppedSubTrees_; + } + /// Says a sub tree was stopped + inline void incrementSubTreeStopped() + { + numberStoppedSubTrees_++; + } + /** Whether to automatically do presolve before branch and bound (subTrees). + 0 - no + 1 - ordinary presolve + 2 - integer presolve (dodgy) + */ + inline int typePresolve() const + { + return presolve_; + } + inline void setTypePresolve(int value) + { + presolve_ = value; + } + + //@} + + /** \name Branching Decisions + + See the CbcBranchDecision class for additional information. + */ + //@{ + + /// Get the current branching decision method. + inline CbcBranchDecision *branchingMethod() const + { + return branchingMethod_; + } + /// Set the branching decision method. + inline void setBranchingMethod(CbcBranchDecision *method) + { + delete branchingMethod_; + branchingMethod_ = method->clone(); + } + /** Set the branching method + + \overload + */ + inline void setBranchingMethod(CbcBranchDecision &method) + { + delete branchingMethod_; + branchingMethod_ = method.clone(); + } + /// Get the current cut modifier method + inline CbcCutModifier *cutModifier() const + { + return cutModifier_; + } + /// Set the cut modifier method + void setCutModifier(CbcCutModifier *modifier); + /** Set the cut modifier method + + \overload + */ + void setCutModifier(CbcCutModifier &modifier); + //@} + + /** \name Row (constraint) and Column (variable) cut generation */ + //@{ + + /** State of search + 0 - no solution + 1 - only heuristic solutions + 2 - branched to a solution + 3 - no solution but many nodes + */ + inline int stateOfSearch() const + { + return stateOfSearch_; + } + inline void setStateOfSearch(int state) + { + stateOfSearch_ = state; + } + /// Strategy worked out - mainly at root node for use by CbcNode + inline int searchStrategy() const + { + return searchStrategy_; + } + /// Set strategy worked out - mainly at root node for use by CbcNode + inline void setSearchStrategy(int value) + { + searchStrategy_ = value; + } + /// Stong branching strategy + inline int strongStrategy() const + { + return strongStrategy_; + } + /// Set strong branching strategy + inline void setStrongStrategy(int value) + { + strongStrategy_ = value; + } + + /// Get the number of cut generators + inline int numberCutGenerators() const + { + return numberCutGenerators_; + } + /// Get the list of cut generators + inline CbcCutGenerator **cutGenerators() const + { + return generator_; + } + ///Get the specified cut generator + inline CbcCutGenerator *cutGenerator(int i) const + { + return generator_[i]; + } + ///Get the specified cut generator before any changes + inline CbcCutGenerator *virginCutGenerator(int i) const + { + return virginGenerator_[i]; + } + /** Add one generator - up to user to delete generators. + howoften affects how generator is used. 0 or 1 means always, + >1 means every that number of nodes. Negative values have same + meaning as positive but they may be switched off (-> -100) by code if + not many cuts generated at continuous. -99 is just done at root. + Name is just for printout. + If depth >0 overrides how often generator is called (if howOften==-1 or >0). + */ + void addCutGenerator(CglCutGenerator *generator, + int howOften = 1, const char *name = NULL, + bool normal = true, bool atSolution = false, + bool infeasible = false, int howOftenInSub = -100, + int whatDepth = -1, int whatDepthInSub = -1); + //@} + /** \name Strategy and sub models + + See the CbcStrategy class for additional information. + */ + //@{ + + /// Get the current strategy + inline CbcStrategy *strategy() const + { + return strategy_; + } + /// Set the strategy. Clones + void setStrategy(CbcStrategy &strategy); + /// Set the strategy. assigns + inline void setStrategy(CbcStrategy *strategy) + { + strategy_ = strategy; + } + /// Get the current parent model + inline CbcModel *parentModel() const + { + return parentModel_; + } + /// Set the parent model + inline void setParentModel(CbcModel &parentModel) + { + parentModel_ = &parentModel; + } + //@} + + /** \name Heuristics and priorities */ + //@{ + /*! \brief Add one heuristic - up to user to delete + + The name is just used for print messages. + */ + void addHeuristic(CbcHeuristic *generator, const char *name = NULL, + int before = -1); + ///Get the specified heuristic + inline CbcHeuristic *heuristic(int i) const + { + return heuristic_[i]; + } + /// Get the number of heuristics + inline int numberHeuristics() const + { + return numberHeuristics_; + } + /// Set the number of heuristics + inline void setNumberHeuristics(int value) + { + numberHeuristics_ = value; + } + /// Pointer to heuristic solver which found last solution (or NULL) + inline CbcHeuristic *lastHeuristic() const + { + return lastHeuristic_; + } + /// set last heuristic which found a solution + inline void setLastHeuristic(CbcHeuristic *last) + { + lastHeuristic_ = last; + } + + /** Pass in branching priorities. + + If ifClique then priorities are on cliques otherwise priorities are + on integer variables. + Other type (if exists set to default) + 1 is highest priority. (well actually -INT_MAX is but that's ugly) + If hotstart > 0 then branches are created to force + the variable to the value given by best solution. This enables a + sort of hot start. The node choice should be greatest depth + and hotstart should normally be switched off after a solution. + + If ifNotSimpleIntegers true then appended to normal integers + + This is now deprecated except for simple usage. If user + creates Cbcobjects then set priority in them + + \internal Added for Kurt Spielberg. + */ + void passInPriorities(const int *priorities, bool ifNotSimpleIntegers); + + /// Returns priority level for an object (or 1000 if no priorities exist) + inline int priority(int sequence) const + { + return object_[sequence]->priority(); + } + + /*! \brief Set an event handler + + A clone of the handler passed as a parameter is stored in CbcModel. + */ + void passInEventHandler(const CbcEventHandler *eventHandler); + + /*! \brief Retrieve a pointer to the event handler */ + inline CbcEventHandler *getEventHandler() const + { + return (eventHandler_); + } + + //@} + + /**@name Setting/Accessing application data */ + //@{ + /** Set application data. + + This is a pointer that the application can store into and + retrieve from the solver interface. + This field is available for the application to optionally + define and use. + */ + void setApplicationData(void *appData); + + /// Get application data + void *getApplicationData() const; + /** + For advanced applications you may wish to modify the behavior of Cbc + e.g. if the solver is a NLP solver then you may not have an exact + optimum solution at each step. Information could be built into + OsiSolverInterface but this is an alternative so that that interface + does not have to be changed. If something similar is useful to + enough solvers then it could be migrated + You can also pass in by using solver->setAuxiliaryInfo. + You should do that if solver is odd - if solver is normal simplex + then use this. + NOTE - characteristics are not cloned + */ + void passInSolverCharacteristics(OsiBabSolver *solverCharacteristics); + /// Get solver characteristics + inline const OsiBabSolver *solverCharacteristics() const + { + return solverCharacteristics_; + } + //@} + + //--------------------------------------------------------------------------- + + /**@name Message handling etc */ + //@{ + /// Pass in Message handler (not deleted at end) + void passInMessageHandler(CoinMessageHandler *handler); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + /// Return handler + inline CoinMessageHandler *messageHandler() const + { + return handler_; + } + /// Return messages + inline CoinMessages &messages() + { + return messages_; + } + /// Return pointer to messages + inline CoinMessages *messagesPointer() + { + return &messages_; + } + /// Set log level + void setLogLevel(int value); + /// Get log level + inline int logLevel() const + { + return handler_->logLevel(); + } + /** Set flag to say if handler_ is the default handler. + + The default handler is deleted when the model is deleted. Other + handlers (supplied by the client) will not be deleted. + */ + inline void setDefaultHandler(bool yesNo) + { + defaultHandler_ = yesNo; + } + /// Check default handler + inline bool defaultHandler() const + { + return defaultHandler_; + } + //@} + //--------------------------------------------------------------------------- + ///@name Specialized + //@{ + + /** + Set special options + 0 bit (1) - check if cuts valid (if on debugger list) + 1 bit (2) - use current basis to check integer solution (rather than all slack) + 2 bit (4) - don't check integer solution (by solving LP) + 3 bit (8) - fast analyze + 4 bit (16) - non-linear model - so no well defined CoinPackedMatrix + 5 bit (32) - keep names + 6 bit (64) - try for dominated columns + 7 bit (128) - SOS type 1 but all declared integer + 8 bit (256) - Set to say solution just found, unset by doing cuts + 9 bit (512) - Try reduced model after 100 nodes + 10 bit (1024) - Switch on some heuristics even if seems unlikely + 11 bit (2048) - Mark as in small branch and bound + 12 bit (4096) - Funny cuts so do slow way (in some places) + 13 bit (8192) - Funny cuts so do slow way (in other places) + 14 bit (16384) - Use Cplex! for fathoming + 15 bit (32768) - Try reduced model after 0 nodes + 16 bit (65536) - Original model had integer bounds + 17 bit (131072) - Perturbation switched off + 18 bit (262144) - donor CbcModel + 19 bit (524288) - recipient CbcModel + 20 bit (1048576) - waiting for sub model to return + 22 bit (4194304) - do not initialize random seed in solver (user has) + 23 bit (8388608) - leave solver_ with cuts + 24 bit (16777216) - just get feasible if no cutoff + 25 bit (33554432) - feasibility pump after root cuts + 26 bit (67108864) - child model but going for complete search + */ + inline void setSpecialOptions(int value) + { + specialOptions_ = value; + } + /// Get special options + inline int specialOptions() const + { + return specialOptions_; + } + /// Set random seed + inline void setRandomSeed(int value) + { + randomSeed_ = value; + } + /// Get random seed + inline int getRandomSeed() const + { + return randomSeed_; + } + /// Set multiple root tries + inline void setMultipleRootTries(int value) + { + multipleRootTries_ = value; + } + /// Get multiple root tries + inline int getMultipleRootTries() const + { + return multipleRootTries_; + } + /// Tell model to stop on event + inline void sayEventHappened() + { + eventHappened_ = true; + } + /// Says if normal solver i.e. has well defined CoinPackedMatrix + inline bool normalSolver() const + { + return (specialOptions_ & 16) == 0; + } + /** Says if model is sitting there waiting for mini branch and bound to finish + This is because an event handler may only have access to parent model in + mini branch and bound + */ + inline bool waitingForMiniBranchAndBound() const + { + return (specialOptions_ & 1048576) != 0; + } + /** Set more special options + at present bottom 6 bits used for shadow price mode + 1024 for experimental hotstart + 2048,4096 breaking out of cuts + 8192 slowly increase minimum drop + 16384 gomory + 32768 more heuristics in sub trees + 65536 no cuts in preprocessing + 131072 Time limits elapsed + 18 bit (262144) - Perturb fathom nodes + 19 bit (524288) - No limit on fathom nodes + 20 bit (1048576) - Reduce sum of infeasibilities before cuts + 21 bit (2097152) - Reduce sum of infeasibilities after cuts + 22 bit (4194304) - Conflict analysis + 23 bit (8388608) - Conflict analysis - temporary bit + 24 bit (16777216) - Add cutoff as LP constraint (out) + 25 bit (33554432) - diving/reordering + 26 bit (67108864) - load global cuts from file + 27 bit (134217728) - append binding global cuts to file + 28 bit (268435456) - idiot branching + 29 bit (536870912) - don't make fake objective + 30 bit (1073741824) - Funny SOS or similar - be careful + */ + inline void setMoreSpecialOptions(int value) + { + moreSpecialOptions_ = value; + } + /// Get more special options + inline int moreSpecialOptions() const + { + return moreSpecialOptions_; + } + /** Set more more special options + 0 bit (1) - find switching variables + 1 bit (2) - using fake objective until solution + 2 bit (4) - switching variables exist + 3 bit (8) - skip most of setBestSolution checks + 4 bit (16) - very lightweight preprocessing in smallB&B + 5 bit (32) - event handler needs to be cloned when parallel + 6 bit (64) - testing - use probing to make cliques + 7/8 bit (128) - try orbital branching (if nauty) + 9 bit (512) - branching on objective (later) + 10 bit (1024) - branching on constraints (later) + 11/12 bit 2048 - intermittent cuts + 13/14 bit 8192 - go to bitter end in strong branching (first time) + 15 bit 32768 - take care of very very small values for Integer/SOS variables + 24 bit (67108864) - model has been flipped + */ + inline void setMoreSpecialOptions2(int value) + { + moreSpecialOptions2_ = value; + } + /// Get more special options2 + inline int moreSpecialOptions2() const + { + return moreSpecialOptions2_; + } + /// Set cutoff as constraint + inline void setCutoffAsConstraint(bool yesNo) + { + cutoffRowNumber_ = (yesNo) ? -2 : -1; + } + /// Set time method + inline void setUseElapsedTime(bool yesNo) + { + if (yesNo) + moreSpecialOptions_ |= 131072; + else + moreSpecialOptions_ &= ~131072; + } + /// Get time method + inline bool useElapsedTime() const + { + return (moreSpecialOptions_ & 131072) != 0; + } + /// Get useful temporary pointer + inline void *temporaryPointer() const + { + return temporaryPointer_; + } + /// Set useful temporary pointer + inline void setTemporaryPointer(void *pointer) + { + temporaryPointer_ = pointer; + } + /// Go to dantzig pivot selection if easy problem (clp only) + void goToDantzig(int numberNodes, ClpDualRowPivot *&savePivotMethod); + /// Now we may not own objects - just point to solver's objects + inline bool ownObjects() const + { + return ownObjects_; + } + /// Check original model before it gets messed up + void checkModel(); + //@} + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcModel(); + + /// Constructor from solver + CbcModel(const OsiSolverInterface &); + + /** Assign a solver to the model (model assumes ownership) + + On return, \p solver will be NULL. + If deleteSolver then current solver deleted (if model owned) + + \note Parameter settings in the outgoing solver are not inherited by + the incoming solver. + */ + void assignSolver(OsiSolverInterface *&solver, bool deleteSolver = true); + + /** \brief Set ownership of solver + + A parameter of false tells CbcModel it does not own the solver and + should not delete it. Once you claim ownership of the solver, you're + responsible for eventually deleting it. Note that CbcModel clones + solvers with abandon. Unless you have a deep understanding of the + workings of CbcModel, the only time you want to claim ownership is when + you're about to delete the CbcModel object but want the solver to + continue to exist (as, for example, when branchAndBound has finished + and you want to hang on to the answer). + */ + inline void setModelOwnsSolver(bool ourSolver) + { + ownership_ = ourSolver ? (ownership_ | 0x80000000) : (ownership_ & (~0x80000000)); + } + + /*! \brief Get ownership of solver + + A return value of true means that CbcModel owns the solver and will + take responsibility for deleting it when that becomes necessary. + */ + inline bool modelOwnsSolver() + { + return ((ownership_ & 0x80000000) != 0); + } + + /** Copy constructor . + If cloneHandler is true then message handler is cloned + */ + CbcModel(const CbcModel &rhs, bool cloneHandler = false); + + /** Clone */ + virtual CbcModel *clone(bool cloneHandler); + + /// Assignment operator + CbcModel &operator=(const CbcModel &rhs); + + /// Destructor + virtual ~CbcModel(); + + /// Returns solver - has current state + inline OsiSolverInterface *solver() const + { + return solver_; + } + + /// Returns current solver - sets new one + inline OsiSolverInterface *swapSolver(OsiSolverInterface *solver) + { + OsiSolverInterface *returnSolver = solver_; + solver_ = solver; + return returnSolver; + } + + /// Returns solver with continuous state + inline OsiSolverInterface *continuousSolver() const + { + return continuousSolver_; + } + + /// Create solver with continuous state + inline void createContinuousSolver() + { + continuousSolver_ = solver_->clone(); + } + /// Clear solver with continuous state + inline void clearContinuousSolver() + { + delete continuousSolver_; + continuousSolver_ = NULL; + } + + /// A copy of the solver, taken at constructor or by saveReferenceSolver + inline OsiSolverInterface *referenceSolver() const + { + return referenceSolver_; + } + + /// Save a copy of the current solver so can be reset to + void saveReferenceSolver(); + + /** Uses a copy of reference solver to be current solver. + Because of possible mismatches all exotic integer information is loat + (apart from normal information in OsiSolverInterface) + so SOS etc and priorities will have to be redone + */ + void resetToReferenceSolver(); + + /// Clears out as much as possible (except solver) + void gutsOfDestructor(); + /** Clears out enough to reset CbcModel as if no branch and bound done + */ + void gutsOfDestructor2(); + /** Clears out enough to reset CbcModel cutoff etc + */ + void resetModel(); + /** Most of copy constructor + mode - 0 copy but don't delete before + 1 copy and delete before + 2 copy and delete before (but use virgin generators) + */ + void gutsOfCopy(const CbcModel &rhs, int mode = 0); + /// Move status, nodes etc etc across + void moveInfo(const CbcModel &rhs); + //@} + + ///@name Multithreading + //@{ + /// Indicates whether Cbc library has been compiled with multithreading support + static bool haveMultiThreadSupport(); + /// Get pointer to masterthread + CbcThread *masterThread() const + { + return masterThread_; + } + /// Get pointer to walkback + CbcNodeInfo **walkback() const + { + return walkback_; + } + /// Get number of threads + inline int getNumberThreads() const + { + return numberThreads_; + } + /// Set number of threads + inline void setNumberThreads(int value) + { + numberThreads_ = value; + } + /// Get thread mode + inline int getThreadMode() const + { + return threadMode_; + } + /** Set thread mode + always use numberThreads for branching + 1 set then deterministic + 2 set then use numberThreads for root cuts + 4 set then use numberThreads in root mini branch and bound + 8 set and numberThreads - do heuristics numberThreads at a time + 8 set and numberThreads==0 do all heuristics at once + default is 0 + */ + inline void setThreadMode(int value) + { + threadMode_ = value; + } + /** Return + -2 if deterministic threaded and main thread + -1 if deterministic threaded and serial thread + 0 if serial + 1 if opportunistic threaded + */ + inline int parallelMode() const + { + if (!numberThreads_) { + if ((threadMode_ & 1) == 0) + return 0; + else + return -1; + return 0; + } else { + if ((threadMode_ & 1) == 0) + return 1; + else + return -2; + } + } + /// Thread stuff for master + inline CbcBaseModel *master() const + { + return master_; + } + /// From here to end of section - code in CbcThread.cpp until class changed + /// Returns true if locked + bool isLocked() const; + /** + Locks a thread if parallel so that stuff like cut pool + can be updated and/or used. + */ + void lockThread(); + /** + Unlocks a thread if parallel to say cut pool stuff not needed + */ + void unlockThread(); + /** Set information in a child + -3 pass pointer to child thread info + -2 just stop + -1 delete simple child stuff + 0 delete opportunistic child stuff + 1 delete deterministic child stuff + */ + void setInfoInChild(int type, CbcThread *info); + /** Move/copy information from one model to another + -1 - initialization + 0 - from base model + 1 - to base model (and reset) + 2 - add in final statistics etc (and reset so can do clean destruction) + */ + void moveToModel(CbcModel *baseModel, int mode); + /// Split up nodes + int splitModel(int numberModels, CbcModel **model, + int numberNodes); + /// Start threads + void startSplitModel(int numberIterations); + /// Merge models + void mergeModels(int numberModel, CbcModel **model, + int numberNodes); + //@} + + ///@name semi-private i.e. users should not use + //@{ + /// Get how many Nodes it took to solve the problem. + int getNodeCount2() const + { + return numberNodes2_; + } + /// Set pointers for speed + void setPointers(const OsiSolverInterface *solver); + /** Perform reduced cost fixing + + Fixes integer variables at their current value based on reduced cost + penalties. Returns number fixed + */ + int reducedCostFix(); + /** Makes all handlers same. If makeDefault 1 then makes top level + default and rest point to that. If 2 then each is copy + */ + void synchronizeHandlers(int makeDefault); + /// Save a solution to saved list + void saveExtraSolution(const double *solution, double objectiveValue); + /// Save a solution to best and move current to saved + void saveBestSolution(const double *solution, double objectiveValue); + /// Delete best and saved solutions + void deleteSolutions(); + /// Encapsulates solver resolve + int resolve(OsiSolverInterface *solver); +#ifdef CLP_RESOLVE + /// Special purpose resolve + int resolveClp(OsiClpSolverInterface *solver, int type); +#endif + + /** Encapsulates choosing a variable - + anyAction -2, infeasible (-1 round again), 0 done + */ + int chooseBranch(CbcNode *&newNode, int numberPassesLeft, + CbcNode *oldNode, OsiCuts &cuts, + bool &resolved, CoinWarmStartBasis *lastws, + const double *lowerBefore, const double *upperBefore, + OsiSolverBranch *&branches); + + /** Return an empty basis object of the specified size + + A useful utility when constructing a basis for a subproblem from scratch. + The object returned will be of the requested capacity and appropriate for + the solver attached to the model. + */ + CoinWarmStartBasis *getEmptyBasis(int ns = 0, int na = 0) const; + + /** Remove inactive cuts from the model + + An OsiSolverInterface is expected to maintain a valid basis, but not a + valid solution, when loose cuts are deleted. Restoring a valid solution + requires calling the solver to reoptimise. If it's certain the solution + will not be required, set allowResolve to false to suppress + reoptimisation. + If saveCuts then slack cuts will be saved + On input current cuts are cuts and newCuts + on exit current cuts will be correct. Returns number dropped + */ + int takeOffCuts(OsiCuts &cuts, + bool allowResolve, OsiCuts *saveCuts, + int numberNewCuts = 0, const OsiRowCut **newCuts = NULL); + + /** Determine and install the active cuts that need to be added for + the current subproblem + + The whole truth is a bit more complicated. The first action is a call to + addCuts1(). addCuts() then sorts through the list, installs the tight + cuts in the model, and does bookkeeping (adjusts reference counts). + The basis returned from addCuts1() is adjusted accordingly. + + If it turns out that the node should really be fathomed by bound, + addCuts() simply treats all the cuts as loose as it does the bookkeeping. + + */ + int addCuts(CbcNode *node, CoinWarmStartBasis *&lastws); + + /** Traverse the tree from node to root and prep the model + + addCuts1() begins the job of prepping the model to match the current + subproblem. The model is stripped of all cuts, and the search tree is + traversed from node to root to determine the changes required. Appropriate + bounds changes are installed, a list of cuts is collected but not + installed, and an appropriate basis (minus the cuts, but big enough to + accommodate them) is constructed. + + Returns true if new problem similar to old + + \todo addCuts1() is called in contexts where it's known in advance that + all that's desired is to determine a list of cuts and do the + bookkeeping (adjust the reference counts). The work of installing + bounds and building a basis goes to waste. + */ + bool addCuts1(CbcNode *node, CoinWarmStartBasis *&lastws); + /** Returns bounds just before where - initially original bounds. + Also sets downstream nodes (lower if force 1, upper if 2) + */ + void previousBounds(CbcNode *node, CbcNodeInfo *where, int iColumn, + double &lower, double &upper, int force); + /** Set objective value in a node. This is separated out so that + odd solvers can use. It may look at extra information in + solverCharacteriscs_ and will also use bound from parent node + */ + void setObjectiveValue(CbcNode *thisNode, const CbcNode *parentNode) const; + + /** If numberBeforeTrust >0 then we are going to use CbcBranchDynamic. + Scan and convert CbcSimpleInteger objects + */ + void convertToDynamic(); + /// Set numberBeforeTrust in all objects + void synchronizeNumberBeforeTrust(int type = 0); + /// Zap integer information in problem (may leave object info) + void zapIntegerInformation(bool leaveObjects = true); + /// Fill in useful estimates + void pseudoShadow(int type); + /** Return pseudo costs + If not all integers or not pseudo costs - returns all zero + Length of arrays are numberIntegers() and entries + correspond to integerVariable()[i] + User must allocate arrays before call + */ + void fillPseudoCosts(double *downCosts, double *upCosts, + int *priority = NULL, + int *numberDown = NULL, int *numberUp = NULL, + int *numberDownInfeasible = NULL, + int *numberUpInfeasible = NULL) const; + /** Do heuristics at root. + 0 - don't delete + 1 - delete + 2 - just delete - don't even use + */ + void doHeuristicsAtRoot(int deleteHeuristicsAfterwards = 0); + /// Adjust heuristics based on model + void adjustHeuristics(); + /// Get the hotstart solution + inline const double *hotstartSolution() const + { + return hotstartSolution_; + } + /// Get the hotstart priorities + inline const int *hotstartPriorities() const + { + return hotstartPriorities_; + } + + /// Return the list of cuts initially collected for this subproblem + inline CbcCountRowCut **addedCuts() const + { + return addedCuts_; + } + /// Number of entries in the list returned by #addedCuts() + inline int currentNumberCuts() const + { + return currentNumberCuts_; + } + /// Global cuts + inline CbcRowCuts *globalCuts() + { + return &globalCuts_; + } + /// Get rid of global cuts + inline void zapGlobalCuts() + { + globalCuts_ = CbcRowCuts(); + } + /// Copy and set a pointer to a row cut which will be added instead of normal branching. + void setNextRowCut(const OsiRowCut &cut); + /// Get a pointer to current node (be careful) + inline CbcNode *currentNode() const + { + return currentNode_; + } + /// Delete a node and possibly null out currentNode_ + void deleteNode(CbcNode * node); + /// Get a pointer to probing info + inline CglTreeProbingInfo *probingInfo() const + { + return probingInfo_; + } + /// Thread specific random number generator + inline CoinThreadRandom *randomNumberGenerator() + { + return &randomNumberGenerator_; + } + /// Set the number of iterations done in strong branching. + inline void setNumberStrongIterations(int number) + { + numberStrongIterations_ = number; + } + /// Get the number of iterations done in strong branching. + inline int numberStrongIterations() const + { + return numberStrongIterations_; + } + /// Get maximum number of iterations (designed to be used in heuristics) + inline int maximumNumberIterations() const + { + return maximumNumberIterations_; + } + /// Set maximum number of iterations (designed to be used in heuristics) + inline void setMaximumNumberIterations(int value) + { + maximumNumberIterations_ = value; + } + + /// Symmetry information + inline CbcSymmetry *symmetryInfo() const + { + return symmetryInfo_; + } + /// Set symmetry information + inline void setSymmetryInfo(CbcSymmetry * info) + { + symmetryInfo_ = info; + } + /// get rid of all + void zapSymmetry(); + /// Root symmetry information + inline CbcSymmetry *rootSymmetryInfo() const + { + return rootSymmetryInfo_; + } + /// Set depth for fast nodes + inline void setFastNodeDepth(int value) + { + fastNodeDepth_ = value; + } + /// Get depth for fast nodes + inline int fastNodeDepth() const + { + return fastNodeDepth_; + } + /// Get anything with priority >= this can be treated as continuous + inline int continuousPriority() const + { + return continuousPriority_; + } + /// Set anything with priority >= this can be treated as continuous + inline void setContinuousPriority(int value) + { + continuousPriority_ = value; + } + inline void incrementExtra(int nodes, int iterations, int fathoms = 1) + { + numberExtraNodes_ += nodes; + numberExtraIterations_ += iterations; + numberFathoms_ += fathoms; + } + /// Zero extra + inline void zeroExtra() + { + numberExtraNodes_ = 0; + numberExtraIterations_ = 0; + numberFathoms_ = 0; + } + /// Number of extra iterations + inline int numberExtraIterations() const + { + return numberExtraIterations_; + } + /// Increment strong info + void incrementStrongInfo(int numberTimes, int numberIterations, + int numberFixed, bool ifInfeasible); + /// Return strong info + inline const int *strongInfo() const + { + return strongInfo_; + } + + /// Return mutable strong info + inline int *mutableStrongInfo() + { + return strongInfo_; + } + /// Get stored row cuts for donor/recipient CbcModel + CglStored *storedRowCuts() const + { + return storedRowCuts_; + } + /// Set stored row cuts for donor/recipient CbcModel + void setStoredRowCuts(CglStored *cuts) + { + storedRowCuts_ = cuts; + } + /// Says whether all dynamic integers + inline bool allDynamic() const + { + return ((ownership_ & 0x40000000) != 0); + } + /// Create C++ lines to get to current state + void generateCpp(FILE *fp, int options); + /// Generate an OsiBranchingInformation object + OsiBranchingInformation usefulInformation() const; + /** Warm start object produced by heuristic or strong branching + + If get a valid integer solution outside branch and bound then it can take + a reasonable time to solve LP which produces clean solution. If this object has + any size then it will be used in solve. + */ + inline void setBestSolutionBasis(const CoinWarmStartBasis &bestSolutionBasis) + { + bestSolutionBasis_ = bestSolutionBasis; + } + /// Redo walkback arrays + void redoWalkBack(); + //@} + + void setMIPStart(const std::vector< std::pair< std::string, double > > &mipstart) + { + this->mipStart_ = mipstart; + } + + /** if original column names will be preserved in preprocessed problem + */ + void setKeepNamesPreproc( bool _keep ) + { + this->keepNamesPreproc = _keep; + } + + bool getKeepNamesPreproc() const + { + return keepNamesPreproc; + } + + /** may be safer to use this overload method: c++ string libraries + * implementation may not be binary compatible */ + void setMIPStart(int count, const char **colNames, const double colValues[]); + + + const std::vector< std::pair< std::string, double > > &getMIPStart() + { + return this->mipStart_; + } + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + + /// The solver associated with this model. + OsiSolverInterface *solver_; + + /** Ownership of objects and other stuff + + 0x80000000 model owns solver + 0x40000000 all variables CbcDynamicPseudoCost + */ + unsigned int ownership_; + + /// A copy of the solver, taken at the continuous (root) node. + OsiSolverInterface *continuousSolver_; + + /// A copy of the solver, taken at constructor or by saveReferenceSolver + OsiSolverInterface *referenceSolver_; + + /// Message handler + CoinMessageHandler *handler_; + + /** Flag to say if handler_ is the default handler. + + The default handler is deleted when the model is deleted. Other + handlers (supplied by the client) will not be deleted. + */ + bool defaultHandler_; + + /// Cbc messages + CoinMessages messages_; + + /// Array for integer parameters + int intParam_[CbcLastIntParam]; + + /// Array for double parameters + double dblParam_[CbcLastDblParam]; + + /** Pointer to an empty warm start object + + It turns out to be useful to have this available as a base from + which to build custom warm start objects. This is typed as CoinWarmStart + rather than CoinWarmStartBasis to allow for the possibility that a + client might want to apply a solver that doesn't use a basis-based warm + start. See getEmptyBasis for an example of how this field can be used. + */ + mutable CoinWarmStart *emptyWarmStart_; + + /// Best objective + double bestObjective_; + /// Best possible objective + double bestPossibleObjective_; + /// Sum of Changes to objective by first solve + double sumChangeObjective1_; + /// Sum of Changes to objective by subsequent solves + double sumChangeObjective2_; + + /// Array holding the incumbent (best) solution. + double *bestSolution_; + /// Arrays holding other solutions. + double **savedSolutions_; + + /** Array holding the current solution. + + This array is used more as a temporary. + */ + double *currentSolution_; + /** For testing infeasibilities - will point to + currentSolution_ or solver-->getColSolution() + */ + mutable const double *testSolution_; + /** MIPstart values + values for integer variables which will be converted to a complete integer initial feasible solution + */ + std::vector< std::pair< std::string, double > > mipStart_; + + /** keepNamesPreproc + * if variables names will be preserved in the pre-processed problem + * (usefull in callbacks) + **/ + bool keepNamesPreproc; + + /** Warm start object produced by heuristic or strong branching + + If get a valid integer solution outside branch and bound then it can take + a reasonable time to solve LP which produces clean solution. If this object has + any size then it will be used in solve. + */ + CoinWarmStartBasis bestSolutionBasis_; + /// Global cuts + CbcRowCuts globalCuts_; + /// Global conflict cuts + CbcRowCuts *globalConflictCuts_; + + /// Minimum degradation in objective value to continue cut generation + double minimumDrop_; + /// Number of solutions + int numberSolutions_; + /// Number of saved solutions + int numberSavedSolutions_; + /// Maximum number of saved solutions + int maximumSavedSolutions_; + /** State of search + 0 - no solution + 1 - only heuristic solutions + 2 - branched to a solution + 3 - no solution but many nodes + */ + int stateOfSearch_; + /// At which depths to do cuts + int whenCuts_; + /// Hotstart solution + double *hotstartSolution_; + /// Hotstart priorities + int *hotstartPriorities_; + /// Number of heuristic solutions + int numberHeuristicSolutions_; + /// Cumulative number of nodes + int numberNodes_; + /** Cumulative number of nodes for statistics. + Must fix to match up + */ + int numberNodes2_; + /// Cumulative number of iterations + int numberIterations_; + /// Cumulative number of solves + int numberSolves_; + /// Status of problem - 0 finished, 1 stopped, 2 difficulties + int status_; + /** Secondary status of problem + -1 unset (status_ will also be -1) + 0 search completed with solution + 1 linear relaxation not feasible (or worse than cutoff) + 2 stopped on gap + 3 stopped on nodes + 4 stopped on time + 5 stopped on user event + 6 stopped on solutions + */ + int secondaryStatus_; + /// Number of integers in problem + int numberIntegers_; + /// Number of rows at continuous + int numberRowsAtContinuous_; + /** + -1 - cutoff as constraint not activated + -2 - waiting to activate + >=0 - activated + */ + int cutoffRowNumber_; + /// Maximum number of cuts + int maximumNumberCuts_; + /** Current phase (so heuristics etc etc can find out). + 0 - initial solve + 1 - solve with cuts at root + 2 - solve with cuts + 3 - other e.g. strong branching + 4 - trying to validate a solution + 5 - at end of search + */ + int phase_; + + /// Number of entries in #addedCuts_ + int currentNumberCuts_; + + /** Current limit on search tree depth + + The allocated size of #walkback_. Increased as needed. + */ + int maximumDepth_; + /** Array used to assemble the path between a node and the search tree root + + The array is resized when necessary. #maximumDepth_ is the current + allocated size. + */ + CbcNodeInfo **walkback_; + /// preProcess used before branch and bound (optional) + CglPreProcess *preProcess_; + CbcNodeInfo **lastNodeInfo_; + const OsiRowCut **lastCut_; + int lastDepth_; + int lastNumberCuts2_; + int maximumCuts_; + int *lastNumberCuts_; + + /** The list of cuts initially collected for this subproblem + + When the subproblem at this node is rebuilt, a set of cuts is collected + for inclusion in the constraint system. If any of these cuts are + subsequently removed because they have become loose, the corresponding + entry is set to NULL. + */ + CbcCountRowCut **addedCuts_; + + /** A pointer to a row cut which will be added instead of normal branching. + After use it should be set to NULL. + */ + OsiRowCut *nextRowCut_; + + /// Current node so can be used elsewhere + CbcNode *currentNode_; + + /// Indices of integer variables + int *integerVariable_; + /// Whether of not integer + char *integerInfo_; + /// Holds solution at continuous (after cuts) + double *continuousSolution_; + /// Array marked whenever a solution is found if non-zero + int *usedInSolution_; + /** + Special options + 0 bit (1) - check if cuts valid (if on debugger list) + 1 bit (2) - use current basis to check integer solution (rather than all slack) + 2 bit (4) - don't check integer solution (by solving LP) + 3 bit (8) - fast analyze + 4 bit (16) - non-linear model - so no well defined CoinPackedMatrix + 5 bit (32) - keep names + 6 bit (64) - try for dominated columns + 7 bit (128) - SOS type 1 but all declared integer + 8 bit (256) - Set to say solution just found, unset by doing cuts + 9 bit (512) - Try reduced model after 100 nodes + 10 bit (1024) - Switch on some heuristics even if seems unlikely + 11 bit (2048) - Mark as in small branch and bound + 12 bit (4096) - Funny cuts so do slow way (in some places) + 13 bit (8192) - Funny cuts so do slow way (in other places) + 14 bit (16384) - Use Cplex! for fathoming + 15 bit (32768) - Try reduced model after 0 nodes + 16 bit (65536) - Original model had integer bounds + 17 bit (131072) - Perturbation switched off + 18 bit (262144) - donor CbcModel + 19 bit (524288) - recipient CbcModel + 20 bit (1048576) - waiting for sub model to return + 22 bit (4194304) - do not initialize random seed in solver (user has) + 23 bit (8388608) - leave solver_ with cuts + 24 bit (16777216) - just get feasible if no cutoff + */ + int specialOptions_; + /** More special options + at present bottom 6 bits used for shadow price mode + 1024 for experimental hotstart + 2048,4096 breaking out of cuts + 8192 slowly increase minimum drop + 16384 gomory + 32768 more heuristics in sub trees + 65536 no cuts in preprocessing + 131072 Time limits elapsed + 18 bit (262144) - Perturb fathom nodes + 19 bit (524288) - No limit on fathom nodes + 20 bit (1048576) - Reduce sum of infeasibilities before cuts + 21 bit (2097152) - Reduce sum of infeasibilities after cuts + */ + int moreSpecialOptions_; + /** More more special options + 0 bit (1) - find switching variables + 1 bit (2) - using fake objective until solution + 2 bit (4) - switching variables exist + 3 bit (8) - skip most of setBestSolution checks + 4 bit (16) - very lightweight preprocessing in smallB&B + 5 bit (32) - event handler needs to be cloned when parallel + 6 bit (64) - testing - use probing to make cliques + 7/8 bit (128) - try orbital branching (if nauty) + 9 bit (512) - branching on objective (later) + 10 bit (1024) - branching on constraints (later) + 11/12 bit 2048 - intermittent cuts + */ + int moreSpecialOptions2_; + /// User node comparison function + CbcCompareBase *nodeCompare_; + /// User feasibility function (see CbcFeasibleBase.hpp) + CbcFeasibilityBase *problemFeasibility_; + /// Tree + CbcTree *tree_; + /// Pointer to top of tree + CbcFullNodeInfo *topOfTree_; + /// A pointer to model to be used for subtrees + CbcModel *subTreeModel_; + /// A pointer to model from CbcHeuristic + CbcModel *heuristicModel_; + /// Number of times any subtree stopped on nodes, time etc + int numberStoppedSubTrees_; + /// Variable selection function + CbcBranchDecision *branchingMethod_; + /// Cut modifier function + CbcCutModifier *cutModifier_; + /// Strategy + CbcStrategy *strategy_; + /// Parent model + CbcModel *parentModel_; + /** Whether to automatically do presolve before branch and bound. + 0 - no + 1 - ordinary presolve + 2 - integer presolve (dodgy) + */ + /// Pointer to array[getNumCols()] (for speed) of column lower bounds + const double *cbcColLower_; + /// Pointer to array[getNumCols()] (for speed) of column upper bounds + const double *cbcColUpper_; + /// Pointer to array[getNumRows()] (for speed) of row lower bounds + const double *cbcRowLower_; + /// Pointer to array[getNumRows()] (for speed) of row upper bounds + const double *cbcRowUpper_; + /// Pointer to array[getNumCols()] (for speed) of primal solution vector + const double *cbcColSolution_; + /// Pointer to array[getNumRows()] (for speed) of dual prices + const double *cbcRowPrice_; + /// Get a pointer to array[getNumCols()] (for speed) of reduced costs + const double *cbcReducedCost_; + /// Pointer to array[getNumRows()] (for speed) of row activity levels. + const double *cbcRowActivity_; + /// Pointer to user-defined data structure + void *appData_; + /// Presolve for CbcTreeLocal + int presolve_; + /** Maximum number of candidates to consider for strong branching. + To disable strong branching, set this to 0. + */ + int numberStrong_; + /** \brief The number of branches before pseudo costs believed + in dynamic strong branching. + + A value of 0 is off. + */ + int numberBeforeTrust_; + /** \brief The number of variables for which to compute penalties + in dynamic strong branching. + */ + int numberPenalties_; + /// For threads - stop after this many "iterations" + int stopNumberIterations_; + /** Scale factor to make penalties match strong. + Should/will be computed */ + double penaltyScaleFactor_; + /// Number of analyze iterations to do + int numberAnalyzeIterations_; + /// Arrays with analysis results + double *analyzeResults_; + /// Useful temporary pointer + void *temporaryPointer_; + /// Number of nodes infeasible by normal branching (before cuts) + int numberInfeasibleNodes_; + /** Problem type as set by user or found by analysis. This will be extended + 0 - not known + 1 - Set partitioning <= + 2 - Set partitioning == + 3 - Set covering + */ + int problemType_; + /// Print frequency + int printFrequency_; + /// Number of cut generators + int numberCutGenerators_; + // Cut generators + CbcCutGenerator **generator_; + // Cut generators before any changes + CbcCutGenerator **virginGenerator_; + /// Number of heuristics + int numberHeuristics_; + /// Heuristic solvers + CbcHeuristic **heuristic_; + /// Pointer to heuristic solver which found last solution (or NULL) + CbcHeuristic *lastHeuristic_; + /// Depth for fast nodes + int fastNodeDepth_; + /*! Pointer to the event handler */ +#ifdef CBC_ONLY_CLP + ClpEventHandler *eventHandler_; +#else + CbcEventHandler *eventHandler_; +#endif + /// Symmetry information + CbcSymmetry *symmetryInfo_; + /// Root symmetry information + CbcSymmetry *rootSymmetryInfo_; + /// Total number of objects + int numberObjects_; + + /** \brief Integer and Clique and ... information + + \note The code assumes that the first objects on the list will be + SimpleInteger objects for each integer variable, followed by + Clique objects. Portions of the code that understand Clique objects + will fail if they do not immediately follow the SimpleIntegers. + Large chunks of the code will fail if the first objects are not + SimpleInteger. As of 2003.08, SimpleIntegers and Cliques are the only + objects. + */ + OsiObject **object_; + /// Now we may not own objects - just point to solver's objects + bool ownObjects_; + + /// Original columns as created by integerPresolve or preprocessing + int *originalColumns_; + /// How often to scan global cuts + int howOftenGlobalScan_; + /** Number of times global cuts violated. When global cut pool then this + should be kept for each cut and type of cut */ + int numberGlobalViolations_; + /// Number of extra iterations in fast lp + int numberExtraIterations_; + /// Number of extra nodes in fast lp + int numberExtraNodes_; + /// Number of times fast lp entered + int numberFathoms_; + /** Value of objective at continuous + (Well actually after initial round of cuts) + */ + double continuousObjective_; + /** Value of objective before root node cuts added + */ + double originalContinuousObjective_; + /// Number of infeasibilities at continuous + int continuousInfeasibilities_; + /// Maximum number of cut passes at root + int maximumCutPassesAtRoot_; + /// Maximum number of cut passes + int maximumCutPasses_; + /// Preferred way of branching + int preferredWay_; + /// Current cut pass number + int currentPassNumber_; + /// Maximum number of cuts (for whichGenerator_) + int maximumWhich_; + /// Maximum number of rows + int maximumRows_; + /// Random seed + int randomSeed_; + /// Multiple root tries + int multipleRootTries_; + /// Current depth + int currentDepth_; + /// Thread specific random number generator + mutable CoinThreadRandom randomNumberGenerator_; + /// Work basis for temporary use + CoinWarmStartBasis workingBasis_; + /// Which cut generator generated this cut + int *whichGenerator_; + /// Maximum number of statistics + int maximumStatistics_; + /// statistics + CbcStatistics **statistics_; + /// Maximum depth reached + int maximumDepthActual_; + /// Number of reduced cost fixings + double numberDJFixed_; + /// Probing info + CglTreeProbingInfo *probingInfo_; + /// Number of fixed by analyze at root + int numberFixedAtRoot_; + /// Number fixed by analyze so far + int numberFixedNow_; + /// Whether stopping on gap + bool stoppedOnGap_; + /// Whether event happened + mutable bool eventHappened_; + /// Number of long strong goes + int numberLongStrong_; + /// Number of old active cuts + int numberOldActiveCuts_; + /// Number of new cuts + int numberNewCuts_; + /// Strategy worked out - mainly at root node + int searchStrategy_; + /** Strategy for strong branching + 0 - normal + when to do all fractional + 1 - root node + 2 - depth less than modifier + 4 - if objective == best possible + 6 - as 2+4 + when to do all including satisfied + 10 - root node etc. + If >=100 then do when depth <= strategy/100 (otherwise 5) + */ + int strongStrategy_; + /// Number of iterations in strong branching + int numberStrongIterations_; + /** 0 - number times strong branching done, 1 - number fixed, 2 - number infeasible + Second group of three is a snapshot at node [6] */ + int strongInfo_[7]; + /** + For advanced applications you may wish to modify the behavior of Cbc + e.g. if the solver is a NLP solver then you may not have an exact + optimum solution at each step. This gives characteristics - just for one BAB. + For actually saving/restoring a solution you need the actual solver one. + */ + OsiBabSolver *solverCharacteristics_; + /// Whether to force a resolve after takeOffCuts + bool resolveAfterTakeOffCuts_; + /// Maximum number of iterations (designed to be used in heuristics) + int maximumNumberIterations_; + /// Anything with priority >= this can be treated as continuous + int continuousPriority_; + /// Number of outstanding update information items + int numberUpdateItems_; + /// Maximum number of outstanding update information items + int maximumNumberUpdateItems_; + /// Update items + CbcObjectUpdateData *updateItems_; + /// Stored row cuts for donor/recipient CbcModel + CglStored *storedRowCuts_; + /** + Parallel + 0 - off + 1 - testing + 2-99 threads + other special meanings + */ + int numberThreads_; + /** thread mode + always use numberThreads for branching + 1 set then deterministic + 2 set then use numberThreads for root cuts + 4 set then use numberThreads in root mini branch and bound + default is 0 + */ + int threadMode_; + /// Number of global cuts on entry to a node + int numberGlobalCutsIn_; + /// Thread stuff for master + CbcBaseModel *master_; + /// Pointer to masterthread + CbcThread *masterThread_; + //@} +}; +/// So we can use osiObject or CbcObject during transition +void getIntegerInformation(const OsiObject *object, double &originalLower, + double &originalUpper); +// So we can call from other programs +// Real main program +class OsiClpSolverInterface; +int CbcMain(int argc, const char *argv[], CbcModel &babSolver); +// four ways of calling +int callCbc(const char *input2, OsiClpSolverInterface &solver1); +int callCbc(const char *input2); +int callCbc(const std::string input2, OsiClpSolverInterface &solver1); +int callCbc(const std::string input2); +// When we want to load up CbcModel with options first +void CbcMain0(CbcModel &babSolver); +int CbcMain1(int argc, const char *argv[], CbcModel &babSolver); +// two ways of calling +int callCbc(const char *input2, CbcModel &babSolver); +int callCbc(const std::string input2, CbcModel &babSolver); +// And when CbcMain0 already called to initialize (with call back) (see CbcMain1 for whereFrom) +int callCbc1(const char *input2, CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom)); +int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom)); +// For uniform setting of cut and heuristic options +void setCutAndHeuristicOptions(CbcModel &model); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNWay.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNWay.hpp new file mode 100644 index 000000000..ca90352ec --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNWay.hpp @@ -0,0 +1,171 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/9/2009-- carved out of CbcBranchActual + +/** Define an n-way class for variables. + Only valid value is one at UB others at LB + Normally 0-1 +*/ +#ifndef CbcNWay_H +#define CbcNWay_H + +class CbcNWay : public CbcObject { + +public: + // Default Constructor + CbcNWay(); + + /** Useful constructor (which are matrix indices) + */ + CbcNWay(CbcModel *model, int numberMembers, + const int *which, int identifier); + + // Copy constructor + CbcNWay(const CbcNWay &); + + /// Clone + virtual CbcObject *clone() const; + + /// Assignment operator + CbcNWay &operator=(const CbcNWay &rhs); + + /// Destructor + virtual ~CbcNWay(); + + /// Set up a consequence for a single member + void setConsequence(int iColumn, const CbcConsequence &consequence); + + /// Applies a consequence for a single member + void applyConsequence(int iSequence, int state) const; + + /// Infeasibility - large is 0.5 (and 0.5 will give this) + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /// Number of members + inline int numberMembers() const + { + return numberMembers_; + } + + /// Members (indices in range 0 ... numberColumns-1) + inline const int *members() const + { + return members_; + } + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns); + +protected: + /// data + /// Number of members + int numberMembers_; + + /// Members (indices in range 0 ... numberColumns-1) + int *members_; + /// Consequences (normally NULL) + CbcConsequence **consequence_; +}; +/** N way branching Object class. + Variable is number of set. + */ +class CbcNWayBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcNWayBranchingObject(); + + /** Useful constructor - order had matrix indices + way_ -1 corresponds to setting first, +1 to second, +3 etc. + this is so -1 and +1 have similarity to normal + */ + CbcNWayBranchingObject(CbcModel *model, const CbcNWay *nway, + int numberBranches, const int *order); + + // Copy constructor + CbcNWayBranchingObject(const CbcNWayBranchingObject &); + + // Assignment operator + CbcNWayBranchingObject &operator=(const CbcNWayBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcNWayBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + +#ifdef JJF_ZERO + // FIXME: what do we need to do here? + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch(); +#endif + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + /** The number of branch arms created for this branching object + */ + virtual int numberBranches() const + { + return numberInSet_; + } + /// Is this a two way object (-1 down, +1 up) + virtual bool twoWay() const + { + return false; + } + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return NWayBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +private: + /// order of branching - points back to CbcNWay + int *order_; + /// Points back to object + const CbcNWay *object_; + /// Number in set + int numberInSet_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNode.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNode.hpp new file mode 100644 index 000000000..78ee037ae --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNode.hpp @@ -0,0 +1,380 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcNode_H +#define CbcNode_H + +#include +#include + +#include "CoinWarmStartBasis.hpp" +#include "CoinSearchTree.hpp" +#include "CbcBranchBase.hpp" +#include "CbcNodeInfo.hpp" +#include "CbcFullNodeInfo.hpp" +#include "CbcPartialNodeInfo.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiCuts; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinWarmStartBasis; +class CbcCountRowCut; +class CbcModel; +class CbcNode; +class CbcSubProblem; +class CbcGeneralBranchingObject; + +/** Information required while the node is live + + When a subproblem is initially created, it is represented by an CbcNode + object and an attached CbcNodeInfo object. + + The CbcNode contains information (depth, branching instructions), that's + needed while the subproblem remains `live', i.e., while the + subproblem is not fathomed and there are branch arms still be be + evaluated. The CbcNode is deleted when the last branch arm has been + evaluated. + + The CbcNodeInfo object contains the information needed to maintain the + search tree and recreate the subproblem for the node. It remains in + existence until there are no nodes remaining in the subtree rooted at this + node. +*/ + +class CbcNode : public CoinTreeNode { + +public: + /// Default Constructor + CbcNode(); + + /// Construct and increment parent reference count + CbcNode(CbcModel *model, CbcNode *lastNode); + + /// Copy constructor + CbcNode(const CbcNode &); + + /// Assignment operator + CbcNode &operator=(const CbcNode &rhs); + + /// Destructor + ~CbcNode(); + + /** Create a description of the subproblem at this node + + The CbcNodeInfo structure holds the information (basis & variable bounds) + required to recreate the subproblem for this node. It also links the node + to its parent (via the parent's CbcNodeInfo object). + + If lastNode == NULL, a CbcFullNodeInfo object will be created. All + parameters except \p model are unused. + + If lastNode != NULL, a CbcPartialNodeInfo object will be created. Basis and + bounds information will be stored in the form of differences between the + parent subproblem and this subproblem. + (More precisely, \p lastws, \p lastUpper, \p lastLower, + \p numberOldActiveCuts, and \p numberNewCuts are used.) + */ + void + createInfo(CbcModel *model, + CbcNode *lastNode, + const CoinWarmStartBasis *lastws, + const double *lastLower, const double *lastUpper, + int numberOldActiveCuts, int numberNewCuts); + + /** Create a branching object for the node + + The routine scans the object list of the model and selects a set of + unsatisfied objects as candidates for branching. The candidates are + evaluated, and an appropriate branch object is installed. + + The numberPassesLeft is decremented to stop fixing one variable each time + and going on and on (e.g. for stock cutting, air crew scheduling) + + If evaluation determines that an object is monotone or infeasible, + the routine returns immediately. In the case of a monotone object, + the branch object has already been called to modify the model. + + Return value: +
    +
  • 0: A branching object has been installed +
  • -1: A monotone object was discovered +
  • -2: An infeasible object was discovered +
+ */ + int chooseBranch(CbcModel *model, + CbcNode *lastNode, + int numberPassesLeft); + /** Create a branching object for the node - when dynamic pseudo costs + + The routine scans the object list of the model and selects a set of + unsatisfied objects as candidates for branching. The candidates are + evaluated, and an appropriate branch object is installed. + This version gives preference in evaluation to variables which + have not been evaluated many times. It also uses numberStrong + to say give up if last few tries have not changed incumbent. + See Achterberg, Koch and Martin. + + The numberPassesLeft is decremented to stop fixing one variable each time + and going on and on (e.g. for stock cutting, air crew scheduling) + + If evaluation determines that an object is monotone or infeasible, + the routine returns immediately. In the case of a monotone object, + the branch object has already been called to modify the model. + + Return value: +
    +
  • 0: A branching object has been installed +
  • -1: A monotone object was discovered +
  • -2: An infeasible object was discovered +
  • >0: Number of quich branching objects (and branches will be non NULL) +
+ */ + int chooseDynamicBranch(CbcModel *model, + CbcNode *lastNode, + OsiSolverBranch *&branches, + int numberPassesLeft); + /** Create a branching object for the node + + The routine scans the object list of the model and selects a set of + unsatisfied objects as candidates for branching. The candidates are + evaluated, and an appropriate branch object is installed. + + The numberPassesLeft is decremented to stop fixing one variable each time + and going on and on (e.g. for stock cutting, air crew scheduling) + + If evaluation determines that an object is monotone or infeasible, + the routine returns immediately. In the case of a monotone object, + the branch object has already been called to modify the model. + + Return value: +
    +
  • 0: A branching object has been installed +
  • -1: A monotone object was discovered +
  • -2: An infeasible object was discovered +
+ Branch state: +
    +
  • -1: start +
  • -1: A monotone object was discovered +
  • -2: An infeasible object was discovered +
+ */ + int chooseOsiBranch(CbcModel *model, + CbcNode *lastNode, + OsiBranchingInformation *usefulInfo, + int branchState); + /** Create a branching object for the node + + The routine scans the object list of the model and selects a set of + unsatisfied objects as candidates for branching. It then solves a + series of problems and a CbcGeneral branch object is installed. + + If evaluation determines that an object is infeasible, + the routine returns immediately. + + Return value: +
    +
  • 0: A branching object has been installed +
  • -2: An infeasible object was discovered +
+ */ + int chooseClpBranch(CbcModel *model, + CbcNode *lastNode); + int analyze(CbcModel *model, double *results); + /// Decrement active cut counts + void decrementCuts(int change = 1); + + /// Decrement all active cut counts in chain starting at parent + void decrementParentCuts(CbcModel *model, int change = 1); + + /// Nulls out node info + void nullNodeInfo(); + /** Initialize reference counts in attached CbcNodeInfo + + This is a convenience routine, which will initialize the reference counts + in the attached CbcNodeInfo object based on the attached + OsiBranchingObject. + + \sa CbcNodeInfo::initializeInfo(int). + */ + void initializeInfo(); + + /// Does next branch and updates state + int branch(OsiSolverInterface *solver); + + /** Double checks in case node can change its mind! + Returns objective value + Can change objective etc */ + double checkIsCutoff(double cutoff); + // Information to make basis and bounds + inline CbcNodeInfo *nodeInfo() const + { + return nodeInfo_; + } + + // Objective value + inline double objectiveValue() const + { + return objectiveValue_; + } + inline void setObjectiveValue(double value) + { + objectiveValue_ = value; + } + /// Number of arms defined for the attached OsiBranchingObject. + inline int numberBranches() const + { + if (branch_) + return (branch_->numberBranches()); + else + return (-1); + } + + /* Active arm of the attached OsiBranchingObject. + + In the simplest instance, coded -1 for the down arm of the branch, +1 for + the up arm. But see OsiBranchingObject::way() + Use nodeInfo--.numberBranchesLeft_ to see how active + */ + int way() const; + /// Depth in branch-and-cut search tree + inline int depth() const + { + return depth_; + } + /// Set depth in branch-and-cut search tree + inline void setDepth(int value) + { + depth_ = value; + } + /// Get the number of objects unsatisfied at this node. + inline int numberUnsatisfied() const + { + return numberUnsatisfied_; + } + /// Set the number of objects unsatisfied at this node. + inline void setNumberUnsatisfied(int value) + { + numberUnsatisfied_ = value; + } + /// Get sum of "infeasibilities" reported by each object + inline double sumInfeasibilities() const + { + return sumInfeasibilities_; + } + /// Set sum of "infeasibilities" reported by each object + inline void setSumInfeasibilities(double value) + { + sumInfeasibilities_ = value; + } + // Guessed objective value (for solution) + inline double guessedObjectiveValue() const + { + return guessedObjectiveValue_; + } + inline void setGuessedObjectiveValue(double value) + { + guessedObjectiveValue_ = value; + } + /// Branching object for this node + inline const OsiBranchingObject *branchingObject() const + { + return branch_; + } + /// Modifiable branching object for this node + inline OsiBranchingObject *modifiableBranchingObject() const + { + return branch_; + } + /// Set branching object for this node (takes ownership) + inline void setBranchingObject(OsiBranchingObject *branchingObject) + { + branch_ = branchingObject; + } + /// The node number + inline int nodeNumber() const + { + return nodeNumber_; + } + inline void setNodeNumber(int node) + { + nodeNumber_ = node; + } + /// Returns true if on tree + inline bool onTree() const + { + return (state_ & 1) != 0; + } + /// Sets true if on tree + inline void setOnTree(bool yesNo) + { + if (yesNo) + state_ |= 1; + else + state_ &= ~1; + } + /// Returns true if active + inline bool active() const + { + return (state_ & 2) != 0; + } + /// Sets true if active + inline void setActive(bool yesNo) + { + if (yesNo) + state_ |= 2; + else + state_ &= ~2; + } + /// Get state (really for debug) + inline int getState() const + { + return state_; + } + /// Set state (really for debug) + inline void setState(int value) + { + state_ = value; + } + /// Print + void print() const; + /// Debug + inline void checkInfo() const + { + assert(nodeInfo_->numberBranchesLeft() == branch_->numberBranchesLeft()); + } + +private: + // Data + /// Information to make basis and bounds + CbcNodeInfo *nodeInfo_; + /// Objective value + double objectiveValue_; + /// Guessed satisfied Objective value + double guessedObjectiveValue_; + /// Sum of "infeasibilities" reported by each object + double sumInfeasibilities_; + /// Branching object for this node + OsiBranchingObject *branch_; + /// Depth of the node in the search tree + int depth_; + /// The number of objects unsatisfied at this node. + int numberUnsatisfied_; + /// The node number + int nodeNumber_; + /** State + 1 - on tree + 2 - active + */ + int state_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNodeInfo.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNodeInfo.hpp new file mode 100644 index 000000000..37dd858d1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcNodeInfo.hpp @@ -0,0 +1,377 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/24/09 carved from CbcNode + +#ifndef CbcNodeInfo_H +#define CbcNodeInfo_H + +#include +#include + +#include "CoinWarmStartBasis.hpp" +#include "CoinSearchTree.hpp" +#include "CbcBranchBase.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiCuts; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinWarmStartBasis; +class CbcCountRowCut; +class CbcModel; +class CbcNode; +class CbcSubProblem; +class CbcGeneralBranchingObject; + +//############################################################################# +/** Information required to recreate the subproblem at this node + + When a subproblem is initially created, it is represented by a CbcNode + object and an attached CbcNodeInfo object. + + The CbcNode contains information needed while the subproblem remains live. + The CbcNode is deleted when the last branch arm has been evaluated. + + The CbcNodeInfo contains information required to maintain the branch-and-cut + search tree structure (links and reference counts) and to recreate the + subproblem for this node (basis, variable bounds, cutting planes). A + CbcNodeInfo object remains in existence until all nodes have been pruned from + the subtree rooted at this node. + + The principle used to maintain the reference count is that the reference + count is always the sum of all potential and actual children of the node. + Specifically, +
    +
  • Once it's determined how the node will branch, the reference count + is set to the number of potential children (i.e., the number + of arms of the branch). +
  • As each child is created by CbcNode::branch() (converting a potential + child to the active subproblem), the reference count is decremented. +
  • If the child survives and will become a node in the search tree + (converting the active subproblem into an actual child), increment the + reference count. +
+ Notice that the active subproblem lives in a sort of limbo, neither a + potential or an actual node in the branch-and-cut tree. + + CbcNodeInfo objects come in two flavours. A CbcFullNodeInfo object contains + a full record of the information required to recreate a subproblem. + A CbcPartialNodeInfo object expresses this information in terms of + differences from the parent. +*/ + +class CbcNodeInfo { + +public: + /** \name Constructors & destructors */ + //@{ + /** Default Constructor + + Creates an empty NodeInfo object. + */ + CbcNodeInfo(); + + /// Copy constructor + CbcNodeInfo(const CbcNodeInfo &); + +#ifdef JJF_ZERO + /** Construct with parent + + Creates a NodeInfo object which knows its parent and assumes it will + in turn have two children. + */ + CbcNodeInfo(CbcNodeInfo *parent); +#endif + + /** Construct with parent and owner + + As for `construct with parent', and attached to \p owner. + */ + CbcNodeInfo(CbcNodeInfo *parent, CbcNode *owner); + + /** Destructor + + Note that the destructor will recursively delete the parent if this + nodeInfo is the last child. + */ + virtual ~CbcNodeInfo(); + //@} + + /** \brief Modify model according to information at node + + The routine modifies the model according to bound and basis + information at node and adds any cuts to the addCuts array. + */ + virtual void applyToModel(CbcModel *model, CoinWarmStartBasis *&basis, + CbcCountRowCut **addCuts, + int ¤tNumberCuts) const = 0; + /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) + virtual int applyBounds(int iColumn, double &lower, double &upper, int force) = 0; + + /** Builds up row basis backwards (until original model). + Returns NULL or previous one to apply . + Depends on Free being 0 and impossible for cuts + */ + virtual CbcNodeInfo *buildRowBasis(CoinWarmStartBasis &basis) const = 0; + /// Clone + virtual CbcNodeInfo *clone() const = 0; + /// Called when number branches left down to zero + virtual void allBranchesGone() {} +#ifndef JJF_ONE + /// Increment number of references + inline void increment(int amount = 1) + { + numberPointingToThis_ += amount; /*printf("CbcNodeInfo %x incremented by %d to %d\n",this,amount,numberPointingToThis_);*/ + } + + /// Decrement number of references and return number left + inline int decrement(int amount = 1) + { + numberPointingToThis_ -= amount; /*printf("CbcNodeInfo %x decremented by %d to %d\n",this,amount,numberPointingToThis_);*/ + return numberPointingToThis_; + } +#else + /// Increment number of references + void increment(int amount = 1); + /// Decrement number of references and return number left + int decrement(int amount = 1); +#endif + /** Initialize reference counts + + Initialize the reference counts used for tree maintenance. + */ + + inline void initializeInfo(int number) + { + numberPointingToThis_ = number; + numberBranchesLeft_ = number; + } + + /// Return number of branches left in object + inline int numberBranchesLeft() const + { + return numberBranchesLeft_; + } + + /// Set number of branches left in object + inline void setNumberBranchesLeft(int value) + { + numberBranchesLeft_ = value; + } + + /// Return number of objects pointing to this + inline int numberPointingToThis() const + { + return numberPointingToThis_; + } + + /// Set number of objects pointing to this + inline void setNumberPointingToThis(int number) + { + numberPointingToThis_ = number; + } + + /// Increment number of objects pointing to this + inline void incrementNumberPointingToThis() + { + numberPointingToThis_++; + } + + /// Say one branch taken + inline int branchedOn() + { + numberPointingToThis_--; + numberBranchesLeft_--; + return numberBranchesLeft_; + } + + /// Say thrown away + inline void throwAway() + { + numberPointingToThis_ -= numberBranchesLeft_; + numberBranchesLeft_ = 0; + } + + /// Parent of this + CbcNodeInfo *parent() const + { + return parent_; + } + /// Set parent null + inline void nullParent() + { + parent_ = NULL; + } + + void addCuts(OsiCuts &cuts, int numberToBranch, //int * whichGenerator, + int numberPointingToThis); + void addCuts(int numberCuts, CbcCountRowCut **cuts, int numberToBranch); + /** Delete cuts (decrements counts) + Slow unless cuts in same order as saved + */ + void deleteCuts(int numberToDelete, CbcCountRowCut **cuts); + void deleteCuts(int numberToDelete, int *which); + + /// Really delete a cut + void deleteCut(int whichOne); + + /// Decrement active cut counts + void decrementCuts(int change = 1); + + /// Increment active cut counts + void incrementCuts(int change = 1); + + /// Decrement all active cut counts in chain starting at parent + void decrementParentCuts(CbcModel *model, int change = 1); + + /// Increment all active cut counts in parent chain + void incrementParentCuts(CbcModel *model, int change = 1); + + /// Array of pointers to cuts + inline CbcCountRowCut **cuts() const + { + return cuts_; + } + + /// Number of row cuts (this node) + inline int numberCuts() const + { + return numberCuts_; + } + inline void setNumberCuts(int value) + { + numberCuts_ = value; + } + + /// Set owner null + inline void nullOwner() + { + owner_ = NULL; + } + const inline CbcNode *owner() const + { + return owner_; + } + inline CbcNode *mutableOwner() const + { + return owner_; + } + /// The node number + inline int nodeNumber() const + { + return nodeNumber_; + } + inline void setNodeNumber(int node) + { + nodeNumber_ = node; + } + /** Deactivate node information. + 1 - bounds + 2 - cuts + 4 - basis! + 8 - just marked + 16 - symmetry branching worked + */ + void deactivate(int mode = 3); + /// Say if normal + inline bool allActivated() const + { + return ((active_ & 7) == 7); + } + /// Say if marked + inline bool marked() const + { + return ((active_ & 8) != 0); + } + /// Mark + inline void mark() + { + active_ |= 8; + } + /// Unmark + inline void unmark() + { + active_ &= ~8; + } + /// Get symmetry value (true worked at this node) + inline bool symmetryWorked() const + { + return (active_ & 16) != 0; + } + /// Say symmetry worked at this node) + inline void setSymmetryWorked() + { + active_ |= 16; + } + + /// Branching object for the parent + inline const OsiBranchingObject *parentBranch() const + { + return parentBranch_; + } + /// If we need to take off parent based data + void unsetParentBasedData(); + +protected: + /** Number of other nodes pointing to this node. + + Number of existing and potential search tree nodes pointing to this node. + `Existing' means referenced by #parent_ of some other CbcNodeInfo. + `Potential' means children still to be created (#numberBranchesLeft_ of + this CbcNodeInfo). + */ + int numberPointingToThis_; + + /// parent + CbcNodeInfo *parent_; + + /// Copy of the branching object of the parent when the node is created + OsiBranchingObject *parentBranch_; + + /// Owner + CbcNode *owner_; + + /// Number of row cuts (this node) + int numberCuts_; + + /// The node number + int nodeNumber_; + + /// Array of pointers to cuts + CbcCountRowCut **cuts_; + + /** Number of rows in problem (before these cuts). This + means that for top of chain it must be rows at continuous */ + int numberRows_; + + /** Number of branch arms left to explore at this node + + \todo There seems to be redundancy between this field and + CbcBranchingObject::numberBranchesLeft_. It'd be good to sort out if + both are necessary. + */ + int numberBranchesLeft_; + /** Active node information. + 1 - bounds + 2 - cuts + 4 - basis! + */ + int active_; + +private: + /// Illegal Assignment operator + CbcNodeInfo &operator=(const CbcNodeInfo &rhs); + + /// routine common to constructors + void setParentBasedData(); +}; + +#endif // CbcNodeInfo_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObject.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObject.hpp new file mode 100644 index 000000000..ed591e2c4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObject.hpp @@ -0,0 +1,288 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/12/2009 carved from CbcBranchBase + +#ifndef CbcObject_H +#define CbcObject_H + +#include +#include +#include "OsiBranchingObject.hpp" +class OsiSolverInterface; +class OsiSolverBranch; + +class CbcModel; +class CbcNode; +class CbcNodeInfo; +class CbcBranchingObject; +class OsiChooseVariable; +class CbcObjectUpdateData; +//############################################################################# + +/** Abstract base class for `objects'. + It now just has stuff that OsiObject does not have + + The branching model used in Cbc is based on the idea of an object. + In the abstract, an object is something that has a feasible region, can be + evaluated for infeasibility, can be branched on (i.e., there's some + constructive action to be taken to move toward feasibility), and allows + comparison of the effect of branching. + + This class (CbcObject) is the base class for an object. To round out the + branching model, the class CbcBranchingObject describes how to perform a + branch, and the class CbcBranchDecision describes how to compare two + CbcBranchingObjects. + + To create a new type of object you need to provide three methods: + #infeasibility(), #feasibleRegion(), and #createCbcBranch(), described below. + + This base class is primarily virtual to allow for any form of structure. + Any form of discontinuity is allowed. + + \todo The notion that all branches are binary (two arms) is wired into the + implementation of CbcObject, CbcBranchingObject, and + CbcBranchDecision. Changing this will require a moderate amount of + recoding. + */ +// This can be used if object wants to skip strong branching +typedef struct { + CbcBranchingObject *possibleBranch; // what a branch would do + double upMovement; // cost going up (and initial away from feasible) + double downMovement; // cost going down + int numIntInfeasUp; // without odd ones + int numObjInfeasUp; // just odd ones + bool finishedUp; // true if solver finished + int numItersUp; // number of iterations in solver + int numIntInfeasDown; // without odd ones + int numObjInfeasDown; // just odd ones + bool finishedDown; // true if solver finished + int numItersDown; // number of iterations in solver + int objectNumber; // Which object it is + int fix; // 0 if no fix, 1 if we can fix up, -1 if we can fix down +} CbcStrongInfo; + +class CbcObject : public OsiObject { + +public: + // Default Constructor + CbcObject(); + + // Useful constructor + CbcObject(CbcModel *model); + + // Copy constructor + CbcObject(const CbcObject &); + + // Assignment operator + CbcObject &operator=(const CbcObject &rhs); + + /// Clone + virtual CbcObject *clone() const = 0; + + /// Destructor + virtual ~CbcObject(); + + /** Infeasibility of the object + + This is some measure of the infeasibility of the object. It should be + scaled to be in the range [0.0, 0.5], with 0.0 indicating the object + is satisfied. + + The preferred branching direction is returned in preferredWay, + + This is used to prepare for strong branching but should also think of + case when no strong branching + + The object may also compute an estimate of cost of going "up" or "down". + This will probably be based on pseudo-cost ideas + */ +#ifdef CBC_NEW_STYLE_BRANCH + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const = 0; +#else + virtual double infeasibility(const OsiBranchingInformation * /*info*/, + int &preferredWay) const + { + return infeasibility(preferredWay); + } + virtual double infeasibility(int & /*preferredWay*/) const + { + throw CoinError("Need code", "infeasibility", "CbcBranchBase"); + } +#endif + + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + */ + virtual void feasibleRegion() = 0; + /// Dummy one for compatibility + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + Returns measure of how much it had to move solution to make feasible + */ + virtual double feasibleRegion(OsiSolverInterface *solver) const; + + /** Create a branching object and indicate which way to branch first. + + The branching object has to know how to create branches (fix + variables, etc.) + */ +#ifdef CBC_NEW_STYLE_BRANCH + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) = 0; +#else + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface * + /* solver */, + const OsiBranchingInformation * + /* info */, + int /* way */) + { + // return createBranch(solver, info, way); + return NULL; + } + virtual OsiBranchingObject *createBranch(OsiSolverInterface * /*solver*/, + const OsiBranchingInformation * /*info*/, int /*way*/) const + { + throw CoinError("Need code", "createBranch", "CbcBranchBase"); + } +#endif + /** Create an Osibranching object and indicate which way to branch first. + + The branching object has to know how to create branches (fix + variables, etc.) + */ + virtual OsiBranchingObject *createOsiBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + /** Create an OsiSolverBranch object + + This returns NULL if branch not represented by bound changes + */ + virtual OsiSolverBranch *solverBranch() const; + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in a good direction. + + If the method cannot generate a feasible point (because there aren't + any, or because it isn't bright enough to find one), it should + return null. + */ + virtual CbcBranchingObject *preferredNewFeasible() const + { + return NULL; + } + + /** \brief Given a valid solution (with reduced costs, etc.), + return a branching object which would give a new feasible + point in a bad direction. + + If the method cannot generate a feasible point (because there aren't + any, or because it isn't bright enough to find one), it should + return null. + */ + virtual CbcBranchingObject *notPreferredNewFeasible() const + { + return NULL; + } + + /** Reset variable bounds to their original values. + + Bounds may be tightened, so it may be good to be able to set this info in object. + */ + virtual void resetBounds(const OsiSolverInterface *) {} + + /** Returns floor and ceiling i.e. closest valid points + */ + virtual void floorCeiling(double &floorValue, double &ceilingValue, double value, + double tolerance) const; + + /** Pass in information on branch just done and create CbcObjectUpdateData instance. + If object does not need data then backward pointer will be NULL. + Assumes can get information from solver */ + virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface *solver, + const CbcNode *node, + const CbcBranchingObject *branchingObject); + + /// Update object by CbcObjectUpdateData + virtual void updateInformation(const CbcObjectUpdateData &) {} + + /// Identifier (normally column number in matrix) + inline int id() const + { + return id_; + } + + /** Set identifier (normally column number in matrix) + but 1000000000 to 1100000000 means optional branching object + i.e. code would work without it */ + inline void setId(int value) + { + id_ = value; + } + + /** Return true if optional branching object + i.e. code would work without it */ + inline bool optionalObject() const + { + return (id_ >= 1000000000 && id_ < 1100000000); + } + + /// Get position in object_ list + inline int position() const + { + return position_; + } + + /// Set position in object_ list + inline void setPosition(int position) + { + position_ = position; + } + + /// update model + inline void setModel(CbcModel *model) + { + model_ = model; + } + + /// Return model + inline CbcModel *model() const + { + return model_; + } + + /// If -1 down always chosen first, +1 up always, 0 normal + inline int preferredWay() const + { + return preferredWay_; + } + /// Set -1 down always chosen first, +1 up always, 0 normal + inline void setPreferredWay(int value) + { + preferredWay_ = value; + } + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *, int, const int *) {} + /// Initialize for branching + virtual void initializeForBranching(CbcModel *) {} + +protected: + /// data + + /// Model + CbcModel *model_; + /// Identifier (normally column number in matrix) + int id_; + /// Position in object list + int position_; + /// If -1 down always chosen first, +1 up always, 0 normal + int preferredWay_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObjectUpdateData.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObjectUpdateData.hpp new file mode 100644 index 000000000..d5861f805 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcObjectUpdateData.hpp @@ -0,0 +1,63 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/12/2009 carved from CbcBranchBase + +#ifndef CbcObjectUpdateData_H +#define CbcObjectUpdateData_H + +#include "CbcObject.hpp" +/* This stores data so an object can be updated + */ +class CbcObjectUpdateData { + +public: + /// Default Constructor + CbcObjectUpdateData(); + + /// Useful constructor + CbcObjectUpdateData(CbcObject *object, + int way, + double change, + int status, + int intDecrease_, + double branchingValue); + + /// Copy constructor + CbcObjectUpdateData(const CbcObjectUpdateData &); + + /// Assignment operator + CbcObjectUpdateData &operator=(const CbcObjectUpdateData &rhs); + + /// Destructor + virtual ~CbcObjectUpdateData(); + +public: + /// data + + /// Object + CbcObject *object_; + /// Branch as defined by instance of CbcObject + int way_; + /// Object number + int objectNumber_; + /// Change in objective + double change_; + /// Status 0 Optimal, 1 infeasible, 2 unknown + int status_; + /// Decrease in number unsatisfied + int intDecrease_; + /// Branching value + double branchingValue_; + /// Objective value before branching + double originalObjective_; + /// Current cutoff + double cutoff_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.cpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.cpp new file mode 100644 index 000000000..aea85d92e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.cpp @@ -0,0 +1,4321 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#include "CoinPragma.hpp" +#include "CoinTime.hpp" +#include "CbcOrClpParam.hpp" + +#include +#include +#include + +#ifdef COIN_HAS_CBC +#ifdef COIN_HAS_CLP +#include "OsiClpSolverInterface.hpp" +#include "ClpSimplex.hpp" +#endif +#include "CbcModel.hpp" +#endif +#include "CoinHelperFunctions.hpp" +#ifdef COIN_HAS_CLP +#include "ClpSimplex.hpp" +#include "ClpFactorization.hpp" +#endif +#ifdef COIN_HAS_READLINE +#include +#include +#endif +#ifdef COIN_HAS_CBC +// from CoinSolve +static char coin_prompt[] = "Coin:"; +#else +static char coin_prompt[] = "Clp:"; +#endif +#ifdef CLP_CILK +#ifndef CBC_THREAD +#define CBC_THREAD +#endif +#endif +#if defined(COIN_HAS_WSMP) && !defined(USE_EKKWSSMP) +#ifndef CBC_THREAD +#define CBC_THREAD +#endif +#endif +#include "ClpConfig.h" +#ifdef CLP_HAS_ABC +#include "AbcCommon.hpp" +#endif +static bool doPrinting = true; +static std::string afterEquals = ""; +static char printArray[250]; +#if COIN_INT_MAX == 0 +#undef COIN_INT_MAX +#define COIN_INT_MAX 2147483647 +#endif +#if FLUSH_PRINT_BUFFER > 2 +int coinFlushBufferFlag = 0; +#endif +void setCbcOrClpPrinting(bool yesNo) +{ + doPrinting = yesNo; +} +//############################################################################# +// Constructors / Destructor / Assignment +//############################################################################# + +//------------------------------------------------------------------- +// Default Constructor +//------------------------------------------------------------------- +CbcOrClpParam::CbcOrClpParam() + : type_(CBC_PARAM_NOTUSED_INVALID) + , lowerDoubleValue_(0.0) + , upperDoubleValue_(0.0) + , lowerIntValue_(0) + , upperIntValue_(0) + , lengthName_(0) + , lengthMatch_(0) + , definedKeyWords_() + , name_() + , shortHelp_() + , longHelp_() + , action_(CBC_PARAM_NOTUSED_INVALID) + , currentKeyWord_(-1) + , display_(0) + , intValue_(-1) + , doubleValue_(-1.0) + , stringValue_("") + , whereUsed_(7) + , fakeKeyWord_(-1) + , fakeValue_(0) +{ +} +// Other constructors +CbcOrClpParam::CbcOrClpParam(std::string name, std::string help, + double lower, double upper, CbcOrClpParameterType type, + int display) + : type_(type) + , lowerIntValue_(0) + , upperIntValue_(0) + , definedKeyWords_() + , name_(name) + , shortHelp_(help) + , longHelp_() + , action_(type) + , currentKeyWord_(-1) + , display_(display) + , intValue_(-1) + , doubleValue_(-1.0) + , stringValue_("") + , whereUsed_(7) + , fakeKeyWord_(-1) + , fakeValue_(0) +{ + lowerDoubleValue_ = lower; + upperDoubleValue_ = upper; + gutsOfConstructor(); +} +CbcOrClpParam::CbcOrClpParam(std::string name, std::string help, + int lower, int upper, CbcOrClpParameterType type, + int display) + : type_(type) + , lowerDoubleValue_(0.0) + , upperDoubleValue_(0.0) + , definedKeyWords_() + , name_(name) + , shortHelp_(help) + , longHelp_() + , action_(type) + , currentKeyWord_(-1) + , display_(display) + , intValue_(-1) + , doubleValue_(-1.0) + , stringValue_("") + , whereUsed_(7) + , fakeKeyWord_(-1) + , fakeValue_(0) +{ + gutsOfConstructor(); + lowerIntValue_ = lower; + upperIntValue_ = upper; +} +// Other strings will be added by append +CbcOrClpParam::CbcOrClpParam(std::string name, std::string help, + std::string firstValue, + CbcOrClpParameterType type, int whereUsed, + int display) + : type_(type) + , lowerDoubleValue_(0.0) + , upperDoubleValue_(0.0) + , lowerIntValue_(0) + , upperIntValue_(0) + , definedKeyWords_() + , name_(name) + , shortHelp_(help) + , longHelp_() + , action_(type) + , currentKeyWord_(0) + , display_(display) + , intValue_(-1) + , doubleValue_(-1.0) + , stringValue_("") + , whereUsed_(whereUsed) + , fakeKeyWord_(-1) + , fakeValue_(0) +{ + gutsOfConstructor(); + definedKeyWords_.push_back(firstValue); +} +// Action +CbcOrClpParam::CbcOrClpParam(std::string name, std::string help, + CbcOrClpParameterType type, int whereUsed, + int display) + : type_(type) + , lowerDoubleValue_(0.0) + , upperDoubleValue_(0.0) + , lowerIntValue_(0) + , upperIntValue_(0) + , definedKeyWords_() + , name_(name) + , shortHelp_(help) + , longHelp_() + , action_(type) + , currentKeyWord_(-1) + , display_(display) + , intValue_(-1) + , doubleValue_(-1.0) + , stringValue_("") + , fakeKeyWord_(-1) + , fakeValue_(0) +{ + whereUsed_ = whereUsed; + gutsOfConstructor(); +} + +//------------------------------------------------------------------- +// Copy constructor +//------------------------------------------------------------------- +CbcOrClpParam::CbcOrClpParam(const CbcOrClpParam &rhs) +{ + type_ = rhs.type_; + lowerDoubleValue_ = rhs.lowerDoubleValue_; + upperDoubleValue_ = rhs.upperDoubleValue_; + lowerIntValue_ = rhs.lowerIntValue_; + upperIntValue_ = rhs.upperIntValue_; + lengthName_ = rhs.lengthName_; + lengthMatch_ = rhs.lengthMatch_; + definedKeyWords_ = rhs.definedKeyWords_; + name_ = rhs.name_; + shortHelp_ = rhs.shortHelp_; + longHelp_ = rhs.longHelp_; + action_ = rhs.action_; + currentKeyWord_ = rhs.currentKeyWord_; + display_ = rhs.display_; + intValue_ = rhs.intValue_; + doubleValue_ = rhs.doubleValue_; + stringValue_ = rhs.stringValue_; + whereUsed_ = rhs.whereUsed_; + fakeKeyWord_ = rhs.fakeKeyWord_; + fakeValue_ = rhs.fakeValue_; +} + +//------------------------------------------------------------------- +// Destructor +//------------------------------------------------------------------- +CbcOrClpParam::~CbcOrClpParam() +{ +} + +//---------------------------------------------------------------- +// Assignment operator +//------------------------------------------------------------------- +CbcOrClpParam & +CbcOrClpParam::operator=(const CbcOrClpParam &rhs) +{ + if (this != &rhs) { + type_ = rhs.type_; + lowerDoubleValue_ = rhs.lowerDoubleValue_; + upperDoubleValue_ = rhs.upperDoubleValue_; + lowerIntValue_ = rhs.lowerIntValue_; + upperIntValue_ = rhs.upperIntValue_; + lengthName_ = rhs.lengthName_; + lengthMatch_ = rhs.lengthMatch_; + definedKeyWords_ = rhs.definedKeyWords_; + name_ = rhs.name_; + shortHelp_ = rhs.shortHelp_; + longHelp_ = rhs.longHelp_; + action_ = rhs.action_; + currentKeyWord_ = rhs.currentKeyWord_; + display_ = rhs.display_; + intValue_ = rhs.intValue_; + doubleValue_ = rhs.doubleValue_; + stringValue_ = rhs.stringValue_; + whereUsed_ = rhs.whereUsed_; + fakeKeyWord_ = rhs.fakeKeyWord_; + fakeValue_ = rhs.fakeValue_; + } + return *this; +} +void CbcOrClpParam::gutsOfConstructor() +{ + std::string::size_type shriekPos = name_.find('!'); + lengthName_ = static_cast< unsigned int >(name_.length()); + if (shriekPos == std::string::npos) { + //does not contain '!' + lengthMatch_ = lengthName_; + } else { + lengthMatch_ = static_cast< unsigned int >(shriekPos); + name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1); + lengthName_--; + } +} +// Sets value of fake keyword to current size of keywords +void CbcOrClpParam::setFakeKeyWord(int fakeValue) +{ + fakeKeyWord_ = static_cast< int >(definedKeyWords_.size()); + assert(fakeKeyWord_ > 0); + fakeValue_ = fakeValue; + assert(fakeValue_ >= 0); +} +/* Returns current parameter option position + but if fake keyword returns fakeValue_ +*/ +int CbcOrClpParam::currentOptionAsInteger() const +{ + int fakeInteger; + return currentOptionAsInteger(fakeInteger); +} +/* Returns current parameter option position + but if fake keyword returns fakeValue_ and sets + fakeInteger to value +*/ +int CbcOrClpParam::currentOptionAsInteger(int &fakeInteger) const +{ + fakeInteger = -COIN_INT_MAX; + if (fakeKeyWord_ < 0) { + return currentKeyWord_; + } else if (currentKeyWord_ >= 0 && currentKeyWord_ < fakeKeyWord_) { + return currentKeyWord_; + } else { + // fake + if (currentKeyWord_ < 0) + fakeInteger = currentKeyWord_ + 1000; + else + fakeInteger = currentKeyWord_ - 1000; + return fakeValue_; + } +} +// Returns length of name for printing +int CbcOrClpParam::lengthMatchName() const +{ + if (lengthName_ == lengthMatch_) + return lengthName_; + else + return lengthName_ + 2; +} +// Insert string (only valid for keywords) +void CbcOrClpParam::append(std::string keyWord) +{ + definedKeyWords_.push_back(keyWord); +} + +int CbcOrClpParam::matches(std::string input) const +{ + // look up strings to do more elegantly + if (input.length() > lengthName_) { + return 0; + } else { + unsigned int i; + for (i = 0; i < input.length(); i++) { + if (tolower(name_[i]) != tolower(input[i])) + break; + } + if (i < input.length()) { + return 0; + } else if (i >= lengthMatch_) { + return 1; + } else { + // matched but too short + return 2; + } + } +} +// Returns name which could match +std::string +CbcOrClpParam::matchName() const +{ + if (lengthMatch_ == lengthName_) + return name_; + else + return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")"; +} + +// Returns parameter option which matches (-1 if none) +int CbcOrClpParam::parameterOption(std::string check) const +{ + int numberItems = static_cast< int >(definedKeyWords_.size()); + if (!numberItems) { + return -1; + } else { + int whichItem = 0; + unsigned int it; + for (it = 0; it < definedKeyWords_.size(); it++) { + std::string thisOne = definedKeyWords_[it]; + std::string::size_type shriekPos = thisOne.find('!'); + size_t length1 = thisOne.length(); + size_t length2 = length1; + if (shriekPos != std::string::npos) { + //contains '!' + length2 = shriekPos; + thisOne = thisOne.substr(0, shriekPos) + thisOne.substr(shriekPos + 1); + length1 = thisOne.length(); + } + if (check.length() <= length1 && length2 <= check.length()) { + unsigned int i; + for (i = 0; i < check.length(); i++) { + if (tolower(thisOne[i]) != tolower(check[i])) + break; + } + if (i < check.length()) { + whichItem++; + } else if (i >= length2) { + break; + } + } else { + whichItem++; + } + } + if (whichItem < numberItems) { + return whichItem; + } else { + if (fakeKeyWord_ <= 0) + return -1; + // allow plus or minus + int n; + if (check.substr(0, 4) == "plus" || check.substr(0, 4) == "PLUS") { + n = 4; + } else if (check.substr(0, 5) == "minus" || check.substr(0, 5) == "MINUS") { + n = 5; + } else { + return -1; + } + int value = 0; + std::string field = check.substr(n); + if (field != "EOL") { + const char *start = field.c_str(); + char *endPointer = NULL; + // check valid + value = static_cast< int >(strtol(start, &endPointer, 10)); + if (*endPointer != '\0') { + return -1; + } + if (n == 4) + return value + 1000; + else + return -value - 1000; + } else { + return -1; + } + } + } +} +// Prints parameter options +void CbcOrClpParam::printOptions() const +{ + std::cout << "= 0 && currentKeyWord_ < static_cast< int >(definedKeyWords_.size())); + std::string current = definedKeyWords_[currentKeyWord_]; + std::string::size_type shriekPos = current.find('!'); + if (shriekPos != std::string::npos) { + //contains '!' + current = current.substr(0, shriekPos) + "(" + current.substr(shriekPos + 1) + ")"; + } + std::cout << ";\n\tcurrent " << current << ">" << std::endl; +} +// Print action and string +void CbcOrClpParam::printString() const +{ + if (name_ == "directory") + std::cout << "Current working directory is " << stringValue_ << std::endl; + else if (name_.substr(0, 6) == "printM") + std::cout << "Current value of printMask is " << stringValue_ << std::endl; + else + std::cout << "Current default (if $ as parameter) for " << name_ + << " is " << stringValue_ << std::endl; +} +void CoinReadPrintit(const char *input) +{ + int length = static_cast< int >(strlen(input)); + assert(length <= 10000); + char temp[10001]; + int i; + int n = 0; + for (i = 0; i < length; i++) { + if (input[i] == '\n') { + temp[n] = '\0'; + std::cout << temp << std::endl; + n = 0; + } else if (n >= 65 && input[i] == ' ') { + temp[n] = '\0'; + std::cout << temp << std::endl; + n = 0; + } else if (n || input[i] != ' ') { + temp[n++] = input[i]; + } + } + if (n) { + temp[n] = '\0'; + std::cout << temp << std::endl; + } +} +// Print Long help +void CbcOrClpParam::printLongHelp() const +{ + if (type_ >= 1 && type_ < 600) { + CoinReadPrintit(longHelp_.c_str()); + if (type_ < CLP_PARAM_INT_SOLVERLOGLEVEL) { + printf("\n", lowerDoubleValue_, upperDoubleValue_, doubleValue_); + assert(upperDoubleValue_ > lowerDoubleValue_); + } else if (type_ < CLP_PARAM_STR_DIRECTION) { + printf("\n", lowerIntValue_, upperIntValue_, intValue_); + assert(upperIntValue_ > lowerIntValue_); + } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) { + printOptions(); + } + } +} +#ifdef COIN_HAS_CBC +int CbcOrClpParam::setDoubleParameter(OsiSolverInterface *model, double value) +{ + int returnCode; + setDoubleParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets double parameter and returns printable string and error code +const char * +CbcOrClpParam::setDoubleParameterWithMessage(OsiSolverInterface *model, double value, int &returnCode) +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + returnCode = 1; + } else { + double oldValue = doubleValue_; + doubleValue_ = value; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + model->getDblParam(OsiDualTolerance, oldValue); + model->setDblParam(OsiDualTolerance, value); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + model->getDblParam(OsiPrimalTolerance, oldValue); + model->setDblParam(OsiPrimalTolerance, value); + break; + default: + break; + } + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +#endif +#ifdef COIN_HAS_CLP +int CbcOrClpParam::setDoubleParameter(ClpSimplex *model, double value) +{ + int returnCode; + setDoubleParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets int parameter and returns printable string and error code +const char * +CbcOrClpParam::setDoubleParameterWithMessage(ClpSimplex *model, double value, int &returnCode) +{ + double oldValue = doubleValue_; + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + returnCode = 1; + } else { + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), oldValue, value); + returnCode = 0; + doubleValue_ = value; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + model->setDualTolerance(value); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + model->setPrimalTolerance(value); + break; + case CLP_PARAM_DBL_ZEROTOLERANCE: + model->setSmallElementValue(value); + break; + case CLP_PARAM_DBL_DUALBOUND: + model->setDualBound(value); + break; + case CLP_PARAM_DBL_PRIMALWEIGHT: + model->setInfeasibilityCost(value); + break; +#ifndef COIN_HAS_CBC + case CLP_PARAM_DBL_TIMELIMIT: + model->setMaximumSeconds(value); + break; +#endif + case CLP_PARAM_DBL_OBJSCALE: + model->setObjectiveScale(value); + break; + case CLP_PARAM_DBL_RHSSCALE: + model->setRhsScale(value); + break; + case CLP_PARAM_DBL_PRESOLVETOLERANCE: + model->setDblParam(ClpPresolveTolerance, value); + break; + default: + break; + } + } + return printArray; +} +double +CbcOrClpParam::doubleParameter(ClpSimplex *model) const +{ + double value; + switch (type_) { +#ifndef COIN_HAS_CBC + case CLP_PARAM_DBL_DUALTOLERANCE: + value = model->dualTolerance(); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + value = model->primalTolerance(); + break; +#endif + case CLP_PARAM_DBL_ZEROTOLERANCE: + value = model->getSmallElementValue(); + break; + case CLP_PARAM_DBL_DUALBOUND: + value = model->dualBound(); + break; + case CLP_PARAM_DBL_PRIMALWEIGHT: + value = model->infeasibilityCost(); + break; +#ifndef COIN_HAS_CBC + case CLP_PARAM_DBL_TIMELIMIT: + value = model->maximumSeconds(); + break; +#endif + case CLP_PARAM_DBL_OBJSCALE: + value = model->objectiveScale(); + break; + case CLP_PARAM_DBL_RHSSCALE: + value = model->rhsScale(); + break; + case CLP_PARAM_DBL_PRESOLVETOLERANCE: + value = model->presolveTolerance(); + break; + default: + value = doubleValue_; + break; + } + return value; +} +int CbcOrClpParam::setIntParameter(ClpSimplex *model, int value) +{ + int returnCode; + setIntParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets int parameter and returns printable string and error code +const char * +CbcOrClpParam::setIntParameterWithMessage(ClpSimplex *model, int value, int &returnCode) +{ + int oldValue = intValue_; + if (value < lowerIntValue_ || value > upperIntValue_) { + sprintf(printArray, "%d was provided for %s - valid range is %d to %d", + value, name_.c_str(), lowerIntValue_, upperIntValue_); + returnCode = 1; + } else { + intValue_ = value; + sprintf(printArray, "%s was changed from %d to %d", + name_.c_str(), oldValue, value); + returnCode = 0; + switch (type_) { + case CLP_PARAM_INT_SOLVERLOGLEVEL: + model->setLogLevel(value); + if (value > 2) + model->factorization()->messageLevel(8); + else + model->factorization()->messageLevel(0); + break; + case CLP_PARAM_INT_MAXFACTOR: + model->factorization()->maximumPivots(value); + break; + case CLP_PARAM_INT_PERTVALUE: + model->setPerturbation(value); + break; + case CLP_PARAM_INT_MAXITERATION: + model->setMaximumIterations(value); + break; + case CLP_PARAM_INT_SPECIALOPTIONS: + model->setSpecialOptions(value); + break; + case CLP_PARAM_INT_RANDOMSEED: { + if (value == 0) { + double time = fabs(CoinGetTimeOfDay()); + while (time >= COIN_INT_MAX) + time *= 0.5; + value = static_cast< int >(time); + sprintf(printArray, "using time of day %s was changed from %d to %d", + name_.c_str(), oldValue, value); + } + model->setRandomSeed(value); + } break; + case CLP_PARAM_INT_MORESPECIALOPTIONS: + model->setMoreSpecialOptions(value); + break; + case CLP_PARAM_INT_VECTOR_MODE: + model->setVectorMode(value); + break; +#ifndef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + model->setNumberThreads(value); + break; +#endif +#endif + default: + break; + } + } + return printArray; +} +int CbcOrClpParam::intParameter(ClpSimplex *model) const +{ + int value; + switch (type_) { +#ifndef COIN_HAS_CBC + case CLP_PARAM_INT_SOLVERLOGLEVEL: + value = model->logLevel(); + break; +#endif + case CLP_PARAM_INT_MAXFACTOR: + value = model->factorization()->maximumPivots(); + break; + break; + case CLP_PARAM_INT_PERTVALUE: + value = model->perturbation(); + break; + case CLP_PARAM_INT_MAXITERATION: + value = model->maximumIterations(); + break; + case CLP_PARAM_INT_SPECIALOPTIONS: + value = model->specialOptions(); + break; + case CLP_PARAM_INT_RANDOMSEED: + value = model->randomNumberGenerator()->getSeed(); + break; + case CLP_PARAM_INT_MORESPECIALOPTIONS: + value = model->moreSpecialOptions(); + break; + case CLP_PARAM_INT_VECTOR_MODE: + value = model->vectorMode(); + break; +#ifndef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + value = model->numberThreads(); + break; +#endif +#endif + default: + value = intValue_; + break; + } + return value; +} +#endif +int CbcOrClpParam::checkDoubleParameter(double value) const +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + return 1; + } else { + return 0; + } +} +#ifdef COIN_HAS_CBC +double +CbcOrClpParam::doubleParameter(OsiSolverInterface *model) const +{ + double value = 0.0; + switch (type_) { + case CLP_PARAM_DBL_DUALTOLERANCE: + model->getDblParam(OsiDualTolerance, value); + break; + case CLP_PARAM_DBL_PRIMALTOLERANCE: + model->getDblParam(OsiPrimalTolerance, value); + break; + default: + return doubleValue_; + break; + } + return value; +} +int CbcOrClpParam::setIntParameter(OsiSolverInterface *model, int value) +{ + int returnCode; + setIntParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets int parameter and returns printable string and error code +const char * +CbcOrClpParam::setIntParameterWithMessage(OsiSolverInterface *model, int value, int &returnCode) +{ + if (value < lowerIntValue_ || value > upperIntValue_) { + sprintf(printArray, "%d was provided for %s - valid range is %d to %d", + value, name_.c_str(), lowerIntValue_, upperIntValue_); + returnCode = 1; + } else { + int oldValue = intValue_; + intValue_ = oldValue; + switch (type_) { + case CLP_PARAM_INT_SOLVERLOGLEVEL: + model->messageHandler()->setLogLevel(value); + break; + default: + break; + } + sprintf(printArray, "%s was changed from %d to %d", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +int CbcOrClpParam::intParameter(OsiSolverInterface *model) const +{ + int value = 0; + switch (type_) { + case CLP_PARAM_INT_SOLVERLOGLEVEL: + value = model->messageHandler()->logLevel(); + break; + default: + value = intValue_; + break; + } + return value; +} +int CbcOrClpParam::setDoubleParameter(CbcModel &model, double value) +{ + int returnCode = 0; + setDoubleParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets double parameter and returns printable string and error code +const char * +CbcOrClpParam::setDoubleParameterWithMessage(CbcModel &model, double value, int &returnCode) +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + returnCode = 1; + } else { + double oldValue = doubleValue_; + doubleValue_ = value; + switch (type_) { + case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: + oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight); + model.setDblParam(CbcModel::CbcInfeasibilityWeight, value); + break; + case CBC_PARAM_DBL_INTEGERTOLERANCE: + oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance); + model.setDblParam(CbcModel::CbcIntegerTolerance, value); + break; + case CBC_PARAM_DBL_INCREMENT: + oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement); + model.setDblParam(CbcModel::CbcCutoffIncrement, value); + case CBC_PARAM_DBL_ALLOWABLEGAP: + oldValue = model.getDblParam(CbcModel::CbcAllowableGap); + model.setDblParam(CbcModel::CbcAllowableGap, value); + break; + case CBC_PARAM_DBL_GAPRATIO: + oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap); + model.setDblParam(CbcModel::CbcAllowableFractionGap, value); + break; + case CBC_PARAM_DBL_CUTOFF: + oldValue = model.getCutoff(); + model.setCutoff(value); + break; + case CBC_PARAM_DBL_TIMELIMIT_BAB: + oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds); + { + //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver()); + //ClpSimplex * lpSolver = clpSolver->getModelPtr(); + //lpSolver->setMaximumSeconds(value); + model.setDblParam(CbcModel::CbcMaximumSeconds, value); + } + break; + case CLP_PARAM_DBL_DUALTOLERANCE: + case CLP_PARAM_DBL_PRIMALTOLERANCE: + setDoubleParameter(model.solver(), value); + return 0; // to avoid message + default: + break; + } + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +double +CbcOrClpParam::doubleParameter(CbcModel &model) const +{ + double value; + switch (type_) { + case CBC_PARAM_DBL_INFEASIBILITYWEIGHT: + value = model.getDblParam(CbcModel::CbcInfeasibilityWeight); + break; + case CBC_PARAM_DBL_INTEGERTOLERANCE: + value = model.getDblParam(CbcModel::CbcIntegerTolerance); + break; + case CBC_PARAM_DBL_INCREMENT: + value = model.getDblParam(CbcModel::CbcCutoffIncrement); + break; + case CBC_PARAM_DBL_ALLOWABLEGAP: + value = model.getDblParam(CbcModel::CbcAllowableGap); + break; + case CBC_PARAM_DBL_GAPRATIO: + value = model.getDblParam(CbcModel::CbcAllowableFractionGap); + break; + case CBC_PARAM_DBL_CUTOFF: + value = model.getCutoff(); + break; + case CBC_PARAM_DBL_TIMELIMIT_BAB: + value = model.getDblParam(CbcModel::CbcMaximumSeconds); + break; + case CLP_PARAM_DBL_DUALTOLERANCE: + case CLP_PARAM_DBL_PRIMALTOLERANCE: + value = doubleParameter(model.solver()); + break; + default: + value = doubleValue_; + break; + } + return value; +} +int CbcOrClpParam::setIntParameter(CbcModel &model, int value) +{ + int returnCode; + setIntParameterWithMessage(model, value, returnCode); + if (doPrinting && strlen(printArray)) + std::cout << printArray << std::endl; + return returnCode; +} +// Sets int parameter and returns printable string and error code +const char * +CbcOrClpParam::setIntParameterWithMessage(CbcModel &model, int value, int &returnCode) +{ + if (value < lowerIntValue_ || value > upperIntValue_) { + sprintf(printArray, "%d was provided for %s - valid range is %d to %d", + value, name_.c_str(), lowerIntValue_, upperIntValue_); + returnCode = 1; + } else { + printArray[0] = '\0'; + if (value == intValue_) + return printArray; + int oldValue = intValue_; + intValue_ = value; + switch (type_) { + case CLP_PARAM_INT_LOGLEVEL: + oldValue = model.messageHandler()->logLevel(); + model.messageHandler()->setLogLevel(CoinAbs(value)); + break; + case CLP_PARAM_INT_SOLVERLOGLEVEL: + oldValue = model.solver()->messageHandler()->logLevel(); + model.solver()->messageHandler()->setLogLevel(value); + break; + case CBC_PARAM_INT_MAXNODES: + oldValue = model.getIntParam(CbcModel::CbcMaxNumNode); + model.setIntParam(CbcModel::CbcMaxNumNode, value); + break; + case CBC_PARAM_INT_MAXSOLS: + oldValue = model.getIntParam(CbcModel::CbcMaxNumSol); + model.setIntParam(CbcModel::CbcMaxNumSol, value); + break; + case CBC_PARAM_INT_MAXSAVEDSOLS: + oldValue = model.maximumSavedSolutions(); + model.setMaximumSavedSolutions(value); + break; + case CBC_PARAM_INT_STRONGBRANCHING: + oldValue = model.numberStrong(); + model.setNumberStrong(value); + break; + case CBC_PARAM_INT_NUMBERBEFORE: + oldValue = model.numberBeforeTrust(); + model.setNumberBeforeTrust(value); + break; + case CBC_PARAM_INT_NUMBERANALYZE: + oldValue = model.numberAnalyzeIterations(); + model.setNumberAnalyzeIterations(value); + break; + case CBC_PARAM_INT_CUTPASSINTREE: + oldValue = model.getMaximumCutPasses(); + model.setMaximumCutPasses(value); + break; + case CBC_PARAM_INT_CUTPASS: + oldValue = model.getMaximumCutPassesAtRoot(); + model.setMaximumCutPassesAtRoot(value); + break; +#ifdef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + oldValue = model.getNumberThreads(); + model.setNumberThreads(value); + break; +#endif + case CBC_PARAM_INT_RANDOMSEED: + oldValue = model.getRandomSeed(); + model.setRandomSeed(value); + break; +#endif + default: + break; + } + sprintf(printArray, "%s was changed from %d to %d", + name_.c_str(), oldValue, value); + returnCode = 0; + } + return printArray; +} +int CbcOrClpParam::intParameter(CbcModel &model) const +{ + int value; + switch (type_) { + case CLP_PARAM_INT_LOGLEVEL: + value = model.messageHandler()->logLevel(); + break; + case CLP_PARAM_INT_SOLVERLOGLEVEL: + value = model.solver()->messageHandler()->logLevel(); + break; + case CBC_PARAM_INT_MAXNODES: + value = model.getIntParam(CbcModel::CbcMaxNumNode); + break; + case CBC_PARAM_INT_MAXSOLS: + value = model.getIntParam(CbcModel::CbcMaxNumSol); + break; + case CBC_PARAM_INT_MAXSAVEDSOLS: + value = model.maximumSavedSolutions(); + break; + case CBC_PARAM_INT_STRONGBRANCHING: + value = model.numberStrong(); + break; + case CBC_PARAM_INT_NUMBERBEFORE: + value = model.numberBeforeTrust(); + break; + case CBC_PARAM_INT_NUMBERANALYZE: + value = model.numberAnalyzeIterations(); + break; + case CBC_PARAM_INT_CUTPASSINTREE: + value = model.getMaximumCutPasses(); + break; + case CBC_PARAM_INT_CUTPASS: + value = model.getMaximumCutPassesAtRoot(); + break; +#ifdef COIN_HAS_CBC +#ifdef CBC_THREAD + case CBC_PARAM_INT_THREADS: + value = model.getNumberThreads(); + break; +#endif + case CBC_PARAM_INT_RANDOMSEED: + value = model.getRandomSeed(); + break; +#endif + default: + value = intValue_; + break; + } + return value; +} +#endif +// Sets current parameter option using string +void CbcOrClpParam::setCurrentOption(const std::string value) +{ + int action = parameterOption(value); + if (action >= 0) + currentKeyWord_ = action; +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = action; +#endif +} +// Sets current parameter option +void CbcOrClpParam::setCurrentOption(int value, bool printIt) +{ + if (printIt && value != currentKeyWord_) + std::cout << "Option for " << name_ << " changed from " + << definedKeyWords_[currentKeyWord_] << " to " + << definedKeyWords_[value] << std::endl; + +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = value; +#endif + currentKeyWord_ = value; +} +// Sets current parameter option and returns printable string +const char * +CbcOrClpParam::setCurrentOptionWithMessage(int value) +{ + if (value != currentKeyWord_) { + char current[100]; + char newString[100]; + if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || currentKeyWord_ < fakeKeyWord_)) + strcpy(current, definedKeyWords_[currentKeyWord_].c_str()); + else if (currentKeyWord_ < 0) + sprintf(current, "minus%d", -currentKeyWord_ - 1000); + else + sprintf(current, "plus%d", currentKeyWord_ - 1000); + if (value >= 0 && (fakeKeyWord_ <= 0 || value < fakeKeyWord_)) + strcpy(newString, definedKeyWords_[value].c_str()); + else if (value < 0) + sprintf(newString, "minus%d", -value - 1000); + else + sprintf(newString, "plus%d", value - 1000); + sprintf(printArray, "Option for %s changed from %s to %s", + name_.c_str(), current, newString); +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = value; +#endif + currentKeyWord_ = value; + } else { + printArray[0] = '\0'; + } + return printArray; +} +// Sets current parameter option using string with message +const char * +CbcOrClpParam::setCurrentOptionWithMessage(const std::string value) +{ + int action = parameterOption(value); + char current[100]; + printArray[0] = '\0'; + if (action >= 0) { +#if FLUSH_PRINT_BUFFER > 2 + if (name_ == "bufferedMode") + coinFlushBufferFlag = action; +#endif + if (action == currentKeyWord_) + return NULL; + if (currentKeyWord_ >= 0 && (fakeKeyWord_ <= 0 || currentKeyWord_ < fakeKeyWord_)) + strcpy(current, definedKeyWords_[currentKeyWord_].c_str()); + else if (currentKeyWord_ < 0) + sprintf(current, "minus%d", -currentKeyWord_ - 1000); + else + sprintf(current, "plus%d", currentKeyWord_ - 1000); + sprintf(printArray, "Option for %s changed from %s to %s", + name_.c_str(), current, value.c_str()); + currentKeyWord_ = action; + } else { + sprintf(printArray, "Option for %s given illegal value %s", + name_.c_str(), value.c_str()); + } + return printArray; +} +void CbcOrClpParam::setIntValue(int value) +{ + if (value < lowerIntValue_ || value > upperIntValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " << lowerIntValue_ << " to " << upperIntValue_ << std::endl; + } else { + intValue_ = value; + } +} +const char * +CbcOrClpParam::setIntValueWithMessage(int value) +{ + printArray[0] = '\0'; + if (value < lowerIntValue_ || value > upperIntValue_) { + sprintf(printArray, "%d was provided for %s - valid range is %d to %d", + value, name_.c_str(), lowerIntValue_, upperIntValue_); + } else { + if (value == intValue_) + return NULL; + sprintf(printArray, "%s was changed from %d to %d", + name_.c_str(), intValue_, value); + intValue_ = value; + } + return printArray; +} +void CbcOrClpParam::setDoubleValue(double value) +{ + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + std::cout << value << " was provided for " << name_ << " - valid range is " << lowerDoubleValue_ << " to " << upperDoubleValue_ << std::endl; + } else { + doubleValue_ = value; + } +} +const char * +CbcOrClpParam::setDoubleValueWithMessage(double value) +{ + printArray[0] = '\0'; + if (value < lowerDoubleValue_ || value > upperDoubleValue_) { + sprintf(printArray, "%g was provided for %s - valid range is %g to %g", + value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_); + } else { + if (value == doubleValue_) + return NULL; + sprintf(printArray, "%s was changed from %g to %g", + name_.c_str(), doubleValue_, value); + doubleValue_ = value; + } + return printArray; +} +void CbcOrClpParam::setStringValue(std::string value) +{ + stringValue_ = value; +} +static char line[1000]; +static char *where = NULL; +extern int CbcOrClpRead_mode; +int CbcOrClpEnvironmentIndex = -1; +// Alternative to environment +char *alternativeEnvironment = NULL; +static size_t fillEnv() +{ +#if defined(_MSC_VER) || defined(__MSVCRT__) + return 0; +#else + // Don't think it will work on Windows + char *environ; + if (!alternativeEnvironment) + environ = getenv("CBC_CLP_ENVIRONMENT"); + else + environ = alternativeEnvironment; + size_t length = 0; + if (environ) { + length = strlen(environ); + if (CbcOrClpEnvironmentIndex < static_cast< int >(length)) { + // find next non blank + char *whereEnv = environ + CbcOrClpEnvironmentIndex; + // munch white space + while (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ') + whereEnv++; + // copy + char *put = line; + while (*whereEnv != '\0') { + if (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ') { + break; + } + *put = *whereEnv; + put++; + assert(put - line < 1000); + whereEnv++; + } + CbcOrClpEnvironmentIndex = static_cast< int >(whereEnv - environ); + *put = '\0'; + length = strlen(line); + } else { + length = 0; + } + } + if (!length) { + CbcOrClpEnvironmentIndex = -1; + if (alternativeEnvironment) { + delete[] alternativeEnvironment; + alternativeEnvironment = NULL; + } + } + return length; +#endif +} +extern FILE *CbcOrClpReadCommand; +// Simple read stuff +std::string +CoinReadNextField() +{ + std::string field; + if (!where) { + // need new line +#ifdef COIN_HAS_READLINE + if (CbcOrClpReadCommand == stdin) { + // Get a line from the user. + where = readline(coin_prompt); + + // If the line has any text in it, save it on the history. + if (where) { + if (*where) + add_history(where); + strcpy(line, where); + free(where); + } + } else { + where = fgets(line, 1000, CbcOrClpReadCommand); + } +#else + if (CbcOrClpReadCommand == stdin) { + fputs(coin_prompt, stdout); + fflush(stdout); + } + where = fgets(line, 1000, CbcOrClpReadCommand); +#endif + if (!where) + return field; // EOF + where = line; + // clean image + char *lastNonBlank = line - 1; + while (*where != '\0') { + if (*where != '\t' && *where < ' ') { + break; + } else if (*where != '\t' && *where != ' ') { + lastNonBlank = where; + } + where++; + } + where = line; + *(lastNonBlank + 1) = '\0'; + } + // munch white space + while (*where == ' ' || *where == '\t') + where++; + char *saveWhere = where; + while (*where != ' ' && *where != '\t' && *where != '\0') + where++; + if (where != saveWhere) { + char save = *where; + *where = '\0'; + //convert to string + field = saveWhere; + *where = save; + } else { + where = NULL; + field = "EOL"; + } + return field; +} + +std::string +CoinReadGetCommand(int argc, const char *argv[]) +{ + std::string field = "EOL"; + // say no = + afterEquals = ""; + while (field == "EOL") { + if (CbcOrClpRead_mode > 0) { + if ((CbcOrClpRead_mode < argc && argv[CbcOrClpRead_mode]) || CbcOrClpEnvironmentIndex >= 0) { + if (CbcOrClpEnvironmentIndex < 0) { + field = argv[CbcOrClpRead_mode++]; + } else { + if (fillEnv()) { + field = line; + } else { + // not there + continue; + } + } + if (field == "-") { + std::cout << "Switching to line mode" << std::endl; + CbcOrClpRead_mode = -1; + field = CoinReadNextField(); + } else if (field[0] != '-') { + if (CbcOrClpRead_mode != 2) { + // now allow std::cout<<"skipping non-command "< 0) { + if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { + if (CbcOrClpEnvironmentIndex < 0) { + const char * input = argv[CbcOrClpRead_mode]; + if (strcmp(input,"--")&&strcmp(input,"stdin")&& + strcmp(input,"stdin_lp")) { + field = argv[CbcOrClpRead_mode++]; + } else { + CbcOrClpRead_mode++; + // -- means import from stdin + // but allow for other than mps files + // Clp does things in different way !! + if (!strcmp(input,"--")) + field = "-"; + else if (!strcmp(input,"stdin")) + field = "-"; + else if (!strcmp(input,"stdin_lp")) + field = "-lp"; + } + } else { + fillEnv(); + field = line; + } + } + } else { + field = CoinReadNextField(); + } + } else { + field = afterEquals; + afterEquals = ""; + } + //std::cout< 0) { + if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { + if (CbcOrClpEnvironmentIndex < 0) { + // may be negative value so do not check for - + field = argv[CbcOrClpRead_mode++]; + } else { + fillEnv(); + field = line; + } + } + } else { + field = CoinReadNextField(); + } + } else { + field = afterEquals; + afterEquals = ""; + } + long int value = 0; + //std::cout<(value); +} +double +CoinReadGetDoubleField(int argc, const char *argv[], int *valid) +{ + std::string field = "EOL"; + if (afterEquals == "") { + if (CbcOrClpRead_mode > 0) { + if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) { + if (CbcOrClpEnvironmentIndex < 0) { + // may be negative value so do not check for - + field = argv[CbcOrClpRead_mode++]; + } else { + fillEnv(); + field = line; + } + } + } else { + field = CoinReadNextField(); + } + } else { + field = afterEquals; + afterEquals = ""; + } + double value = 0.0; + //std::cout< ¶meters) +{ + parameters.clear(); + parameters.push_back(CbcOrClpParam("?", "For help", CBC_PARAM_GENERALQUERY, 7, 0)); + parameters.push_back(CbcOrClpParam("???", "For help", CBC_PARAM_FULLGENERALQUERY, 7, 0)); + parameters.push_back(CbcOrClpParam("-", "From stdin", CLP_PARAM_ACTION_STDIN, 3, 0)); + +// some help strings that repeat for many options +#define CUTS_LONGHELP \ + "Value 'on' enables the cut generator and CBC will try it in the branch and cut tree (see cutDepth on how to fine tune the behavior). " \ + "Value 'root' lets CBC run the cut generator generate only at the root node. " \ + "Value 'ifmove' lets CBC use the cut generator in the tree if it looks as if it is doing some good and moves the objective value. " \ + "Value 'forceon' turns on the cut generator and forces CBC to use it at every node." +#define HEURISTICS_LONGHELP \ + "Value 'on' means to use the heuristic in each node of the tree, i.e. after preprocessing. " \ + "Value 'before' means use the heuristic only if option doHeuristics is used. " \ + "Value 'both' means to use the heuristic if option doHeuristics is used and during solve." + +#if defined(ABC_INHERIT) || ABOCA_LITE + CbcOrClpParam paramAboca("abc", "Whether to visit Aboca", "off", CLP_PARAM_STR_ABCWANTED, 7, 0); + paramAboca.append("one"); + paramAboca.append("two"); + paramAboca.append("three"); + paramAboca.append("four"); + paramAboca.append("five"); + paramAboca.append("six"); + paramAboca.append("seven"); + paramAboca.append("eight"); + paramAboca.append("on"); + paramAboca.append("decide"); + paramAboca.setFakeKeyWord(10); + paramAboca.setLonghelp( + "Decide whether to use A Basic Optimization Code (Accelerated?) \ +and whether to try going parallel!"); + parameters.push_back(paramAboca); +#endif + { + CbcOrClpParam p("allC!ommands", "Whether to print less used commands", + "no", CLP_PARAM_STR_ALLCOMMANDS); + + p.append("more"); + p.append("all"); + p.setLonghelp( + "For the sake of your sanity, only the more useful and simple commands \ +are printed out on ?."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("allow!ableGap", "Stop when gap between best possible and \ +best less than this", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ALLOWABLEGAP); + p.setDoubleValue(0.0); + p.setLonghelp( + "If the gap between best known solution and the best possible solution is less than this \ +value, then the search will be terminated. Also see ratioGap."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("allS!lack", "Set basis back to all slack and reset solution", + CLP_PARAM_ACTION_ALLSLACK, 3); + p.setLonghelp( + "Mainly useful for tuning purposes. Normally the first dual or primal will be using an all slack \ +basis anyway."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("artif!icialCost", "Costs >= this treated as artificials in feasibility pump", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1); + p.setDoubleValue(0.0); + p.setLonghelp( + "A value of 0.0 means off. Otherwise, variables with costs >= this are treated as artificial variables and fixed to lower bound in feasibility pump."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("auto!Scale", "Whether to scale objective, rhs and bounds of problem if they look odd", + "off", CLP_PARAM_STR_AUTOSCALE, 7, 0); + p.append("on"); + p.setLonghelp( + "If you think you may get odd objective values or large equality rows etc then\ + it may be worth setting this true. It is still experimental and you may prefer\ + to use objective!Scale and rhs!Scale."); + parameters.push_back(p); + } + { + CbcOrClpParam p("barr!ier", "Solve using primal dual predictor corrector algorithm", + CLP_PARAM_ACTION_BARRIER); + p.setLonghelp( + "This command solves the current model using the primal dual predictor \ +corrector algorithm. You may want to link in an alternative \ +ordering and factorization. It will also solve models \ +with quadratic objectives."); + parameters.push_back(p); + } + { + CbcOrClpParam p("basisI!n", "Import basis from bas file", + CLP_PARAM_ACTION_BASISIN, 3); + p.setLonghelp( + "This will read an MPS format basis file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. If you have libz then it can read compressed\ + files 'xxxxxxxx.gz' or xxxxxxxx.bz2."); + parameters.push_back(p); + } + { + CbcOrClpParam p("basisO!ut", "Export basis as bas file", + CLP_PARAM_ACTION_BASISOUT); + + p.setLonghelp( + "This will write an MPS format basis file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.bas'."); + parameters.push_back(p); + } + { + CbcOrClpParam p("biasLU", "Whether factorization biased towards U", + "UU", CLP_PARAM_STR_BIASLU, 2, 0); + + p.append("UX"); + p.append("LX"); + p.append("LL"); + p.setCurrentOption("LX"); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("branch!AndCut", "Do Branch and Cut", + CBC_PARAM_ACTION_BAB); + p.setLonghelp( + "This does branch and cut. There are many parameters which can affect the performance. \ +First just try with default settings and look carefully at the log file. Did cuts help? Did they take too long? \ +Look at output to see which cuts were effective and then do some tuning. You will see that the \ +options for cuts are off, on, root and ifmove, forceon. Off is \ +obvious. " CUTS_LONGHELP " For probing, forceonbut just does fixing probing in tree - not strengthening etc. \ +If pre-processing reduced the size of the \ +problem or strengthened many coefficients then it is probably wise to leave it on. Switch off heuristics \ +which did not provide solutions. The other major area to look at is the search. Hopefully good solutions \ +were obtained fairly early in the search so the important point is to select the best variable to branch on. \ +See whether strong branching did a good job - or did it just take a lot of iterations. Adjust the strongBranching \ +and trustPseudoCosts parameters. If cuts did a good job, then you may wish to \ +have more rounds of cuts - see passC!uts and passT!ree."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("bscale", "Whether to scale in barrier (and ordering speed)", + "off", CLP_PARAM_STR_BARRIERSCALE, 7, 0); + p.append("on"); + p.append("off1"); + p.append("on1"); + p.append("off2"); + p.append("on2"); + parameters.push_back(p); + } +#if FLUSH_PRINT_BUFFER > 2 + { + CbcOrClpParam p("buff!eredMode", "Whether to flush print buffer", + "on", CLP_PARAM_STR_BUFFER_MODE); + + p.append("off"); + p.setLonghelp( + "Default is on, off switches on unbuffered output"); + p.setIntValue(0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("chol!esky", "Which cholesky algorithm", + "native", CLP_PARAM_STR_CHOLESKY, 7); + + p.append("dense"); + //#ifdef FOREIGN_BARRIER +#ifdef COIN_HAS_WSMP + p.append("fudge!Long"); + p.append("wssmp"); +#else + p.append("fudge!Long_dummy"); + p.append("wssmp_dummy"); +#endif +#if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK) + p.append("Uni!versityOfFlorida"); +#else + p.append("Uni!versityOfFlorida_dummy"); +#endif +#ifdef TAUCS_BARRIER + p.append("Taucs"); +#else + p.append("Taucs_dummy"); +#endif +#ifdef COIN_HAS_MUMPS + p.append("Mumps"); +#else + p.append("Mumps_dummy"); +#endif +#ifdef PARDISO_BARRIER + p.append("Pardiso"); +#else + p.append("Pardiso_dummy"); +#endif + p.setLonghelp( + "For a barrier code to be effective it needs a good Cholesky ordering and factorization. \ +The native ordering and factorization is not state of the art, although acceptable. \ +You may want to link in one from another source. See Makefile.locations for some \ +possibilities."); + + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("clique!Cuts", "Whether to use Clique cuts", + "off", CBC_PARAM_STR_CLIQUECUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglClique"); + + parameters.push_back(p); + } + { + CbcOrClpParam p("combine!Solutions", "Whether to use combine solution heuristic", + "off", CBC_PARAM_STR_COMBINE); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("onquick"); + p.append("bothquick"); + p.append("beforequick"); + p.setLonghelp( + "This heuristic does branch and cut on given problem by just \ +using variables which have appeared in one or more solutions. \ +It is obviously only tried after two or more solutions have been found. " + HEURISTICS_LONGHELP); + + parameters.push_back(p); + } + { + CbcOrClpParam p("combine2!Solutions", "Whether to use crossover solution heuristic", + "off", CBC_PARAM_STR_CROSSOVER2); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This heuristic does branch and cut on the problem given by \ +fixing variables which have the same value in two or more solutions. \ +It obviously only tries after two or more solutions. " + HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("constraint!fromCutoff", "Whether to use cutoff as constraint", + "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT); + + p.append("on"); + p.append("variable"); + p.append("forcevariable"); + p.append("conflict"); + p.setLonghelp( + "For some problems, cut generators and general branching work better if the problem would be infeasible if the cost is too high. " + "If this option is enabled, the objective function is added as a constraint which right hand side is set to the current cutoff value (objective value of best known solution)"); + parameters.push_back(p); + } + { + CbcOrClpParam p("cost!Strategy", "How to use costs for branching priorities", + "off", CBC_PARAM_STR_COSTSTRATEGY); + + p.append("pri!orities"); + p.append("column!Order?"); + p.append("01f!irst?"); + p.append("01l!ast?"); + p.append("length!?"); + p.append("singletons"); + p.append("nonzero"); + p.append("general!Force?"); + p.setLonghelp( + "Value 'priorities' assigns highest priority to variables with largest absolute cost. This primitive strategy can be surprisingly effective. " + "Value 'columnorder' assigns the priorities 1, 2, 3, ... with respect to the column ordering. " + "Value '01first' ('01last') assignes two sets of priorities such that binary variables get high (low) priority. " + "Value 'length' assigns high priority to variables that occur in many equations. "); + + parameters.push_back(p); + } + { + CbcOrClpParam p("cplex!Use", "Whether to use Cplex!", + "off", CBC_PARAM_STR_CPX); + p.append("on"); + p.setLonghelp( + " If the user has Cplex, but wants to use some of Cbc's heuristics \ +then you can! If this is on, then Cbc will get to the root node and then \ +hand over to Cplex. If heuristics find a solution this can be significantly \ +quicker. You will probably want to switch off Cbc's cuts as Cplex thinks \ +they are genuine constraints. It is also probable that you want to switch \ +off preprocessing, although for difficult problems it is worth trying \ +both."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("cpp!Generate", "Generates C++ code", + -1, 50000, CLP_PARAM_INT_CPP, 1); + p.setLonghelp( + "Once you like what the stand-alone solver does then this allows \ +you to generate user_driver.cpp which approximates the code. \ +0 gives simplest driver, 1 generates saves and restores, 2 \ +generates saves and restores even for variables at default value. \ +4 bit in cbc generates size dependent code rather than computed values. \ +This is now deprecated as you can call stand-alone solver - see \ +Cbc/examples/driver4.cpp."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("crash", "Whether to create basis for problem", + "off", CLP_PARAM_STR_CRASH); + + p.append("on"); + p.append("so!low_halim"); + p.append("lots"); +#ifdef CLP_INHERIT_MODE + p.append("dual"); + p.append("dw"); + p.append("idiot"); +#else + p.append("idiot1"); + p.append("idiot2"); + p.append("idiot3"); + p.append("idiot4"); + p.append("idiot5"); + p.append("idiot6"); + p.append("idiot7"); +#endif + p.setLonghelp( + "If crash is set to 'on' and there is an all slack basis then Clp will flip or put structural\ + variables into the basis with the aim of getting dual feasible. On average, dual simplex seems to perform\ + better without it and there are alternative types of 'crash' for primal simplex, e.g. 'idiot' or 'sprint'. \ + A variant due to Solow and Halim which is as 'on' but just flips is also available."); + + parameters.push_back(p); + } + { + CbcOrClpParam p("cross!over", "Whether to get a basic solution with the simplex algorithm after the barrier algorithm finished", + "on", CLP_PARAM_STR_CROSSOVER); + p.append("off"); + p.append("maybe"); + p.append("presolve"); + p.setLonghelp( + "Interior point algorithms do not obtain a basic solution.\ + This option will crossover to a basic solution suitable for ranging or branch and cut. With the current state \ +of the solver for quadratic programs it may be a good idea to switch off crossover for this case (and maybe \ +presolve as well) - the option 'maybe' does this."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("csv!Statistics", "Create one line of statistics", + CLP_PARAM_ACTION_CSVSTATISTICS, 2, 1); + p.setLonghelp( + "This appends statistics to given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. Adds header if file empty or does not exist."); + parameters.push_back(p); + } + { + CbcOrClpParam p("cutD!epth", "Depth in tree at which to do cuts", + -1, COIN_INT_MAX, CBC_PARAM_INT_CUTDEPTH); + p.setLonghelp( + "Cut generators may be off, on, on only at the root node, or on if they look useful. \ + Setting this option to a positive value K let CBC call a cutgenerator on a node whenever the depth in the tree is a multiple of K. \ + The default of -1 lets CBC decide."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("cutL!ength", "Length of a cut", + -1, COIN_INT_MAX, CBC_PARAM_INT_CUTLENGTH); + p.setLonghelp("At present this only applies to Gomory cuts. -1 (default) leaves as is. \ +Any value >0 says that all cuts <= this length can be generated both at \ +root node and in tree. 0 says to use some dynamic lengths. If value >=10,000,000 \ +then the length in tree is value%10000000 - so 10000100 means unlimited length \ +at root and 100 in tree."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("cuto!ff", "Bound on the objective value for all solutions", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_CUTOFF); + p.setDoubleValue(1.0e50); + p.setLonghelp( + "All solutions must have a better objective value (in a minimization sense) than the value of this option. \ +CBC also updates this value whenever it obtains a solution to the value of \ +the objective function of the solution minus the cutoff increment."); + parameters.push_back(p); + } + { + CbcOrClpParam p("cuts!OnOff", "Switches all cut generators on or off", + "off", CBC_PARAM_STR_CUTSSTRATEGY); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + "This can be used to switch on or off all cut generators (apart from Reduce and Split). " + "Then one can turn individual ones off or on. " + CUTS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("debug!In", "read valid solution from file", + CLP_PARAM_ACTION_DEBUG, 7, 1); + + p.setLonghelp( + "This will read a solution file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set.\n\n\ +If set to create it will create a file called debug.file after search.\n\n\ +The idea is that if you suspect a bad cut generator \ +you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \ +re-run with debug set to 'debug.file' The create case has same effect as saveSolution."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("decomp!ose", "Whether to try decomposition", + -COIN_INT_MAX, COIN_INT_MAX, CLP_PARAM_INT_DECOMPOSE_BLOCKS, 1); + p.setLonghelp( + "0 - off, 1 choose blocks >1 use as blocks \ +Dantzig Wolfe if primal, Benders if dual \ +- uses sprint pass for number of passes"); + p.setIntValue(0); + parameters.push_back(p); + } +#if CLP_MULTIPLE_FACTORIZATIONS > 0 + { + CbcOrClpParam p("dense!Threshold", "Threshold for using dense factorization", + -1, 10000, CBC_PARAM_INT_DENSE, 1); + p.setLonghelp( + "If processed problem <= this use dense factorization"); + p.setIntValue(-1); + parameters.push_back(p); + } +#endif +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("depth!MiniBab", "Depth at which to try mini branch-and-bound", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB); + + p.setIntValue(-1); + p.setLonghelp( + "Rather a complicated parameter but can be useful. -1 means off for large problems but on as if -12 for problems where rows+columns<500, -2 \ +means use Cplex if it is linked in. Otherwise if negative then go into depth first complete search fast branch and bound when depth>= -value-2 \ +(so -3 will use this at depth>=1). This mode is only switched on after 500 nodes. If you really want to switch it off for small problems then set \ +this to -999. If >=0 the value doesn't matter very much. The code will do approximately 100 nodes of fast branch and bound every now and then at depth>=5. \ +The actual logic is too twisted to describe here."); + parameters.push_back(p); + } + { + CbcOrClpParam p("dextra3", "Extra double parameter 3", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcOrClpParam p("dextra4", "Extra double parameter 4", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcOrClpParam p("dextra4", "Extra double parameter 5", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0); + p.setDoubleValue(0.0); + parameters.push_back(p); + } + { + CbcOrClpParam p("Dins", "Whether to try Distance Induced Neighborhood Search", + "off", CBC_PARAM_STR_DINS); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("often"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("direction", "Minimize or Maximize", + "min!imize", CLP_PARAM_STR_DIRECTION); + p.append("max!imize"); + p.append("zero"); + p.setLonghelp( + "The default is minimize - use 'direction maximize' for maximization.\n\ +You can also use the parameters 'maximize' or 'minimize'."); + parameters.push_back(p); + } + { + CbcOrClpParam p("directory", "Set Default directory for import etc.", + CLP_PARAM_ACTION_DIRECTORY); + p.setLonghelp( + "This sets the directory which import, export, saveModel, restoreModel etc will use.\ + It is initialized to './'"); + parameters.push_back(p); + } + { + CbcOrClpParam p("dirSample", "Set directory where the COIN-OR sample problems are.", + CLP_PARAM_ACTION_DIRSAMPLE, 7, 1); + + p.setLonghelp( + "This sets the directory where the COIN-OR sample problems reside. It is\ + used only when -unitTest is passed to clp. clp will pick up the test problems\ + from this directory.\ + It is initialized to '../../Data/Sample'"); + parameters.push_back(p); + } + { + CbcOrClpParam p("dirNetlib", "Set directory where the netlib problems are.", + CLP_PARAM_ACTION_DIRNETLIB, 7, 1); + + p.setLonghelp( + "This sets the directory where the netlib problems reside. One can get\ + the netlib problems from COIN-OR or from the main netlib site. This\ + parameter is used only when -netlib is passed to clp. clp will pick up the\ + netlib problems from this directory. If clp is built without zlib support\ + then the problems must be uncompressed.\ + It is initialized to '../../Data/Netlib'"); + parameters.push_back(p); + } + { + CbcOrClpParam p("dirMiplib", "Set directory where the miplib 2003 problems are.", + CBC_PARAM_ACTION_DIRMIPLIB, 7, 1); + + p.setLonghelp( + "This sets the directory where the miplib 2003 problems reside. One can\ + get the miplib problems from COIN-OR or from the main miplib site. This\ + parameter is used only when -miplib is passed to cbc. cbc will pick up the\ + miplib problems from this directory. If cbc is built without zlib support\ + then the problems must be uncompressed.\ + It is initialized to '../../Data/miplib3'"); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("diveO!pt", "Diving options", + -1, 200000, CBC_PARAM_INT_DIVEOPT, 1); + p.setLonghelp( + "If >2 && <20 then modify diving options - \ + \n\t3 only at root and if no solution, \ + \n\t4 only at root and if this heuristic has not got solution, \ + \n\t5 decay only if no solution, \ + \n\t6 if depth <3 or decay, \ + \n\t7 run up to 2 times if solution found 4 otherwise, \ + \n\t>10 All only at root (DivingC normal as value-10), \ + \n\t>20 All with value-20)."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("diveS!olves", "Diving solve option", + -1, 200000, CBC_PARAM_INT_DIVEOPTSOLVES, 1); + + p.setLonghelp( + "If >0 then do up to this many solves. However, the last digit is ignored \ +and used for extra options: \ + 1-3 enables fixing of satisfied integer variables (but not at bound), \ + where 1 switches this off for that dive if the dive goes infeasible, \ + and 2 switches it off permanently if the dive goes infeasible."); + p.setIntValue(100); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingS!ome", "Whether to try Diving heuristics", + "off", CBC_PARAM_STR_DIVINGS); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This switches on a random diving heuristic at various times. \ +One may prefer to individually turn diving heuristics on or off. " + HEURISTICS_LONGHELP); +// C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - PseudoCost, V - VectorLength. + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingC!oefficient", "Whether to try Coefficient diving heuristic", + "off", CBC_PARAM_STR_DIVINGC); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingF!ractional", "Whether to try Fractional diving heuristic", + "off", CBC_PARAM_STR_DIVINGF); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingG!uided", "Whether to try Guided diving heuristic", + "off", CBC_PARAM_STR_DIVINGG); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingL!ineSearch", "Whether to try Linesearch diving heuristic", + "off", CBC_PARAM_STR_DIVINGL); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingP!seudoCost", "Whether to try Pseudocost diving heuristic", + "off", CBC_PARAM_STR_DIVINGP); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("DivingV!ectorLength", "Whether to try Vectorlength diving heuristic", + "off", CBC_PARAM_STR_DIVINGV); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("doH!euristic", "Do heuristics before any preprocessing", + CBC_PARAM_ACTION_DOHEURISTIC, 3); + p.setLonghelp( + "Normally heuristics are done in branch and bound. It may be useful to do them outside. \ +Only those heuristics with 'both' or 'before' set will run. \ +Doing this may also set cutoff, which can help with preprocessing."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("dualB!ound", "Initially algorithm acts as if no \ +gap between bounds exceeds this value", + 1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALBOUND); + p.setLonghelp( + "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\ + algorithm where you first get feasible then optimal. If a problem has both upper and\ + lower bounds then it is trivial to get dual feasible by setting non basic variables\ + to correct bound. If the gap between the upper and lower bounds of a variable is more\ + than the value of dualBound Clp introduces fake bounds so that it can make the problem\ + dual feasible. This has the same effect as a composite objective function in the\ + primal algorithm. Too high a value may mean more iterations, while too low a bound means\ + the code may go all the way and then have to increase the bounds. OSL had a heuristic to\ + adjust bounds, maybe we need that here."); + + parameters.push_back(p); + } + { + CbcOrClpParam p("dualize", "Solves dual reformulation", + 0, 4, CLP_PARAM_INT_DUALIZE, 1); + p.setLonghelp( + "Don't even think about it."); + + parameters.push_back(p); + } + { + CbcOrClpParam p("dualP!ivot", "Dual pivot choice algorithm", + "auto!matic", CLP_PARAM_STR_DUALPIVOT, 7, 1); + p.append("dant!zig"); + p.append("partial"); + p.append("steep!est"); + p.append("PEsteep!est"); + p.append("PEdantzig"); + p.setLonghelp( + "The Dantzig method is simple but its use is deprecated. Steepest is the method of choice and there\ + are two variants which keep all weights updated but only scan a subset each iteration.\ + Partial switches this on while automatic decides at each iteration based on information\ + about the factorization.\ + The PE variants add the Positive Edge criterion. \ + This selects incoming variables to try to avoid degenerate moves. See also option psi."); + parameters.push_back(p); + } + { + CbcOrClpParam p("dualS!implex", "Do dual simplex algorithm", + CLP_PARAM_ACTION_DUALSIMPLEX); + p.setLonghelp( + "This command solves the continuous relaxation of the current model using the dual steepest edge algorithm.\ +The time and iterations may be affected by settings such as presolve, scaling, crash\ + and also by dual pivot method, fake bound on variables and dual and primal tolerances."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("dualT!olerance", "For an optimal solution \ +no dual infeasibility may exceed this value", + 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_DUALTOLERANCE); + p.setLonghelp( + "Normally the default tolerance is fine, but one may want to increase it a\ + bit if the dual simplex algorithm seems to be having a hard time. One method which can be faster is \ +to use a large tolerance e.g. 1.0e-4 and the dual simplex algorithm and then to clean up the problem using the primal simplex algorithm with the \ +correct tolerance (remembering to switch off presolve for this final short clean up phase)."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("dw!Heuristic", "Whether to try Dantzig Wolfe heuristic", + "off", CBC_PARAM_STR_DW); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This heuristic is very very compute intensive. It tries to find a Dantzig Wolfe structure and use that. " + HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("either!Simplex", "Do dual or primal simplex algorithm", + CLP_PARAM_ACTION_EITHERSIMPLEX); + p.setLonghelp( + "This command solves the continuous relaxation of the current model using the dual or primal algorithm,\ + based on a dubious analysis of model."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("end", "Stops clp execution", + CLP_PARAM_ACTION_EXIT); + p.setLonghelp( + "This stops execution ; end, exit, quit and stop are synonyms"); + parameters.push_back(p); + } + { + CbcOrClpParam p("environ!ment", "Read commands from environment", + CLP_PARAM_ACTION_ENVIRONMENT, 7, 0); + p.setLonghelp( + "This starts reading from environment variable CBC_CLP_ENVIRONMENT."); + parameters.push_back(p); + } + { + CbcOrClpParam p("error!sAllowed", "Whether to allow import errors", + "off", CLP_PARAM_STR_ERRORSALLOWED, 3); + + p.append("on"); + p.setLonghelp( + "The default is not to use any model which had errors when reading the mps file.\ + Setting this to 'on' will allow all errors from which the code can recover\ + simply by ignoring the error. There are some errors from which the code can not recover \ +e.g. no ENDATA. This has to be set before import i.e. -errorsAllowed on -import xxxxxx.mps."); + parameters.push_back(p); + } + { + CbcOrClpParam p("exit", "Stops clp execution", + CLP_PARAM_ACTION_EXIT); + p.setLonghelp( + "This stops the execution of Clp, end, exit, quit and stop are synonyms"); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("exper!iment", "Whether to use testing features", + -1, 200000, CBC_PARAM_INT_EXPERIMENT, 0); + p.setLonghelp( + "Defines how adventurous you want to be in using new ideas. \ +0 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!"); + + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcOrClpParam p("expensive!Strong", "Whether to do even more strong branching", + 0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0); + + p.setLonghelp( + "Strategy for extra strong branching. \ +0 is normal strong branching. \ +1, 2, 4, and 6 does strong branching on all fractional variables if \ +at the root node (1), \ +at depth less than modifier (2), \ +objective equals best possible (4), or \ +at depth less than modifier and objective equals best possible (6). \ +11, 12, 14, and 16 are like 1, 2, 4, and 6, respecitively, but do strong branching on all integer (incl. non-fractional) variables. \ +Values >= 100 are used to specify a depth limit (value/100), otherwise 5 is used. \ +If the values >= 100, then above rules are applied to value%100."); + p.setIntValue(0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("export", "Export model as mps file", + CLP_PARAM_ACTION_EXPORT); + + p.setLonghelp( + "This will write an MPS format file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.mps'. \ +It can be useful to get rid of the original names and go over to using Rnnnnnnn and Cnnnnnnn. This can be done by setting 'keepnames' off before importing mps file."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("extra1", "Extra integer parameter 1", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("extra2", "Extra integer parameter 2", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("extra3", "Extra integer parameter 3", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("extra4", "Extra integer parameter 4", + -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA4, 0); + + p.setIntValue(-1); + p.setLonghelp( + "This switches on yet more special options!! \ +The bottom digit is a strategy when to used shadow price stuff e.g. 3 \ +means use until a solution is found. The next two digits say what sort \ +of dual information to use. After that it goes back to powers of 2 so -\n\ +\n\t1000 - switches on experimental hotstart\n\ +\n\t2,4,6000 - switches on experimental methods of stopping cuts\n\ +\n\t8000 - increase minimum drop gradually\n\ +\n\t16000 - switches on alternate gomory criterion"); + parameters.push_back(p); + } + { + CbcOrClpParam p("extraV!ariables", "Allow creation of extra integer variables", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0); + p.setIntValue(0); + p.setLonghelp( + "Switches on a trivial re-formulation that introduces extra integer variables to group together variables with same cost."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("fact!orization", "Which factorization to use", + "normal", CLP_PARAM_STR_FACTORIZATION); + p.append("dense"); + p.append("simple"); + p.append("osl"); + p.setLonghelp( +#ifndef ABC_INHERIT + "The default is to use the normal CoinFactorization, but \ +other choices are a dense one, OSL's, or one designed for small problems." +#else + "Normally the default is to use the normal CoinFactorization, but \ +other choices are a dense one, OSL's, or one designed for small problems. \ +However if at Aboca then the default is CoinAbcFactorization and other choices are \ +a dense one, one designed for small problems or if enabled a long factorization." +#endif + ); + parameters.push_back(p); + } + { + CbcOrClpParam p("fakeB!ound", "All bounds <= this value - DEBUG", + 1.0, 1.0e15, CLP_PARAM_ACTION_FAKEBOUND, 0); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("feas!ibilityPump", "Whether to try the Feasibility Pump heuristic", + "off", CBC_PARAM_STR_FPUMP); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This heuristic is due to Fischetti, Glover, and Lodi \ +and uses a sequence of LPs to try and get an integer feasible solution. \ +Some fine tuning is available by options passFeasibilityPump and pumpTune. " + HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("fix!OnDj", "Try heuristic based on fixing variables with \ +reduced costs greater than this", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DJFIX, 1); + p.setLonghelp( + "If this is set integer variables with reduced costs greater than this will be fixed \ +before branch and bound - use with extreme caution!"); + parameters.push_back(p); + } + { + CbcOrClpParam p("flow!CoverCuts", "Whether to use Flow Cover cuts", + "off", CBC_PARAM_STR_FLOWCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setFakeKeyWord(3); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglFlowCover"); // Can also enter testing values by plusnn (==ifmove) + parameters.push_back(p); + } + { + CbcOrClpParam p("force!Solution", "Whether to use given solution as crash for BAB", + -1, 20000000, CLP_PARAM_INT_USESOLUTION); + p.setIntValue(-1); + p.setLonghelp( + "-1 off. If 1 then tries to branch to solution given by AMPL or priorities file. \ +If 0 then just tries to set as best solution \ +If >1 then also does that many nodes on fixed problem."); + parameters.push_back(p); + } + { + CbcOrClpParam p("fraction!forBAB", "Fraction in feasibility pump", + 1.0e-5, 1.1, CBC_PARAM_DBL_SMALLBAB, 1); + p.setDoubleValue(0.5); + p.setLonghelp( + "After a pass in the feasibility pump, variables which have not moved \ +about are fixed and if the preprocessed model is smaller than this fraction of the original problem, \ +a few nodes of branch and bound are done on the reduced problem."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("gamma!(Delta)", "Whether to regularize barrier", + "off", CLP_PARAM_STR_GAMMA, 7, 1); + p.append("on"); + p.append("gamma"); + p.append("delta"); + p.append("onstrong"); + p.append("gammastrong"); + p.append("deltastrong"); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("GMI!Cuts", "Whether to use alternative Gomory cuts", + "off", CBC_PARAM_STR_GMICUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("endonly"); + p.append("long"); + p.append("longroot"); + p.append("longifmove"); + p.append("forceLongOn"); + p.append("longendonly"); + p.setLonghelp(CUTS_LONGHELP + " This version is by Giacomo Nannicini and may be more robust than gomoryCuts."); + parameters.push_back(p); + } + { + CbcOrClpParam p("gomory!Cuts", "Whether to use Gomory cuts", + "off", CBC_PARAM_STR_GOMORYCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.append("forceLongOn"); + p.append("long"); + p.setLonghelp( + "The original cuts - beware of imitations! Having gone out of favor, \ +they are now more fashionable as LP solvers are more robust and they interact well \ +with other cuts. They will almost always give cuts (although in this executable \ +they are limited as to number of variables in cut). However the cuts may be dense \ +so it is worth experimenting (Long allows any length). " + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglGomory"); + parameters.push_back(p); + } + { + CbcOrClpParam p("greedy!Heuristic", "Whether to use a greedy heuristic", + "off", CBC_PARAM_STR_GREEDY); + + p.append("on"); + p.append("both"); + p.append("before"); + //p.append("root"); + p.setLonghelp( + "This heuristic tries to obtain a feasible solution by just fixing a percentage of variables and then try a small branch and cut run. " + HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("gsolu!tion", "Puts glpk solution to file", + CLP_PARAM_ACTION_GMPL_SOLUTION); + + p.setLonghelp( + "Will write a glpk solution file to the given file name. It will use the default \ +directory given by 'directory'. A name of '$' will use the previous value for the \ +name. This is initialized to 'stdout' (this defaults to ordinary solution if stdout). \ +If problem created from gmpl model - will do any reports."); + parameters.push_back(p); + } + { + CbcOrClpParam p("guess", "Guesses at good parameters", CLP_PARAM_ACTION_GUESS, 7); + p.setLonghelp( + "This looks at model statistics and does an initial solve \ +setting some parameters which may help you to think of possibilities."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("heur!isticsOnOff", "Switches most primal heuristics on or off", + "off", CBC_PARAM_STR_HEURISTICSTRATEGY); + p.append("on"); + p.setLonghelp( + "This option can be used to switch on or off all heuristics that search for feasible solutions,\ + except for the local tree search, as it dramatically alters the search.\ + Then individual heuristics can be turned off or on."); + parameters.push_back(p); + } + { + CbcOrClpParam p("help", "Print out version, non-standard options and some help", + CLP_PARAM_ACTION_HELP, 3); + p.setLonghelp( + "This prints out some help to get user started. If you have printed this then \ +you should be past that stage:-)"); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("hOp!tions", "Heuristic options", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_HOPTIONS, 1); + p.setIntValue(0); + p.setLonghelp( + "Value 1 stops heuristics immediately if the allowable gap has been reached. \ +Other values are for the feasibility pump - \ +2 says do exact number of passes given, \ +4 only applies if an initial cutoff has been given and says relax after 50 passes, \ +while 8 will adapt the cutoff rhs after the first solution if it looks as if the code is stalling."); + parameters.push_back(p); + } + { + CbcOrClpParam p("hot!StartMaxIts", "Maximum iterations on hot start", + 0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("idiot!Crash", "Whether to try idiot crash", + -1, COIN_INT_MAX, CLP_PARAM_INT_IDIOT); + + p.setLonghelp( + "This is a type of 'crash' which works well on some homogeneous problems.\ + It works best on problems with unit elements and rhs but will do something to any \ + model. It should only be used before the primal simplex algorithm. It can be set to -1 when the code \ + decides for itself whether to use it, 0 to switch off, or n > 0 to do n passes."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("import", "Import model from mps file", + CLP_PARAM_ACTION_IMPORT, 3); + p.setLonghelp( + "This will read an MPS format file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. If you have libgz then it can read compressed\ + files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'. \ +If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("inc!rement", "A valid solution must be at least this \ +much better than last integer solution", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_INCREMENT); + + p.setLonghelp( + "Whenever a solution is found the bound on the objective value for new solutions is set to the\ + objective function of the found solution (in a minimization sense) plus this. If it is not set then CBC will try and work one out, e.g. if \ +all objective coefficients are multiples of 0.01 and only integer variables have entries in \ +the objective function, then the increment can be set to 0.01. Be careful if setting this to a negative value!"); + + parameters.push_back(p); + } + { + CbcOrClpParam p("inf!easibilityWeight", "Each integer infeasibility is expected \ +to cost this much", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1); + p.setLonghelp( + "A primitive way of deciding which node to explore next. Satisfying each integer infeasibility is \ +expected to cost this much."); + parameters.push_back(p); + } + { + CbcOrClpParam p("initialS!olve", "Solve to continuous", + CLP_PARAM_ACTION_SOLVECONTINUOUS); + + p.setLonghelp( + "This just solves the problem to continuous - without adding any cuts"); + parameters.push_back(p); + } + { + CbcOrClpParam p("integerT!olerance", "For a feasible solution \ +no integer variable may be more than this away from an integer value", + 1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE); + p.setLonghelp( + "Beware of setting this smaller than the primal feasibility tolerance."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("keepN!ames", "Whether to keep names from import", + "on", CLP_PARAM_STR_KEEPNAMES); + p.append("off"); + p.setLonghelp( + "It saves space to get rid of names so if you need to you can set this to off. \ +This needs to be set before the import of model - so -keepnames off -import xxxxx.mps."); + parameters.push_back(p); + } + { + CbcOrClpParam p("KKT", "Whether to use KKT factorization in barrier", + "off", CLP_PARAM_STR_KKT, 7, 1); + p.append("on"); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("knapsack!Cuts", "Whether to use Knapsack cuts", + "off", CBC_PARAM_STR_KNAPSACKCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglKnapsackCover"); + parameters.push_back(p); + } + { + CbcOrClpParam p("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts", + "off", CBC_PARAM_STR_LAGOMORYCUTS); + p.append("endonlyroot"); + p.append("endcleanroot"); + p.append("root"); + p.append("endonly"); + p.append("endclean"); + p.append("endboth"); + p.append("onlyaswell"); + p.append("cleanaswell"); + p.append("bothaswell"); + p.append("onlyinstead"); + p.append("cleaninstead"); + p.append("bothinstead"); + p.append("onlyaswellroot"); + p.append("cleanaswellroot"); + p.append("bothaswellroot"); + p.setLonghelp( + "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \ +by Matteo Fischetti & Domenico Salvagnin. This simplification \ +just uses original constraints while modifying objective using other cuts. \ +So you don't use messy constraints generated by Gomory etc. \ +A variant is to allow non messy cuts e.g. clique cuts. \ +So 'only' does this while 'clean' also allows integral valued cuts. \ +'End' is recommended and waits until other cuts have finished before it \ +does a few passes. \ +The length options for gomory cuts are used."); + parameters.push_back(p); + } + { + CbcOrClpParam p("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts", + "off", CBC_PARAM_STR_LATWOMIRCUTS); + + p.append("endonlyroot"); + p.append("endcleanroot"); + p.append("endbothroot"); + p.append("endonly"); + p.append("endclean"); + p.append("endboth"); + p.append("onlyaswell"); + p.append("cleanaswell"); + p.append("bothaswell"); + p.append("onlyinstead"); + p.append("cleaninstead"); + p.append("bothinstead"); + p.setLonghelp( + "This is a Lagrangean relaxation for TwoMir cuts. See \ + lagomoryCuts for description of options."); + parameters.push_back(p); + } + { + CbcOrClpParam p("lift!AndProjectCuts", "Whether to use Lift and Project cuts", + "off", CBC_PARAM_STR_LANDPCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + "These cuts may be expensive to compute. " + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglLandP"); + parameters.push_back(p); + } + { + CbcOrClpParam p("local!TreeSearch", "Whether to use local tree search when a solution is found", + "off", CBC_PARAM_STR_LOCALTREE); + p.append("on"); + p.setLonghelp( + "The heuristic is from Fischetti and Lodi and is not really a heuristic although it can be used as one \ +(with limited functionality). It is not switched on when heuristics are switched on."); + parameters.push_back(p); + } +#endif + { +#ifndef COIN_HAS_CBC + CbcOrClpParam p("log!Level", "Level of detail in Solver output", + -1, COIN_INT_MAX, CLP_PARAM_INT_SOLVERLOGLEVEL); + parameters.push_back(p); +#else + CbcOrClpParam p("log!Level", "Level of detail in Coin branch and Cut output", + -63, 63, CLP_PARAM_INT_LOGLEVEL); + p.setIntValue(1); +#endif + p.setLonghelp( + "If 0 then there should be no output in normal circumstances. 1 is probably the best\ + value for most uses, while 2 and 3 give more information."); + parameters.push_back(p); + } + { + CbcOrClpParam p("max!imize", "Set optimization direction to maximize", + CLP_PARAM_ACTION_MAXIMIZE, 7); + p.setLonghelp( + "The default is minimize - use 'maximize' for maximization.\n\ +You can also use the parameters 'direction maximize'."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("maxF!actor", "Maximum number of iterations between \ +refactorizations", + 1, COIN_INT_MAX, CLP_PARAM_INT_MAXFACTOR); + p.setLonghelp( + "If this is left at its default value of 200 then CLP will guess a\ + value to use. CLP may decide to re-factorize earlier for accuracy."); + parameters.push_back(p); + } + { + CbcOrClpParam p("maxIt!erations", "Maximum number of iterations before \ +stopping", + 0, COIN_INT_MAX, CLP_PARAM_INT_MAXITERATION); + p.setLonghelp( + "This can be used for testing purposes. The corresponding library call\n\ + \tsetMaximumIterations(value)\n can be useful. If the code stops on\ + seconds or by an interrupt this will be treated as stopping on maximum iterations. This is ignored in branchAndCut - use maxN!odes."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("maxN!odes", "Maximum number of nodes to do", + -1, COIN_INT_MAX, CBC_PARAM_INT_MAXNODES); + p.setLonghelp( + "This is a repeatable way to limit search. Normally using time is easier \ +but then the results may not be repeatable."); + parameters.push_back(p); + } + { + CbcOrClpParam p("maxSaved!Solutions", "Maximum number of solutions to save", + 0, COIN_INT_MAX, CBC_PARAM_INT_MAXSAVEDSOLS); + p.setLonghelp( + "Number of solutions to save."); + parameters.push_back(p); + } + { + CbcOrClpParam p("maxSo!lutions", "Maximum number of feasible solutions to get", + 1, COIN_INT_MAX, CBC_PARAM_INT_MAXSOLS); + p.setLonghelp( + "You may want to stop after (say) two solutions or an hour. \ +This is checked every node in tree, so it is possible to get more solutions from heuristics."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("min!imize", "Set optimization direction to minimize", + CLP_PARAM_ACTION_MINIMIZE, 7); + p.setLonghelp( + "The default is minimize - use 'maximize' for maximization.\n\ +This should only be necessary if you have previously set maximization \ +You can also use the parameters 'direction minimize'."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("mipO!ptions", "Dubious options for mip", + 0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0); + p.setIntValue(1057); + parameters.push_back(p); + } + { + CbcOrClpParam p("more!MipOptions", "More dubious options for mip", + -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0); + parameters.push_back(p); + } + { + CbcOrClpParam p("more2!MipOptions", "More more dubious options for mip", + -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMOREMIPOPTIONS, 0); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcOrClpParam p("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts", + "off", CBC_PARAM_STR_MIXEDCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglMixedIntegerRounding2"); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("mess!ages", "Controls if Clpnnnn is printed", + "off", CLP_PARAM_STR_MESSAGES); + + p.append("on"); + p.setLonghelp("The default behavior is to put out messages such as:\n\ + Clp0005 2261 Objective 109.024 Primal infeas 944413 (758)\n\ +but this program turns this off to make it look more friendly. It can be useful\ + to turn them back on if you want to be able to 'grep' for particular messages or if\ + you intend to override the behavior of a particular message. This only affects Clp not Cbc."); + parameters.push_back(p); + } + { + CbcOrClpParam p("miplib", "Do some of miplib test set", + CBC_PARAM_ACTION_MIPLIB, 3, 1); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("mips!tart", "reads an initial feasible solution from file", + CBC_PARAM_ACTION_MIPSTART); + p.setLonghelp("\ +The MIPStart allows one to enter an initial integer feasible solution \ +to CBC. Values of the main decision variables which are active (have \ +non-zero values) in this solution are specified in a text file. The \ +text file format used is the same of the solutions saved by CBC, but \ +not all fields are required to be filled. First line may contain the \ +solution status and will be ignored, remaining lines contain column \ +indexes, names and values as in this example:\n\ +\n\ +Stopped on iterations - objective value 57597.00000000\n\ + 0 x(1,1,2,2) 1 \n\ + 1 x(3,1,3,2) 1 \n\ + 5 v(5,1) 2 \n\ + 33 x(8,1,5,2) 1 \n\ + ...\n\ +\n\ +Column indexes are also ignored since pre-processing can change them. \ +There is no need to include values for continuous or integer auxiliary \ +variables, since they can be computed based on main decision variables. \ +Starting CBC with an integer feasible solution can dramatically improve \ +its performance: several MIP heuristics (e.g. RINS) rely on having at \ +least one feasible solution available and can start immediately if the \ +user provides one. Feasibility Pump (FP) is a heuristic which tries to \ +overcome the problem of taking too long to find feasible solution (or \ +not finding at all), but it not always succeeds. If you provide one \ +starting solution you will probably save some time by disabling FP. \ +\n\n\ +Knowledge specific to your problem can be considered to write an \ +external module to quickly produce an initial feasible solution - some \ +alternatives are the implementation of simple greedy heuristics or the \ +solution (by CBC for example) of a simpler model created just to find \ +a feasible solution. \ +\n\n\ +Silly options added. If filename ends .low then integers not mentioned \ +are set low - also .high, .lowcheap, .highcheap, .lowexpensive, .highexpensive \ +where .lowexpensive sets costed ones to make expensive others low. Also if \ +filename starts empty. then no file is read at all - just actions done. \ +\n\n\ +Question and suggestions regarding MIPStart can be directed to\n\ +haroldo.santos@gmail.com. "); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp", + 0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("moreT!une", "Yet more dubious ideas for feasibility pump", + 0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0); + + p.setLonghelp( + "Yet more ideas for Feasibility Pump \n\ +\t/100000 == 1 use box constraints and original obj in cleanup\n\ +\t/1000 == 1 Pump will run twice if no solution found\n\ +\t/1000 == 2 Pump will only run after root cuts if no solution found\n\ +\t/1000 >10 as above but even if solution found\n\ +\t/100 == 1,3.. exact 1.0 for objective values\n\ +\t/100 == 2,3.. allow more iterations per pass\n\ +\t n fix if value of variable same for last n iterations."); + p.setIntValue(0); + parameters.push_back(p); + } + { + CbcOrClpParam p("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions", + 0, COIN_INT_MAX, CBC_PARAM_INT_MULTIPLEROOTS, 0); + p.setIntValue(0); + p.setLonghelp( + "Solve (in parallel, if enabled) the root phase this number of times, \ + each with its own different seed, and collect all solutions and cuts generated. \ + The actual format is aabbcc where aa is the number of extra passes; \ + if bb is non zero, then it is number of threads to use (otherwise uses threads setting); \ + and cc is the number of times to do root phase. \ +The solvers do not interact with each other. However if extra passes are specified \ +then cuts are collected and used in later passes - so there is interaction there. \ +Some parts of this implementation have their origin in idea of \ +Andrea Lodi, Matteo Fischetti, Michele Monaci, Domenico Salvagnin, and Andrea Tramontani."); + parameters.push_back(p); + } + { + CbcOrClpParam p("naive!Heuristics", "Whether to try some stupid heuristic", + "off", CBC_PARAM_STR_NAIVE, 7, 1); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp( + "This is naive heuristics which, e.g., fix all integers with costs to zero!. " + HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("netlib", "Solve entire netlib test set", + CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1); + p.setLonghelp( + "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\ +The user can set options before e.g. clp -presolve off -netlib"); + parameters.push_back(p); + } + { + CbcOrClpParam p("netlibB!arrier", "Solve entire netlib test set with barrier", + CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1); + p.setLonghelp( + "This exercises the unit test for clp and then solves the netlib test set using barrier.\ +The user can set options before e.g. clp -kkt on -netlib"); + parameters.push_back(p); + } + { + CbcOrClpParam p("netlibD!ual", "Solve entire netlib test set (dual)", + CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1); + + p.setLonghelp( + "This exercises the unit test for clp and then solves the netlib test set using dual.\ +The user can set options before e.g. clp -presolve off -netlib"); + parameters.push_back(p); + } + { + CbcOrClpParam p("netlibP!rimal", "Solve entire netlib test set (primal)", + CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1); + p.setLonghelp( + "This exercises the unit test for clp and then solves the netlib test set using primal.\ +The user can set options before e.g. clp -presolve off -netlibp"); + parameters.push_back(p); + } + { + CbcOrClpParam p("netlibT!une", "Solve entire netlib test set with 'best' algorithm", + CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1); + p.setLonghelp( + "This exercises the unit test for clp and then solves the netlib test set using whatever \ +works best. I know this is cheating but it also stresses the code better by doing a \ +mixture of stuff. The best algorithm was chosen on a Linux ThinkPad using native cholesky \ +with University of Florida ordering."); + parameters.push_back(p); + } + { + CbcOrClpParam p("network", "Tries to make network matrix", + CLP_PARAM_ACTION_NETWORK, 7, 0); + p.setLonghelp( + "Clp will go faster if the matrix can be converted to a network. The matrix\ + operations may be a bit faster with more efficient storage, but the main advantage\ + comes from using a network factorization. It will probably not be as fast as a \ +specialized network code."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("nextB!estSolution", "Prints next best saved solution to file", + CLP_PARAM_ACTION_NEXTBESTSOLUTION); + + p.setLonghelp( + "To write best solution, just use solution. This prints next best (if exists) \ + and then deletes it. \ + This will write a primitive solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."); + parameters.push_back(p); + } + { + CbcOrClpParam p("node!Strategy", "What strategy to use to select the next node from the branch and cut tree", + "hybrid", CBC_PARAM_STR_NODESTRATEGY); + p.append("fewest"); + p.append("depth"); + p.append("upfewest"); + p.append("downfewest"); + p.append("updepth"); + p.append("downdepth"); + p.setLonghelp( + "Normally before a feasible solution is found, CBC will choose a node with fewest infeasibilities. \ + Alternatively, one may choose tree-depth as the criterion. This requires the minimal amount of memory, but may take a long time to find the best solution.\ + Additionally, one may specify whether up or down branches must \ +be selected first (the up-down choice will carry on after a first solution has been bound). \ +The default choice 'hybrid' does breadth first on small depth nodes and then switches to 'fewest'."); + parameters.push_back(p); + } + { + CbcOrClpParam p("numberA!nalyze", "Number of analysis iterations", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0); + p.setLonghelp( + "This says how many iterations to spend at root node analyzing problem. \ +This is a first try and will hopefully become more sophisticated."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("objective!Scale", "Scale factor to apply to objective", + -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_OBJSCALE, 1); + p.setLonghelp( + "If the objective function has some very large values, you may wish to scale them\ + internally by this amount. It can also be set by autoscale. It is applied after scaling. You are unlikely to need this."); + p.setDoubleValue(1.0); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC +#ifdef COIN_HAS_NTY + { + CbcOrClpParam p("Orbit!alBranching", "Whether to try orbital branching", + "off", CBC_PARAM_STR_ORBITAL); + p.append("on"); + p.append("strong"); + p.append("force"); + p.append("simple"); + p.append("fastish"); + p.append("lightweight"); + p.append("moreprinting"); + p.append("cuts"); + p.append("cutslight"); + p.setLonghelp( + "This switches on Orbital branching. \ +Value 'on' just adds orbital, 'strong' tries extra fixing in strong branching. \ +'cuts' just adds global cuts to break symmetry. \ +'fastish' only computes symmetry at root. \ +'lightweight' is as on where computation seems cheap"); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("PrepN!ames", "If column names will be kept in pre-processed model", + "off", CBC_PARAM_STR_PREPROCNAMES); + p.append("on"); + p.setLonghelp( + "Normally the preprocessed model has column names replaced by new names C0000...\ +Setting this option to on keeps original names in variables which still exist in the preprocessed problem"); + parameters.push_back(p); + } + + { + CbcOrClpParam p("outDup!licates", "takes duplicate rows etc out of integer model", + CLP_PARAM_ACTION_OUTDUPROWS, 7, 0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("output!Format", "Which output format to use", + 1, 6, CLP_PARAM_INT_OUTPUTFORMAT); + p.setLonghelp( + "Normally export will be done using normal representation for numbers and two values\ + per line. You may want to do just one per line (for grep or suchlike) and you may wish\ + to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\ + otherwise odd values gives one value per line, even two. Values 1,2 give normal format, 3,4\ + gives greater precision, while 5,6 give IEEE values. When used for exporting a basis 1 does not save \ +values, 2 saves values, 3 with greater accuracy and 4 in IEEE."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("para!metrics", "Import data from file and do parametrics", + CLP_PARAM_ACTION_PARAMETRICS, 3); + p.setLonghelp( + "This will read a file with parametric data from the given file name \ +and then do parametrics. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. This can not read from compressed files. \ +File is in modified csv format - a line ROWS will be followed by rows data \ +while a line COLUMNS will be followed by column data. The last line \ +should be ENDATA. The ROWS line must exist and is in the format \ +ROWS, inital theta, final theta, interval theta, n where n is 0 to get \ +CLPI0062 message at interval or at each change of theta \ +and 1 to get CLPI0063 message at each iteration. If interval theta is 0.0 \ +or >= final theta then no interval reporting. n may be missed out when it is \ +taken as 0. If there is Row data then \ +there is a headings line with allowed headings - name, number, \ +lower(rhs change), upper(rhs change), rhs(change). Either the lower and upper \ +fields should be given or the rhs field. \ +The optional COLUMNS line is followed by a headings line with allowed \ +headings - name, number, objective(change), lower(change), upper(change). \ + Exactly one of name and number must be given for either section and \ +missing ones have value 0.0."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("passC!uts", "Number of rounds that cut generators are applied in the root node", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASS); + + p.setIntValue(20); + p.setLonghelp( + "The default is to do 100 passes if the problem has less than 500 columns, 100 passes (but \ +stop if the drop in the objective function value is small) if the problem has less than 5000 columns, and 20 passes otherwise. \ +A negative value -n means that n passes are also applied if the objective does not drop."); + parameters.push_back(p); + } + { + CbcOrClpParam p("passF!easibilityPump", "How many passes to do in the Feasibility Pump heuristic", + 0, 10000, CBC_PARAM_INT_FPUMPITS); + p.setIntValue(20); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("passP!resolve", "How many passes in presolve", + -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1); + p.setLonghelp( + "Normally Presolve does 10 passes but you may want to do less to make it\ + more lightweight or do more if improvements are still being made. As Presolve will return\ + if nothing is being taken out, you should not normally need to use this fine tuning."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("passT!reeCuts", "Number of rounds that cut generators are applied in the tree", + -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_CUTPASSINTREE); + p.setIntValue(1); + p.setLonghelp("The default is to do one pass. A negative value -n means that n passes are also applied if the objective does not drop."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("pertV!alue", "Method of perturbation", + -5000, 102, CLP_PARAM_INT_PERTVALUE, 1); + parameters.push_back(p); + } + { + CbcOrClpParam p("perturb!ation", "Whether to perturb the problem", + "on", CLP_PARAM_STR_PERTURBATION); + p.append("off"); + p.setLonghelp( + "Perturbation helps to stop cycling, but CLP uses other measures for this.\ + However, large problems and especially ones with unit elements and unit right hand sides or costs\ + benefit from perturbation. Normally CLP tries to be intelligent, but one can switch this off."); + // The Clp library has this off by default. This program has it on by default. + parameters.push_back(p); + } + { + CbcOrClpParam p("PFI", "Whether to use Product Form of Inverse in simplex", + "off", CLP_PARAM_STR_PFI, 7, 0); + p.append("on"); + p.setLonghelp( + "By default clp uses Forrest-Tomlin L-U update. If you are masochistic you can switch it off."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic", + "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT); + + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("pivotAndF!ix", "Whether to try Pivot and Fix heuristic", + "off", CBC_PARAM_STR_PIVOTANDFIX); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("plus!Minus", "Tries to make +- 1 matrix", + CLP_PARAM_ACTION_PLUSMINUS, 7, 0); + p.setLonghelp( + "Clp will go slightly faster if the matrix can be converted so that the elements are\ + not stored and are known to be unit. The main advantage is memory use. Clp may automatically\ + see if it can convert the problem so you should not need to use this."); + parameters.push_back(p); + } + { + CbcOrClpParam p("pO!ptions", "Dubious print options", + 0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1); + p.setIntValue(0); + p.setLonghelp( + "If this is > 0 then presolve will give more information and branch and cut will give statistics"); + parameters.push_back(p); + } + { + CbcOrClpParam p("preO!pt", "Presolve options", + 0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("presolve", "Whether to presolve problem", + "on", CLP_PARAM_STR_PRESOLVE); + p.append("off"); + p.append("more"); + p.append("file"); + p.setLonghelp("Presolve analyzes the model to find such things as redundant equations, equations\ + which fix some variables, equations which can be transformed into bounds, etc. For the\ + initial solve of any problem this is worth doing unless one knows that it will have no effect. \ +Option 'on' will normally do 5 passes, while using 'more' will do 10. If the problem is very large one can \ +let CLP write the original problem to file by using 'file'."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("preprocess", "Whether to use integer preprocessing", + "off", CBC_PARAM_STR_PREPROCESS); + + p.append("on"); + p.append("save"); + p.append("equal"); + p.append("sos"); + p.append("trysos"); + p.append("equalall"); + p.append("strategy"); + p.append("aggregate"); + p.append("forcesos"); + p.append("stop!aftersaving"); + p.setLonghelp( + "This tries to reduce size of model in a similar way to presolve and \ +it also tries to strengthen the model - this can be very useful and is worth trying. \ + Value 'save' saves the presolved problem to a file presolved.mps.\ + Value 'equal' will turn inequality-cliques into equalities.\ + Value 'sos' lets CBC search for rows with upper bound 1 and where all nonzero coefficients are 1 and creates special ordered sets if the sets are not overlapping and all integer variables (except for at most one) are in the sets.\ + Value 'trysos' is same as 'sos', but allows any number of integer variables outside of sets.\ + Value 'equalall' lets CBC turn all valid inequalities into equalities by adding integer slack variables."); // Value 'strategy' is as on but uses CbcStrategy. + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("preT!olerance", "Tolerance to use in presolve", + 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRESOLVETOLERANCE); + p.setLonghelp( + "One may want to increase this tolerance if presolve says the problem is \ +infeasible and one has awkward numbers and is sure that the problem is really feasible."); + parameters.push_back(p); + } + { + CbcOrClpParam p("primalP!ivot", "Primal pivot choice algorithm", + "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1); + + p.append("exa!ct"); + p.append("dant!zig"); + p.append("part!ial"); + p.append("steep!est"); + p.append("change"); + p.append("sprint"); + p.append("PEsteep!est"); + p.append("PEdantzig"); + p.setLonghelp( + "The Dantzig method is simple but its use is deprecated. Exact devex is the method of choice and there\ + are two variants which keep all weights updated but only scan a subset each iteration.\ + Partial switches this on while 'change' initially does 'dantzig' until the factorization\ + becomes denser. This is still a work in progress.\ + The PE variants add the Positive Edge criterion.\ + This selects incoming variables to try to avoid degenerate moves. \ + See also Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP;\ + Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex."); + + parameters.push_back(p); + } + { + CbcOrClpParam p("primalS!implex", "Do primal simplex algorithm", + CLP_PARAM_ACTION_PRIMALSIMPLEX); + + p.setLonghelp( + "This command solves the continuous relaxation of the current model using the primal algorithm.\ + The default is to use exact devex.\ + The time and iterations may be affected by settings such as presolve, scaling, crash\ + and also by column selection method, infeasibility weight and dual and primal tolerances."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("primalT!olerance", "For a feasible solution \ +no primal infeasibility, i.e., constraint violation, may exceed this value", + 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRIMALTOLERANCE); + p.setLonghelp( + "Normally the default tolerance is fine, but one may want to increase it a\ + bit if the primal simplex algorithm seems to be having a hard time."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("primalW!eight", "Initially algorithm acts as if it \ +costs this much to be infeasible", + 1.0e-20, COIN_DBL_MAX, CLP_PARAM_DBL_PRIMALWEIGHT); + p.setLonghelp( + "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\ + algorithm where you first get feasible then optimal. So Clp is minimizing this weight times\ + the sum of primal infeasibilities plus the true objective function (in minimization sense).\ + Too high a value may mean more iterations, while too low a value means\ + the algorithm may iterate into the wrong directory for long and then has to increase the weight in order to get feasible."); // OSL had a heuristic to adjust bounds, maybe we need that here. + parameters.push_back(p); + } + { + CbcOrClpParam p("psi", "Two-dimension pricing factor for Positive Edge criterion", + -1.1, 1.1, CLP_PARAM_DBL_PSI); + + p.setDoubleValue(-0.5); + p.setLonghelp( + "The Positive Edge criterion has been added to \ +select incoming variables to try and avoid degenerate moves. \ +Variables not in the promising set have their infeasibility weight multiplied by psi, \ +so 0.01 would mean that if there were any promising variables, then they would always be chosen, \ +while 1.0 effectively switches the algorithm off. \ +There are two ways of switching this feature on. One way is to set psi to a positive value and then \ +the Positive Edge criterion will be used for both primal and dual simplex. The other way is to select PEsteepest \ +in dualpivot choice (for example), then the absolute value of psi is used. \ +Code donated by Jeremy Omer. See \ +Towhidi, M., Desrosiers, J., Soumis, F., The positive edge criterion within COIN-OR's CLP; \ +Omer, J., Towhidi, M., Soumis, F., The positive edge pricing rule for the dual simplex."); // Until this settles down it is only implemented in CLP. + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("printi!ngOptions", "Print options", + "normal", CLP_PARAM_STR_INTPRINT, 3); + p.append("integer"); + p.append("special"); + p.append("rows"); + p.append("all"); + p.append("csv"); + p.append("bound!ranging"); + p.append("rhs!ranging"); + p.append("objective!ranging"); + p.append("stats"); + p.append("boundsint"); + p.append("boundsall"); + p.append("fixint"); + p.append("fixall"); + p.setLonghelp( + "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\ +integer - nonzero integer column variables\n\ +special - in format suitable for OsiRowCutDebugger\n\ +rows - nonzero column variables and row activities\n\ +all - all column variables and row activities.\n\ +\nFor non-integer problems 'integer' and 'special' act like 'normal'. \ +Also see printMask for controlling output."); + parameters.push_back(p); + } + { + CbcOrClpParam p("printM!ask", "Control printing of solution on a mask", + CLP_PARAM_ACTION_PRINTMASK, 3); + + p.setLonghelp( + "If set then only those names which match mask are printed in a solution. \ +'?' matches any character and '*' matches any set of characters. \ + The default is '' i.e. unset so all variables are printed. \ +This is only active if model has names."); + parameters.push_back(p); + } + +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("prio!rityIn", "Import priorities etc from file", + CBC_PARAM_ACTION_PRIORITYIN, 3); + p.setLonghelp( + "This will read a file with priorities from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to '', i.e. it must be set. This can not read from compressed files. \ +File is in csv format with allowed headings - name, number, priority, direction, up, down, solution. Exactly one of\ + name and number must be given."); + parameters.push_back(p); + } + + { + CbcOrClpParam p("probing!Cuts", "Whether to use Probing cuts", + "off", CBC_PARAM_STR_PROBINGCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceonglobal"); + p.append("forceOnBut"); + p.append("forceOnStrong"); + p.append("forceOnButStrong"); + p.append("strongRoot"); + p.setLonghelp(CUTS_LONGHELP + " Value 'forceOnBut' turns on probing and forces CBC to do probing at every node, but does only probing, not strengthening etc. \ + Value 'strong' forces CBC to strongly do probing at every node, that is, also when CBC would usually turn it off because it hasn't found something. \ + Value 'forceonbutstrong' is like 'forceonstrong', but does only probing (column fixing) and turns off row strengthening, so the matrix will not change inside the branch and bound. \ + Reference: https://github.com/coin-or/Cgl/wiki/CglProbing"); + parameters.push_back(p); + } + { + CbcOrClpParam p("proximity!Search", "Whether to do proximity search heuristic", + "off", CBC_PARAM_STR_PROXIMITY); + + p.append("on"); + p.append("both"); + p.append("before"); + p.append("10"); + p.append("100"); + p.append("300"); + // but allow numbers after this (returning 1) + p.setFakeKeyWord(1); + p.setLonghelp( + "This heuristic looks for a solution close to the incumbent solution (Fischetti and Monaci, 2012). \ +The idea is to define a sub-MIP without additional constraints but with a modified objective function intended to attract the search \ +in the proximity of the incumbent. \ +The approach works well for 0-1 MIPs whose solution landscape is not too irregular (meaning the there is reasonable probability of \ +finding an improved solution by flipping a small number of binary variables), in particular when it is applied to the first heuristic solutions \ +found at the root node. " + HEURISTICS_LONGHELP); // Can also set different maxNode settings by plusnnnn (and are 'on'(on==30)). + parameters.push_back(p); + } + { + CbcOrClpParam p("pumpC!utoff", "Fake cutoff for use in feasibility pump", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF); + p.setDoubleValue(0.0); + p.setLonghelp( + "A value of 0.0 means off. Otherwise, add a constraint forcing objective below this value\ + in feasibility pump"); + parameters.push_back(p); + } + { + CbcOrClpParam p("pumpI!ncrement", "Fake increment for use in feasibility pump", + -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1); + p.setDoubleValue(0.0); + p.setLonghelp( + "A value of 0.0 means off. Otherwise use as absolute increment to cutoff \ +when solution found in feasibility pump"); + parameters.push_back(p); + } + { + CbcOrClpParam p("pumpT!une", "Dubious ideas for feasibility pump", + 0, 100000000, CBC_PARAM_INT_FPUMPTUNE); + p.setIntValue(1003); + p.setLonghelp( + "This fine tunes Feasibility Pump \n\ +\t>=10000000 use as objective weight switch\n\ +\t>=1000000 use as accumulate switch\n\ +\t>=1000 use index+1 as number of large loops\n\ +\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\ +\t%100 == 10,20 affects how each solve is done\n\ +\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \ +If accumulate is on then after a major pass, variables which have not moved \ +are fixed and a small branch and bound is tried."); + p.setIntValue(0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("quit", "Stops clp execution", + CLP_PARAM_ACTION_EXIT); + p.setLonghelp( + "This stops the execution of Clp, end, exit, quit and stop are synonyms"); + + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("randomC!bcSeed", "Random seed for Cbc", + -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED); + + p.setLonghelp( + "Allows initialization of the random seed for pseudo-random numbers used in heuristics such as the Feasibility Pump to decide whether to round up or down. " + "The special value of 0 lets Cbc use the time of the day for the initial seed."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("randomi!zedRounding", "Whether to try randomized rounding heuristic", + "off", CBC_PARAM_STR_RANDROUND); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("randomS!eed", "Random seed for Clp", + 0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED); + + p.setLonghelp( + "Initialization of the random seed for pseudo-random numbers used to break ties in degenerate problems. " + "This may yield a different continuous optimum and, in the context of Cbc, different cuts and heuristic solutions. " + "The special value of 0 lets CLP use the time of the day for the initial seed."); + p.setIntValue(1234567); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("ratio!Gap", "Stop when gap between best possible and \ +best known is less than this fraction of larger of two", + 0.0, COIN_DBL_MAX, CBC_PARAM_DBL_GAPRATIO); + p.setDoubleValue(0.0); + p.setLonghelp( + "If the gap between the best known solution and the best possible solution is less than this fraction \ +of the objective value at the root node then the search will terminate. See 'allowableGap' for a \ +way of using absolute value rather than fraction."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("restoreS!olution", "reads solution from file", + CLP_PARAM_ACTION_RESTORESOL); + + p.setLonghelp( + "This will read a binary solution file from the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'solution.file'. This reads in a file from saveSolution"); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("readSt!ored", "Import stored cuts from file", + CLP_PARAM_ACTION_STOREDFILE, 3, 0); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("reallyO!bjectiveScale", "Scale factor to apply to objective in place", + -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_OBJSCALE2, 0); + p.setLonghelp("You can set this to -1.0 to test maximization or other to stress code"); + p.setDoubleValue(1.0); + parameters.push_back(p); + } + { + CbcOrClpParam p("reallyS!cale", "Scales model in place", + CLP_PARAM_ACTION_REALLY_SCALE, 7, 0); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts", + "off", CBC_PARAM_STR_REDSPLITCUTS); + + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp( + "These cuts may be expensive to generate. " + CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglRedSplit"); + parameters.push_back(p); + } + { + CbcOrClpParam p("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2", + "off", CBC_PARAM_STR_REDSPLIT2CUTS); + p.append("on"); + p.append("root"); + p.append("longOn"); + p.append("longRoot"); + p.setLonghelp("This switches on reduce and split cuts (either at root or in entire tree). \ +This version is by Giacomo Nannicini based on Francois Margot's version. \ +Standard setting only uses rows in tableau <= 256, long uses all. \ +These cuts may be expensive to generate. \ +See option cuts for more information on the possible values."); + parameters.push_back(p); + } + { + CbcOrClpParam p("residual!CapacityCuts", "Whether to use Residual Capacity cuts", + "off", CBC_PARAM_STR_RESIDCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglResidualCapacity"); + + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("restore!Model", "Restore model from binary file", + CLP_PARAM_ACTION_RESTORE, 7, 1); + p.setLonghelp( + "This reads data save by saveModel from the given file. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.prob'."); + + parameters.push_back(p); + } + { + CbcOrClpParam p("reverse", "Reverses sign of objective", + CLP_PARAM_ACTION_REVERSE, 7, 0); + p.setLonghelp( + "Useful for testing if maximization works correctly"); + parameters.push_back(p); + } + { + CbcOrClpParam p("rhs!Scale", "Scale factor to apply to rhs and bounds", + -COIN_DBL_MAX, COIN_DBL_MAX, CLP_PARAM_DBL_RHSSCALE, 0); + p.setLonghelp( + "If the rhs or bounds have some very large meaningful values, you may wish to scale them\ + internally by this amount. It can also be set by autoscale. This should not be needed."); + p.setDoubleValue(1.0); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("Rens", "Whether to try Relaxation Enforced Neighborhood Search", + "off", CBC_PARAM_STR_RENS); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("200"); + p.append("1000"); + p.append("10000"); + p.append("dj"); + p.append("djbefore"); + p.append("usesolution"); + p.setLonghelp(HEURISTICS_LONGHELP + " Value 'on' just does 50 nodes. 200, 1000, and 10000 does that many nodes."); + parameters.push_back(p); + } + { + CbcOrClpParam p("Rins", "Whether to try Relaxed Induced Neighborhood Search", + "off", CBC_PARAM_STR_RINS); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("often"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } + { + CbcOrClpParam p("round!ingHeuristic", "Whether to use simple (but effective) Rounding heuristic", + "off", CBC_PARAM_STR_ROUNDING); + p.append("on"); + p.append("both"); + p.append("before"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("saveM!odel", "Save model to binary file", + CLP_PARAM_ACTION_SAVE, 7, 1); + p.setLonghelp( + "This will save the problem to the given file name for future use\ + by restoreModel. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'default.prob'."); + parameters.push_back(p); + } + { + CbcOrClpParam p("saveS!olution", "saves solution to file", + CLP_PARAM_ACTION_SAVESOL); + + p.setLonghelp( + "This will write a binary solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'solution.file'. To read the file use fread(int) twice to pick up number of rows \ +and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \ +activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \ +If name contains '_fix_read_' then does not write but reads and will fix all variables"); + parameters.push_back(p); + } + { + CbcOrClpParam p("scal!ing", "Whether to scale problem", + "off", CLP_PARAM_STR_SCALING); + p.append("equi!librium"); + p.append("geo!metric"); + p.append("auto!matic"); + p.append("dynamic"); + p.append("rows!only"); + p.setLonghelp( + "Scaling can help in solving problems which might otherwise fail because of lack of\ + accuracy. It can also reduce the number of iterations. It is not applied if the range\ + of elements is small. When the solution is evaluated in the unscaled problem, it is possible that small primal and/or\ + dual infeasibilities occur. " + "Option 'equilibrium' uses the largest element for scaling. " + "Option 'geometric' uses the squareroot of the product of largest and smallest element. " + "Option 'auto' let CLP choose a method that gives the best ratio of the largest element to the smallest one."); + p.setCurrentOption(3); // say auto + parameters.push_back(p); + } +#ifndef COIN_HAS_CBC + { + CbcOrClpParam p("sec!onds", "Maximum seconds", + -1.0, COIN_DBL_MAX, CLP_PARAM_DBL_TIMELIMIT); + + p.setLonghelp("After this many seconds clp will act as if maximum iterations had been reached \ +(if value >=0)."); + parameters.push_back(p); + } +#else + { + CbcOrClpParam p("sec!onds", "maximum seconds", + -1.0, COIN_DBL_MAX, CBC_PARAM_DBL_TIMELIMIT_BAB); + p.setLonghelp( + "After this many seconds coin solver will act as if maximum nodes had been reached."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("sleep", "for debug", + CLP_PARAM_ACTION_DUMMY, 7, 0); + + p.setLonghelp( + "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("slow!cutpasses", "Maximum number of rounds for slower cut generators", + -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS); + p.setLonghelp( + "Some cut generators are fairly slow - this limits the number of times they are tried.\ + The cut generators identified as 'may be slow' at present are Lift and project cuts and both versions of Reduce and Split cuts."); + p.setIntValue(10); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("slp!Value", "Number of slp passes before primal", + -50000, 50000, CLP_PARAM_INT_SLPVALUE, 1); + p.setLonghelp( + "If you are solving a quadratic problem using primal then it may be helpful to do some \ +sequential Lps to get a good approximate solution."); + parameters.push_back(p); + } +#if CLP_MULTIPLE_FACTORIZATIONS > 0 + { + CbcOrClpParam p("small!Factorization", "Threshold for using small factorization", + -1, 10000, CBC_PARAM_INT_SMALLFACT, 1); + p.setLonghelp( + "If processed problem <= this use small factorization"); + p.setIntValue(-1); + parameters.push_back(p); + } +#endif +#endif + { + CbcOrClpParam p("solu!tion", "Prints solution to file", + CLP_PARAM_ACTION_SOLUTION); + p.setLonghelp( + "This will write a primitive solution file to the given file name. It will use the default\ + directory given by 'directory'. A name of '$' will use the previous value for the name. This\ + is initialized to 'stdout'. The amount of output can be varied using printi!ngOptions or printMask."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CLP +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("solv!e", "Solve problem", + CBC_PARAM_ACTION_BAB); + p.setLonghelp( + "If there are no integer variables then this just solves LP. If there are integer variables \ +this does branch and cut." ); + parameters.push_back( p ); + } + { + CbcOrClpParam p("sosO!ptions", "Whether to use SOS from AMPL", "off", CBC_PARAM_STR_SOS); + p.append("on"); + p.setCurrentOption("on"); + p.setLonghelp( + "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\ + be turned off - this does so." ); + parameters.push_back( p ); + } + { + CbcOrClpParam p("slog!Level", "Level of detail in (LP) Solver output", -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL); + p.setLonghelp( + "If 0 then there should be no output in normal circumstances. 1 is probably the best\ + value for most uses, while 2 and 3 give more information. This parameter is only used inside MIP - for Clp use 'log'"); + parameters.push_back(p); + } + { + // Due to James Howey + CbcOrClpParam p("sosP!rioritize", "How to deal with SOS priorities", + "off", CBC_PARAM_STR_SOSPRIORITIZE); + p.append("high"); + p.append("low"); + p.append("orderhigh"); + p.append("orderlow"); + p.setLonghelp( + "This sets priorities for SOS. Values 'high' and 'low' just set a priority \ + relative to the for integer variables. Value 'orderhigh' gives first highest priority to the first SOS and integer variables \ + a low priority. Value 'orderlow' gives integer variables a high priority then SOS in order."); + parameters.push_back(p); + } +#else + // allow solve as synonym for possible dual + { + CbcOrClpParam p("solv!e", "Solve problem using dual simplex (probably)", + CLP_PARAM_ACTION_EITHERSIMPLEX); + p.setLonghelp( + "Just so can use solve for clp as well as in cbc"); + parameters.push_back(p); + } +#endif +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("spars!eFactor", "Whether factorization treated as sparse", + "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0); + p.append("off"); + parameters.push_back(p); + } + { + CbcOrClpParam p("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp", + 0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0); + parameters.push_back(p); + } + { + CbcOrClpParam p("sprint!Crash", "Whether to try sprint crash", + -1, COIN_INT_MAX, CLP_PARAM_INT_SPRINT); + p.setLonghelp( + "For long and thin problems this method may solve a series of small problems\ + created by taking a subset of the columns. The idea as 'Sprint' was introduced by J. Forrest after\ + an LP code of that name of the 60's which tried the same tactic (not totally successfully).\ + CPLEX calls it 'sifting'. -1 lets CLP automatically choose the number of passes, 0 is off, n is number of passes"); + parameters.push_back(p); + } + { + CbcOrClpParam p("stat!istics", "Print some statistics", + CLP_PARAM_ACTION_STATISTICS); + p.setLonghelp( + "This command prints some statistics for the current model.\ + If log level >1 then more is printed.\ + These are for presolved model if presolve on (and unscaled)."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("stop", "Stops clp execution", + CLP_PARAM_ACTION_EXIT); + p.setLonghelp( + "This stops the execution of Clp, end, exit, quit and stop are synonyms"); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("strat!egy", "Switches on groups of features", + 0, 2, CBC_PARAM_INT_STRATEGY); + p.setLonghelp( + "This turns on newer features. \ +Use 0 for easy problems, 1 is default, 2 is aggressive. \ +1 uses Gomory cuts with a tolerance of 0.01 at the root node, \ +does a possible restart after 100 nodes if many variables could be fixed, \ +activates a diving and RINS heuristic, and makes the feasibility pump \ +more aggressive."); // This does not apply to unit tests (where 'experiment' may have similar effects + p.setIntValue(1); + parameters.push_back(p); + } +#ifdef CBC_KEEP_DEPRECATED + { + CbcOrClpParam p("strengthen", "Create strengthened problem", + CBC_PARAM_ACTION_STRENGTHEN, 3); + p.setLonghelp( + "This creates a new problem by applying the root node cuts. All tight constraints \ +will be in resulting problem"); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("strong!Branching", "Number of variables to look at in strong branching", + 0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING); + p.setIntValue(20); + p.setLonghelp( + "In order to decide which variable to branch on, the code will choose up to this number \ +of unsatisfied variables to try minimal up and down branches on. Then the most effective one is chosen. \ +If a variable is branched on many times then the previous average up and down costs may be used - \ +see also option trustPseudoCosts."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("subs!titution", "How long a column to substitute for in presolve", + 0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0); + p.setLonghelp( + "Normally Presolve gets rid of 'free' variables when there are no more than 3 \ + coefficients in a row. If you increase this, the number of rows may decrease but the number of \ + coefficients may increase."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("testO!si", "Test OsiObject stuff", + -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0); + parameters.push_back(p); + } +#endif +#ifdef CBC_THREAD + { + CbcOrClpParam p("thread!s", "Number of threads to try and use", + -100, 100000, CBC_PARAM_INT_THREADS, 1); + p.setIntValue(0); + p.setLonghelp( + "To use multiple threads, set threads to number wanted. It may be better \ +to use one or two more than number of cpus available. If 100+n then n threads and \ +search is repeatable (maybe be somewhat slower), \ +if 200+n use threads for root cuts, 400+n threads used in sub-trees."); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("tighten!Factor", "Tighten bounds using this times largest \ +activity at continuous solution", + 1.0e-3, COIN_DBL_MAX, CBC_PARAM_DBL_TIGHTENFACTOR, 0); + p.setLonghelp( + "This sleazy trick can help on some problems."); + parameters.push_back(p); + } + +#endif +#ifdef COIN_HAS_CLP + { + CbcOrClpParam p("tightLP", "Poor person's preSolve for now", + CLP_PARAM_ACTION_TIGHTEN, 7, 0); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("timeM!ode", "Whether to use CPU or elapsed time", + "cpu", CLP_PARAM_STR_TIME_MODE); + p.append("elapsed"); + p.setLonghelp( + "cpu uses CPU time for stopping, while elapsed uses elapsed time. \ +(On Windows, elapsed time is always used)."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("trust!PseudoCosts", "Number of branches before we trust pseudocosts", + -3, COIN_INT_MAX, CBC_PARAM_INT_NUMBERBEFORE); + p.setLonghelp( + "Using strong branching computes pseudo-costs. This parameter determines after how many branches for a variable we just \ +trust the pseudo costs and do not do any more strong branching."); + p.setIntValue(10); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("tune!PreProcess", "Dubious tuning parameters for preprocessing", + 0, COIN_INT_MAX, CLP_PARAM_INT_PROCESSTUNE, 1); + p.setLonghelp( + "Format aabbcccc - \n If aa then this is number of major passes (i.e. with presolve) \n \ +If bb and bb>0 then this is number of minor passes (if unset or 0 then 10) \n \ +cccc is bit set \n 0 - 1 Heavy probing \n 1 - 2 Make variables integer if possible (if obj value)\n \ +2 - 4 As above but even if zero objective value\n \ +7 - 128 Try and create cliques\n 8 - 256 If all +1 try hard for dominated rows\n \ +10 - 1024 Use a larger feasibility tolerance in presolve\n \ +11 - 2048 Try probing before creating cliques\n \ +12 - 4096 Switch off duplicate column checking for integers \n \n \ + Now aa 99 has special meaning i.e. just one simple presolve."); + parameters.push_back(p); + } + { + CbcOrClpParam p("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts", + "off", CBC_PARAM_STR_TWOMIRCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.append("forceandglobal"); + p.append("forceLongOn"); + p.setLonghelp(CUTS_LONGHELP + " Reference: https://github.com/coin-or/Cgl/wiki/CglTwomir"); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("unitTest", "Do unit test", + CLP_PARAM_ACTION_UNITTEST, 3, 1); + p.setLonghelp( + "This exercises the unit test for clp"); + parameters.push_back(p); + } + { + CbcOrClpParam p("userClp", "Hand coded Clp stuff", + CLP_PARAM_ACTION_USERCLP, 0, 0); + p.setLonghelp( + "There are times e.g. when using AMPL interface when you may wish to do something unusual. \ +Look for USERCLP in main driver and modify sample code."); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("userCbc", "Hand coded Cbc stuff", + CBC_PARAM_ACTION_USERCBC, 0, 0); + p.setLonghelp( + "There are times e.g. when using AMPL interface when you may wish to do something unusual. \ +Look for USERCBC in main driver and modify sample code. \ +It is possible you can get same effect by using example driver4.cpp."); + parameters.push_back(p); + } +#endif +#ifdef COIN_AVX2 + { + CbcOrClpParam p("vector!Mode", "Try and use vector instructions", + 0, 11, CLP_PARAM_INT_VECTOR_MODE); + p.setLonghelp( + "At present only for Intel architectures - but could be extended. \ +Uses avx2 or avx512 instructions. Uses different storage for matrix - can be \ +of benefit without instruction set on some problems. \ +Being lazy I have used 10 to switch on a pool matrix (11 may come later)"); + p.setIntValue(0); + parameters.push_back(p); + } +#endif +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search", + "off", CBC_PARAM_STR_VND); + p.append("on"); + p.append("both"); + p.append("before"); + p.append("intree"); + p.setLonghelp(HEURISTICS_LONGHELP); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("vector", "Whether to use vector? Form of matrix in simplex", + "off", CLP_PARAM_STR_VECTOR, 7, 0); + p.append("on"); + p.setLonghelp( + "If this is on ClpPackedMatrix uses extra column copy in odd format."); + parameters.push_back(p); + } + { + CbcOrClpParam p("verbose", "Switches on longer help on single ?", + 0, 31, CLP_PARAM_INT_VERBOSE, 0); + p.setLonghelp( + "Set to 1 to get short help with ? list, 2 to get long help, 3 for both. (add 4 to just get ampl ones)."); + p.setIntValue(0); + parameters.push_back(p); + } +#ifdef COIN_HAS_CBC + { + CbcOrClpParam p("vub!heuristic", "Type of VUB heuristic", + -2, 20, CBC_PARAM_INT_VUBTRY, 0); + p.setLonghelp( + "This heuristic tries and fix some integer variables."); + p.setIntValue(-1); + parameters.push_back(p); + } + { + CbcOrClpParam p("zero!HalfCuts", "Whether to use zero half cuts", + "off", CBC_PARAM_STR_ZEROHALFCUTS); + p.append("on"); + p.append("root"); + p.append("ifmove"); + p.append("forceOn"); + p.append("onglobal"); + p.setLonghelp(CUTS_LONGHELP + " This implementation was written by Alberto Caprara."); + parameters.push_back(p); + } +#endif + { + CbcOrClpParam p("zeroT!olerance", "Kill all coefficients \ +whose absolute value is less than this value", + 1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE); + p.setLonghelp( + "This applies to reading mps files (and also lp files \ +if KILL_ZERO_READLP defined)"); + p.setDoubleValue(1.0e-20); + parameters.push_back(p); + } +} +// Given a parameter type - returns its number in list +int whichParam(const CbcOrClpParameterType &name, + const std::vector< CbcOrClpParam > ¶meters) +{ + for (int i = 0; i < (int)parameters.size(); i++) { + if (parameters[i].type() == name) + return i; + } + return std::numeric_limits< int >::max(); // should not arrive here +} +#ifdef COIN_HAS_CLP +/* Restore a solution from file. + mode 0 normal, 1 swap rows and columns and primal and dual + if 2 set then also change signs +*/ +void restoreSolution(ClpSimplex *lpSolver, std::string fileName, int mode) +{ + FILE *fp = fopen(fileName.c_str(), "rb"); + if (fp) { + int numberRows = lpSolver->numberRows(); + int numberColumns = lpSolver->numberColumns(); + int numberRowsFile; + int numberColumnsFile; + double objectiveValue; + size_t nRead; + nRead = fread(&numberRowsFile, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&numberColumnsFile, sizeof(int), 1, fp); + if (nRead != 1) + throw("Error in fread"); + nRead = fread(&objectiveValue, sizeof(double), 1, fp); + if (nRead != 1) + throw("Error in fread"); + double *dualRowSolution = lpSolver->dualRowSolution(); + double *primalRowSolution = lpSolver->primalRowSolution(); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + double *primalColumnSolution = lpSolver->primalColumnSolution(); + if (mode) { + // swap + int k = numberRows; + numberRows = numberColumns; + numberColumns = k; + double *temp; + temp = dualRowSolution; + dualRowSolution = primalColumnSolution; + primalColumnSolution = temp; + temp = dualColumnSolution; + dualColumnSolution = primalRowSolution; + primalRowSolution = temp; + } + if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) { + std::cout << "Mismatch on rows and/or columns - giving up" << std::endl; + } else { + lpSolver->setObjectiveValue(objectiveValue); + if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) { + nRead = fread(primalRowSolution, sizeof(double), numberRows, fp); + if (nRead != static_cast< size_t >(numberRows)) + throw("Error in fread"); + nRead = fread(dualRowSolution, sizeof(double), numberRows, fp); + if (nRead != static_cast< size_t >(numberRows)) + throw("Error in fread"); + nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp); + if (nRead != static_cast< size_t >(numberColumns)) + throw("Error in fread"); + nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp); + if (nRead != static_cast< size_t >(numberColumns)) + throw("Error in fread"); + } else { + std::cout << "Mismatch on rows and/or columns - truncating" << std::endl; + double *temp = new double[CoinMax(numberRowsFile, numberColumnsFile)]; + nRead = fread(temp, sizeof(double), numberRowsFile, fp); + if (nRead != static_cast< size_t >(numberRowsFile)) + throw("Error in fread"); + CoinMemcpyN(temp, numberRows, primalRowSolution); + nRead = fread(temp, sizeof(double), numberRowsFile, fp); + if (nRead != static_cast< size_t >(numberRowsFile)) + throw("Error in fread"); + CoinMemcpyN(temp, numberRows, dualRowSolution); + nRead = fread(temp, sizeof(double), numberColumnsFile, fp); + if (nRead != static_cast< size_t >(numberColumnsFile)) + throw("Error in fread"); + CoinMemcpyN(temp, numberColumns, primalColumnSolution); + nRead = fread(temp, sizeof(double), numberColumnsFile, fp); + if (nRead != static_cast< size_t >(numberColumnsFile)) + throw("Error in fread"); + CoinMemcpyN(temp, numberColumns, dualColumnSolution); + delete[] temp; + } + if (mode == 3) { + int i; + for (i = 0; i < numberRows; i++) { + primalRowSolution[i] = -primalRowSolution[i]; + dualRowSolution[i] = -dualRowSolution[i]; + } + for (i = 0; i < numberColumns; i++) { + primalColumnSolution[i] = -primalColumnSolution[i]; + dualColumnSolution[i] = -dualColumnSolution[i]; + } + } + } + fclose(fp); + } else { + std::cout << "Unable to open file " << fileName << std::endl; + } +} +// Dump a solution to file +void saveSolution(const ClpSimplex *lpSolver, std::string fileName) +{ + if (strstr(fileName.c_str(), "_fix_read_")) { + FILE *fp = fopen(fileName.c_str(), "rb"); + if (fp) { + ClpSimplex *solver = const_cast< ClpSimplex * >(lpSolver); + restoreSolution(solver, fileName, 0); + // fix all + int logLevel = solver->logLevel(); + int iColumn; + int numberColumns = solver->numberColumns(); + double *primalColumnSolution = solver->primalColumnSolution(); + double *columnLower = solver->columnLower(); + double *columnUpper = solver->columnUpper(); + for (iColumn = 0; iColumn < numberColumns; iColumn++) { + double value = primalColumnSolution[iColumn]; + if (value > columnUpper[iColumn]) { + if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1) + printf("%d value of %g - bounds %g %g\n", + iColumn, value, columnLower[iColumn], columnUpper[iColumn]); + value = columnUpper[iColumn]; + } else if (value < columnLower[iColumn]) { + if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1) + printf("%d value of %g - bounds %g %g\n", + iColumn, value, columnLower[iColumn], columnUpper[iColumn]); + value = columnLower[iColumn]; + } + columnLower[iColumn] = value; + columnUpper[iColumn] = value; + } + return; + } + } + FILE *fp = fopen(fileName.c_str(), "wb"); + if (fp) { + int numberRows = lpSolver->numberRows(); + int numberColumns = lpSolver->numberColumns(); + double objectiveValue = lpSolver->objectiveValue(); + size_t nWrite; + nWrite = fwrite(&numberRows, sizeof(int), 1, fp); + if (nWrite != 1) + throw("Error in fwrite"); + nWrite = fwrite(&numberColumns, sizeof(int), 1, fp); + if (nWrite != 1) + throw("Error in fwrite"); + nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp); + if (nWrite != 1) + throw("Error in fwrite"); + double *dualRowSolution = lpSolver->dualRowSolution(); + double *primalRowSolution = lpSolver->primalRowSolution(); + nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp); + if (nWrite != static_cast< size_t >(numberRows)) + throw("Error in fwrite"); + nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp); + if (nWrite != static_cast< size_t >(numberRows)) + throw("Error in fwrite"); + double *dualColumnSolution = lpSolver->dualColumnSolution(); + double *primalColumnSolution = lpSolver->primalColumnSolution(); + nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp); + if (nWrite != static_cast< size_t >(numberColumns)) + throw("Error in fwrite"); + nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp); + if (nWrite != static_cast< size_t >(numberColumns)) + throw("Error in fwrite"); + fclose(fp); + } else { + std::cout << "Unable to open file " << fileName << std::endl; + } +} +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.hpp new file mode 100644 index 000000000..26d14126a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcOrClpParam.hpp @@ -0,0 +1,585 @@ + +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifdef USE_CBCCONFIG +#include "CbcConfig.h" +#else +#include "ClpConfig.h" +#endif + +#ifndef CbcOrClpParam_H +#define CbcOrClpParam_H +/** + This has parameter handling stuff which can be shared between Cbc and Clp (and Dylp etc). + + This (and .cpp) should be copied so that it is the same in Cbc/Test and Clp/Test. + I know this is not elegant but it seems simplest. + + It uses COIN_HAS_CBC for parameters wanted by CBC + It uses COIN_HAS_CLP for parameters wanted by CLP (or CBC using CLP) + It could use COIN_HAS_DYLP for parameters wanted by DYLP + It could use COIN_HAS_DYLP_OR_CLP for parameters wanted by DYLP or CLP etc etc + + */ +class OsiSolverInterface; +class CbcModel; +class ClpSimplex; +/*! \brief Parameter codes + + Parameter type ranges are allocated as follows +
    +
  • 1 -- 100 double parameters +
  • 101 -- 200 integer parameters +
  • 201 -- 300 Clp string parameters +
  • 301 -- 400 Cbc string parameters +
  • 401 -- 500 (mostly) Clp actions +
  • 501 -- 600 (mostly) Cbc actions +
+ + `Actions' do not necessarily invoke an immediate action; it's just that they + don't fit neatly into the parameters array. + + This coding scheme is in flux. +*/ + +enum CbcOrClpParameterType + +{ + CBC_PARAM_GENERALQUERY = -100, + CBC_PARAM_FULLGENERALQUERY, + + CLP_PARAM_DBL_PRIMALTOLERANCE = 1, + CLP_PARAM_DBL_DUALTOLERANCE, + CLP_PARAM_DBL_TIMELIMIT, + CLP_PARAM_DBL_DUALBOUND, + CLP_PARAM_DBL_PRIMALWEIGHT, + CLP_PARAM_DBL_OBJSCALE, + CLP_PARAM_DBL_RHSSCALE, + CLP_PARAM_DBL_ZEROTOLERANCE, + CLP_PARAM_DBL_PSI, + + CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, + CBC_PARAM_DBL_CUTOFF, + CBC_PARAM_DBL_INTEGERTOLERANCE, + CBC_PARAM_DBL_INCREMENT, + CBC_PARAM_DBL_ALLOWABLEGAP, + CBC_PARAM_DBL_TIMELIMIT_BAB, + CBC_PARAM_DBL_GAPRATIO, + + CBC_PARAM_DBL_DJFIX = 81, + CBC_PARAM_DBL_TIGHTENFACTOR, + CLP_PARAM_DBL_PRESOLVETOLERANCE, + CLP_PARAM_DBL_OBJSCALE2, + CBC_PARAM_DBL_FAKEINCREMENT, + CBC_PARAM_DBL_FAKECUTOFF, + CBC_PARAM_DBL_ARTIFICIALCOST, + CBC_PARAM_DBL_DEXTRA3, + CBC_PARAM_DBL_SMALLBAB, + CBC_PARAM_DBL_DEXTRA4, + CBC_PARAM_DBL_DEXTRA5, + + CLP_PARAM_INT_SOLVERLOGLEVEL = 101, +#ifndef COIN_HAS_CBC + CLP_PARAM_INT_LOGLEVEL = 101, +#endif + CLP_PARAM_INT_MAXFACTOR, + CLP_PARAM_INT_PERTVALUE, + CLP_PARAM_INT_MAXITERATION, + CLP_PARAM_INT_PRESOLVEPASS, + CLP_PARAM_INT_IDIOT, + CLP_PARAM_INT_SPRINT, + CLP_PARAM_INT_OUTPUTFORMAT, + CLP_PARAM_INT_SLPVALUE, + CLP_PARAM_INT_PRESOLVEOPTIONS, + CLP_PARAM_INT_PRINTOPTIONS, + CLP_PARAM_INT_SPECIALOPTIONS, + CLP_PARAM_INT_SUBSTITUTION, + CLP_PARAM_INT_DUALIZE, + CLP_PARAM_INT_VERBOSE, + CLP_PARAM_INT_CPP, + CLP_PARAM_INT_PROCESSTUNE, + CLP_PARAM_INT_USESOLUTION, + CLP_PARAM_INT_RANDOMSEED, + CLP_PARAM_INT_MORESPECIALOPTIONS, + CLP_PARAM_INT_DECOMPOSE_BLOCKS, + CLP_PARAM_INT_VECTOR_MODE, + + CBC_PARAM_INT_STRONGBRANCHING = 151, + CBC_PARAM_INT_CUTDEPTH, + CBC_PARAM_INT_MAXNODES, + CBC_PARAM_INT_NUMBERBEFORE, + CBC_PARAM_INT_NUMBERANALYZE, + CBC_PARAM_INT_MIPOPTIONS, + CBC_PARAM_INT_MOREMIPOPTIONS, + CBC_PARAM_INT_MAXHOTITS, + CBC_PARAM_INT_FPUMPITS, + CBC_PARAM_INT_MAXSOLS, + CBC_PARAM_INT_FPUMPTUNE, + CBC_PARAM_INT_TESTOSI, + CBC_PARAM_INT_EXTRA1, + CBC_PARAM_INT_EXTRA2, + CBC_PARAM_INT_EXTRA3, + CBC_PARAM_INT_EXTRA4, + CBC_PARAM_INT_DEPTHMINIBAB, + CBC_PARAM_INT_CUTPASSINTREE, + CBC_PARAM_INT_THREADS, + CBC_PARAM_INT_CUTPASS, + CBC_PARAM_INT_VUBTRY, + CBC_PARAM_INT_DENSE, + CBC_PARAM_INT_EXPERIMENT, + CBC_PARAM_INT_DIVEOPT, + CBC_PARAM_INT_DIVEOPTSOLVES, + CBC_PARAM_INT_STRATEGY, + CBC_PARAM_INT_SMALLFACT, + CBC_PARAM_INT_HOPTIONS, + CBC_PARAM_INT_CUTLENGTH, + CBC_PARAM_INT_FPUMPTUNE2, +#ifdef COIN_HAS_CBC + CLP_PARAM_INT_LOGLEVEL, +#endif + CBC_PARAM_INT_MAXSAVEDSOLS, + CBC_PARAM_INT_RANDOMSEED, + CBC_PARAM_INT_MULTIPLEROOTS, + CBC_PARAM_INT_STRONG_STRATEGY, + CBC_PARAM_INT_EXTRA_VARIABLES, + CBC_PARAM_INT_MAX_SLOW_CUTS, + CBC_PARAM_INT_MOREMOREMIPOPTIONS, + + CLP_PARAM_STR_DIRECTION = 201, + CLP_PARAM_STR_DUALPIVOT, + CLP_PARAM_STR_SCALING, + CLP_PARAM_STR_ERRORSALLOWED, + CLP_PARAM_STR_KEEPNAMES, + CLP_PARAM_STR_SPARSEFACTOR, + CLP_PARAM_STR_PRIMALPIVOT, + CLP_PARAM_STR_PRESOLVE, + CLP_PARAM_STR_CRASH, + CLP_PARAM_STR_BIASLU, + CLP_PARAM_STR_PERTURBATION, + CLP_PARAM_STR_MESSAGES, + CLP_PARAM_STR_AUTOSCALE, + CLP_PARAM_STR_CHOLESKY, + CLP_PARAM_STR_KKT, + CLP_PARAM_STR_BARRIERSCALE, + CLP_PARAM_STR_GAMMA, + CLP_PARAM_STR_CROSSOVER, + CLP_PARAM_STR_PFI, + CLP_PARAM_STR_INTPRINT, + CLP_PARAM_STR_VECTOR, + CLP_PARAM_STR_FACTORIZATION, + CLP_PARAM_STR_ALLCOMMANDS, + CLP_PARAM_STR_TIME_MODE, + CLP_PARAM_STR_ABCWANTED, + CLP_PARAM_STR_BUFFER_MODE, + + CBC_PARAM_STR_NODESTRATEGY = 301, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_STR_CUTSSTRATEGY, + CBC_PARAM_STR_HEURISTICSTRATEGY, + CBC_PARAM_STR_GOMORYCUTS, + CBC_PARAM_STR_PROBINGCUTS, + CBC_PARAM_STR_KNAPSACKCUTS, + CBC_PARAM_STR_REDSPLITCUTS, + CBC_PARAM_STR_ROUNDING, + CBC_PARAM_STR_SOLVER, + CBC_PARAM_STR_CLIQUECUTS, + CBC_PARAM_STR_COSTSTRATEGY, + CBC_PARAM_STR_FLOWCUTS, + CBC_PARAM_STR_MIXEDCUTS, + CBC_PARAM_STR_TWOMIRCUTS, + CBC_PARAM_STR_PREPROCESS, + CBC_PARAM_STR_FPUMP, + CBC_PARAM_STR_GREEDY, + CBC_PARAM_STR_COMBINE, + CBC_PARAM_STR_PROXIMITY, + CBC_PARAM_STR_LOCALTREE, + CBC_PARAM_STR_SOS, + CBC_PARAM_STR_LANDPCUTS, + CBC_PARAM_STR_RINS, + CBC_PARAM_STR_RESIDCUTS, + CBC_PARAM_STR_RENS, + CBC_PARAM_STR_DIVINGS, + CBC_PARAM_STR_DIVINGC, + CBC_PARAM_STR_DIVINGF, + CBC_PARAM_STR_DIVINGG, + CBC_PARAM_STR_DIVINGL, + CBC_PARAM_STR_DIVINGP, + CBC_PARAM_STR_DIVINGV, + CBC_PARAM_STR_DINS, + CBC_PARAM_STR_PIVOTANDFIX, + CBC_PARAM_STR_RANDROUND, + CBC_PARAM_STR_NAIVE, + CBC_PARAM_STR_ZEROHALFCUTS, + CBC_PARAM_STR_CPX, + CBC_PARAM_STR_CROSSOVER2, + CBC_PARAM_STR_PIVOTANDCOMPLEMENT, + CBC_PARAM_STR_VND, + CBC_PARAM_STR_LAGOMORYCUTS, + CBC_PARAM_STR_LATWOMIRCUTS, + CBC_PARAM_STR_REDSPLIT2CUTS, + CBC_PARAM_STR_GMICUTS, + CBC_PARAM_STR_CUTOFF_CONSTRAINT, + CBC_PARAM_STR_DW, + CBC_PARAM_STR_ORBITAL, + CBC_PARAM_STR_PREPROCNAMES, + CBC_PARAM_STR_SOSPRIORITIZE, + + CLP_PARAM_ACTION_DIRECTORY = 401, + CLP_PARAM_ACTION_DIRSAMPLE, + CLP_PARAM_ACTION_DIRNETLIB, + CBC_PARAM_ACTION_DIRMIPLIB, + CLP_PARAM_ACTION_IMPORT, + CLP_PARAM_ACTION_EXPORT, + CLP_PARAM_ACTION_RESTORE, + CLP_PARAM_ACTION_SAVE, + CLP_PARAM_ACTION_DUALSIMPLEX, + CLP_PARAM_ACTION_PRIMALSIMPLEX, + CLP_PARAM_ACTION_EITHERSIMPLEX, + CLP_PARAM_ACTION_MAXIMIZE, + CLP_PARAM_ACTION_MINIMIZE, + CLP_PARAM_ACTION_EXIT, + CLP_PARAM_ACTION_STDIN, + CLP_PARAM_ACTION_UNITTEST, + CLP_PARAM_ACTION_NETLIB_EITHER, + CLP_PARAM_ACTION_NETLIB_DUAL, + CLP_PARAM_ACTION_NETLIB_PRIMAL, + CLP_PARAM_ACTION_SOLUTION, + CLP_PARAM_ACTION_SAVESOL, + CLP_PARAM_ACTION_TIGHTEN, + CLP_PARAM_ACTION_FAKEBOUND, + CLP_PARAM_ACTION_HELP, + CLP_PARAM_ACTION_PLUSMINUS, + CLP_PARAM_ACTION_NETWORK, + CLP_PARAM_ACTION_ALLSLACK, + CLP_PARAM_ACTION_REVERSE, + CLP_PARAM_ACTION_BARRIER, + CLP_PARAM_ACTION_NETLIB_BARRIER, + CLP_PARAM_ACTION_NETLIB_TUNE, + CLP_PARAM_ACTION_REALLY_SCALE, + CLP_PARAM_ACTION_BASISIN, + CLP_PARAM_ACTION_BASISOUT, + CLP_PARAM_ACTION_SOLVECONTINUOUS, + CLP_PARAM_ACTION_CLEARCUTS, + CLP_PARAM_ACTION_VERSION, + CLP_PARAM_ACTION_STATISTICS, + CLP_PARAM_ACTION_DEBUG, + CLP_PARAM_ACTION_DUMMY, + CLP_PARAM_ACTION_PRINTMASK, + CLP_PARAM_ACTION_OUTDUPROWS, + CLP_PARAM_ACTION_USERCLP, + CLP_PARAM_ACTION_MODELIN, + CLP_PARAM_ACTION_CSVSTATISTICS, + CLP_PARAM_ACTION_STOREDFILE, + CLP_PARAM_ACTION_ENVIRONMENT, + CLP_PARAM_ACTION_PARAMETRICS, + CLP_PARAM_ACTION_GMPL_SOLUTION, + CLP_PARAM_ACTION_RESTORESOL, + CLP_PARAM_ACTION_GUESS, + + CBC_PARAM_ACTION_BAB = 501, + CBC_PARAM_ACTION_MIPLIB, + CBC_PARAM_ACTION_STRENGTHEN, + CBC_PARAM_ACTION_PRIORITYIN, + CBC_PARAM_ACTION_MIPSTART, + CBC_PARAM_ACTION_USERCBC, + CBC_PARAM_ACTION_DOHEURISTIC, + CLP_PARAM_ACTION_NEXTBESTSOLUTION, + + CBC_PARAM_NOTUSED_OSLSTUFF = 601, + CBC_PARAM_NOTUSED_CBCSTUFF, + + CBC_PARAM_NOTUSED_INVALID = 1000 +}; +#include +#include + +/// Very simple class for setting parameters + +class CbcOrClpParam { +public: + /**@name Constructor and destructor */ + //@{ + /// Constructors + CbcOrClpParam(); + CbcOrClpParam(std::string name, std::string help, + double lower, double upper, CbcOrClpParameterType type, int display = 2); + CbcOrClpParam(std::string name, std::string help, + int lower, int upper, CbcOrClpParameterType type, int display = 2); + // Other strings will be added by insert + CbcOrClpParam(std::string name, std::string help, std::string firstValue, + CbcOrClpParameterType type, int whereUsed = 7, int display = 2); + // Action + CbcOrClpParam(std::string name, std::string help, + CbcOrClpParameterType type, int whereUsed = 7, int display = 2); + /// Copy constructor. + CbcOrClpParam(const CbcOrClpParam &); + /// Assignment operator. This copies the data + CbcOrClpParam &operator=(const CbcOrClpParam &rhs); + /// Destructor + ~CbcOrClpParam(); + //@} + + /**@name stuff */ + //@{ + /// Insert string (only valid for keywords) + void append(std::string keyWord); + /// Adds one help line + void addHelp(std::string keyWord); + /// Returns name + inline std::string name() const + { + return name_; + } + /// Returns short help + inline std::string shortHelp() const + { + return shortHelp_; + } + /// Returns long help + inline std::string longHelp() const + { + return longHelp_; + } + /// Returns set of valid strings + inline const std::vector& definedKeywords() const + { + return definedKeyWords_; + } + /// Returns the lower bound for a double-valued parameter + inline double lowerDoubleValue() const + { + return lowerDoubleValue_; + } + /// Returns the upper bound for a double-valued parameter + inline double upperDoubleValue() const + { + return upperDoubleValue_; + } + /// Returns the lower bound for an int-valued parameter + inline int lowerIntValue() const + { + return lowerIntValue_; + } + /// Returns the upper bound for an int-valued parameter + inline int upperIntValue() const + { + return upperIntValue_; + } + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(CbcModel &model, double value); + /// Sets double parameter and returns printable string and error code + const char *setDoubleParameterWithMessage(CbcModel &model, double value, int &returnCode); + /// Gets a double parameter + double doubleParameter(CbcModel &model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(CbcModel &model, int value); + /// Sets int parameter and returns printable string and error code + const char *setIntParameterWithMessage(CbcModel &model, int value, int &returnCode); + /// Gets a int parameter + int intParameter(CbcModel &model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(ClpSimplex *model, double value); + /// Gets a double parameter + double doubleParameter(ClpSimplex *model) const; + /// Sets double parameter and returns printable string and error code + const char *setDoubleParameterWithMessage(ClpSimplex *model, double value, int &returnCode); + /// Sets a int parameter (nonzero code if error) + int setIntParameter(ClpSimplex *model, int value); + /// Sets int parameter and returns printable string and error code + const char *setIntParameterWithMessage(ClpSimplex *model, int value, int &returnCode); + /// Gets a int parameter + int intParameter(ClpSimplex *model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(OsiSolverInterface *model, double value); + /// Sets double parameter and returns printable string and error code + const char *setDoubleParameterWithMessage(OsiSolverInterface *model, double value, int &returnCode); + /// Gets a double parameter + double doubleParameter(OsiSolverInterface *model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(OsiSolverInterface *model, int value); + /// Sets int parameter and returns printable string and error code + const char *setIntParameterWithMessage(OsiSolverInterface *model, int value, int &returnCode); + /// Gets a int parameter + int intParameter(OsiSolverInterface *model) const; + /// Checks a double parameter (nonzero code if error) + int checkDoubleParameter(double value) const; + /// Returns name which could match + std::string matchName() const; + /// Returns length of name for ptinting + int lengthMatchName() const; + /// Returns parameter option which matches (-1 if none) + int parameterOption(std::string check) const; + /// Prints parameter options + void printOptions() const; + /// Returns current parameter option + inline std::string currentOption() const + { + return definedKeyWords_[currentKeyWord_]; + } + /// Sets current parameter option + void setCurrentOption(int value, bool printIt = false); + /// Sets current parameter option and returns printable string + const char *setCurrentOptionWithMessage(int value); + /// Sets current parameter option using string + void setCurrentOption(const std::string value); + /// Sets current parameter option using string with message + const char *setCurrentOptionWithMessage(const std::string value); + /// Returns current parameter option position + int currentOptionAsInteger() const; + /** Returns current parameter option position + but if fake keyword returns a fake value and sets + fakeInteger to true value. If not fake then fakeInteger is -COIN_INT_MAX + */ + int currentOptionAsInteger(int &fakeInteger) const; + /// Sets int value + void setIntValue(int value); + /// Sets int value with message + const char *setIntValueWithMessage(int value); + inline int intValue() const + { + return intValue_; + } + /// Sets double value + void setDoubleValue(double value); + /// Sets double value with message + const char *setDoubleValueWithMessage(double value); + inline double doubleValue() const + { + return doubleValue_; + } + /// Sets string value + void setStringValue(std::string value); + inline std::string stringValue() const + { + return stringValue_; + } + /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched + int matches(std::string input) const; + /// type + inline CbcOrClpParameterType type() const + { + return type_; + } + /// whether to display + inline int displayThis() const + { + return display_; + } + /// Set Long help + inline void setLonghelp(const std::string help) + { + longHelp_ = help; + } + /// Print Long help + void printLongHelp() const; + /// Print action and string + void printString() const; + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + inline int whereUsed() const + { + return whereUsed_; + } + /// Gets value of fake keyword + inline int fakeKeyWord() const + { + return fakeKeyWord_; + } + /// Sets value of fake keyword + inline void setFakeKeyWord(int value, int fakeValue) + { + fakeKeyWord_ = value; + fakeValue_ = fakeValue; + } + /// Sets value of fake keyword to current size of keywords + void setFakeKeyWord(int fakeValue); + +private: + /// gutsOfConstructor + void gutsOfConstructor(); + //@} + ////////////////// data ////////////////// +private: + /**@name data + We might as well throw all type data in - could derive? + */ + //@{ + // Type see CbcOrClpParameterType + CbcOrClpParameterType type_; + /// If double == okay + double lowerDoubleValue_; + double upperDoubleValue_; + /// If int == okay + int lowerIntValue_; + int upperIntValue_; + // Length of name + unsigned int lengthName_; + // Minimum match + unsigned int lengthMatch_; + /// set of valid strings + std::vector< std::string > definedKeyWords_; + /// Name + std::string name_; + /// Short help + std::string shortHelp_; + /// Long help + std::string longHelp_; + /// Action + CbcOrClpParameterType action_; + /// Current keyWord (if a keyword parameter) + int currentKeyWord_; + /// Display on ? + int display_; + /// Integer parameter - current value + int intValue_; + /// Double parameter - current value + double doubleValue_; + /// String parameter - current value + std::string stringValue_; + /** 7 if used everywhere, + 1 - used by clp + 2 - used by cbc + 4 - used by ampl + */ + int whereUsed_; + /** If >=0 then integers allowed as a fake keyword + So minusnnnn would got to -nnnn in currentKeyword_ + and plusnnnn would go to fakeKeyword_+nnnn + */ + int fakeKeyWord_; + /// Return this as main value if an integer + int fakeValue_; + //@} +}; +/// Simple read stuff +std::string CoinReadNextField(); + +std::string CoinReadGetCommand(int argc, const char *argv[]); +std::string CoinReadGetString(int argc, const char *argv[]); +// valid 0 - okay, 1 bad, 2 not there +int CoinReadGetIntField(int argc, const char *argv[], int *valid); +double CoinReadGetDoubleField(int argc, const char *argv[], int *valid); +void CoinReadPrintit(const char *input); +void setCbcOrClpPrinting(bool yesNo); +#define CBCMAXPARAMETERS 250 +/* + Subroutine to establish the cbc parameter array. See the description of + class CbcOrClpParam for details. Pulled from C..Main() for clarity. +*/ +void establishParams(std::vector< CbcOrClpParam > ¶ms); +// Given a parameter type - returns its number in list +int whichParam(const CbcOrClpParameterType &name, + const std::vector< CbcOrClpParam > ¶meters); +// Dump/restore a solution to file +void saveSolution(const ClpSimplex *lpSolver, std::string fileName); +void restoreSolution(ClpSimplex *lpSolver, std::string fileName, int mode); +#endif /* CbcOrClpParam_H */ + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcParam.hpp new file mode 100644 index 000000000..721849795 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcParam.hpp @@ -0,0 +1,338 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcParam_H +#define CbcParam_H + +#include "OsiSolverInterface.hpp" +#include "CbcModel.hpp" +class ClpSimplex; +/*! \brief Parameter codes + + Parameter type ranges are allocated as follows +
    +
  • 1 -- 100 double parameters +
  • 101 -- 200 integer parameters +
  • 201 -- 250 string parameters +
  • 251 -- 300 cuts etc(string but broken out for clarity) +
  • 301 -- 400 `actions' +
+ + `Actions' do not necessarily invoke an immediate action; it's just that they + don't fit neatly into the parameters array. + + This coding scheme is in flux. + CBC_PARAM_STR_NODESTRATEGY, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, + CLP_PARAM_ACTION_CLEARCUTS, + CBC_PARAM_NOTUSED_OSLSTUFF, + CBC_PARAM_NOTUSED_CBCSTUFF are not used at present (03.10.24). +*/ + +enum CbcParameterType + +{ CBC_PARAM_GENERALQUERY = -100, + CBC_PARAM_FULLGENERALQUERY, + + CLP_PARAM_DBL_PRIMALTOLERANCE = 1, + CLP_PARAM_DBL_DUALTOLERANCE, + CBC_PARAM_DBL_CUTOFF, + CLP_PARAM_DBL_TIMELIMIT, + CLP_PARAM_DBL_DUALBOUND, + CLP_PARAM_DBL_PRIMALWEIGHT, + CLP_PARAM_DBL_OBJSCALE, + CLP_PARAM_DBL_RHSSCALE, + + CBC_PARAM_DBL_INFEASIBILITYWEIGHT = 51, + CBC_PARAM_DBL_INTEGERTOLERANCE, + CBC_PARAM_DBL_INCREMENT, + CBC_PARAM_DBL_ALLOWABLEGAP, + + CBC_PARAM_DBL_DJFIX = 81, + CBC_PARAM_DBL_GAPRATIO, + CBC_PARAM_DBL_TIGHTENFACTOR, + + CLP_PARAM_INT_LOGLEVEL = 101, + CLP_PARAM_INT_SOLVERLOGLEVEL, + CBC_PARAM_INT_MAXNODES, + CBC_PARAM_INT_STRONGBRANCHING, + CLP_PARAM_INT_MAXFACTOR, + CLP_PARAM_INT_PERTVALUE, + CLP_PARAM_INT_MAXITERATION, + CLP_PARAM_INT_PRESOLVEPASS, + CLP_PARAM_INT_IDIOT, + CLP_PARAM_INT_SPRINT, + CLP_PARAM_INT_OUTPUTFORMAT, + CLP_PARAM_INT_SLPVALUE, + CLP_PARAM_INT_PRESOLVEOPTIONS, + CLP_PARAM_INT_PRINTOPTIONS, + CLP_PARAM_INT_SPECIALOPTIONS, + + CLP_PARAM_STR_DIRECTION = 201, + CLP_PARAM_STR_DUALPIVOT, + CLP_PARAM_STR_SCALING, + CLP_PARAM_STR_ERRORSALLOWED, + CLP_PARAM_STR_KEEPNAMES, + CLP_PARAM_STR_SPARSEFACTOR, + CLP_PARAM_STR_PRIMALPIVOT, + CLP_PARAM_STR_PRESOLVE, + CLP_PARAM_STR_CRASH, + CLP_PARAM_STR_BIASLU, + CLP_PARAM_STR_PERTURBATION, + CLP_PARAM_STR_MESSAGES, + CLP_PARAM_STR_AUTOSCALE, + CLP_PARAM_STR_CHOLESKY, + CLP_PARAM_STR_KKT, + CLP_PARAM_STR_BARRIERSCALE, + CLP_PARAM_STR_GAMMA, + CLP_PARAM_STR_CROSSOVER, + CLP_PARAM_STR_PFI, + CLP_PARAM_NOTUSED_ALGORITHM, + + CBC_PARAM_STR_NODESTRATEGY = 251, + CBC_PARAM_STR_BRANCHSTRATEGY, + CBC_PARAM_NOTUSED_ADDCUTSSTRATEGY, + CBC_PARAM_STR_GOMORYCUTS, + CBC_PARAM_STR_PROBINGCUTS, + CBC_PARAM_STR_KNAPSACKCUTS, + CBC_PARAM_NOTUSED_ODDHOLECUTS, + CBC_PARAM_STR_ROUNDING, + CBC_PARAM_STR_SOLVER, + CBC_PARAM_STR_CLIQUECUTS, + CBC_PARAM_STR_COSTSTRATEGY, + CBC_PARAM_STR_FLOWCUTS, + CBC_PARAM_STR_MIXEDCUTS, + CBC_PARAM_STR_TWOMIRCUTS, + CBC_PARAM_STR_PREPROCESS, + + CLP_PARAM_ACTION_DIRECTORY = 301, + CLP_PARAM_ACTION_IMPORT, + CLP_PARAM_ACTION_EXPORT, + CLP_PARAM_ACTION_RESTORE, + CLP_PARAM_ACTION_SAVE, + CLP_PARAM_ACTION_DUALSIMPLEX, + CLP_PARAM_ACTION_PRIMALSIMPLEX, + CLP_PARAM_ACTION_MAXIMIZE, + CLP_PARAM_ACTION_MINIMIZE, + CLP_PARAM_ACTION_EXIT, + CLP_PARAM_ACTION_STDIN, + CLP_PARAM_ACTION_UNITTEST, + CLP_PARAM_ACTION_NETLIB_DUAL, + CLP_PARAM_ACTION_NETLIB_PRIMAL, + CLP_PARAM_ACTION_SOLUTION, + CLP_PARAM_ACTION_TIGHTEN, + CLP_PARAM_ACTION_FAKEBOUND, + CLP_PARAM_ACTION_HELP, + CLP_PARAM_ACTION_PLUSMINUS, + CLP_PARAM_ACTION_NETWORK, + CLP_PARAM_ACTION_ALLSLACK, + CLP_PARAM_ACTION_REVERSE, + CLP_PARAM_ACTION_BARRIER, + CLP_PARAM_ACTION_NETLIB_BARRIER, + CLP_PARAM_ACTION_REALLY_SCALE, + CLP_PARAM_ACTION_BASISIN, + CLP_PARAM_ACTION_BASISOUT, + CLP_PARAM_ACTION_SOLVECONTINUOUS, + CBC_PARAM_ACTION_BAB, + CBC_PARAM_ACTION_MIPLIB, + CLP_PARAM_ACTION_CLEARCUTS, + CLP_VERSION_NOTUSED_PRINTVERSION, + + CBC_PARAM_NOTUSED_OSLSTUFF = 401, + CBC_PARAM_NOTUSED_CBCSTUFF, + + CBC_PARAM_NOTUSED_INVALID = 1000 +}; + +/// Very simple class for setting parameters + +class CbcParam { + +public: + /**@name Constructor and destructor */ + //@{ + /// Constructors + CbcParam(); + CbcParam(std::string name, std::string help, + double lower, double upper, CbcParameterType type, bool display = true); + CbcParam(std::string name, std::string help, + int lower, int upper, CbcParameterType type, bool display = true); + // Other strings will be added by insert + CbcParam(std::string name, std::string help, std::string firstValue, + CbcParameterType type, int defaultIndex = 0, bool display = true); + // Action + CbcParam(std::string name, std::string help, + CbcParameterType type, int indexNumber = -1, bool display = true); + /// Copy constructor. + CbcParam(const CbcParam &); + /// Assignment operator. This copies the data + CbcParam &operator=(const CbcParam &rhs); + /// Destructor + ~CbcParam(); + //@} + + /**@name stuff */ + //@{ + /// Insert string (only valid for keywords) + void append(std::string keyWord); + /// Adds one help line + void addHelp(std::string keyWord); + /// Returns name + inline std::string name() const + { + return name_; + }; + /// Returns short help + inline std::string shortHelp() const + { + return shortHelp_; + }; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(CbcModel &model, double value) const; + /// Gets a double parameter + double doubleParameter(CbcModel &model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(CbcModel &model, int value) const; + /// Gets a int parameter + int intParameter(CbcModel &model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(ClpSimplex *model, double value) const; + /// Gets a double parameter + double doubleParameter(ClpSimplex *model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(ClpSimplex *model, int value) const; + /// Gets a int parameter + int intParameter(ClpSimplex *model) const; + /// Sets a double parameter (nonzero code if error) + int setDoubleParameter(OsiSolverInterface *model, double value) const; + /// Gets a double parameter + double doubleParameter(OsiSolverInterface *model) const; + /// Sets a int parameter (nonzero code if error) + int setIntParameter(OsiSolverInterface *model, int value) const; + /// Gets a int parameter + int intParameter(OsiSolverInterface *model) const; + /// Checks a double parameter (nonzero code if error) + int checkDoubleParameter(double value) const; + /// Returns name which could match + std::string matchName() const; + /// Returns parameter option which matches (-1 if none) + int parameterOption(std::string check) const; + /// Prints parameter options + void printOptions() const; + /// Returns current parameter option + inline std::string currentOption() const + { + return definedKeyWords_[currentKeyWord_]; + } + /// Sets current parameter option + inline void setCurrentOption(int value) + { + currentKeyWord_ = value; + } + /// Sets int value + inline void setIntValue(int value) + { + intValue_ = value; + } + inline int intValue() const + { + return intValue_; + } + /// Sets double value + inline void setDoubleValue(double value) + { + doubleValue_ = value; + } + inline double doubleValue() const + { + return doubleValue_; + } + /// Sets string value + inline void setStringValue(std::string value) + { + stringValue_ = value; + } + inline std::string stringValue() const + { + return stringValue_; + } + /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched + int matches(std::string input) const; + /// type + inline CbcParameterType type() const + { + return type_; + } + /// whether to display + inline bool displayThis() const + { + return display_; + } + /// Set Long help + inline void setLonghelp(const std::string help) + { + longHelp_ = help; + } + /// Print Long help + void printLongHelp() const; + /// Print action and string + void printString() const; + /// type for classification + inline int indexNumber() const + { + return indexNumber_; + } + +private: + /// gutsOfConstructor + void gutsOfConstructor(); + //@} + ////////////////// data ////////////////// +private: + /**@name data + We might as well throw all type data in - could derive? + */ + //@{ + // Type see CbcParameterType + CbcParameterType type_; + /// If double == okay + double lowerDoubleValue_; + double upperDoubleValue_; + /// If int == okay + int lowerIntValue_; + int upperIntValue_; + // Length of name + unsigned int lengthName_; + // Minimum match + unsigned int lengthMatch_; + /// set of valid strings + std::vector< std::string > definedKeyWords_; + /// Name + std::string name_; + /// Short help + std::string shortHelp_; + /// Long help + std::string longHelp_; + /// Action + CbcParameterType action_; + /// Current keyWord (if a keyword parameter) + int currentKeyWord_; + /// Display on ? + bool display_; + /// Integer parameter - current value + int intValue_; + /// Double parameter - current value + double doubleValue_; + /// String parameter - current value + std::string stringValue_; + /// index number to use for display purposes + int indexNumber_; + //@} +}; +#endif /* CbcParam_H */ + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcPartialNodeInfo.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcPartialNodeInfo.hpp new file mode 100644 index 000000000..bab69cdfa --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcPartialNodeInfo.hpp @@ -0,0 +1,116 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/24/09 carved from CbcNode + +#ifndef CbcPartialNodeInfo_H +#define CbcPartialNodeInfo_H + +#include +#include + +#include "CoinWarmStartBasis.hpp" +#include "CoinSearchTree.hpp" +#include "CbcBranchBase.hpp" +#include "CbcNodeInfo.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiCuts; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinWarmStartBasis; +class CbcCountRowCut; +class CbcModel; +class CbcNode; +class CbcSubProblem; +class CbcGeneralBranchingObject; +/** \brief Holds information for recreating a subproblem by incremental change + from the parent. + + A CbcPartialNodeInfo object contains changes to the bounds and basis, and + additional cuts, required to recreate a subproblem by modifying and + augmenting the parent subproblem. +*/ + +class CbcPartialNodeInfo : public CbcNodeInfo { + +public: + /** \brief Modify model according to information at node + + The routine modifies the model according to bound and basis change + information at node and adds any cuts to the addCuts array. + */ + virtual void applyToModel(CbcModel *model, CoinWarmStartBasis *&basis, + CbcCountRowCut **addCuts, + int ¤tNumberCuts) const; + + /// Just apply bounds to one variable - force means overwrite by lower,upper (1=>infeasible) + virtual int applyBounds(int iColumn, double &lower, double &upper, int force); + /** Builds up row basis backwards (until original model). + Returns NULL or previous one to apply . + Depends on Free being 0 and impossible for cuts + */ + virtual CbcNodeInfo *buildRowBasis(CoinWarmStartBasis &basis) const; + // Default Constructor + CbcPartialNodeInfo(); + + // Constructor from current state + CbcPartialNodeInfo(CbcNodeInfo *parent, CbcNode *owner, + int numberChangedBounds, const int *variables, + const double *boundChanges, + const CoinWarmStartDiff *basisDiff); + + // Copy constructor + CbcPartialNodeInfo(const CbcPartialNodeInfo &); + + // Destructor + ~CbcPartialNodeInfo(); + + /// Clone + virtual CbcNodeInfo *clone() const; + /// Basis diff information + inline const CoinWarmStartDiff *basisDiff() const + { + return basisDiff_; + } + /// Which variable (top bit if upper bound changing) + inline const int *variables() const + { + return variables_; + } + // New bound + inline const double *newBounds() const + { + return newBounds_; + } + /// Number of bound changes + inline int numberChangedBounds() const + { + return numberChangedBounds_; + } + +protected: + /* Data values */ + + /// Basis diff information + CoinWarmStartDiff *basisDiff_; + /// Which variable (top bit if upper bound changing) + int *variables_; + // New bound + double *newBounds_; + /// Number of bound changes + int numberChangedBounds_; + +private: + /// Illegal Assignment operator + CbcPartialNodeInfo &operator=(const CbcPartialNodeInfo &rhs); +}; + +#endif //CbcPartialNodeInfo_H + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSOS.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSOS.hpp new file mode 100644 index 000000000..06b59a9ed --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSOS.hpp @@ -0,0 +1,290 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/9/2009-- carved out of CbcBranchActual + +#ifndef CbcSOS_H +#define CbcSOS_H + +/** \brief Branching object for Special Ordered Sets of type 1 and 2. + + SOS1 are an ordered set of variables where at most one variable can be + non-zero. SOS1 are commonly defined with binary variables (interpreted as + selection between alternatives) but this is not necessary. An SOS1 with + all binary variables is a special case of a clique (setting any one + variable to 1 forces all others to 0). + + In theory, the implementation makes no assumptions about integrality in + Type 1 sets. In practice, there are places where the code seems to have been + written with a binary SOS mindset. Current development of SOS branching + objects is proceeding in OsiSOS. + + SOS2 are an ordered set of variables in which at most two consecutive + variables can be non-zero and must sum to 1 (interpreted as interpolation + between two discrete values). By definition the variables are non-integer. +*/ + +class CbcSOS : public CbcObject { + +public: + // Default Constructor + CbcSOS(); + + /** \brief Constructor with SOS type and member information + + Type specifies SOS 1 or 2. Identifier is an arbitrary value. + + Which should be an array of variable indices with numberMembers entries. + Weights can be used to assign arbitrary weights to variables, in the order + they are specified in which. If no weights are provided, a default array of + 0, 1, 2, ... is generated. + */ + + CbcSOS(CbcModel *model, int numberMembers, + const int *which, const double *weights, int identifier, + int type = 1); + + // Copy constructor + CbcSOS(const CbcSOS &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcSOS &operator=(const CbcSOS &rhs); + + // Destructor + virtual ~CbcSOS(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /// This looks at solution and sets bounds to contain solution + virtual void feasibleRegion(); + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /** Pass in information on branch just done and create CbcObjectUpdateData instance. + If object does not need data then backward pointer will be NULL. + Assumes can get information from solver */ + virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface *solver, + const CbcNode *node, + const CbcBranchingObject *branchingObject); + /// Update object by CbcObjectUpdateData + virtual void updateInformation(const CbcObjectUpdateData &data); + using CbcObject::solverBranch; + /** Create an OsiSolverBranch object + + This returns NULL if branch not represented by bound changes + */ + virtual OsiSolverBranch *solverBranch() const; + /// Redoes data when sequence numbers change + virtual void redoSequenceEtc(CbcModel *model, int numberColumns, const int *originalColumns); + + /// Construct an OsiSOS object + OsiSOS *osiObject(const OsiSolverInterface *solver) const; + /// Number of members + inline int numberMembers() const + { + return numberMembers_; + } + + /// Members (indices in range 0 ... numberColumns-1) + inline const int *members() const + { + return members_; + } + + /// SOS type + inline int sosType() const + { + return sosType_; + } + /// Down number times + inline int numberTimesDown() const + { + return numberTimesDown_; + } + /// Up number times + inline int numberTimesUp() const + { + return numberTimesUp_; + } + + /** Array of weights */ + inline const double *weights() const + { + return weights_; + } + + /// Set number of members + inline void setNumberMembers(int n) + { + numberMembers_ = n; + } + + /// Members (indices in range 0 ... numberColumns-1) + inline int *mutableMembers() const + { + return members_; + } + + /** Array of weights */ + inline double *mutableWeights() const + { + return weights_; + } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return (sosType_ == 1 && integerValued_); + } + /// Set whether set is integer valued or not + inline void setIntegerValued(bool yesNo) + { + integerValued_ = yesNo; + } + +protected: + /// data + + /// Members (indices in range 0 ... numberColumns-1) + int *members_; + /** \brief Weights for individual members + + Arbitrary weights for members. Can be used to attach meaning to variable + values independent of objective coefficients. For example, if the SOS set + comprises binary variables used to choose a facility of a given size, the + weight could be the corresponding facilty size. Fractional values of the + SOS variables can then be used to estimate ideal facility size. + + Weights cannot be completely arbitrary. From the code, they must be + differ by at least 1.0e-7 + */ + + double *weights_; + /// Current pseudo-shadow price estimate down + mutable double shadowEstimateDown_; + /// Current pseudo-shadow price estimate up + mutable double shadowEstimateUp_; + /// Down pseudo ratio + double downDynamicPseudoRatio_; + /// Up pseudo ratio + double upDynamicPseudoRatio_; + /// Number of times we have gone down + int numberTimesDown_; + /// Number of times we have gone up + int numberTimesUp_; + /// Number of members + int numberMembers_; + /// SOS type + int sosType_; + /// Whether integer valued + bool integerValued_; + /// Whether odd values e.g. negative + bool oddValues_; +}; + +/** Branching object for Special ordered sets + + Variable_ is the set id number (redundant, as the object also holds a + pointer to the set. + */ +class CbcSOSBranchingObject : public CbcBranchingObject { + +public: + // Default Constructor + CbcSOSBranchingObject(); + + // Useful constructor + CbcSOSBranchingObject(CbcModel *model, const CbcSOS *clique, + int way, + double separator); + + // Copy constructor + CbcSOSBranchingObject(const CbcSOSBranchingObject &); + + // Assignment operator + CbcSOSBranchingObject &operator=(const CbcSOSBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + // Destructor + virtual ~CbcSOSBranchingObject(); + + using CbcBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(); + /** Update bounds in solver as in 'branch' and update given bounds. + branchState is -1 for 'down' +1 for 'up' */ + virtual void fix(OsiSolverInterface *solver, + double *lower, double *upper, + int branchState) const; + + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch() + { + CbcBranchingObject::previousBranch(); + computeNonzeroRange(); + } + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return SoSBranchObj; + } + + /** Compare the original object of \c this with the original object of \c + brObj. Assumes that there is an ordering of the original objects. + This method should be invoked only if \c this and brObj are of the same + type. + Return negative/0/positive depending on whether \c this is + smaller/same/larger than the argument. + */ + virtual int compareOriginalObject(const CbcBranchingObject *brObj) const; + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + + /** Fill out the \c firstNonzero_ and \c lastNonzero_ data members */ + void computeNonzeroRange(); + +protected: + /// data + const CbcSOS *set_; + /// separator + double separator_; + /** The following two members describe the range in the members_ of the + original object that whose upper bound is not fixed to 0. This is not + necessary for Cbc to function correctly, this is there for heuristics so + that separate branching decisions on the same object can be pooled into + one branching object. */ + int firstNonzero_; + int lastNonzero_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleInteger.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleInteger.hpp new file mode 100644 index 000000000..a5d213b5f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleInteger.hpp @@ -0,0 +1,299 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/9/2009-- carved out of CbcBranchActual + +#ifndef CbcSimpleInteger_H +#define CbcSimpleInteger_H + +#include "CbcBranchingObject.hpp" + +/** Simple branching object for an integer variable + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class CbcIntegerBranchingObject : public CbcBranchingObject { + +public: + /// Default constructor + CbcIntegerBranchingObject(); + + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + CbcIntegerBranchingObject(CbcModel *model, int variable, + int way, double value); + + /** Create a degenerate branch object + + Specifies a `one-way branch'. Calling branch() for this object will + always result in lowerValue <= x <= upperValue. Used to fix a variable + when lowerValue = upperValue. + */ + + CbcIntegerBranchingObject(CbcModel *model, int variable, int way, + double lowerValue, double upperValue); + + /// Copy constructor + CbcIntegerBranchingObject(const CbcIntegerBranchingObject &); + + /// Assignment operator + CbcIntegerBranchingObject &operator=(const CbcIntegerBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcIntegerBranchingObject(); + + /// Does part of constructor + void fillPart(int variable, int way, double value); + using CbcBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + Returns change in guessed objective on next branch + */ + virtual double branch(); + /** Update bounds in solver as in 'branch' and update given bounds. + branchState is -1 for 'down' +1 for 'up' */ + virtual void fix(OsiSolverInterface *solver, + double *lower, double *upper, + int branchState) const; + /** Change (tighten) bounds in object to reflect bounds in solver. + Return true if now fixed */ + virtual bool tighten(OsiSolverInterface *); + +#ifdef JJF_ZERO + // No need to override. Default works fine. + /** Reset every information so that the branching object appears to point to + the previous child. This method does not need to modify anything in any + solver. */ + virtual void previousBranch(); +#endif + + using CbcBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(); + + /// Lower and upper bounds for down branch + inline const double *downBounds() const + { + return down_; + } + /// Lower and upper bounds for up branch + inline const double *upBounds() const + { + return up_; + } + /// Set lower and upper bounds for down branch + inline void setDownBounds(const double bounds[2]) + { + memcpy(down_, bounds, 2 * sizeof(double)); + } + /// Set lower and upper bounds for up branch + inline void setUpBounds(const double bounds[2]) + { + memcpy(up_, bounds, 2 * sizeof(double)); + } +#ifdef FUNNY_BRANCHING + /** Which variable (top bit if upper bound changing, + next bit if on down branch */ + inline const int *variables() const + { + return variables_; + } + // New bound + inline const double *newBounds() const + { + return newBounds_; + } + /// Number of bound changes + inline int numberExtraChangedBounds() const + { + return numberExtraChangedBounds_; + } + /// Just apply extra bounds to one variable - COIN_DBL_MAX ignore + int applyExtraBounds(int iColumn, double lower, double upper, int way); + /// Deactivate bounds for branching + void deactivate(); + /// Are active bounds for branching + inline bool active() const + { + return (down_[1] != -COIN_DBL_MAX); + } +#endif + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return SimpleIntegerBranchObj; + } + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +protected: + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +#ifdef FUNNY_BRANCHING + /** Which variable (top bit if upper bound changing) + next bit if changing on down branch only */ + int *variables_; + // New bound + double *newBounds_; + /// Number of Extra bound changes + int numberExtraChangedBounds_; +#endif +}; + +/// Define a single integer class + +class CbcSimpleInteger : public CbcObject { + +public: + // Default Constructor + CbcSimpleInteger(); + + // Useful constructor - passed model and index + CbcSimpleInteger(CbcModel *model, int iColumn, double breakEven = 0.5); + + // Useful constructor - passed model and Osi object + CbcSimpleInteger(CbcModel *model, const OsiSimpleInteger *object); + + // Copy constructor + CbcSimpleInteger(const CbcSimpleInteger &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcSimpleInteger &operator=(const CbcSimpleInteger &rhs); + + // Destructor + virtual ~CbcSimpleInteger(); + /// Construct an OsiSimpleInteger object + OsiSimpleInteger *osiObject() const; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + using CbcObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Create a branching object and indicate which way to branch first. + + The branching object has to know how to create branches (fix + variables, etc.) + */ + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + /// Fills in a created branching object + /*virtual*/ void fillCreateBranch(CbcIntegerBranchingObject *branching, const OsiBranchingInformation *info, int way); + + using CbcObject::solverBranch; + /** Create an OsiSolverBranch object + + This returns NULL if branch not represented by bound changes + */ + virtual OsiSolverBranch *solverBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. The algorithm takes a bit of care in order to compensate for + minor numerical inaccuracy. + */ + virtual void feasibleRegion(); + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + /// Set column number + inline void setColumnNumber(int value) + { + columnNumber_ = value; + } + + /** Reset variable bounds to their original values. + + Bounds may be tightened, so it may be good to be able to set this info in object. + */ + virtual void resetBounds(const OsiSolverInterface *solver); + + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + /// Original bounds + inline double originalLowerBound() const + { + return originalLower_; + } + inline void setOriginalLowerBound(double value) + { + originalLower_ = value; + } + inline double originalUpperBound() const + { + return originalUpper_; + } + inline void setOriginalUpperBound(double value) + { + originalUpper_ = value; + } + /// Breakeven e.g 0.7 -> >= 0.7 go up first + inline double breakEven() const + { + return breakEven_; + } + /// Set breakeven e.g 0.7 -> >= 0.7 go up first + inline void setBreakEven(double value) + { + breakEven_ = value; + } + +protected: + /// data + + /// Original lower bound + double originalLower_; + /// Original upper bound + double originalUpper_; + /// Breakeven i.e. >= this preferred is up + double breakEven_; + /// Column number in model + int columnNumber_; + /// If -1 down always chosen first, +1 up always, 0 normal + int preferredWay_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerDynamicPseudoCost.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerDynamicPseudoCost.hpp new file mode 100644 index 000000000..71dd3bd30 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerDynamicPseudoCost.hpp @@ -0,0 +1,619 @@ +// $Id$ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/17/2009 - carved out of CbcBranchDynamic + +#ifndef CbcSimpleIntegerDynamicPseudoCost_H +#define CbcSimpleIntegerDynamicPseudoCost_H + +#include "CbcSimpleInteger.hpp" + +#define TYPERATIO 0.9 +#define MINIMUM_MOVEMENT 0.1 +#define TYPE2 0 +// was 1 - but that looks flakey +#define INFEAS 1 +#define MOD_SHADOW 1 +// weight at 1.0 is max min +#define WEIGHT_AFTER 0.8 +#define WEIGHT_BEFORE 0.1 +//Stolen from Constraint Integer Programming book (with epsilon change) +#define WEIGHT_PRODUCT + +/** Define a single integer class but with dynamic pseudo costs. + Based on work by Achterberg, Koch and Martin. + + It is wild overkill but to keep design all twiddly things are in each. + This could be used for fine tuning. + + */ + +class CbcSimpleIntegerDynamicPseudoCost : public CbcSimpleInteger { + +public: + // Default Constructor + CbcSimpleIntegerDynamicPseudoCost(); + + // Useful constructor - passed model index + CbcSimpleIntegerDynamicPseudoCost(CbcModel *model, int iColumn, double breakEven = 0.5); + + // Useful constructor - passed model index and pseudo costs + CbcSimpleIntegerDynamicPseudoCost(CbcModel *model, int iColumn, + double downDynamicPseudoCost, double upDynamicPseudoCost); + + // Useful constructor - passed model index and pseudo costs + CbcSimpleIntegerDynamicPseudoCost(CbcModel *model, int dummy, int iColumn, + double downDynamicPseudoCost, double upDynamicPseudoCost); + + // Copy constructor + CbcSimpleIntegerDynamicPseudoCost(const CbcSimpleIntegerDynamicPseudoCost &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcSimpleIntegerDynamicPseudoCost &operator=(const CbcSimpleIntegerDynamicPseudoCost &rhs); + + // Destructor + virtual ~CbcSimpleIntegerDynamicPseudoCost(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /// Fills in a created branching object + // void fillCreateBranch(CbcIntegerBranchingObject * branching, const OsiBranchingInformation * info, int way) ; + + /** Pass in information on branch just done and create CbcObjectUpdateData instance. + If object does not need data then backward pointer will be NULL. + Assumes can get information from solver */ + virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface *solver, + const CbcNode *node, + const CbcBranchingObject *branchingObject); + /// Update object by CbcObjectUpdateData + virtual void updateInformation(const CbcObjectUpdateData &data); + /// Copy some information i.e. just variable stuff + void copySome(const CbcSimpleIntegerDynamicPseudoCost *otherObject); + /// Updates stuff like pseudocosts before threads + virtual void updateBefore(const OsiObject *rhs); + /// Updates stuff like pseudocosts after threads finished + virtual void updateAfter(const OsiObject *rhs, const OsiObject *baseObject); + /// Updates stuff like pseudocosts after mini branch and bound + void updateAfterMini(int numberDown, int numberDownInfeasible, double sumDown, + int numberUp, int numberUpInfeasible, double sumUp); + + using CbcSimpleInteger::solverBranch; + /** Create an OsiSolverBranch object + + This returns NULL if branch not represented by bound changes + */ + virtual OsiSolverBranch *solverBranch() const; + + /// Down pseudo cost + inline double downDynamicPseudoCost() const + { + return downDynamicPseudoCost_; + } + /// Set down pseudo cost + void setDownDynamicPseudoCost(double value); + /// Modify down pseudo cost in a slightly different way + void updateDownDynamicPseudoCost(double value); + + /// Up pseudo cost + inline double upDynamicPseudoCost() const + { + return upDynamicPseudoCost_; + } + /// Set up pseudo cost + void setUpDynamicPseudoCost(double value); + /// Modify up pseudo cost in a slightly different way + void updateUpDynamicPseudoCost(double value); + + /// Down pseudo shadow price cost + inline double downShadowPrice() const + { + return downShadowPrice_; + } + /// Set down pseudo shadow price cost + inline void setDownShadowPrice(double value) + { + downShadowPrice_ = value; + } + /// Up pseudo shadow price cost + inline double upShadowPrice() const + { + return upShadowPrice_; + } + /// Set up pseudo shadow price cost + inline void setUpShadowPrice(double value) + { + upShadowPrice_ = value; + } + + /// Up down separator + inline double upDownSeparator() const + { + return upDownSeparator_; + } + /// Set up down separator + inline void setUpDownSeparator(double value) + { + upDownSeparator_ = value; + } + + /// Down sum cost + inline double sumDownCost() const + { + return sumDownCost_; + } + /// Set down sum cost + inline void setSumDownCost(double value) + { + sumDownCost_ = value; + } + /// Add to down sum cost and set last and square + inline void addToSumDownCost(double value) + { + sumDownCost_ += value; + lastDownCost_ = value; + } + + /// Up sum cost + inline double sumUpCost() const + { + return sumUpCost_; + } + /// Set up sum cost + inline void setSumUpCost(double value) + { + sumUpCost_ = value; + } + /// Add to up sum cost and set last and square + inline void addToSumUpCost(double value) + { + sumUpCost_ += value; + lastUpCost_ = value; + } + + /// Down sum change + inline double sumDownChange() const + { + return sumDownChange_; + } + /// Set down sum change + inline void setSumDownChange(double value) + { + sumDownChange_ = value; + } + /// Add to down sum change + inline void addToSumDownChange(double value) + { + sumDownChange_ += value; + } + + /// Up sum change + inline double sumUpChange() const + { + return sumUpChange_; + } + /// Set up sum change + inline void setSumUpChange(double value) + { + sumUpChange_ = value; + } + /// Add to up sum change and set last and square + inline void addToSumUpChange(double value) + { + sumUpChange_ += value; + } + + /// Sum down decrease number infeasibilities from strong or actual + inline double sumDownDecrease() const + { + return sumDownDecrease_; + } + /// Set sum down decrease number infeasibilities from strong or actual + inline void setSumDownDecrease(double value) + { + sumDownDecrease_ = value; + } + /// Add to sum down decrease number infeasibilities from strong or actual + inline void addToSumDownDecrease(double value) + { + sumDownDecrease_ += value; /*lastDownDecrease_ = (int) value;*/ + } + + /// Sum up decrease number infeasibilities from strong or actual + inline double sumUpDecrease() const + { + return sumUpDecrease_; + } + /// Set sum up decrease number infeasibilities from strong or actual + inline void setSumUpDecrease(double value) + { + sumUpDecrease_ = value; + } + /// Add to sum up decrease number infeasibilities from strong or actual + inline void addToSumUpDecrease(double value) + { + sumUpDecrease_ += value; /*lastUpDecrease_ = (int) value;*/ + } + + /// Down number times + inline int numberTimesDown() const + { + return numberTimesDown_; + } + /// Set down number times + inline void setNumberTimesDown(int value) + { + numberTimesDown_ = value; + } + /// Increment down number times + inline void incrementNumberTimesDown() + { + numberTimesDown_++; + } + + /// Up number times + inline int numberTimesUp() const + { + return numberTimesUp_; + } + /// Set up number times + inline void setNumberTimesUp(int value) + { + numberTimesUp_ = value; + } + /// Increment up number times + inline void incrementNumberTimesUp() + { + numberTimesUp_++; + } + + /// Number times branched + inline int numberTimesBranched() const + { + return numberTimesDown_ + numberTimesUp_; + } + /// Down number times infeasible + inline int numberTimesDownInfeasible() const + { + return numberTimesDownInfeasible_; + } + /// Set down number times infeasible + inline void setNumberTimesDownInfeasible(int value) + { + numberTimesDownInfeasible_ = value; + } + /// Increment down number times infeasible + inline void incrementNumberTimesDownInfeasible() + { + numberTimesDownInfeasible_++; + } + + /// Up number times infeasible + inline int numberTimesUpInfeasible() const + { + return numberTimesUpInfeasible_; + } + /// Set up number times infeasible + inline void setNumberTimesUpInfeasible(int value) + { + numberTimesUpInfeasible_ = value; + } + /// Increment up number times infeasible + inline void incrementNumberTimesUpInfeasible() + { + numberTimesUpInfeasible_++; + } + + /// Number of times before trusted + inline int numberBeforeTrust() const + { + return numberBeforeTrust_; + } + /// Set number of times before trusted + inline void setNumberBeforeTrust(int value) + { + numberBeforeTrust_ = value; + } + /// Increment number of times before trusted + inline void incrementNumberBeforeTrust() + { + numberBeforeTrust_++; + } + + /// Return "up" estimate + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + + /// method - see below for details + inline int method() const + { + return method_; + } + /// Set method + inline void setMethod(int value) + { + method_ = value; + } + + /// Pass in information on a down branch + void setDownInformation(double changeObjectiveDown, int changeInfeasibilityDown); + /// Pass in information on a up branch + void setUpInformation(double changeObjectiveUp, int changeInfeasibilityUp); + /// Pass in probing information + void setProbingInformation(int fixedDown, int fixedUp); + + /// Print - 0 -summary, 1 just before strong + void print(int type = 0, double value = 0.0) const; + /// Same - returns true if contents match(ish) + bool same(const CbcSimpleIntegerDynamicPseudoCost *obj) const; + +protected: + /// data + + /// Down pseudo cost + double downDynamicPseudoCost_; + /// Up pseudo cost + double upDynamicPseudoCost_; + /** Up/down separator + If >0.0 then do first branch up if value-floor(value) + >= this value + */ + double upDownSeparator_; + /// Sum down cost from strong or actual + double sumDownCost_; + /// Sum up cost from strong or actual + double sumUpCost_; + /// Sum of all changes to x when going down + double sumDownChange_; + /// Sum of all changes to x when going up + double sumUpChange_; + /// Current pseudo-shadow price estimate down + mutable double downShadowPrice_; + /// Current pseudo-shadow price estimate up + mutable double upShadowPrice_; + /// Sum down decrease number infeasibilities from strong or actual + double sumDownDecrease_; + /// Sum up decrease number infeasibilities from strong or actual + double sumUpDecrease_; + /// Last down cost from strong (i.e. as computed by last strong) + double lastDownCost_; + /// Last up cost from strong (i.e. as computed by last strong) + double lastUpCost_; + /// Last down decrease number infeasibilities from strong (i.e. as computed by last strong) + mutable int lastDownDecrease_; + /// Last up decrease number infeasibilities from strong (i.e. as computed by last strong) + mutable int lastUpDecrease_; + /// Number of times we have gone down + int numberTimesDown_; + /// Number of times we have gone up + int numberTimesUp_; + /// Number of times we have been infeasible going down + int numberTimesDownInfeasible_; + /// Number of times we have been infeasible going up + int numberTimesUpInfeasible_; + /// Number of branches before we trust + int numberBeforeTrust_; + /// Number of local probing fixings going down + int numberTimesDownLocalFixed_; + /// Number of local probing fixings going up + int numberTimesUpLocalFixed_; + /// Number of total probing fixings going down + double numberTimesDownTotalFixed_; + /// Number of total probing fixings going up + double numberTimesUpTotalFixed_; + /// Number of times probing done + int numberTimesProbingTotal_; + /// Number of times infeasible when tested + /** Method - + 0 - pseudo costs + 1 - probing + */ + int method_; +}; +/** Simple branching object for an integer variable with pseudo costs + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class CbcIntegerPseudoCostBranchingObject : public CbcIntegerBranchingObject { + +public: + /// Default constructor + CbcIntegerPseudoCostBranchingObject(); + + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be is lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + CbcIntegerPseudoCostBranchingObject(CbcModel *model, int variable, + int way, double value); + + /** Create a degenerate branch object + + Specifies a `one-way branch'. Calling branch() for this object will + always result in lowerValue <= x <= upperValue. Used to fix a variable + when lowerValue = upperValue. + */ + + CbcIntegerPseudoCostBranchingObject(CbcModel *model, int variable, int way, + double lowerValue, double upperValue); + + /// Copy constructor + CbcIntegerPseudoCostBranchingObject(const CbcIntegerPseudoCostBranchingObject &); + + /// Assignment operator + CbcIntegerPseudoCostBranchingObject &operator=(const CbcIntegerPseudoCostBranchingObject &rhs); + + /// Clone + virtual CbcBranchingObject *clone() const; + + /// Destructor + virtual ~CbcIntegerPseudoCostBranchingObject(); + + using CbcBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + This version also changes guessed objective value + */ + virtual double branch(); + + /// Change in guessed + inline double changeInGuessed() const + { + return changeInGuessed_; + } + /// Set change in guessed + inline void setChangeInGuessed(double value) + { + changeInGuessed_ = value; + } + + /** Return the type (an integer identifier) of \c this */ + virtual CbcBranchObjType type() const + { + return SimpleIntegerDynamicPseudoCostBranchObj; + } + + /** Compare the \c this with \c brObj. \c this and \c brObj must be os the + same type and must have the same original object, but they may have + different feasible regions. + Return the appropriate CbcRangeCompare value (first argument being the + sub/superset if that's the case). In case of overlap (and if \c + replaceIfOverlap is true) replace the current branching object with one + whose feasible region is the overlap. + */ + virtual CbcRangeCompare compareBranchingObject(const CbcBranchingObject *brObj, const bool replaceIfOverlap = false); + +protected: + /// Change in guessed objective value for next branch + double changeInGuessed_; +}; +#ifdef SWITCH_VARIABLES +/** Define a single integer class but with associated switched variable + So Binary variable switches on/off a continuous variable + designed for badly scaled problems + */ + +class CbcSwitchingBinary : public CbcSimpleIntegerDynamicPseudoCost { + +public: + // Default Constructor + CbcSwitchingBinary(); + + // Useful constructor + CbcSwitchingBinary(CbcSimpleIntegerDynamicPseudoCost *oldObject, + int nOdd, const int *other, const int *otherRow); + + // Copy constructor + CbcSwitchingBinary(const CbcSwitchingBinary &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcSwitchingBinary &operator=(const CbcSwitchingBinary &rhs); + + // Destructor + virtual ~CbcSwitchingBinary(); + + /// Add in zero switches + void addZeroSwitches(int nAdd, const int *columns); + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + /// Same - returns true if contents match(ish) + bool same(const CbcSwitchingBinary *obj) const; + /// Set associated bounds + virtual int setAssociatedBounds(OsiSolverInterface *solver = NULL, + int cleanBasis = 0) const; + /// Check associated bounds + int checkAssociatedBounds(const OsiSolverInterface *solver, const double *solution, + int printLevel, int state[3], int &nBadFixed) const; + /// Lower bound when binary zero + inline const double *zeroLowerBound() const + { + return zeroLowerBound_; + } + /// Lower bound when binary one + inline const double *oneLowerBound() const + { + return oneLowerBound_; + } + /// Upper bound when binary zero + inline const double *zeroUpperBound() const + { + return zeroUpperBound_; + } + /// Upper bound when binary one + inline const double *oneUpperBound() const + { + return oneUpperBound_; + } + /** Continuous variable - + */ + inline const int *otherVariable() const + { + return otherVariable_; + } + /// Number of other variables + inline int numberOther() const + { + return numberOther_; + } + /** Type + 1 - single switch + 2 - double switch + 3 - both + */ + inline int type() const + { + return type_; + } + +protected: + /// data + + /// Lower bound when binary zero + double *zeroLowerBound_; + /// Lower bound when binary one + double *oneLowerBound_; + /// Upper bound when binary zero + double *zeroUpperBound_; + /// Upper bound when binary one + double *oneUpperBound_; + /** Continuous variable - + */ + int *otherVariable_; + /// Number of other variables + int numberOther_; + /** Type + 1 - single switch + 2 - double switch + 3 - both + */ + int type_; +}; +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerPseudoCost.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerPseudoCost.hpp new file mode 100644 index 000000000..08e477b73 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSimpleIntegerPseudoCost.hpp @@ -0,0 +1,122 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcSimpleIntegerPseudoCost_H +#define CbcSimpleIntegerPseudoCost_H + +#include "CbcSimpleInteger.hpp" +/// Define a single integer class but with pseudo costs + +class CbcSimpleIntegerPseudoCost : public CbcSimpleInteger { + +public: + // Default Constructor + CbcSimpleIntegerPseudoCost(); + + // Useful constructor - passed model index + CbcSimpleIntegerPseudoCost(CbcModel *model, int iColumn, double breakEven = 0.5); + + // Useful constructor - passed and model index and pseudo costs + CbcSimpleIntegerPseudoCost(CbcModel *model, int iColumn, + double downPseudoCost, double upPseudoCost); + // Useful constructor - passed and model index and pseudo costs + CbcSimpleIntegerPseudoCost(CbcModel *model, int dummy, int iColumn, + double downPseudoCost, double upPseudoCost); + + // Copy constructor + CbcSimpleIntegerPseudoCost(const CbcSimpleIntegerPseudoCost &); + + /// Clone + virtual CbcObject *clone() const; + + // Assignment operator + CbcSimpleIntegerPseudoCost &operator=(const CbcSimpleIntegerPseudoCost &rhs); + + // Destructor + virtual ~CbcSimpleIntegerPseudoCost(); + + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, + int &preferredWay) const; + + /// Creates a branching object + virtual CbcBranchingObject *createCbcBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way); + + /// Down pseudo cost + inline double downPseudoCost() const + { + return downPseudoCost_; + } + /// Set down pseudo cost + inline void setDownPseudoCost(double value) + { + downPseudoCost_ = value; + } + + /// Up pseudo cost + inline double upPseudoCost() const + { + return upPseudoCost_; + } + /// Set up pseudo cost + inline void setUpPseudoCost(double value) + { + upPseudoCost_ = value; + } + + /// Up down separator + inline double upDownSeparator() const + { + return upDownSeparator_; + } + /// Set up down separator + inline void setUpDownSeparator(double value) + { + upDownSeparator_ = value; + } + + /// Return "up" estimate + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + + /// method - see below for details + inline int method() const + { + return method_; + } + /// Set method + inline void setMethod(int value) + { + method_ = value; + } + +protected: + /// data + + /// Down pseudo cost + double downPseudoCost_; + /// Up pseudo cost + double upPseudoCost_; + /** Up/down separator + If >0.0 then do first branch up if value-floor(value) + >= this value + */ + double upDownSeparator_; + /** Method - + 0 - normal - return min (up,down) + 1 - if before any solution return CoinMax(up,down) + 2 - if before branched solution return CoinMax(up,down) + 3 - always return CoinMax(up,down) + */ + int method_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSolver.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSolver.hpp new file mode 100644 index 000000000..b38390505 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSolver.hpp @@ -0,0 +1,460 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file CbcSolver.hpp + \brief Defines CbcSolver, the proposed top-level class for the new-style + cbc solver. + + This class is currently an orphan. With the removal of all code flagged + with the NEW_STYLE_SOLVER, this class is never instantiated (and cannot + be instantiated). It is available to be coopted as a top-level object + wrapping the current CbcMain0 and CbcMain1, should that appear to be a + desireable path forward. -- lh, 091211 -- +*/ + +#ifndef CbcSolver_H +#define CbcSolver_H + +#include +#include +#include "CoinMessageHandler.hpp" +#include "OsiClpSolverInterface.hpp" + +#if CBC_OTHER_SOLVER == 1 +#include "OsiCpxSolverInterface.hpp" +#endif + +#include "CbcModel.hpp" +#include "CbcOrClpParam.hpp" + +class CbcUser; +class CbcStopNow; +class CglCutGenerator; + +//############################################################################# + +/*! \brief This allows the use of the standalone solver in a flexible manner. + + It has an original OsiClpSolverInterface and CbcModel which it can use + repeatedly, e.g., to get a heuristic solution and then start again. + + So I [jjf] will need a primitive scripting language which can then call + solve and manipulate solution value and solution arrays. + + Also provides for user callback functions. Currently two ideas in + gestation, CbcUser and CbcStopNow. The latter seems limited to deciding + whether or not to stop. The former seems completely general, with a notion + of importing and exporting, and a `solve', which should be interpreted as + `do whatever this user function does'. + + Parameter initialisation is at last centralised in fillParameters(). +*/ + +class CbcSolver { + +public: + ///@name Solve method + //@{ + /** This takes a list of commands, does "stuff" and returns + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + int solve(int argc, const char *argv[], int returnMode); + /** This takes a list of commands, does "stuff" and returns + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + int solve(const char *input, int returnMode); + //@} + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcSolver(); + + /// Constructor from solver + CbcSolver(const OsiClpSolverInterface &); + + /// Constructor from model + CbcSolver(const CbcModel &); + + /** Copy constructor . + */ + CbcSolver(const CbcSolver &rhs); + + /// Assignment operator + CbcSolver &operator=(const CbcSolver &rhs); + + /// Destructor + ~CbcSolver(); + /// Fill with standard parameters + void fillParameters(); + /*! \brief Set default values in solvers from parameters + + Misleading. The current code actually reads default values from + the underlying solvers and installs them as default values for a subset of + parameters in #parameters_. + */ + void fillValuesInSolver(); + /// Add user function + void addUserFunction(CbcUser *function); + /// Set user call back + void setUserCallBack(CbcStopNow *function); + /// Add cut generator + void addCutGenerator(CglCutGenerator *generator); + //@} + ///@name miscellaneous methods to line up with old + //@{ + // analyze model + int *analyze(OsiClpSolverInterface *solverMod, int &numberChanged, double &increment, + bool changeInt, CoinMessageHandler *generalMessageHandler); + /** 1 - add heuristics to model + 2 - do heuristics (and set cutoff and best solution) + 3 - for miplib test so skip some + (out model later) + */ + //int doHeuristics(CbcModel * model, int type); + /** Updates model_ from babModel_ according to returnMode + returnMode - + 0 model and solver untouched - babModel updated + 1 model updated - just with solution basis etc + 2 model updated i.e. as babModel (babModel NULL) (only use without preprocessing) + */ + void updateModel(ClpSimplex *model2, int returnMode); + //@} + ///@name useful stuff + //@{ + /// Get int value + int intValue(CbcOrClpParameterType type) const; + /// Set int value + void setIntValue(CbcOrClpParameterType type, int value); + /// Get double value + double doubleValue(CbcOrClpParameterType type) const; + /// Set double value + void setDoubleValue(CbcOrClpParameterType type, double value); + /// User function (NULL if no match) + CbcUser *userFunction(const char *name) const; + /// Return original Cbc model + inline CbcModel *model() + { + return &model_; + } + /// Return updated Cbc model + inline CbcModel *babModel() + { + return babModel_; + } + /// Number of userFunctions + inline int numberUserFunctions() const + { + return numberUserFunctions_; + } + /// User function array + inline CbcUser **userFunctionArray() const + { + return userFunction_; + } + /// Copy of model on initial load (will contain output solutions) + inline OsiClpSolverInterface *originalSolver() const + { + return originalSolver_; + } + /// Copy of model on initial load + inline CoinModel *originalCoinModel() const + { + return originalCoinModel_; + } + /// Copy of model on initial load (will contain output solutions) + void setOriginalSolver(OsiClpSolverInterface *originalSolver); + /// Copy of model on initial load + void setOriginalCoinModel(CoinModel *originalCoinModel); + /// Number of cutgenerators + inline int numberCutGenerators() const + { + return numberCutGenerators_; + } + /// Cut generator array + inline CglCutGenerator **cutGeneratorArray() const + { + return cutGenerator_; + } + /// Start time + inline double startTime() const + { + return startTime_; + } + /// Whether to print to std::cout + inline void setPrinting(bool onOff) + { + noPrinting_ = !onOff; + } + /// Where to start reading commands + inline void setReadMode(int value) + { + readMode_ = value; + } + //@} +private: + ///@name Private member data + //@{ + + /// Reference model + CbcModel model_; + + /// Updated model + CbcModel *babModel_; + + /// User functions + CbcUser **userFunction_; + /** Status of user functions + 0 - not used + 1 - needs cbc_load + 2 - available - data in coinModel + 3 - data loaded - can do cbc_save + */ + int *statusUserFunction_; + /// Copy of model on initial load (will contain output solutions) + OsiClpSolverInterface *originalSolver_; + /// Copy of model on initial load + CoinModel *originalCoinModel_; + /// Cut generators + CglCutGenerator **cutGenerator_; + /// Number of user functions + int numberUserFunctions_; + /// Number of cut generators + int numberCutGenerators_; + /// Stop now stuff + CbcStopNow *callBack_; + /// Cpu time at instantiation + double startTime_; + /// Parameters and values + std::vector< CbcOrClpParam > parameters_; + /// Whether to do miplib test + bool doMiplib_; + /// Whether to print to std::cout + bool noPrinting_; + /// Where to start reading commands + int readMode_; + //@} +}; +//############################################################################# + +/// Structure to hold useful arrays +typedef struct { + // Priorities + int *priorities_; + // SOS priorities + int *sosPriority_; + // Direction to branch first + int *branchDirection_; + // Input solution + double *primalSolution_; + // Down pseudo costs + double *pseudoDown_; + // Up pseudo costs + double *pseudoUp_; +} CbcSolverUsefulData2; + +//############################################################################# + +/** + The CbcSolver class was taken out at a 9/12/09 meeting + This is a feeble replacement. + At present everything is public +*/ +class CbcSolverUsefulData { + +public: + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcSolverUsefulData(); + + /** Copy constructor . + */ + CbcSolverUsefulData(const CbcSolverUsefulData &rhs); + + /// Assignment operator + CbcSolverUsefulData &operator=(const CbcSolverUsefulData &rhs); + + /// Destructor + ~CbcSolverUsefulData(); + //@} + + ///@name Member data + //@{ + // For time + double totalTime_; + // Parameters + std::vector parameters_; + // Printing + bool noPrinting_; + // Whether to use signal handler + bool useSignalHandler_; + // Default pump tuning + int initialPumpTune_; + //@} +}; +/// And this uses it +// When we want to load up CbcModel with options first +void CbcMain0(CbcModel &babSolver, CbcSolverUsefulData &solverData); +int CbcMain1(int argc, const char *argv[], CbcModel &babSolver, int(CbcModel *currentSolver, int whereFrom), CbcSolverUsefulData &solverData); + +//############################################################################# + +/*! \brief A class to allow the use of unknown user functionality + + For example, access to a modelling language (CbcAmpl). +*/ +class CbcUser { + +public: + ///@name import/export methods + //@{ + /*! \brief Import - gets full command arguments + + \return + - -1 - no action + - 0 - data read in without error + - 1 - errors + */ + virtual int importData(CbcSolver * /*model*/, int & /*argc*/, char ** /*argv[]*/) + { + return -1; + } + + /*! \brief Export + + Values for mode: + - 1 OsiClpSolver + - 2 CbcModel + - add 10 if infeasible from odd situation + */ + virtual void exportSolution(CbcSolver * /*model*/, + int /*mode*/, const char * /*message*/ = NULL) {} + + /// Export Data (i.e. at very end) + virtual void exportData(CbcSolver * /*model*/) {} + + /// Get useful stuff + virtual void fillInformation(CbcSolver * /*model*/, + CbcSolverUsefulData & /*info*/) {} + //@} + + ///@name usage methods + //@{ + /// CoinModel if valid + inline CoinModel *coinModel() const + { + return coinModel_; + } + /// Other info - needs expanding + virtual void *stuff() + { + return NULL; + } + /// Name + inline std::string name() const + { + return userName_; + } + /// Solve (whatever that means) + virtual void solve(CbcSolver *model, const char *options) = 0; + /// Returns true if function knows about option + virtual bool canDo(const char *options) = 0; + //@} + + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcUser(); + + /// Copy constructor + CbcUser(const CbcUser &rhs); + + /// Assignment operator + CbcUser &operator=(const CbcUser &rhs); + + /// Clone + virtual CbcUser *clone() const = 0; + + /// Destructor + virtual ~CbcUser(); + //@} + +protected: + ///@name Private member data + //@{ + + /// CoinModel + CoinModel *coinModel_; + + /// Name of user function + std::string userName_; + + //@} +}; +//############################################################################# + +/*! \brief Support the use of a call back class to decide whether to stop + + Definitely under construction. +*/ + +class CbcStopNow { + +public: + ///@name Decision methods + //@{ + /*! \brief Import + + Values for whereFrom: + - 1 after initial solve by dualsimplex etc + - 2 after preprocessing + - 3 just before branchAndBound (so user can override) + - 4 just after branchAndBound (before postprocessing) + - 5 after postprocessing + - 6 after a user called heuristic phase + + \return 0 if good + nonzero return code to stop + */ + virtual int callBack(CbcModel * /*currentSolver*/, int /*whereFrom*/) + { + return 0; + } + //@} + + ///@name Constructors and destructors etc + //@{ + /// Default Constructor + CbcStopNow(); + + /** Copy constructor . + */ + CbcStopNow(const CbcStopNow &rhs); + + /// Assignment operator + CbcStopNow &operator=(const CbcStopNow &rhs); + + /// Clone + virtual CbcStopNow *clone() const; + + /// Destructor + virtual ~CbcStopNow(); + //@} + +private: + ///@name Private member data + //@{ + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcStrategy.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcStrategy.hpp new file mode 100644 index 000000000..2c1ffe76c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcStrategy.hpp @@ -0,0 +1,269 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcStrategy_H +#define CbcStrategy_H + +#include "CbcModel.hpp" +class CglPreProcess; +class CbcNodeInfo; +class CbcNode; +class CoinWarmStartDiff; + +//############################################################################# +/** Strategy base class */ + +class CbcStrategy { +public: + // Default Constructor + CbcStrategy(); + + virtual ~CbcStrategy(); + + /// Clone + virtual CbcStrategy *clone() const = 0; + + /// Setup cut generators + virtual void setupCutGenerators(CbcModel &model) = 0; + /// Setup heuristics + virtual void setupHeuristics(CbcModel &model) = 0; + /// Do printing stuff + virtual void setupPrinting(CbcModel &model, int modelLogLevel) = 0; + /// Other stuff e.g. strong branching and preprocessing + virtual void setupOther(CbcModel &model) = 0; + /// Set model depth (i.e. how nested) + inline void setNested(int depth) + { + depth_ = depth; + } + /// Get model depth (i.e. how nested) + inline int getNested() const + { + return depth_; + } + /// Say preProcessing done + inline void setPreProcessState(int state) + { + preProcessState_ = state; + } + /// See what sort of preprocessing was done + inline int preProcessState() const + { + return preProcessState_; + } + /// Pre-processing object + inline CglPreProcess *process() const + { + return process_; + } + /// Delete pre-processing object to save memory + void deletePreProcess(); + /// Return a new Full node information pointer (descendant of CbcFullNodeInfo) + virtual CbcNodeInfo *fullNodeInfo(CbcModel *model, int numberRowsAtContinuous) const; + /// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo) + virtual CbcNodeInfo *partialNodeInfo(CbcModel *model, CbcNodeInfo *parent, CbcNode *owner, + int numberChangedBounds, const int *variables, + const double *boundChanges, + const CoinWarmStartDiff *basisDiff) const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + /** After a CbcModel::resolve this can return a status + -1 no effect + 0 treat as optimal + 1 as 0 but do not do any more resolves (i.e. no more cuts) + 2 treat as infeasible + */ + virtual int status(CbcModel *model, CbcNodeInfo *parent, int whereFrom); + +private: + /// Illegal Assignment operator + CbcStrategy &operator=(const CbcStrategy &rhs); + +protected: + // Data + /// Model depth + int depth_; + /** PreProcessing state - + -1 infeasible + 0 off + 1 was done (so need post-processing) + */ + int preProcessState_; + /// If preprocessing then this is object + CglPreProcess *process_; +}; + +/** Null class + */ + +class CbcStrategyNull : public CbcStrategy { +public: + // Default Constructor + CbcStrategyNull() {} + + // Copy constructor + CbcStrategyNull(const CbcStrategyNull &rhs) + : CbcStrategy(rhs) + { + } + + // Destructor + ~CbcStrategyNull() {} + + /// Clone + virtual CbcStrategy *clone() const + { + return new CbcStrategyNull(*this); + } + + /// Setup cut generators + virtual void setupCutGenerators(CbcModel &) {} + /// Setup heuristics + virtual void setupHeuristics(CbcModel &) {} + /// Do printing stuff + virtual void setupPrinting(CbcModel &, int) {} + /// Other stuff e.g. strong branching + virtual void setupOther(CbcModel &) {} + +protected: + // Data +private: + /// Illegal Assignment operator + CbcStrategyNull &operator=(const CbcStrategyNull &rhs); +}; + +/** Default class + */ + +class CbcStrategyDefault : public CbcStrategy { +public: + // Default Constructor + CbcStrategyDefault(int cutsOnlyAtRoot = 1, + int numberStrong = 5, + int numberBeforeTrust = 0, + int printLevel = 0); + + // Copy constructor + CbcStrategyDefault(const CbcStrategyDefault &); + + // Destructor + ~CbcStrategyDefault(); + + /// Clone + virtual CbcStrategy *clone() const; + + /// Setup cut generators + virtual void setupCutGenerators(CbcModel &model); + /// Setup heuristics + virtual void setupHeuristics(CbcModel &model); + /// Do printing stuff + virtual void setupPrinting(CbcModel &model, int modelLogLevel); + /// Other stuff e.g. strong branching + virtual void setupOther(CbcModel &model); + /// Set up preProcessing - see below + inline void setupPreProcessing(int desired = 1, int passes = 10) + { + desiredPreProcess_ = desired; + preProcessPasses_ = passes; + } + /// See what sort of preprocessing wanted + inline int desiredPreProcess() const + { + return desiredPreProcess_; + } + /// See how many passes wanted + inline int preProcessPasses() const + { + return preProcessPasses_; + } + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + +protected: + // Data + + // Whether to do cuts only at root (-1 -> switch off totally) + int cutsOnlyAtRoot_; + + // How much strong branching to do + int numberStrong_; + + // Number branches needed to trust with dynamic pseudo costs + int numberBeforeTrust_; + + // Print level 0 little, 1 medium + int printLevel_; + + /** Desired pre-processing + 0 - none + 1 - ordinary + 2 - find sos + 3 - find cliques + 4 - more aggressive sos + 5 - add integer slacks + */ + int desiredPreProcess_; + /// Number of pre-processing passes + int preProcessPasses_; + +private: + /// Illegal Assignment operator + CbcStrategyDefault &operator=(const CbcStrategyDefault &rhs); +}; + +/** Default class for sub trees + */ + +class CbcStrategyDefaultSubTree : public CbcStrategy { +public: + // Default Constructor + CbcStrategyDefaultSubTree(CbcModel *parent = NULL, int cutsOnlyAtRoot = 1, + int numberStrong = 5, + int numberBeforeTrust = 0, + int printLevel = 0); + + // Copy constructor + CbcStrategyDefaultSubTree(const CbcStrategyDefaultSubTree &); + + // Destructor + ~CbcStrategyDefaultSubTree(); + + /// Clone + virtual CbcStrategy *clone() const; + + /// Setup cut generators + virtual void setupCutGenerators(CbcModel &model); + /// Setup heuristics + virtual void setupHeuristics(CbcModel &model); + /// Do printing stuff + virtual void setupPrinting(CbcModel &model, int modelLogLevel); + /// Other stuff e.g. strong branching + virtual void setupOther(CbcModel &model); + +protected: + // Data + // Parent model + CbcModel *parentModel_; + // Whether to do cuts only at root (-1 -> switch off totally) + int cutsOnlyAtRoot_; + + // How much strong branching to do + int numberStrong_; + + // Number branches needed to trust with dynamic pseudo costs + int numberBeforeTrust_; + + // Print level 0 little, 1 medium + int printLevel_; + +private: + /// Illegal Assignment operator + CbcStrategyDefaultSubTree &operator=(const CbcStrategyDefaultSubTree &rhs); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSubProblem.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSubProblem.hpp new file mode 100644 index 000000000..6734fef52 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcSubProblem.hpp @@ -0,0 +1,84 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// Edwin 11/10/2009-- carved out of CbcBranchActual + +#ifndef CbcSubProblem_H +#define CbcSubProblem_H + +#ifdef COIN_HAS_CLP +#include "ClpSimplex.hpp" +#include "ClpNode.hpp" + +/** Defines a general subproblem + Basis will be made more compact later +*/ +class CoinWarmStartDiff; +class CbcSubProblem { + +public: + /// Default constructor + CbcSubProblem(); + + /// Constructor from model + CbcSubProblem(const OsiSolverInterface *solver, + const double *lowerBefore, + const double *upperBefore, + const unsigned char *status, + int depth); + + /// Copy constructor + CbcSubProblem(const CbcSubProblem &); + + /// Assignment operator + CbcSubProblem &operator=(const CbcSubProblem &rhs); + + /// Destructor + virtual ~CbcSubProblem(); + + /// Take over + void takeOver(CbcSubProblem &, bool cleanup); + /// Apply subproblem (1=bounds, 2=basis, 3=both) + void apply(OsiSolverInterface *model, int what = 3) const; + +public: + /// Value of objective + double objectiveValue_; + /// Sum of infeasibilities + double sumInfeasibilities_; + /// Branch value + double branchValue_; + /// Dj on branching variable at end + double djValue_; + /** Which variable (top bit if upper bound changing) + next bit if changing on down branch only */ + int *variables_; + /// New bound + double *newBounds_; + /// Status + mutable CoinWarmStartBasis *status_; + /// Depth + int depth_; + /// Number of Extra bound changes + int numberChangedBounds_; + /// Number of infeasibilities + int numberInfeasibilities_; + /** Status 1 bit going up on first, 2 bit set first branch infeasible on second, 4 bit redundant branch, + bits after 256 give reason for stopping (just last node) + 0 - solution + 1 - infeasible + 2 - maximum depth + >2 - error or max time or something + */ + int problemStatus_; + /// Variable branched on + int branchVariable_; +}; + +#endif //COIN_HAS_CLP +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTree.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTree.hpp new file mode 100644 index 000000000..7d481f05d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTree.hpp @@ -0,0 +1,493 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcTree_H +#define CbcTree_H + +#include +#include +#include + +#include "CoinHelperFunctions.hpp" +#include "CbcCompare.hpp" + +/*! \brief Using MS heap implementation + + It's unclear if this is needed any longer, or even if it should be allowed. + Cbc occasionally tries to do things to the tree (typically tweaking the + comparison predicate) that can cause a violation of the heap property (parent better + than either child). In a debug build, Microsoft's heap implementation does checks that + detect this and fail. This symbol switched to an alternate implementation of CbcTree, + and there are clearly differences, but no explanation as to why or what for. + + As of 100921, the code is cleaned up to make it through `cbc -unitTest' without + triggering `Invalid heap' in an MSVS debug build. The method validateHeap() can + be used for debugging if this turns up again. +*/ +//#define CBC_DUBIOUS_HEAP +#if defined(_MSC_VER) || defined(__MNO_CYGWIN) +//#define CBC_DUBIOUS_HEAP +#endif +#if 1 //ndef CBC_DUBIOUS_HEAP + +/*! \brief Controls search tree debugging + + In order to have validateHeap() available, set CBC_DEBUG_HEAP + to 1 or higher. + + - 1 calls validateHeap() after each change to the heap + - 2 will print a line for major operations (clean, set comparison, etc.) + - 3 will print information about each push and pop + +#define CBC_DEBUG_HEAP 1 +*/ + +/*! \class CbcTree + \brief Implementation of the live set as a heap. + + This class is used to hold the set of live nodes in the search tree. +*/ +class CbcTree { + +public: + /*! \name Constructors and related */ + //@{ + /// Default Constructor + CbcTree(); + + /// Copy constructor + CbcTree(const CbcTree &rhs); + + /// = operator + CbcTree &operator=(const CbcTree &rhs); + + /// Destructor + virtual ~CbcTree(); + + /// Clone + virtual CbcTree *clone() const; + + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + //@} + + /*! \name Heap access and maintenance methods */ + //@{ + /// Set comparison function and resort heap + void setComparison(CbcCompareBase &compare); + + /// Return the top node of the heap + virtual CbcNode *top() const; + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Remove the top node from the heap + virtual void pop(); + + /*! \brief Gets best node and takes off heap + + Before returning the node from the top of the heap, the node + is offered an opportunity to reevaluate itself. Callers should + be prepared to check that the node returned is suitable for use. + */ + virtual CbcNode *bestNode(double cutoff); + + /*! \brief Rebuild the heap */ + virtual void rebuild(); + //@} + + /*! \name Direct node access methods */ + //@{ + /// Test for an empty tree + virtual bool empty(); + + /// Return size + virtual int size() const { return static_cast< int >(nodes_.size()); } + + /// Return a node pointer + inline CbcNode *operator[](int i) const { return nodes_[i]; } + + /// Return a node pointer + inline CbcNode *nodePointer(int i) const { return nodes_[i]; } + void realpop(); + /** After changing data in the top node, fix the heap */ + void fixTop(); + void realpush(CbcNode *node); + //@} + + /*! \name Search tree maintenance */ + //@{ + /*! \brief Prune the tree using an objective function cutoff + + This routine removes all nodes with objective worse than the + specified cutoff value. It also sets bestPossibleObjective to + the best objective over remaining nodes. + */ + virtual void cleanTree(CbcModel *model, double cutoff, double &bestPossibleObjective); + + /// Get best on list using alternate method + CbcNode *bestAlternate(); + + /// We may have got an intelligent tree so give it one more chance + virtual void endSearch() {} + + /// Get best possible objective function in the tree + virtual double getBestPossibleObjective(); + + /// Reset maximum node number + inline void resetNodeNumbers() { maximumNodeNumber_ = 0; } + + /// Get maximum node number + inline int maximumNodeNumber() const { return maximumNodeNumber_; } + + /// Set number of branches + inline void setNumberBranching(int value) { numberBranching_ = value; } + + /// Get number of branches + inline int getNumberBranching() const { return numberBranching_; } + + /// Set maximum branches + inline void setMaximumBranching(int value) { maximumBranching_ = value; } + + /// Get maximum branches + inline int getMaximumBranching() const { return maximumBranching_; } + + /// Get branched variables + inline unsigned int *branched() const { return branched_; } + + /// Get bounds + inline int *newBounds() const { return newBound_; } + + /// Last objective in branch-and-cut search tree + inline double lastObjective() const + { + return lastObjective_; + } + /// Last depth in branch-and-cut search tree + inline int lastDepth() const + { + return lastDepth_; + } + /// Last number of objects unsatisfied + inline int lastUnsatisfied() const + { + return lastUnsatisfied_; + } + /// Adds branching information to complete state + void addBranchingInformation(const CbcModel *model, const CbcNodeInfo *nodeInfo, + const double *currentLower, + const double *currentUpper); + /// Increase space for data + void increaseSpace(); + //@} + +#if CBC_DEBUG_HEAP > 0 + /*! \name Debugging methods */ + //@{ + /*! \brief Check that the heap property is satisfied. */ + void validateHeap(); + //@} +#endif + +protected: + /// Storage vector for the heap + std::vector< CbcNode * > nodes_; + /// Sort predicate for heap ordering. + CbcCompare comparison_; + /// Maximum "node" number so far to split ties + int maximumNodeNumber_; + /// Size of variable list + int numberBranching_; + /// Maximum size of variable list + int maximumBranching_; + /// Objective of last node pushed on tree + double lastObjective_; + /// Depth of last node pushed on tree + int lastDepth_; + /// Number unsatisfied of last node pushed on tree + int lastUnsatisfied_; + /** Integer variables branched or bounded + top bit set if new upper bound + next bit set if a branch + */ + unsigned int *branched_; + /// New bound + int *newBound_; +}; + +#ifdef JJF_ZERO // not used +/*! \brief Implementation of live set as a managed array. + + This class is used to hold the set of live nodes in the search tree. +*/ +class CbcTreeArray : public CbcTree { + +public: + // Default Constructor + CbcTreeArray(); + + // Copy constructor + CbcTreeArray(const CbcTreeArray &rhs); + // = operator + CbcTreeArray &operator=(const CbcTreeArray &rhs); + + virtual ~CbcTreeArray(); + + /// Clone + virtual CbcTree *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + + /*! \name Heap access and maintenance methods */ + //@{ + + /// Set comparison function and resort heap + void setComparison(CbcCompareBase &compare); + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Gets best node and takes off heap + virtual CbcNode *bestNode(double cutoff); + + //@} + /*! \name vector methods */ + //@{ + + /// Test if empty *** note may be overridden + virtual bool empty(); + + //@} + + /*! \name Search tree maintenance */ + //@{ + + /*! \brief Prune the tree using an objective function cutoff + + This routine removes all nodes with objective worst than the + specified cutoff value. + It also sets bestPossibleObjective to best + of all on tree before deleting. + */ + + void cleanTree(CbcModel *model, double cutoff, double &bestPossibleObjective); + /// Get best possible objective function in the tree + virtual double getBestPossibleObjective(); + //@} +protected: + /// Returns + /// Last node + CbcNode *lastNode_; + /// Last node popped + CbcNode *lastNodePopped_; + /// Not used yet + int switches_; +}; + +/// New style +#include "CoinSearchTree.hpp" +/*! \class tree + \brief Implementation of live set as a heap. + + This class is used to hold the set of live nodes in the search tree. +*/ + +class CbcNewTree : public CbcTree, public CoinSearchTreeManager { + +public: + // Default Constructor + CbcNewTree(); + + // Copy constructor + CbcNewTree(const CbcNewTree &rhs); + // = operator + CbcNewTree &operator=(const CbcNewTree &rhs); + + virtual ~CbcNewTree(); + + /// Clone + virtual CbcNewTree *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *) {} + + /*! \name Heap access and maintenance methods */ + //@{ + + /// Set comparison function and resort heap + void setComparison(CbcCompareBase &compare); + + /// Return the top node of the heap + virtual CbcNode *top() const; + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Remove the top node from the heap + virtual void pop(); + /// Gets best node and takes off heap + virtual CbcNode *bestNode(double cutoff); + + //@} + /*! \name vector methods */ + //@{ + + /// Test if empty *** note may be overridden + virtual bool empty(); + + /// Return size + inline int size() const + { + return nodes_.size(); + } + + /// [] operator + inline CbcNode *operator[](int i) const + { + return nodes_[i]; + } + + /// Return a node pointer + inline CbcNode *nodePointer(int i) const + { + return nodes_[i]; + } + + //@} + + /*! \name Search tree maintenance */ + //@{ + + /*! \brief Prune the tree using an objective function cutoff + + This routine removes all nodes with objective worst than the + specified cutoff value. + It also sets bestPossibleObjective to best + of all on tree before deleting. + */ + + void cleanTree(CbcModel *model, double cutoff, double &bestPossibleObjective); + + /// Get best on list using alternate method + CbcNode *bestAlternate(); + + /// We may have got an intelligent tree so give it one more chance + virtual void endSearch() {} + //@} +protected: +}; +#endif +#else +/* CBC_DUBIOUS_HEAP is defined + + See note at top of file. This code is highly suspect. + -- lh, 100921 -- +*/ +class CbcTree { + +public: + // Default Constructor + CbcTree(); + + // Copy constructor + CbcTree(const CbcTree &rhs); + // = operator + CbcTree &operator=(const CbcTree &rhs); + + virtual ~CbcTree(); + + /// Clone + virtual CbcTree *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp) {} + + /*! \name Heap access and maintenance methods */ + //@{ + + /// Set comparison function and resort heap + void setComparison(CbcCompareBase &compare); + + /// Return the top node of the heap + virtual CbcNode *top() const; + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Remove the top node from the heap + virtual void pop(); + /// Gets best node and takes off heap + virtual CbcNode *bestNode(double cutoff); + + //@} + /*! \name vector methods */ + //@{ + + /// Test if empty *** note may be overridden + //virtual bool empty() ; + + /// Return size + inline int size() const + { + return nodes_.size(); + } + + /// [] operator + inline CbcNode *operator[](int i) const + { + return nodes_[i]; + } + + /// Return a node pointer + inline CbcNode *nodePointer(int i) const + { + return nodes_[i]; + } + + virtual bool empty(); + //inline int size() const { return size_; } + void realpop(); + /** After changing data in the top node, fix the heap */ + void fixTop(); + void realpush(CbcNode *node); + //@} + + /*! \name Search tree maintenance */ + //@{ + + /*! \brief Prune the tree using an objective function cutoff + + This routine removes all nodes with objective worst than the + specified cutoff value. + It also sets bestPossibleObjective to best + of all on tree before deleting. + */ + + void cleanTree(CbcModel *model, double cutoff, double &bestPossibleObjective); + + /// Get best on list using alternate method + CbcNode *bestAlternate(); + + /// We may have got an intelligent tree so give it one more chance + virtual void endSearch() {} + /// Reset maximum node number + inline void resetNodeNumbers() + { + maximumNodeNumber_ = 0; + } + + /// Get maximum node number + inline int maximumNodeNumber() const { return maximumNodeNumber_; } + //@} +protected: + std::vector< CbcNode * > nodes_; + CbcCompare comparison_; ///> Sort function for heap ordering. + /// Maximum "node" number so far to split ties + int maximumNodeNumber_; +}; +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTreeLocal.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTreeLocal.hpp new file mode 100644 index 000000000..e2bcb991c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CbcTreeLocal.hpp @@ -0,0 +1,393 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CbcTreeLocal_H +#define CbcTreeLocal_H + +//############################################################################# +/* This implements (approximately) local branching as in the 2002 paper by + Matteo Fischetti and Andrea Lodi. + + The very simple version of the algorithm for problems with + 0-1 variables and continuous is as follows: + + Obtain a feasible solution (one can be passed in). + + Add a cut which limits search to a k neighborhood of this solution. + (At most k 0-1 variables may change value) + Do branch and bound on this problem. + + If finished search and proven optimal then we can reverse cut so + any solutions must be at least k+1 away from solution and we can + add a new cut limiting search to a k neighborhood of new solution + repeat. + + If finished search and no new solution then the simplest version + would reverse last cut and complete search. The version implemented + here can use time and node limits and can widen search (increase effective k) + .... and more + +*/ + +#include "CbcTree.hpp" +#include "CbcNode.hpp" +#include "OsiRowCut.hpp" +class CbcModel; + +class CbcTreeLocal : public CbcTree { + +public: + // Default Constructor + CbcTreeLocal(); + + /* Constructor with solution. + If solution NULL no solution, otherwise must be integer + range is initial upper bound (k) on difference from given solution. + typeCuts - + 0 means just 0-1 cuts and will need to refine 0-1 solution + 1 uses weaker cuts on all integer variables + maxDiversification is maximum number of range widenings to try + timeLimit is seconds in subTree + nodeLimit is nodes in subTree + refine is whether to see if we can prove current solution is optimal + when we fix all 0-1 (in case typeCuts==0 and there are general integer variables) + if false then no refinement but reverse cuts weaker + */ + CbcTreeLocal(CbcModel *model, const double *solution, int range = 10, + int typeCuts = 0, int maxDiversification = 0, + int timeLimit = 1000000, int nodeLimit = 1000000, bool refine = true); + // Copy constructor + CbcTreeLocal(const CbcTreeLocal &rhs); + + // = operator + CbcTreeLocal &operator=(const CbcTreeLocal &rhs); + + virtual ~CbcTreeLocal(); + + /// Clone + virtual CbcTree *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /*! \name Heap access and maintenance methods */ + //@{ + + /// Return the top node of the heap + virtual CbcNode *top() const; + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Remove the top node from the heap + virtual void pop(); + + //@} + /*! \name Other stuff */ + //@{ + + /// Create cut - return -1 if bad, 0 if okay and 1 if cut is everything + int createCut(const double *solution, OsiRowCut &cut); + + /// Test if empty *** note may be overridden + virtual bool empty(); + + /// We may have got an intelligent tree so give it one more chance + virtual void endSearch(); + /// Other side of last cut branch (if bias==rhs_ will be weakest possible) + void reverseCut(int state, double bias = 0.0); + /// Delete last cut branch + void deleteCut(OsiRowCut &cut); + /// Pass in solution (so can be used after heuristic) + void passInSolution(const double *solution, double solutionValue); + // range i.e. k + inline int range() const + { + return range_; + } + // setrange i.e. k + inline void setRange(int value) + { + range_ = value; + } + // Type of cuts - 0=just 0-1, 1=all + inline int typeCuts() const + { + return typeCuts_; + } + // Type of cuts - 0=just 0-1, 1=all + inline void setTypeCuts(int value) + { + typeCuts_ = value; + } + // maximum number of diversifications + inline int maxDiversification() const + { + return maxDiversification_; + } + // maximum number of diversifications + inline void setMaxDiversification(int value) + { + maxDiversification_ = value; + } + // time limit per subtree + inline int timeLimit() const + { + return timeLimit_; + } + // time limit per subtree + inline void setTimeLimit(int value) + { + timeLimit_ = value; + } + // node limit for subtree + inline int nodeLimit() const + { + return nodeLimit_; + } + // node limit for subtree + inline void setNodeLimit(int value) + { + nodeLimit_ = value; + } + // Whether to do refinement step + inline bool refine() const + { + return refine_; + } + // Whether to do refinement step + inline void setRefine(bool yesNo) + { + refine_ = yesNo; + } + + //@} +private: + // Node for local cuts + CbcNode *localNode_; + // best solution + double *bestSolution_; + // saved solution + double *savedSolution_; + // solution number at start of pass + int saveNumberSolutions_; + /* Cut. If zero size then no solution yet. Otherwise is left hand branch */ + OsiRowCut cut_; + // This cut fixes all 0-1 variables + OsiRowCut fixedCut_; + // Model + CbcModel *model_; + // Original lower bounds + double *originalLower_; + // Original upper bounds + double *originalUpper_; + // range i.e. k + int range_; + // Type of cuts - 0=just 0-1, 1=all + int typeCuts_; + // maximum number of diversifications + int maxDiversification_; + // current diversification + int diversification_; + // Whether next will be strong diversification + bool nextStrong_; + // Current rhs + double rhs_; + // Save allowable gap + double savedGap_; + // Best solution + double bestCutoff_; + // time limit per subtree + int timeLimit_; + // time when subtree started + int startTime_; + // node limit for subtree + int nodeLimit_; + // node count when subtree started + int startNode_; + // -1 not started, 0 == stop on first solution, 1 don't stop on first, 2 refinement step + int searchType_; + // Whether to do refinement step + bool refine_; +}; + +class CbcTreeVariable : public CbcTree { + +public: + // Default Constructor + CbcTreeVariable(); + + /* Constructor with solution. + If solution NULL no solution, otherwise must be integer + range is initial upper bound (k) on difference from given solution. + typeCuts - + 0 means just 0-1 cuts and will need to refine 0-1 solution + 1 uses weaker cuts on all integer variables + maxDiversification is maximum number of range widenings to try + timeLimit is seconds in subTree + nodeLimit is nodes in subTree + refine is whether to see if we can prove current solution is optimal + when we fix all 0-1 (in case typeCuts==0 and there are general integer variables) + if false then no refinement but reverse cuts weaker + */ + CbcTreeVariable(CbcModel *model, const double *solution, int range = 10, + int typeCuts = 0, int maxDiversification = 0, + int timeLimit = 1000000, int nodeLimit = 1000000, bool refine = true); + // Copy constructor + CbcTreeVariable(const CbcTreeVariable &rhs); + + // = operator + CbcTreeVariable &operator=(const CbcTreeVariable &rhs); + + virtual ~CbcTreeVariable(); + + /// Clone + virtual CbcTree *clone() const; + /// Create C++ lines to get to current state + virtual void generateCpp(FILE *fp); + + /*! \name Heap access and maintenance methods */ + //@{ + + /// Return the top node of the heap + virtual CbcNode *top() const; + + /// Add a node to the heap + virtual void push(CbcNode *x); + + /// Remove the top node from the heap + virtual void pop(); + + //@} + /*! \name Other stuff */ + //@{ + + /// Create cut - return -1 if bad, 0 if okay and 1 if cut is everything + int createCut(const double *solution, OsiRowCut &cut); + + /// Test if empty *** note may be overridden + virtual bool empty(); + + /// We may have got an intelligent tree so give it one more chance + virtual void endSearch(); + /// Other side of last cut branch (if bias==rhs_ will be weakest possible) + void reverseCut(int state, double bias = 0.0); + /// Delete last cut branch + void deleteCut(OsiRowCut &cut); + /// Pass in solution (so can be used after heuristic) + void passInSolution(const double *solution, double solutionValue); + // range i.e. k + inline int range() const + { + return range_; + } + // setrange i.e. k + inline void setRange(int value) + { + range_ = value; + } + // Type of cuts - 0=just 0-1, 1=all + inline int typeCuts() const + { + return typeCuts_; + } + // Type of cuts - 0=just 0-1, 1=all + inline void setTypeCuts(int value) + { + typeCuts_ = value; + } + // maximum number of diversifications + inline int maxDiversification() const + { + return maxDiversification_; + } + // maximum number of diversifications + inline void setMaxDiversification(int value) + { + maxDiversification_ = value; + } + // time limit per subtree + inline int timeLimit() const + { + return timeLimit_; + } + // time limit per subtree + inline void setTimeLimit(int value) + { + timeLimit_ = value; + } + // node limit for subtree + inline int nodeLimit() const + { + return nodeLimit_; + } + // node limit for subtree + inline void setNodeLimit(int value) + { + nodeLimit_ = value; + } + // Whether to do refinement step + inline bool refine() const + { + return refine_; + } + // Whether to do refinement step + inline void setRefine(bool yesNo) + { + refine_ = yesNo; + } + + //@} +private: + // Node for local cuts + CbcNode *localNode_; + // best solution + double *bestSolution_; + // saved solution + double *savedSolution_; + // solution number at start of pass + int saveNumberSolutions_; + /* Cut. If zero size then no solution yet. Otherwise is left hand branch */ + OsiRowCut cut_; + // This cut fixes all 0-1 variables + OsiRowCut fixedCut_; + // Model + CbcModel *model_; + // Original lower bounds + double *originalLower_; + // Original upper bounds + double *originalUpper_; + // range i.e. k + int range_; + // Type of cuts - 0=just 0-1, 1=all + int typeCuts_; + // maximum number of diversifications + int maxDiversification_; + // current diversification + int diversification_; + // Whether next will be strong diversification + bool nextStrong_; + // Current rhs + double rhs_; + // Save allowable gap + double savedGap_; + // Best solution + double bestCutoff_; + // time limit per subtree + int timeLimit_; + // time when subtree started + int startTime_; + // node limit for subtree + int nodeLimit_; + // node count when subtree started + int startNode_; + // -1 not started, 0 == stop on first solution, 1 don't stop on first, 2 refinement step + int searchType_; + // Whether to do refinement step + bool refine_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cbc_C_Interface.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cbc_C_Interface.h new file mode 100644 index 000000000..abef85624 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cbc_C_Interface.h @@ -0,0 +1,904 @@ +/* $Id$ */ +/* + Copyright (C) 2004 International Business Machines Corporation and others. + All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef CbcModelC_H +#define CbcModelC_H + +/* include all defines and ugly stuff */ +#include "Coin_C_defines.h" +#include + +/* + * Original version contributed by Bob Entriken, + * significantly updated by Miles Lubin. + * 2018: several updates by Haroldo + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Current version of Cbc */ +COINLIBAPI const char *COINLINKAGE Cbc_getVersion(void); + +/** \name Problem creation and modification routines */ +/**@{*/ + +/** @brief Creates an empty problem */ +COINLIBAPI Cbc_Model *COINLINKAGE +Cbc_newModel(void); + +/** @brief Sets problem name. + * + * @param model problem object + * @param array string with problem name + **/ +COINLIBAPI int COINLINKAGE +Cbc_setProblemName(Cbc_Model *model, const char *array); + +/** @brief Creates a new column + * + * Creates a new column (variable) + * + * @param model problem object + * @param name variable name + * @param lb column lower bound + * @param ub column upper bound + * @param obj objective function coefficient + * @param isInteger 1 if variable is integral, 0 otherwise + * @param nz number of rows (constraints) where this column appears, can be 0 if constraints will be added later + * @param rows index of rows where this column appears, NULL if rows will be added later + * @param coefs coefficients that this column appears in its rows, NULL if rows will be added later + ***/ +COINLIBAPI void COINLINKAGE +Cbc_addCol(Cbc_Model *model, const char *name, double lb, + double ub, double obj, char isInteger, + int nz, int *rows, double *coefs); + +/** @brief Adds a new row + * + * Adds a new row (linear constraint) to the problem + * + * @param model problem object + * @param name constraint name + * @param nz number of variables with non-zero coefficients in this row + * @param cols index of variables that appear in this row + * @param coefs cofficients that that variables appear + * @param sense constraint sense: L if <=, G if >=, E if =, R if ranged and N if free + * @param rhs right hand size + * */ +COINLIBAPI void COINLINKAGE +Cbc_addRow(Cbc_Model *model, const char *name, int nz, + const int *cols, const double *coefs, char sense, double rhs); + +/** @brief Add SOS constraints to the model using row-order matrix */ +COINLIBAPI void COINLINKAGE +Cbc_addSOS(Cbc_Model *model, int numRows, const int *rowStarts, + const int *colIndices, const double *weights, const int type); + +/** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ + The constraint matrix is + given in standard compressed sparse column (without gaps). +
    +
  • start[i] stores the starting index of the ith column +
  • index[k] stores the row index of the kth nonzero element +
  • value[k] stores the coefficient of the kth nonzero element +
+ */ +COINLIBAPI void COINLINKAGE +Cbc_loadProblem(Cbc_Model *model, const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + +/** @brief Set the name of a column + * + * @param model problem object + * @param iColumn column index + * @param column name + **/ +COINLIBAPI void COINLINKAGE +Cbc_setColName(Cbc_Model *model, int iColumn, const char *name); + +/** @brief Set the name of a row + * + * @param model problem object + * @param iRow row index + * @param name row name + **/ +COINLIBAPI void COINLINKAGE +Cbc_setRowName(Cbc_Model *model, int iRow, const char *name); + +/** @brief Sets optimization direction + * + * @param model problem object + * @param sense: direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) + **/ +COINLIBAPI void COINLINKAGE +Cbc_setObjSense(Cbc_Model *model, double sense); + +/** @brief Set the lower bound of a single constraint + * + * @param model problem object + * @param index row index + * @param value new row lower bound + **/ +COINLIBAPI void COINLINKAGE +Cbc_setRowLower(Cbc_Model *model, int index, double value); + +/** @brief Set the upper bound of a single constraint + * + * @param model problem object + * @param index row index + * @param value new row upper bound + **/ +COINLIBAPI void COINLINKAGE +Cbc_setRowUpper(Cbc_Model *model, int index, double value); + +/** @brief Set the objective coefficient of a single variable + * + * @param model problem object + * @param index variable index + * @param value new objective function coefficient for this variable + **/ +COINLIBAPI void COINLINKAGE +Cbc_setObjCoeff(Cbc_Model *model, int index, double value); + +/** @brief Set the lower bound of a single variable + * + * @param model problem object + * @param index variable index + * @param value variable lower bound + **/ +COINLIBAPI void COINLINKAGE +Cbc_setColLower(Cbc_Model *model, int index, double value); + +/** @brief Set the upper bound of a single variable + * + * @param model problem object + * @param index variable index + * @param value new variable upper bound + **/ +COINLIBAPI void COINLINKAGE +Cbc_setColUpper(Cbc_Model *model, int index, double value); + +/** @brief Set this variable to be continuous + * + * @param model problem object + * @param iColumn column index + **/ +COINLIBAPI void COINLINKAGE +Cbc_setContinuous(Cbc_Model *model, int iColumn); + +/** @brief Set this variable to be integer + * + * @param model problem object + * @param iColumn column index + **/ +COINLIBAPI void COINLINKAGE +Cbc_setInteger(Cbc_Model *model, int iColumn); + +/** @brief Cbc_Model destructor */ +COINLIBAPI void COINLINKAGE +Cbc_deleteModel(Cbc_Model *model); + +/** @brief Enter initial feasible solution + * + * Enter an initial feasible solution. Only the non-zero main + * binary/integer decision variables need to be informed. + * Auxiliary and/or continuous variables are computed + * automatically. + * + * @param model problem object + * @param count number of variables + * @param colNames names of variables + * @param colValues variable values + * + **/ +COINLIBAPI void COINLINKAGE +Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double colValues[]); + +/** @brief Enter initial feasible solution + * + * Enter an initial feasible solution. Only the non-zero main + * binary/integer decision variables need to be informed. + * Auxiliary and/or continuous variables are computed + * automatically. Same as setMIPStart but using variable indexes. + * + * @param model problem object + * @param count number of variables + * @param colIdxs indexes of variables + * @param colValues variable values + * + **/ +COINLIBAPI void COINLINKAGE +Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double colValues[]); + +/** @brief Creates a copy of the current model + * + * @param model problem object + * @return model copy + **/ +COINLIBAPI Cbc_Model *COINLINKAGE +Cbc_clone(Cbc_Model *model); + +/**@}*/ + +/** \name Routines to query problem contents +*/ +/**@{*/ + +/** @brief Queries problem name + * + * @param model problem object + * @param maxNumberCharacters space in string array + * @param array string where problem name will be saved + **/ +COINLIBAPI void COINLINKAGE +Cbc_problemName(Cbc_Model *model, int maxNumberCharacters, char *array); + +/** @brief Number of nonzero elements in constraint matrix + * + * @param model problem object + * @return number of non-zero entries in constraint matrix + **/ +COINLIBAPI int COINLINKAGE +Cbc_getNumElements(Cbc_Model *model); + +/** @brief Number of variables in the model + * @param model problem object + * @return number of columns (variables) + **/ +COINLIBAPI int COINLINKAGE +Cbc_getNumCols(Cbc_Model *model); + +/** @brief Number of integer variables in the model + * + * @param model problem object + * @return number of integer variables in this model + **/ +COINLIBAPI int COINLINKAGE +Cbc_getNumIntegers(Cbc_Model *model); + +/** Number of constraints in the model + * @param model problem object + * @return number of rows (constraints) in the model + **/ +COINLIBAPI int COINLINKAGE +Cbc_getNumRows(Cbc_Model *model); + +/** @brief Queries row name + * + * @param model problem object + * @param row index + * @param name string where row name will be stored + * @param string where row name will be stored + **/ +COINLIBAPI void COINLINKAGE +Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength); + +/** Queries column name + * + * @param model problem object + * @param iColumn column index + * @param name where name will be stored + * @param maxLength maximum length of name string + **/ +COINLIBAPI void COINLINKAGE +Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength); + +/** @brief Number of non-zero entries in a row + * + * @param model problem object + * @param row row index + * @return number of non-zero entries in row + **/ +COINLIBAPI int COINLINKAGE +Cbc_getRowNz(Cbc_Model *model, int row); + +/** @brief Indices of variables that appear on a row + * + * @param model problem object + * @param row row index + * @return vector with indexes of columns that appear on this row + **/ +COINLIBAPI const int *COINLINKAGE +Cbc_getRowIndices(Cbc_Model *model, int row); + +/** @brief Coefficients of variables that appear on this row + * + * @param model problem object + * @param row row index + * @return coefficients of variables that appear on this row + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getRowCoeffs(Cbc_Model *model, int row); + +/** @brief Number of non-zero entries in a column + * + * @param model problem object + * @param col column index + * @return numbef of rows that this column appears + **/ +COINLIBAPI int COINLINKAGE +Cbc_getColNz(Cbc_Model *model, int col); + +/** @brief Indices of rows that a column appears + * + * @param model problem object + * @param col column index + * @return indices of rows that this column appears + **/ +COINLIBAPI const int *COINLINKAGE +Cbc_getColIndices(Cbc_Model *model, int col); + +/** @brief Coefficients that a column appear in rows + * + * @param model problem object + * @param col column index + * @return coefficients of this column in rows + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getColCoeffs(Cbc_Model *model, int col); + +/** @brief Right hand side of a row + * + * @param model problem object + * @param row row index + * @return row right hand side + **/ +COINLIBAPI double COINLINKAGE +Cbc_getRowRHS(Cbc_Model *model, int row); + +/** @brief Sense a row + * @param model problem object + * @param row row index + * @return row sense: E for =, L for <=, G for >= and R for ranged row + **/ +COINLIBAPI char COINLINKAGE +Cbc_getRowSense(Cbc_Model *model, int row); + +/** @brief Direction of optimization + * + * @param model problem object + * @return Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore) + **/ +COINLIBAPI double COINLINKAGE +Cbc_getObjSense(Cbc_Model *model); + +/** @brief Constraint lower bounds + * + * @param model problem object + * @return vector with lower bounds of constraints + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getRowLower(Cbc_Model *model); + +/** @brief Constraint upper bounds + * + * @param model problem object + * @return constraint upper bounds + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getRowUpper(Cbc_Model *model); + +/** @brief Objective vector + * + * @param model problem object + * @return vector with coefficients of variables in the objective function + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getObjCoefficients(Cbc_Model *model); + +/** @brief Variable lower bounds + * + * @param model problem object + * @return vector with lower bounds of variables + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getColLower(Cbc_Model *model); + +/** @brief Variable upper bounds + * + * @param model problem object + * @return vector with column upper bounds + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getColUpper(Cbc_Model *model); + +/** @brief Determine whether the ith variable is integer restricted + * + * @param model problem object + * @param i variable index + * @return 1 if variable is integer, 0 otherwise + **/ +COINLIBAPI int COINLINKAGE +Cbc_isInteger(Cbc_Model *model, int i); + + +/**@}*/ + +/** \name Routines to load and save problems from disk +*/ +/**@{*/ + +/** @brief Read an mps file from the given filename + * + * @param model problem object + * @param fileName file name + **/ +COINLIBAPI int COINLINKAGE +Cbc_readMps(Cbc_Model *model, const char *filename); + +/** @brief Read an lp file from the given filename + * + * @param model problem object + * @param fileName file name + **/ +COINLIBAPI int COINLINKAGE +Cbc_readLp(Cbc_Model *model, const char *filename); + +/** @brief Write an mps file from the given filename + * + * @param model problem object + * @param fileName file name + **/ +COINLIBAPI void COINLINKAGE +Cbc_writeMps(Cbc_Model *model, const char *filename); + +/** @brief Write an lp file from the given filename + * + * @param model problem object + * @param fileName file name + **/ +COINLIBAPI void COINLINKAGE +Cbc_writeLp(Cbc_Model *model, const char *filename); + +/**@}*/ + +/**@name Getting and setting model data + Note that problem access and modification methods, + such as getColLower and setColLower, + are *not valid* after calling Cbc_solve(). + Therefore it is not recommended to reuse a Cbc_Model + object for multiple solves. A workaround is to call Cbc_clone() + before solving. + * */ +/**@{*/ + +/** Provide an initial feasible solution to accelerate branch-and-bound + Note that feasibility of the solution is *not* verified. + */ +COINLIBAPI void COINLINKAGE +Cbc_setInitialSolution(Cbc_Model *model, const double *sol); +/** "Column start" vector of constraint matrix. Same format as Cbc_loadProblem() */ +COINLIBAPI const CoinBigIndex *COINLINKAGE +Cbc_getVectorStarts(Cbc_Model *model); +/** "Row index" vector of constraint matrix */ +COINLIBAPI const int *COINLINKAGE +Cbc_getIndices(Cbc_Model *model); +/** Coefficient vector of constraint matrix */ +COINLIBAPI const double *COINLINKAGE +Cbc_getElements(Cbc_Model *model); + +/** Maximum lenght of a row or column name */ +COINLIBAPI size_t COINLINKAGE +Cbc_maxNameLength(Cbc_Model *model); +/** Print the model */ +COINLIBAPI void COINLINKAGE +Cbc_printModel(Cbc_Model *model, const char *argPrefix); +/**@}*/ + +/**@name Solver parameters */ +/**@{*/ +/** Set parameter "name" to value "value". Note that this + * translates directly to using "-name value" as a + * command-line argument to Cbc.*/ +COINLIBAPI void COINLINKAGE +Cbc_setParameter(Cbc_Model *model, const char *name, const char *value); + + +/** returns the allowable gap + */ +COINLIBAPI double COINLINKAGE +Cbc_getAllowableGap(Cbc_Model *model); + +/** sets the allowable gap + */ +COINLIBAPI void COINLINKAGE +Cbc_setAllowableGap(Cbc_Model *model, double allowedGap); + +/** returns the allowable fraction gap + */ +COINLIBAPI double COINLINKAGE +Cbc_getAllowableFractionGap(Cbc_Model *model); + +/** sets the allowable fraction gap + */ +COINLIBAPI void COINLINKAGE +Cbc_setAllowableFractionGap(Cbc_Model *model, double allowedFracionGap); + +/** returns the allowable percentage gap + */ +COINLIBAPI double COINLINKAGE +Cbc_getAllowablePercentageGap(Cbc_Model *model); + +/** sets the allowable percentage gap + */ +COINLIBAPI void COINLINKAGE +Cbc_setAllowablePercentageGap(Cbc_Model *model, double allowedPercentageGap); + +/** returns the time limit for the search process + */ +COINLIBAPI double COINLINKAGE +Cbc_getMaximumSeconds(Cbc_Model *model); + +/** sets the time limit for the search process + */ +COINLIBAPI void COINLINKAGE +Cbc_setMaximumSeconds(Cbc_Model *model, double maxSeconds); + + +/** returns the maximum number of nodes that can be explored in the search tree + */ +COINLIBAPI int COINLINKAGE +Cbc_getMaximumNodes(Cbc_Model *model); + +/** sets the maximum number of nodes that can be explored in the search tree + */ +COINLIBAPI void COINLINKAGE +Cbc_setMaximumNodes(Cbc_Model *model, int maxNodes); + +/** returns solution limit for the search process + */ +COINLIBAPI int COINLINKAGE +Cbc_getMaximumSolutions(Cbc_Model *model); + +/** sets a solution limit as a stopping criterion + */ +COINLIBAPI void COINLINKAGE +Cbc_setMaximumSolutions(Cbc_Model *model, int maxSolutions); + +/** returns the current log leven + */ +COINLIBAPI int COINLINKAGE +Cbc_getLogLevel(Cbc_Model *model); + +/** sets the log level + */ +COINLIBAPI void COINLINKAGE +Cbc_setLogLevel(Cbc_Model *model, int logLevel); + + +/** returns the cutoff + */ +COINLIBAPI double COINLINKAGE +Cbc_getCutoff(Cbc_Model *model); + +/** sets the cutoff + */ +COINLIBAPI void COINLINKAGE +Cbc_setCutoff(Cbc_Model *model, double cutoff); + + + +/**@}*/ +/**@name Message handling. Call backs are handled by ONE function */ +/**@{*/ +/** Pass in Callback function. + Message numbers up to 1000000 are Clp, Coin ones have 1000000 added */ +COINLIBAPI void COINLINKAGE +Cbc_registerCallBack(Cbc_Model *model, + cbc_callback userCallBack); + +/** Unset Callback function */ +COINLIBAPI void COINLINKAGE +Cbc_clearCallBack(Cbc_Model *model); + +COINLIBAPI void COINLINKAGE Cbc_addCutCallback( + Cbc_Model *model, cbc_cut_callback cutcb, + const char *name, void *appData ); + +/**@}*/ + +/**@name Solving the model */ +/**@{*/ +/* Solve the model with Cbc (using CbcMain1). + */ +COINLIBAPI int COINLINKAGE +Cbc_solve(Cbc_Model *model); +/**@}*/ + +/**@name Accessing the solution and optimization status */ +/**@{*/ + +/** @brief Best feasible solution vector + * + * @param model problem object + * @return vector with best solution found + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getColSolution(Cbc_Model *model); + + +/** @brief Best known bound on the optimal objective value + * + * @param model problem object + * @return best possible cost (lower bound) + **/ +COINLIBAPI double COINLINKAGE +Cbc_getBestPossibleObjValue(Cbc_Model *model); + +/** @brief Best integer feasible solution + * + * Best integer feasible solution or NULL if no integer feas sol found + * + * @param model problem object + * @return vector with the best solution found or NULL if no feasible solution was found + **/ +COINLIBAPI double *COINLINKAGE +Cbc_bestSolution(Cbc_Model *model); + +/** @brief number of integer feasible solution saved + * + * @param model problem object + * @return number of saved solutions + **/ +COINLIBAPI int COINLINKAGE +Cbc_numberSavedSolutions(Cbc_Model *model); + +/** @brief Vector with the i-th saved solution + * + * @param model problem object + * @param whichSol index of the solution to be retrieved + * @return vector with integer feasible solution + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_savedSolution(Cbc_Model *model, int whichSol); + +/** @brief Cost of the whichSol solution + * + * @param model problem object + * @param whichSol solution index + * @return solution cost + **/ +COINLIBAPI double COINLINKAGE +Cbc_savedSolutionObj(Cbc_Model *model, int whichSol); + +/** @brief Queries vector of reduced costs + * + * @param model problem object + * @return reduced cost vector + **/ +COINLIBAPI const double *COINLINKAGE +Cbc_getReducedCost(Cbc_Model *model); + +/** If optimization was abandoned due to numerical difficulties + * + * @param model problem object + * @return 1 if numerical difficulties interrupted the optimization, 0 otherwise + * */ +COINLIBAPI int COINLINKAGE +Cbc_isAbandoned(Cbc_Model *model); + +/** @brief If the optimal solution was found + * + * @param model problem object + * @return 1 if optimal solution was found, 0 otherwise + **/ +COINLIBAPI int COINLINKAGE +Cbc_isProvenOptimal(Cbc_Model *model); + +/** @brief If infeasibility was proven + * + * If model is infeasible, please note that infeasibility can also be declared + * if cutoff is informed and no solution better than the cutoff exists. + * + * @param model problem object + * @return 1 if model is infeasible, 0 otherwise + **/ +COINLIBAPI int COINLINKAGE +Cbc_isProvenInfeasible(Cbc_Model *model); + +/** @brief Is continuous model unbounded ? + * + * @param model problem object + * @return 1 if model is unbounded, 0 otherwise + * */ +COINLIBAPI int COINLINKAGE +Cbc_isContinuousUnbounded(Cbc_Model *model); + +/** Objective value of best feasible solution + * + * @param model problem object + * @return cost of the best solution found + * */ +COINLIBAPI double COINLINKAGE +Cbc_getObjValue(Cbc_Model *model); + +/** @brief Final optimization status + * + * Returns the optimization status. For more info check function + * isProvenOptimal, isProvenInfeasible, etc. Check also secondary status. + * Possible status are: + * + * -1 before branchAndBound + * 0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found (or check value of best solution) + * 1 stopped - on maxnodes, maxsols, maxtime + * 2 execution abandoned due to numerical dificulties + * 5 user programmed interruption + * + * @param model problem object + * @return problem status + */ +COINLIBAPI int COINLINKAGE Cbc_status(Cbc_Model *model); + +/** @brief Secondary status of problem + * + * Returns additional information regarding the optimization status + * + * -1 unset (status_ will also be -1) + * 0 search completed with solution + * 1 linear relaxation not feasible (or worse than cutoff) + * 2 stopped on gap + * 3 stopped on nodes + * 4 stopped on time + * 5 stopped on user event + * 6 stopped on solutions + * 7 linear relaxation unbounded + * 8 stopped on iteration limit + * + * @model problem object + * @return optimization status + */ +COINLIBAPI int COINLINKAGE +Cbc_secondaryStatus(Cbc_Model *model); + +/** Sum of primal infeasibilities */ +COINLIBAPI double COINLINKAGE +Cbc_sumPrimalInfeasibilities(Cbc_Model *model); + +/** Number of primal infeasibilities */ +COINLIBAPI int COINLINKAGE +Cbc_numberPrimalInfeasibilities(Cbc_Model *model); + +/** Just check solution (for external use) - sets sum of + infeasibilities etc */ +COINLIBAPI void COINLINKAGE +Cbc_checkSolution(Cbc_Model *model); + +/** Number of iterations */ +COINLIBAPI int COINLINKAGE +Cbc_getIterationCount(Cbc_Model *model); + +/** Node limit reached? */ +COINLIBAPI int COINLINKAGE +Cbc_isNodeLimitReached(Cbc_Model *model); +/** Time limit reached? */ +COINLIBAPI int COINLINKAGE +Cbc_isSecondsLimitReached(Cbc_Model *model); +/** Solution limit reached? */ +COINLIBAPI int COINLINKAGE +Cbc_isSolutionLimitReached(Cbc_Model *model); +/** Are there numerical difficulties (for initialSolve) ? */ +COINLIBAPI int COINLINKAGE +Cbc_isInitialSolveAbandoned(Cbc_Model *model); +/** Is optimality proven (for initialSolve) ? */ +COINLIBAPI int COINLINKAGE +Cbc_isInitialSolveProvenOptimal(Cbc_Model *model); +/** Is primal infeasiblity proven (for initialSolve) ? */ +COINLIBAPI int COINLINKAGE +Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model *model); +/** "row" solution + * This is the vector A*x, where A is the constraint matrix + * and x is the current solution. */ +COINLIBAPI const double *COINLINKAGE +Cbc_getRowActivity(Cbc_Model *model); +/** Number of nodes explored in B&B tree */ +COINLIBAPI int COINLINKAGE +Cbc_getNodeCount(Cbc_Model *model); +/** Print the solution */ +COINLIBAPI void COINLINKAGE +Cbc_printSolution(Cbc_Model *model); + +/**@}*/ + +/** \name OsiSolverInterface related routines (used in callbacks) */ +/**@{*/ + +/** @brief Returns number of cols in OsiSolverInterface object */ +COINLIBAPI int COINLINKAGE +Osi_getNumCols( void *osi ); + +/** @brief Returns column name in OsiSolverInterface object */ +COINLIBAPI void COINLINKAGE +Osi_getColName( void *osi, int i, char *name, int maxLen ); + +/** @brief Returns column lower bounds in OsiSolverInterface object */ +COINLIBAPI const double * COINLINKAGE +Osi_getColLower( void *osi ); + +/** @brief Returns column upper bounds in OsiSolverInterface object */ +COINLIBAPI const double * COINLINKAGE +Osi_getColUpper( void *osi ); + +/** @brief Returns integrality information for columns in OsiSolverInterface object */ +COINLIBAPI int COINLINKAGE +Osi_isInteger( void *osi, int col ); + +/** @brief Returns number of rows in OsiSolverInterface object */ +COINLIBAPI int COINLINKAGE +Osi_getNumRows( void *osi ); + +COINLIBAPI int COINLINKAGE +Osi_getRowNz(void *osi, int row); + +/** @brief Indices of variables that appear on a row */ +COINLIBAPI const int *COINLINKAGE +Osi_getRowIndices(void *osi, int row); + +/** @brief Coefficients of variables that appear on this row + * + * @param model problem object + * @param row row index + * @return coefficients of variables that appear on this row + **/ +COINLIBAPI const double *COINLINKAGE +Osi_getRowCoeffs(void *osi, int row); + +/** @brief Right hand side of a row + * + * @param model problem object + * @param row row index + * @return row right hand side + **/ +COINLIBAPI double COINLINKAGE +Osi_getRowRHS(void *osi, int row); + +/** @brief Sense a row + * @param model problem object + * @param row row index + * @return row sense: E for =, L for <=, G for >= and R for ranged row + **/ +COINLIBAPI char COINLINKAGE +Osi_getRowSense(void *osi, int row); + +/** @brief Returns solution vector in OsiSolverInterface object */ +COINLIBAPI const double * COINLINKAGE +Osi_getColSolution( void *osi ); + + +/**@}*/ + +/** \name OsiCuts related routines (used in callbacks) */ +/**@{*/ + +/** adds a row cut (used in callback) */ +COINLIBAPI void COINLINKAGE +OsiCuts_addRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs ); + +/**@}*/ + +#ifdef __cplusplus +} +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cgl012cut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cgl012cut.hpp new file mode 100644 index 000000000..1b08cabae --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Cgl012cut.hpp @@ -0,0 +1,464 @@ +// $Id$ +// Copyright (C) 2010, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/** @file 012cut.h Include file for C coded 0-1/2 separator */ +#ifndef CGL012CUT +#define CGL012CUT +#include +#include +#include + +#define CGL_NEW_SHORT +#ifndef CGL_NEW_SHORT +typedef /* arc */ + struct arc_st +{ + int len; /* length of the arc */ + struct node_st *head; /* head node */ +} + arc; + +typedef /* node */ + struct node_st +{ + arc *first; /* first outgoing arc */ + int dist; /* tentative shortest path length */ + struct node_st *parent; /* parent pointer */ + struct node_st *next; /* next node in queue */ + struct node_st *prev; /* previous node in queue */ + int status; /* status of node */ + int temp; /* for temporary labels */ + int index; /* index of the node in the graph */ +} node; +#endif +typedef struct +{ + int length; // Length of arc + int to; // To node +} cgl_arc; + +typedef struct +{ + cgl_arc * firstArc; // First outgoing arc + int parentNode; // Parent node in shortest path + int index; // Which node I am + int distanceBack; // Distance back to source +} cgl_node; + +typedef struct +{ + int nnodes; // Number of nodes in graph + int narcs; // Number of arcs in graph + cgl_node * nodes; + cgl_arc * arcs; +} cgl_graph; +/* #define PRINT */ +/* #define PRINT_CUTS */ +#define REDUCTION + +typedef struct { +int mr; /* number of rows in the ILP matrix */ +int mc; /* number of columns in the ILP matrix */ +int mnz; /* number of nonzero's in the ILP matrix */ +int *mtbeg; /* starting position of each row in arrays mtind and mtval */ +int *mtcnt; /* number of entries of each row in arrays mtind and mtval */ +int *mtind; /* column indices of the nonzero entries of the ILP matrix */ +int *mtval; /* values of the nonzero entries of the ILP matrix */ +int *vlb; /* lower bounds on the variables */ +int *vub; /* upper bounds on the variables */ +int *mrhs; /* right hand sides of the constraints */ +char *msense; /* senses of the constraints: 'L', 'G' or 'E' */ +const double *xstar; /* current optimal solution of the LP relaxation */ +} ilp; + +typedef struct { +int mr; /* number of rows in the parity ILP matrix */ +int mc; /* number of columns in the parity ILP matrix */ +int mnz; /* number of 1's in the parity ILP matrix */ +int *mtbeg; /* starting position of each row in arrays mtind and mtval */ +int *mtcnt; /* number of entries of each row in arrays mtind and mtval */ +int *mtind; /* column indices of the 1's of the parity ILP matrix */ +short int *mrhs; /* right hand side parity of the constraints */ +double *xstar; /* current optimal solution of the LP relaxation */ +double *slack; /* slack of the constraints w.r.t. xstar */ +short int *row_to_delete; /* flag for marking rows not to be considered */ +short int *col_to_delete; /* flag for marking columns not to be considered */ +int *gcd; /* greatest common divisor of each row in the input ILP matrix */ +short int *possible_weak; /* possible weakening types of each column */ +short int *type_even_weak; /* type of even weakening of each column + (lower or upper bound weakening) */ +short int *type_odd_weak; /* type of odd weakening of each column + (lower or upper bound weakening) */ +double *loss_even_weak; /* loss for the even weakening of each column */ +double *loss_odd_weak; /* loss for the odd weakening of each column */ +double *min_loss_by_weak; /* minimum loss for the weakening of each column */ +} parity_ilp; + +typedef struct { +int nweak; /* number of variables weakened */ +int *var; /* list of variables weakened */ +short int *type; /* type of weakening (lower or upper bound weakening) */ +} info_weak; + +typedef struct { +int endpoint1, endpoint2; /* endpoints of the edge */ +double weight; /* edge weight */ +short int parity; /* edge parity (even or odd) */ +int constr; /* constraint associated with the edge */ +info_weak *weak; /* weakening information */ +} edge; + +typedef struct { +int nnodes; /* number of nodes */ +int nedges; /* number of edges */ +int *nodes; /* indexes of the ILP columns corresponding to the nodes */ +int *ind; /* indexes of the nodes corresponding to the ILP columns */ +edge **even_adj_list; /* pointers to the even edges */ +edge **odd_adj_list; /* pointers to the odd edges */ +} separation_graph; + +#ifndef CGL_NEW_SHORT +typedef struct { +int nnodes; /* number of nodes */ +int narcs; /* number of arcs */ +node *nodes; /* array of the nodes - see "types_db.h" */ +arc *arcs; /* array of the arcs - see "types_db.h" */ +} auxiliary_graph; +#else +typedef struct { +int nnodes; /* number of nodes */ +int narcs; /* number of arcs */ +cgl_node *nodes; /* array of the nodes - see "types_db.h" */ +cgl_arc *arcs; /* array of the arcs - see "types_db.h" */ +} auxiliary_graph; +#endif + +typedef struct { +long dist; /* distance from/to root */ +int pred; /* index of the predecessor */ +} short_path_node; + +typedef struct { +double weight; /* overall weight of the cycle */ +int length; /* number of edges in the cycle */ +edge **edge_list; /* list of edges in the cycle */ +} cycle; + +typedef struct { +int cnum; /* overall number of cycles */ +cycle **list; /* pointers to the cycles in the list */ +} cycle_list; + +typedef struct { +int n_of_constr; /* number of constraints combined to get the cut */ +int *constr_list; /* list of the constraints combined */ +short int *in_constr_list; /* flag saying whether a given constraint is + in the list of constraints of the cut (IN) + or not (OUT) */ +int cnzcnt; /* overall number of nonzero's in the cut */ +int *cind; /* column indices of the nonzero entries of the cut */ +int *cval; /* values of the nonzero entries of the cut */ +int crhs; /* right hand side of the cut */ +char csense; /* sense of the cut: 'L', 'G' or 'E' */ +double violation; /* violation of the cut w.r.t. the current LP solution */ +} cut; + +typedef struct { +int cnum; /* overall number of cuts */ +cut **list; /* pointers to the cuts in the list */ +} cut_list; + +typedef struct { +int n_of_constr; /* number of constraints combined to get the cut */ +int *constr_list; /* list of the constraints combined */ +int code; /* identifier of the cut */ +int n_it_violated; /* number of consecutive iterations (starting from the + last and going backward) in which the cut was + violated by the LP solution */ +int it_found; /* iteration in which the cut was separated */ +double score; /* score of the cut, used to choose wich cut should be + added to the current LP (if any) */ +} pool_cut; + +typedef struct { +int cnum; /* overall number of cuts */ +pool_cut **list; /* pointers to the cuts in the list */ +int *ncod; /* number of cuts with a given code in the pool */ +} pool_cut_list; + +typedef struct { +int *ccoef; /* coefficients of the cut */ +int crhs; /* right hand side of the cut */ +int pool_index; /* index of the cut in the pool */ +double score; /* cut score (to be maximized) */ +} select_cut; + +typedef struct { +int n_it_zero; /* number of consecutive iterations (starting from the + last and going backward) in which each variable took + the value 0 in the LP solution */ +} log_var; +/** 012Cut Generator Class + + This class is to make Cgl01cut thread safe etc +*/ + +class Cgl012Cut { + +public: + + /**@name Generate Cuts */ + //@{ +int sep_012_cut( +/* + INPUT parameters: +*/ +int mr, /* number of rows in the ILP matrix */ +int mc, /* number of columns in the ILP matrix */ +int mnz, /* number of nonzero's in the ILP matrix */ +int *mtbeg, /* starting position of each row in arrays mtind and mtval */ +int *mtcnt, /* number of entries of each row in arrays mtind and mtval */ +int *mtind, /* column indices of the nonzero entries of the ILP matrix */ +int *mtval, /* values of the nonzero entries of the ILP matrix */ +int *vlb, /* lower bounds on the variables */ +int *vub, /* upper bounds on the variables */ +int *mrhs, /* right hand sides of the constraints */ +char *msense, /* senses of the constraints: 'L', 'G' or 'E' */ +const double *xstar, /* current optimal solution of the LP relaxation */ +bool aggressive, /* flag asking whether as many cuts as possible are + required on output (TRUE) or not (FALSE) */ +/* + OUTPUT parameters (the memory for the vectors is allocated INTERNALLY + by the procedure: if some memory is already allocated, it is FREED): +*/ +int *cnum, /* number of violated 0-1/2 cuts identified by the procedure */ +int *cnzcnt, /* overall number of nonzero's in the cuts */ +int **cbeg, /* starting position of each cut in arrays cind and cval */ +int **ccnt, /* number of entries of each cut in arrays cind and cval */ +int **cind, /* column indices of the nonzero entries of the cuts */ +int **cval, /* values of the nonzero entries of the cuts */ +int **crhs, /* right hand sides of the cuts */ +char **csense /* senses of the cuts: 'L', 'G' or 'E' */ +/* + NOTE that all the numerical input/output vectors are INTEGER (with + the exception of xstar), since the procedure is intended to work + with pure ILP's, and that the ILP matrix has to be given on input + in ROW format. +*/ + ); +void ilp_load( + int mr, /* number of rows in the ILP matrix */ + int mc, /* number of columns in the ILP matrix */ + int mnz, /* number of nonzero's in the ILP matrix */ + int *mtbeg, /* starting position of each row in arrays mtind and mtval */ + int *mtcnt, /* number of entries of each row in arrays mtind and mtval */ + int *mtind, /* column indices of the nonzero entries of the ILP matrix */ + int *mtval, /* values of the nonzero entries of the ILP matrix */ + int *vlb, /* lower bounds on the variables */ + int *vub, /* upper bounds on the variables */ + int *mrhs, /* right hand sides of the constraints */ + char *msense /* senses of the constraints: 'L', 'G' or 'E' */ + ); +void free_ilp(); +/* alloc_parity_ilp: allocate the memory for the parity ILP data structure */ + +void alloc_parity_ilp( + int mr, /* number of rows in the ILP matrix */ + int mc, /* number of columns in the ILP matrix */ + int mnz /* number of nonzero's in the ILP matrix */ + ); +void free_parity_ilp(); + void initialize_log_var(); +/* free_log_var */ + void free_log_var(); +private: +/* best_weakening: find the best upper/lower bound weakening of a set + of variables */ + +int best_weakening( + int n_to_weak, /* number of variables to weaken */ +int *vars_to_weak, /* indices of the variables to weaken */ +short int original_parity, /* original parity of the constraint to weaken */ +double original_slack, /* original slack of the constraint to weaken */ +double *best_even_slack, /* best possible slack of a weakened constraint + with even right-hand-side */ +double *best_odd_slack, /* best possible slack of a weakened constraint + with odd right-hand-side */ +info_weak **info_even_weak, /* weakening information about the best possible + even weakened constraint */ +info_weak **info_odd_weak, /* weakening information about the best possible + odd weakened constraint */ +short int only_odd, /* flag which tells whether only an odd weakening is of + interest (TRUE) or both weakenings are (FALSE) */ +short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); + +/* best_cut: find the coefficients, the rhs and the violation of the + best possible cut that can be obtained by weakening a given set of + coefficients to even and a rhs to odd, dividing by 2 and rounding */ + +short int best_cut( + int *ccoef, /* vector of the coefficients */ + int *crhs, /* pointer to rhs value */ + double *violation, /* violation of the cut */ + short int update, /* TRUE/FALSE: if TRUE, the new ccoef and crhs are + given on output */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* get_cut: extract a hopefully violated cut from an odd cycle of the + separation graph */ + +cut *get_cut( + cycle *s_cyc /* shortest odd cycles identified in the separation graph */ + ); + +/* update_log_var: update the log information for the problem variables */ + void update_log_var(); + +/* basic_separation: try to identify violated 0-1/2 cuts by using the + original procedure described in Caprara and Fischetti's MP paper */ + + cut_list *basic_separation(); + +/* score_by_moving: compute the score of the best cut obtainable from + the current local search solution by inserting/deleting a constraint */ + +double score_by_moving( + int i, /* constraint to be moved */ + short int itype, /* type of move - ADD or DEL */ + double thresh /* minimum value of an interesting score */ + ); +/* modify_current: update the current local search solution by inserting/ + deleting a constraint */ + +void modify_current( + int i, /* constraint to be moved */ + short int itype /* type of move - ADD or DEL */ + ); + +/* best neighbour: find the cut to be added/deleted from the current + solution among those allowed by the tabu rules */ + + short int best_neighbour(cut_list *out_cuts /* list of the violated cuts found */); + +/* add_tight_constraint: initialize the current cut by adding a tight + constraint to it */ + + void add_tight_constraint(); + +/* tabu_012: try to identify violated 0-1/2 cuts by a simple tabu search + procedure adapted from that used by Battiti and Protasi for finding + large cliques */ + + cut_list *tabu_012(); +/* initialize: initialize the data structures for local search */ + + void initialize(); +/* restart: perform a restart of the search - IMPORTANT: in the current + implementation vector last_moved is not cleared at restart */ + + void restart(short int failure /* flag forcing the restart if some trouble occurred */); + void print_constr(int i /* constraint to be printed */); + void print_parity_ilp(); + +/* get_parity_ilp: construct an internal data structure containing all the + information which can be useful for 0-1/2 cut separation */ + + void get_parity_ilp(); +/* initialize_sep_graph: allocate and initialize the data structure + to contain the information associated with a separation graph */ + + separation_graph *initialize_sep_graph(); + void print_cut(cut *v_cut); +/* get_ori_cut_coef: get the coefficients of a cut, before dividing by 2 and + rounding, starting from the list of the constraints combined to get + the cut */ + +short int get_ori_cut_coef( + int n_of_constr, /* number of constraints combined */ + int *constr_list, /* list of the constraints combined */ + int *ccoef, /* cut left hand side coefficients */ + int *crhs, /* cut right hand side */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* define_cut: construct a cut data structure from a vector of + coefficients and a right-hand-side */ + +cut *define_cut( + int *ccoef, /* coefficients of the cut */ + int crhs /* right hand side of the cut */ + ); + +/* cut_score: define the score of a (violated) cut */ + +double cut_score( + int *ccoef, /* cut left hand side coefficients */ + int crhs, /* cut right hand side */ + double viol, /* cut violation */ + short int only_viol /* flag which tells whether only an inequality of + slack smaller than MAX_SLACK is of interest (TRUE) + otherwise (FALSE) */ + ); +/* get_current_cut: return a cut data type with the information about + the current cut of the search procedure */ + + cut *get_current_cut(); +/* print_cur_cut: display cur_cut on output */ + + void print_cur_cut(); + void print_cut_list(cut_list *cuts); + //@} +public: + /**@name Constructors and destructors */ + //@{ + /// Default constructor + Cgl012Cut (); + + /// Copy constructor + Cgl012Cut ( + const Cgl012Cut &); + + /// Assignment operator + Cgl012Cut & + operator=( + const Cgl012Cut& rhs); + + /// Destructor + virtual ~Cgl012Cut (); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + //@} + + + /**@name Private member data */ + //@{ + +ilp *inp_ilp; /* input ILP data structure */ +parity_ilp *p_ilp; /* parity ILP data structure */ +int iter; +double gap; +double maxgap; +int errorNo; +int sep_iter; /* number of the current separation iteration */ +log_var **vlog; /* information about the value attained + by the variables in the last iterations, + used to possibly set to 0 some coefficient + > 0 in a cut to be added */ +bool aggr; /* flag saying whether as many cuts as possible are required + from the separation procedure (TRUE) or not (FALSE) */ + //@} +}; +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglAllDifferent.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglAllDifferent.hpp new file mode 100644 index 000000000..ed369d1c1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglAllDifferent.hpp @@ -0,0 +1,115 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglAllDifferent_H +#define CglAllDifferent_H + +#include + +#include "CglCutGenerator.hpp" + +/** AllDifferent Cut Generator Class + This has a number of sets. All the members in each set are general integer + variables which have to be different from all others in the set. + + At present this only generates column cuts + + At present it is very primitive compared to proper CSP implementations + */ +class CglAllDifferent : public CglCutGenerator { + +public: + + + /**@name Generate Cuts */ + //@{ + /** This fixes (or reduces bounds) on sets of all different variables + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglAllDifferent (); + + /// Useful constructot + CglAllDifferent(int numberSets, const int * starts, const int * which); + + /// Copy constructor + CglAllDifferent ( + const CglAllDifferent &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglAllDifferent & + operator=( + const CglAllDifferent& rhs); + + /// Destructor + virtual + ~CglAllDifferent (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const + { return false;} + //@} + /**@name Sets and Gets */ + //@{ + /// Set log level + inline void setLogLevel(int value) + { logLevel_=value;} + /// Get log level + inline int getLogLevel() const + { return logLevel_;} + /// Set Maximum number of sets to look at at once + inline void setMaxLook(int value) + { maxLook_=value;} + /// Get Maximum number of sets to look at at once + inline int getMaxLook() const + { return maxLook_;} + //@} + +private: + + // Private member methods + /**@name */ + //@{ + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// Number of sets + int numberSets_; + /// Total number of variables in all different sets + int numberDifferent_; + /// Maximum number of sets to look at at once + int maxLook_; + /// Log level - 0 none, 1 - a bit, 2 - more details + int logLevel_; + /// Start of each set + int * start_; + /// Members (0,1,....) not as in original model + int * which_; + /// Original members + int * originalWhich_; + //@} +}; +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglClique.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglClique.hpp new file mode 100644 index 000000000..5e65e5489 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglClique.hpp @@ -0,0 +1,312 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CglClique_h_ +#define _CglClique_h_ + +#include "CglCutGenerator.hpp" + +//class OsiCuts; +//class OsiSolverInterface; + +class CglClique : public CglCutGenerator { + + friend void CglCliqueUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); +public: + /// Copy constructor + CglClique(const CglClique& rhs); + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglClique& operator=(const CglClique& rhs); + +public: + + virtual void + generateCuts(const OsiSolverInterface& si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /**@name Constructors and destructors */ + //@{ + /** Default constructor. + If the setPacking argument is set to true then CglClique will assume that the + problem in the solverinterface passed to the generateCuts() method + describes a set packing problem, i.e., + - all variables are binary + - the matrix is a 0-1 matrix + - all constraints are '= 1' or '<= 1' + + Otherwise the user can use the considerRows() method to set the list of + clique rows, that is, + - all coeffs corresponding to binary variables at fractional level is 1 + - all other coeffs are non-negative + - the constraint is '= 1' or '<= 1'. + + If the user does not set the list of clique rows then CglClique will + start the generateCuts() methods by scanning the matrix for them. + Also justOriginalRows can be set to true to limit clique creation + */ + CglClique(bool setPacking = false, bool justOriginalRows = false); + /// Destructor + virtual ~CglClique() {} + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + void considerRows(const int numRows, const int* rowInd); + +public: + /** possible choices for selecting the next node in the star clique search + */ + enum scl_next_node_method { + SCL_MIN_DEGREE, + SCL_MAX_DEGREE, + SCL_MAX_XJ_MAX_DEG + }; + + void setStarCliqueNextNodeMethod(scl_next_node_method method) { + scl_next_node_rule = method; + } + + void setStarCliqueCandidateLengthThreshold(int maxlen) { + scl_candidate_length_threshold = maxlen; + } + void setRowCliqueCandidateLengthThreshold(int maxlen) { + rcl_candidate_length_threshold = maxlen; + } + + void setStarCliqueReport(bool yesno = true) { scl_report_result = yesno; } + void setRowCliqueReport(bool yesno = true) { rcl_report_result = yesno; } + + void setDoStarClique(bool yesno = true) { do_star_clique = yesno; } + void setDoRowClique(bool yesno = true) { do_row_clique = yesno; } + + void setMinViolation(double minviol) { petol = minviol; } + double getMinViolation() const { return petol; } + /// Maximum number of binaries for looking at all + inline void setMaxNumber(int value) { maxNumber_ = value; } + +private: + + struct frac_graph ; + friend struct frac_graph ; + + /** A node of the fractional graph. There is a node for every variable at + fractional level. */ + struct fnode { + /** pointer into all_nbr */ + int *nbrs; + /** 1-x_i-x_j, needed for odd holes, in the same order as the adj list, + pointer into all_edgecost */ + double *edgecosts; + /** degree of the node */ + int degree; + /** the fractional value of the variable corresponding to this node */ + double val; + }; + + /** A graph corresponding to a fractional solution of an LP. Two nodes are + adjacent iff their columns are non-orthogonal. */ + struct frac_graph { + /** # of nodes = # of fractional values in the LP solution */ + int nodenum; + /** # of edges in the graph */ + int edgenum; + /** density= edgenum/(nodenum choose 2) */ + double density; + int min_deg_node; + int min_degree; + int max_deg_node; + int max_degree; + /** The array of the nodes in the graph */ + fnode *nodes; + /** The array of all the neighbors. First the indices of the nodes + adjacent to node 0 are listed, then those adjacent to node 1, etc. */ + int *all_nbr; + /** The array of the costs of the edges going to the neighbors */ + double *all_edgecost; + + frac_graph() : + nodenum(0), edgenum(0), density(0), + min_deg_node(0), min_degree(0), max_deg_node(0), max_degree(0), + nodes(0), all_nbr(0), all_edgecost(0) {} + }; + +protected: + /** An indicator showing whether the whole matrix in the solverinterface is + a set packing problem or not */ + bool setPacking_; + /// True if just look at original rows + bool justOriginalRows_; + /** pieces of the set packing part of the solverinterface */ + int sp_numrows; + int* sp_orig_row_ind; + int sp_numcols; + int* sp_orig_col_ind; + double* sp_colsol; + int* sp_col_start; + int* sp_col_ind; + int* sp_row_start; + int* sp_row_ind; + + /** the intersection graph corresponding to the set packing problem */ + frac_graph fgraph; + /** the node-node incidence matrix of the intersection graph. */ + bool* node_node; + + /** The primal tolerance in the solverinterface. */ + double petol; + /// Maximum number of binaries for looking at all + int maxNumber_; + + /** data for the star clique algorithm */ + + /** Parameters */ + /**@{*/ + /** whether to do the row clique algorithm or not. */ + bool do_row_clique; + /** whether to do the star clique algorithm or not. */ + bool do_star_clique; + + /** How the next node to be added to the star clique should be selected */ + scl_next_node_method scl_next_node_rule; + /** In the star clique method the maximal length of the candidate list + (those nodes that are in a star, i.e., connected to the center of the + star) to allow complete enumeration of maximal cliques. Otherwise a + greedy algorithm is used. */ + int scl_candidate_length_threshold; + /** whether to give a detailed statistics on the star clique method */ + bool scl_report_result; + + /** In the row clique method the maximal length of the candidate list + (those nodes that can extend the row clique, i.e., connected to all + nodes in the row clique) to allow complete enumeration of maximal + cliques. Otherwise a greedy algorithm is used. */ + int rcl_candidate_length_threshold; + /** whether to give a detailed statistics on the row clique method */ + bool rcl_report_result; + /**@}*/ + + /** variables/arrays that are used across many methods */ + /**@{*/ + /** List of indices that must be in the to be created clique. This is just + a pointer, it is never new'd and therefore does not need to be + delete[]'d either. */ + const int* cl_perm_indices; + /** The length of cl_perm_indices */ + int cl_perm_length; + + /** List of indices that should be considered for extending the ones listed + in cl_perm_indices. */ + int* cl_indices; + /** The length of cl_indices */ + int cl_length; + + /** An array of nodes discarded from the candidate list. These are + rechecked when a maximal clique is found just to make sure that the + clique is really maximal. */ + int* cl_del_indices; + /** The length of cl_del_indices */ + int cl_del_length; + + /**@}*/ + +private: + /** Scan through the variables and select those that are binary and are at + a fractional level. */ + void selectFractionalBinaries(const OsiSolverInterface& si); + /** Scan through the variables and select those that are at a fractional + level. We already know that everything is binary. */ + void selectFractionals(const OsiSolverInterface& si); + /** */ + void selectRowCliques(const OsiSolverInterface& si,int numOriginalRows); + /** */ + void createSetPackingSubMatrix(const OsiSolverInterface& si); + /** */ + void createFractionalGraph(); + /** */ + int createNodeNode(); + /** */ + void deleteSetPackingSubMatrix(); + /** */ + void deleteFractionalGraph(); + /** */ + void find_scl(OsiCuts& cs); + /** */ + void find_rcl(OsiCuts& cs); + /** */ + int scl_choose_next_node(const int current_nodenum, + const int *current_indices, + const int *current_degrees, + const double *current_values); + /** */ + void scl_delete_node(const int del_ind, int& current_nodenum, + int *current_indices, int *current_degrees, + double *current_values); + /** */ + int enumerate_maximal_cliques(int& pos, bool* scl_label, OsiCuts& cs); + /** */ + int greedy_maximal_clique(OsiCuts& cs); + /** */ + void recordClique(const int len, int* indices, OsiCuts& cs); +}; +//############################################################################# +/** A function that tests the methods in the CglClique class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglCliqueUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +/// This works on a fake solver i.e. invented rows +class CglProbing; +class CglFakeClique : public CglClique { + +public: + /// Copy constructor + CglFakeClique(const CglFakeClique& rhs); + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglFakeClique& operator=(const CglFakeClique& rhs); + + virtual void + generateCuts(const OsiSolverInterface& si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /**@name Constructors and destructors */ + //@{ + /** Default constructor. + If the setPacking argument is set to true then CglFakeClique will assume that the + problem in the solverinterface passed to the generateCuts() method + describes a set packing problem, i.e., + - all variables are binary + - the matrix is a 0-1 matrix + - all constraints are '= 1' or '<= 1' + + Otherwise the user can use the considerRows() method to set the list of + clique rows, that is, + - all coeffs corresponding to binary variables at fractional level is 1 + - all other coeffs are non-negative + - the constraint is '= 1' or '<= 1'. + + If the user does not set the list of clique rows then CglFakeClique will + start the generateCuts() methods by scanning the matrix for them. + */ + CglFakeClique(OsiSolverInterface * solver=NULL,bool setPacking = false); + /// Destructor + virtual ~CglFakeClique(); + /// Assign solver (generator takes over ownership) + void assignSolver(OsiSolverInterface * fakeSolver); +protected: + /// fake solver to use + OsiSolverInterface * fakeSolver_; + /// Probing object + CglProbing * probing_; +}; + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglConfig.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglConfig.h new file mode 100644 index 000000000..7f2605b51 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglConfig.h @@ -0,0 +1,19 @@ +/* src/config_cgl.h. Generated by configure. */ +/* src/config_cgl.h.in. */ + +#ifndef __CONFIG_CGL_H__ +#define __CONFIG_CGL_H__ + +/* Version number of project */ +#define CGL_VERSION "0.60" + +/* Major Version number of project */ +#define CGL_VERSION_MAJOR 0 + +/* Minor Version number of project */ +#define CGL_VERSION_MINOR 60 + +/* Release Version number of project */ +#define CGL_VERSION_RELEASE 9999 + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglCutGenerator.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglCutGenerator.hpp new file mode 100644 index 000000000..61ff27c16 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglCutGenerator.hpp @@ -0,0 +1,133 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglCutGenerator_H +#define CglCutGenerator_H + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" +#include "CglTreeInfo.hpp" + +//------------------------------------------------------------------- +// +// Abstract base class for generating cuts. +// +//------------------------------------------------------------------- +/// +/** Cut Generator Base Class + +This is an abstract base class for generating cuts. A specific cut +generator will inherit from this class. +*/ +class CglCutGenerator { + +public: + /**@name Generate Cuts */ + //@{ + /** Generate cuts for the model data contained in si. + The generated cuts are inserted into and returned in the + collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, + const CglTreeInfo info = CglTreeInfo()) + = 0; + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglCutGenerator(); + + /// Copy constructor + CglCutGenerator(const CglCutGenerator &); + + /// Clone + virtual CglCutGenerator *clone() const = 0; + + /// Assignment operator + CglCutGenerator &operator=(const CglCutGenerator &rhs); + + /// Destructor + virtual ~CglCutGenerator(); + + /** Create C++ lines to set the generator in the current state. + The output must be parsed by the calling code, as each line + starts with a key indicating the following:
+ 0: must be kept (for #includes etc)
+ 3: Set to changed (not default) values
+ 4: Set to default values (redundant)
+ + Keys 1, 2, 5, 6, 7, 8 are defined, but not applicable to + cut generators. + */ + virtual std::string generateCpp(FILE *) { return ""; } + + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface *) {} + //@} + + /**@name Gets and Sets */ + //@{ + /** + Get Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + inline int getAggressiveness() const + { + return aggressive_; + } + + /** + Set Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + inline void setAggressiveness(int value) + { + aggressive_ = value; + } + /// Set whether can do global cuts + inline void setGlobalCuts(bool trueOrFalse) + { + canDoGlobalCuts_ = trueOrFalse; + } + /// Say whether can do global cuts + inline bool canDoGlobalCuts() const + { + return canDoGlobalCuts_; + } + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const; + /// Return true if needs optimal basis to do cuts + virtual bool needsOptimalBasis() const; + /// Return maximum length of cut in tree + virtual int maximumLengthOfCutInTree() const + { + return COIN_INT_MAX; + } + //@} + + // test this class + //static void unitTest(); + + // private: + + /** + Aggressiveness - 0 = neutral, 100 is normal root node. + Really just a hint to cut generator + */ + int aggressive_; + /// True if can do global cuts i.e. no general integers + bool canDoGlobalCuts_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglDuplicateRow.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglDuplicateRow.hpp new file mode 100644 index 000000000..1a2c9b30b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglDuplicateRow.hpp @@ -0,0 +1,189 @@ +// $Id$ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglDuplicateRow_H +#define CglDuplicateRow_H + +#include + +#include "CglCutGenerator.hpp" +class CglStored; + +/** DuplicateRow Cut Generator Class */ +class CglDuplicateRow : public CglCutGenerator { + +public: + + + /**@name Generate Cuts */ + //@{ + /** Fix variables and find duplicate/dominated rows for the model of the + solver interface, si. + + This is a very simple minded idea but I (JJF) am using it in a project so thought + I might as well add it. It should really be called before first solve and I may + modify CBC to allow for that. + + This is designed for problems with few rows and many integer variables where the rhs + are <= or == and all coefficients and rhs are small integers. + + If effective rhs is K then we can fix all variables with coefficients > K to their lower bounds + (effective rhs just means original with variables with nonzero lower bounds subtracted out). + + If one row is a subset of another and the effective rhs are same we can fix some variables + and then the two rows are identical. + + The generator marks identical rows so can be taken out in solve + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); +private: + /// Does work for modes 1,2 + void generateCuts12( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Does work for mode 4 + void generateCuts4( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Does work for mode 8 + void generateCuts8( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); +public: + /** Fix variables and find duplicate/dominated rows for the model of the + solver interface, si. + + This is a very simple minded idea but I (JJF) am using it in a project so thought + I might as well add it. It should really be called before first solve and I may + modify CBC to allow for that. + + This is designed for problems with few rows and many integer variables where the rhs + are <= or == and all coefficients and rhs are small integers. + + If effective rhs is K then we can fix all variables with coefficients > K to their lower bounds + (effective rhs just means original with variables with nonzero lower bounds subtracted out). + + If one row is a subset of another and the effective rhs are same we can fix some variables + and then the two rows are identical. + + This version does deletions and fixings and may return stored cuts for + dominated columns + */ + CglStored * outDuplicates( OsiSolverInterface * solver); + + //@} + + /**@name Get information on size of problem */ + //@{ + /// Get duplicate row list, -1 means still in, -2 means out (all fixed), k>= means same as row k + inline const int * duplicate() const + { return duplicate_;} + /// Size of dynamic program + inline int sizeDynamic() const + { return sizeDynamic_;} + /// Number of rows in original problem + inline int numberOriginalRows() const + { return matrix_.getNumRows();} + //@} + + /**@name Get information on size of problem */ + //@{ + /// logLevel + inline int logLevel() const + { return logLevel_;} + inline void setLogLevel(int value) + { logLevel_ = value;} + //@} + + + /**@name We only check for duplicates amongst rows with effective rhs <= this */ + //@{ + /// Get + inline int maximumRhs() const + { return maximumRhs_;} + /// Set + inline void setMaximumRhs(int value) + { maximumRhs_=value;} + //@} + + /**@name We only check for dominated amongst groups of columns whose size <= this */ + //@{ + /// Get + inline int maximumDominated() const + { return maximumDominated_;} + /// Set + inline void setMaximumDominated(int value) + { maximumDominated_=value;} + //@} + /**@name gets and sets */ + //@{ + /// Get mode + inline int mode() const + { return mode_;} + /// Set mode + inline void setMode(int value) + { mode_=value;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglDuplicateRow (); + + /// Useful constructor + CglDuplicateRow (OsiSolverInterface * solver); + + /// Copy constructor + CglDuplicateRow ( + const CglDuplicateRow & rhs); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglDuplicateRow & + operator=( + const CglDuplicateRow& rhs); + + /// Destructor + virtual + ~CglDuplicateRow (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +protected: + + + // Protected member data + + /**@name Protected member data */ + //@{ + /// Matrix + CoinPackedMatrix matrix_; + /// Matrix by row + CoinPackedMatrix matrixByRow_; + /// Possible rhs (if 0 then not possible) + int * rhs_; + /// Marks duplicate rows + int * duplicate_; + /// To allow for <= rows + int * lower_; + /// Stored cuts if we found dominance cuts + CglStored * storedCuts_; + /// Check dominated columns if less than this number of candidates + int maximumDominated_; + /// Check duplicates if effective rhs <= this + int maximumRhs_; + /// Size of dynamic program + int sizeDynamic_; + /// 1 do rows, 2 do columns, 3 do both + int mode_; + /// Controls print out + int logLevel_; + //@} +}; +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglFlowCover.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglFlowCover.hpp new file mode 100644 index 000000000..afdf513cb --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglFlowCover.hpp @@ -0,0 +1,371 @@ +// $Id$ +//----------------------------------------------------------------------------- +// name: Cgl Lifted Simple Generalized Flow Cover Cut Generator +// author: Yan Xu email: yan.xu@sas.com +// Jeff Linderoth email: jtl3@lehigh.edu +// Martin Savelsberg email: martin.savelsbergh@isye.gatech.edu +// date: 05/01/2003 +// comments: please scan this file for '???' and read the comments +//----------------------------------------------------------------------------- +// Copyright (C) 2003, Yan Xu, Jeff Linderoth, Martin Savelsberg and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglFlowCover_H +#define CglFlowCover_H + +#include + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +//============================================================================= + +/** This enumerative constant describes the various col types.*/ +enum CglFlowColType { + /** The column(variable) is a negative binary variable.*/ + CGLFLOW_COL_BINNEG = -2, + /** The column is a negative continous variable.*/ + CGLFLOW_COL_CONTNEG, + /** The column is a positive continous variable.*/ + CGLFLOW_COL_CONTPOS = 1, + /** The column is a positive binary variable.*/ + CGLFLOW_COL_BINPOS +}; + +enum CglFlowColStatus{ +}; + +/** This enumerative constant describes the various stati of vars in + a cut or not.*/ +enum CglFlowColCut{ + /** The column is NOT in cover.*/ + CGLFLOW_COL_OUTCUT = 0, + /** The column is in cover now. */ + CGLFLOW_COL_INCUT, + /** The column is decided to be in cover. */ + CGLFLOW_COL_INCUTDONE, + /** The column is in L-. */ + CGLFLOW_COL_INLMIN, + /** The column is decided to be in L-. */ + CGLFLOW_COL_INLMINDONE, + /** The column is in L--.*/ + CGLFLOW_COL_INLMINMIN, + /** This enumerative constant describes the various stati of vars in + determining the cover.*/ + /** The column is a prime candidate. */ + CGLFLOW_COL_PRIME, + /** The column is a secondary candidate. */ + CGLFLOW_COL_SECONDARY +}; + +/** This enumerative constant describes the various row types.*/ +enum CglFlowRowType { + /** The row type of this row is NOT defined yet.*/ + CGLFLOW_ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is continous, and the RHS + is zero.*/ + CGLFLOW_ROW_VARUB, + /** After the row is flipped to 'L', the row has exactlytwo variables: + one is positive binary and the other is continous, and the RHS + is zero.*/ + CGLFLOW_ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + CGLFLOW_ROW_VAREQ, + /** Rows can not be classfied into other types and the row sense + is NOT 'E'.*/ + CGLFLOW_ROW_MIXUB, + /** Rows can not be classfied into other types and the row sense is 'E'.*/ + CGLFLOW_ROW_MIXEQ, + /** All variables are NOT binary and the row sense is NOT 'E'. */ + CGLFLOW_ROW_NOBINUB, + /** All variables are NOT binary and the row sense is 'E'. */ + CGLFLOW_ROW_NOBINEQ, + /** The row has one binary and 2 or more other types of variables and + the row sense is NOT 'E'. */ + CGLFLOW_ROW_SUMVARUB, + /** The row has one binary and 2 or more other types of variables and + the row sense is 'E'. */ + CGLFLOW_ROW_SUMVAREQ, + /** All variables are binary. */ + CGLFLOW_ROW_UNINTERSTED +}; + +//============================================================================= + +/** Variable upper bound class. */ +class CglFlowVUB +{ +protected: + int varInd_; /** The index of the associated 0-1 variable.*/ + double upper_; /** The Value of the associated upper bound.*/ + +public: + CglFlowVUB() : varInd_(-1), upper_(-1) {} + + CglFlowVUB(const CglFlowVUB& source) { + varInd_= source.varInd_; + upper_ = source.upper_; + } + + CglFlowVUB& operator=(const CglFlowVUB& rhs) { + if (this == &rhs) + return *this; + varInd_= rhs.varInd_; + upper_ = rhs.upper_; + return *this; + } + + /**@name Query and set functions for associated 0-1 variable index + and value. + */ + //@{ + inline int getVar() const { return varInd_; } + inline double getVal() const { return upper_; } + inline void setVar(const int v) { varInd_ = v; } + inline void setVal(const double v) { upper_ = v; } + //@} +}; + +//============================================================================= + +/** Variable lower bound class, which is the same as vub. */ +typedef CglFlowVUB CglFlowVLB; + +/** Overloaded operator<< for printing VUB and VLB.*/ +std::ostream& operator<<( std::ostream& os, const CglFlowVUB &v ); + +//============================================================================= + +/** + * Lifed Simple Generalized Flow Cover Cut Generator Class. + */ +class CglFlowCover : public CglCutGenerator { + friend void CglFlowCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /** + * Do the following tasks: + *
    + *
  • classify row types + *
  • indentify vubs and vlbs + *
+ * This function is called by + * generateCuts(const OsiSolverInterface & si, OsiCuts & cs). + */ + void flowPreprocess(const OsiSolverInterface& si); + + /**@name Generate Cuts */ + //@{ + /** Generate Lifed Simple Generalized flow cover cuts for the model data + contained in si. The generated cuts are inserted into and returned + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Functions to query and set maximum number of cuts can be + generated. */ + //@{ + inline int getMaxNumCuts() const { return maxNumCuts_; } + inline void setMaxNumCuts(int mc) { maxNumCuts_ = mc; } + //@} + + /**@name Functions to query and set the number of cuts have been + generated. */ + //@{ + inline int getNumFlowCuts() { return numFlowCuts_; } + inline void setNumFlowCuts(int fc) { numFlowCuts_ = fc; } + inline void incNumFlowCuts(int fc = 1) { numFlowCuts_ += fc; } + //@} + + //------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglFlowCover (); + + /// Copy constructor + CglFlowCover ( + const CglFlowCover &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglFlowCover & + operator=( + const CglFlowCover& rhs); + + /// Destructor + virtual + ~CglFlowCover (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + //------------------------------------------------------------------------- + // Private member functions + + /** Based a given row, a LP solution and other model data, this function + tries to generate a violated lifted simple generalized flow cover. + */ + bool generateOneFlowCut( const OsiSolverInterface & si, + const int rowLen, + int* ind, + double* coef, + char sense, + double rhs, + OsiRowCut& flowCut, + double& violation ); + + + /** Transform a row from ">=" to "<=", and vice versa. */ + void flipRow(int rowLen, double* coef, double& rhs) const; + + /** Transform a row from ">=" to "<=", and vice versa. Have 'sense'. */ + void flipRow(int rowLen, double* coef, char& sen, double& rhs) const; + + /** Determine the type of a given row. */ + CglFlowRowType determineOneRowType(const OsiSolverInterface& si, + int rowLen, int* ind, + double* coef, char sen, + double rhs) const; + /** Lift functions */ + void liftMinus(double &movement, /* Output */ + int t, + int r, + double z, + double dPrimePrime, + double lambda, + double ml, + double *M, + double *rho) const; + + bool liftPlus(double &alpha, + double &beta, + int r, + double m_j, + double lambda, + double y_j, + double x_j, + double dPrimePrime, + double *M) const; + + + //------------------------------------------------------------------------- + //**@name Query and set the row type of a givne row. */ + //@{ + inline const CglFlowRowType* getRowTypes() const + { return rowTypes_; } + inline CglFlowRowType getRowType(const int i) const + { return rowTypes_[i]; } + /** Set rowtypes, take over the ownership. */ + inline void setRowTypes(CglFlowRowType* rt) + { rowTypes_ = rt; rt = 0; } + inline void setRowTypes(const CglFlowRowType rt, const int i) { + if (rowTypes_ != 0) + rowTypes_[i] = rt; + else { + std::cout << "ERROR: Should allocate memory for rowType_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for rowType_", + "setRowType", "CglFlowCover"); + } + } + //@} + + //------------------------------------------------------------------------- + //**@name Query and set vubs. */ + //@{ + inline const CglFlowVUB* getVubs() const { return vubs_; } + inline const CglFlowVUB& getVubs(int i) const { return vubs_[i]; } + /** Set CglFlowVUBs,take over the ownership. */ + inline void setVubs(CglFlowVUB* vubs) { vubs_ = vubs; vubs = 0; } + inline void setVubs(const CglFlowVUB& vub, int i) { + if (vubs_ != 0) + vubs_[i] = vub; + else { + std::cout << "ERROR: Should allocate memory for vubs_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for vubs_", "setVubs", + "CglFlowCover"); + } + } + inline void printVubs(std::ostream& os) const { + for (int i = 0; i < numCols_; ++i) { + os << "ix: " << i << ", " << vubs_[i]; + } + } + //@} + + //------------------------------------------------------------------------- + //**@name Query and set vlbs. */ + //@{ + inline const CglFlowVLB* getVlbs() const { return vlbs_; } + inline const CglFlowVLB& getVlbs(int i) const { return vlbs_[i]; } + /** Set CglFlowVLBs,take over the ownership. */ + inline void setVlbs(CglFlowVLB* vlbs) { vlbs_ = vlbs; vlbs = 0; } + inline void setVlbs(const CglFlowVLB& vlb, int i) { + if (vlbs_ != 0) + vlbs_[i] = vlb; + else { + std::cout << "ERROR: Should allocate memory for vlbs_ before " + << "using it " << std::endl; + throw CoinError("Forgot to allocate memory for vlbs_", "setVlbs", + "CglFlowCover"); + } + } + //@} + +private: + //------------------------------------------------------------------------ + // Private member data + + /** The maximum number of flow cuts to be generated. Default is 1000. */ + int maxNumCuts_; + /** Tolerance used for numerical purpose. */ + double EPSILON_; + /** The variable upper bound of a flow is not indentified yet.*/ + int UNDEFINED_; + /** Very large number. */ + double INFTY_; + /** If violation of a cut is greater that this number, the cut is useful.*/ + double TOLERANCE_; + /** First time preprocessing */ + bool firstProcess_; + /** The number rows of the problem.*/ + int numRows_; + /** The number columns of the problem.*/ + int numCols_; + /** The number flow cuts found.*/ + int numFlowCuts_; + /** Indicate whether initial flow preprecessing has been done. */ + bool doneInitPre_; + /** The array of CglFlowVUBs. */ + CglFlowVUB* vubs_; + /** The array of CglFlowVLBs. */ + CglFlowVLB* vlbs_; + /** CglFlowRowType of the rows in model. */ + CglFlowRowType* rowTypes_; +}; + +//############################################################################# +/** A function that tests the methods in the CglFlowCover class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglFlowCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMI.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMI.hpp new file mode 100644 index 000000000..3e205b354 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMI.hpp @@ -0,0 +1,364 @@ +// Last edit: 02/05/2013 +// +// Name: CglGMI.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design, Singapore +// email: nannicini@sutd.edu.sg +// Date: 11/17/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2009, Giacomo Nannicini. All Rights Reserved. + +#ifndef CglGMI_H +#define CglGMI_H + +#include "CglCutGenerator.hpp" +#include "CglGMIParam.hpp" +#include "CoinWarmStartBasis.hpp" +#include "CoinFactorization.hpp" + +/* Enable tracking of rejection of cutting planes. If this is disabled, + the cut generator is slightly faster. If defined, it enables proper use + of setTrackRejection and related functions. */ +//#define TRACK_REJECT + +/* Debug output */ +//#define GMI_TRACE + +/* Debug output: print optimal tableau */ +//#define GMI_TRACETAB + +/* Print reason for cut rejection, whenever a cut is discarded */ +//#define GMI_TRACE_CLEAN + +/** Gomory cut generator with several cleaning procedures, used to test + * the numerical safety of the resulting cuts + */ + +class CglGMI : public CglCutGenerator { + + friend void CglGMIUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + + /** Public enum: all possible reasons for cut rejection */ + enum RejectionType{ + failureFractionality, + failureDynamism, + failureViolation, + failureSupport, + failureScale + }; + + /**@name generateCuts */ + //@{ + /** Generate Gomory Mixed-Integer cuts for the model of the solver + interface si. + + Insert the generated cuts into OsiCuts cs. + + Warning: This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau and + optimal basis inverse and makes assumptions on the way slack variables + are added by the solver. The Osi implementations for Clp and Cplex + verify these assumptions. + + When calling the generator, the solver interface si must contain + an optimized problem and information related to the optimal + basis must be available through the OsiSolverInterface methods + (si->optimalBasisIsAvailable() must return 'true'). It is also + essential that the integrality of structural variable i can be + obtained using si->isInteger(i). + + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const { return true; } + //@} + + /**@name Common Methods */ + //@{ + // Function for checking equality with user tolerance + inline bool areEqual(double x, double y, + double epsAbs = 1e-12, + double epsRel = 1e-12) { + return (fabs((x) - (y)) <= + std::max(epsAbs, epsRel * std::max(fabs(x), fabs(y)))); + } + + // Function for checking is a number is zero + inline bool isZero(double x, double epsZero = 1e-20) { + return (fabs(x) <= epsZero); + } + + + // Function for checking if a number is integer + inline bool isIntegerValue(double x, + double intEpsAbs = 1e-9, + double intEpsRel = 1e-15) { + return (fabs((x) - floor((x)+0.5)) <= + std::max(intEpsAbs, intEpsRel * fabs(x))); + } + + + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglGMIParam object. + void setParam(const CglGMIParam &source); + // Return the CglGMIParam object of the generator. + inline CglGMIParam getParam() const {return param;} + inline CglGMIParam & getParam() {return param;} + + // Compute entries of is_integer. + void computeIsInteger(); + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + /// Set/get tracking of the rejection of cutting planes. + /// Note that all rejection related functions will not do anything + /// unless the generator is compiled with the define GMI_TRACK_REJECTION + void setTrackRejection(bool value); + bool getTrackRejection(); + + /// Get number of cuts rejected for given reason; see above + int getNumberRejectedCuts(RejectionType reason); + + /// Reset counters for cut rejection tracking; see above + void resetRejectionCounters(); + + /// Get total number of generated cuts since last resetRejectionCounters() + int getNumberGeneratedCuts(); + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglGMI(); + + /// Constructor with specified parameters + CglGMI(const CglGMIParam ¶m); + + /// Copy constructor + CglGMI(const CglGMI &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglGMI & operator=(const CglGMI& rhs); + + /// Destructor + virtual ~CglGMI(); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglGMI members are properly set. + void generateCuts(OsiCuts & cs); + + /// Compute the fractional part of value, allowing for small error. + inline double aboveInteger(double value) const; + + /// Compute the fractionalities involved in the cut, and the cut rhs. + /// Returns true if cut is accepted, false if discarded + inline bool computeCutFractionality(double varRhs, double& cutRhs); + + /// Compute the cut coefficient on a given variable + inline double computeCutCoefficient(double rowElem, int index); + + /// Use multiples of the initial inequalities to cancel out the coefficient + /// on a slack variables. + inline void eliminateSlack(double cutElem, int cutIndex, double* cut, + double& cutRhs, const double *elements, + const CoinBigIndex *rowStart, const int *indices, + const int *rowLength, const double *rhs); + + /// Change the sign of the coefficients of the non basic + /// variables at their upper bound. + inline void flip(double& rowElem, int rowIndex); + + /// Change the sign of the coefficients of the non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. Two functions: one for original variables, one for slacks. + inline void unflipOrig(double& rowElem, int rowIndex, double& rowRhs); + inline void unflipSlack(double& rowElem, int rowIndex, double& rowRhs, + const double* slack_val); + + /// Pack a row of ncol elements + inline void packRow(double* row, double* rowElem, int* rowIndex, + int& rowNz); + + /// Clean the cutting plane; the cleaning procedure does several things + /// like removing small coefficients, scaling, and checks several + /// acceptance criteria. If this returns false, the cut should be discarded. + /// There are several cleaning procedures available, that can be selected + /// via the parameter param.setCLEANING_PROCEDURE(int value) + bool cleanCut(double* cutElem, int* cutIndex, int& cutNz, + double& cutRhs, const double* xbar); + + /// Cut cleaning procedures: return true if successfull, false if + /// cut should be discarded by the caller of if problems encountered + + /// Check the violation + bool checkViolation(const double* cutElem, const int* cutIndex, + int cutNz, double cutrhs, const double* xbar); + + /// Check the dynamism + bool checkDynamism(const double* cutElem, const int* cutIndex, + int cutNz); + + /// Check the support + bool checkSupport(int cutNz); + + /// Remove small coefficients and adjust the rhs accordingly + bool removeSmallCoefficients(double* cutElem, int* cutIndex, + int& cutNz, double& cutRhs); + + /// Adjust the rhs by relaxing by a small amount (relative or absolute) + void relaxRhs(double& rhs); + + /// Scale the cutting plane in different ways; + /// scaling_type possible values: + /// 0 : scale to obtain integral cut + /// 1 : scale based on norm, to obtain cut norm equal to ncol + /// 2 : scale to obtain largest coefficient equal to 1 + bool scaleCut(double* cutElem, int* cutIndex, int cutNz, + double& cutRhs, int scalingType); + + /// Scale the cutting plane in order to generate integral coefficients + bool scaleCutIntegral(double* cutElem, int* cutIndex, int cutNz, + double& cutRhs); + + /// Compute the nearest rational number; used by scale_row_integral + bool nearestRational(double val, double maxdelta, long maxdnom, + long& numerator, long& denominator); + + /// Compute the greatest common divisor + long computeGcd(long a, long b); + + /// print a vector of integers + void printvecINT(const char *vecstr, const int *x, int n) const; + /// print a vector of doubles: dense form + void printvecDBL(const char *vecstr, const double *x, int n) const; + /// print a vector of doubles: sparse form + void printvecDBL(const char *vecstr, const double *elem, const int * index, + int nz) const; + + /// Recompute the simplex tableau for want of a better accuracy. + /// Requires an empty CoinFactorization object to do the computations, + /// and two empty (already allocated) arrays which will contain + /// the basis indices on exit. Returns 0 if successfull. + int factorize(CoinFactorization & factorization, + int* colBasisIndex, int* rowBasisIndex); + + + //@} + + + // Private member data + +/**@name Private member data */ + + //@{ + + /// Object with CglGMIParam members. + CglGMIParam param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + bool *isInteger; + + /// Current basis status: columns + int *cstat; + + /// Current basis status: rows + int *rstat; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + /// Pointer on matrix of coefficient ordered by columns. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byCol; + + /// Fractionality of the cut and related quantities. + double f0; + double f0compl; + double ratiof0compl; + +#if defined(TRACK_REJECT) || defined (TRACK_REJECT_SIMPLE) + /// Should we track the reason of each cut rejection? + bool trackRejection; + /// Number of failures by type + int fracFail; + int dynFail; + int violFail; + int suppFail; + int smallCoeffFail; + int scaleFail; + /// Total number of generated cuts + int numGeneratedCuts; +#endif + + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglGMI class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglGMIUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMIParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMIParam.hpp new file mode 100644 index 000000000..a1aae4173 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGMIParam.hpp @@ -0,0 +1,313 @@ +// Name: CglGMIParam.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// email: nannicini@sutd.edu.sg +// based on CglRedSplitParam.hpp by Francois Margot +// Date: 11/17/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2009, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglGMIParam_H +#define CglGMIParam_H + +#include "CglParam.hpp" + + + /**@name CglGMI Parameters */ + //@{ + + /** Class collecting parameters for the GMI cut generator. + + Parameters of the generator are listed below. Modifying the default + values for parameters other than the last four might result in + invalid cuts. + + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - USE_INTSLACKS: Use integer slacks to generate cuts. + (not implemented yet, will be in the future). + See method setUSE_INTSLACKS(). + - AWAY: Look only at basic integer variables whose current value is at + least this value away from being integer. See method setAway(). + - CHECK_DUPLICATES: Should we check for duplicates when adding a cut + to the collection? Can be slow. + Default 0 - do not check, add cuts anyway. + - CLEAN_PROC: Cleaning procedure that should be used. Look below at the + enumeration CleaningProcedure for possible values. + - INTEGRAL_SCALE_CONT: If we try to scale cut coefficients so that + they become integral, do we also scale on + continuous variables? + Default 0 - do not scale continuous vars. + Used only if CLEAN_PROC does integral scaling. + - ENFORCE_SCALING: Discard badly scaled cuts, or keep them (unscaled). + Default 1 - yes. + + */ + //@} + +class CglGMIParam : public CglParam { + +public: + + /**@name Enumerations */ + enum CleaningProcedure{ + /* CglLandP procedure I */ + CP_CGLLANDP1, + /* CglLandP procedure II */ + CP_CGLLANDP2, + /* CglRedSplit procedure I */ + CP_CGLREDSPLIT, + /* Only integral cuts, i.e. cuts with integral coefficients */ + CP_INTEGRAL_CUTS, + /* CglLandP procedure I with integral scaling */ + CP_CGLLANDP1_INT, + /* CglLandP procedure I with scaling of the max element to 1 if possible */ + CP_CGLLANDP1_SCALEMAX, + /* CglLandP procedure I with scaling of the rhs to 1 if possible */ + CP_CGLLANDP1_SCALERHS + }; + + /**@name Set/get methods */ + + //@{ + /** Aliases for parameter get/set method in the base class CglParam */ + + /** Value for Infinity. Default: DBL_MAX */ + inline void setInfinity(double value) {setINFINIT(value);} + inline double getInfinity() const {return INFINIT;} + + /** Epsilon for comparing numbers. Default: 1.0e-6 */ + inline void setEps(double value) {setEPS(value);} + inline double getEps() const {return EPS;} + + /** Epsilon for zeroing out coefficients. Default: 1.0e-5 */ + inline void setEpsCoeff(double value) {setEPS_COEFF(value);} + inline double getEpsCoeff() const {return EPS_COEFF;} + + /** Maximum support of the cutting planes. Default: INT_MAX */ + inline void setMaxSupport(int value) {setMAX_SUPPORT(value);} + inline int getMaxSupport() const {return MAX_SUPPORT;} + /** Alias for consistency with our naming scheme */ + inline void setMaxSupportAbs(int value) {setMAX_SUPPORT(value);} + inline int getMaxSupportAbs() const {return MAX_SUPPORT;} + inline int getMAX_SUPPORT_ABS() const {return MAX_SUPPORT;} + + /** Set AWAY, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.005 */ + virtual void setAway(double value); + /** Get value of away */ + inline double getAway() const {return AWAY;} + /// Aliases + inline void setAWAY(double value) {setAway(value);} + inline double getAWAY() const {return AWAY;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 0 */ + virtual void setEPS_ELIM(double value); + /** Get the value of EPS_ELIM */ + inline double getEPS_ELIM() const {return EPS_ELIM;} + /// Aliases + inline void setEpsElim(double value) {setEPS_ELIM(value);} + inline double getEpsElim() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(double value); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + /// Aliases + inline void setEpsRelaxAbs(double value) {setEPS_RELAX_ABS(value);} + inline double getEpsRelaxAbs() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(double value); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + /// Aliases + inline void setEpsRelaxRel(double value) {setEPS_RELAX_REL(value);} + inline double getEpsRelaxRel() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN;} + /// Aliases + inline void setMaxDyn(double value) {setMAXDYN(value);} + inline double getMaxDyn() const {return MAXDYN;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-7 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + /// Aliases + inline void setMinViol(double value) {setMINVIOL(value);} + inline double getMinViol() const {return MINVIOL;} + + /** Set the value of MAX_SUPPORT_REL, the factor contributing to the + maximum support relative to the number of columns. Maximum + allowed support is: MAX_SUPPORT_ABS + + MAX_SUPPORT_REL*ncols. Default: 0.1 */ + virtual void setMAX_SUPPORT_REL(double value); + /** Get the value of MINVIOL */ + inline double getMAX_SUPPORT_REL() const {return MAX_SUPPORT_REL;} + /// Aliases + inline void setMaxSupportRel(double value) {setMAX_SUPPORT_REL(value);} + inline double getMaxSupportRel() const {return MAX_SUPPORT_REL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(bool value); + /** Get the value of USE_INTSLACKS */ + inline bool getUSE_INTSLACKS() const {return USE_INTSLACKS;} + /// Aliases + inline void setUseIntSlacks(bool value) {setUSE_INTSLACKS(value);} + inline int getUseIntSlacks() const {return USE_INTSLACKS;} + + /** Set the value of CHECK_DUPLICATES. Default: 0 */ + virtual void setCHECK_DUPLICATES(bool value); + /** Get the value of CHECK_DUPLICATES */ + inline bool getCHECK_DUPLICATES() const {return CHECK_DUPLICATES;} + /// Aliases + inline void setCheckDuplicates(bool value) {setCHECK_DUPLICATES(value);} + inline bool getCheckDuplicates() const {return CHECK_DUPLICATES;} + + /** Set the value of CLEAN_PROC. Default: CP_CGLLANDP1 */ + virtual void setCLEAN_PROC(CleaningProcedure value); + /** Get the value of CLEAN_PROC. */ + inline CleaningProcedure getCLEAN_PROC() const {return CLEAN_PROC;} + /// Aliases + inline void setCleanProc(CleaningProcedure value) {setCLEAN_PROC(value);} + inline CleaningProcedure getCleaningProcedure() const {return CLEAN_PROC;} + + /** Set the value of INTEGRAL_SCALE_CONT. Default: 0 */ + virtual void setINTEGRAL_SCALE_CONT(bool value); + /** Get the value of INTEGRAL_SCALE_CONT. */ + inline bool getINTEGRAL_SCALE_CONT() const {return INTEGRAL_SCALE_CONT;} + /// Aliases + inline void setIntegralScaleCont(bool value) {setINTEGRAL_SCALE_CONT(value);} + inline bool getIntegralScaleCont() const {return INTEGRAL_SCALE_CONT;} + + /** Set the value of ENFORCE_SCALING. Default: 1 */ + virtual void setENFORCE_SCALING(bool value); + /** Get the value of ENFORCE_SCALING. */ + inline bool getENFORCE_SCALING() const {return ENFORCE_SCALING;} + /// Aliases + inline void setEnforceScaling(bool value) {setENFORCE_SCALING(value);} + inline bool getEnforcescaling() const {return ENFORCE_SCALING;} + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglGMIParam(double eps = 1e-12, + double away = 0.005, + double eps_coeff = 1e-11, + double eps_elim = 0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-4, + int max_supp_abs = 1000, + double max_supp_rel = 0.1, + CleaningProcedure clean_proc = CP_CGLLANDP1, + bool use_int_slacks = false, + bool check_duplicates = false, + bool integral_scale_cont = false, + bool enforce_scaling = true); + + /// Constructor from CglParam + CglGMIParam(CglParam &source, + double away = 0.005, + double eps_elim = 1e-12, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-4, + double max_supp_rel = 0.1, + CleaningProcedure clean_proc = CP_CGLLANDP1, + bool use_int_slacks = false, + bool check_duplicates = false, + bool integral_scale_cont = false, + bool enforce_scaling = true); + + /// Copy constructor + CglGMIParam(const CglGMIParam &source); + + /// Clone + virtual CglGMIParam* clone() const; + + /// Assignment operator + virtual CglGMIParam& operator=(const CglGMIParam &rhs); + + /// Destructor + virtual ~CglGMIParam(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Use row only if pivot variable should be integer but is more + than AWAY from being integer. */ + double AWAY; + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 0. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-11 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 1.e-13 */ + double EPS_RELAX_REL; + + /** Maximum ratio between largest and smallest non zero + coefficients in a cut. Default: 1e6. */ + double MAXDYN; + + /** Minimum violation for the current basic solution in a generated cut. + Default: 1e-4. */ + double MINVIOL; + + /** Maximum support relative to number of columns. Must be between 0 + and 1. Default: 0. */ + double MAX_SUPPORT_REL; + + /** Which cleaning procedure should be used? */ + CleaningProcedure CLEAN_PROC; + + /** Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. */ + bool USE_INTSLACKS; + + /** Check for duplicates when adding the cut to the collection? */ + bool CHECK_DUPLICATES; + + /** Should we try to rescale cut coefficients on continuous variables + so that they become integral, or do we only rescale coefficients + on integral variables? Used only by cleaning procedure that try + the integral scaling. */ + bool INTEGRAL_SCALE_CONT; + + /** Should we discard badly scaled cuts (according to the scaling + procedure in use)? If false, CglGMI::scaleCut always returns + true, even though it still scales cuts whenever possible, but + not cut is rejected for scaling. Default true. Used only by + cleaning procedure that try to scale. */ + bool ENFORCE_SCALING; + + //@} +}; + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGomory.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGomory.hpp new file mode 100644 index 000000000..c9d3c8933 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglGomory.hpp @@ -0,0 +1,204 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglGomory_H +#define CglGomory_H + +#include + +#include "CglCutGenerator.hpp" + +class CoinWarmStartBasis; +/** Gomory Cut Generator Class */ +class CglGomory : public CglCutGenerator { + friend void CglGomoryUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Gomory cuts for the model of the + solver interface, si. + + Insert the generated cuts into OsiCut, cs. + + There is a limit option, which will only generate cuts with + less than this number of entries. + + We can also only look at 0-1 variables a certain distance + from integer. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /** Generates cuts given matrix and solution etc, + returns number of cuts generated */ + int generateCuts( const OsiRowCutDebugger * debugger, + OsiCuts & cs, + const CoinPackedMatrix & columnCopy, + const CoinPackedMatrix & rowCopy, + const double * colsol, + const double * colLower, const double * colUpper, + const double * rowLower, const double * rowUpper, + const char * intVar , + const CoinWarmStartBasis* warm, + const CglTreeInfo info = CglTreeInfo()); + /** Generates cuts given matrix and solution etc, + returns number of cuts generated (no row copy passed in) */ + int generateCuts( const OsiRowCutDebugger * debugger, + OsiCuts & cs, + const CoinPackedMatrix & columnCopy, + const double * colsol, + const double * colLower, const double * colUpper, + const double * rowLower, const double * rowUpper, + const char * intVar , + const CoinWarmStartBasis* warm, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const { return true; } + //@} + + /**@name Change way Gomory works */ + //@{ + /// Pass in a copy of original solver (clone it) + void passInOriginalSolver(OsiSolverInterface * solver); + /// Returns original solver + inline OsiSolverInterface * originalSolver() const + { return originalSolver_;} + /// Set type - 0 normal, 1 add original matrix one, 2 replace + inline void setGomoryType(int type) + { gomoryType_=type;} + /// Return type + inline int gomoryType() const + { return gomoryType_;} + //@} + + /**@name Change limit on how many variables in cut (default 50) */ + //@{ + /// Set + void setLimit(int limit); + /// Get + int getLimit() const; + /// Set at root (if + +#include "CglCutGenerator.hpp" +#include "CglTreeInfo.hpp" + +/** Knapsack Cover Cut Generator Class */ +class CglKnapsackCover : public CglCutGenerator { + friend void CglKnapsackCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + /** A method to set which rows should be tested for knapsack covers */ + void setTestedRowIndices(int num, const int* ind); + + /**@name Generate Cuts */ + //@{ + /** Generate knapsack cover cuts for the model of the solver interface, si. + Insert the generated cuts into OsiCut, cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglKnapsackCover (); + + /// Copy constructor + CglKnapsackCover ( + const CglKnapsackCover &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglKnapsackCover & + operator=( + const CglKnapsackCover& rhs); + + /// Destructor + virtual + ~CglKnapsackCover (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + + + /**@name Sets and gets */ + //@{ + /// Set limit on number in knapsack + inline void setMaxInKnapsack(int value) + { if (value>0) maxInKnapsack_ = value;} + /// get limit on number in knapsack + inline int getMaxInKnapsack() const + {return maxInKnapsack_;} + /// Switch off expensive cuts + inline void switchOffExpensive() + { expensiveCuts_=false;} + /// Switch on expensive cuts + inline void switchOnExpensive() + { expensiveCuts_=true;} +private: + + // Private member methods + + + /**@name Private methods */ + //@{ + + /** deriveAKnapsack + returns 1 if it is able to derive + a (canonical) knapsack inequality + in binary variables of the form ax<=b + from the rowIndex-th row in the model, + returns 0 otherwise. + */ + int deriveAKnapsack( + const OsiSolverInterface & si, + OsiCuts & cs, + CoinPackedVector & krow, + bool treatAsLRow, + double & b, + int * complement, + double * xstar, + int rowIndex, + int numberElements, + const int * index, + const double * element); + + int deriveAKnapsack( + const OsiSolverInterface & si, + OsiCuts & cs, + CoinPackedVector & krow, + double & b, + int * complement, + double * xstar, + int rowIndex, + const CoinPackedVectorBase & matrixRow); + + /** Find a violated minimal cover from + a canonical form knapsack inequality by + solving the -most- violated cover problem + and postprocess to ensure minimality + */ + int findExactMostViolatedMinCover( + int nCols, + int row, + CoinPackedVector & krow, + double b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + + /** Find the most violate minimum cover by solving the lp-relaxation of the + most-violate-min-cover problem + */ + int findLPMostViolatedMinCover( + int nCols, + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + +/// find a minimum cover by a simple greedy approach + int findGreedyCover( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder + ); + + /// lift the cover inequality + int liftCoverCut( + double & b, + int nRowElem, + CoinPackedVector & cover, + CoinPackedVector & remainder, + CoinPackedVector & cut ); + + /// sequence-independent lift and uncomplement and add the resulting cut to the cut set + int liftAndUncomplementAndAdd( + double rowub, + CoinPackedVector & krow, + double & b, + int * complement, + int row, + CoinPackedVector & cover, + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// sequence-dependent lift, uncomplement and add the resulting cut to the cut set +void seqLiftAndUncomplementAndAdd( + int nCols, + double * xstar, + int * complement, + int row, + int nRowElem, + double & b, + CoinPackedVector & cover, // need not be violated + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// sequence-dependent lift binary variables either up or down, uncomplement and add to the cut set +void liftUpDownAndUncomplementAndAdd( + int nCols, + double * xstar, + int * complement, + int row, + int nRowElem, + double & b, + + // the following 3 packed vectors partition the krow: + CoinPackedVector & fracCover, // vars have frac soln values in lp relaxation + // and form cover with the vars atOne + CoinPackedVector & atOne, // vars have soln value of 1 in lp relaxation + // and together with fracCover form minimal (?) cover. + CoinPackedVector & remainder, + OsiCuts & cs ); + + /// find a cover using a variation of the logic found in OSL (w/o SOS) + int findPseudoJohnAndEllisCover ( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & cover, + CoinPackedVector & remainder); + + /// find a cover using the basic logic found in OSL (w/o SOS) + int findJohnAndEllisCover ( + int row, + CoinPackedVector & krow, + double & b, + double * xstar, + CoinPackedVector & fracCover, + CoinPackedVector & atOnes, + CoinPackedVector & remainder); + + + /** A C-style implementation of the Horowitz-Sahni exact solution + procedure for solving knapsack problem. + + (ToDo: implement the more efficient dynamic programming approach) + + (Reference: Martello and Toth, Knapsack Problems, Wiley, 1990, p30.) + */ + int exactSolveKnapsack( + int n, + double c, + double const *pp, + double const *ww, + double & z, + int * x); + /// For testing gub stuff + int gubifyCut(CoinPackedVector & cut); +public: + /** Creates cliques for use by probing. + Only cliques >= minimumSize and < maximumSize created + Can also try and extend cliques as a result of probing (root node). + Returns number of cliques found. + */ + int createCliques( OsiSolverInterface & si, + int minimumSize=2, int maximumSize=100, bool extendCliques=false); +private: + /// Delete all clique information + void deleteCliques(); + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// epsilon + double epsilon_; + /// Tolerance to use for violation - bigger than epsilon_ + double epsilon2_; + /// 1-epsilon + double onetol_; + /// Maximum in knapsack + int maxInKnapsack_; + /** which rows to look at. If specified, only these rows will be considered + for generating knapsack covers. Otherwise all rows will be tried */ + int numRowsToCheck_; + int* rowsToCheck_; + /// exactKnapsack can be expensive - this switches off some + bool expensiveCuts_; + /// Cliques + /// **** TEMP so can reference from listing + const OsiSolverInterface * solver_; + int whichRow_; + int * complement_; + double * elements_; + /// Number of cliques + int numberCliques_; + /// Clique type + typedef struct { + unsigned int equality:1; // nonzero if clique is == + } CliqueType; + CliqueType * cliqueType_; + /// Start of each clique + int * cliqueStart_; + /// Entries for clique + CliqueEntry * cliqueEntry_; + /** Start of oneFixes cliques for a column in matrix or -1 if not + in any clique */ + int * oneFixStart_; + /** Start of zeroFixes cliques for a column in matrix or -1 if not + in any clique */ + int * zeroFixStart_; + /// End of fixes for a column + int * endFixStart_; + /// Clique numbers for one or zero fixes + int * whichClique_; + /// Number of columns + int numberColumns_; + /** For each column with nonzero in row copy this gives a clique "number". + So first clique mentioned in row is always 0. If no entries for row + then no cliques. If sequence > numberColumns then not in clique. + */ + //CliqueEntry * cliqueRow_; + /// cliqueRow_ starts for each row + //int * cliqueRowStart_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglKnapsackCover class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglKnapsackCoverUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandP.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandP.hpp new file mode 100644 index 000000000..cd5cffff4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandP.hpp @@ -0,0 +1,306 @@ +// Copyright (C) 2005-2009, Pierre Bonami and others. All Rights Reserved. +// Author: Pierre Bonami +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// Date: 07/21/05 +// +// $Id$ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//--------------------------------------------------------------------------- +#ifndef CglLandP_H +#define CglLandP_H + +#include "CglLandPValidator.hpp" +#include "CglCutGenerator.hpp" +#include "CglParam.hpp" + +#include +class CoinWarmStartBasis; +/** Performs one round of Lift & Project using CglLandPSimplex + to build cuts +*/ + +namespace LAP +{ +enum LapMessagesTypes +{ + BEGIN_ROUND, + END_ROUND, + DURING_SEP, + CUT_REJECTED, + CUT_FAILED, + CUT_GAP, + LAP_CUT_FAILED_DO_MIG, + LAP_MESSAGES_DUMMY_END +}; +/** Output messages for Cgl */ +class LapMessages : public CoinMessages +{ +public: + /** Constructor */ + LapMessages( ); + /** destructor.*/ + virtual ~LapMessages() {} +}; +class CglLandPSimplex; +} + +class CglLandP : public CglCutGenerator +{ + friend void CglLandPUnitTest(OsiSolverInterface *si, const std::string & mpsDir); + + friend class LAP::CglLandPSimplex; + friend class CftCglp; + +public: + + enum SelectionRules + { + mostNegativeRc /** select most negative reduced cost */, + bestPivot /** select best possible pivot.*/, + initialReducedCosts/** Select only those rows which had initialy a 0 reduced cost.*/ + }; + + enum ExtraCutsMode + { + none/** Generate no extra cuts.*/, + AtOptimalBasis /** Generate cuts from the optimal basis.*/, + WhenEnteringBasis /** Generate cuts as soon as a structural enters the basis.*/, + AllViolatedMigs/** Generate all violated Mixed integer Gomory cuts in the course of the optimization.*/ + }; + + /** Space where cuts are optimized.*/ + enum SeparationSpaces + { + Fractional=0 /** True fractional space.*/, + Fractional_rc/** Use fractional space only for computing reduced costs.*/, + Full /** Work in full space.*/ + }; + + /** Normalization */ + enum Normalization + { + Unweighted = 0, + WeightRHS, + WeightLHS, + WeightBoth + }; + + enum LHSnorm + { + L1 = 0, + L2, + SupportSize, + Infinity, + Average, + Uniform + }; + /** RHS weight in normalization.*/ + enum RhsWeightType + { + Fixed = 0 /** 2*initial number of constraints. */, + Dynamic /** 2 * current number of constraints. */ + }; + /** Class storing parameters. + \remark I take all parameters from Ionut's code */ + class Parameters : public CglParam + { + public: + /** Default constructor (with default values)*/ + Parameters(); + /** Copy constructor */ + Parameters(const Parameters &other); + /** Assignment opertator */ + Parameters & operator=(const Parameters &other); + /// @name integer parameters + ///@{ + + /** Max number of pivots before we generate the cut + \default 20 */ + int pivotLimit; + /** Max number of pivots at regular nodes. Put a value if you want it lower than the global pivot limit. + \default 100.*/ + int pivotLimitInTree; + /** Maximum number of cuts generated at a given round*/ + int maxCutPerRound; + /** Maximum number of failed pivots before aborting */ + int failedPivotLimit; + /** maximum number of consecutive degenerate pivots + \default 0 */ + int degeneratePivotLimit; + /** Maximum number of extra rows to generate per round.*/ + int extraCutsLimit; + ///@} + /// @name double parameters + ///@{ + /** Tolerance for small pivots values (should be the same as the solver */ + double pivotTol; + /** A variable have to be at least away from integrity to be generated */ + double away; + /** Total time limit for cut generation.*/ + double timeLimit; + /** Time limit for generating a single cut.*/ + double singleCutTimeLimit; + /** Weight to put in RHS of normalization if static.*/ + double rhsWeight; + ///@} + + /// @name Flags + ///@{ + /** Do we use tableau row or the disjunction (I don't really get that there should be a way to always use the tableau)*/ + bool useTableauRow; + /** Do we apply Egon Balas's Heuristic for modularized cuts */ + bool modularize; + /** Do we strengthen the final cut (always do if modularize is 1) */ + bool strengthen; + /** Wether to limit or not the number of mistaken RC (when perturbation is applied).*/ + bool countMistakenRc; + /** Work in the reduced space (only non-structurals enter the basis) */ + SeparationSpaces sepSpace; + /** Apply perturbation procedure. */ + bool perturb; + /** How to weight normalization.*/ + Normalization normalization; + /** How to weight RHS of normalization.*/ + RhsWeightType rhsWeightType; + /** How to weight LHS of normalization.*/ + LHSnorm lhs_norm; + /** Generate extra constraints from optimal lift-and-project basis.*/ + ExtraCutsMode generateExtraCuts; + /** Which rule to apply for choosing entering and leaving variables.*/ + SelectionRules pivotSelection; + ///@} + }; + + + /** Constructor for the class*/ + CglLandP(const CglLandP::Parameters ¶ms = CglLandP::Parameters(), + const LAP::Validator &validator = LAP::Validator()); + /** Destructor */ + ~CglLandP(); + /** Copy constructor */ + CglLandP(const CglLandP &source); + /** Assignment operator */ + CglLandP& operator=(const CglLandP &rhs); + /** Clone function */ + CglCutGenerator * clone() const; + + /**@name Generate Cuts */ + //@{ + + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + //@} + + virtual bool needsOptimalBasis() const + { + return true; + } + + LAP::Validator & validator() + { + return validator_; + } + /** set level of log for cut generation procedure : +
    +
  1. for none
  2. +
  3. for log at begin and end of procedure + at some time interval
  4. +
  5. for log at every cut generated
  6. +
+ */ + void setLogLevel(int level) + { + handler_->setLogLevel(level); + } + + class NoBasisError : public CoinError + { + public: + NoBasisError(): CoinError("No basis available","LandP","") {} + }; + + class SimplexInterfaceError : public CoinError + { + public: + SimplexInterfaceError(): CoinError("Invalid conversion to simplex interface", "CglLandP","CglLandP") {} + }; + Parameters & parameter() + { + return params_; + } +private: + + + void scanExtraCuts(OsiCuts& cs, const double * colsol) const; + + Parameters params_; + + /** Some informations that will be changed by the pivots and that we want to keep*/ + struct CachedData + { + CachedData(int nBasics = 0 , int nNonBasics = 0); + CachedData(const CachedData & source); + + CachedData& operator=(const CachedData &source); + /** Get the data from a problem */ + void getData(const OsiSolverInterface &si); + + void clean(); + + ~CachedData(); + /** Indices of basic variables in starting basis (ordered if variable basics_[i] s basic in row i)*/ + int * basics_; + /** Indices of non-basic variables */ + int *nonBasics_; + /** number of basics variables */ + int nBasics_; + /** number of non-basics */ + int nNonBasics_; + /** Optimal basis */ + CoinWarmStartBasis * basis_; + /** Stores the value of the solution to cut */ + double * colsol_; + /** Stores the values of the slacks */ + double * slacks_; + /** Stores wheter slacks are integer constrained */ + bool * integers_; + /** Solver before pivots */ + OsiSolverInterface * solver_; + }; + /** Retrieve sorted integer variables which are fractional in the solution. + Return the number of variables.*/ + int getSortedFractionals(CoinPackedVector &xFrac, + const CachedData & data, + const CglLandP::Parameters& params) const; + /** Retrieve sorted integer variables which are fractional in the solution. + Return the number of variables.*/ + void getSortedFractionalIndices(std::vector& indices, + const CachedData &data, + const CglLandP::Parameters & params) const; + /** Cached informations about problem.*/ + CachedData cached_; + /** message handler */ + CoinMessageHandler * handler_; + /** messages */ + CoinMessages messages_; + /** cut validator */ + LAP::Validator validator_; + /** number of rows in the original problems. */ + int numrows_; + /** number of columns in the original problems. */ + int numcols_; + /** Original lower bounds for the problem (for lifting cuts).*/ + double * originalColLower_; + /** Original upper bounds for the problem (for lifting cuts).*/ + double * originalColUpper_; + /** Flag to say if cuts can be lifted.*/ + bool canLift_; + /** Store some extra cut which could be cheaply generated but do not cut current incumbent.*/ + OsiCuts extraCuts_; +}; +void CglLandPUnitTest(OsiSolverInterface *si, const std::string & mpsDir); + +#endif + diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandPValidator.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandPValidator.hpp new file mode 100644 index 000000000..69fb7e281 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLandPValidator.hpp @@ -0,0 +1,130 @@ +// Copyright (C) 2005-2009, Pierre Bonami and others. All Rights Reserved. +// Author: Pierre Bonami +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// Date: 11/22/05 +// +// $Id$ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//--------------------------------------------------------------------------- + +#ifndef CglLandPValidator_H +#define CglLandPValidator_H +#include "OsiSolverInterface.hpp" +#include "CglParam.hpp" +#include + +/** constants describing rejection codes*/ +//[5] = {"Accepted", "violation too small", "small coefficient too small", "big dynamic","too dense"} + + +namespace LAP +{ + +/** Class to validate or reject a cut */ +class Validator +{ +public: + /** Reasons for rejecting a cut */ + enum RejectionsReasons + { + NoneAccepted=0 /**Cut was accepted*/, + SmallViolation /** Violation of the cut is too small */, + SmallCoefficient /** There is a small coefficient we can not get rid off.*/, + BigDynamic /** Dynamic of coefficinet is too important. */, + DenseCut/**cut is too dense */, + EmptyCut/**After cleaning cut has become empty*/, + DummyEnd/** dummy*/ + }; + + /** Constructor with default values */ + Validator(double maxFillIn = 1., + double maxRatio = 1e8, + double minViolation = 0, + bool scale = false, + double rhsScale = 1); + + /** Clean an OsiCut */ + int cleanCut(OsiRowCut & aCut, const double * solCut,const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper); + /** Clean an OsiCut by another method */ + int cleanCut2(OsiRowCut & aCut, const double * solCut, const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper); + /** Call the cut cleaner */ + int operator()(OsiRowCut & aCut, const double * solCut,const OsiSolverInterface &si, const CglParam & par, + const double * colLower, const double * colUpper) + { + return cleanCut(aCut, solCut, si, par, colLower, colUpper); + } + /** @name set functions */ + /** @{ */ + void setMaxFillIn(double value) + { + maxFillIn_ = value; + } + void setMaxRatio(double value) + { + maxRatio_ = value; + } + void setMinViolation(double value) + { + minViolation_ = value; + } + + void setRhsScale(double v) + { + rhsScale_ = v; + } + /** @} */ + /** @name get functions */ + /** @{ */ + double getMaxFillIn() + { + return maxFillIn_; + } + double getMaxRatio() + { + return maxRatio_; + } + double getMinViolation() + { + return minViolation_; + } + /** @} */ + + const char* failureString(RejectionsReasons code) const + { + return rejections_[static_cast (code)]; + } + const char* failureString(int code) const + { + return rejections_[ code]; + } + int numRejected(RejectionsReasons code)const + { + return numRejected_[static_cast (code)]; + } + int numRejected(int code)const + { + return numRejected_[ code]; + } +private: + /** max percentage of given formulation fillIn should be accepted for cut fillin.*/ + double maxFillIn_; + /** max ratio between smallest and biggest coefficient */ + double maxRatio_; + /** minimum violation for accepting a cut */ + double minViolation_; + /** Do we do scaling? */ + //bool scale_; + /** Scale of right-hand-side.*/ + double rhsScale_; + /** Strings explaining reason for rejections */ + static const char* rejections_[DummyEnd]; + /** Number of cut rejected for each of the reasons.*/ + std::vector numRejected_; +}; + +}/* Ends namespace LAP.*/ +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLiftAndProject.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLiftAndProject.hpp new file mode 100644 index 000000000..364ba5a01 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglLiftAndProject.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglLiftAndProject_H +#define CglLiftAndProject_H + +#include + +#include "CglCutGenerator.hpp" + +/** Lift And Project Cut Generator Class */ +class CglLiftAndProject : public CglCutGenerator { + friend void CglLiftAndProjectUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + /**@name Generate Cuts */ + //@{ + /** Generate lift-and-project cuts for the + model of the solver interface, si. + Insert the generated cuts into OsiCut, cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /** Get the normalization : Either beta=+1 or beta=-1. + */ + + double getBeta() const { + return beta_; + } + + /** Set the normalization : Either beta=+1 or beta=-1. + Default value is 1. + */ + void setBeta(int oneOrMinusOne){ + if (oneOrMinusOne==1 || oneOrMinusOne==-1){ + beta_= static_cast(oneOrMinusOne); + } + else { + throw CoinError("Unallowable value. Beta must be 1 or -1", + "cutGeneration","CglLiftAndProject"); + } + } + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglLiftAndProject (); + + /// Copy constructor + CglLiftAndProject ( + const CglLiftAndProject &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglLiftAndProject & + operator=( + const CglLiftAndProject& rhs); + + /// Destructor + virtual + ~CglLiftAndProject (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// The normalization is beta_=1 or beta_=-1 + double beta_; + /// epsilon + double epsilon_; + /// 1-epsilon + double onetol_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglLiftAndProject class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglLiftAndProjectUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMessage.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMessage.hpp new file mode 100644 index 000000000..3b43e46a5 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMessage.hpp @@ -0,0 +1,49 @@ +// $Id$ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglMessage_H +#define CglMessage_H + +#include "CoinPragma.hpp" + +// This deals with Cgl messages (as against Osi messages etc) + +#include "CoinMessageHandler.hpp" +enum CGL_Message { + CGL_INFEASIBLE, + CGL_CLIQUES, + CGL_FIXED, + CGL_PROCESS_STATS, + CGL_SLACKS, + CGL_PROCESS_STATS2, + CGL_PROCESS_SOS1, + CGL_PROCESS_SOS2, + CGL_UNBOUNDED, + CGL_ELEMENTS_CHANGED1, + CGL_ELEMENTS_CHANGED2, + CGL_MADE_INTEGER, + CGL_ADDED_INTEGERS, + CGL_POST_INFEASIBLE, + CGL_POST_CHANGED, + CGL_GENERAL, + CGL_DUMMY_END +}; + +/** This deals with Cgl messages (as against Osi messages etc) + */ +class CglMessage : public CoinMessages { + +public: + /**@name Constructors etc */ + //@{ + /** Constructor */ + CglMessage(Language language = us_en); + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding.hpp new file mode 100644 index 000000000..1abba2ec8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding.hpp @@ -0,0 +1,429 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// name: Mixed Integer Rounding Cut Generator +// authors: Joao Goncalves (jog7@lehigh.edu) +// Laszlo Ladanyi (ladanyi@us.ibm.com) +// date: August 11, 2004 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglMixedIntegerRounding_H +#define CglMixedIntegerRounding_H + +#include +#include +//#include + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + +// Class to store variable upper bounds (VUB) +class CglMixIntRoundVUB +{ + // Variable upper bounds have the form x_j <= a y_j, where x_j is + // a continuous variable and y_j is an integer variable + +protected: + int var_; // The index of y_j + double val_; // The value of a + +public: + // Default constructor + CglMixIntRoundVUB() : var_(-1), val_(-1) {} + + // Copy constructor + CglMixIntRoundVUB(const CglMixIntRoundVUB& source) { + var_ = source.var_; + val_ = source.val_; + } + + // Assignment operator + CglMixIntRoundVUB& operator=(const CglMixIntRoundVUB& rhs) { + if (this != &rhs) { + var_ = rhs.var_; + val_ = rhs.val_; + } + return *this; + } + + // Destructor + ~CglMixIntRoundVUB() {} + + // Query and set functions + int getVar() const { return var_; } + double getVal() const { return val_; } + void setVar(const int v) { var_ = v; } + void setVal(const double v) { val_ = v; } +}; + +//============================================================================= + +// Class to store variable lower bounds (VLB). +// It is the same as the class to store variable upper bounds +typedef CglMixIntRoundVUB CglMixIntRoundVLB; + +//============================================================================= + +/** Mixed Integer Rounding Cut Generator Class */ + +// Reference: +// Hugues Marchand and Laurence A. Wolsey +// Aggregation and Mixed Integer Rounding to Solve MIPs +// Operations Research, 49(3), May-June 2001. +// Also published as CORE Dicusion Paper 9839, June 1998. + +class CglMixedIntegerRounding : public CglCutGenerator { + + friend void CglMixedIntegerRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + // The row type of this row is NOT defined yet. + ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARUB, + /** After the row is flipped to 'L', the row has exactly two variables: + one is positive binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + ROW_VAREQ, + // The row contains continuous and integer variables; + // the total number of variables is at least 2 + ROW_MIX, + // The row contains only continuous variables + ROW_CONT, + // The row contains only integer variables + ROW_INT, + // The row contains other types of rows + ROW_OTHER + }; + + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Rounding cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglMixedIntegerRounding (); + + /// Alternate Constructor + CglMixedIntegerRounding (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc = -1); + + /// Copy constructor + CglMixedIntegerRounding ( + const CglMixedIntegerRounding &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglMixedIntegerRounding & + operator=( + const CglMixedIntegerRounding& rhs); + + /// Destructor + virtual + ~CglMixedIntegerRounding (); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + + //--------------------------------------------------------------------------- + /**@name Set and get methods */ + //@{ + /// Set MAXAGGR_ + inline void setMAXAGGR_ (int maxaggr) { + if (maxaggr > 0) { + MAXAGGR_ = maxaggr; + } + else { + throw CoinError("Unallowable value. maxaggr must be > 0", + "gutsOfConstruct","CglMixedIntegerRounding"); + } + } + + /// Get MAXAGGR_ + inline int getMAXAGGR_ () const { return MAXAGGR_; } + + /// Set MULTIPLY_ + inline void setMULTIPLY_ (bool multiply) { MULTIPLY_ = multiply; } + + /// Get MULTIPLY_ + inline bool getMULTIPLY_ () const { return MULTIPLY_; } + + /// Set CRITERION_ + inline void setCRITERION_ (int criterion) { + if ((criterion >= 1) && (criterion <= 3)) { + CRITERION_ = criterion; + } + else { + throw CoinError("Unallowable value. criterion must be 1, 2 or 3", + "gutsOfConstruct","CglMixedIntegerRounding"); + } + } + + /// Get CRITERION_ + inline int getCRITERION_ () const { return CRITERION_; } + + + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + + //@} + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglMixedIntegerRounding& rhs); + + // Do preprocessing. + // It determines the type of each row. It also identifies the variable + // upper bounds and variable lower bounds. + // It may change sense and RHS for ranged rows + void mixIntRoundPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs) const; + + // Generate MIR cuts + void generateMirCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + const double* coefByRow, + const int* colInds, + const CoinBigIndex* rowStarts, + const int* rowLengths, + //const CoinPackedMatrix& matrixByCol, + const double* coefByCol, + const int* rowInds, + const CoinBigIndex* colStarts, + const int* colLengths, + OsiCuts& cs ) const; + + // Copy row selected to CoinPackedVector + void copyRowSelected( const int iAggregate, + const int rowSelected, + std::set& setRowsAggregated, + int* listRowsAggregated, + double* xlpExtra, + const char sen, + const double rhs, + const double lhs, + const CoinPackedMatrix& matrixByRow, + CoinPackedVector& rowToAggregate, + double& rhsToAggregate) const; + + // Select a row to aggregate + bool selectRowToAggregate( const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double* colUpperBound, + const double* colLowerBound, + const std::set& setRowsAggregated, + const double* xlp, const double* coefByCol, + const int* rowInds, const CoinBigIndex* colStarts, + const int* colLengths, + int& rowSelected, + int& colSelected ) const; + + // Aggregation heuristic. + // Combines one or more rows of the original matrix + void aggregateRow( const int colSelected, + CoinPackedVector& rowToAggregate, double rhs, + CoinPackedVector& rowAggregated, + double& rhsAggregated ) const; + + // Choose the bound substitution based on the criteria defined by the user + inline bool isLowerSubst(const double inf, + const double aj, + const double xlp, + const double LB, + const double UB) const; + + // Bound substitution heuristic + bool boundSubstitution( const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double* xlp, + const double* xlpExtra, + const double* colUpperBound, + const double* colLowerBound, + CoinPackedVector& mixedKnapsack, + double& rhsMixedKnapsack, double& sStar, + CoinPackedVector& contVariablesInS ) const; + + // c-MIR separation heuristic + bool cMirSeparation ( const OsiSolverInterface& si, + const CoinPackedMatrix& matrixByRow, + const CoinPackedVector& rowAggregated, + const int* listRowsAggregated, + const char* sense, const double* RHS, + //const double* coefByRow, + //const int* colInds, const int* rowStarts, + //const int* rowLengths, + const double* xlp, const double sStar, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedVector& mixedKnapsack, + const double& rhsMixedKnapsack, + const CoinPackedVector& contVariablesInS, + OsiRowCut& flowCut ) const; + + // function to create one c-MIR inequality + void cMirInequality( const int numInt, + const double delta, + const double numeratorBeta, + const int *knapsackIndices, + const double* knapsackElements, + const double* xlp, + const double sStar, + const double* colUpperBound, + const std::set& setC, + CoinPackedVector& cMIR, + double& rhscMIR, + double& sCoef, + double& violation) const; + + // function to compute G + inline double functionG( const double d, const double f ) const; + + // function to print statistics (used only in debug mode) + void printStats( + std::ofstream & fout, + const bool hasCut, + const OsiSolverInterface& si, + const CoinPackedVector& rowAggregated, + const double& rhsAggregated, const double* xlp, + const double* xlpExtra, + const int* listRowsAggregated, + const int* listColsSelected, + const int level, + const double* colUpperBound, + const double* colLowerBound ) const; + + +private: + //--------------------------------------------------------------------------- + // Private member data + + // Maximum number of rows to aggregate + int MAXAGGR_; + // Flag that indicates if an aggregated row is also multiplied by -1 + bool MULTIPLY_; + // The criterion to use in the bound substitution + int CRITERION_; + // Tolerance used for numerical purposes + double EPSILON_; + /// There is no variable upper bound or variable lower bound defined + int UNDEFINED_; + // If violation of a cut is greater that this number, the cut is accepted + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.
    +
  • -1: preprocess according to solver settings; +
  • 0: Do preprocessing only if it has not yet been done; +
  • 1: Do preprocessing. +
+ Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // The array of CglMixIntRoundVUBs. + CglMixIntRoundVUB* vubs_; + // The array of CglMixIntRoundVLBs. + CglMixIntRoundVLB* vlbs_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // The number of rows of type ROW_MIX + int numRowMix_; + // The indices of the rows of type ROW_MIX + int* indRowMix_; + // The number of rows of type ROW_CONT + int numRowCont_; + // The indices of the rows of type ROW_CONT + int* indRowCont_; + // The number of rows of type ROW_INT + int numRowInt_; + // The indices of the rows of type ROW_INT + int* indRowInt_; + // The number of rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int numRowContVB_; + // The indices of the rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int* indRowContVB_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + +}; + +//############################################################################# +// A function that tests the methods in the CglMixedIntegerRounding class. The +// only reason for it not to be a member method is that this way it doesn't +// have to be compiled into the library. And that's a gain, because the +// library should be compiled with optimization on, but this method should be +// compiled with debugging. +void CglMixedIntegerRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding2.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding2.hpp new file mode 100644 index 000000000..16ee3ddc2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglMixedIntegerRounding2.hpp @@ -0,0 +1,427 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// name: Mixed Integer Rounding Cut Generator +// authors: Joao Goncalves (jog7@lehigh.edu) +// Laszlo Ladanyi (ladanyi@us.ibm.com) +// date: August 11, 2004 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglMixedIntegerRounding2_H +#define CglMixedIntegerRounding2_H + +#include +#include +//#include + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" +#include "CoinIndexedVector.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + +// Class to store variable upper bounds (VUB) +class CglMixIntRoundVUB2 +{ + // Variable upper bounds have the form x_j <= a y_j, where x_j is + // a continuous variable and y_j is an integer variable + +protected: + int var_; // The index of y_j + double val_; // The value of a + +public: + // Default constructor + CglMixIntRoundVUB2() : var_(-1), val_(-1) {} + + // Copy constructor + CglMixIntRoundVUB2(const CglMixIntRoundVUB2& source) { + var_ = source.var_; + val_ = source.val_; + } + + // Assignment operator + CglMixIntRoundVUB2& operator=(const CglMixIntRoundVUB2& rhs) { + if (this != &rhs) { + var_ = rhs.var_; + val_ = rhs.val_; + } + return *this; + } + + // Destructor + ~CglMixIntRoundVUB2() {} + + // Query and set functions + int getVar() const { return var_; } + double getVal() const { return val_; } + void setVar(const int v) { var_ = v; } + void setVal(const double v) { val_ = v; } +}; + +//============================================================================= + +// Class to store variable lower bounds (VLB). +// It is the same as the class to store variable upper bounds +typedef CglMixIntRoundVUB2 CglMixIntRoundVLB2; + +//============================================================================= + +/** Mixed Integer Rounding Cut Generator Class */ + +// Reference: +// Hugues Marchand and Laurence A. Wolsey +// Aggregation and Mixed Integer Rounding to Solve MIPs +// Operations Research, 49(3), May-June 2001. +// Also published as CORE Dicusion Paper 9839, June 1998. + +class CglMixedIntegerRounding2 : public CglCutGenerator { + + friend void CglMixedIntegerRounding2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + // The row type of this row is NOT defined yet. + ROW_UNDEFINED, + /** After the row is flipped to 'L', the row has exactly two variables: + one is negative binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARUB, + /** After the row is flipped to 'L', the row has exactly two variables: + one is positive binary and the other is a continous, + and the RHS is zero.*/ + ROW_VARLB, + /** The row sense is 'E', the row has exactly two variables: + one is binary and the other is a continous, and the RHS is zero.*/ + ROW_VAREQ, + // The row contains continuous and integer variables; + // the total number of variables is at least 2 + ROW_MIX, + // The row contains only continuous variables + ROW_CONT, + // The row contains only integer variables + ROW_INT, + // The row contains other types of rows + ROW_OTHER + }; + + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Rounding cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglMixedIntegerRounding2 (); + + /// Alternate Constructor + CglMixedIntegerRounding2 (const int maxaggr, + const bool multiply, + const int criterion, + const int preproc = -1); + + /// Copy constructor + CglMixedIntegerRounding2 ( + const CglMixedIntegerRounding2 &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglMixedIntegerRounding2 & + operator=( + const CglMixedIntegerRounding2& rhs); + + /// Destructor + virtual + ~CglMixedIntegerRounding2 (); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + + //--------------------------------------------------------------------------- + /**@name Set and get methods */ + //@{ + /// Set MAXAGGR_ + inline void setMAXAGGR_ (int maxaggr) { + if (maxaggr > 0) { + MAXAGGR_ = maxaggr; + } + else { + throw CoinError("Unallowable value. maxaggr must be > 0", + "gutsOfConstruct","CglMixedIntegerRounding2"); + } + } + + /// Get MAXAGGR_ + inline int getMAXAGGR_ () const { return MAXAGGR_; } + + /// Set MULTIPLY_ + inline void setMULTIPLY_ (bool multiply) { MULTIPLY_ = multiply; } + + /// Get MULTIPLY_ + inline bool getMULTIPLY_ () const { return MULTIPLY_; } + + /// Set CRITERION_ + inline void setCRITERION_ (int criterion) { + if ((criterion >= 1) && (criterion <= 3)) { + CRITERION_ = criterion; + } + else { + throw CoinError("Unallowable value. criterion must be 1, 2 or 3", + "gutsOfConstruct","CglMixedIntegerRounding2"); + } + } + + /// Get CRITERION_ + inline int getCRITERION_ () const { return CRITERION_; } + + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + //@} + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct ( const int maxaggr, + const bool multiply, + const int criterion, + const int preproc); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglMixedIntegerRounding2& rhs); + + // Do preprocessing. + // It determines the type of each row. It also identifies the variable + // upper bounds and variable lower bounds. + // It may change sense and RHS for ranged rows + void mixIntRoundPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(//const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs) const; + + // Generate MIR cuts + void generateMirCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + //const double* coefByRow, + //const int* colInds, + //const int* rowStarts, + //const CoinPackedMatrix& matrixByCol, + const double* coefByCol, + const int* rowInds, + const CoinBigIndex* colStarts, + OsiCuts& cs ) const; + + // Copy row selected to CoinIndexedVector + void copyRowSelected( const int iAggregate, + const int rowSelected, + CoinIndexedVector& setRowsAggregated, + int* listRowsAggregated, + double* xlpExtra, + const char sen, + const double rhs, + const double lhs, + const CoinPackedMatrix& matrixByRow, + CoinIndexedVector& rowToAggregate, + double& rhsToAggregate) const; + + // Select a row to aggregate + bool selectRowToAggregate( //const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double* colUpperBound, + const double* colLowerBound, + const CoinIndexedVector& setRowsAggregated, + const double* xlp, const double* coefByCol, + const int* rowInds, const CoinBigIndex* colStarts, + int& rowSelected, + int& colSelected ) const; + + // Aggregation heuristic. + // Combines one or more rows of the original matrix + void aggregateRow( const int colSelected, + CoinIndexedVector& rowToAggregate, double rhs, + CoinIndexedVector& rowAggregated, + double& rhsAggregated ) const; + + // Choose the bound substitution based on the criteria defined by the user + inline bool isLowerSubst(const double inf, + const double aj, + const double xlp, + const double LB, + const double UB) const; + + // Bound substitution heuristic + bool boundSubstitution( const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double* xlp, + const double* xlpExtra, + const double* colUpperBound, + const double* colLowerBound, + CoinIndexedVector& mixedKnapsack, + double& rhsMixedKnapsack, double& sStar, + CoinIndexedVector& contVariablesInS ) const; + + // c-MIR separation heuristic + bool cMirSeparation ( const OsiSolverInterface& si, + const CoinPackedMatrix& matrixByRow, + const CoinIndexedVector& rowAggregated, + const int* listRowsAggregated, + const char* sense, const double* RHS, + //const double* coefByRow, + //const int* colInds, const int* rowStarts, + const double* xlp, const double sStar, + const double* colUpperBound, + const double* colLowerBound, + const CoinIndexedVector& mixedKnapsack, + const double& rhsMixedKnapsack, + const CoinIndexedVector& contVariablesInS, + CoinIndexedVector * workVector, + OsiRowCut& flowCut ) const; + + // function to create one c-MIR inequality + void cMirInequality( const int numInt, + const double delta, + const double numeratorBeta, + const int *knapsackIndices, + const double* knapsackElements, + const double* xlp, + const double sStar, + const double* colUpperBound, + const CoinIndexedVector& setC, + CoinIndexedVector& cMIR, + double& rhscMIR, + double& sCoef, + double& violation) const; + + // function to compute G + inline double functionG( const double d, const double f ) const; + + // function to print statistics (used only in debug mode) + void printStats( + std::ofstream & fout, + const bool hasCut, + const OsiSolverInterface& si, + const CoinIndexedVector& rowAggregated, + const double& rhsAggregated, const double* xlp, + const double* xlpExtra, + const int* listRowsAggregated, + const int* listColsSelected, + const int level, + const double* colUpperBound, + const double* colLowerBound ) const; + + +private: + //--------------------------------------------------------------------------- + // Private member data + + // Maximum number of rows to aggregate + int MAXAGGR_; + // Flag that indicates if an aggregated row is also multiplied by -1 + bool MULTIPLY_; + // The criterion to use in the bound substitution + int CRITERION_; + // Tolerance used for numerical purposes + double EPSILON_; + /// There is no variable upper bound or variable lower bound defined + int UNDEFINED_; + // If violation of a cut is greater that this number, the cut is accepted + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.
    +
  • -1: preprocess according to solver settings; +
  • 0: Do preprocessing only if it has not yet been done; +
  • 1: Do preprocessing. +
+ Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // The array of CglMixIntRoundVUB2s. + CglMixIntRoundVUB2* vubs_; + // The array of CglMixIntRoundVLB2s. + CglMixIntRoundVLB2* vlbs_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // The number of rows of type ROW_MIX + int numRowMix_; + // The indices of the rows of type ROW_MIX + int* indRowMix_; + // The number of rows of type ROW_CONT + int numRowCont_; + // The indices of the rows of type ROW_CONT + int* indRowCont_; + // The number of rows of type ROW_INT + int numRowInt_; + // The indices of the rows of type ROW_INT + int* indRowInt_; + // The number of rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int numRowContVB_; + // The indices of the rows of type ROW_CONT that have at least one variable + // with variable upper or lower bound + int* indRowContVB_; + // If integer - for speed + char * integerType_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + +}; + +//############################################################################# +// A function that tests the methods in the CglMixedIntegerRounding2 class. The +// only reason for it not to be a member method is that this way it doesn't +// have to be compiled into the library. And that's a gain, because the +// library should be compiled with optimization on, but this method should be +// compiled with debugging. +void CglMixedIntegerRounding2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglOddHole.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglOddHole.hpp new file mode 100644 index 000000000..63ff2486e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglOddHole.hpp @@ -0,0 +1,160 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglOddHole_H +#define CglOddHole_H + +#include + +#include "CglCutGenerator.hpp" + +/** Odd Hole Cut Generator Class */ +class CglOddHole : public CglCutGenerator { + friend void CglOddHoleUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate odd hole cuts for the model of the solver interface, si. + This looks at all rows of type sum x(i) <= 1 (or == 1) (x 0-1) + and sees if there is an odd cycle cut. See Grotschel, Lovasz + and Schrijver (1988) for method. + This is then lifted by using the corresponding Chvatal cut i.e. + Take all rows in cycle and add them together. RHS will be odd so + weaken all odd coefficients so 1.0 goes to 0.0 etc - then + constraint is sum even(j)*x(j) <= odd which can be replaced by + sum (even(j)/2)*x(j) <= (odd-1.0)/2. + A similar cut can be generated for sum x(i) >= 1. + + Insert the generated cuts into OsiCut, cs. + + This is only done for rows with unsatisfied 0-1 variables. If there + are many of these it will be slow. Improvements would do a + randomized subset and also speed up shortest path algorithm used. + + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Create Row List */ + //@{ + /// Create a list of rows which might yield cuts + /// this is to speed up process + /// The possible parameter is a list to cut down search + void createRowList( const OsiSolverInterface & si, + const int * possible=NULL); + /// This version passes in a list - 1 marks possible + void createRowList(int numberRows, const int * whichRow); + //@} + + /**@name Create Clique List */ + //@{ + /// Create a list of extra row cliques which may not be in matrix + /// At present these are classical cliques + void createCliqueList(int numberCliques, const int * cliqueStart, + const int * cliqueMember); + //@} + + /**@name Number Possibilities */ + //@{ + /// Returns how many rows might give odd hole cuts + int numberPossible(); + //@} + /**@name Gets and Sets */ + //@{ + /// Minimum violation + double getMinimumViolation() const; + void setMinimumViolation(double value); + /// Minimum violation per entry + double getMinimumViolationPer() const; + void setMinimumViolationPer(double value); + /// Maximum number of entries in a cut + int getMaximumEntries() const; + void setMaximumEntries(int value); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglOddHole (); + + /// Copy constructor + CglOddHole ( + const CglOddHole &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglOddHole & + operator=( + const CglOddHole& rhs); + + /// Destructor + virtual + ~CglOddHole (); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + + // Private member methods + + + /**@name Private methods */ + //@{ + /// Generate cuts from matrix copy and solution + /// If packed true then <=1 rows, otherwise >=1 rows. + void generateCuts(const OsiRowCutDebugger * debugger, + const CoinPackedMatrix & rowCopy, + const double * solution, const double * dj, + OsiCuts & cs, const int * suitableRow, + const int * fixedColumn,const CglTreeInfo info, + bool packed); + //@} + + // Private member data + + /**@name Private member data */ + //@{ + /// list of suitableRows + int * suitableRows_; + /// start of each clique + int * startClique_; + /// clique members + int * member_; + /// epsilon + double epsilon_; + /// 1-epsilon + double onetol_; + /// Minimum violation + double minimumViolation_; + /// Minimum violation per entry + double minimumViolationPer_; + /// Maximum number of entries in a cut + int maximumEntries_; + /// number of rows when suitability tested + int numberRows_; + /// number of cliques + int numberCliques_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglOddHole class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglOddHoleUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglParam.hpp new file mode 100644 index 000000000..13414e060 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglParam.hpp @@ -0,0 +1,93 @@ +// Name: CglParam.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 11/24/06 +// +// $Id$ +// +// This code is licensed under the terms of the Eclipse Public License (EPL). +//----------------------------------------------------------------------------- +// Copyright (C) 2006, Francois Margot and others. All Rights Reserved. + +#ifndef CglParam_H +#define CglParam_H +#include "CglConfig.h" +#include "CoinFinite.hpp" +/** Class collecting parameters for all cut generators. Each generator + may have a derived class to add parameters. Each generator might + also set different default values for the parameters in CglParam. */ + +class CglParam { + +public: + /**@name Public Set/get methods */ + //@{ + + /** Set INFINIT */ + virtual void setINFINIT(const double inf); + /** Get value of INFINIT */ + inline double getINFINIT() const { return INFINIT; } + + /** Set EPS */ + virtual void setEPS(const double eps); + /** Get value of EPS */ + inline double getEPS() const { return EPS; } + + /** Set EPS_COEFF */ + virtual void setEPS_COEFF(const double eps_c); + /** Get value of EPS_COEFF */ + inline double getEPS_COEFF() const { return EPS_COEFF; } + + /** Set MAX_SUPPORT */ + virtual void setMAX_SUPPORT(const int max_s); + /** Get value of MAX_SUPPORT */ + inline int getMAX_SUPPORT() const { return MAX_SUPPORT; } + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglParam(const double inf = COIN_DBL_MAX, const double eps = 1e-6, + const double eps_c = 1e-5, const int max_s = COIN_INT_MAX); + + /// Copy constructor + CglParam(const CglParam &); + + /// Clone + virtual CglParam *clone() const; + + /// Assignment operator + CglParam &operator=(const CglParam &rhs); + + /// Destructor + virtual ~CglParam(); + //@} + +protected: + // Protected member data + + /**@name Protected member data */ + + //@{ + // Value for infinity. Default: COIN_DBL_MAX. + double INFINIT; + + // EPSILON for double comparisons. Default: 1e-6. + double EPS; + + // Returned cuts do not have coefficients with absolute value smaller + // than EPS_COEFF. Default: 1e-5. + double EPS_COEFF; + + /** Maximum number of non zero coefficients in a generated cut; + Default: COIN_INT_MAX */ + int MAX_SUPPORT; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglPreProcess.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglPreProcess.hpp new file mode 100644 index 000000000..9d8a093ef --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglPreProcess.hpp @@ -0,0 +1,600 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglPreProcess_H +#define CglPreProcess_H + +#include +#include + +#include "CoinMessageHandler.hpp" +#include "OsiSolverInterface.hpp" +#include "CglStored.hpp" +#include "OsiPresolve.hpp" +#include "CglCutGenerator.hpp" + +//############################################################################# + +/** Class for preProcessing and postProcessing. + + While cuts can be added at any time in the tree, some cuts are actually just + stronger versions of existing constraints. In this case they can replace those + constraints rather than being added as new constraints. This is awkward in the + tree but reasonable at the root node. + + This is a general process class which uses other cut generators to strengthen + constraints, establish that constraints are redundant, fix variables and + find relationships such as x + y == 1. + + Presolve will also be done. + + If row names existed they may be replaced by R0000000..., unless + setKeepColumnNames(true) is set. + +*/ + +class CglPreProcess { + +public: + ///@name Main methods + //@{ + /** preProcess problem - returning new problem. + If makeEquality true then <= cliques converted to ==. + Presolve will be done numberPasses times. + + Returns NULL if infeasible + + This version uses default strategy. For more control copy and edit + code from this function i.e. call preProcessNonDefault + */ + OsiSolverInterface *preProcess(OsiSolverInterface &model, + bool makeEquality = false, int numberPasses = 5); + /** preProcess problem - returning new problem. + If makeEquality true then <= cliques converted to ==. + Presolve will be done numberPasses times. + + Returns NULL if infeasible + + This version assumes user has added cut generators to CglPreProcess object + before calling it. As an example use coding in preProcess + If makeEquality is 1 add slacks to get cliques, + if 2 add slacks to get sos (but only if looks plausible) and keep sos info + */ + OsiSolverInterface *preProcessNonDefault(OsiSolverInterface &model, + int makeEquality = 0, int numberPasses = 5, + int tuning = 0); + /** Creates solution in original model + deleteStuff 0 - don't, 1 do (but not if infeasible), 2 always */ + void postProcess(OsiSolverInterface &model, int deleteStuff = 2); + /** Tightens primal bounds to make dual and branch and cutfaster. Unless + fixed or integral, bounds are slightly looser than they could be. + Returns non-zero if problem infeasible + Fudge for branch and bound - put bounds on columns of factor * + largest value (at continuous) - should improve stability + in branch and bound on infeasible branches (0.0 is off) + */ + int tightenPrimalBounds(OsiSolverInterface &model, double factor = 0.0); + /** Fix some of problem - returning new problem. + Uses reduced costs. + Optional signed character array + 1 always keep, -1 always discard, 0 use djs + + */ + OsiSolverInterface *someFixed(OsiSolverInterface &model, + double fractionToKeep = 0.25, + bool fixContinuousAsWell = false, + char *keep = NULL) const; + /** Replace cliques by more maximal cliques + Returns NULL if rows not reduced by greater than cliquesNeeded*rows + + */ + OsiSolverInterface *cliqueIt(OsiSolverInterface &model, + double cliquesNeeded = 0.0) const; + /// If we have a cutoff - fix variables + int reducedCostFix(OsiSolverInterface &model); + //@} + + //--------------------------------------------------------------------------- + + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false if the value of the parameter is out of range. + + The get methods return the value of the parameter. + + */ + //@{ + /** Set cutoff bound on the objective function. + + When using strict comparison, the bound is adjusted by a tolerance to + avoid accidentally cutting off the optimal solution. + */ + void setCutoff(double value); + + /// Get the cutoff bound on the objective function - always as minimize + double getCutoff() const; + /// The original solver associated with this model. + inline OsiSolverInterface *originalModel() const + { + return originalModel_; + } + /// Set original model (probably acopy) + inline void setOriginalModel(OsiSolverInterface *originalModel) + { + originalModel_ = originalModel; + } + /// Solver after making clique equalities (may == original) + inline OsiSolverInterface *startModel() const + { + return startModel_; + } + /// Number of solvers + inline int numberSolvers() const + { + return numberSolvers_; + } + /// Copies of solver at various stages after presolve + inline OsiSolverInterface *modelAtPass(int iPass) const + { + if (iPass >= 0 && iPass < numberSolvers_) + return model_[iPass]; + else + return NULL; + } + /// Copies of solver at various stages after presolve after modifications + inline OsiSolverInterface *modifiedModel(int iPass) const + { + if (iPass >= 0 && iPass < numberSolvers_) + return modifiedModel_[iPass]; + else + return NULL; + } + /// Matching presolve information + inline OsiPresolve *presolve(int iPass) const + { + if (iPass >= 0 && iPass < numberSolvers_) + return presolve_[iPass]; + else + return NULL; + } + /// Set matching presolve information + inline void setPresolve(int iPass, OsiPresolve *presolve) + { + if (iPass >= 0 && iPass < numberSolvers_) + presolve_[iPass] = presolve; + } + /** Return a pointer to the original columns (with possible clique slacks) + MUST be called before postProcess otherwise you just get 0,1,2.. */ + const int *originalColumns(); + /** Return a pointer to the original rows + MUST be called before postProcess otherwise you just get 0,1,2.. */ + const int *originalRows(); + /// Number of SOS if found + inline int numberSOS() const + { + return numberSOS_; + } + /// Type of each SOS + inline const int *typeSOS() const + { + return typeSOS_; + } + /// Start of each SOS + inline const int *startSOS() const + { + return startSOS_; + } + /// Columns in SOS + inline const int *whichSOS() const + { + return whichSOS_; + } + /// Weights for each SOS column + inline const double *weightSOS() const + { + return weightSOS_; + } + /// Pass in prohibited columns + void passInProhibited(const char *prohibited, int numberColumns); + /// Updated prohibited columns + inline const char *prohibited() + { + return prohibited_; + } + /// Number of iterations PreProcessing + inline int numberIterationsPre() const + { + return numberIterationsPre_; + } + /// Number of iterations PostProcessing + inline int numberIterationsPost() const + { + return numberIterationsPost_; + } + /** Pass in row types + 0 normal + 1 cut rows - will be dropped if remain in + At end of preprocess cut rows will be dropped + and put into cuts + */ + void passInRowTypes(const char *rowTypes, int numberRows); + /** Updated row types - may be NULL + Carried around and corresponds to existing rows + -1 added by preprocess e.g. x+y=1 + 0 normal + 1 cut rows - can be dropped if wanted + */ + inline const char *rowTypes() + { + return rowType_; + } + /// Return cuts from dropped rows + inline const CglStored &cuts() const + { + return cuts_; + } + /// Return pointer to cuts from dropped rows + inline const CglStored *cutsPointer() const + { + return &cuts_; + } + /// Update prohibited and rowType + void update(const OsiPresolve *pinfo, const OsiSolverInterface *solver); + /// Get options + inline int options() const + { + return options_; + } + /// Set options + inline void setOptions(int value) + { + options_ = value; + } + //@} + + ///@name Cut generator methods + //@{ + /// Get the number of cut generators + inline int numberCutGenerators() const + { + return numberCutGenerators_; + } + /// Get the list of cut generators + inline CglCutGenerator **cutGenerators() const + { + return generator_; + } + ///Get the specified cut generator + inline CglCutGenerator *cutGenerator(int i) const + { + return generator_[i]; + } + /** Add one generator - up to user to delete generators. + */ + void addCutGenerator(CglCutGenerator *generator); + //@} + + /**@name Setting/Accessing application data */ + //@{ + /** Set application data. + + This is a pointer that the application can store into and + retrieve. + This field is available for the application to optionally + define and use. + */ + void setApplicationData(void *appData); + + /// Get application data + void *getApplicationData() const; + //@} + + //--------------------------------------------------------------------------- + + /**@name Message handling */ + //@{ + /// Pass in Message handler (not deleted at end) + void passInMessageHandler(CoinMessageHandler *handler); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + /// Return handler + inline CoinMessageHandler *messageHandler() const + { + return handler_; + } + /// Return messages + inline CoinMessages messages() + { + return messages_; + } + /// Return pointer to messages + inline CoinMessages *messagesPointer() + { + return &messages_; + } + //@} + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors etc + //@{ + /// Constructor + CglPreProcess(); + + /// Copy constructor . + CglPreProcess(const CglPreProcess &rhs); + + /// Assignment operator + CglPreProcess &operator=(const CglPreProcess &rhs); + + /// Destructor + ~CglPreProcess(); + + /// Clears out as much as possible + void gutsOfDestructor(); + + /// Set time limit + void setTimeLimit(const double timeLimit, const bool useElapsedTime); + + /// Keeps original column names + void setKeepColumnNames(const bool keep); + + //@} +private: + ///@name private methods + //@{ + /** Return model with useful modifications. + If constraints true then adds any x+y=1 or x-y=0 constraints + If NULL infeasible + */ + OsiSolverInterface *modified(OsiSolverInterface *model, + bool constraints, + int &numberChanges, + int iBigPass, + int numberPasses); + /// create original columns and rows + void createOriginalIndices(); + /// Make continuous variables integer + void makeInteger(); + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + + /// The original solver associated with this model. + OsiSolverInterface *originalModel_; + /// Solver after making clique equalities (may == original) + OsiSolverInterface *startModel_; + /// Number of solvers at various stages + int numberSolvers_; + /// Copies of solver at various stages after presolve + OsiSolverInterface **model_; + /// Copies of solver at various stages after presolve after modifications + OsiSolverInterface **modifiedModel_; + /// Matching presolve information + OsiPresolve **presolve_; + + /// Message handler + CoinMessageHandler *handler_; + + /** Flag to say if handler_ is the default handler. + + The default handler is deleted when the model is deleted. Other + handlers (supplied by the client) will not be deleted. + */ + bool defaultHandler_; + + /// Cgl messages + CoinMessages messages_; + + /// Pointer to user-defined data structure + void *appData_; + /// Original column numbers + int *originalColumn_; + /// Original row numbers + int *originalRow_; + /// Number of cut generators + int numberCutGenerators_; + /// Cut generators + CglCutGenerator **generator_; + /// Number of SOS if found + int numberSOS_; + /// Type of each SOS + int *typeSOS_; + /// Start of each SOS + int *startSOS_; + /// Columns in SOS + int *whichSOS_; + /// Weights for each SOS column + double *weightSOS_; + /// Number of columns in original prohibition set + int numberProhibited_; + /// Number of iterations done in PreProcessing + int numberIterationsPre_; + /// Number of iterations done in PostProcessing + int numberIterationsPost_; + /// Columns which should not be presolved e.g. SOS + char *prohibited_; + /// Number of rows in original row types + int numberRowType_; + /** Options + 1 - original model had integer bounds before tightening + 2 - don't do probing + 4 - don't do duplicate rows + 8 - don't do cliques + 16 - some heavy probing options + 64 - very heavy probing + */ + int options_; + /** Row types (may be NULL) + Carried around and corresponds to existing rows + -1 added by preprocess e.g. x+y=1 + 0 normal + 1 cut rows - can be dropped if wanted + */ + char *rowType_; + /// Cuts from dropped rows + CglStored cuts_; + + /// use elapsed (wallclock time) or cpu time + bool useElapsedTime_; + + /// time limit (default COIN_DBL_MAX) + double timeLimit_; + + /// keep column names + bool keepColumnNames_; + + /// current elapsed or cpu time + double getCurrentCPUTime() const; + + //@} +}; + +/// For Bron-Kerbosch +class CglBK { + +public: + ///@name Main methods + //@{ + /// For recursive Bron-Kerbosch + void bronKerbosch(); + /// Creates strengthened smaller model + OsiSolverInterface *newSolver(const OsiSolverInterface &model); + //@} + + //--------------------------------------------------------------------------- + + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false if the value of the parameter is out of range. + + The get methods return the value of the parameter. + + */ + //@{ + //@} + + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors etc + //@{ + /// Default constructor + CglBK(); + + /// Useful constructor + CglBK(const OsiSolverInterface &model, const char *rowType, + int numberElements); + + /// Copy constructor . + CglBK(const CglBK &rhs); + + /// Assignment operator + CglBK &operator=(const CglBK &rhs); + + /// Destructor + ~CglBK(); + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + /// Current candidates (created at each level) + int *candidates_; + /// Array to mark stuff + char *mark_; + /// Starts for graph (numberPossible+1) + CoinBigIndex *start_; + /// Other column/node + int *otherColumn_; + /// Original row (in parallel with otherColumn_) + int *originalRow_; + /// How many times each original row dominated + int *dominated_; + /// Clique entries + CoinPackedMatrix *cliqueMatrix_; + /// points to row types + const char *rowType_; + /// Number of original columns + int numberColumns_; + /// Number of original rows + int numberRows_; + /// Number possible + int numberPossible_; + /// Current number of candidates + int numberCandidates_; + /// First not (stored backwards from numberPossible_) + int firstNot_; + /// Current number in clique + int numberIn_; + /// For acceleration + int left_; + int lastColumn_; + //@} +}; +/** + Only store unique row cuts +*/ +// for hashing +typedef struct { + int index, next; +} CglHashLink; +class OsiRowCut; +class CglUniqueRowCuts { +public: + CglUniqueRowCuts(int initialMaxSize = 0, int hashMultiplier = 4); + ~CglUniqueRowCuts(); + CglUniqueRowCuts(const CglUniqueRowCuts &rhs); + CglUniqueRowCuts &operator=(const CglUniqueRowCuts &rhs); + inline OsiRowCut *cut(int sequence) const + { + return rowCut_[sequence]; + } + inline int numberCuts() const + { + return numberCuts_; + } + inline int sizeRowCuts() const + { + return numberCuts_; + } + inline OsiRowCut *rowCutPtr(int sequence) + { + return rowCut_[sequence]; + } + void eraseRowCut(int sequence); + // insert cut + inline void insert(const OsiRowCut &cut) + { + insertIfNotDuplicate(cut); + } + // Return 0 if added, 1 if not + int insertIfNotDuplicate(const OsiRowCut &cut); + // Add in cuts as normal cuts (and delete) + void addCuts(OsiCuts &cs); + +private: + OsiRowCut **rowCut_; + /// Hash table + CglHashLink *hash_; + int size_; + int hashMultiplier_; + int numberCuts_; + int lastHash_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglProbing.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglProbing.hpp new file mode 100644 index 000000000..a4bd501ed --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglProbing.hpp @@ -0,0 +1,543 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglProbing_H +#define CglProbing_H + +#include + +#include "CglCutGenerator.hpp" + /** Only useful type of disaggregation is most normal + For now just done for 0-1 variables + Can be used for building cliques + */ + typedef struct { + //unsigned int zeroOne:1; // nonzero if affected variable is 0-1 + //unsigned int whenAtUB:1; // nonzero if fixing happens when this variable at 1 + //unsigned int affectedToUB:1; // nonzero if affected variable fixed to UB + //unsigned int affected:29; // If 0-1 then 0-1 sequence, otherwise true + unsigned int affected; + } disaggregationAction; + +/** Probing Cut Generator Class */ +class CglProbing : public CglCutGenerator { + friend void CglProbingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + + /**@name Generate Cuts */ + //@{ + /** Generate probing/disaggregation cuts for the model of the + solver interface, si. + + This is a simplification of probing ideas put into OSL about + ten years ago. The only known documentation is a copy of a + talk handout - we think Robin Lougee-Heimer has a copy! + + For selected integer variables (e.g. unsatisfied ones) the effect of + setting them up or down is investigated. Setting a variable up + may in turn set other variables (continuous as well as integer). + There are various possible results: + + 1) It is shown that problem is infeasible (this may also be + because objective function or reduced costs show worse than + best solution). If the other way is feasible we can generate + a column cut (and continue probing), if not feasible we can + say problem infeasible. + + 2) If both ways are feasible, it can happen that x to 0 implies y to 1 + ** and x to 1 implies y to 1 (again a column cut). More common + is that x to 0 implies y to 1 and x to 1 implies y to 0 so we could + substitute for y which might lead later to more powerful cuts. + ** This is not done in this code as there is no mechanism for + returning information. + + 3) When x to 1 a constraint went slack by c. We can tighten the + constraint ax + .... <= b (where a may be zero) to + (a+c)x + .... <= b. If this cut is violated then it is + generated. + + 4) Similarly we can generate implied disaggregation cuts + + Note - differences to cuts in OSL. + + a) OSL had structures intended to make this faster. + b) The "chaining" in 2) was done + c) Row cuts modified original constraint rather than adding cut + b) This code can cope with general integer variables. + + Insert the generated cuts into OsiCut, cs. + + If a "snapshot" of a matrix exists then this will be used. + Presumably this will give global cuts and will be faster. + No check is done to see if cuts will be global. + + Otherwise use current matrix. + + Both row cuts and column cuts may be returned + + The mode options are: + 0) Only unsatisfied integer variables will be looked at. + If no information exists for that variable then + probing will be done so as a by-product you "may" get a fixing + or infeasibility. This will be fast and is only available + if a snapshot exists (otherwise as 1). + The bounds in the snapshot are the ones used. + 1) Look at unsatisfied integer variables, using current bounds. + Probing will be done on all looked at. + 2) Look at all integer variables, using current bounds. + Probing will be done on all + + ** If generateCutsAndModify is used then new relaxed + row bounds and tightened column bounds are generated + Returns number of infeasibilities + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + int generateCutsAndModify( const OsiSolverInterface & si, OsiCuts & cs, + CglTreeInfo * info); + //@} + + /**@name snapshot etc */ + //@{ + /** Create a copy of matrix which is to be used + this is to speed up process and to give global cuts + Can give an array with 1 set to select, 0 to ignore + column bounds are tightened + If array given then values of 1 will be set to 0 if redundant. + Objective may be added as constraint + Returns 1 if infeasible otherwise 0 + */ + int snapshot ( const OsiSolverInterface & si, + char * possible=NULL, + bool withObjective=true); + /// Deletes snapshot + void deleteSnapshot ( ); + /** Creates cliques for use by probing. + Only cliques >= minimumSize and < maximumSize created + Can also try and extend cliques as a result of probing (root node). + Returns number of cliques found. + */ + int createCliques( OsiSolverInterface & si, + int minimumSize=2, int maximumSize=100); + /// Delete all clique information + void deleteCliques(); + /** Create a fake model by adding cliques + if type&4 then delete rest of model first, + if 1 then add proper cliques, 2 add fake cliques */ + OsiSolverInterface * cliqueModel(const OsiSolverInterface * model, + int type); + //@} + + /**@name Get tighter column bounds */ + //@{ + /// Lower + const double * tightLower() const; + /// Upper + const double * tightUpper() const; + /// Array which says tighten continuous + const char * tightenBounds() const + { return tightenBounds_;} + //@} + + /**@name Get possible freed up row bounds - only valid after mode==3 */ + //@{ + /// Lower + const double * relaxedRowLower() const; + /// Upper + const double * relaxedRowUpper() const; + //@} + + /**@name Change mode */ + //@{ + /// Set + void setMode(int mode); + /// Get + int getMode() const; + //@} + + /**@name Change maxima */ + //@{ + /// Set maximum number of passes per node + void setMaxPass(int value); + /// Get maximum number of passes per node + int getMaxPass() const; + /// Set log level - 0 none, 1 - a bit, 2 - more details + void setLogLevel(int value); + /// Get log level + int getLogLevel() const; + /// Set maximum number of unsatisfied variables to look at + void setMaxProbe(int value); + /// Get maximum number of unsatisfied variables to look at + int getMaxProbe() const; + /// Set maximum number of variables to look at in one probe + void setMaxLook(int value); + /// Get maximum number of variables to look at in one probe + int getMaxLook() const; + /// Set maximum number of elements in row for it to be considered + void setMaxElements(int value); + /// Get maximum number of elements in row for it to be considered + int getMaxElements() const; + /// Set maximum number of passes per node (root node) + void setMaxPassRoot(int value); + /// Get maximum number of passes per node (root node) + int getMaxPassRoot() const; + /// Set maximum number of unsatisfied variables to look at (root node) + void setMaxProbeRoot(int value); + /// Get maximum number of unsatisfied variables to look at (root node) + int getMaxProbeRoot() const; + /// Set maximum number of variables to look at in one probe (root node) + void setMaxLookRoot(int value); + /// Get maximum number of variables to look at in one probe (root node) + int getMaxLookRoot() const; + /// Set maximum number of elements in row for it to be considered (root node) + void setMaxElementsRoot(int value); + /// Get maximum number of elements in row for it to be considered (root node) + int getMaxElementsRoot() const; + /** + Returns true if may generate Row cuts in tree (rather than root node). + Used so know if matrix will change in tree. Really + meant so column cut generators can still be active + without worrying code. + Default is true + */ + virtual bool mayGenerateRowCutsInTree() const; + //@} + + /**@name Get information back from probing */ + //@{ + /// Number looked at this time + inline int numberThisTime() const + { return numberThisTime_;} + /// Which ones looked at this time + inline const int * lookedAt() const + { return lookedAt_;} + //@} + + /**@name Stop or restart row cuts (otherwise just fixing from probing) */ + //@{ + /// Set + /// 0 no cuts, 1 just disaggregation type, 2 coefficient ( 3 both) + void setRowCuts(int type); + /// Get + int rowCuts() const; + //@} + /// Clique type + typedef struct { + unsigned int equality:1; // nonzero if clique is == + } CliqueType; + + /**@name Information on cliques */ + //@{ + /// Number of cliques + inline int numberCliques() const + { return numberCliques_;} + /// Clique type + inline CliqueType * cliqueType() const + { return cliqueType_;} + /// Start of each clique + inline CoinBigIndex * cliqueStart() const + { return cliqueStart_;} + /// Entries for clique + inline CliqueEntry * cliqueEntry() const + { return cliqueEntry_;} + //@} + + /**@name Whether use objective as constraint */ + //@{ + /** Set + 0 don't + 1 do + -1 don't even think about it + */ + void setUsingObjective(int yesNo); + /// Get + int getUsingObjective() const; + //@} + + /**@name Mark which continuous variables are to be tightened */ + //@{ + /// Mark variables to be tightened + void tightenThese(const OsiSolverInterface & solver, int number, const int * which); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglProbing (); + + /// Copy constructor + CglProbing ( + const CglProbing &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglProbing & + operator=( + const CglProbing& rhs); + + /// Destructor + virtual + ~CglProbing (); + + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + /**@name probe */ + //@{ + /// Does probing and adding cuts (without cliques and mode_!=0) + int probe( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy,const CoinBigIndex * rowStartPos, + const int * realRow, const double * rowLower, const double * rowUpper, + const char * intVar, double * minR, double * maxR, int * markR, + CglTreeInfo * info); + /// Does probing and adding cuts (with cliques) + int probeCliques( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy, const int * realRow, + double * rowLower, double * rowUpper, + char * intVar, double * minR, double * maxR, int * markR, + CglTreeInfo * info); + /// Does probing and adding cuts for clique slacks + int probeSlacks( const OsiSolverInterface & si, + const OsiRowCutDebugger * debugger, + OsiCuts & cs, + double * colLower, double * colUpper, CoinPackedMatrix *rowCopy, + CoinPackedMatrix *columnCopy, + double * rowLower, double * rowUpper, + char * intVar, double * minR, double * maxR,int * markR, + CglTreeInfo * info); + /** Does most of work of generateCuts + Returns number of infeasibilities */ + int gutsOfGenerateCuts( const OsiSolverInterface & si, + OsiCuts & cs, + double * rowLower, double * rowUpper, + double * colLower, double * colUpper, + CglTreeInfo * info); + /// Sets up clique information for each row + void setupRowCliqueInformation(const OsiSolverInterface & si); + /** This tightens column bounds (and can declare infeasibility) + It may also declare rows to be redundant */ + int tighten(double *colLower, double * colUpper, + const int *column, const double *rowElements, + const CoinBigIndex *rowStart,const CoinBigIndex * rowStartPos, + const int * rowLength, + double *rowLower, double *rowUpper, + int nRows,int nCols,char * intVar,int maxpass, + double tolerance); + /// This just sets minima and maxima on rows + void tighten2(double *colLower, double * colUpper, + const int *column, const double *rowElements, + const CoinBigIndex *rowStart, + const int * rowLength, + double *rowLower, double *rowUpper, + double * minR, double * maxR, int * markR, + int nRows); + //@} + + // Private member data + + struct disaggregation_struct_tag ; + friend struct CglProbing::disaggregation_struct_tag ; + + /**@name Private member data */ + //@{ + /// Row copy (only if snapshot) + CoinPackedMatrix * rowCopy_; + /// Column copy (only if snapshot) + CoinPackedMatrix * columnCopy_; + /// Lower bounds on rows + double * rowLower_; + /// Upper bounds on rows + double * rowUpper_; + /// Lower bounds on columns + double * colLower_; + /// Upper bounds on columns + double * colUpper_; + /// Number of rows in snapshot (or when cliqueRow stuff computed) + int numberRows_; + /// Number of columns in problem ( must == current) + int numberColumns_; + /// Tolerance to see if infeasible + double primalTolerance_; + /** Mode - 0 lazy using snapshot, 1 just unsatisfied, 2 all. + 16 bit set if want to extend cliques at root node + */ + int mode_; + /** Row cuts flag + 0 no cuts, 1 just disaggregation type, 2 coefficient ( 3 both), 4 just column cuts + -n as +n but just fixes variables unless at root + */ + int rowCuts_; + /// Maximum number of passes to do in probing + int maxPass_; + /// Log level - 0 none, 1 - a bit, 2 - more details + int logLevel_; + /// Maximum number of unsatisfied variables to probe + int maxProbe_; + /// Maximum number of variables to look at in one probe + int maxStack_; + /// Maximum number of elements in row for scan + int maxElements_; + /// Maximum number of passes to do in probing at root + int maxPassRoot_; + /// Maximum number of unsatisfied variables to probe at root + int maxProbeRoot_; + /// Maximum number of variables to look at in one probe at root + int maxStackRoot_; + /// Maximum number of elements in row for scan at root + int maxElementsRoot_; + /// Whether to include objective as constraint + int usingObjective_; + /// Number of integer variables + int numberIntegers_; + /// Number of 0-1 integer variables + int number01Integers_; + /// Number looked at this time + int numberThisTime_; + /// Total number of times called + int totalTimesCalled_; + /// Which ones looked at this time + int * lookedAt_; + /// Disaggregation cuts and for building cliques + typedef struct disaggregation_struct_tag { + int sequence; // integer variable + // index will be NULL if no probing done yet + int length; // length of newValue + disaggregationAction * index; // columns whose bounds will be changed + } disaggregation; + disaggregation * cutVector_; + /// Cliques + /// Number of cliques + int numberCliques_; + /// Clique type + CliqueType * cliqueType_; + /// Start of each clique + CoinBigIndex * cliqueStart_; + /// Entries for clique + CliqueEntry * cliqueEntry_; + /** Start of oneFixes cliques for a column in matrix or -1 if not + in any clique */ + int * oneFixStart_; + /** Start of zeroFixes cliques for a column in matrix or -1 if not + in any clique */ + int * zeroFixStart_; + /// End of fixes for a column + int * endFixStart_; + /// Clique numbers for one or zero fixes + int * whichClique_; + /** For each column with nonzero in row copy this gives a clique "number". + So first clique mentioned in row is always 0. If no entries for row + then no cliques. If sequence > numberColumns then not in clique. + */ + CliqueEntry * cliqueRow_; + /// cliqueRow_ starts for each row + int * cliqueRowStart_; + /// If not null and [i] !=0 then also tighten even if continuous + char * tightenBounds_; + //@} +}; +inline int affectedInDisaggregation(const disaggregationAction & dis) +{ return dis.affected&0x1fffffff;} +inline void setAffectedInDisaggregation(disaggregationAction & dis, + int affected) +{ dis.affected = affected|(dis.affected&0xe0000000);} +#ifdef NDEBUG +inline bool zeroOneInDisaggregation(const disaggregationAction & ) +{ return true;} +#else +inline bool zeroOneInDisaggregation(const disaggregationAction & dis) +//{ return (dis.affected&0x80000000)!=0;} +{ assert ((dis.affected&0x80000000)!=0); return true;} +#endif +inline void setZeroOneInDisaggregation(disaggregationAction & dis,bool zeroOne) +{ dis.affected = (zeroOne ? 0x80000000 : 0)|(dis.affected&0x7fffffff);} +inline bool whenAtUBInDisaggregation(const disaggregationAction & dis) +{ return (dis.affected&0x40000000)!=0;} +inline void setWhenAtUBInDisaggregation(disaggregationAction & dis,bool whenAtUB) +{ dis.affected = (whenAtUB ? 0x40000000 : 0)|(dis.affected&0xbfffffff);} +inline bool affectedToUBInDisaggregation(const disaggregationAction & dis) +{ return (dis.affected&0x20000000)!=0;} +inline void setAffectedToUBInDisaggregation(disaggregationAction & dis,bool affectedToUB) +{ dis.affected = (affectedToUB ? 0x20000000 : 0)|(dis.affected&0xdfffffff);} + +//############################################################################# +/** A function that tests the methods in the CglProbing class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglProbingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); +/// This just uses implication info +class CglImplication : public CglCutGenerator { + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate cuts from implication table + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglImplication (); + + /// Constructor with info + CglImplication (CglTreeProbingInfo * info); + + /// Copy constructor + CglImplication ( + const CglImplication &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglImplication & + operator=( + const CglImplication& rhs); + + /// Destructor + virtual + ~CglImplication (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + /**@name Set implication */ + //@{ + /// Set implication + inline void setProbingInfo(CglTreeProbingInfo * info) + { probingInfo_=info;} + //@} + +private: + /**@name Private member data */ + //@{ + /// Pointer to tree probing info + CglTreeProbingInfo * probingInfo_; + //@} +}; +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit.hpp new file mode 100644 index 000000000..1e46ba989 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit.hpp @@ -0,0 +1,448 @@ +// Last edit: 4/20/07 +// +// Name: CglRedSplit.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 2/6/05 +// +// $Id$ +//----------------------------------------------------------------------------- +// Copyright (C) 2005, Francois Margot and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglRedSplit_H +#define CglRedSplit_H + +#include "CglCutGenerator.hpp" +#include "CglRedSplitParam.hpp" + +/** Gomory Reduce-and-Split Cut Generator Class; See method generateCuts(). + Based on the paper by K. Anderson, G. Cornuejols, Yanjun Li, + "Reduce-and-Split Cuts: Improving the Performance of Mixed Integer + Gomory Cuts", Management Science 51 (2005). */ + +class CglRedSplit : public CglCutGenerator { + + friend void CglRedSplitUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + /**@name generateCuts */ + //@{ + /** Generate Reduce-and-Split Mixed Integer Gomory cuts + for the model of the solver interface si. + + Insert the generated cuts into OsiCuts cs. + + Warning: This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau and + optimal basis inverse and makes assumptions on the way slack variables + are added by the solver. The Osi implementations for Clp and Cplex + verify these assumptions. + + When calling the generator, the solver interface si + must contain an optimized + problem and information related to the optimal basis must be available + through the OsiSolverInterface methods (si->optimalBasisIsAvailable() + must return 'true'). It is also essential that the integrality of + structural variable i can be obtained using si->isInteger(i). + + Reduce-and-Split cuts are variants of Gomory cuts: Starting from + the current optimal tableau, linear combinations of the rows of + the current optimal simplex tableau are used for generating Gomory + cuts. The choice of the linear combinations is driven by the objective + of reducing the coefficients of the non basic continuous variables + in the resulting row. + Note that this generator might not be able to generate cuts for some + solutions violating integrality constraints. + + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglRedSplitParam object. + void setParam(const CglRedSplitParam &source); + // Return the CglRedSplitParam object of the generator. + inline CglRedSplitParam getParam() const {return param;} + + // Compute entries of low_is_lub and up_is_lub. + void compute_is_lub(); + + // Compute entries of is_integer. + void compute_is_integer(); + + /// Set given_optsol to the given optimal solution given_sol. + /// If given_optsol is set using this method, + /// the code will stop as soon as + /// a generated cut is violated by the given solution; exclusively + /// for debugging purposes. + void set_given_optsol(const double *given_sol, const int card_sol); + + /// Print some of the data members + void print() const; + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + //@} + + /**@name Public Methods (soon to be obsolete)*/ + //@{ + //************************************************************ + // TO BE REMOVED + /** Set limit, the maximum number of non zero coefficients in generated cut; + Default: 50 */ + void setLimit(int limit); + /** Get value of limit */ + int getLimit() const; + + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.05 */ + void setAway(double value); + /// Get value of away + double getAway() const; + /** Set the value of LUB, value considered large for the absolute value of + a lower or upper bound on a variable; + Default: 1000 */ + void setLUB(double value); + /** Get the value of LUB */ + double getLUB() const; + + /** Set the value of EPS, epsilon for double computations; + Default: 1e-7 */ + void setEPS(double value); + /** Get the value of EPS */ + double getEPS() const; + + /** Set the value of EPS_COEFF, epsilon for values of coefficients; + Default: 1e-8 */ + void setEPS_COEFF(double value); + /** Get the value of EPS_COEFF */ + double getEPS_COEFF() const; + + /** Set the value of EPS_COEFF_LUB, epsilon for values of coefficients for + variables with absolute value of lower or upper bound larger than LUB; + Default: 1e-13 */ + void setEPS_COEFF_LUB(double value); + /** Get the value of EPS_COEFF_LUB */ + double getEPS_COEFF_LUB() const; + + /** Set the value of EPS_RELAX, value used for relaxing the right hand side + of each generated cut; + Default: 1e-8 */ + void setEPS_RELAX(double value); + /** Get the value of EPS_RELAX */ + double getEPS_RELAX() const; + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + void setNormIsZero(double value); + /** Get the value of normIsZero */ + double getNormIsZero() const; + + /** Set the value of minReduc, threshold for relative norm improvement for + performing a reduction; Default: 0.05 */ + void setMinReduc(double value); + /// Get the value of minReduc + double getMinReduc() const; + + /** Set the maximum allowed value for (mTab * mTab * CoinMax(mTab, nTab)) where + mTab is the number of rows used in the combinations and nTab is the + number of continuous non basic variables. The work of the generator is + proportional to (mTab * mTab * CoinMax(mTab, nTab)). Reducing the value of + maxTab makes the generator faster, but weaker. Default: 1e7. */ + void setMaxTab(double value); + /// Get the value of maxTab + double getMaxTab() const; + // END TO BE REMOVED + //************************************************************ + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplit(); + + /// Constructor with specified parameters + CglRedSplit(const CglRedSplitParam &RS_param); + + /// Copy constructor + CglRedSplit (const CglRedSplit &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglRedSplit & + operator=( + const CglRedSplit& rhs); + + /// Destructor + virtual + ~CglRedSplit (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglRedSplit members are properly set. + void generateCuts(OsiCuts & cs); + + /// Compute the fractional part of value, allowing for small error. + inline double rs_above_integer(double value); + + /// Perform row r1 of pi := row r1 of pi - step * row r2 of pi. + void update_pi_mat(int r1, int r2, int step); + + /// Perform row r1 of tab := row r1 of tab - step * row r2 of tab. + void update_redTab(int r1, int r2, int step); + + /// Find optimal integer step for changing row r1 by adding to it a + /// multiple of another row r2. + void find_step(int r1, int r2, int *step, + double *reduc, double *norm); + + /// Test if an ordered pair of rows yields a reduction. Perform the + /// reduction if it is acceptable. + int test_pair(int r1, int r2, double *norm); + + /// Reduce rows of contNonBasicTab. + void reduce_contNonBasicTab(); + + /// Generate a row of the current LP tableau. + void generate_row(int index_row, double *row); + + /// Generate a mixed integer Chvatal-Gomory cut, when all non basic + /// variables are non negative and at their lower bound. + int generate_cgcut(double *row, double *rhs); + + /// Generate a mixed integer Chvatal-Gomory cut, when all non basic + /// variables are non negative and at their lower bound (different formula) + int generate_cgcut_2(int basic_ind, double *row, double *rhs); + + /// Use multiples of the initial inequalities to cancel out the coefficients + /// of the slack variables. + void eliminate_slacks(double *row, + const double *elements, + const CoinBigIndex *start, + const int *indices, + const int *rowLength, + const double *rhs, double *rowrhs); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound. + void flip(double *row); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. + void unflip(double *row, double *rowrhs, double *slack_val); + + /// Return the scale factor for the row. + /// Compute max_coeff: maximum absolute value of the coefficients. + /// Compute min_coeff: minimum absolute value of the coefficients + /// larger than EPS_COEFF. + /// Return -1 if max_coeff < EPS_COEFF or if max_coeff/min_coeff > MAXDYN + /// or MAXDYN_LUB (depending if the row has a non zero coeff. for a variable + /// with large lower/upper bound) */. + double row_scale_factor(double *row); + + /// Generate the packed cut from the row representation. + int generate_packed_row(const double *xlp, double *row, + int *rowind, double *rowelem, + int *card_row, double & rhs); + + /// Check that the generated cuts do not cut a given optimal solution. + void check_optsol(const int calling_place, + const double *xlp, const double *slack_val, + const int do_flip); + + /// Check that the generated cuts do not cut a given optimal solution. + void check_optsol(const int calling_place, + const double *xlp, const double *slack_val, + const double *ck_row, const double ck_rhs, + const int cut_number, const int do_flip); + + // Check that two vectors are different. + bool rs_are_different_vectors(const int *vect1, + const int *vect2, + const int dim); + + // Check that two vectors are different. + bool rs_are_different_vectors(const double *vect1, + const double *vect2, + const int dim); + + // Check that two matrices are different. + bool rs_are_different_matrices(const CoinPackedMatrix *mat1, + const CoinPackedMatrix *mat2, + const int nmaj, + const int nmin); + //@} + + + // Private member data + +/**@name Private member data */ + + //@{ + + /// Object with CglRedSplitParam members. + CglRedSplitParam param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Number of integer basic structural variables that are fractional in the + /// current lp solution (at least param.away_ from being integer). + int card_intBasicVar_frac; + + /// Number of integer non basic structural variables in the + /// current lp solution. + int card_intNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current lp solution. + int card_contNonBasicVar; + + /// Number of non basic variables (structural or slack) at their + /// upper bound in the current lp solution. + int card_nonBasicAtUpper; + + /// Number of non basic variables (structural or slack) at their + /// lower bound in the current lp solution. + int card_nonBasicAtLower; + + /// Characteristic vector for integer basic structural variables + /// with non integer value in the current lp solution. + int *cv_intBasicVar_frac; + + /// List of integer structural basic variables + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar_frac; + + /// List of integer structural non basic variables. + int *intNonBasicVar; + + /// List of continuous non basic variables (structural or slack). + // slacks are considered continuous (no harm if this is not the case). + int *contNonBasicVar; + + /// List of non basic variables (structural or slack) at their + /// upper bound. + int *nonBasicAtUpper; + + /// List of non basic variables (structural or slack) at their lower + /// bound. + int *nonBasicAtLower; + + /// Number of rows in the reduced tableau (= card_intBasicVar_frac). + int mTab; + + /// Number of columns in the reduced tableau (= card_contNonBasicVar) + int nTab; + + /// Tableau of multipliers used to alter the rows used in generation. + /// Dimensions: mTab by mTab. Initially, pi_mat is the identity matrix. + int **pi_mat; + + /// Current tableau for continuous non basic variables (structural or slack). + /// Only rows used for generation. + /// Dimensions: mTab by nTab. + double **contNonBasicTab; + + /// Current tableau for integer non basic structural variables. + /// Only rows used for generation. + // Dimensions: mTab by card_intNonBasicVar. + double **intNonBasicTab; + + /// Right hand side of the tableau. + /// Only rows used for generation. + double *rhsTab ; + + /// Given optimal solution that should not be cut; only for debug. + const double *given_optsol; + + /// Number of entries in given_optsol. + int card_given_optsol; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + int *is_integer; + + /// Characteristic vector of the structural variables whose lower bound + /// in absolute value is larger than LUB. + int *low_is_lub; + + /// Characteristic vector of the structural variables whose upper bound + /// in absolute value is larger than LUB. + int *up_is_lub; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on column type. Reset by each call to generateCuts(). + const char *colType; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CglRedSplit class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglRedSplitUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2.hpp new file mode 100644 index 000000000..98e8f7312 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2.hpp @@ -0,0 +1,494 @@ +// Last edit: 04/03/10 +// +// Name: CglRedSplit2.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// Singapore +// email: nannicini@sutd.edu.sg +// based on CglRedSplit by Francois Margot +// Date: 03/09/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2010, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglRedSplit2_H +#define CglRedSplit2_H + +#include "CglCutGenerator.hpp" +#include "CglRedSplit2Param.hpp" +#include "CoinWarmStartBasis.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinTime.hpp" + +/** Reduce-and-Split Cut Generator Class; See method generateCuts(). + Based on the papers "Practical strategies for generating rank-1 + split cuts in mixed-integer linear programming" by G. Cornuejols + and G. Nannicini, published on Mathematical Programming + Computation, and "Combining Lift-and-Project and Reduce-and-Split" + by E. Balas, G. Cornuejols, T. Kis and G. Nannicini, published on + INFORMS Journal on Computing. Part of this code is based on + CglRedSplit by F. Margot. */ + +class CglRedSplit2 : public CglCutGenerator { + + friend void CglRedSplit2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); +public: + /**@name generateCuts */ + //@{ + /** Generate Reduce-and-Split Mixed Integer Gomory cuts + for the model of the solver interface si. + + Insert the generated cuts into OsiCuts cs. + + This generator currently works only with the Lp solvers Clp or + Cplex9.0 or higher. It requires access to the optimal tableau + and optimal basis inverse and makes assumptions on the way slack + variables are added by the solver. The Osi implementations for + Clp and Cplex verify these assumptions. + + When calling the generator, the solver interface si must contain + an optimized problem and information related to the optimal + basis must be available through the OsiSolverInterface methods + (si->optimalBasisIsAvailable() must return 'true'). It is also + essential that the integrality of structural variable i can be + obtained using si->isInteger(i). + + Reduce-and-Split cuts are a class of split cuts. We compute + linear combinations of the rows of the simplex tableau, trying + to reduce some of the coefficients on the nonbasic continuous + columns. We have a large number of heuristics to choose which + coefficients should be reduced, and by using which rows. The + paper explains everything in detail. + + Note that this generator can potentially generate a huge number + of cuts, depending on how it is parametered. Default parameters + should be good for most situations; if you want to go heavy on + split cuts, use more row selection strategies or a different + number of rows in the linear combinations. Again, look at the + paper for details. If you want to generate a small number of + cuts, default parameters are not the best choice. + + A combination of Reduce-and-Split with Lift & Project is + described in the paper "Combining Lift-and-Project and + Reduce-and-Split". The Reduce-and-Split code for the + implementation used in that paper is included here. + + This generator does not generate the same cuts as CglRedSplit, + therefore both generators can be used in conjunction. + + */ + + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + + // Generate the row multipliers computed by Reduce-and-Split from the + // given OsiSolverInterface. The multipliers are written in lambda; + // lambda should be of size nrow*maxNumMultipliers. We generate at most + // maxNumMultipliers m-vectors of row multipliers, and return the number + // of m-vectors that were generated. + // If the caller wants to know which variables are basic in each row + // (same order as lambda), basicVariables should be non-NULL (size nrow). + // This method can also generate the cuts corresponding to the multipliers + // returned; it suffices to pass non-NULL OsiCuts. + // This method is not needed by the typical user; however, it is useful + // in the context of generating Lift & Project cuts. + int generateMultipliers(const OsiSolverInterface& si, int* lambda, + int maxNumMultipliers, int* basicVariables = NULL, + OsiCuts* cs = NULL); + + // Try to improve a Lift & Project cut, by employing the + // Reduce-and-Split procedure. We start from a row of a L&P tableau, + // and generate a cut trying to reduce the coefficients on the + // nonbasic variables. Note that this L&P tableau will in general + // have nonbasic variables which are nonzero in the point that we + // want to cut off, so we should be careful. Arguments: + // OsiSolverInterface which contains the simplex tableau, initial + // row from which the cut is derived, row rhs, row number of the + // source row (if it is in the simplex tableau; otherwise, a + // negative number; needed to avoid using duplicate rows), point + // that we want to cut off (note: this is NOT a basic solution for + // the OsiSolverInterace!), list of variables which are basic in + // xbar but are nonbasic in the OsiSolverInterface. The computed cut + // is written in OsiRowCut* cs. Finally, if a starting disjunction + // is provided in the vector lambda (of size ncols, i.e. a + // disjunction on the structural variables), the disjunction is + // modified according to the cut which is produced. + int tiltLandPcut(const OsiSolverInterface* si, double* row, + double rowRhs, int rownumber, const double* xbar, + const int* newnonbasics, OsiRowCut* cs, int* lambda = NULL); + + //@} + + + /**@name Public Methods */ + //@{ + + // Set the parameters to the values of the given CglRedSplit2Param object. + void setParam(const CglRedSplit2Param &source); + // Return the CglRedSplit2Param object of the generator. + inline CglRedSplit2Param& getParam() {return param;} + + /// Print some of the data members; used for debugging + void print() const; + + /// Print the current simplex tableau + void printOptTab(OsiSolverInterface *solver) const; + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplit2(); + + /// Constructor with specified parameters + CglRedSplit2(const CglRedSplit2Param &RS_param); + + /// Copy constructor + CglRedSplit2(const CglRedSplit2 &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglRedSplit2 & operator=(const CglRedSplit2& rhs); + + /// Destructor + virtual ~CglRedSplit2 (); + + //@} + +private: + + // Private member methods + +/**@name Private member methods */ + + //@{ + + // Method generating the cuts after all CglRedSplit2 members are + // properly set. This does the actual work. Returns the number of + // generated cuts (or multipliers). + // Will generate cuts if cs != NULL, and will generate multipliers + // if lambda != NULL. + int generateCuts(OsiCuts* cs, int maxNumCuts, int* lambda = NULL); + + /// Compute the fractional part of value, allowing for small error. + inline double rs_above_integer(const double value) const; + + /// Fill workNonBasicTab, depending on the column selection strategy. + /// Accepts a list of variables indices that should be ignored; by + /// default, this list is empty (it is only used by Lift & Project). + /// The list ignore_list contains -1 as the last element. + /// Note that the implementation of the ignore_list is not very efficient + /// if the list is long, so it should be used only if its short. + void fill_workNonBasicTab(CglRedSplit2Param::ColumnSelectionStrategy + strategy, const int* ignore_list = NULL); + + /// Fill workNonBasicTab, alternate version for Lift & Project: also + /// reduces columns which are now nonbasic but are basic in xbar. + /// This function should be called only when CglRedSplit2 is used in + /// conjunction with CglLandP to generate L&P+RS cuts. + void fill_workNonBasicTab(const int* newnonbasics, const double* xbar, + CglRedSplit2Param::ColumnScalingStrategy scaling); + + /// Reduce rows of workNonBasicTab, i.e. compute integral linear + /// combinations of the rows in order to reduce row coefficients on + /// workNonBasicTab + void reduce_workNonBasicTab(int numRows, + CglRedSplit2Param::RowSelectionStrategy + rowSelectionStrategy, + int maxIterations); + + /// Generate a linear combination of the rows of the current LP + /// tableau, using the row multipliers stored in the matrix pi_mat + /// on the row of index index_row + void generate_row(int index_row, double *row); + + /// Generate a mixed integer Gomory cut, when all non basic + /// variables are non negative and at their lower bound. + int generate_cgcut(double *row, double *rhs); + + /// Use multiples of the initial inequalities to cancel out the coefficients + /// of the slack variables. + void eliminate_slacks(double *row, + const double *elements, + const CoinBigIndex *start, + const int *indices, + const int *rowLength, + const double *rhs, double *rowrhs); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound. + void flip(double *row); + + /// Change the sign of the coefficients of the continuous non basic + /// variables at their upper bound and do the translations restoring + /// the original bounds. Modify the right hand side + /// accordingly. + void unflip(double *row, double *rowrhs); + + /// Returns 1 if the row has acceptable max/min coeff ratio. + /// Compute max_coeff: maximum absolute value of the coefficients. + /// Compute min_coeff: minimum absolute value of the coefficients + /// larger than EPS_COEFF. + /// Return 0 if max_coeff/min_coeff > MAXDYN. + int check_dynamism(double *row); + + /// Generate the packed cut from the row representation. + int generate_packed_row(const double *xlp, double *row, + int *rowind, double *rowelem, + int *card_row, double & rhs); + + // Compute entries of is_integer. + void compute_is_integer(); + + // Check that two vectors are different. + bool rs_are_different_vectors(const int *vect1, + const int *vect2, + const int dim); + + // allocate matrix of integers + void rs_allocmatINT(int ***v, int m, int n); + // deallocate matrix of integers + void rs_deallocmatINT(int ***v, int m); + // allocate matrix of doubles + void rs_allocmatDBL(double ***v, int m, int n); + // deallocate matrix of doubles + void rs_deallocmatDBL(double ***v, int m); + // print a vector of integers + void rs_printvecINT(const char *vecstr, const int *x, int n) const; + // print a vector of doubles + void rs_printvecDBL(const char *vecstr, const double *x, int n) const; + // print a matrix of integers + void rs_printmatINT(const char *vecstr, const int * const *x, int m, int n) const; + // print a matrix of doubles + void rs_printmatDBL(const char *vecstr, const double * const *x, int m, int n) const; + // dot product + double rs_dotProd(const double *u, const double *v, int dim) const; + double rs_dotProd(const int *u, const double *v, int dim) const; + // From Numerical Recipes in C: LU decomposition + int ludcmp(double **a, int n, int *indx, double *d, double* vv) const; + // from Numerical Recipes in C: backward substitution + void lubksb(double **a, int n, int *indx, double *b) const; + + // Check if the linear combination given by listOfRows with given multipliers + // improves the norm of row #rowindex; note: multipliers are rounded! + // Returns the difference with respect to the old norm (if negative there is + // an improvement, if positive norm increases) + double compute_norm_change(double oldnorm, const int* listOfRows, + int numElemList, const double* multipliers) const; + + // Compute the list of rows that should be used to reduce row #rowIndex + int get_list_rows_reduction(int rowIndex, int numRowsReduction, + int* list, const double* norm, + CglRedSplit2Param::RowSelectionStrategy + rowSelectionStrategy) const; + + // Sorts the rows by increasing number of nonzeroes with respect to a given + // row (rowIndex), on the nonbasic variables (whichTab == 0 means only + // integer, whichTab == 1 means only workTab, whichTab == 2 means both). + // The array for sorting must be allocated (and deleted) by caller. + // Corresponds to BRS1 in the paper. + int sort_rows_by_nonzeroes(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Greedy variant of the previous function; slower but typically + // more effective. Corresponds to BRS2 in the paper. + int sort_rows_by_nonzeroes_greedy(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Sorts the rows by decreasing absolute value of the cosine of the + // angle with respect to a given row (rowIndex), on the nonbasic + // variables (whichTab == 0 means only integer, whichTab == 1 means + // only workTab, whichTab == 2 means both). The array for sorting + // must be allocated (and deleted) by caller. Very effective + // strategy in practice. Corresponds to BRS3 in the paper. + int sort_rows_by_cosine(struct sortElement* array, int rowIndex, + int maxRows, int whichTab) const; + + // Did we hit the time limit? + inline bool checkTime() const{ + if ((CoinCpuTime() - startTime) < param.getTimeLimit()){ + return true; + } + return false; + } + + //@} + + + // Private member data + + /**@name Private member data */ + + //@{ + + /// Object with CglRedSplit2Param members. + CglRedSplit2Param param; + + /// Number of rows ( = number of slack variables) in the current LP. + int nrow; + + /// Number of structural variables in the current LP. + int ncol; + + /// Number of rows which have been reduced + int numRedRows; + + /// Lower bounds for structural variables + const double *colLower; + + /// Upper bounds for structural variables + const double *colUpper; + + /// Lower bounds for constraints + const double *rowLower; + + /// Upper bounds for constraints + const double *rowUpper; + + /// Righ hand side for constraints (upper bound for ranged constraints). + const double *rowRhs; + + /// Reduced costs for columns + const double *reducedCost; + + /// Row price + const double *rowPrice; + + /// Objective coefficients + const double* objective; + + /// Number of integer basic structural variables + int card_intBasicVar; + + /// Number of integer basic structural variables that are fractional in the + /// current lp solution (at least param.away_ from being integer). + int card_intBasicVar_frac; + + /// Number of integer non basic structural variables in the + /// current lp solution. + int card_intNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current lp solution. + int card_contNonBasicVar; + + /// Number of continuous non basic variables (structural or slack) in the + /// current working set for coefficient reduction + int card_workNonBasicVar; + + /// Number of non basic variables (structural or slack) at their + /// upper bound in the current lp solution. + int card_nonBasicAtUpper; + + /// Number of non basic variables (structural or slack) at their + /// lower bound in the current lp solution. + int card_nonBasicAtLower; + + /// Characteristic vector for integer basic structural variables + int *cv_intBasicVar; + + /// Characteristic vector for integer basic structural variables + /// with non integer value in the current lp solution. + int *cv_intBasicVar_frac; + + /// Characteristic vector for rows of the tableau selected for reduction + /// with non integer value in the current lp solution + int *cv_fracRowsTab; + + /// List of integer structural basic variables + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar; + + /// List of integer structural basic variables with fractional value + /// (in order of pivot in selected rows for cut generation). + int *intBasicVar_frac; + + /// List of integer structural non basic variables. + int *intNonBasicVar; + + /// List of continuous non basic variables (structural or slack). + // slacks are considered continuous (no harm if this is not the case). + int *contNonBasicVar; + + /// List of non basic variables (structural or slack) at their + /// upper bound. + int *nonBasicAtUpper; + + /// List of non basic variables (structural or slack) at their lower + /// bound. + int *nonBasicAtLower; + + /// Number of rows in the reduced tableau (= card_intBasicVar). + int mTab; + + /// Number of columns in the reduced tableau (= card_contNonBasicVar) + int nTab; + + /// Tableau of multipliers used to alter the rows used in generation. + /// Dimensions: mTab by mTab. Initially, pi_mat is the identity matrix. + int **pi_mat; + + /// Simplex tableau for continuous non basic variables (structural or slack). + /// Only rows used for generation. + /// Dimensions: mTab by card_contNonBasicVar. + double **contNonBasicTab; + + /// Current tableau for continuous non basic variables (structural or slack). + /// Only columns used for coefficient reduction. + /// Dimensions: mTab by card_workNonBasicVar. + double **workNonBasicTab; + + /// Simplex tableau for integer non basic structural variables. + /// Only rows used for generation. + // Dimensions: mTab by card_intNonBasicVar. + double **intNonBasicTab; + + /// Right hand side of the tableau. + /// Only rows used for generation. + double *rhsTab; + + /// Norm of rows in workNonBasicTab; needed for faster computations + double *norm; + + /// Characteristic vectors of structural integer variables or continuous + /// variables currently fixed to integer values. + int *is_integer; + + /// Pointer on solver. Reset by each call to generateCuts(). + OsiSolverInterface *solver; + + /// Pointer on point to separate. Reset by each call to generateCuts(). + const double *xlp; + + /// Pointer on row activity. Reset by each call to generateCuts(). + const double *rowActivity; + + /// Pointer on matrix of coefficient ordered by rows. + /// Reset by each call to generateCuts(). + const CoinPackedMatrix *byRow; + + /// Time at which cut computations began. + /// Reset by each call to generateCuts(). + double startTime; + + //@} +}; + +//############################################################################# +/** A function that tests some of the methods in the CglRedSplit2 + class. The only reason for it not to be a member method is that + this way it doesn't have to be compiled into the library. And + that's a gain, because the library should be compiled with + optimization on, but this method should be compiled with + debugging. */ +void CglRedSplit2UnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2Param.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2Param.hpp new file mode 100644 index 000000000..369c67634 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplit2Param.hpp @@ -0,0 +1,495 @@ +// Name: CglRedSplit2Param.hpp +// Author: Giacomo Nannicini +// Singapore University of Technology and Design +// Singapore +// email: nannicini@sutd.edu.sg +// Date: 03/09/09 +//----------------------------------------------------------------------------- +// Copyright (C) 2010, Giacomo Nannicini and others. All Rights Reserved. + +#ifndef CglRedSplit2Param_H +#define CglRedSplit2Param_H + +#include "CglParam.hpp" +#include + + /**@name CglRedSplit2 Parameters */ + //@{ + + /** Class collecting parameters the Reduced-and-split cut generator. + + An important thing to note is that the cut generator allows for + the selection of a number of strategies that can be combined + together. By default, a selection that typically yields a good + compromise between speed and cut strenght is made. The selection + can be changed by resetting the default choices (see the + functions whose name starts with "reset") or by setting the + parameter use_default_strategies to false in the + constructors. After this, the chosen strategies can be added to + the list by using the functions whose name starts with + "add". All strategies will be combined together: if we choose 3 + row selection strategies, 2 column selection strategies, and 2 + possible numbers of rows, we end up with a total of 3*2*2 + combinations. + + For a detailed explanation of the parameters and their meaning, + see the paper by Cornuejols and Nannicini: "Practical strategies + for generating rank-1 split cuts in mixed-integer linear + programming", on Mathematical Programming Computation. + + Parameters of the generator are listed below. + + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - EPS_RELAX_ABS: Absolute relaxation of cut rhs. + - EPS_RELAX_REL: Relative relaxation of cut rhs. + - MAX_SUPP_ABS: Maximum cut support (absolute). + - MAX_SUPP_REL: Maximum cut support (relative): the formula to + compute maximum cut support is + MAX_SUPP_ABS + ncol*MAX_SUPP_REL. + - USE_INTSLACKS: Use integer slacks to generate cuts. (not implemented). + See method setUSE_INTSLACKS(). + - normIsZero: Norm of a vector is considered zero if smaller than + this value. See method setNormIsZero(). + - minNormReduction: a cut is generated if the new norm of the row on the + continuous nonbasics is reduced by at least + this factor (relative reduction). + - away: Look only at basic integer variables whose current value + is at least this value from being integer. See method setAway(). + - maxSumMultipliers: maximum sum (in absolute value) of row multipliers + - normalization: normalization factor for the norm of lambda in the + coefficient reduction algorithm (convex min problem) + - numRowsReduction: Maximum number of rows in the linear system for + norm reduction. + - columnSelectionStrategy: parameter to select which columns should be + used for coefficient reduction. + - rowSelectionStrategy: parameter to select which rows should be + used for coefficient reduction. + - timeLimit: Time limit (in seconds) for cut generation. + - maxNumCuts: Maximum number of cuts that can be returned at each pass; + we could generate more cuts than this number (see below) + - maxNumComputedCuts: Maximum number of cuts that can be computed + by the generator at each pass + - maxNonzeroesTab : Rows of the simplex tableau with more than + this number of nonzeroes will not be + considered for reduction. Only works if + RS_FAST_* are defined in CglRedSplit2. + - skipGomory: Skip traditional Gomory cuts, i.e. GMI cuts arising from + a single row of the tableau (instead of a combination). + Default is 1 (true), because we assume that they are + generated by a traditional Gomory generator anyway. + */ + //@} + +class CglRedSplit2Param : public CglParam { + +public: + /** Enumerations for parameters */ + + /** Row selection strategies; same names as in the paper */ + enum RowSelectionStrategy{ + /* Pick rows that introduce the fewest nonzeroes on integer nonbasics */ + RS1, + /* Pick rows that introduce the fewest nonzeroes on the set of working + continuous nonbasics */ + RS2, + /* Pick rows that introduce the fewest nonzeroes on both integer and + working continuous nonbasics */ + RS3, + /* Same as RS0 but with greedy algorithm */ + RS4, + /* Same as RS1 but with greedy algorithm */ + RS5, + /* Same as RS2 but with greedy algorithm */ + RS6, + /* Pick rows with smallest angle in the space of integer and working + continuous nonbasics */ + RS7, + /* Pick rows with smallest angle in the space of working + continuous nonbasics */ + RS8, + /* Use all strategies */ + RS_ALL, + /* Use best ones - that is, RS8 and RS7 */ + RS_BEST + }; + + /** Column selection strategies; again, look them up in the paper. */ + enum ColumnSelectionStrategy{ + /* C-3P */ + CS1, CS2, CS3, + /* C-5P */ + CS4, CS5, CS6, CS7, CS8, + /* I-2P-2/3 */ + CS9, CS10, + /* I-2P-4/5 */ + CS11, CS12, + /* I-2P-1/2 */ + CS13, CS14, + /* I-3P */ + CS15, CS16, CS17, + /* I-4P */ + CS18, CS19, CS20, CS21, + /* Use all strategies up to this point */ + CS_ALL, + /* Use best strategies (same effect as CS_ALL, because it turns out that + using all strategies is the best thing to do) */ + CS_BEST, + /* Optimize over all continuous nonbasic columns; this does not give + good results, but we use it for testing Lift & Project + RedSplit */ + CS_ALLCONT, + /* Lift & Project specific strategy: only select variables which + are nonbasic in the tableau but are basic in the point to cut + off. This strategy cannot be used outside L&P. It is not very + effective even with L&P, but is left here for testing.*/ + CS_LAP_NONBASICS + }; + + /** Scaling strategies for new nonbasic columns for Lift & Project; + * "factor" is the value of columnScalingBoundLAP_ */ + enum ColumnScalingStrategy{ + /* No scaling */ + SC_NONE, + /* Multiply by |xbar[i]| where xbar[i] is the value of the + corresponding component of the point that we want to cut off */ + SC_LINEAR, + /* Multiply by min(factor,|xbar[i]|) */ + SC_LINEAR_BOUNDED, + /* Multiply by min(factor,log(|xbar[i]|)) */ + SC_LOG_BOUNDED, + /* Multiply all new nonbasics by factor */ + SC_UNIFORM, + /* Multiply only nonzero coefficients by factor */ + SC_UNIFORM_NZ + }; + + /**@name Set/get methods */ + //@{ + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.005 */ + virtual void setAway(double value); + /// Get value of away + inline double getAway() const {return away_;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 0.0 */ + void setEPS_ELIM(double value); + /** Get the value of EPS_ELIM */ + double getEPS_ELIM() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(double eps_ra); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(double eps_rr); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-3 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + + /** Maximum absolute support of the cutting planes. Default: INT_MAX. + Aliases for consistency with our naming scheme. */ + inline void setMAX_SUPP_ABS(int value) {setMAX_SUPPORT(value);} + inline int getMAX_SUPP_ABS() const {return MAX_SUPPORT;} + + /** Maximum relative support of the cutting planes. Default: 0.0. + The maximum support is MAX_SUPP_ABS + MAX_SUPPREL*ncols. */ + inline void setMAX_SUPP_REL(double value); + inline double getMAX_SUPP_REL() const {return MAX_SUPP_REL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(int value); + /** Get the value of USE_INTSLACKS */ + inline int getUSE_INTSLACKS() const {return USE_INTSLACKS;} + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + virtual void setNormIsZero(double value); + /** Get the value of normIsZero */ + inline double getNormIsZero() const {return normIsZero_;} + + /** Set the value of minNormReduction; Default: 0.1 */ + virtual void setMinNormReduction(double value); + /** Get the value of normIsZero */ + inline double getMinNormReduction() const {return minNormReduction_;} + + /** Set the value of maxSumMultipliers; Default: 10 */ + virtual void setMaxSumMultipliers(int value); + /** Get the value of maxSumMultipliers */ + inline int getMaxSumMultipliers() const {return maxSumMultipliers_;} + + /** Set the value of normalization; Default: 0.0001 */ + virtual void setNormalization(double value); + /** Get the value of normalization */ + inline double getNormalization() const {return normalization_;} + + /** Set the value of numRowsReduction, max number of rows that are used + * for each row reduction step. In particular, the linear system will + * involve a numRowsReduction*numRowsReduction matrix */ + virtual void addNumRowsReduction(int value); + /// get the value + inline std::vector getNumRowsReduction() const {return numRowsReduction_;} + /// reset + inline void resetNumRowsReduction() {numRowsReduction_.clear();} + + /** Add the value of columnSelectionStrategy */ + virtual void addColumnSelectionStrategy(ColumnSelectionStrategy value); + /// get the value + inline std::vector getColumnSelectionStrategy() const {return columnSelectionStrategy_;} + /// reset + inline void resetColumnSelectionStrategy(){columnSelectionStrategy_.clear();} + + /** Set the value for rowSelectionStrategy, which changes the way we choose + * the rows for the reduction step */ + virtual void addRowSelectionStrategy(RowSelectionStrategy value); + /// get the value + inline std::vector getRowSelectionStrategy() const {return rowSelectionStrategy_;}; + /// reset + inline void resetRowSelectionStrategy() {rowSelectionStrategy_.clear();} + + /** Set the value of numRowsReductionLAP, max number of rows that are used + * for each row reduction step during Lift & Project. + * In particular, the linear system will involve a + * numRowsReduction*numRowsReduction matrix */ + virtual void addNumRowsReductionLAP(int value); + /// get the value + inline std::vector getNumRowsReductionLAP() const {return numRowsReductionLAP_;} + /// reset + inline void resetNumRowsReductionLAP() {numRowsReductionLAP_.clear();} + + /** Add the value of columnSelectionStrategyLAP */ + virtual void addColumnSelectionStrategyLAP(ColumnSelectionStrategy value); + /// get the value + inline std::vector getColumnSelectionStrategyLAP() const {return columnSelectionStrategyLAP_;} + /// reset + inline void resetColumnSelectionStrategyLAP(){columnSelectionStrategyLAP_.clear();} + + /** Set the value for rowSelectionStrategyLAP, which changes the way we + * choose the rows for the reduction step */ + virtual void addRowSelectionStrategyLAP(RowSelectionStrategy value); + /// get the value + inline std::vector getRowSelectionStrategyLAP() const {return rowSelectionStrategyLAP_;}; + /// reset + inline void resetRowSelectionStrategyLAP() {rowSelectionStrategyLAP_.clear();} + + /** Set the value for columnScalingStrategyLAP, which sets the way nonbasic + * columns that are basic in the fractional point to cut off are scaled */ + virtual void setColumnScalingStrategyLAP(ColumnScalingStrategy value); + /// get the value + inline ColumnScalingStrategy getColumnScalingStrategyLAP() const {return columnScalingStrategyLAP_; }; + + /** Set the value for the bound in the column scaling factor */ + virtual void setColumnScalingBoundLAP(double value); + /// get the value + inline double getColumnScalingBoundLAP() const {return columnScalingBoundLAP_;}; + + /** Set the value of the time limit for cut generation (in seconds) */ + virtual void setTimeLimit(double value); + /// get the value + inline double getTimeLimit() const {return timeLimit_;} + + /** Set the value for the maximum number of cuts that can be returned */ + virtual void setMaxNumCuts(int value); + /// get the value + inline int getMaxNumCuts() const {return maxNumCuts_;} + + /** Set the value for the maximum number of cuts that can be computed */ + virtual void setMaxNumComputedCuts(int value); + /// get the value + inline int getMaxNumComputedCuts() const {return maxNumComputedCuts_;} + + /** Set the value for the maximum number of nonzeroes in a row of + * the simplex tableau for the row to be considered */ + virtual void setMaxNonzeroesTab(int value); + /// get the value + inline int getMaxNonzeroesTab() const {return maxNonzeroesTab_;} + + /** Set the value of skipGomory: should we skip simple Gomory cuts, + * i.e. GMI cuts derived from a single row of the simple tableau? + * This is 1 (true) by default: we only generate cuts from linear + * combinations of at least two rows. */ + virtual void setSkipGomory(int value); + /// get the value + inline int getSkipGomory() const {return skipGomory_;} + + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor. If use_default_strategies is true, we add + /// to the list of strategies the default ones. If is false, the + /// list of strategies is left empty (must be populated before usage!). + CglRedSplit2Param(bool use_default_strategies = true, + double eps = 1e-12, + double eps_coeff = 1e-11, + double eps_elim = 0.0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-3, + int max_supp_abs = 1000, + double max_supp_rel = 0.1, + int use_int_slacks = 0, + double norm_zero = 1e-5, + double minNormReduction = 0.1, + int maxSumMultipliers = 10, + double normalization = 0.0001, + double away = 0.005, + double timeLimit = 60, + int maxNumCuts = 10000, + int maxNumComputedCuts = 10000, + int maxNonzeroesTab = 1000, + double columnScalingBoundLAP = 5.0, + int skipGomory = 1); + + /// Constructor from CglParam. If use_default_strategies is true, we + /// add to the list of strategies the default ones. If is false, the + /// list of strategies is left empty (must be populated before + /// usage!). + CglRedSplit2Param(const CglParam &source, + bool use_default_strategies = true, + double eps_elim = 0.0, + double eps_relax_abs = 1e-11, + double eps_relax_rel = 1e-13, + double max_dyn = 1e6, + double min_viol = 1e-3, + double max_supp_rel = 0.1, + int use_int_slacks = 0, + double norm_zero = 1e-5, + double minNormReduction = 0.1, + int maxSumMultipliers = 10, + double normalization = 0.0001, + double away = 0.005, + double timeLimit = 60, + int maxNumCuts = 10000, + int maxNumComputedCuts = 10000, + int maxNonzeroesTab = 1000, + double columnScalingBoundLAP = 5.0, + int skipGomory = 1); + + /// Copy constructor + CglRedSplit2Param(const CglRedSplit2Param &source); + + /// Clone + virtual CglRedSplit2Param* clone() const; + + /// Assignment operator + virtual CglRedSplit2Param& operator=(const CglRedSplit2Param &rhs); + + /// Destructor + virtual ~CglRedSplit2Param(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 0.0. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-11 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 1e-13 */ + double EPS_RELAX_REL; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e6. + double MAXDYN; + + /// Minimum violation for the current basic solution in a generated cut. + /// Default: 1e-3. + double MINVIOL; + + /// Maximum support - relative part of the formula + double MAX_SUPP_REL; + + /// Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. + int USE_INTSLACKS; + + /// Norm of a vector is considered zero if smaller than normIsZero; + /// Default: 1e-5. + double normIsZero_; + + /// Minimum reduction to accept a new row. + double minNormReduction_; + + /// Maximum sum of the vector of row multipliers to generate a cut + int maxSumMultipliers_; + + /// Normalization factor for the norm of lambda in the quadratic + /// minimization problem that is solved during the coefficient reduction step + double normalization_; + + /// Use row only if pivot variable should be integer but is more + /// than away_ from being integer. Default: 0.005 + double away_; + + /// Maximum number of rows to use for the reduction of a given row. + std::vector numRowsReduction_; + + /// Column selection method + std::vector columnSelectionStrategy_; + + /// Row selection method + std::vector rowSelectionStrategy_; + + /// Maximum number of rows to use for the reduction during Lift & Project + std::vector numRowsReductionLAP_; + + /// Column selection method for Lift & Project + std::vector columnSelectionStrategyLAP_; + + /// Row selection method for Lift & Project + std::vector rowSelectionStrategyLAP_; + + /// Column scaling strategy for the nonbasics columns that were basic in + /// the point that we want to cut off (Lift & Project only) + ColumnScalingStrategy columnScalingStrategyLAP_; + + /// Minimum value for column scaling (Lift & Project only) + double columnScalingBoundLAP_; + + /// Time limit + double timeLimit_; + + /// Maximum number of returned cuts + int maxNumCuts_; + + /// Maximum number of computed cuts + int maxNumComputedCuts_; + + /// Maximum number of nonzeroes in tableau row for reduction + int maxNonzeroesTab_; + + /// Skip simple Gomory cuts + int skipGomory_; + + //@} +}; + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplitParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplitParam.hpp new file mode 100644 index 000000000..a7cb88e31 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglRedSplitParam.hpp @@ -0,0 +1,272 @@ +// Name: CglRedSplitParam.hpp +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 11/24/06 +// +// $Id$ +//----------------------------------------------------------------------------- +// Copyright (C) 2006, Francois Margot and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglRedSplitParam_H +#define CglRedSplitParam_H + +#include "CglParam.hpp" + + + /**@name CglRedSplit Parameters */ + //@{ + + /** Class collecting parameters the Reduced-and-split cut generator. + + Parameters of the generator are listed below. Modifying the default + values for parameters other than the last four might result in + invalid cuts. + + - LUB: Value considered large for the absolute value of a lower or upper + bound on a variable. See method setLUB(). + - MAXDYN: Maximum ratio between largest and smallest non zero + coefficients in a cut. See method setMAXDYN(). + - MAXDYN_LUB: Maximum ratio between largest and smallest non zero + coefficients in a cut involving structural variables with + lower or upper bound in absolute value larger than LUB. + Should logically be larger or equal to MAXDYN. + See method setMAXDYN_LUB(). + - EPS_ELIM: Precision for deciding if a coefficient is zero when + eliminating slack variables. See method setEPS_ELIM(). + - EPS_COEFF_LUB: Precision for deciding if a coefficient of a + generated cut is zero when the corresponding + variable has a lower or upper bound larger than + LUB in absolute value. See method setEPS_COEFF_LUB(). + - MINVIOL: Minimum violation for the current basic solution in + a generated cut. See method setMINVIOL(). + - USE_INTSLACKS: Use integer slacks to generate cuts. (not implemented). + See method setUSE_INTSLACKS(). + - USE_CG2: Use alternative formula to generate a mixed integer Gomory + cut (see methods CglRedSPlit::generate_cgcut() + and CglRedSPlit::generate_cgcut_2()). See method setUSE_CG2(). + - normIsZero: Norm of a vector is considered zero if smaller than + this value. See method setNormIsZero(). + - minReduc: Reduction is performed only if the norm of the vector is + reduced by this fraction. See method setMinReduc(). + - away: Look only at basic integer variables whose current value + is at least this value from being integer. See method setAway(). + - maxTab: Controls the number of rows selected for the generation. See + method setMaxTab(). + */ + //@} + +class CglRedSplitParam : public CglParam { + +public: + + /**@name Set/get methods */ + //@{ + /** Set away, the minimum distance from being integer used for selecting + rows for cut generation; all rows whose pivot variable should be + integer but is more than away from integrality will be selected; + Default: 0.05 */ + virtual void setAway(const double value); + /// Get value of away + inline double getAway() const {return away_;} + + /** Set the value of LUB, value considered large for the absolute value of + a lower or upper bound on a variable; + Default: 1000 */ + virtual void setLUB(const double value); + /** Get the value of LUB */ + inline double getLUB() const {return LUB;} + + /** Set the value of EPS_ELIM, epsilon for values of coefficients when + eliminating slack variables; + Default: 1e-12 */ + void setEPS_ELIM(const double value); + /** Get the value of EPS_ELIM */ + double getEPS_ELIM() const {return EPS_ELIM;} + + /** Set EPS_RELAX_ABS */ + virtual void setEPS_RELAX_ABS(const double eps_ra); + /** Get value of EPS_RELAX_ABS */ + inline double getEPS_RELAX_ABS() const {return EPS_RELAX_ABS;} + + /** Set EPS_RELAX_REL */ + virtual void setEPS_RELAX_REL(const double eps_rr); + /** Get value of EPS_RELAX_REL */ + inline double getEPS_RELAX_REL() const {return EPS_RELAX_REL;} + + // Set the maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e8. + virtual void setMAXDYN(double value); + /** Get the value of MAXDYN */ + inline double getMAXDYN() const {return MAXDYN_LUB;} + + // Set the maximum ratio between largest and smallest non zero + // coefficient in a cut involving structural variables with + // lower or upper bound in absolute value larger than LUB. + // Should logically be larger or equal to MAXDYN. Default: 1e13. + virtual void setMAXDYN_LUB(double value); + /** Get the value of MAXDYN_LUB */ + inline double getMAXDYN_LUB() const {return MAXDYN_LUB;} + + /** Set the value of EPS_COEFF_LUB, epsilon for values of coefficients for + variables with absolute value of lower or upper bound larger than LUB; + Default: 1e-13 */ + virtual void setEPS_COEFF_LUB(const double value); + /** Get the value of EPS_COEFF_LUB */ + inline double getEPS_COEFF_LUB() const {return EPS_COEFF_LUB;} + + /** Set the value of MINVIOL, the minimum violation for the current + basic solution in a generated cut. Default: 1e-7 */ + virtual void setMINVIOL(double value); + /** Get the value of MINVIOL */ + inline double getMINVIOL() const {return MINVIOL;} + + /** Set the value of USE_INTSLACKS. Default: 0 */ + virtual void setUSE_INTSLACKS(int value); + /** Get the value of USE_INTSLACKS */ + inline int getUSE_INTSLACKS() const {return USE_INTSLACKS;} + + /** Set the value of USE_CG2. Default: 0 */ + virtual void setUSE_CG2(int value); + /** Get the value of USE_CG2 */ + inline int getUSE_CG2() const {return USE_CG2;} + + /** Set the value of normIsZero, the threshold for considering a norm to be + 0; Default: 1e-5 */ + virtual void setNormIsZero(const double value); + /** Get the value of normIsZero */ + inline double getNormIsZero() const {return normIsZero;} + + /** Set the value of minReduc, threshold for relative norm improvement for + performing a reduction; Default: 0.05 */ + virtual void setMinReduc(const double value); + /// Get the value of minReduc + inline double getMinReduc() const {return minReduc;} + + /** Set the maximum allowed value for (mTab * mTab * CoinMax(mTab, nTab)) where + mTab is the number of rows used in the combinations and nTab is the + number of continuous non basic variables. The work of the generator is + proportional to (mTab * mTab * CoinMax(mTab, nTab)). Reducing the value of + maxTab makes the generator faster, but weaker. Default: 1e7. */ + virtual void setMaxTab(const double value); + /// Get the value of maxTab + inline double getMaxTab() const {return maxTab_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglRedSplitParam(const double lub = 1000.0, + const double eps_elim = 1e-12, + const double eps_relax_abs = 1e-8, + const double eps_relax_rel = 0.0, + const double max_dyn = 1e8, + const double max_dyn_lub = 1e13, + const double eps_coeff_lub = 1e-13, + const double min_viol = 1e-7, + const int use_int_slacks = 0, + const int use_cg2 = 0, + const double norm_zero = 1e-5, + const double min_reduc = 0.05, + const double away = 0.05, + const double max_tab = 1e7); + + /// Constructor from CglParam + CglRedSplitParam(const CglParam &source, + const double lub = 1000.0, + const double eps_elim = 1e-12, + const double eps_relax_abs = 1e-8, + const double eps_relax_rel = 0.0, + const double max_dyn = 1e8, + const double max_dyn_lub = 1e13, + const double eps_coeff_lub = 1e-13, + const double min_viol = 1e-7, + const int use_int_slacks = 0, + const int use_cg2 = 0, + const double norm_zero = 1e-5, + const double min_reduc = 0.05, + const double away = 0.05, + const double max_tab = 1e7); + + /// Copy constructor + CglRedSplitParam(const CglRedSplitParam &source); + + /// Clone + virtual CglRedSplitParam* clone() const; + + /// Assignment operator + virtual CglRedSplitParam& operator=(const CglRedSplitParam &rhs); + + /// Destructor + virtual ~CglRedSplitParam(); + //@} + +protected: + + /**@name Parameters */ + //@{ + + /** Value considered large for the absolute value of lower or upper + bound on a variable. Default: 1000. */ + double LUB; + + /** Epsilon for value of coefficients when eliminating slack variables. + Default: 1e-12. */ + double EPS_ELIM; + + /** Value added to the right hand side of each generated cut to relax it. + Default: 1e-8 */ + double EPS_RELAX_ABS; + + /** For a generated cut with right hand side rhs_val, + EPS_RELAX_EPS * fabs(rhs_val) is used to relax the constraint. + Default: 0 */ + double EPS_RELAX_REL; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut. Default: 1e8. + double MAXDYN; + + // Maximum ratio between largest and smallest non zero + // coefficients in a cut involving structural variables with + // lower or upper bound in absolute value larger than LUB. + // Should logically be larger or equal to MAXDYN. Default: 1e13. + double MAXDYN_LUB; + + /// Epsilon for value of coefficients for variables with absolute value of + /// lower or upper bound larger than LUB. Default: 1e-13. + double EPS_COEFF_LUB; + + /// Minimum violation for the current basic solution in a generated cut. + /// Default: 1e-7. + double MINVIOL; + + /// Use integer slacks to generate cuts if USE_INTSLACKS = 1. Default: 0. + int USE_INTSLACKS; + + /// Use second way to generate a mixed integer Gomory cut + /// (see methods generate_cgcut()) and generate_cgcut_2()). Default: 0. + int USE_CG2; + + /// Norm of a vector is considered zero if smaller than normIsZero; + /// Default: 1e-5. + double normIsZero; + + /// Minimum reduction in percent that must be achieved by a potential + /// reduction step in order to be performed; Between 0 and 1, default: 0.05. + double minReduc; + + /// Use row only if pivot variable should be integer but is more + /// than away_ from being integer. + double away_; + + /// Maximum value for (mTab * mTab * CoinMax(mTab, nTab)). See method + /// setMaxTab(). + double maxTab_; + + //@} +}; + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglResidualCapacity.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglResidualCapacity.hpp new file mode 100644 index 000000000..1fb7e114f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglResidualCapacity.hpp @@ -0,0 +1,240 @@ +// LAST EDIT: +//----------------------------------------------------------------------------- +// Implementation of Residual Capacity Inequalities +// Francisco Barahona (barahon@us.ibm.com) +// +// date: May 18, 2006 +//----------------------------------------------------------------------------- +// Copyright (C) 2004, International Business Machines Corporation and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. + +#ifndef CglResidualCapacity_H +#define CglResidualCapacity_H + +#include +#include +//#include + +#include "CoinError.hpp" + +#include "CglCutGenerator.hpp" + +//============================================================================= + +#ifndef CGL_DEBUG +#define CGL_DEBUG 0 +#endif + +//============================================================================= + + + + +//============================================================================= + +/** Residual Capacity Inequalities Cut Generator Class + + References: + T Magnanti, P Mirchandani, R Vachani, + "The convex hull of two core capacitated network design problems," + Math Programming 60 (1993), 233-250. + + A Atamturk, D Rajan, + "On splittable and unsplittable flow capacitated network design + arc-set polyhedra," Math Programming 92 (2002), 315-333. **/ + +class CglResidualCapacity : public CglCutGenerator { + + friend void CglResidualCapacityUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +private: + //--------------------------------------------------------------------------- + // Enumeration constants that describe the various types of rows + enum RowType { + /** row of the type a_1 c_1 + + a_k c_k - d z_1 - - d z_p <= b, + where c_i are continuous variables and z_j are integer variables + */ + ROW_L, + /** row of the type -a_1 c_1 - - a_k c_k + d z_1 + + d z_p >= b, + where c_i are continuous variables and z_j are integer variables + */ + ROW_G, + /** equation that can be treated as ROW_L and ROW_G + */ + ROW_BOTH, + /** Other types of rows + */ + ROW_OTHER + }; + + +public: + /**@name Get and Set Parameters */ + //@{ + /// Set Epsilon + void setEpsilon(double value); + /// Get Epsilon + double getEpsilon() const; + /// Set Tolerance + void setTolerance(double value); + /// Get Tolerance + double getTolerance() const; + /// Set doPreproc + void setDoPreproc(int value); + /// Get doPreproc + bool getDoPreproc() const; + //@} + + /**@name Generate Cuts */ + //@{ + /** Generate Residual Capacity cuts for the model data + contained in si. The generated cuts are inserted + in the collection of cuts cs. + */ + virtual void generateCuts(const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + //--------------------------------------------------------------------------- + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglResidualCapacity (); + + /// Alternate Constructor + CglResidualCapacity ( const double tolerance ); + + /// Copy constructor + CglResidualCapacity ( + const CglResidualCapacity &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglResidualCapacity & + operator=( + const CglResidualCapacity& rhs); + + /// Destructor + virtual + ~CglResidualCapacity (); + /// This is to refresh preprocessing + virtual void refreshPrep(); + //@} + + + +private: + //-------------------------------------------------------------------------- + // Private member methods + + // Construct + void gutsOfConstruct ( const double tolerance); + + // Delete + void gutsOfDelete(); + + // Copy + void gutsOfCopy (const CglResidualCapacity& rhs); + + // Do preprocessing. + // It determines the type of each row. + // It may change sense and RHS for ranged rows + void resCapPreprocess(const OsiSolverInterface& si); + + // Determine the type of a given row. + RowType determineRowType(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, const char sense, + const double rhs, + const double* colLowerBound, + const double* colUpperBound) const; + // helps the function above + bool treatAsLessThan(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, + const double rhs, + const double* colLowerBound, + const double* colUpperBound) const; + + // Generate Residual Capacity cuts + void generateResCapCuts( const OsiSolverInterface& si, + const double* xlp, + const double* colUpperBound, + const double* colLowerBound, + const CoinPackedMatrix& matrixByRow, + const double* LHS, + const double* coefByRow, + const int* colInds, + const CoinBigIndex* rowStarts, + const int* rowLengths, + OsiCuts& cs ) const; + + + // Residual Capacity separation + bool resCapSeparation(const OsiSolverInterface& si, + const int rowLen, const int* ind, + const double* coef, + const double rhs, + const double *xlp, + const double* colUpperBound, + const double* colLowerBound, + OsiRowCut& resCapCut) const; + + + +private: + //--------------------------------------------------------------------------- + // Private member data + /** Tolerance used for numerical purposes, default value: 1.e-6 **/ + double EPSILON_; + /** If violation of a cut is greater that this number, + the cut is accepted, default value: 1.e-4 **/ + double TOLERANCE_; + /** Controls the preprocessing of the matrix to identify rows suitable for + cut generation.
    +
  • -1: preprocess according to solver settings; +
  • 0: Do preprocessing only if it has not yet been done; +
  • 1: Do preprocessing. +
+ Default value: -1 **/ + int doPreproc_; + // The number of rows of the problem. + int numRows_; + // The number columns of the problem. + int numCols_; + // Indicates whether preprocessing has been done. + bool doneInitPre_; + // Array with the row types of the rows in the model. + RowType* rowTypes_; + // The indices of the rows of the initial matrix + int* indRows_; + // Sense of rows (modified if ranges) + char * sense_; + // RHS of rows (modified if ranges) + double * RHS_; + // The number of rows of type ROW_L + int numRowL_; + // The indices of the rows of type ROW_L + int* indRowL_; + // The number of rows of type ROW_G + int numRowG_; + // The indices of the rows of type ROW_G + int* indRowG_; +}; + +//############################################################################# +/** A function that tests the methods in the CglResidualCapacity class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglResidualCapacityUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglSimpleRounding.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglSimpleRounding.hpp new file mode 100644 index 000000000..133ebaf1e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglSimpleRounding.hpp @@ -0,0 +1,174 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglSimpleRounding_H +#define CglSimpleRounding_H + +#include + +#include "CglCutGenerator.hpp" +#include "CoinPackedMatrix.hpp" + +/** Simple Rounding Cut Generator Class + + This class generates simple rounding cuts via the following method: + For each contraint, + attempt to derive a <= inequality in all integer variables + by netting out any continuous variables. + Divide the resulting integer inequality through by + the greatest common denomimator (gcd) of the lhs coefficients. + Round down the rhs. + + Warning: Use with careful attention to data precision. + + (Reference: Nemhauser and Wolsey, Integer and Combinatorial Optimization, 1988, pg 211.) +*/ + +class CglSimpleRounding : public CglCutGenerator { + friend void CglSimpleRoundingUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate simple rounding cuts for the model accessed through the solver interface. + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglSimpleRounding (); + + /// Copy constructor + CglSimpleRounding ( + const CglSimpleRounding &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglSimpleRounding & + operator=( + const CglSimpleRounding& rhs); + + /// Destructor + virtual + ~CglSimpleRounding (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + + /// Derive a <= inequality in integer variables from the rowIndex-th constraint + bool deriveAnIntegerRow( + const OsiSolverInterface & si, + int rowIndex, + const CoinShallowPackedVector & matrixRow, + CoinPackedVector & irow, + double & b, + bool * negative) const; + + + /** Given a vector of doubles, x, with size elements and a positive tolerance, + dataTol, this method returns the smallest power of 10 needed so that + x[i]*10**power "is integer" for all i=0,...,size-1. + + ** change of definition of dataTol so that it refers to original + data, not to scaled data as that seems to lead to problems. + + So if xScaled is x[i]*10**power and xInt is rounded(xScaled) + then fabs(xScaled-xInt) <= dataTol*10**power. This means that + dataTol should be smaller - say 1.0e-12 rather tahn 1.0e-8 + + Returns -number of times overflowed if the power is so big that it will + cause overflow (i.e. integer stored will be bigger than 2**31). + Test in cut generator. + */ + int power10ToMakeDoubleAnInt( + int size, // the length of the vector x + const double * x, + double dataTol ) const; // the precision of the data, i.e. the positive + // epsilon, which is equivalent to zero + + /**@name Greatest common denominators methods */ + //@{ + /// Returns the greatest common denominator of two positive integers, a and b. + inline int gcd(int a, int b) const; + + /** Returns the greatest common denominator of a vector of + positive integers, vi, of length n. + */ + inline int gcdv(int n, const int * const vi) const; + //@} + + //@} + + /**@name Private member data */ + //@{ + /// A value within an epsilon_ neighborhood of 0 is considered to be 0. + double epsilon_; + //@} +}; + + +//------------------------------------------------------------------- +// Returns the greatest common denominator of two +// positive integers, a and b, found using Euclid's algorithm +//------------------------------------------------------------------- +int +CglSimpleRounding::gcd(int a, int b) const +{ + if(a > b) { + // Swap a and b + int temp = a; + a = b; + b = temp; + } + int remainder = b % a; + if (remainder == 0) return a; + else return gcd(remainder,a); +} + +//------------------------------------------------------------------- +// Returns the greatest common denominator of a vector of +// positive integers, vi, of length n. +//------------------------------------------------------------------- +int +CglSimpleRounding::gcdv(int n, const int* const vi) const +{ + if (n==0) + abort(); + + if (n==1) + return vi[0]; + + int retval=gcd(vi[0], vi[1]); + for (int i=2; i + +#include "CglCutGenerator.hpp" + +class CoinWarmStartBasis; +class CglTreeProbingInfo; +/** Stored Cut Generator Class */ +class CglStored : public CglCutGenerator { + +public: + /**@name Generate Cuts */ + //@{ + /** Generate Mixed Integer Stored cuts for the model of the + solver interface, si. + + Insert the generated cuts into OsiCut, cs. + + This generator just looks at previously stored cuts + and inserts any that are violated by enough + */ + virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Change criterion on whether to include cut. + Violations of more than this will be added to current cut list + (default 1.0e-5) */ + //@{ + /// Set + inline void setRequiredViolation(double value) + { + requiredViolation_ = value; + } + /// Get + inline double getRequiredViolation() const + { + return requiredViolation_; + } + /// Takes over ownership of probing info + inline void setProbingInfo(CglTreeProbingInfo *info) + { + probingInfo_ = info; + } + //@} + + /**@name Cut stuff */ + //@{ + /// Add cuts + void addCut(const OsiCuts &cs); + /// Add a row cut + void addCut(const OsiRowCut &cut); + /// Add a row cut from a packed vector + void addCut(double lb, double ub, const CoinPackedVector &vector); + /// Add a row cut from elements + void addCut(double lb, double ub, int size, const int *colIndices, const double *elements); + inline int sizeRowCuts() const + { + return cuts_.sizeRowCuts(); + } + const OsiRowCut *rowCutPointer(int index) const + { + return cuts_.rowCutPtr(index); + } + /// Save stuff + void saveStuff(double bestObjective, const double *bestSolution, + const double *lower, const double *upper); + /// Best solution (or NULL) + inline const double *bestSolution() const + { + return bestSolution_; + } + /// Best objective + double bestObjective() const; + /// Tight lower bounds + const double *tightLower() const + { + return bounds_; + } + /// Tight upper bounds + const double *tightUpper() const + { + return bounds_ + numberColumns_; + } + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglStored(int numberColumns = 0); + + /// Copy constructor + CglStored(const CglStored &rhs); + + /// Constructor from file + CglStored(const char *fileName); + + /// Clone + virtual CglCutGenerator *clone() const; + + /// Assignment operator + CglStored & + operator=(const CglStored &rhs); + + /// Destructor + virtual ~CglStored(); + //@} + +protected: + // Protected member methods + + // Protected member data + + /**@name Protected member data */ + //@{ + /// Only add if more than this requiredViolation + double requiredViolation_; + /// Pointer to probing information + CglTreeProbingInfo *probingInfo_; + /// Cuts + OsiCuts cuts_; + /// Number of columns in model + int numberColumns_; + /// Best solution (objective at end) + double *bestSolution_; + /// Tight bounds + double *bounds_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTreeInfo.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTreeInfo.hpp new file mode 100644 index 000000000..738ea665e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTreeInfo.hpp @@ -0,0 +1,216 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglTreeInfo_H +#define CglTreeInfo_H + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" +#include "CoinHelperFunctions.hpp" +class CglStored; +/** Information about where the cut generator is invoked from. */ + +class CglTreeInfo { +public: + /// The level of the search tree node + int level; + /** How many times the cut generator was already invoked in this search tree + node */ + int pass; + /** The number of rows in the original formulation. Some generators may not + want to consider already generated rows when generating new ones. */ + int formulation_rows; + /** Options + 1 - treat costed integers as important + 2 - switch off some stuff as variables semi-integer + 4 - set global cut flag if at root node + 8 - set global cut flag if at root node and first pass + 16 - set global cut flag and make cuts globally valid + 32 - last round of cuts did nothing - maybe be more aggressive + 64 - in preprocessing stage + 128 - looks like solution + 256 - want alternate cuts + 512 - in sub tree (i.e. parent model) + 1024 - in must call again mode or after everything mode + */ + int options; + /// Set true if in tree (to avoid ambiguity at first branch) + bool inTree; + /** nonzero if called from child of main model + 1 if heuristic run + 2 if doing full search + */ + int hasParent; + /// parent solver + OsiSolverInterface *parentSolver; + /// Original columns (if preprocessed) + int *originalColumns; + /** Replacement array. Before Branch and Cut it may be beneficial to strengthen rows + rather than adding cuts. If this array is not NULL then the cut generator can + place a pointer to the stronger cut in this array which is number of rows in size. + + A null (i.e. zero elements and free rhs) cut indicates that the row is useless + and can be removed. + + The calling function can then replace those rows. + */ + OsiRowCut **strengthenRow; + /// Optional pointer to thread specific random number generator + CoinThreadRandom *randomNumberGenerator; + /// Default constructor + CglTreeInfo(); + + /// Copy constructor + CglTreeInfo( + const CglTreeInfo &); + /// Clone + virtual CglTreeInfo *clone() const; + + /// Assignment operator + CglTreeInfo & + operator=( + const CglTreeInfo &rhs); + + /// Destructor + virtual ~CglTreeInfo(); + /// Take action if cut generator can fix a variable (toValue -1 for down, +1 for up) + virtual bool fixes(int, int, int, bool) { return false; } + /** Initalizes fixing arrays etc - returns >0 if we want to save info + 0 if we don't and -1 if is to be used */ + virtual int initializeFixing(const OsiSolverInterface *) { return 0; } +}; + +/** Derived class to pick up probing info. */ +typedef struct { + //unsigned int oneFixed:1; // nonzero if variable to 1 fixes all + //unsigned int sequence:31; // variable (in matrix) (but also see cliqueRow_) + unsigned int fixes; +} CliqueEntry; + +class CglTreeProbingInfo : public CglTreeInfo { +public: + /// Default constructor + CglTreeProbingInfo(); + /// Constructor from model + CglTreeProbingInfo(const OsiSolverInterface *model); + + /// Copy constructor + CglTreeProbingInfo( + const CglTreeProbingInfo &); + /// Clone + virtual CglTreeInfo *clone() const; + + /// Assignment operator + CglTreeProbingInfo & + operator=( + const CglTreeProbingInfo &rhs); + + /// Destructor + virtual ~CglTreeProbingInfo(); + OsiSolverInterface *analyze(const OsiSolverInterface &si, int createSolver = 0, + int numberExtraCliques = 0, const CoinBigIndex *starts = NULL, + const CliqueEntry *entries = NULL, const char *type = NULL); + /** Take action if cut generator can fix a variable + (toValue -1 for down, +1 for up) + Returns true if still room, false if not */ + virtual bool fixes(int variable, int toValue, int fixedVariable, bool fixedToLower); + /** Initalizes fixing arrays etc - returns >0 if we want to save info + 0 if we don't and -1 if is to be used */ + virtual int initializeFixing(const OsiSolverInterface *model); + /// Fix entries in a solver using implications + int fixColumns(OsiSolverInterface &si) const; + /// Fix entries in a solver using implications for one variable + int fixColumns(int iColumn, int value, OsiSolverInterface &si) const; + /// Packs down entries + int packDown(); + /// Generate cuts from implications + void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, + const CglTreeInfo info) const; + /// Entries for fixing variables + inline CliqueEntry *fixEntries() + { + convert(); + return fixEntry_; + } + /// Starts of integer variable going to zero + inline int *toZero() + { + convert(); + return toZero_; + } + /// Starts of integer variable going to one + inline int *toOne() + { + convert(); + return toOne_; + } + /// List of 0-1 integer variables + inline int *integerVariable() const + { + return integerVariable_; + } + /// Backward look up + inline int *backward() const + { + return backward_; + } + /// Number of variables + inline int numberVariables() const + { + return numberVariables_; + } + /// Number of 0-1 variables + inline int numberIntegers() const + { + return numberIntegers_; + } + +private: + /// Converts to ordered + void convert(); + +protected: + /// Entries for fixing variables + CliqueEntry *fixEntry_; + /// Starts of integer variable going to zero + int *toZero_; + /// Starts of integer variable going to one + int *toOne_; + /// List of 0-1 integer variables + int *integerVariable_; + /// Backward look up + int *backward_; + /// Entries for fixing variable when collecting + int *fixingEntry_; + /// Number of variables + int numberVariables_; + /// Number of 0-1 variables + int numberIntegers_; + /// Maximum number in fixEntry_ + int maximumEntries_; + /// Number entries in fixingEntry_ (and fixEntry_) or -2 if correct style + int numberEntries_; +}; +inline int sequenceInCliqueEntry(const CliqueEntry &cEntry) +{ + return cEntry.fixes & 0x7fffffff; +} +inline void setSequenceInCliqueEntry(CliqueEntry &cEntry, int sequence) +{ + cEntry.fixes = sequence | (cEntry.fixes & 0x80000000); +} +inline bool oneFixesInCliqueEntry(const CliqueEntry &cEntry) +{ + return (cEntry.fixes & 0x80000000) != 0; +} +inline void setOneFixesInCliqueEntry(CliqueEntry &cEntry, bool oneFixes) +{ + cEntry.fixes = (oneFixes ? 0x80000000 : 0) | (cEntry.fixes & 0x7fffffff); +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTwomir.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTwomir.hpp new file mode 100644 index 000000000..95f45f038 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglTwomir.hpp @@ -0,0 +1,562 @@ +// $Id$ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CglTwomir_H +#define CglTwomir_H +#include + +#include "CglCutGenerator.hpp" +#include "CoinFactorization.hpp" + +typedef struct +{ + + int nz; /* current length of arrays index[] and coeff[] */ + int max_nz; /* max length of arrays index[] and coeff[] */ + double *coeff; /* coefficient of each variable in the constraint */ + int *index; /* index of the variable (value in 0 ... nrow+ncol) */ + double rhs; /* rhs of the constraint */ + char sense; /* ?? is it necessary */ + +} DGG_constraint_t; + +typedef struct{ + int n; + DGG_constraint_t **c; + int *ctype; + double *alpha; +} DGG_list_t; + +/******************** BASIS INFORMATION ADTs **********************************/ +typedef struct{ + int q_min; + int q_max; + int t_min; + int t_max; + int a_max; + int max_elements; +} cutParams; + +typedef struct +{ + double gomory_threshold; /* factional variable must be this away from int */ + int ncol, /* number of columns in LP */ + nrow, /* number of constaints in LP */ + ninteger; /* number of integer variables in LP */ + + int nbasic_col, /* number of basic columns in the LP */ + nbasic_row; /* number of basic rows in the LP */ + + /* the following arrays are all of size (ncol+nrow) */ + int *info; /* description of each variable (see below) */ + double *lb; /* specifies the lower bound (if any) of each variable */ + double *ub; /* specifies the upper bound (if any) of each variable */ + double *x; /* current solution */ + double *rc; /* current reduced cost */ + double *opt_x; + + cutParams cparams; +} DGG_data_t; + +/* the following macros allow us to decode the info of the DGG_data + type. The encoding is as follows, + bit 1 : if the variable is basic or not (non-basic). + bit 2 : if the variable is integer or or not (rational). + bit 3 : if the variable is structural or not (artifical). + bit 4 : if the variable is non-basic and at its upper bound + (else if non-basic at lower bound). */ + +#define DGG_isBasic(data,idx) ((data->info[idx])&1) +#define DGG_isInteger(data,idx) ((data->info[idx] >> 1)&1) +#define DGG_isStructural(data,idx) ((data->info[idx] >> 2)&1) +#define DGG_isEqualityConstraint(data,idx) ((data->info[idx] >> 3)&1) +#define DGG_isNonBasicAtUB(data,idx) ((data->info[idx] >> 4)&1) +#define DGG_isNonBasicAtLB(data,idx) ((data->info[idx] >> 5)&1) +#define DGG_isConstraintBoundedAbove(data,idx) ((data->info[idx] >> 6)&1) +#define DGG_isConstraintBoundedBelow(data,idx) ((data->info[idx] >> 7)&1) + +#define DGG_setIsBasic(data,idx) ((data->info[idx]) |= 1) +#define DGG_setIsInteger(data,idx) ((data->info[idx]) |= (1<<1)) +#define DGG_setIsStructural(data,idx) ((data->info[idx]) |= (1<<2)) +#define DGG_setEqualityConstraint(data,idx) ((data->info[idx]) |= (1<<3)) +#define DGG_setIsNonBasicAtUB(data,idx) ((data->info[idx]) |= (1<<4)) +#define DGG_setIsNonBasicAtLB(data,idx) ((data->info[idx]) |= (1<<5)) +#define DGG_setIsConstraintBoundedAbove(data,idx) ((data->info[idx]) |= (1<<6)) +#define DGG_setIsConstraintBoundedBelow(data,idx) ((data->info[idx]) |= (1<<7)) + +class CoinWarmStartBasis; +/** Twostep MIR Cut Generator Class */ +class CglTwomir : public CglCutGenerator { + + friend void CglTwomirUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + + +public: + + /// Problem name + std::string probname_; + + /**@name Generate Cuts */ + //@{ + /** Generate Two step MIR cuts either from the tableau rows or from the + formulation rows + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + /// Return true if needs optimal basis to do cuts (will return true) + virtual bool needsOptimalBasis() const; + + /**@name Change criterion on which scalings to use (default = 1,1,1,1) */ + //@{ + /// Set + void setMirScale (int tmin, int tmax) {t_min_ = tmin; t_max_ = tmax;} + void setTwomirScale (int qmin, int qmax) {q_min_ = qmin; q_max_ = qmax;} + void setAMax (int a) {a_max_ = a;} + void setMaxElements (int n) {max_elements_ = n;} + void setMaxElementsRoot (int n) {max_elements_root_ = n;} + void setCutTypes (bool mir, bool twomir, bool tab, bool form) + { do_mir_ = mir; do_2mir_ = twomir; do_tab_ = tab; do_form_ = form;} + void setFormulationRows (int n) {form_nrows_ = n;} + + /// Get + int getTmin() const {return t_min_;} + int getTmax() const {return t_max_;} + int getQmin() const {return q_min_;} + int getQmax() const {return q_max_;} + int getAmax() const {return a_max_;} + int getMaxElements() const {return max_elements_;} + int getMaxElementsRoot() const {return max_elements_root_;} + int getIfMir() const { return do_mir_;} + int getIfTwomir() const { return do_2mir_;} + int getIfTableau() const { return do_tab_;} + int getIfFormulation() const { return do_form_;} + //@} + + /**@name Change criterion on which variables to look at. All ones + more than "away" away from integrality will be investigated + (default 0.05) */ + //@{ + /// Set away + void setAway(double value); + /// Get away + double getAway() const; + /// Set away at root + void setAwayAtRoot(double value); + /// Get away at root + double getAwayAtRoot() const; + /// Return maximum length of cut in tree + virtual int maximumLengthOfCutInTree() const + { return max_elements_;} + //@} + + /**@name Change way TwoMir works */ + //@{ + /// Pass in a copy of original solver (clone it) + void passInOriginalSolver(OsiSolverInterface * solver); + /// Returns original solver + inline OsiSolverInterface * originalSolver() const + { return originalSolver_;} + /// Set type - 0 normal, 1 add original matrix one, 2 replace + inline void setTwomirType(int type) + { twomirType_=type;} + /// Return type + inline int twomirType() const + { return twomirType_;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglTwomir (); + + /// Copy constructor + CglTwomir (const CglTwomir &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglTwomir & operator=(const CglTwomir& rhs); + + /// Destructor + virtual ~CglTwomir (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any inforamtion + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + // Private member data + /**@name Private member data */ + //@{ + /// Threadsafe random number generator + CoinThreadRandom randomNumberGenerator_; + /// Original solver + OsiSolverInterface * originalSolver_; + /// Only investigate if more than this away from integrality + double away_; + /// Only investigate if more than this away from integrality (at root) + double awayAtRoot_; + /// Type - 0 normal, 1 add original matrix one, 2 replace + int twomirType_; + bool do_mir_; + bool do_2mir_; + bool do_tab_; + bool do_form_; + + int t_min_; /// t_min - first value of t to use for tMIR inequalities + int t_max_; /// t_max - last value of t to use for tMIR inequalities + int q_min_; /// q_min - first value of t to use for 2-Step tMIR inequalities + int q_max_; /// q_max - last value of t to use for 2-Step tMIR inequalities + int a_max_; /// a_max - maximum value of bhat/alpha + int max_elements_; /// Maximum number of elements in cut + int max_elements_root_; /// Maximum number of elements in cut at root + int form_nrows_; //number of rows on which formulation cuts will be generated + //@} +}; + +//############################################################################# + +/* +#include +#include +#include +#include +#include +#include +#include +*/ + +/******************** DEBUG DEFINITIONS ***************************************/ + +#define DGG_DEBUG_DGG 1 +#define DGG_TRACE_ERRORS 0 +#define DGG_DISPLAY 0 +#define DGG_AUTO_CHECK_CUT_OFF_OPTIMAL 1 + +/******************** CONFIGURATION DEFAULTS **********************************/ + +#define DGG_DEFAULT_METHOD 2 +#define DGG_DEFAULT_TMIN 1 +#define DGG_DEFAULT_TMAX 1 +#define DGG_DEFAULT_TAUMIN 2 +#define DGG_DEFAULT_TAUMAX 6 +#define DGG_DEFAULT_MAX_CUTS 500 +#define DGG_DEFAULT_IMPROVEMENT_THRESH 0.001 +#define DGG_DEFAULT_NBELOW_THRESH INT_MAX +#define DGG_DEFAULT_NROOT_ROUNDS 2 +#define DGG_DEFAULT_NEGATIVE_SCALED_TWOSTEPS 0 +#define DGG_DEFAULT_ALPHA_RULE 0 +#define DGG_DEFAULT_CUT_INC 250 +#define DGG_DEFAULT_CUT_FORM 0 +#define DGG_DEFAULT_NICEFY 0 +#define DGG_DEFAULT_ONLY_DELAYED 0 +#define DGG_DEFAULT_DELAYED_FREQ 9999999 +#define DGG_DEFAULT_LPROWS_FREQ 9999999 +#define DGG_DEFAULT_WHICH_FORMULATION_CUTS 2 + +/******************** SOLVER CONFIGURATION DEFINITIONS ************************/ + +#define DGG_OSI 0 +#define DGG_CPX 1 +#define DGG_QSO 2 + +/* determines the solver to be used */ +#define DGG_SOLVER DGG_OSI + +/* adds checking routines to make sure solver works as expected */ +#define DGG_DEBUG_SOLVER 0 + +/* turn off screen output from solver */ +#define DGG_SOLVER_SCREEN_FLAG 0 + +/******************** CUT DEFINITIONS *****************************************/ + +/* internal names for cut types */ +#define DGG_TMIR_CUT 1 +#define DGG_2STEP_CUT 2 + +/* internal names for alpha-selection rules */ +#define DGG_ALPHA_MIN_SUM 0 +#define DGG_ALPHA_RANDOM_01 1 +#define DGG_ALPHA_RANDOM_COEFF 2 +#define DGG_ALPHA_ALL 3 +#define DGG_ALPHA_MAX_STEEP 5 + +/******************** PRECISION & NUMERICAL ISSUES DEFINITIONS ****************/ + +/* how steep a cut must be before adding it to the lp */ +#define DGG_MIN_STEEPNESS 1.0e-4 +#define DGG_MAX_L2NORM 1.0e7 + +/* 0 = min steepness, 1 = max norm */ +#define DGG_NORM_CRITERIA 1 + +/* used to define how fractional a basic-integer variable must be + before choosing to use it to generate a TMIR cut on. + OSI's default is 1.0e-7 */ +#define DGG_GOMORY_THRESH 0.005 + +#define DGG_RHS_THRESH 0.005 + +/* used for comparing variables to their upper bounds. + OSI's default is 1.0e-7. + We set it to 1.0e6 because e-7 seems too sensitive. + In fact, with e-7 the problem dsbmip.mps complains. */ +#define DGG_BOUND_THRESH 1.0e-6 + +/* used for comparing the lhs (activity) value of a tableau row + with the rhs. This is only used for debugging purposes. */ +#define DGG_EQUALITY_THRESH 1.0e-5 + +/* used for comparing a variable's lower bound to 0.0 + and determining if we need to shift the variable */ +#define DGG_SHIFT_THRESH 1.0e-6 + +/* used for determing how far from an integer is still an integer. + This value is used for comparing coefficients to integers. + OSI's default is 1.0e-10. */ +#define DGG_INTEGRALITY_THRESH 1.0e-10 + +/* the min value that a coeff can have in the tableau row + before being set to zero. */ +#define CBC_CHECK_CUT +#ifndef CBC_CHECK_CUT +#define DGG_MIN_TABLEAU_COEFFICIENT 1.0e-8 +#else +#define DGG_MIN_TABLEAU_COEFFICIENT 1.0e-12 +#endif + +/* smallest value rho is allowed to have for a simple 2-step MIR + (ie: not an extended two-step MIR) */ +#define DGG_MIN_RHO 1.0e-7 +#define DGG_MIN_ALPHA 1.0e-7 + +/* when a slack is null: used to check if a cut is satisfied or not. */ +#define DGG_NULL_SLACK 1.0e-5 + +/* nicefy constants */ +#define DGG_NICEFY_MIN_ABSVALUE 1.0e-13 +#define DGG_NICEFY_MIN_FIX 1.0e-7 +#define DGG_NICEFY_MAX_PADDING 1.0e-6 +#define DGG_NICEFY_MAX_RATIO 1.0e9 + + +/******************** ERROR-CATCHING MACROS ***********************************/ +#if DGG_TRACE_ERRORS > 0 + +#define __DGG_PRINT_LOC__(F) fprintf(((F==0)?stdout:F), " in %s (%s:%d)\n", __func__, __FILE__, __LINE__) + +#define DGG_THROW(A,REST...) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + return (A);} + +#define DGG_IF_EXIT(A,B,REST...) {\ + if(A) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + exit(B);}} + +#define DGG_CHECKRVAL(A,B) {\ + if(A) {\ + __DGG_PRINT_LOC__(stdout); \ + return B; } } + +#define DGG_CHECKRVAL1(A,B) {\ + if(A) {\ + __DGG_PRINT_LOC__(stdout); \ + rval = B; goto CLEANUP; } } + +#define DGG_WARNING(A, REST...) {\ + if(A) {\ + fprintf(stdout, ##REST); \ + __DGG_PRINT_LOC__(stdout); \ + }} + +#define DGG_TEST(A,B,REST...) {\ + if(A) DGG_THROW(B,##REST) } + +#define DGG_TEST2(A,B,C,REST) {DGG_TEST(A,B,C,REST) } +#define DGG_TEST3(A,B,C,D,REST) {DGG_TEST(A,B,C,D,REST) } + +#else + +#define DGG_IF_EXIT(A,B,REST) {if(A) {fprintf(stdout, REST);exit(B);}} + +#define DGG_THROW(A,B) return(A) + +#define DGG_CHECKRVAL(A,B) { if(A) return(B); } +#define DGG_CHECKRVAL1(A,B){ if(A) { rval = B; goto CLEANUP; } } + +#define DGG_TEST(A,B,REST) { if(A) return(B);} +#define DGG_TEST2(A,B,REST,C) { DGG_TEST(A,B,REST) } +#define DGG_TEST3(A,B,REST,C,D) { DGG_TEST(A,B,REST) } + +#endif + +/******************** SIMPLE MACROS AND FUNCTIONS *****************************/ + +#define DGG_MIN(a,b) ( (ab)?a:b ) +#define KREM(vht,alpha,tau) (DGG_MIN( ceil(vht / alpha), tau ) - 1) +#define LMIN(vht, d, bht) (DGG_MIN( floor(d*bht/bht), d)) +#define ABOV(v) (v - floor(v)) +#define QINT(vht,bht,tau) ( (int)floor( (vht*(tau-1))/bht ) ) +#define V2I(bht,tau,i) ( ((i+1)*bht / tau) ) + +int DGG_is_even(double vht, double bht, int tau, int q); +double frac_part(double value); +int DGG_is_a_multiple_of_b(double a, double b); + + +/* free function for DGG_data_t. Frees internal arrays and data structure */ +int DGG_freeData( DGG_data_t *data ); + +/******************** CONSTRAINT ADTs *****************************************/ +DGG_constraint_t* DGG_newConstraint(int max_arrays); +void DGG_freeConstraint(DGG_constraint_t *c); +DGG_constraint_t *DGG_copyConstraint(DGG_constraint_t *c); +void DGG_scaleConstraint(DGG_constraint_t *c, int t); + +/******************** CONFIGURATION *******************************************/ +void DGG_list_init (DGG_list_t *l); +int DGG_list_addcut (DGG_list_t *l, DGG_constraint_t *cut, int ctype, double alpha); +void DGG_list_delcut (DGG_list_t *l, int i); +void DGG_list_free(DGG_list_t *l); + +/******************* SOLVER SPECIFIC METHODS **********************************/ +DGG_data_t *DGG_getData(const void *solver_ptr); + +/******************* CONSTRAINT MANIPULATION **********************************/ + +/* DGG_transformConstraint: manipulates a constraint in the following way: + +packs everything in output + +1 - variables at their upper bounds are substituted for their +complements. This is done by adjusting the coefficients and +the right hand side (simple substitution). + +2 - variables with non-zero lower bounds are shifted. */ + +int DGG_transformConstraint( DGG_data_t *data, + double **x_out, + double **rc_out, + char **isint_out, + DGG_constraint_t *constraint ); + +/* DGG_unTransformConstraint : + +1 - Undoes step (1) of DGG_transformConstraint +2 - Undoes step (2) of DGG_transformConstraint */ + +int DGG_unTransformConstraint( DGG_data_t *data, + DGG_constraint_t *constraint ); + +/* substitutes each slack variable by the structural variables which + define it. This function, hence, changes the constraint 'cut'. */ + +int DGG_substituteSlacks( const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t *cut ); + +int DGG_nicefyConstraint( const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t *cut); + +/******************* CUT GENERATION *******************************************/ +int DGG_getFormulaConstraint( int row_idx, + const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t* row ); + +int DGG_getTableauConstraint( int index, + const void *solver_ptr, + DGG_data_t *data, + DGG_constraint_t* tabrow, + const int * colIsBasic, + const int * rowIsBasic, + CoinFactorization & factorization, + int mode ); + +DGG_constraint_t* DGG_getSlackExpression(const void *solver_ptr, DGG_data_t* data, int row_index); + + int DGG_generateTabRowCuts( DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr ); + + int DGG_generateFormulationCuts( DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr, + int nrows, + CoinThreadRandom & generator); + + + int DGG_generateFormulationCutsFromBase( DGG_constraint_t *base, + double slack, + DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr, + CoinThreadRandom & generator); + + int DGG_generateCutsFromBase( DGG_constraint_t *base, + DGG_list_t *list, + DGG_data_t *data, + const void *solver_ptr ); + +int DGG_buildMir( char *isint, + DGG_constraint_t *base, + DGG_constraint_t **cut_out ); + +int DGG_build2step( double alpha, + char *isint, + DGG_constraint_t *base, + DGG_constraint_t **cut_out ); + + int DGG_addMirToList ( DGG_constraint_t *base, + char *isint, + double *x, + DGG_list_t *list, + DGG_data_t *data, + DGG_constraint_t *orig_base ); + + int DGG_add2stepToList ( DGG_constraint_t *base, + char *isint, + double *x, + double *rc, + DGG_list_t *list, + DGG_data_t *data, + DGG_constraint_t *orig_base ); + +/******************* CUT INFORMATION ******************************************/ + +double DGG_cutLHS(DGG_constraint_t *c, double *x); +int DGG_isCutDesirable(DGG_constraint_t *c, DGG_data_t *d); + +/******************* TEST / DEBUGGING ROUTINES ********************************/ + +int DGG_isConstraintViolated(DGG_data_t *d, DGG_constraint_t *c); + +int DGG_isBaseTrivial(DGG_data_t *d, DGG_constraint_t* c); +int DGG_is2stepValid(double alpha, double bht); + +int DGG_cutsOffPoint(double *x, DGG_constraint_t *cut); + +//############################################################################# +/** A function that tests the methods in the CglTwomir class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglTwomirUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir); + + +#endif + + diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglZeroHalf.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglZeroHalf.hpp new file mode 100644 index 000000000..6cc278812 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CglZeroHalf.hpp @@ -0,0 +1,133 @@ +// $Id$ +// Copyright (C) 2010, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +#ifndef CglZeroHalf_H +#define CglZeroHalf_H + +#include + +#include "CglCutGenerator.hpp" +#include "CoinPackedMatrix.hpp" +#include "Cgl012cut.hpp" + +/** Zero Half Cut Generator Class + + This class generates zero half cuts via the following method: + + See - + +G. Andreello, A. Caprara, M. Fischetti, + “Embedding Cuts in a Branch and Cut Framework: a Computational Study + with {0,1/2}-Cuts”, INFORMS Journal on Computing 19(2), 229-238, 2007. + +*/ + +class CglZeroHalf : public CglCutGenerator { + friend void CglZeroHalfUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +public: + + /**@name Generate Cuts */ + //@{ + /** Generate zero half cuts for the model accessed through the solver interface. + Insert generated cuts into the cut set cs. + */ + virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs, + const CglTreeInfo info = CglTreeInfo()); + //@} + + /**@name Sets and Gets */ + //@{ + /// Get flags + inline int getFlags() const + { return flags_;} + /// Set flags + inline void setFlags(int value) + { flags_ = value;} + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + CglZeroHalf (); + + /// Copy constructor + CglZeroHalf ( + const CglZeroHalf &); + + /// Clone + virtual CglCutGenerator * clone() const; + + /// Assignment operator + CglZeroHalf & + operator=( + const CglZeroHalf& rhs); + + /// Destructor + virtual + ~CglZeroHalf (); + /// Create C++ lines to get to current state + virtual std::string generateCpp( FILE * fp); + /// This can be used to refresh any information + virtual void refreshSolver(OsiSolverInterface * solver); + //@} + +private: + + // Private member methods + + /**@name Private methods */ + //@{ + //@} + + + /**@name Private member data */ + //@{ + /// number of rows in the ILP matrix + int mr_; + /// number of columns in the ILP matrix + int mc_; + /// number of nonzero's in the ILP matrix + int mnz_; + /// starting position of each row in arrays mtind and mtval + int *mtbeg_; + /// number of entries of each row in arrays mtind and mtval + int *mtcnt_; + /// column indices of the nonzero entries of the ILP matrix + int *mtind_; + /// values of the nonzero entries of the ILP matrix + int *mtval_; + /// lower bounds on the variables + int *vlb_; + /// upper bounds on the variables + int *vub_; + /// right hand sides of the constraints + int *mrhs_; + /// senses of the constraints: 'L', 'G' or 'E' + char *msense_; + /// Cgl012Cut object to make thread safe + Cgl012Cut cutInfo_; + /** Flags + 1 bit - global cuts + */ + int flags_; + //@} +}; +/// A simple Dijkstra shortest path - make better later +#ifndef CGL_NEW_SHORT +void cglShortestPath(cgl_graph * graph, int source, int maximumLength); +#else +void cglShortestPath(auxiliary_graph * graph, int source, int maximumLength); +#endif +//############################################################################# +/** A function that tests the methods in the CglZeroHalf class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CglZeroHalfUnitTest(const OsiSolverInterface * siP, + const std::string mpdDir ); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpAmplObjective.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpAmplObjective.hpp new file mode 100644 index 000000000..9f547f646 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpAmplObjective.hpp @@ -0,0 +1,113 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpAmplObjective_H +#define ClpAmplObjective_H + +#include "ClpObjective.hpp" +#include "CoinPackedMatrix.hpp" + +//############################################################################# + +/** Ampl Objective Class + +*/ + +class ClpAmplObjective : public ClpObjective { + +public: + ///@name Stuff + //@{ + + /** Returns gradient. If Ampl then solution may be NULL, + also returns an offset (to be added to current one) + If refresh is false then uses last solution + Uses model for scaling + includeLinear 0 - no, 1 as is, 2 as feasible + */ + virtual double *gradient(const ClpSimplex *model, + const double *solution, double &offset, bool refresh, + int includeLinear = 2); + /// Resize objective + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex *model, double *region, + bool useFeasibleCosts); + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex *model, + const double *solution, + const double *change, + double maximumTheta, + double ¤tObj, + double &predictedObj, + double &thetaObj); + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex *model, const double *solution) const; + virtual void resize(int newNumberColumns); + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale objective + virtual void reallyScale(const double *columnScale); + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char *which); + + /// Say we have new primal solution - so may need to recompute + virtual void newXValues(); + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpAmplObjective(); + + /// Constructor from ampl info + ClpAmplObjective(void *amplInfo); + + /** Copy constructor . + */ + ClpAmplObjective(const ClpAmplObjective &rhs); + + /// Assignment operator + ClpAmplObjective &operator=(const ClpAmplObjective &rhs); + + /// Destructor + virtual ~ClpAmplObjective(); + + /// Clone + virtual ClpObjective *clone() const; + + //@} + ///@name Gets and sets + //@{ + /// Linear objective + double *linearObjective() const; + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Saved offset + double offset_; + /// Ampl info + void *amplObjective_; + /// Objective + double *objective_; + /// Gradient + double *gradient_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyBase.hpp new file mode 100644 index 000000000..e7b029bf4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyBase.hpp @@ -0,0 +1,321 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpCholeskyBase_H +#define ClpCholeskyBase_H + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" +//#define CLP_LONG_CHOLESKY 0 +#ifndef CLP_LONG_CHOLESKY +#define CLP_LONG_CHOLESKY 0 +#endif +/* valid combinations are + CLP_LONG_CHOLESKY 0 and COIN_LONG_WORK 0 + CLP_LONG_CHOLESKY 1 and COIN_LONG_WORK 1 + CLP_LONG_CHOLESKY 2 and COIN_LONG_WORK 1 +*/ +#if COIN_LONG_WORK == 0 +#if CLP_LONG_CHOLESKY > 0 +#define CHOLESKY_BAD_COMBINATION +#endif +#else +#if CLP_LONG_CHOLESKY == 0 +#define CHOLESKY_BAD_COMBINATION +#endif +#endif +#ifdef CHOLESKY_BAD_COMBINATION +#warning("Bad combination of CLP_LONG_CHOLESKY and COIN_BIG_DOUBLE/COIN_LONG_WORK"); +"Bad combination of CLP_LONG_CHOLESKY and COIN_LONG_WORK" +#endif +#if CLP_LONG_CHOLESKY > 1 + typedef long double longDouble; +#define CHOL_SMALL_VALUE 1.0e-15 +#elif CLP_LONG_CHOLESKY == 1 +typedef double longDouble; +#define CHOL_SMALL_VALUE 1.0e-11 +#else +typedef double longDouble; +#define CHOL_SMALL_VALUE 1.0e-11 +#endif +class ClpInterior; +class ClpCholeskyDense; +class ClpMatrixBase; + +/** Base class for Clp Cholesky factorization + Will do better factorization. very crude ordering + + Derived classes may be using more sophisticated methods +*/ + +class ClpCholeskyBase { + +public: + /**@name Virtual methods that the derived classes may provide */ + //@{ + /** Orders rows and saves pointer to matrix.and model. + returns non-zero if not enough memory. + You can use preOrder to set up ADAT + If using default symbolic etc then must set sizeFactor_ to + size of input matrix to order (and to symbolic). + Also just permute_ and permuteInverse_ should be created */ + virtual int order(ClpInterior *model); + /** Does Symbolic factorization given permutation. + This is called immediately after order. If user provides this then + user must provide factorize and solve. Otherwise the default factorization is used + returns non-zero if not enough memory */ + virtual int symbolic(); + /** Factorize - filling in rowsDropped and returning number dropped. + If return code negative then out of memory */ + virtual int factorize(const CoinWorkDouble *diagonal, int *rowsDropped); + /** Uses factorization to solve. */ + virtual void solve(CoinWorkDouble *region); + /** Uses factorization to solve. - given as if KKT. + region1 is rows+columns, region2 is rows */ + virtual void solveKKT(CoinWorkDouble *region1, CoinWorkDouble *region2, const CoinWorkDouble *diagonal, + CoinWorkDouble diagonalScaleFactor); + +private: + /// AMD ordering + int orderAMD(); + +public: + //@} + + /**@name Gets */ + //@{ + /// status. Returns status + inline int status() const + { + return status_; + } + /// numberRowsDropped. Number of rows gone + inline int numberRowsDropped() const + { + return numberRowsDropped_; + } + /// reset numberRowsDropped and rowsDropped. + void resetRowsDropped(); + /// rowsDropped - which rows are gone + inline char *rowsDropped() const + { + return rowsDropped_; + } + /// choleskyCondition. + inline double choleskyCondition() const + { + return choleskyCondition_; + } + /// goDense i.e. use dense factoriaztion if > this (default 0.7). + inline double goDense() const + { + return goDense_; + } + /// goDense i.e. use dense factoriaztion if > this (default 0.7). + inline void setGoDense(double value) + { + goDense_ = value; + } + /// rank. Returns rank + inline int rank() const + { + return numberRows_ - numberRowsDropped_; + } + /// Return number of rows + inline int numberRows() const + { + return numberRows_; + } + /// Return size + inline int size() const + { + return sizeFactor_; + } + /// Return sparseFactor + inline longDouble *sparseFactor() const + { + return sparseFactor_; + } + /// Return diagonal + inline longDouble *diagonal() const + { + return diagonal_; + } + /// Return workDouble + inline longDouble *workDouble() const + { + return workDouble_; + } + /// If KKT on + inline bool kkt() const + { + return doKKT_; + } + /// Set KKT + inline void setKKT(bool yesNo) + { + doKKT_ = yesNo; + } + /// Set integer parameter + inline void setIntegerParameter(int i, int value) + { + integerParameters_[i] = value; + } + /// get integer parameter + inline int getIntegerParameter(int i) + { + return integerParameters_[i]; + } + /// Set double parameter + inline void setDoubleParameter(int i, double value) + { + doubleParameters_[i] = value; + } + /// get double parameter + inline double getDoubleParameter(int i) + { + return doubleParameters_[i]; + } + //@} + +public: + /**@name Constructors, destructor + */ + //@{ + /** Constructor which has dense columns activated. + Default is off. */ + ClpCholeskyBase(int denseThreshold = -1); + /** Destructor (has to be public) */ + virtual ~ClpCholeskyBase(); + /// Copy + ClpCholeskyBase(const ClpCholeskyBase &); + /// Assignment + ClpCholeskyBase &operator=(const ClpCholeskyBase &); + //@} + //@{ + ///@name Other + /// Clone + virtual ClpCholeskyBase *clone() const; + + /// Returns type + inline int type() const + { + if (doKKT_) + return 100; + else + return type_; + } + +protected: + /// Sets type + inline void setType(int type) + { + type_ = type; + } + /// model. + inline void setModel(ClpInterior *model) + { + model_ = model; + } + //@} + + /**@name Symbolic, factor and solve */ + //@{ + /** Symbolic1 - works out size without clever stuff. + Uses upper triangular as much easier. + Returns size + */ + int symbolic1(const int *Astart, const int *Arow); + /** Symbolic2 - Fills in indices + Uses lower triangular so can do cliques etc + */ + void symbolic2(const int *Astart, const int *Arow); + /** Factorize - filling in rowsDropped and returning number dropped + in integerParam. + */ + void factorizePart2(int *rowsDropped); + /** solve - 1 just first half, 2 just second half - 3 both. + If 1 and 2 then diagonal has sqrt of inverse otherwise inverse + */ + void solve(CoinWorkDouble *region, int type); + /// Forms ADAT - returns nonzero if not enough memory + int preOrder(bool lowerTriangular, bool includeDiagonal, bool doKKT); + /// Updates dense part (broken out for profiling) + void updateDense(longDouble *d, /*longDouble * work,*/ int *first); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// type (may be useful) if > 20 do KKT + int type_; + /// Doing full KKT (only used if default symbolic and factorization) + bool doKKT_; + /// Go dense at this fraction + double goDense_; + /// choleskyCondition. + double choleskyCondition_; + /// model. + ClpInterior *model_; + /// numberTrials. Number of trials before rejection + int numberTrials_; + /// numberRows. Number of Rows in factorization + int numberRows_; + /// status. Status of factorization + int status_; + /// rowsDropped + char *rowsDropped_; + /// permute inverse. + int *permuteInverse_; + /// main permute. + int *permute_; + /// numberRowsDropped. Number of rows gone + int numberRowsDropped_; + /// sparseFactor. + longDouble *sparseFactor_; + /// choleskyStart - element starts + int *choleskyStart_; + /// choleskyRow (can be shorter than sparsefactor) + int *choleskyRow_; + /// Index starts + int *indexStart_; + /// Diagonal + longDouble *diagonal_; + /// double work array + longDouble *workDouble_; + /// link array + int *link_; + // Integer work array + int *workInteger_; + // Clique information + int *clique_; + /// sizeFactor. + int sizeFactor_; + /// Size of index array + int sizeIndex_; + /// First dense row + int firstDense_; + /// integerParameters + int integerParameters_[64]; + /// doubleParameters; + double doubleParameters_[64]; + /// Row copy of matrix + ClpMatrixBase *rowCopy_; + /// Dense indicators + char *whichDense_; + /// Dense columns (updated) + longDouble *denseColumn_; + /// Dense cholesky + ClpCholeskyDense *dense_; + /// Dense threshold (for taking out of Cholesky) + int denseThreshold_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyDense.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyDense.hpp new file mode 100644 index 000000000..35aaeb48d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyDense.hpp @@ -0,0 +1,157 @@ +/* $Id$ */ +/* + Copyright (C) 2003, International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef ClpCholeskyDense_H +#define ClpCholeskyDense_H + +#include "ClpCholeskyBase.hpp" +class ClpMatrixBase; + +class ClpCholeskyDense : public ClpCholeskyBase { + +public: + /**@name Virtual methods that the derived classes provides */ + /**@{*/ + /** Orders rows and saves pointer to matrix.and model. + Returns non-zero if not enough memory */ + virtual int order(ClpInterior *model); + /** Does Symbolic factorization given permutation. + This is called immediately after order. If user provides this then + user must provide factorize and solve. Otherwise the default factorization is used + returns non-zero if not enough memory */ + virtual int symbolic(); + /** Factorize - filling in rowsDropped and returning number dropped. + If return code negative then out of memory */ + virtual int factorize(const CoinWorkDouble *diagonal, int *rowsDropped); + /** Uses factorization to solve. */ + virtual void solve(CoinWorkDouble *region); + /**@}*/ + + /**@name Non virtual methods for ClpCholeskyDense */ + /**@{*/ + /** Reserves space. + If factor not NULL then just uses passed space + Returns non-zero if not enough memory */ + int reserveSpace(const ClpCholeskyBase *factor, int numberRows); + /** Returns space needed */ + int space(int numberRows) const; + /** part 2 of Factorize - filling in rowsDropped */ + void factorizePart2(int *rowsDropped); + /** part 2 of Factorize - filling in rowsDropped - blocked */ + void factorizePart3(int *rowsDropped); + /** Forward part of solve */ + void solveF1(longDouble *a, int n, CoinWorkDouble *region); + void solveF2(longDouble *a, int n, CoinWorkDouble *region, CoinWorkDouble *region2); + /** Backward part of solve */ + void solveB1(longDouble *a, int n, CoinWorkDouble *region); + void solveB2(longDouble *a, int n, CoinWorkDouble *region, CoinWorkDouble *region2); + int bNumber(const longDouble *array, int &, int &); + /** A */ + inline longDouble *aMatrix() const + { + return sparseFactor_; + } + /** Diagonal */ + inline longDouble *diagonal() const + { + return diagonal_; + } + /**@}*/ + + /**@name Constructors, destructor */ + /**@{*/ + /** Default constructor. */ + ClpCholeskyDense(); + /** Destructor */ + virtual ~ClpCholeskyDense(); + /** Copy */ + ClpCholeskyDense(const ClpCholeskyDense &); + /** Assignment */ + ClpCholeskyDense &operator=(const ClpCholeskyDense &); + /** Clone */ + virtual ClpCholeskyBase *clone() const; + /**@}*/ + +private: + /**@name Data members */ + /**@{*/ + /** Just borrowing space */ + bool borrowSpace_; + /**@}*/ +}; + +/* structure for C */ +typedef struct { + longDouble *diagonal_; + longDouble *a; + longDouble *work; + int *rowsDropped; + double doubleParameters_[1]; /* corresponds to 10 */ + int integerParameters_[2]; /* corresponds to 34, nThreads */ + int n; + int numberBlocks; +} ClpCholeskyDenseC; + +extern "C" { +void ClpCholeskySpawn(void *); +} +/**Non leaf recursive factor */ +void ClpCholeskyCfactor(ClpCholeskyDenseC *thisStruct, + longDouble *a, int n, int numberBlocks, + longDouble *diagonal, longDouble *work, int *rowsDropped); + +/**Non leaf recursive triangle rectangle update */ +void ClpCholeskyCtriRec(ClpCholeskyDenseC *thisStruct, + longDouble *aTri, int nThis, + longDouble *aUnder, longDouble *diagonal, + longDouble *work, + int nLeft, int iBlock, int jBlock, + int numberBlocks); +/**Non leaf recursive rectangle triangle update */ +void ClpCholeskyCrecTri(ClpCholeskyDenseC *thisStruct, + longDouble *aUnder, int nTri, int nDo, + int iBlock, int jBlock, longDouble *aTri, + longDouble *diagonal, longDouble *work, + int numberBlocks); +/** Non leaf recursive rectangle rectangle update, + nUnder is number of rows in iBlock, + nUnderK is number of rows in kBlock +*/ +void ClpCholeskyCrecRec(ClpCholeskyDenseC *thisStruct, + longDouble *above, int nUnder, int nUnderK, + int nDo, longDouble *aUnder, longDouble *aOther, + longDouble *work, + int iBlock, int jBlock, + int numberBlocks); +/**Leaf recursive factor */ +void ClpCholeskyCfactorLeaf(ClpCholeskyDenseC *thisStruct, + longDouble *a, int n, + longDouble *diagonal, longDouble *work, + int *rowsDropped); +/**Leaf recursive triangle rectangle update */ +void ClpCholeskyCtriRecLeaf(/*ClpCholeskyDenseC * thisStruct,*/ + longDouble *aTri, longDouble *aUnder, + longDouble *diagonal, longDouble *work, + int nUnder); +/**Leaf recursive rectangle triangle update */ +void ClpCholeskyCrecTriLeaf(/*ClpCholeskyDenseC * thisStruct, */ + longDouble *aUnder, longDouble *aTri, + /*longDouble * diagonal,*/ longDouble *work, int nUnder); +/** Leaf recursive rectangle rectangle update, + nUnder is number of rows in iBlock, + nUnderK is number of rows in kBlock +*/ +void ClpCholeskyCrecRecLeaf(/*ClpCholeskyDenseC * thisStruct, */ + const longDouble *COIN_RESTRICT above, + const longDouble *COIN_RESTRICT aUnder, + longDouble *COIN_RESTRICT aOther, + const longDouble *COIN_RESTRICT work, + int nUnder); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyPardiso.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyPardiso.hpp new file mode 100644 index 000000000..1aa39671a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpCholeskyPardiso.hpp @@ -0,0 +1,67 @@ +/* $Id: ClpCholeskyPardiso.hpp 1665 2011-01-04 17:55:54Z lou $ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpCholeskyPardiso_H +#define ClpCholeskyPardiso_H +#ifdef PARDISO_BARRIER + +#include "ClpCholeskyBase.hpp" +#include "mkl_pardiso.h" +#include "mkl_types.h" + +class ClpMatrixBase; +class ClpCholeskyDense; + +/** Pardiso class for Clp Cholesky factorization + +*/ +class ClpCholeskyPardiso : public ClpCholeskyBase { + +public: + /**@name Virtual methods that the derived classes provides */ + //@{ + /** Orders rows and saves pointer to matrix.and model. + Returns non-zero if not enough memory */ + virtual int order(ClpInterior *model); + /** Does Symbolic factorization given permutation. + This is called immediately after order. If user provides this then + user must provide factorize and solve. Otherwise the default factorization is used + returns non-zero if not enough memory */ + virtual int symbolic(); + /** Factorize - filling in rowsDropped and returning number dropped. + If return code negative then out of memory */ + virtual int factorize(const double *diagonal, int *rowsDropped); + /** Uses factorization to solve. */ + virtual void solve(double *region); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Constructor which has dense columns activated. + Default is off. */ + ClpCholeskyPardiso(int denseThreshold = -1); + /** Destructor */ + virtual ~ClpCholeskyPardiso(); + // Copy + ClpCholeskyPardiso(const ClpCholeskyPardiso &); + // Assignment + ClpCholeskyPardiso &operator=(const ClpCholeskyPardiso &); + /// Clone + virtual ClpCholeskyBase *clone() const; + //@} + +private: + /**@name Data members */ + //@{ + int lastNumberDropped_; + //MKL_INT iparm_[64]; + //@} +}; + +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConfig.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConfig.h new file mode 100644 index 000000000..e391cc914 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConfig.h @@ -0,0 +1,17 @@ +/* src/config_clp.h. Generated by configure. */ +/* src/config_clp.h.in. */ + +/* Define to 1, 2, 3, or 4 if Aboca should be build. */ +/* #undef CLP_HAS_ABC */ + +/* Version number of project */ +#define CLP_VERSION "1.17" + +/* Major Version number of project */ +#define CLP_VERSION_MAJOR 1 + +/* Minor Version number of project */ +#define CLP_VERSION_MINOR 17 + +/* Release Version number of project */ +#define CLP_VERSION_RELEASE 9999 diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraint.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraint.hpp new file mode 100644 index 000000000..f2930aca3 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraint.hpp @@ -0,0 +1,129 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraint_H +#define ClpConstraint_H + +//############################################################################# +class ClpSimplex; +class ClpModel; + +/** Constraint Abstract Base Class + +Abstract Base Class for describing a constraint or objective function + +*/ +class ClpConstraint { + +public: + ///@name Stuff + //@{ + + /** Fills gradient. If Linear then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient undefined at current solution + */ + virtual int gradient(const ClpSimplex *model, + const double *solution, + double *gradient, + double &functionValue, + double &offset, + bool useScaling = false, + bool refresh = true) const = 0; + /// Constraint function value + virtual double functionValue(const ClpSimplex *model, + const double *solution, + bool useScaling = false, + bool refresh = true) const; + /// Resize constraint + virtual void resize(int newNumberColumns) = 0; + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int *which) = 0; + /// Scale constraint + virtual void reallyScale(const double *columnScale) = 0; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char *which) const = 0; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char *which) const = 0; + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraint(); + + /// Copy constructor + ClpConstraint(const ClpConstraint &); + + /// Assignment operator + ClpConstraint &operator=(const ClpConstraint &rhs); + + /// Destructor + virtual ~ClpConstraint(); + + /// Clone + virtual ClpConstraint *clone() const = 0; + + //@} + + ///@name Other + //@{ + /// Returns type, 0 linear, 1 nonlinear + inline int type() + { + return type_; + } + /// Row number (-1 is objective) + inline int rowNumber() const + { + return rowNumber_; + } + + /// Number of possible coefficients in gradient + virtual int numberCoefficients() const = 0; + + /// Stored constraint function value + inline double functionValue() const + { + return functionValue_; + } + + /// Constraint offset + inline double offset() const + { + return offset_; + } + /// Say we have new primal solution - so may need to recompute + virtual void newXValues() {} + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Gradient at last evaluation + mutable double *lastGradient_; + /// Value of non-linear part of constraint + mutable double functionValue_; + /// Value of offset for constraint + mutable double offset_; + /// Type of constraint - linear is 1 + int type_; + /// Row number (-1 is objective) + int rowNumber_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintAmpl.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintAmpl.hpp new file mode 100644 index 000000000..c820c517b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintAmpl.hpp @@ -0,0 +1,109 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraintAmpl_H +#define ClpConstraintAmpl_H + +#include "ClpConstraint.hpp" + +//############################################################################# + +/** Ampl Constraint Class + +*/ + +class ClpConstraintAmpl : public ClpConstraint { + +public: + ///@name Stuff + //@{ + + /** Fills gradient. If Ampl then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient udefined at current solution + */ + virtual int gradient(const ClpSimplex *model, + const double *solution, + double *gradient, + double &functionValue, + double &offset, + bool useScaling = false, + bool refresh = true) const; + /// Resize constraint + virtual void resize(int newNumberColumns); + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale constraint + virtual void reallyScale(const double *columnScale); + /** Given a zeroed array sets nonampl columns to 1. + Returns number of nonampl columns + */ + virtual int markNonlinear(char *which) const; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char *which) const; + /// Say we have new primal solution - so may need to recompute + virtual void newXValues(); + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraintAmpl(); + + /// Constructor from ampl + ClpConstraintAmpl(int row, void *amplInfo); + + /** Copy constructor . + */ + ClpConstraintAmpl(const ClpConstraintAmpl &rhs); + + /// Assignment operator + ClpConstraintAmpl &operator=(const ClpConstraintAmpl &rhs); + + /// Destructor + virtual ~ClpConstraintAmpl(); + + /// Clone + virtual ClpConstraint *clone() const; + //@} + ///@name Gets and sets + //@{ + /// Number of coefficients + virtual int numberCoefficients() const; + /// Columns + inline const int *column() const + { + return column_; + } + /// Coefficients + inline const double *coefficient() const + { + return coefficient_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Ampl info + void *amplInfo_; + /// Column + int *column_; + /// Coefficients + double *coefficient_; + /// Number of coefficients in gradient + int numberCoefficients_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintLinear.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintLinear.hpp new file mode 100644 index 000000000..924840e35 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintLinear.hpp @@ -0,0 +1,113 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraintLinear_H +#define ClpConstraintLinear_H + +#include "ClpConstraint.hpp" + +//############################################################################# + +/** Linear Constraint Class + +*/ + +class ClpConstraintLinear : public ClpConstraint { + +public: + ///@name Stuff + //@{ + + /** Fills gradient. If Linear then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient udefined at current solution + */ + virtual int gradient(const ClpSimplex *model, + const double *solution, + double *gradient, + double &functionValue, + double &offset, + bool useScaling = false, + bool refresh = true) const; + /// Resize constraint + virtual void resize(int newNumberColumns); + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale constraint + virtual void reallyScale(const double *columnScale); + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char *which) const; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char *which) const; + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraintLinear(); + + /// Constructor from constraint + ClpConstraintLinear(int row, int numberCoefficients, int numberColumns, + const int *column, const double *element); + + /** Copy constructor . + */ + ClpConstraintLinear(const ClpConstraintLinear &rhs); + + /// Assignment operator + ClpConstraintLinear &operator=(const ClpConstraintLinear &rhs); + + /// Destructor + virtual ~ClpConstraintLinear(); + + /// Clone + virtual ClpConstraint *clone() const; + //@} + ///@name Gets and sets + //@{ + /// Number of coefficients + virtual int numberCoefficients() const; + /// Number of columns in linear constraint + inline int numberColumns() const + { + return numberColumns_; + } + /// Columns + inline const int *column() const + { + return column_; + } + /// Coefficients + inline const double *coefficient() const + { + return coefficient_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Column + int *column_; + /// Coefficients + double *coefficient_; + /// Useful to have number of columns about + int numberColumns_; + /// Number of coefficients + int numberCoefficients_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintQuadratic.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintQuadratic.hpp new file mode 100644 index 000000000..c93ff1404 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpConstraintQuadratic.hpp @@ -0,0 +1,123 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpConstraintQuadratic_H +#define ClpConstraintQuadratic_H + +#include "ClpConstraint.hpp" + +//############################################################################# + +/** Quadratic Constraint Class + +*/ + +class ClpConstraintQuadratic : public ClpConstraint { + +public: + ///@name Stuff + //@{ + + /** Fills gradient. If Quadratic then solution may be NULL, + also returns true value of function and offset so we can use x not deltaX in constraint + If refresh is false then uses last solution + Uses model for scaling + Returns non-zero if gradient udefined at current solution + */ + virtual int gradient(const ClpSimplex *model, + const double *solution, + double *gradient, + double &functionValue, + double &offset, + bool useScaling = false, + bool refresh = true) const; + /// Resize constraint + virtual void resize(int newNumberColumns); + /// Delete columns in constraint + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale constraint + virtual void reallyScale(const double *columnScale); + /** Given a zeroed array sets nonquadratic columns to 1. + Returns number of nonquadratic columns + */ + virtual int markNonlinear(char *which) const; + /** Given a zeroed array sets possible nonzero coefficients to 1. + Returns number of nonzeros + */ + virtual int markNonzero(char *which) const; + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpConstraintQuadratic(); + + /// Constructor from quadratic + ClpConstraintQuadratic(int row, int numberQuadraticColumns, int numberColumns, + const CoinBigIndex *start, + const int *column, const double *element); + + /** Copy constructor . + */ + ClpConstraintQuadratic(const ClpConstraintQuadratic &rhs); + + /// Assignment operator + ClpConstraintQuadratic &operator=(const ClpConstraintQuadratic &rhs); + + /// Destructor + virtual ~ClpConstraintQuadratic(); + + /// Clone + virtual ClpConstraint *clone() const; + //@} + ///@name Gets and sets + //@{ + /// Number of coefficients + virtual int numberCoefficients() const; + /// Number of columns in constraint + inline int numberColumns() const + { + return numberColumns_; + } + /// Column starts + inline CoinBigIndex *start() const + { + return start_; + } + /// Columns + inline const int *column() const + { + return column_; + } + /// Coefficients + inline const double *coefficient() const + { + return coefficient_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Column starts + CoinBigIndex *start_; + /// Column (if -1 then linear coefficient) + int *column_; + /// Coefficients + double *coefficient_; + /// Useful to have number of columns about + int numberColumns_; + /// Number of coefficients in gradient + int numberCoefficients_; + /// Number of quadratic columns + int numberQuadraticColumns_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowDantzig.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowDantzig.hpp new file mode 100644 index 000000000..88ed9bb15 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowDantzig.hpp @@ -0,0 +1,72 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDualRowDantzig_H +#define ClpDualRowDantzig_H + +#include "ClpDualRowPivot.hpp" + +//############################################################################# + +/** Dual Row Pivot Dantzig Algorithm Class + +This is simplest choice - choose largest infeasibility + +*/ + +class ClpDualRowDantzig : public ClpDualRowPivot { + +public: + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector *input, + CoinIndexedVector *spare, + CoinIndexedVector *spare2, + CoinIndexedVector *updatedColumn); + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + */ + virtual void updatePrimalSolution(CoinIndexedVector *input, + double theta, + double &changeInObjective); + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpDualRowDantzig(); + + /// Copy constructor + ClpDualRowDantzig(const ClpDualRowDantzig &); + + /// Assignment operator + ClpDualRowDantzig &operator=(const ClpDualRowDantzig &rhs); + + /// Destructor + virtual ~ClpDualRowDantzig(); + + /// Clone + virtual ClpDualRowPivot *clone(bool copyData = true) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowPivot.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowPivot.hpp new file mode 100644 index 000000000..635239927 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowPivot.hpp @@ -0,0 +1,136 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDualRowPivot_H +#define ClpDualRowPivot_H + +class ClpSimplex; +class CoinIndexedVector; + +//############################################################################# + +/** Dual Row Pivot Abstract Base Class + +Abstract Base Class for describing an interface to an algorithm +to choose row pivot in dual simplex algorithm. For some algorithms +e.g. Dantzig choice then some functions may be null. + +*/ + +class ClpDualRowPivot { + +public: + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow() = 0; + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector *input, + CoinIndexedVector *spare, + CoinIndexedVector *spare2, + CoinIndexedVector *updatedColumn) + = 0; + + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + Would be faster if we kept basic regions, but on other hand it + means everything is always in sync + */ + /* FIXME: this was pure virtul (=0). Why? */ + virtual void updatePrimalSolution(CoinIndexedVector *input, + double theta, + double &changeInObjective) + = 0; + /** Saves any weights round factorization as pivot rows may change + Will be empty unless steepest edge (will save model) + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) for strong branching - initialize to 1 , infeasibilities + 6) scale back + 7) for strong branching - initialize full weights , infeasibilities + */ + virtual void saveWeights(ClpSimplex *model, int mode); + /// checks accuracy and may re-initialize (may be empty) + virtual void checkAccuracy(); + /// Gets rid of last update (may be empty) + virtual void unrollWeights(); + /// Gets rid of all arrays (may be empty) + virtual void clearArrays(); + /// Returns true if would not find any row + virtual bool looksOptimal() const + { + return false; + } + /// Called when maximum pivots changes + virtual void maximumPivotsChanged() {} + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpDualRowPivot(); + + /// Copy constructor + ClpDualRowPivot(const ClpDualRowPivot &); + + /// Assignment operator + ClpDualRowPivot &operator=(const ClpDualRowPivot &rhs); + + /// Destructor + virtual ~ClpDualRowPivot(); + + /// Clone + virtual ClpDualRowPivot *clone(bool copyData = true) const = 0; + + //@} + + ///@name Other + //@{ + /// Returns model + inline ClpSimplex *model() + { + return model_; + } + + /// Sets model (normally to NULL) + inline void setModel(ClpSimplex *newmodel) + { + model_ = newmodel; + } + + /// Returns type (above 63 is extra information) + inline int type() + { + return type_; + } + + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Pointer to model + ClpSimplex *model_; + /// Type of row pivot algorithm + int type_; + //@} +}; +#ifndef CLP_DUAL_COLUMN_MULTIPLIER +//#define CLP_DUAL_COLUMN_MULTIPLIER 0.99999 +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowSteepest.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowSteepest.hpp new file mode 100644 index 000000000..4f3d87494 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDualRowSteepest.hpp @@ -0,0 +1,160 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDualRowSteepest_H +#define ClpDualRowSteepest_H + +#include "ClpDualRowPivot.hpp" +class CoinIndexedVector; + +//############################################################################# + +/** Dual Row Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + +class ClpDualRowSteepest : public ClpDualRowPivot { + +public: + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /** Updates weights and returns pivot alpha. + Also does FT update */ + virtual double updateWeights(CoinIndexedVector *input, + CoinIndexedVector *spare, + CoinIndexedVector *spare2, + CoinIndexedVector *updatedColumn); + + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + */ + virtual void updatePrimalSolution(CoinIndexedVector *input, + double theta, + double &changeInObjective); + + /** Saves any weights round factorization as pivot rows may change + Save model + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) for strong branching - initialize (uninitialized) , infeasibilities + */ + virtual void saveWeights(ClpSimplex *model, int mode); + /// Pass in saved weights + void passInSavedWeights(const CoinIndexedVector *saved); + /// Get saved weights + inline CoinIndexedVector *savedWeights() + { + return savedWeights_; + } + /// Gets rid of last update + virtual void unrollWeights(); + /// Gets rid of all arrays + virtual void clearArrays(); + /// Returns true if would not find any row + virtual bool looksOptimal() const; + /// Called when maximum pivots changes + virtual void maximumPivotsChanged(); + //@} + + /** enums for persistence + */ + enum Persistence { + normal = 0x00, // create (if necessary) and destroy + keep = 0x01 // create (if necessary) and leave + }; + + ///@name Constructors and destructors + //@{ + /** Default Constructor + 0 is uninitialized, 1 full, 2 is partial uninitialized, + 3 starts as 2 but may switch to 1. + By partial is meant that the weights are updated as normal + but only part of the infeasible basic variables are scanned. + This can be faster on very easy problems. + */ + ClpDualRowSteepest(int mode = 3); + + /// Copy constructor + ClpDualRowSteepest(const ClpDualRowSteepest &); + + /// Assignment operator + ClpDualRowSteepest &operator=(const ClpDualRowSteepest &rhs); + + /// Fill most values + void fill(const ClpDualRowSteepest &rhs); + + /// Destructor + virtual ~ClpDualRowSteepest(); + + /// Clone + virtual ClpDualRowPivot *clone(bool copyData = true) const; + + //@} + /**@name gets and sets */ + //@{ + /// Mode + inline int mode() const + { + return mode_; + } + /// Set mode + inline void setMode(int mode) + { + mode_ = mode; + } + /// Set/ get persistence + inline void setPersistence(Persistence life) + { + persistence_ = life; + } + inline Persistence persistence() const + { + return persistence_; + } + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + /** Status + 0) Normal + -1) Needs initialization + 1) Weights are stored by sequence number + */ + int state_; + /** If 0 then we are using uninitialized weights, 1 then full, + if 2 then uninitialized partial, 3 switchable */ + int mode_; + /// Life of weights + Persistence persistence_; + /// weight array + double *weights_; + /// square of infeasibility array (just for infeasible rows) + CoinIndexedVector *infeasible_; + /// alternate weight array (so we can unroll) + CoinIndexedVector *alternateWeights_; + /// save weight array (so we can use checkpoint) + CoinIndexedVector *savedWeights_; + /// Dubious weights + int *dubiousWeights_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDummyMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDummyMatrix.hpp new file mode 100644 index 000000000..736fa78a8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDummyMatrix.hpp @@ -0,0 +1,186 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDummyMatrix_H +#define ClpDummyMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a dummy matrix as derived from ClpMatrixBase. + This is so you can do ClpPdco but may come in useful elsewhere. + It just has dimensions but no data +*/ + +class ClpDummyMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const + { + return true; + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const + { + return numberElements_; + } + /** Number of columns. */ + virtual int getNumCols() const + { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const + { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const; + + virtual const CoinBigIndex *getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const; + + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel); + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis(const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const {} + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void times(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + + using ClpMatrixBase::transposeTimes; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + //@} + + /**@name Other */ + //@{ + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDummyMatrix(); + /// Constructor with data + ClpDummyMatrix(int numberColumns, int numberRows, + int numberElements); + /** Destructor */ + virtual ~ClpDummyMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDummyMatrix(const ClpDummyMatrix &); + /** The copy constructor from an CoinDummyMatrix. */ + ClpDummyMatrix(const CoinPackedMatrix &); + + ClpDummyMatrix &operator=(const ClpDummyMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// Number of elements + int numberElements_; + + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicExampleMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicExampleMatrix.hpp new file mode 100644 index 000000000..08f9a7efa --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicExampleMatrix.hpp @@ -0,0 +1,199 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDynamicExampleMatrix_H +#define ClpDynamicExampleMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpDynamicMatrix.hpp" +class ClpSimplex; +/** This implements a dynamic matrix when we have a limit on the number of + "interesting rows". This version inherits from ClpDynamicMatrix and knows that + the real matrix is gub. This acts just like ClpDynamicMatrix but generates columns. + This "generates" columns by choosing from stored set. It is maent as a starting point + as to how you could use shortest path to generate columns. + + So it has its own copy of all data needed. It populates ClpDynamicWatrix with enough + to allow for gub keys and active variables. In turn ClpDynamicMatrix populates + a CoinPackedMatrix with active columns and rows. + + As there is one copy here and one in ClpDynamicmatrix these names end in Gen_ + + It is obviously more efficient to just use ClpDynamicMatrix but the ideas is to + show how much code a user would have to write. + + This does not work very well with bounds + +*/ + +class ClpDynamicExampleMatrix : public ClpDynamicMatrix { + +public: + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + + /** Creates a variable. This is called after partial pricing and will modify matrix. + Will update bestSequence. + */ + virtual void createVariable(ClpSimplex *model, int &bestSequence); + /** If addColumn forces compression then this allows descendant to know what to do. + If >= then entry stayed in, if -1 then entry went out to lower bound.of zero. + Entries at upper bound (really nonzero) never go out (at present). + */ + virtual void packDown(const int *in, int numberToPack); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDynamicExampleMatrix(); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + The contents of original matrix in model will be taken over and original matrix + will be sanitized so can be deleted (to avoid a very small memory leak) + */ + ClpDynamicExampleMatrix(ClpSimplex *model, int numberSets, + int numberColumns, const CoinBigIndex *starts, + const double *lower, const double *upper, + const CoinBigIndex *startColumn, const int *row, + const double *element, const double *cost, + const double *columnLower = NULL, const double *columnUpper = NULL, + const unsigned char *status = NULL, + const unsigned char *dynamicStatus = NULL, + int numberIds = 0, const int *ids = NULL); +#if 0 + /// This constructor just takes over ownership (except for lower, upper) + ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, + int numberColumns, int * starts, + const double * lower, const double * upper, + int * startColumn, int * row, + double * element, double * cost, + double * columnLower = NULL, double * columnUpper = NULL, + const unsigned char * status = NULL, + const unsigned char * dynamicStatus = NULL, + int numberIds = 0, const int *ids = NULL); +#endif + /** Destructor */ + virtual ~ClpDynamicExampleMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDynamicExampleMatrix(const ClpDynamicExampleMatrix &); + ClpDynamicExampleMatrix &operator=(const ClpDynamicExampleMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + //@} + /**@name gets and sets */ + //@{ + /// Starts of each column + inline CoinBigIndex *startColumnGen() const + { + return startColumnGen_; + } + /// rows + inline int *rowGen() const + { + return rowGen_; + } + /// elements + inline double *elementGen() const + { + return elementGen_; + } + /// costs + inline double *costGen() const + { + return costGen_; + } + /// full starts + inline CoinBigIndex *fullStartGen() const + { + return fullStartGen_; + } + /// ids in next level matrix + inline int *idGen() const + { + return idGen_; + } + /// Optional lower bounds on columns + inline double *columnLowerGen() const + { + return columnLowerGen_; + } + /// Optional upper bounds on columns + inline double *columnUpperGen() const + { + return columnUpperGen_; + } + /// size + inline int numberColumns() const + { + return numberColumns_; + } + inline void setDynamicStatusGen(int sequence, DynamicStatus status) + { + unsigned char &st_byte = dynamicStatusGen_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | status); + } + inline DynamicStatus getDynamicStatusGen(int sequence) const + { + return static_cast< DynamicStatus >(dynamicStatusGen_[sequence] & 7); + } + /// Whether flagged + inline bool flaggedGen(int i) const + { + return (dynamicStatusGen_[i] & 8) != 0; + } + inline void setFlaggedGen(int i) + { + dynamicStatusGen_[i] = static_cast< unsigned char >(dynamicStatusGen_[i] | 8); + } + inline void unsetFlagged(int i) + { + dynamicStatusGen_[i] = static_cast< unsigned char >(dynamicStatusGen_[i] & ~8); + } + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// size + int numberColumns_; + /// Starts of each column + CoinBigIndex *startColumnGen_; + /// rows + int *rowGen_; + /// elements + double *elementGen_; + /// costs + double *costGen_; + /// start of each set + CoinBigIndex *fullStartGen_; + /// for status and which bound + unsigned char *dynamicStatusGen_; + /** identifier for each variable up one level (startColumn_, etc). This is + of length maximumGubColumns_. For this version it is just sequence number + at this level */ + int *idGen_; + /// Optional lower bounds on columns + double *columnLowerGen_; + /// Optional upper bounds on columns + double *columnUpperGen_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicMatrix.hpp new file mode 100644 index 000000000..11678b45f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpDynamicMatrix.hpp @@ -0,0 +1,420 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpDynamicMatrix_H +#define ClpDynamicMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpPackedMatrix.hpp" +class ClpSimplex; +/** This implements a dynamic matrix when we have a limit on the number of + "interesting rows". This version inherits from ClpPackedMatrix and knows that + the real matrix is gub. A later version could use shortest path to generate columns. + +*/ + +class ClpDynamicMatrix : public ClpPackedMatrix { + +public: + /// enums for status of various sorts + enum DynamicStatus { + soloKey = 0x00, + inSmall = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03 + }; + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big dynamic or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double *rhsOffset(ClpSimplex *model, bool forceRefresh = false, + bool check = false); + + using ClpPackedMatrix::times; + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// Modifies rhs offset + void modifyOffset(int sequence, double amount); + /// Gets key value when none in small + double keyValue(int iSet) const; + /** + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex *model, CoinIndexedVector *array, + double *other, int mode); + /** + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + */ + virtual int generalExpanded(ClpSimplex *model, int mode, int &number); + /** Purely for column generation and similar ideas. Allows + matrix and any bounds or costs to be updated (sensibly). + Returns non-zero if any changes. + */ + virtual int refresh(ClpSimplex *model); + /** Creates a variable. This is called after partial pricing and will modify matrix. + Will update bestSequence. + */ + virtual void createVariable(ClpSimplex *model, int &bestSequence); + /// Returns reduced cost of a variable + virtual double reducedCost(ClpSimplex *model, int sequence) const; + /// Does gub crash + void gubCrash(); + /// Writes out model (without names) + void writeMps(const char *name); + /// Populates initial matrix from dynamic status + void initialProblem(); + /** Adds in a column to gub structure (called from descendant) and returns sequence */ + int addColumn(CoinBigIndex numberEntries, const int *row, const double *element, + double cost, double lower, double upper, int iSet, + DynamicStatus status); + /** If addColumn forces compression then this allows descendant to know what to do. + If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero. + Entries at upper bound (really nonzero) never go out (at present). + */ + virtual void packDown(const int *, int) {} + /// Gets lower bound (to simplify coding) + inline double columnLower(int sequence) const + { + if (columnLower_) + return columnLower_[sequence]; + else + return 0.0; + } + /// Gets upper bound (to simplify coding) + inline double columnUpper(int sequence) const + { + if (columnUpper_) + return columnUpper_[sequence]; + else + return COIN_DBL_MAX; + } + + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpDynamicMatrix(); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + The contents of original matrix in model will be taken over and original matrix + will be sanitized so can be deleted (to avoid a very small memory leak) + */ + ClpDynamicMatrix(ClpSimplex *model, int numberSets, + int numberColumns, const int *starts, + const double *lower, const double *upper, + const CoinBigIndex *startColumn, const int *row, + const double *element, const double *cost, + const double *columnLower = NULL, const double *columnUpper = NULL, + const unsigned char *status = NULL, + const unsigned char *dynamicStatus = NULL); + + /** Destructor */ + virtual ~ClpDynamicMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpDynamicMatrix(const ClpDynamicMatrix &); + /** The copy constructor from an CoinPackedMatrix. */ + ClpDynamicMatrix(const CoinPackedMatrix &); + + ClpDynamicMatrix &operator=(const ClpDynamicMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + //@} + /**@name gets and sets */ + //@{ + /// Status of row slacks + inline ClpSimplex::Status getStatus(int sequence) const + { + return static_cast< ClpSimplex::Status >(status_[sequence] & 7); + } + inline void setStatus(int sequence, ClpSimplex::Status status) + { + unsigned char &st_byte = status_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | status); + } + /// Whether flagged slack + inline bool flaggedSlack(int i) const + { + return (status_[i] & 8) != 0; + } + inline void setFlaggedSlack(int i) + { + status_[i] = static_cast< unsigned char >(status_[i] | 8); + } + inline void unsetFlaggedSlack(int i) + { + status_[i] = static_cast< unsigned char >(status_[i] & ~8); + } + /// Number of sets (dynamic rows) + inline int numberSets() const + { + return numberSets_; + } + /// Number of possible gub variables + inline int numberGubEntries() const + { + return startSet_[numberSets_]; + } + /// Sets + inline int *startSets() const + { + return startSet_; + } + /// Whether flagged + inline bool flagged(int i) const + { + return (dynamicStatus_[i] & 8) != 0; + } + inline void setFlagged(int i) + { + dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] | 8); + } + inline void unsetFlagged(int i) + { + dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] & ~8); + } + inline void setDynamicStatus(int sequence, DynamicStatus status) + { + unsigned char &st_byte = dynamicStatus_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | status); + } + inline DynamicStatus getDynamicStatus(int sequence) const + { + return static_cast< DynamicStatus >(dynamicStatus_[sequence] & 7); + } + /// Saved value of objective offset + inline double objectiveOffset() const + { + return objectiveOffset_; + } + /// Starts of each column + inline CoinBigIndex *startColumn() const + { + return startColumn_; + } + /// rows + inline int *row() const + { + return row_; + } + /// elements + inline double *element() const + { + return element_; + } + /// costs + inline double *cost() const + { + return cost_; + } + /// ids of active columns (just index here) + inline int *id() const + { + return id_; + } + /// Optional lower bounds on columns + inline double *columnLower() const + { + return columnLower_; + } + /// Optional upper bounds on columns + inline double *columnUpper() const + { + return columnUpper_; + } + /// Lower bounds on sets + inline double *lowerSet() const + { + return lowerSet_; + } + /// Upper bounds on sets + inline double *upperSet() const + { + return upperSet_; + } + /// size + inline int numberGubColumns() const + { + return numberGubColumns_; + } + /// first free + inline int firstAvailable() const + { + return firstAvailable_; + } + /// first dynamic + inline int firstDynamic() const + { + return firstDynamic_; + } + /// number of columns in dynamic model + inline int lastDynamic() const + { + return lastDynamic_; + } + /// number of rows in original model + inline int numberStaticRows() const + { + return numberStaticRows_; + } + /// size of working matrix (max) + inline CoinBigIndex numberElements() const + { + return numberElements_; + } + inline int *keyVariable() const + { + return keyVariable_; + } + /// Switches off dj checking each factorization (for BIG models) + void switchOffCheck(); + /// Status region for gub slacks + inline unsigned char *gubRowStatus() const + { + return status_; + } + /// Status region for gub variables + inline unsigned char *dynamicStatus() const + { + return dynamicStatus_; + } + /// Returns which set a variable is in + int whichSet(int sequence) const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Sum of dual infeasibilities + double sumDualInfeasibilities_; + /// Sum of primal infeasibilities + double sumPrimalInfeasibilities_; + /// Sum of Dual infeasibilities using tolerance based on error in duals + double sumOfRelaxedDualInfeasibilities_; + /// Sum of Primal infeasibilities using tolerance based on error in primals + double sumOfRelaxedPrimalInfeasibilities_; + /// Saved best dual on gub row in pricing + double savedBestGubDual_; + /// Saved best set in pricing + int savedBestSet_; + /// Backward pointer to pivot row !!! + int *backToPivotRow_; + /// Key variable of set (only accurate if none in small problem) + mutable int *keyVariable_; + /// Backward pointer to extra row + int *toIndex_; + // Reverse pointer from index to set + int *fromIndex_; + /// Number of sets (dynamic rows) + int numberSets_; + /// Number of active sets + int numberActiveSets_; + /// Saved value of objective offset + double objectiveOffset_; + /// Lower bounds on sets + double *lowerSet_; + /// Upper bounds on sets + double *upperSet_; + /// Status of slack on set + unsigned char *status_; + /// Pointer back to model + ClpSimplex *model_; + /// first free + int firstAvailable_; + /// first free when iteration started + int firstAvailableBefore_; + /// first dynamic + int firstDynamic_; + /// number of columns in dynamic model + int lastDynamic_; + /// number of rows in original model + int numberStaticRows_; + /// size of working matrix (max) + CoinBigIndex numberElements_; + /// Number of dual infeasibilities + int numberDualInfeasibilities_; + /// Number of primal infeasibilities + int numberPrimalInfeasibilities_; + /** If pricing will declare victory (i.e. no check every factorization). + -1 - always check + 0 - don't check + 1 - in don't check mode but looks optimal + */ + int noCheck_; + /// Infeasibility weight when last full pass done + double infeasibilityWeight_; + /// size + int numberGubColumns_; + /// current maximum number of columns (then compress) + int maximumGubColumns_; + /// current maximum number of elemnts (then compress) + CoinBigIndex maximumElements_; + /// Start of each set + int *startSet_; + /// next in chain + int *next_; + /// Starts of each column + CoinBigIndex *startColumn_; + /// rows + int *row_; + /// elements + double *element_; + /// costs + double *cost_; + /// ids of active columns (just index here) + int *id_; + /// for status and which bound + unsigned char *dynamicStatus_; + /// Optional lower bounds on columns + double *columnLower_; + /// Optional upper bounds on columns + double *columnUpper_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpEventHandler.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpEventHandler.hpp new file mode 100644 index 000000000..8c12e846d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpEventHandler.hpp @@ -0,0 +1,193 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpEventHandler_H +#define ClpEventHandler_H + +#include "ClpSimplex.hpp" +/** Base class for Clp event handling + +This is just here to allow for event handling. By event I mean a Clp event +e.g. end of values pass. + +One use would be to let a user handle a system event e.g. Control-C. This could be done +by deriving a class MyEventHandler which knows about such events. If one occurs +MyEventHandler::event() could clear event status and return 3 (stopped). + +Clp would then return to user code. + +As it is called every iteration this should be fine grained enough. + +User can derive and construct from CbcModel - not pretty + +*/ + +class ClpEventHandler { + +public: + /** enums for what sort of event. + + These will also be returned in ClpModel::secondaryStatus() as int + */ + enum Event { + endOfIteration = 100, // used to set secondary status + endOfFactorization, // after gutsOfSolution etc + endOfValuesPass, + node, // for Cbc + treeStatus, // for Cbc + solution, // for Cbc + theta, // hit in parametrics + pivotRow, // used to choose pivot row + presolveStart, // ClpSolve presolve start + presolveSize, // sees if ClpSolve presolve too big or too small + presolveInfeasible, // ClpSolve presolve infeasible + presolveBeforeSolve, // ClpSolve presolve before solve + presolveAfterFirstSolve, // ClpSolve presolve after solve + presolveAfterSolve, // ClpSolve presolve after solve + presolveEnd, // ClpSolve presolve end + goodFactorization, // before gutsOfSolution + complicatedPivotIn, // in modifyCoefficients + noCandidateInPrimal, // tentative end + looksEndInPrimal, // About to declare victory (or defeat) + endInPrimal, // Victory (or defeat) + beforeStatusOfProblemInPrimal, + startOfStatusOfProblemInPrimal, + complicatedPivotOut, // in modifyCoefficients + noCandidateInDual, // tentative end + looksEndInDual, // About to declare victory (or defeat) + endInDual, // Victory (or defeat) + beforeStatusOfProblemInDual, + startOfStatusOfProblemInDual, + startOfIterationInDual, + updateDualsInDual, + beforeDeleteRim, + endOfCreateRim, + slightlyInfeasible, + modifyMatrixInMiniPresolve, + moreMiniPresolve, + modifyMatrixInMiniPostsolve, + beforeChooseIncoming, + afterChooseIncoming, + beforeCreateNonLinear, + afterCreateNonLinear, + startOfCrossover, // in Idiot + noTheta // At end (because no pivot) + }; + /**@name Virtual method that the derived classes should provide. + The base class instance does nothing and as event() is only useful method + it would not be very useful NOT providing one! + */ + //@{ + /** This can do whatever it likes. If return code -1 then carries on + if 0 sets ClpModel::status() to 5 (stopped by event) and will return to user. + At present if <-1 carries on and if >0 acts as if 0 - this may change. + For ClpSolve 2 -> too big return status of -2 and -> too small 3 + */ + virtual int event(Event whichEvent); + /** This can do whatever it likes. Return code -1 means no action. + This passes in something + */ + virtual int eventWithInfo(Event whichEvent, void *info); + //@} + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + ClpEventHandler(ClpSimplex *model = NULL); + /** Destructor */ + virtual ~ClpEventHandler(); + // Copy + ClpEventHandler(const ClpEventHandler &); + // Assignment + ClpEventHandler &operator=(const ClpEventHandler &); + /// Clone + virtual ClpEventHandler *clone() const; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setSimplex(ClpSimplex *model); + /// Get model + inline ClpSimplex *simplex() const + { + return model_; + } + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to simplex + ClpSimplex *model_; + //@} +}; +/** Base class for Clp disaster handling + +This is here to allow for disaster handling. By disaster I mean that Clp +would otherwise give up + +*/ + +class ClpDisasterHandler { + +public: + /**@name Virtual methods that the derived classe should provide. + */ + //@{ + /// Into simplex + virtual void intoSimplex() = 0; + /// Checks if disaster + virtual bool check() const = 0; + /// saves information for next attempt + virtual void saveInfo() = 0; + /// Type of disaster 0 can fix, 1 abort + virtual int typeOfDisaster(); + //@} + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + ClpDisasterHandler(ClpSimplex *model = NULL); + /** Destructor */ + virtual ~ClpDisasterHandler(); + // Copy + ClpDisasterHandler(const ClpDisasterHandler &); + // Assignment + ClpDisasterHandler &operator=(const ClpDisasterHandler &); + /// Clone + virtual ClpDisasterHandler *clone() const = 0; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setSimplex(ClpSimplex *model); + /// Get model + inline ClpSimplex *simplex() const + { + return model_; + } + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to simplex + ClpSimplex *model_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpFactorization.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpFactorization.hpp new file mode 100644 index 000000000..9d63f01b0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpFactorization.hpp @@ -0,0 +1,556 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpFactorization_H +#define ClpFactorization_H + +#include "CoinPragma.hpp" + +#include "CoinFactorization.hpp" +class ClpMatrixBase; +class ClpSimplex; +class ClpNetworkBasis; +class CoinOtherFactorization; +#ifndef CLP_MULTIPLE_FACTORIZATIONS +#define CLP_MULTIPLE_FACTORIZATIONS 4 +#endif +#ifdef CLP_MULTIPLE_FACTORIZATIONS +#include "CoinDenseFactorization.hpp" +#include "ClpSimplex.hpp" +#endif +#ifndef COIN_FAST_CODE +#define COIN_FAST_CODE +#endif +#ifndef CLP_FACTORIZATION_NEW_TIMING +#define CLP_FACTORIZATION_NEW_TIMING 1 +#endif + +/** This just implements CoinFactorization when an ClpMatrixBase object + is passed. If a network then has a dummy CoinFactorization and + a genuine ClpNetworkBasis object +*/ +class ClpFactorization +#ifndef CLP_MULTIPLE_FACTORIZATIONS + : public CoinFactorization +#endif +{ + + //friend class CoinFactorization; + +public: + /**@name factorization */ + //@{ + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + if increasingRows_ >1. + Allows scaling + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize(ClpSimplex *model, int solveType, bool valuesPass); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpFactorization(); + /** Destructor */ + ~ClpFactorization(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor from an CoinFactorization. */ + ClpFactorization(const CoinFactorization &); + /** The copy constructor. */ + ClpFactorization(const ClpFactorization &, int denseIfSmaller = 0); +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /** The copy constructor from an CoinOtherFactorization. */ + ClpFactorization(const CoinOtherFactorization &); +#endif + ClpFactorization &operator=(const ClpFactorization &); + //@} + + /* **** below here is so can use networkish basis */ + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + int replaceColumn(const ClpSimplex *model, + CoinIndexedVector *regionSparse, + CoinIndexedVector *tableauColumn, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); +#if ABOCA_LITE_FACTORIZATION + /// Does btranU part of replaceColumn (skipping entries) + void replaceColumn1(CoinIndexedVector *regionSparse, int pivotRow); + /// Does replaceColumn - having already done btranU + int replaceColumn2(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck); +#endif + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room + region1 starts as zero and is zero at end */ + int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2); + /** Updates one column (FTRAN) from region2 + region1 starts as zero and is zero at end */ + int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room. + Also updates region3 + region1 starts as zero and is zero at end */ + int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermuteRegion3 = false); + /// For debug (no statistics update) + int updateColumnForDebug(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /** Updates one column (BTRAN) from region2 + region1 starts as zero and is zero at end */ + int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + /** Updates two columns (BTRAN) from regionSparse2 and 3 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output - same for 3 + */ + void updateTwoColumnsTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3) const; + //@} +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /**@name Lifted from CoinFactorization */ + //@{ + /// Total number of elements in factorization + inline int numberElements() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberElements(); + else + return coinFactorizationB_->numberElements(); + } + /// Returns address of permute region + inline int *permute() const + { + if (coinFactorizationA_) + return coinFactorizationA_->permute(); + else + return coinFactorizationB_->permute(); + } + /// Returns address of pivotColumn region (also used for permuting) + inline int *pivotColumn() const + { + if (coinFactorizationA_) + return coinFactorizationA_->pivotColumn(); + else + return coinFactorizationB_->permute(); + } + /// Maximum number of pivots between factorizations + inline int maximumPivots() const + { + if (coinFactorizationA_) + return coinFactorizationA_->maximumPivots(); + else + return coinFactorizationB_->maximumPivots(); + } + /// Set maximum number of pivots between factorizations + inline void maximumPivots(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->maximumPivots(value); + else + coinFactorizationB_->maximumPivots(value); + } + /// Returns number of pivots since factorization + inline int pivots() const + { + if (coinFactorizationA_) + return coinFactorizationA_->pivots(); + else + return coinFactorizationB_->pivots(); + } + /// Whether larger areas needed + inline double areaFactor() const + { + if (coinFactorizationA_) + return coinFactorizationA_->areaFactor(); + else + return 0.0; + } + /// Set whether larger areas needed + inline void areaFactor(double value) + { + if (coinFactorizationA_) + coinFactorizationA_->areaFactor(value); + } + /// Zero tolerance + inline double zeroTolerance() const + { + if (coinFactorizationA_) + return coinFactorizationA_->zeroTolerance(); + else + return coinFactorizationB_->zeroTolerance(); + } + /// Set zero tolerance + inline void zeroTolerance(double value) + { + if (coinFactorizationA_) + coinFactorizationA_->zeroTolerance(value); + else + coinFactorizationB_->zeroTolerance(value); + } + /// Set tolerances to safer of existing and given + void saferTolerances(double zeroTolerance, double pivotTolerance); + /** get sparse threshold */ + inline int sparseThreshold() const + { + if (coinFactorizationA_) + return coinFactorizationA_->sparseThreshold(); + else + return 0; + } + /** Set sparse threshold */ + inline void sparseThreshold(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->sparseThreshold(value); + } + /// Returns status + inline int status() const + { + if (coinFactorizationA_) + return coinFactorizationA_->status(); + else + return coinFactorizationB_->status(); + } + /// Sets status + inline void setStatus(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->setStatus(value); + else + coinFactorizationB_->setStatus(value); + } + /// Returns number of dense rows + inline int numberDense() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberDense(); + else + return 0; + } +#if 1 + /// Returns number in U area + inline CoinBigIndex numberElementsU() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberElementsU(); + else + return -1; + } + /// Returns number in L area + inline CoinBigIndex numberElementsL() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberElementsL(); + else + return -1; + } + /// Returns number in R area + inline CoinBigIndex numberElementsR() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberElementsR(); + else + return 0; + } +#endif + bool timeToRefactorize() const; +#if CLP_FACTORIZATION_NEW_TIMING > 1 + void statsRefactor(char when) const; +#endif + /// Level of detail of messages + inline int messageLevel() const + { + if (coinFactorizationA_) + return coinFactorizationA_->messageLevel(); + else + return 1; + } + /// Set level of detail of messages + inline void messageLevel(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->messageLevel(value); + } + /// Get rid of all memory + inline void clearArrays() + { + if (coinFactorizationA_) + coinFactorizationA_->clearArrays(); + else if (coinFactorizationB_) + coinFactorizationB_->clearArrays(); + } + /// Number of Rows after factorization + inline int numberRows() const + { + if (coinFactorizationA_) + return coinFactorizationA_->numberRows(); + else + return coinFactorizationB_->numberRows(); + } + /// Gets dense threshold + inline int denseThreshold() const + { + if (coinFactorizationA_) + return coinFactorizationA_->denseThreshold(); + else + return 0; + } + /// Sets dense threshold + inline void setDenseThreshold(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->setDenseThreshold(value); + } + /// Pivot tolerance + inline double pivotTolerance() const + { + if (coinFactorizationA_) + return coinFactorizationA_->pivotTolerance(); + else if (coinFactorizationB_) + return coinFactorizationB_->pivotTolerance(); + return 1.0e-8; + } + /// Set pivot tolerance + inline void pivotTolerance(double value) + { + if (coinFactorizationA_) + coinFactorizationA_->pivotTolerance(value); + else if (coinFactorizationB_) + coinFactorizationB_->pivotTolerance(value); + } + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) + { + if (coinFactorizationA_) + coinFactorizationA_->relaxAccuracyCheck(value); + } + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + inline int persistenceFlag() const + { + if (coinFactorizationA_) + return coinFactorizationA_->persistenceFlag(); + else + return 0; + } + inline void setPersistenceFlag(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->setPersistenceFlag(value); + } + /// Delete all stuff (leaves as after CoinFactorization()) + inline void almostDestructor() + { + if (coinFactorizationA_) + coinFactorizationA_->almostDestructor(); + else if (coinFactorizationB_) + coinFactorizationB_->clearArrays(); + } + /// Returns areaFactor but adjusted for dense + inline double adjustedAreaFactor() const + { + if (coinFactorizationA_) + return coinFactorizationA_->adjustedAreaFactor(); + else + return 0.0; + } + inline void setBiasLU(int value) + { + if (coinFactorizationA_) + coinFactorizationA_->setBiasLU(value); + } + /// true if Forrest Tomlin update, false if PFI + inline void setForrestTomlin(bool value) + { + if (coinFactorizationA_) + coinFactorizationA_->setForrestTomlin(value); + } + /// Sets default values + inline void setDefaultValues() + { + if (coinFactorizationA_) { + // row activities have negative sign +#ifndef COIN_FAST_CODE + coinFactorizationA_->slackValue(-1.0); +#endif + coinFactorizationA_->zeroTolerance(1.0e-13); + } + } + /// If nonzero force use of 1,dense 2,small 3,osl + void forceOtherFactorization(int which); + /// Get switch to osl if number rows <= this + inline int goOslThreshold() const + { + return goOslThreshold_; + } + /// Set switch to osl if number rows <= this + inline void setGoOslThreshold(int value) + { + goOslThreshold_ = value; + } + /// Get switch to dense if number rows <= this + inline int goDenseThreshold() const + { + return goDenseThreshold_; + } + /// Set switch to dense if number rows <= this + inline void setGoDenseThreshold(int value) + { + goDenseThreshold_ = value; + } + /// Get switch to small if number rows <= this + inline int goSmallThreshold() const + { + return goSmallThreshold_; + } + /// Set switch to small if number rows <= this + inline void setGoSmallThreshold(int value) + { + goSmallThreshold_ = value; + } + /// Go over to dense or small code if small enough + void goDenseOrSmall(int numberRows); + /// Sets factorization + void setFactorization(ClpFactorization &factorization); + /// Return 1 if dense code + inline int isDenseOrSmall() const + { + return coinFactorizationB_ ? 1 : 0; + } + /// Return coinFactorizationA_ + inline CoinFactorization *coinFactorization() const + { + return coinFactorizationA_; + } +#else + inline bool timeToRefactorize() const + { + return (pivots() * 3 > maximumPivots() * 2 && numberElementsR() * 3 > (numberElementsL() + numberElementsU()) * 2 + 1000 && !numberDense()); + } + /// Sets default values + inline void setDefaultValues() + { + // row activities have negative sign +#ifndef COIN_FAST_CODE + slackValue(-1.0); +#endif + zeroTolerance(1.0e-13); + } + /// Go over to dense code + inline void goDense() {} +#endif + //@} + + /**@name other stuff */ + //@{ + /** makes a row copy of L for speed and to allow very sparse problems */ + void goSparse(); + /// Cleans up i.e. gets rid of network basis + void cleanUp(); + /// Says whether to redo pivot order + bool needToReorder() const; + /// To switch statistics on or off + inline void doStatistics(bool trueFalse) const + { + doStatistics_ = trueFalse; + } +#ifndef SLIM_CLP + /// Says if a network basis + inline bool networkBasis() const + { + return (networkBasis_ != NULL); + } +#else + /// Says if a network basis + inline bool networkBasis() const + { + return false; + } +#endif + /// Fills weighted row list + void getWeights(int *weights) const; + //@} + + ////////////////// data ////////////////// +private: + /**@name data */ + //@{ + /// Pointer to network basis +#ifndef SLIM_CLP + ClpNetworkBasis *networkBasis_; +#endif +#ifdef CLP_MULTIPLE_FACTORIZATIONS + /// Pointer to CoinFactorization + CoinFactorization *coinFactorizationA_; + /// Pointer to CoinOtherFactorization + CoinOtherFactorization *coinFactorizationB_; +#ifdef CLP_REUSE_ETAS + /// Pointer to model + ClpSimplex *model_; +#endif + /// If nonzero force use of 1,dense 2,small 3,osl + int forceB_; + /// Switch to osl if number rows <= this + int goOslThreshold_; + /// Switch to small if number rows <= this + int goSmallThreshold_; + /// Switch to dense if number rows <= this + int goDenseThreshold_; +#endif +#ifdef CLP_FACTORIZATION_NEW_TIMING + /// For guessing when to re-factorize + mutable double shortestAverage_; + mutable double totalInR_; + mutable double totalInIncreasingU_; + mutable int endLengthU_; + mutable int lastNumberPivots_; + mutable int effectiveStartNumberU_; +#endif + /// To switch statistics on or off + mutable bool doStatistics_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubDynamicMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubDynamicMatrix.hpp new file mode 100644 index 000000000..72db5f195 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubDynamicMatrix.hpp @@ -0,0 +1,270 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpGubDynamicMatrix_H +#define ClpGubDynamicMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpGubMatrix.hpp" +/** This implements Gub rows plus a ClpPackedMatrix. + This a dynamic version which stores the gub part and dynamically creates matrix. + All bounds are assumed to be zero and infinity + + This is just a simple example for real column generation +*/ + +class ClpGubDynamicMatrix : public ClpGubMatrix { + +public: + /**@name Main functions provided */ + //@{ + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + /** This is local to Gub to allow synchronization: + mode=0 when status of basis is good + mode=1 when variable is flagged + mode=2 when all variables unflagged (returns number flagged) + mode=3 just reset costs (primal) + mode=4 correct number of dual infeasibilities + mode=5 return 4 if time to re-factorize + mode=8 - make sure set is clean + mode=9 - adjust lower, upper on set by incoming + */ + virtual int synchronize(ClpSimplex *model, int mode); + /// Sets up an effective RHS and does gub crash if needed + virtual void useEffectiveRhs(ClpSimplex *model, bool cheapest = true); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue); + /// Add a new variable to a set + void insertNonBasic(int sequence, int iSet); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double *rhsOffset(ClpSimplex *model, bool forceRefresh = false, + bool check = false); + + using ClpPackedMatrix::times; + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /** Just for debug + Returns sum and number of primal infeasibilities. Recomputes keys + */ + virtual int checkFeasible(ClpSimplex *model, double &sum) const; + /// Cleans data after setWarmStart + void cleanData(ClpSimplex *model); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpGubDynamicMatrix(); + /** Destructor */ + virtual ~ClpGubDynamicMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpGubDynamicMatrix(const ClpGubDynamicMatrix &); + /** This is the real constructor. + It assumes factorization frequency will not be changed. + This resizes model !!!! + */ + ClpGubDynamicMatrix(ClpSimplex *model, int numberSets, + int numberColumns, const int *starts, + const double *lower, const double *upper, + const CoinBigIndex *startColumn, const int *row, + const double *element, const double *cost, + const double *lowerColumn = NULL, const double *upperColumn = NULL, + const unsigned char *status = NULL); + + ClpGubDynamicMatrix &operator=(const ClpGubDynamicMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + //@} + /**@name gets and sets */ + //@{ + /// enums for status of various sorts + enum DynamicStatus { + inSmall = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03 + }; + /// Whether flagged + inline bool flagged(int i) const + { + return (dynamicStatus_[i] & 8) != 0; + } + inline void setFlagged(int i) + { + dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] | 8); + } + inline void unsetFlagged(int i) + { + dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] & ~8); + } + inline void setDynamicStatus(int sequence, DynamicStatus status) + { + unsigned char &st_byte = dynamicStatus_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | status); + } + inline DynamicStatus getDynamicStatus(int sequence) const + { + return static_cast< DynamicStatus >(dynamicStatus_[sequence] & 7); + } + /// Saved value of objective offset + inline double objectiveOffset() const + { + return objectiveOffset_; + } + /// Starts of each column + inline CoinBigIndex *startColumn() const + { + return startColumn_; + } + /// rows + inline int *row() const + { + return row_; + } + /// elements + inline double *element() const + { + return element_; + } + /// costs + inline double *cost() const + { + return cost_; + } + /// full starts + inline int *fullStart() const + { + return fullStart_; + } + /// ids of active columns (just index here) + inline int *id() const + { + return id_; + } + /// Optional lower bounds on columns + inline double *lowerColumn() const + { + return lowerColumn_; + } + /// Optional upper bounds on columns + inline double *upperColumn() const + { + return upperColumn_; + } + /// Optional true lower bounds on sets + inline double *lowerSet() const + { + return lowerSet_; + } + /// Optional true upper bounds on sets + inline double *upperSet() const + { + return upperSet_; + } + /// size + inline int numberGubColumns() const + { + return numberGubColumns_; + } + /// first free + inline int firstAvailable() const + { + return firstAvailable_; + } + /// set first free + inline void setFirstAvailable(int value) + { + firstAvailable_ = value; + } + /// first dynamic + inline int firstDynamic() const + { + return firstDynamic_; + } + /// number of columns in dynamic model + inline int lastDynamic() const + { + return lastDynamic_; + } + /// size of working matrix (max) + inline CoinBigIndex numberElements() const + { + return numberElements_; + } + /// Status region for gub slacks + inline unsigned char *gubRowStatus() const + { + return status_; + } + /// Status region for gub variables + inline unsigned char *dynamicStatus() const + { + return dynamicStatus_; + } + /// Returns which set a variable is in + int whichSet(int sequence) const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Saved value of objective offset + double objectiveOffset_; + /// Starts of each column + CoinBigIndex *startColumn_; + /// rows + int *row_; + /// elements + double *element_; + /// costs + double *cost_; + /// full starts + int *fullStart_; + /// ids of active columns (just index here) + int *id_; + /// for status and which bound + unsigned char *dynamicStatus_; + /// Optional lower bounds on columns + double *lowerColumn_; + /// Optional upper bounds on columns + double *upperColumn_; + /// Optional true lower bounds on sets + double *lowerSet_; + /// Optional true upper bounds on sets + double *upperSet_; + /// size + int numberGubColumns_; + /// first free + int firstAvailable_; + /// saved first free + int savedFirstAvailable_; + /// first dynamic + int firstDynamic_; + /// number of columns in dynamic model + int lastDynamic_; + /// size of working matrix (max) + CoinBigIndex numberElements_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubMatrix.hpp new file mode 100644 index 000000000..e887da2a2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpGubMatrix.hpp @@ -0,0 +1,373 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpGubMatrix_H +#define ClpGubMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpPackedMatrix.hpp" +class ClpSimplex; +/** This implements Gub rows plus a ClpPackedMatrix. + + There will be a version using ClpPlusMinusOne matrix but + there is no point doing one with ClpNetworkMatrix (although + an embedded network is attractive). + +*/ + +class ClpGubMatrix : public ClpPackedMatrix { + +public: + /**@name Main functions provided */ + //@{ + /** Returns a new matrix in reverse order without gaps (GUB wants NULL) */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis(const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + /// Returns number of hidden rows e.g. gub + virtual int hiddenRows() const; + //@} + + /**@name Matrix times vector methods */ + //@{ + + using ClpPackedMatrix::transposeTimes; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** expands an updated column to allow for extra rows which the main + solver does not know about and returns number added if mode 0. + If mode 1 deletes extra entries + + This active in Gub + */ + virtual int extendUpdated(ClpSimplex *model, CoinIndexedVector *update, int mode); + /** + mode=0 - Set up before "update" and "times" for primal solution using extended rows + mode=1 - Cleanup primal solution after "times" using extended rows. + mode=2 - Check (or report on) primal infeasibilities + */ + virtual void primalExpanded(ClpSimplex *model, int mode); + /** + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex *model, CoinIndexedVector *array, + double *other, int mode); + /** + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + */ + virtual int generalExpanded(ClpSimplex *model, int mode, int &number); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue); + /// Sets up an effective RHS and does gub crash if needed + virtual void useEffectiveRhs(ClpSimplex *model, bool cheapest = true); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double *rhsOffset(ClpSimplex *model, bool forceRefresh = false, + bool check = false); + /** This is local to Gub to allow synchronization: + mode=0 when status of basis is good + mode=1 when variable is flagged + mode=2 when all variables unflagged (returns number flagged) + mode=3 just reset costs (primal) + mode=4 correct number of dual infeasibilities + mode=5 return 4 if time to re-factorize + mode=6 - return 1 if there may be changing bounds on variable (column generation) + mode=7 - do extra restores for column generation + mode=8 - make sure set is clean + mode=9 - adjust lower, upper on set by incoming + */ + virtual int synchronize(ClpSimplex *model, int mode); + /// Correct sequence in and out to give true value + virtual void correctSequence(const ClpSimplex *model, int &sequenceIn, int &sequenceOut); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpGubMatrix(); + /** Destructor */ + virtual ~ClpGubMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpGubMatrix(const ClpGubMatrix &); + /** The copy constructor from an CoinPackedMatrix. */ + ClpGubMatrix(const CoinPackedMatrix &); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpGubMatrix(const ClpGubMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + ClpGubMatrix(const CoinPackedMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + + /** This takes over ownership (for space reasons) */ + ClpGubMatrix(CoinPackedMatrix *matrix); + + /** This takes over ownership (for space reasons) and is the + real constructor*/ + ClpGubMatrix(ClpPackedMatrix *matrix, int numberSets, + const int *start, const int *end, + const double *lower, const double *upper, + const unsigned char *status = NULL); + + ClpGubMatrix &operator=(const ClpGubMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + /** redoes next_ for a set. */ + void redoSet(ClpSimplex *model, int newKey, int oldKey, int iSet); + //@} + /**@name gets and sets */ + //@{ + /// Status + inline ClpSimplex::Status getStatus(int sequence) const + { + return static_cast< ClpSimplex::Status >(status_[sequence] & 7); + } + inline void setStatus(int sequence, ClpSimplex::Status status) + { + unsigned char &st_byte = status_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | status); + } + /// To flag a variable + inline void setFlagged(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 64); + } + inline void clearFlagged(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~64); + } + inline bool flagged(int sequence) const + { + return ((status_[sequence] & 64) != 0); + } + /// To say key is above ub + inline void setAbove(int sequence) + { + unsigned char iStat = status_[sequence]; + iStat = static_cast< unsigned char >(iStat & ~24); + status_[sequence] = static_cast< unsigned char >(iStat | 16); + } + /// To say key is feasible + inline void setFeasible(int sequence) + { + unsigned char iStat = status_[sequence]; + iStat = static_cast< unsigned char >(iStat & ~24); + status_[sequence] = static_cast< unsigned char >(iStat | 8); + } + /// To say key is below lb + inline void setBelow(int sequence) + { + unsigned char iStat = status_[sequence]; + iStat = static_cast< unsigned char >(iStat & ~24); + status_[sequence] = iStat; + } + inline double weight(int sequence) const + { + int iStat = status_[sequence] & 31; + iStat = iStat >> 3; + return static_cast< double >(iStat - 1); + } + /// Starts + inline int *start() const + { + return start_; + } + /// End + inline int *end() const + { + return end_; + } + /// Lower bounds on sets + inline double *lower() const + { + return lower_; + } + /// Upper bounds on sets + inline double *upper() const + { + return upper_; + } + /// Key variable of set + inline int *keyVariable() const + { + return keyVariable_; + } + /// Backward pointer to set number + inline int *backward() const + { + return backward_; + } + /// Number of sets (gub rows) + inline int numberSets() const + { + return numberSets_; + } + /// Switches off dj checking each factorization (for BIG models) + void switchOffCheck(); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Sum of dual infeasibilities + double sumDualInfeasibilities_; + /// Sum of primal infeasibilities + double sumPrimalInfeasibilities_; + /// Sum of Dual infeasibilities using tolerance based on error in duals + double sumOfRelaxedDualInfeasibilities_; + /// Sum of Primal infeasibilities using tolerance based on error in primals + double sumOfRelaxedPrimalInfeasibilities_; + /// Infeasibility weight when last full pass done + double infeasibilityWeight_; + /// Starts + int *start_; + /// End + int *end_; + /// Lower bounds on sets + double *lower_; + /// Upper bounds on sets + double *upper_; + /// Status of slacks + mutable unsigned char *status_; + /// Saved status of slacks + unsigned char *saveStatus_; + /// Saved key variables + int *savedKeyVariable_; + /// Backward pointer to set number + int *backward_; + /// Backward pointer to pivot row !!! + int *backToPivotRow_; + /// Change in costs for keys + double *changeCost_; + /// Key variable of set + mutable int *keyVariable_; + /** Next basic variable in set - starts at key and end with -(set+1). + Now changes to -(nonbasic+1). + next_ has extra space for 2* longest set */ + mutable int *next_; + /// Backward pointer to index in CoinIndexedVector + int *toIndex_; + // Reverse pointer from index to set + int *fromIndex_; + /// Pointer back to model + ClpSimplex *model_; + /// Number of dual infeasibilities + int numberDualInfeasibilities_; + /// Number of primal infeasibilities + int numberPrimalInfeasibilities_; + /** If pricing will declare victory (i.e. no check every factorization). + -1 - always check + 0 - don't check + 1 - in don't check mode but looks optimal + */ + int noCheck_; + /// Number of sets (gub rows) + int numberSets_; + /// Number in vector without gub extension + int saveNumber_; + /// Pivot row of possible next key + int possiblePivotKey_; + /// Gub slack in (set number or -1) + int gubSlackIn_; + /// First gub variables (same as start_[0] at present) + int firstGub_; + /// last gub variable (same as end_[numberSets_-1] at present) + int lastGub_; + /** type of gub - 0 not contiguous, 1 contiguous + add 8 bit to say no ubs on individual variables */ + int gubType_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpInterior.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpInterior.hpp new file mode 100644 index 000000000..0f32a286f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpInterior.hpp @@ -0,0 +1,622 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Tomlin (pdco) + John Forrest (standard predictor-corrector) + + Note JJF has added arrays - this takes more memory but makes + flow easier to understand and hopefully easier to extend + + */ +#ifndef ClpInterior_H +#define ClpInterior_H + +#include +#include +#include "ClpModel.hpp" +#include "ClpMatrixBase.hpp" +#include "ClpSolve.hpp" +#include "CoinDenseVector.hpp" +class ClpLsqr; +class ClpPdcoBase; +/// ******** DATA to be moved into protected section of ClpInterior +typedef struct { + double atolmin; + double r3norm; + double LSdamp; + double *deltay; +} Info; +/// ******** DATA to be moved into protected section of ClpInterior + +typedef struct { + double atolold; + double atolnew; + double r3ratio; + int istop; + int itncg; +} Outfo; +/// ******** DATA to be moved into protected section of ClpInterior + +typedef struct { + double gamma; + double delta; + int MaxIter; + double FeaTol; + double OptTol; + double StepTol; + double x0min; + double z0min; + double mu0; + int LSmethod; // 1=Cholesky 2=QR 3=LSQR + int LSproblem; // See below + int LSQRMaxIter; + double LSQRatol1; // Initial atol + double LSQRatol2; // Smallest atol (unless atol1 is smaller) + double LSQRconlim; + int wait; +} Options; +class Lsqr; +class ClpCholeskyBase; +// ***** END +/** This solves LPs using interior point methods + + It inherits from ClpModel and all its arrays are created at + algorithm time. + +*/ + +class ClpInterior : public ClpModel { + friend void ClpInteriorUnitTest(const std::string &mpsDir, + const std::string &netlibDir); + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpInterior(); + + /// Copy constructor. + ClpInterior(const ClpInterior &); + /// Copy constructor from model. + ClpInterior(const ClpModel &); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + */ + ClpInterior(const ClpModel *wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns, + bool dropNames = true, bool dropIntegers = true); + /// Assignment operator. This copies the data + ClpInterior &operator=(const ClpInterior &rhs); + /// Destructor + ~ClpInterior(); + // Ones below are just ClpModel with some changes + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ + void loadProblem(const ClpMatrixBase &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /// This one is for after presolve to save memory + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, const int *length, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /** Borrow model. This is so we dont have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm. + This is same as ClpModel one. */ + void borrowModel(ClpModel &otherModel); + /** Return model - updates any scalars */ + void returnModel(ClpModel &otherModel); + //@} + + /**@name Functions most useful to user */ + //@{ + /** Pdco algorithm - see ClpPdco.hpp for method */ + int pdco(); + // ** Temporary version + int pdco(ClpPdcoBase *stuff, Options &options, Info &info, Outfo &outfo); + /// Primal-Dual Predictor-Corrector barrier + int primalDual(); + //@} + + /**@name most useful gets and sets */ + //@{ + /// If problem is primal feasible + inline bool primalFeasible() const + { + return (sumPrimalInfeasibilities_ <= 1.0e-5); + } + /// If problem is dual feasible + inline bool dualFeasible() const + { + return (sumDualInfeasibilities_ <= 1.0e-5); + } + /// Current (or last) algorithm + inline int algorithm() const + { + return algorithm_; + } + /// Set algorithm + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + /// Sum of dual infeasibilities + inline CoinWorkDouble sumDualInfeasibilities() const + { + return sumDualInfeasibilities_; + } + /// Sum of primal infeasibilities + inline CoinWorkDouble sumPrimalInfeasibilities() const + { + return sumPrimalInfeasibilities_; + } + /// dualObjective. + inline CoinWorkDouble dualObjective() const + { + return dualObjective_; + } + /// primalObjective. + inline CoinWorkDouble primalObjective() const + { + return primalObjective_; + } + /// diagonalNorm + inline CoinWorkDouble diagonalNorm() const + { + return diagonalNorm_; + } + /// linearPerturbation + inline CoinWorkDouble linearPerturbation() const + { + return linearPerturbation_; + } + inline void setLinearPerturbation(CoinWorkDouble value) + { + linearPerturbation_ = value; + } + /// projectionTolerance + inline CoinWorkDouble projectionTolerance() const + { + return projectionTolerance_; + } + inline void setProjectionTolerance(CoinWorkDouble value) + { + projectionTolerance_ = value; + } + /// diagonalPerturbation + inline CoinWorkDouble diagonalPerturbation() const + { + return diagonalPerturbation_; + } + inline void setDiagonalPerturbation(CoinWorkDouble value) + { + diagonalPerturbation_ = value; + } + /// gamma + inline CoinWorkDouble gamma() const + { + return gamma_; + } + inline void setGamma(CoinWorkDouble value) + { + gamma_ = value; + } + /// delta + inline CoinWorkDouble delta() const + { + return delta_; + } + inline void setDelta(CoinWorkDouble value) + { + delta_ = value; + } + /// ComplementarityGap + inline CoinWorkDouble complementarityGap() const + { + return complementarityGap_; + } + //@} + + /**@name most useful gets and sets */ + //@{ + /// Largest error on Ax-b + inline CoinWorkDouble largestPrimalError() const + { + return largestPrimalError_; + } + /// Largest error on basic duals + inline CoinWorkDouble largestDualError() const + { + return largestDualError_; + } + /// Maximum iterations + inline int maximumBarrierIterations() const + { + return maximumBarrierIterations_; + } + inline void setMaximumBarrierIterations(int value) + { + maximumBarrierIterations_ = value; + } + /// Set cholesky (and delete present one) + void setCholesky(ClpCholeskyBase *cholesky); + /// Return number fixed to see if worth presolving + int numberFixed() const; + /** fix variables interior says should be. If reallyFix false then just + set values to exact bounds */ + void fixFixed(bool reallyFix = true); + /// Primal erturbation vector + inline CoinWorkDouble *primalR() const + { + return primalR_; + } + /// Dual erturbation vector + inline CoinWorkDouble *dualR() const + { + return dualR_; + } + //@} + +protected: + /**@name protected methods */ + //@{ + /// Does most of deletion + void gutsOfDelete(); + /// Does most of copying + void gutsOfCopy(const ClpInterior &rhs); + /// Returns true if data looks okay, false if not + bool createWorkingData(); + void deleteWorkingData(); + /// Sanity check on input rim data + bool sanityCheck(); + /// This does housekeeping + int housekeeping(); + //@} +public: + /**@name public methods */ + //@{ + /// Raw objective value (so always minimize) + inline CoinWorkDouble rawObjectiveValue() const + { + return objectiveValue_; + } + /// Returns 1 if sequence indicates column + inline int isColumn(int sequence) const + { + return sequence < numberColumns_ ? 1 : 0; + } + /// Returns sequence number within section + inline int sequenceWithin(int sequence) const + { + return sequence < numberColumns_ ? sequence : sequence - numberColumns_; + } + /// Checks solution + void checkSolution(); + /** Modifies djs to allow for quadratic. + returns quadratic offset */ + CoinWorkDouble quadraticDjs(CoinWorkDouble *djRegion, const CoinWorkDouble *solution, + CoinWorkDouble scaleFactor); + + /// To say a variable is fixed + inline void setFixed(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 1); + } + inline void clearFixed(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~1); + } + inline bool fixed(int sequence) const + { + return ((status_[sequence] & 1) != 0); + } + + /// To flag a variable + inline void setFlagged(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 2); + } + inline void clearFlagged(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~2); + } + inline bool flagged(int sequence) const + { + return ((status_[sequence] & 2) != 0); + } + + /// To say a variable is fixed OR free + inline void setFixedOrFree(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 4); + } + inline void clearFixedOrFree(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~4); + } + inline bool fixedOrFree(int sequence) const + { + return ((status_[sequence] & 4) != 0); + } + + /// To say a variable has lower bound + inline void setLowerBound(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 8); + } + inline void clearLowerBound(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~8); + } + inline bool lowerBound(int sequence) const + { + return ((status_[sequence] & 8) != 0); + } + + /// To say a variable has upper bound + inline void setUpperBound(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 16); + } + inline void clearUpperBound(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~16); + } + inline bool upperBound(int sequence) const + { + return ((status_[sequence] & 16) != 0); + } + + /// To say a variable has fake lower bound + inline void setFakeLower(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 32); + } + inline void clearFakeLower(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~32); + } + inline bool fakeLower(int sequence) const + { + return ((status_[sequence] & 32) != 0); + } + + /// To say a variable has fake upper bound + inline void setFakeUpper(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 64); + } + inline void clearFakeUpper(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~64); + } + inline bool fakeUpper(int sequence) const + { + return ((status_[sequence] & 64) != 0); + } + //@} + + ////////////////// data ////////////////// +protected: + /**@name data. Many arrays have a row part and a column part. + There is a single array with both - columns then rows and + then normally two arrays pointing to rows and columns. The + single array is the owner of memory + */ + //@{ + /// Largest error on Ax-b + CoinWorkDouble largestPrimalError_; + /// Largest error on basic duals + CoinWorkDouble largestDualError_; + /// Sum of dual infeasibilities + CoinWorkDouble sumDualInfeasibilities_; + /// Sum of primal infeasibilities + CoinWorkDouble sumPrimalInfeasibilities_; + /// Worst complementarity + CoinWorkDouble worstComplementarity_; + /// +public: + CoinWorkDouble xsize_; + CoinWorkDouble zsize_; + +protected: + /// Working copy of lower bounds (Owner of arrays below) + CoinWorkDouble *lower_; + /// Row lower bounds - working copy + CoinWorkDouble *rowLowerWork_; + /// Column lower bounds - working copy + CoinWorkDouble *columnLowerWork_; + /// Working copy of upper bounds (Owner of arrays below) + CoinWorkDouble *upper_; + /// Row upper bounds - working copy + CoinWorkDouble *rowUpperWork_; + /// Column upper bounds - working copy + CoinWorkDouble *columnUpperWork_; + /// Working copy of objective + CoinWorkDouble *cost_; + +public: + /// Rhs + CoinWorkDouble *rhs_; + CoinWorkDouble *x_; + CoinWorkDouble *y_; + CoinWorkDouble *dj_; + +protected: + /// Pointer to Lsqr object + ClpLsqr *lsqrObject_; + /// Pointer to stuff + ClpPdcoBase *pdcoStuff_; + /// Below here is standard barrier stuff + /// mu. + CoinWorkDouble mu_; + /// objectiveNorm. + CoinWorkDouble objectiveNorm_; + /// rhsNorm. + CoinWorkDouble rhsNorm_; + /// solutionNorm. + CoinWorkDouble solutionNorm_; + /// dualObjective. + CoinWorkDouble dualObjective_; + /// primalObjective. + CoinWorkDouble primalObjective_; + /// diagonalNorm. + CoinWorkDouble diagonalNorm_; + /// stepLength + CoinWorkDouble stepLength_; + /// linearPerturbation + CoinWorkDouble linearPerturbation_; + /// diagonalPerturbation + CoinWorkDouble diagonalPerturbation_; + // gamma from Saunders and Tomlin regularized + CoinWorkDouble gamma_; + // delta from Saunders and Tomlin regularized + CoinWorkDouble delta_; + /// targetGap + CoinWorkDouble targetGap_; + /// projectionTolerance + CoinWorkDouble projectionTolerance_; + /// maximumRHSError. maximum Ax + CoinWorkDouble maximumRHSError_; + /// maximumBoundInfeasibility. + CoinWorkDouble maximumBoundInfeasibility_; + /// maximumDualError. + CoinWorkDouble maximumDualError_; + /// diagonalScaleFactor. + CoinWorkDouble diagonalScaleFactor_; + /// scaleFactor. For scaling objective + CoinWorkDouble scaleFactor_; + /// actualPrimalStep + CoinWorkDouble actualPrimalStep_; + /// actualDualStep + CoinWorkDouble actualDualStep_; + /// smallestInfeasibility + CoinWorkDouble smallestInfeasibility_; + /// historyInfeasibility. +#define LENGTH_HISTORY 5 + CoinWorkDouble historyInfeasibility_[LENGTH_HISTORY]; + /// complementarityGap. + CoinWorkDouble complementarityGap_; + /// baseObjectiveNorm + CoinWorkDouble baseObjectiveNorm_; + /// worstDirectionAccuracy + CoinWorkDouble worstDirectionAccuracy_; + /// maximumRHSChange + CoinWorkDouble maximumRHSChange_; + /// errorRegion. i.e. Ax + CoinWorkDouble *errorRegion_; + /// rhsFixRegion. + CoinWorkDouble *rhsFixRegion_; + /// upperSlack + CoinWorkDouble *upperSlack_; + /// lowerSlack + CoinWorkDouble *lowerSlack_; + /// diagonal + CoinWorkDouble *diagonal_; + /// solution + CoinWorkDouble *solution_; + /// work array + CoinWorkDouble *workArray_; + /// delta X + CoinWorkDouble *deltaX_; + /// delta Y + CoinWorkDouble *deltaY_; + /// deltaZ. + CoinWorkDouble *deltaZ_; + /// deltaW. + CoinWorkDouble *deltaW_; + /// deltaS. + CoinWorkDouble *deltaSU_; + CoinWorkDouble *deltaSL_; + /// Primal regularization array + CoinWorkDouble *primalR_; + /// Dual regularization array + CoinWorkDouble *dualR_; + /// rhs B + CoinWorkDouble *rhsB_; + /// rhsU. + CoinWorkDouble *rhsU_; + /// rhsL. + CoinWorkDouble *rhsL_; + /// rhsZ. + CoinWorkDouble *rhsZ_; + /// rhsW. + CoinWorkDouble *rhsW_; + /// rhs C + CoinWorkDouble *rhsC_; + /// zVec + CoinWorkDouble *zVec_; + /// wVec + CoinWorkDouble *wVec_; + /// cholesky. + ClpCholeskyBase *cholesky_; + /// numberComplementarityPairs i.e. ones with lower and/or upper bounds (not fixed) + int numberComplementarityPairs_; + /// numberComplementarityItems_ i.e. number of active bounds + int numberComplementarityItems_; + /// Maximum iterations + int maximumBarrierIterations_; + /// gonePrimalFeasible. + bool gonePrimalFeasible_; + /// goneDualFeasible. + bool goneDualFeasible_; + /// Which algorithm being used + int algorithm_; + //@} +}; +//############################################################################# +/** A function that tests the methods in the ClpInterior class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. + + It also does some testing of ClpFactorization class + */ +void ClpInteriorUnitTest(const std::string &mpsDir, + const std::string &netlibDir); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpLinearObjective.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpLinearObjective.hpp new file mode 100644 index 000000000..5c900a2b9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpLinearObjective.hpp @@ -0,0 +1,104 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpLinearObjective_H +#define ClpLinearObjective_H + +#include "ClpObjective.hpp" + +//############################################################################# + +/** Linear Objective Class + +*/ + +class ClpLinearObjective : public ClpObjective { + +public: + ///@name Stuff + //@{ + + /** Returns objective coefficients. + + Offset is always set to 0.0. All other parameters unused. + */ + virtual double *gradient(const ClpSimplex *model, + const double *solution, double &offset, bool refresh, + int includeLinear = 2); + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex *model, double *region, + bool useFeasibleCosts); + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex *model, + const double *solution, + const double *change, + double maximumTheta, + double ¤tObj, + double &predictedObj, + double &thetaObj); + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex *model, const double *solution) const; + /// Resize objective + virtual void resize(int newNumberColumns); + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale objective + virtual void reallyScale(const double *columnScale); + + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpLinearObjective(); + + /// Constructor from objective + ClpLinearObjective(const double *objective, int numberColumns); + + /// Copy constructor + ClpLinearObjective(const ClpLinearObjective &); + /** Subset constructor. Duplicates are allowed + and order is as given. + */ + ClpLinearObjective(const ClpLinearObjective &rhs, int numberColumns, + const int *whichColumns); + + /// Assignment operator + ClpLinearObjective &operator=(const ClpLinearObjective &rhs); + + /// Destructor + virtual ~ClpLinearObjective(); + + /// Clone + virtual ClpObjective *clone() const; + /** Subset clone. Duplicates are allowed + and order is as given. + */ + virtual ClpObjective *subsetClone(int numberColumns, + const int *whichColumns) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Objective + double *objective_; + /// number of columns + int numberColumns_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMatrixBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMatrixBase.hpp new file mode 100644 index 000000000..a3aa1e870 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMatrixBase.hpp @@ -0,0 +1,561 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpMatrixBase_H +#define ClpMatrixBase_H + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" + +#include "CoinPackedMatrix.hpp" +class CoinIndexedVector; +class ClpSimplex; +class ClpModel; +// Compilers can produce better code if they know about __restrict +#ifndef COIN_RESTRICT +#ifdef COIN_USE_RESTRICT +#define COIN_RESTRICT __restrict +#else +#define COIN_RESTRICT +#endif +#endif + +/** Abstract base class for Clp Matrices + +Since this class is abstract, no object of this type can be created. + +If a derived class provides all methods then all Clp algorithms +should work. Some can be very inefficient e.g. getElements etc is +only used for tightening bounds for dual and the copies are +deleted. Many methods can just be dummy i.e. abort(); if not +all features are being used. So if column generation was being done +then it makes no sense to do steepest edge so there would be +no point providing subsetTransposeTimes. +*/ + +class ClpMatrixBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const = 0; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const = 0; + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const = 0; + /** Number of columns. */ + virtual int getNumCols() const = 0; + /** Number of rows. */ + virtual int getNumRows() const = 0; + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const = 0; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const = 0; + + virtual const CoinBigIndex *getVectorStarts() const = 0; + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const = 0; + /** The length of a single major-dimension vector. */ + virtual int getVectorLength(int index) const; + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel) = 0; + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel) = 0; +#ifndef CLP_NO_VECTOR + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase *const *columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase *const *rows); +#endif + /** Modify one element of packed matrix. An element may be added. + This works for either ordering If the new element is zero it will be + deleted unless keepZero true */ + virtual void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false); + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); + + /** Returns a new matrix in reverse order without gaps + Is allowed to return NULL if doesn't want to have row copy */ + virtual ClpMatrixBase *reverseOrderedCopy() const + { + return NULL; + } + + /// Returns number of elements in column part of basis + virtual int countBasis(const int *whichColumn, + int &numberColumnBasic) + = 0; + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element) + = 0; + /** Creates scales for column copy (rowCopy in model may be modified) + default does not allow scaling + returns non-zero if no scaling done */ + virtual int scale(ClpModel *, ClpSimplex * = NULL) const + { + return 1; + } + /** Scales rowCopy if column copy scaled + Only called if scales already exist */ + virtual void scaleRowCopy(ClpModel *) const {} + /// Returns true if can create row copy + virtual bool canGetRowCopy() const + { + return true; + } + /** Realy really scales column copy + Only called if scales already exist. + Up to user to delete */ + inline virtual ClpMatrixBase *scaledColumnCopy(ClpModel *) const + { + return this->clone(); + } + + /** Checks if all elements are in valid range. Can just + return true if you are not paranoid. For Clp I will + probably expect no zeros. Code can modify matrix to get rid of + small elements. + check bits (can be turned off to save time) : + 1 - check if matrix has gaps + 2 - check if zero elements + 4 - check and compress duplicates + 8 - report on large and small + */ + virtual bool allElementsInRange(ClpModel *, + double, double, + int = 15) + { + return true; + } + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + If returns zeros then can't tell anything */ + virtual void rangeOfElements(double &smallestNegative, double &largestNegative, + double &smallestPositive, double &largestPositive); + + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const = 0; + /** Unpacks a column into an CoinIndexedvector + ** in packed format + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const = 0; + /** Purely for column generation and similar ideas. Allows + matrix and any bounds or costs to be updated (sensibly). + Returns non-zero if any changes. + */ + virtual int refresh(ClpSimplex *) + { + return 0; + } + + // Really scale matrix + virtual void reallyScale(const double *rowScale, const double *columnScale); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + Default returns vector of ones + */ + virtual CoinBigIndex *dubiousWeights(const ClpSimplex *model, int *inputWeights) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const = 0; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const = 0; + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const = 0; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Returns number of hidden rows e.g. gub + virtual int hiddenRows() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + /** expands an updated column to allow for extra rows which the main + solver does not know about and returns number added. + + This will normally be a no-op - it is in for GUB but may get extended to + general non-overlapping and embedded networks. + + mode 0 - extend + mode 1 - delete etc + */ + virtual int extendUpdated(ClpSimplex *model, CoinIndexedVector *update, int mode); + /** + utility primal function for dealing with dynamic constraints + mode=0 - Set up before "update" and "times" for primal solution using extended rows + mode=1 - Cleanup primal solution after "times" using extended rows. + mode=2 - Check (or report on) primal infeasibilities + */ + virtual void primalExpanded(ClpSimplex *model, int mode); + /** + utility dual function for dealing with dynamic constraints + mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended + updates array (and may use other if dual values pass) + mode=1 - Update dual solution after "transposeTimes" using extended rows. + mode=2 - Compute all djs and compute key dual infeasibilities + mode=3 - Report on key dual infeasibilities + mode=4 - Modify before updateTranspose in partial pricing + */ + virtual void dualExpanded(ClpSimplex *model, CoinIndexedVector *array, + double *other, int mode); + /** + general utility function for dealing with dynamic constraints + mode=0 - Create list of non-key basics in pivotVariable_ using + number as numberBasic in and out + mode=1 - Set all key variables as basic + mode=2 - return number extra rows needed, number gives maximum number basic + mode=3 - before replaceColumn + mode=4 - return 1 if can do primal, 2 if dual, 3 if both + mode=5 - save any status stuff (when in good state) + mode=6 - restore status stuff + mode=7 - flag given variable (normally sequenceIn) + mode=8 - unflag all variables + mode=9 - synchronize costs and bounds + mode=10 - return 1 if there may be changing bounds on variable (column generation) + mode=11 - make sure set is clean (used when a variable rejected - but not flagged) + mode=12 - after factorize but before permute stuff + mode=13 - at end of simplex to delete stuff + + */ + virtual int generalExpanded(ClpSimplex *model, int mode, int &number); + /** + update information for a pivot (and effective rhs) + */ + virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue); + /** Creates a variable. This is called after partial pricing and may modify matrix. + May update bestSequence. + */ + virtual void createVariable(ClpSimplex *model, int &bestSequence); + /** Just for debug if odd type matrix. + Returns number of primal infeasibilities. */ + virtual int checkFeasible(ClpSimplex *model, double &sum) const; + /// Returns reduced cost of a variable + double reducedCost(ClpSimplex *model, int sequence) const; + /// Correct sequence in and out to give true value (if both -1 maybe do whole matrix) + virtual void correctSequence(const ClpSimplex *model, int &sequenceIn, int &sequenceOut); + //@} + + //--------------------------------------------------------------------------- + /**@name Matrix times vector methods + They can be faster if scalar is +- 1 + Also for simplex I am not using basic/non-basic split */ + //@{ + /** Return y + A * x * scalar in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *COIN_RESTRICT x, double *COIN_RESTRICT y) const = 0; + /** And for scaling - default aborts for when scaling not supported + (unless pointers NULL when as normal) + */ + virtual void times(double scalar, + const double *COIN_RESTRICT x, double *COIN_RESTRICT y, + const double *COIN_RESTRICT rowScale, + const double *COIN_RESTRICT columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *COIN_RESTRICT x, double *COIN_RESTRICT y) const = 0; + /** And for scaling - default aborts for when scaling not supported + (unless pointers NULL when as normal) + */ + virtual void transposeTimes(double scalar, + const double *COIN_RESTRICT x, double *COIN_RESTRICT y, + const double *COIN_RESTRICT rowScale, + const double *COIN_RESTRICT columnScale, + double *COIN_RESTRICT spare = NULL) const; +#if COIN_LONG_WORK + // For long double versions (aborts if not supported) + virtual void times(CoinWorkDouble scalar, + const CoinWorkDouble *COIN_RESTRICT x, CoinWorkDouble *COIN_RESTRICT y) const; + virtual void transposeTimes(CoinWorkDouble scalar, + const CoinWorkDouble *COIN_RESTRICT x, CoinWorkDouble *COIN_RESTRICT y) const; +#endif + /** Return x * scalar *A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const = 0; + /** Return x *A in z but + just for indices in y. + This is only needed for primal steepest edge. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const = 0; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex *, + const CoinIndexedVector *) const + { + return false; + } + /** Updates two arrays for steepest and does devex weights + (need not be coded) + Returns nonzero if updates reduced cost and infeas - + new infeas in dj1 */ + virtual int transposeTimes2(const ClpSimplex *model, + const CoinIndexedVector *pi1, CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, + CoinIndexedVector *spare, + double *infeas, double *reducedCost, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /// Updates second array for steepest and does devex weights (need not be coded) + virtual void subsetTimes2(const ClpSimplex *model, + CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, CoinIndexedVector *dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /** Return x *A in z but + just for number indices in y. + Default cheats with fake CoinIndexedVector and + then calls subsetTransposeTimes */ + virtual void listTransposeTimes(const ClpSimplex *model, + double *x, + int *y, + int number, + double *z) const; + //@} + //@{ + ///@name Other + /// Clone + virtual ClpMatrixBase *clone() const = 0; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given. + Derived classes need not provide this as it may not always make + sense */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + /// Gets rid of any mutable by products + virtual void backToBasics() {} + /** Returns type. + The types which code may need to know about are: + 1 - ClpPackedMatrix + 11 - ClpNetworkMatrix + 12 - ClpPlusMinusOneMatrix + */ + inline int type() const + { + return type_; + } + /// Sets type + void setType(int newtype) + { + type_ = newtype; + } + /// Sets up an effective RHS + void useEffectiveRhs(ClpSimplex *model); + /** Returns effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive. This may re-compute */ + virtual double *rhsOffset(ClpSimplex *model, bool forceRefresh = false, + bool check = false); + /// If rhsOffset used this is iteration last refreshed + inline int lastRefresh() const + { + return lastRefresh_; + } + /// If rhsOffset used this is refresh frequency (0==off) + inline int refreshFrequency() const + { + return refreshFrequency_; + } + inline void setRefreshFrequency(int value) + { + refreshFrequency_ = value; + } + /// whether to skip dual checks most of time + inline bool skipDualCheck() const + { + return skipDualCheck_; + } + inline void setSkipDualCheck(bool yes) + { + skipDualCheck_ = yes; + } + /** Partial pricing tuning parameter - minimum number of "objects" to scan. + e.g. number of Gub sets but could be number of variables */ + inline int minimumObjectsScan() const + { + return minimumObjectsScan_; + } + inline void setMinimumObjectsScan(int value) + { + minimumObjectsScan_ = value; + } + /// Partial pricing tuning parameter - minimum number of negative reduced costs to get + inline int minimumGoodReducedCosts() const + { + return minimumGoodReducedCosts_; + } + inline void setMinimumGoodReducedCosts(int value) + { + minimumGoodReducedCosts_ = value; + } + /// Current start of search space in matrix (as fraction) + inline double startFraction() const + { + return startFraction_; + } + inline void setStartFraction(double value) + { + startFraction_ = value; + } + /// Current end of search space in matrix (as fraction) + inline double endFraction() const + { + return endFraction_; + } + inline void setEndFraction(double value) + { + endFraction_ = value; + } + /// Current best reduced cost + inline double savedBestDj() const + { + return savedBestDj_; + } + inline void setSavedBestDj(double value) + { + savedBestDj_ = value; + } + /// Initial number of negative reduced costs wanted + inline int originalWanted() const + { + return originalWanted_; + } + inline void setOriginalWanted(int value) + { + originalWanted_ = value; + } + /// Current number of negative reduced costs which we still need + inline int currentWanted() const + { + return currentWanted_; + } + inline void setCurrentWanted(int value) + { + currentWanted_ = value; + } + /// Current best sequence + inline int savedBestSequence() const + { + return savedBestSequence_; + } + inline void setSavedBestSequence(int value) + { + savedBestSequence_ = value; + } + //@} + +protected: + /**@name Constructors, destructor
+ NOTE: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + ClpMatrixBase(); + /** Destructor (has to be public) */ +public: + virtual ~ClpMatrixBase(); + +protected: + // Copy + ClpMatrixBase(const ClpMatrixBase &); + // Assignment + ClpMatrixBase &operator=(const ClpMatrixBase &); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /** Effective RHS offset if it is being used. This is used for long problems + or big gub or anywhere where going through full columns is + expensive */ + double *rhsOffset_; + /// Current start of search space in matrix (as fraction) + double startFraction_; + /// Current end of search space in matrix (as fraction) + double endFraction_; + /// Best reduced cost so far + double savedBestDj_; + /// Initial number of negative reduced costs wanted + int originalWanted_; + /// Current number of negative reduced costs which we still need + int currentWanted_; + /// Saved best sequence in pricing + int savedBestSequence_; + /// type (may be useful) + int type_; + /// If rhsOffset used this is iteration last refreshed + int lastRefresh_; + /// If rhsOffset used this is refresh frequency (0==off) + int refreshFrequency_; + /// Partial pricing tuning parameter - minimum number of "objects" to scan + int minimumObjectsScan_; + /// Partial pricing tuning parameter - minimum number of negative reduced costs to get + int minimumGoodReducedCosts_; + /// True sequence in (i.e. from larger problem) + int trueSequenceIn_; + /// True sequence out (i.e. from larger problem) + int trueSequenceOut_; + /// whether to skip dual checks most of time + bool skipDualCheck_; + //@} +}; +// bias for free variables +#define FREE_BIAS 1.0e1 +// Acceptance criteria for free variables +#define FREE_ACCEPT 1.0e2 + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMessage.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMessage.hpp new file mode 100644 index 000000000..c40d93053 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpMessage.hpp @@ -0,0 +1,131 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpMessage_H +#define ClpMessage_H + +#include "CoinPragma.hpp" +#include + +// This deals with Clp messages (as against Osi messages etc) + +#include "CoinMessageHandler.hpp" +enum CLP_Message { + CLP_SIMPLEX_FINISHED, + CLP_SIMPLEX_INFEASIBLE, + CLP_SIMPLEX_UNBOUNDED, + CLP_SIMPLEX_STOPPED, + CLP_SIMPLEX_ERROR, + CLP_SIMPLEX_INTERRUPT, + CLP_SIMPLEX_STATUS, + CLP_DUAL_BOUNDS, + CLP_SIMPLEX_ACCURACY, + CLP_SIMPLEX_BADFACTOR, + CLP_SIMPLEX_BOUNDTIGHTEN, + CLP_SIMPLEX_INFEASIBILITIES, + CLP_SIMPLEX_FLAG, + CLP_SIMPLEX_GIVINGUP, + CLP_DUAL_CHECKB, + CLP_DUAL_ORIGINAL, + CLP_SIMPLEX_PERTURB, + CLP_PRIMAL_ORIGINAL, + CLP_PRIMAL_WEIGHT, + CLP_PRIMAL_OPTIMAL, + CLP_SINGULARITIES, + CLP_MODIFIEDBOUNDS, + CLP_RIMSTATISTICS1, + CLP_RIMSTATISTICS2, + CLP_RIMSTATISTICS3, + CLP_POSSIBLELOOP, + CLP_SMALLELEMENTS, + CLP_DUPLICATEELEMENTS, + CLP_SIMPLEX_HOUSE1, + CLP_SIMPLEX_HOUSE2, + CLP_SIMPLEX_NONLINEAR, + CLP_SIMPLEX_FREEIN, + CLP_SIMPLEX_PIVOTROW, + CLP_DUAL_CHECK, + CLP_PRIMAL_DJ, + CLP_PACKEDSCALE_INITIAL, + CLP_PACKEDSCALE_WHILE, + CLP_PACKEDSCALE_FINAL, + CLP_PACKEDSCALE_FORGET, + CLP_INITIALIZE_STEEP, + CLP_UNABLE_OPEN, + CLP_BAD_BOUNDS, + CLP_BAD_MATRIX, + CLP_LOOP, + CLP_IMPORT_RESULT, + CLP_IMPORT_ERRORS, + CLP_EMPTY_PROBLEM, + CLP_CRASH, + CLP_END_VALUES_PASS, + CLP_QUADRATIC_BOTH, + CLP_QUADRATIC_PRIMAL_DETAILS, + CLP_IDIOT_ITERATION, + CLP_INFEASIBLE, + CLP_MATRIX_CHANGE, + CLP_TIMING, + CLP_INTERVAL_TIMING, + CLP_SPRINT, + CLP_BARRIER_ITERATION, + CLP_BARRIER_OBJECTIVE_GAP, + CLP_BARRIER_GONE_INFEASIBLE, + CLP_BARRIER_CLOSE_TO_OPTIMAL, + CLP_BARRIER_COMPLEMENTARITY, + CLP_BARRIER_EXIT2, + CLP_BARRIER_STOPPING, + CLP_BARRIER_EXIT, + CLP_BARRIER_SCALING, + CLP_BARRIER_MU, + CLP_BARRIER_INFO, + CLP_BARRIER_END, + CLP_BARRIER_ACCURACY, + CLP_BARRIER_SAFE, + CLP_BARRIER_NEGATIVE_GAPS, + CLP_BARRIER_REDUCING, + CLP_BARRIER_DIAGONAL, + CLP_BARRIER_SLACKS, + CLP_BARRIER_DUALINF, + CLP_BARRIER_KILLED, + CLP_BARRIER_ABS_DROPPED, + CLP_BARRIER_ABS_ERROR, + CLP_BARRIER_FEASIBLE, + CLP_BARRIER_STEP, + CLP_BARRIER_KKT, + CLP_RIM_SCALE, + CLP_SLP_ITER, + CLP_COMPLICATED_MODEL, + CLP_BAD_STRING_VALUES, + CLP_CRUNCH_STATS, + CLP_PARAMETRICS_STATS, + CLP_PARAMETRICS_STATS2, +#ifndef NO_FATHOM_PRINT + CLP_FATHOM_STATUS, + CLP_FATHOM_SOLUTION, + CLP_FATHOM_FINISH, +#endif + CLP_GENERAL, + CLP_GENERAL2, + CLP_GENERAL_WARNING, + CLP_DUMMY_END +}; + +/** This deals with Clp messages (as against Osi messages etc) + */ +class ClpMessage : public CoinMessages { + +public: + /**@name Constructors etc */ + //@{ + /** Constructor */ + ClpMessage(Language language = us_en); + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpModel.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpModel.hpp new file mode 100644 index 000000000..18798de17 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpModel.hpp @@ -0,0 +1,1442 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpModel_H +#define ClpModel_H + +#include "ClpConfig.h" + +#include +#include +#include +#include +#include +//#ifndef COIN_USE_CLP +//#define COIN_USE_CLP +//#endif +#include "ClpPackedMatrix.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinTypes.hpp" +#include "CoinFinite.hpp" +#include "ClpParameters.hpp" +#include "ClpObjective.hpp" +class ClpEventHandler; +/** This is the base class for Linear and quadratic Models + This knows nothing about the algorithm, but it seems to + have a reasonable amount of information + + I would welcome suggestions for what should be in this and + how it relates to OsiSolverInterface. Some methods look + very similar. + +*/ +class CoinBuild; +class CoinModel; +class ClpModel { + +public: + /**@name Constructors and destructor + Note - copy methods copy ALL data so can chew up memory + until other copy is freed + */ + //@{ + /// Default constructor + ClpModel(bool emptyMessages = false); + + /** Copy constructor. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 auto-but-as-initialSolve-in-bab + */ + ClpModel(const ClpModel &rhs, int scalingMode = -1); + /// Assignment operator. This copies the data + ClpModel &operator=(const ClpModel &rhs); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + */ + ClpModel(const ClpModel *wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns, + bool dropNames = true, bool dropIntegers = true); + /// Destructor + ~ClpModel(); + //@} + + /**@name Load model - loads some stuff and initializes others */ + //@{ + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ + void loadProblem(const ClpMatrixBase &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /** This loads a model from a coinModel object - returns number of errors. + + modelObject not const as may be changed as part of process + If tryPlusMinusOne then will try adding as +-1 matrix + */ + int loadProblem(CoinModel &modelObject, bool tryPlusMinusOne = false); + /// This one is for after presolve to save memory + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, const int *length, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ + void loadQuadraticObjective(const int numberColumns, + const CoinBigIndex *start, + const int *column, const double *element); + void loadQuadraticObjective(const CoinPackedMatrix &matrix); + /// Get rid of quadratic objective + void deleteQuadraticObjective(); + /// This just loads up a row objective + void setRowObjective(const double *rowObjective); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /// Read GMPL files from the given filenames + int readGMPL(const char *filename, const char *dataName, + bool keepNames = false); + /// Copy in integer informations + void copyInIntegerInformation(const char *information); + /// Drop integer informations + void deleteIntegerInformation(); + /** Set the index-th variable to be a continuous variable */ + void setContinuous(int index); + /** Set the index-th variable to be an integer variable */ + void setInteger(int index); + /** Return true if the index-th variable is an integer variable */ + bool isInteger(int index) const; + /// Resizes rim part of model + void resize(int newNumberRows, int newNumberColumns); +private: + /// Makes sure matrix dimensions are at least model dimensions + void synchronizeMatrix(); +public: + /// Deletes rows + void deleteRows(int number, const int *which); + /// Add one row + void addRow(int numberInRow, const int *columns, + const double *elements, double rowLower = -COIN_DBL_MAX, + double rowUpper = COIN_DBL_MAX); + /// Add rows + void addRows(int number, const double *rowLower, + const double *rowUpper, + const CoinBigIndex *rowStarts, const int *columns, + const double *elements); + /// Add rows + void addRows(int number, const double *rowLower, + const double *rowUpper, + const CoinBigIndex *rowStarts, const int *rowLengths, + const int *columns, + const double *elements); +#ifndef CLP_NO_VECTOR + void addRows(int number, const double *rowLower, + const double *rowUpper, + const CoinPackedVectorBase *const *rows); +#endif + /** Add rows from a build object. + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + Returns number of errors e.g. duplicates + */ + int addRows(const CoinBuild &buildObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /** Add rows from a model object. returns + -1 if object in bad state (i.e. has column information) + otherwise number of errors. + + modelObject non const as can be regularized as part of build + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + */ + int addRows(CoinModel &modelObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + + /// Deletes columns + void deleteColumns(int number, const int *which); + /// Deletes rows AND columns (keeps old sizes) + void deleteRowsAndColumns(int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + /// Add one column + void addColumn(int numberInColumn, + const int *rows, + const double *elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, + double objective = 0.0); + /// Add columns + void addColumns(int number, const double *columnLower, + const double *columnUpper, + const double *objective, + const CoinBigIndex *columnStarts, const int *rows, + const double *elements); + void addColumns(int number, const double *columnLower, + const double *columnUpper, + const double *objective, + const CoinBigIndex *columnStarts, const int *columnLengths, + const int *rows, + const double *elements); +#ifndef CLP_NO_VECTOR + void addColumns(int number, const double *columnLower, + const double *columnUpper, + const double *objective, + const CoinPackedVectorBase *const *columns); +#endif + /** Add columns from a build object + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + Returns number of errors e.g. duplicates + */ + int addColumns(const CoinBuild &buildObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /** Add columns from a model object. returns + -1 if object in bad state (i.e. has row information) + otherwise number of errors + modelObject non const as can be regularized as part of build + If tryPlusMinusOne then will try adding as +-1 matrix + if no matrix exists. + */ + int addColumns(CoinModel &modelObject, bool tryPlusMinusOne = false, + bool checkDuplicates = true); + /// Modify one element of a matrix + inline void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false) + { + matrix_->modifyCoefficient(row, column, newElement, keepZero); + } + /** Change row lower bounds */ + void chgRowLower(const double *rowLower); + /** Change row upper bounds */ + void chgRowUpper(const double *rowUpper); + /** Change column lower bounds */ + void chgColumnLower(const double *columnLower); + /** Change column upper bounds */ + void chgColumnUpper(const double *columnUpper); + /** Change objective coefficients */ + void chgObjCoefficients(const double *objIn); + /** Borrow model. This is so we don't have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm */ + void borrowModel(ClpModel &otherModel); + /** Return model - nulls all arrays so can be deleted safely + also updates any scalars */ + void returnModel(ClpModel &otherModel); + + /// Create empty ClpPackedMatrix + void createEmptyMatrix(); + /** Really clean up matrix (if ClpPackedMatrix). + a) eliminate all duplicate AND small elements in matrix + b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 + c) reallocate arrays and make max lengths equal to lengths + d) orders elements + returns number of elements eliminated or -1 if not ClpPackedMatrix + */ + CoinBigIndex cleanMatrix(double threshold = 1.0e-20); + /// Copy contents - resizing if necessary - otherwise re-use memory + void copy(const ClpMatrixBase *from, ClpMatrixBase *&to); +#ifndef CLP_NO_STD + /// Drops names - makes lengthnames 0 and names empty + void dropNames(); + /// Copies in names + void copyNames(const std::vector< std::string > &rowNames, + const std::vector< std::string > &columnNames); + /// Copies in Row names - modifies names first .. last-1 + void copyRowNames(const std::vector< std::string > &rowNames, int first, int last); + /// Copies in Column names - modifies names first .. last-1 + void copyColumnNames(const std::vector< std::string > &columnNames, int first, int last); + /// Copies in Row names - modifies names first .. last-1 + void copyRowNames(const char *const *rowNames, int first, int last); + /// Copies in Column names - modifies names first .. last-1 + void copyColumnNames(const char *const *columnNames, int first, int last); + /// Set name of row + void setRowName(int rowIndex, std::string &name); + /// Set name of col + void setColumnName(int colIndex, std::string &name); +#endif + /** Find a network subset. + rotate array should be numberRows. On output + -1 not in network + 0 in network as is + 1 in network with signs swapped + Returns number of network rows + */ + int findNetwork(char *rotate, double fractionNeeded = 0.75); + /** This creates a coinModel object + */ + CoinModel *createCoinModel() const; + + /** Write the problem in MPS format to the specified file. + + Row and column names may be null. + formatType is +
    +
  • 0 - normal +
  • 1 - extra accuracy +
  • 2 - IEEE hex +
+ + Returns non-zero on I/O error + */ + int writeMps(const char *filename, + int formatType = 0, int numberAcross = 2, + double objSense = 0.0) const; + //@} + /**@name gets and sets */ + //@{ + /// Number of rows + inline int numberRows() const + { + return numberRows_; + } + inline int getNumRows() const + { + return numberRows_; + } + /// Number of columns + inline int getNumCols() const + { + return numberColumns_; + } + inline int numberColumns() const + { + return numberColumns_; + } + /// Primal tolerance to use + inline double primalTolerance() const + { + return dblParam_[ClpPrimalTolerance]; + } + void setPrimalTolerance(double value); + /// Dual tolerance to use + inline double dualTolerance() const + { + return dblParam_[ClpDualTolerance]; + } + void setDualTolerance(double value); + /// Primal objective limit + inline double primalObjectiveLimit() const + { + return dblParam_[ClpPrimalObjectiveLimit]; + } + void setPrimalObjectiveLimit(double value); + /// Dual objective limit + inline double dualObjectiveLimit() const + { + return dblParam_[ClpDualObjectiveLimit]; + } + void setDualObjectiveLimit(double value); + /// Objective offset + inline double objectiveOffset() const + { + return dblParam_[ClpObjOffset]; + } + void setObjectiveOffset(double value); + /// Presolve tolerance to use + inline double presolveTolerance() const + { + return dblParam_[ClpPresolveTolerance]; + } +#ifndef CLP_NO_STD + inline const std::string &problemName() const + { + return strParam_[ClpProbName]; + } +#endif + /// Number of iterations + inline int numberIterations() const + { + return numberIterations_; + } + inline int getIterationCount() const + { + return numberIterations_; + } + inline void setNumberIterations(int numberIterationsNew) + { + numberIterations_ = numberIterationsNew; + } + /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ + inline int solveType() const + { + return solveType_; + } + inline void setSolveType(int type) + { + solveType_ = type; + } + /// Maximum number of iterations + inline int maximumIterations() const + { + return intParam_[ClpMaxNumIteration]; + } + void setMaximumIterations(int value); + /// Maximum time in seconds (from when set called) + inline double maximumSeconds() const + { + return dblParam_[ClpMaxSeconds]; + } + void setMaximumSeconds(double value); + void setMaximumWallSeconds(double value); + /// Returns true if hit maximum iterations (or time) + bool hitMaximumIterations() const; + /** Status of problem: + -1 - unknown e.g. before solve or if postSolve says not optimal + 0 - optimal + 1 - primal infeasible + 2 - dual infeasible + 3 - stopped on iterations or time + 4 - stopped due to errors + 5 - stopped by event handler (virtual int ClpEventHandler::event()) + */ + inline int status() const + { + return problemStatus_; + } + inline int problemStatus() const + { + return problemStatus_; + } + /// Set problem status + inline void setProblemStatus(int problemStatusNew) + { + problemStatus_ = problemStatusNew; + } + /** Secondary status of problem - may get extended + 0 - none + 1 - primal infeasible because dual limit reached OR (probably primal + infeasible but can't prove it - main status was 4) + 2 - scaled problem optimal - unscaled problem has primal infeasibilities + 3 - scaled problem optimal - unscaled problem has dual infeasibilities + 4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities + 5 - giving up in primal with flagged variables + 6 - failed due to empty problem check + 7 - postSolve says not optimal + 8 - failed due to bad element check + 9 - status was 3 and stopped on time + 10 - status was 3 but stopped as primal feasible + 11 - status was 1/2 from presolve found infeasible or unbounded + 100 up - translation of enum from ClpEventHandler + */ + inline int secondaryStatus() const + { + return secondaryStatus_; + } + inline void setSecondaryStatus(int newstatus) + { + secondaryStatus_ = newstatus; + } + /// Are there a numerical difficulties? + inline bool isAbandoned() const + { + return problemStatus_ == 4; + } + /// Is optimality proven? + inline bool isProvenOptimal() const + { + return problemStatus_ == 0; + } + /// Is primal infeasiblity proven? + inline bool isProvenPrimalInfeasible() const + { + return problemStatus_ == 1; + } + /// Is dual infeasiblity proven? + inline bool isProvenDualInfeasible() const + { + return problemStatus_ == 2; + } + /// Is the given primal objective limit reached? + bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + inline bool isIterationLimitReached() const + { + return problemStatus_ == 3; + } + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const + { + return optimizationDirection_; + } + inline double getObjSense() const + { + return optimizationDirection_; + } + void setOptimizationDirection(double value); + /// Primal row solution + inline double *primalRowSolution() const + { + return rowActivity_; + } + inline const double *getRowActivity() const + { + return rowActivity_; + } + /// Primal column solution + inline double *primalColumnSolution() const + { + return columnActivity_; + } + inline const double *getColSolution() const + { + return columnActivity_; + } + inline void setColSolution(const double *input) + { + memcpy(columnActivity_, input, numberColumns_ * sizeof(double)); + } + /// Dual row solution + inline double *dualRowSolution() const + { + return dual_; + } + inline const double *getRowPrice() const + { + return dual_; + } + /// Reduced costs + inline double *dualColumnSolution() const + { + return reducedCost_; + } + inline const double *getReducedCost() const + { + return reducedCost_; + } + /// Row lower + inline double *rowLower() const + { + return rowLower_; + } + inline const double *getRowLower() const + { + return rowLower_; + } + /// Row upper + inline double *rowUpper() const + { + return rowUpper_; + } + inline const double *getRowUpper() const + { + return rowUpper_; + } + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + void setObjectiveCoefficient(int elementIndex, double elementValue); + /** Set an objective function coefficient */ + inline void setObjCoeff(int elementIndex, double elementValue) + { + setObjectiveCoefficient(elementIndex, elementValue); + } + + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + void setColumnLower(int elementIndex, double elementValue); + + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + void setColumnUpper(int elementIndex, double elementValue); + + /** Set a single column lower and upper bound */ + void setColumnBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of columns simultaneously
+ The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + void setColumnSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + inline void setColLower(int elementIndex, double elementValue) + { + setColumnLower(elementIndex, elementValue); + } + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + inline void setColUpper(int elementIndex, double elementValue) + { + setColumnUpper(elementIndex, elementValue); + } + + /** Set a single column lower and upper bound */ + inline void setColBounds(int elementIndex, + double lower, double upper) + { + setColumnBounds(elementIndex, lower, upper); + } + + /** Set the bounds on a number of columns simultaneously
+ @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + inline void setColSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList) + { + setColumnSetBounds(indexFirst, indexLast, boundList); + } + + /** Set a single row lower bound
+ Use -DBL_MAX for -infinity. */ + void setRowLower(int elementIndex, double elementValue); + + /** Set a single row upper bound
+ Use DBL_MAX for infinity. */ + void setRowUpper(int elementIndex, double elementValue); + + /** Set a single row lower and upper bound */ + void setRowBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of rows simultaneously
+ @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + either bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + void setRowSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + //@} + /// Scaling + inline const double *rowScale() const + { + return rowScale_; + } + inline const double *columnScale() const + { + return columnScale_; + } + inline const double *inverseRowScale() const + { + return inverseRowScale_; + } + inline const double *inverseColumnScale() const + { + return inverseColumnScale_; + } + inline double *mutableRowScale() const + { + return rowScale_; + } + inline double *mutableColumnScale() const + { + return columnScale_; + } + inline double *mutableInverseRowScale() const + { + return inverseRowScale_; + } + inline double *mutableInverseColumnScale() const + { + return inverseColumnScale_; + } + inline double *swapRowScale(double *newScale) + { + double *oldScale = rowScale_; + rowScale_ = newScale; + return oldScale; + } + void setRowScale(double *scale); + void setColumnScale(double *scale); + /// Scaling of objective + inline double objectiveScale() const + { + return objectiveScale_; + } + inline void setObjectiveScale(double value) + { + objectiveScale_ = value; + } + /// Scaling of rhs and bounds + inline double rhsScale() const + { + return rhsScale_; + } + inline void setRhsScale(double value) + { + rhsScale_ = value; + } + /// Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3 auto, 4 auto-but-as-initialSolve-in-bab + void scaling(int mode = 1); + /** If we constructed a "really" scaled model then this reverses the operation. + Quantities may not be exactly as they were before due to rounding errors */ + void unscale(); + /// Gets scalingFlag + inline int scalingFlag() const + { + return scalingFlag_; + } + /// Objective + inline double *objective() const + { + if (objective_) { + double offset; + return objective_->gradient(NULL, NULL, offset, false); + } else { + return NULL; + } + } + inline double *objective(const double *solution, double &offset, bool refresh = true) const + { + offset = 0.0; + if (objective_) { + return objective_->gradient(NULL, solution, offset, refresh); + } else { + return NULL; + } + } + inline const double *getObjCoefficients() const + { + if (objective_) { + double offset; + return objective_->gradient(NULL, NULL, offset, false); + } else { + return NULL; + } + } + /// Row Objective + inline double *rowObjective() const + { + return rowObjective_; + } + inline const double *getRowObjCoefficients() const + { + return rowObjective_; + } + /// Column Lower + inline double *columnLower() const + { + return columnLower_; + } + inline const double *getColLower() const + { + return columnLower_; + } + /// Column Upper + inline double *columnUpper() const + { + return columnUpper_; + } + inline const double *getColUpper() const + { + return columnUpper_; + } + /// Matrix (if not ClpPackedmatrix be careful about memory leak + inline CoinPackedMatrix *matrix() const + { + if (matrix_ == NULL) + return NULL; + else + return matrix_->getPackedMatrix(); + } + /// Number of elements in matrix + inline CoinBigIndex getNumElements() const + { + return matrix_->getNumElements(); + } + /** Small element value - elements less than this set to zero, + default is 1.0e-20 */ + inline double getSmallElementValue() const + { + return smallElement_; + } + inline void setSmallElementValue(double value) + { + smallElement_ = value; + } + /// Row Matrix + inline ClpMatrixBase *rowCopy() const + { + return rowCopy_; + } + /// Set new row matrix + void setNewRowCopy(ClpMatrixBase *newCopy); + /// Clp Matrix + inline ClpMatrixBase *clpMatrix() const + { + return matrix_; + } + /// Scaled ClpPackedMatrix + inline ClpPackedMatrix *clpScaledMatrix() const + { + return scaledMatrix_; + } + /// Sets pointer to scaled ClpPackedMatrix + inline void setClpScaledMatrix(ClpPackedMatrix *scaledMatrix) + { + delete scaledMatrix_; + scaledMatrix_ = scaledMatrix; + } + /// Swaps pointer to scaled ClpPackedMatrix + inline ClpPackedMatrix *swapScaledMatrix(ClpPackedMatrix *scaledMatrix) + { + ClpPackedMatrix *oldMatrix = scaledMatrix_; + scaledMatrix_ = scaledMatrix; + return oldMatrix; + } + /** Replace Clp Matrix (current is not deleted unless told to + and new is used) + So up to user to delete current. This was used where + matrices were being rotated. ClpModel takes ownership. + */ + void replaceMatrix(ClpMatrixBase *matrix, bool deleteCurrent = false); + /** Replace Clp Matrix (current is not deleted unless told to + and new is used) So up to user to delete current. This was used where + matrices were being rotated. This version changes CoinPackedMatrix + to ClpPackedMatrix. ClpModel takes ownership. + */ + inline void replaceMatrix(CoinPackedMatrix *newmatrix, + bool deleteCurrent = false) + { + replaceMatrix(new ClpPackedMatrix(newmatrix), deleteCurrent); + } + /// Objective value + inline double objectiveValue() const + { + return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; + } + inline void setObjectiveValue(double value) + { + objectiveValue_ = (value + dblParam_[ClpObjOffset]) / optimizationDirection_; + } + inline double getObjValue() const + { + return objectiveValue_ * optimizationDirection_ - dblParam_[ClpObjOffset]; + } + /// Integer information + inline char *integerInformation() const + { + return integerType_; + } + /** Infeasibility/unbounded ray (NULL returned if none/wrong) + Up to user to use delete [] on these arrays. */ + double *infeasibilityRay(bool fullRay = false) const; + double *unboundedRay() const; + /// For advanced users - no need to delete - sign not changed + inline double *ray() const + { + return ray_; + } + /// just test if infeasibility or unbounded Ray exists + inline bool rayExists() const + { + return (ray_ != NULL); + } + /// just delete ray if exists + inline void deleteRay() + { + delete[] ray_; + ray_ = NULL; + } + /// Access internal ray storage. Users should call infeasibilityRay() or unboundedRay() instead. + inline const double *internalRay() const + { + return ray_; + } + /// See if status (i.e. basis) array exists (partly for OsiClp) + inline bool statusExists() const + { + return (status_ != NULL); + } + /// Return address of status (i.e. basis) array (char[numberRows+numberColumns]) + inline unsigned char *statusArray() const + { + return status_; + } + /** Return copy of status (i.e. basis) array (char[numberRows+numberColumns]), + use delete [] */ + unsigned char *statusCopy() const; + /// Copy in status (basis) vector + void copyinStatus(const unsigned char *statusArray); + + /// User pointer for whatever reason + inline void setUserPointer(void *pointer) + { + userPointer_ = pointer; + } + inline void *getUserPointer() const + { + return userPointer_; + } + /// Trusted user pointer + inline void setTrustedUserPointer(ClpTrustedData *pointer) + { + trustedUserPointer_ = pointer; + } + inline ClpTrustedData *getTrustedUserPointer() const + { + return trustedUserPointer_; + } + /// What has changed in model (only for masochistic users) + inline int whatsChanged() const + { + return whatsChanged_; + } + inline void setWhatsChanged(int value) + { + whatsChanged_ = value; + } + /// Number of threads (not really being used) + inline int numberThreads() const + { + return numberThreads_; + } + inline void setNumberThreads(int value) + { + numberThreads_ = value; + } + //@} + /**@name Message handling */ + //@{ + /// Pass in Message handler (not deleted at end) + void passInMessageHandler(CoinMessageHandler *handler); + /// Pass in Message handler (not deleted at end) and return current + CoinMessageHandler *pushMessageHandler(CoinMessageHandler *handler, + bool &oldDefault); + /// back to previous message handler + void popMessageHandler(CoinMessageHandler *oldHandler, bool oldDefault); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + /// Overrides message handler with a default one + void setDefaultMessageHandler(); + /// Return handler + inline CoinMessageHandler *messageHandler() const + { + return handler_; + } + /// Return messages + inline CoinMessages messages() const + { + return messages_; + } + /// Return pointer to messages + inline CoinMessages *messagesPointer() + { + return &messages_; + } + /// Return Coin messages + inline CoinMessages coinMessages() const + { + return coinMessages_; + } + /// Return pointer to Coin messages + inline CoinMessages *coinMessagesPointer() + { + return &coinMessages_; + } + /** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ + inline void setLogLevel(int value) + { + handler_->setLogLevel(value); + } + inline int logLevel() const + { + return handler_->logLevel(); + } + /// Return true if default handler + inline bool defaultHandler() const + { + return defaultHandler_; + } + /// Pass in Event handler (cloned and deleted at end) + void passInEventHandler(const ClpEventHandler *eventHandler); + /// Event handler + inline ClpEventHandler *eventHandler() const + { + return eventHandler_; + } + /// Thread specific random number generator + inline CoinThreadRandom *randomNumberGenerator() + { + return &randomNumberGenerator_; + } + /// Thread specific random number generator + inline CoinThreadRandom &mutableRandomNumberGenerator() + { + return randomNumberGenerator_; + } + /// Set seed for thread specific random number generator + inline void setRandomSeed(int value) + { + randomNumberGenerator_.setSeed(value); + } + /// length of names (0 means no names0 + inline int lengthNames() const + { + return lengthNames_; + } +#ifndef CLP_NO_STD + /// length of names (0 means no names0 + inline void setLengthNames(int value) + { + lengthNames_ = value; + } + /// Row names + inline const std::vector< std::string > *rowNames() const + { + return &rowNames_; + } + inline const std::string &rowName(int iRow) const + { + return rowNames_[iRow]; + } + /// Return name or Rnnnnnnn + std::string getRowName(int iRow) const; + /// Column names + inline const std::vector< std::string > *columnNames() const + { + return &columnNames_; + } + inline const std::string &columnName(int iColumn) const + { + return columnNames_[iColumn]; + } + /// Return name or Cnnnnnnn + std::string getColumnName(int iColumn) const; +#endif + /// Objective methods + inline ClpObjective *objectiveAsObject() const + { + return objective_; + } + void setObjective(ClpObjective *objective); + inline void setObjectivePointer(ClpObjective *newobjective) + { + objective_ = newobjective; + } + /** Solve a problem with no elements - return status and + dual and primal infeasibilites */ + int emptyProblem(int *infeasNumber = NULL, double *infeasSum = NULL, bool printMessage = true); + + //@} + + /**@name Matrix times vector methods + They can be faster if scalar is +- 1 + These are covers so user need not worry about scaling + Also for simplex I am not using basic/non-basic split */ + //@{ + /** Return y + A * x * scalar in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + void times(double scalar, + const double *x, double *y) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + void transposeTimes(double scalar, + const double *x, double *y) const; + //@} + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the volume algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + + ** once it has been decided where solver sits this may be redone + */ + //@{ + /// Set an integer parameter + bool setIntParam(ClpIntParam key, int value); + /// Set an double parameter + bool setDblParam(ClpDblParam key, double value); +#ifndef CLP_NO_STD + /// Set an string parameter + bool setStrParam(ClpStrParam key, const std::string &value); +#endif + // Get an integer parameter + inline bool getIntParam(ClpIntParam key, int &value) const + { + if (key < ClpLastIntParam) { + value = intParam_[key]; + return true; + } else { + return false; + } + } + // Get an double parameter + inline bool getDblParam(ClpDblParam key, double &value) const + { + if (key < ClpLastDblParam) { + value = dblParam_[key]; + return true; + } else { + return false; + } + } +#ifndef CLP_NO_STD + // Get a string parameter + inline bool getStrParam(ClpStrParam key, std::string &value) const + { + if (key < ClpLastStrParam) { + value = strParam_[key]; + return true; + } else { + return false; + } + } +#endif + /// Create C++ lines to get to current state + void generateCpp(FILE *fp); + /** For advanced options + 1 - Don't keep changing infeasibility weight + 2 - Keep nonLinearCost round solves + 4 - Force outgoing variables to exact bound (primal) + 8 - Safe to use dense initial factorization + 16 -Just use basic variables for operation if column generation + 32 -Create ray even in BAB + 64 -Treat problem as feasible until last minute (i.e. minimize infeasibilities) + 128 - Switch off all matrix sanity checks + 256 - No row copy + 512 - If not in values pass, solution guaranteed, skip as much as possible + 1024 - In branch and bound + 2048 - Don't bother to re-factorize if < 20 iterations + 4096 - Skip some optimality checks + 8192 - Do Primal when cleaning up primal + 16384 - In fast dual (so we can switch off things) + 32768 - called from Osi + 65536 - keep arrays around as much as possible (also use maximumR/C) + 131072 - transposeTimes is -1.0 and can skip basic and fixed + 262144 - extra copy of scaled matrix + 524288 - Clp fast dual + 1048576 - don't need to finish dual (can return 3) + 2097152 - ray even if >2 pivots AND if problem is "crunched" + 4194304 - don't scale integer variables + 8388608 - Idiot when not really sure about it + 16777216 - zero costs! + NOTE - many applications can call Clp but there may be some short cuts + which are taken which are not guaranteed safe from all applications. + Vetted applications will have a bit set and the code may test this + At present I expect a few such applications - if too many I will + have to re-think. It is up to application owner to change the code + if she/he needs these short cuts. I will not debug unless in Coin + repository. See COIN_CLP_VETTED comments. + 0x01000000 is Cbc (and in branch and bound) + 0x02000000 is in a different branch and bound + */ + inline unsigned int specialOptions() const + { + return specialOptions_; + } + void setSpecialOptions(unsigned int value); +#define COIN_CBC_USING_CLP 0x01000000 + inline bool inCbcBranchAndBound() const + { + return (specialOptions_ & COIN_CBC_USING_CLP) != 0; + } + //@} + + /**@name private or protected methods */ + //@{ +protected: + /// Does most of deletion (0 = all, 1 = most) + void gutsOfDelete(int type); + /** Does most of copying + If trueCopy 0 then just points to arrays + If -1 leaves as much as possible */ + void gutsOfCopy(const ClpModel &rhs, int trueCopy = 1); + /// gets lower and upper bounds on rows + void getRowBound(int iRow, double &lower, double &upper) const; + /// puts in format I like - 4 array matrix - may make row copy + void gutsOfLoadModel(int numberRows, int numberColumns, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /// Does much of scaling + void gutsOfScaling(); + /// Objective value - always minimize + inline double rawObjectiveValue() const + { + return objectiveValue_; + } + /// If we are using maximumRows_ and Columns_ + inline bool permanentArrays() const + { + return (specialOptions_ & 65536) != 0; + } + /// Start using maximumRows_ and Columns_ + void startPermanentArrays(); + /// Stop using maximumRows_ and Columns_ + void stopPermanentArrays(); + /// Create row names as char ** + const char *const *rowNamesAsChar() const; + /// Create column names as char ** + const char *const *columnNamesAsChar() const; + /// Delete char * version of names + void deleteNamesAsChar(const char *const *names, int number) const; + /// On stopped - sets secondary status + void onStopped(); + //@} + + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + double optimizationDirection_; + /// Array of double parameters + double dblParam_[ClpLastDblParam]; + /// Objective value + double objectiveValue_; + /// Small element value + double smallElement_; + /// Scaling of objective + double objectiveScale_; + /// Scaling of rhs and bounds + double rhsScale_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// Row activities + double *rowActivity_; + /// Column activities + double *columnActivity_; + /// Duals + double *dual_; + /// Reduced costs + double *reducedCost_; + /// Row lower + double *rowLower_; + /// Row upper + double *rowUpper_; + /// Objective + ClpObjective *objective_; + /// Row Objective (? sign) - may be NULL + double *rowObjective_; + /// Column Lower + double *columnLower_; + /// Column Upper + double *columnUpper_; + /// Packed matrix + ClpMatrixBase *matrix_; + /// Row copy if wanted + ClpMatrixBase *rowCopy_; + /// Scaled packed matrix + ClpPackedMatrix *scaledMatrix_; + /// Infeasible/unbounded ray + double *ray_; + /// Row scale factors for matrix + double *rowScale_; + /// Column scale factors + double *columnScale_; + /// Inverse row scale factors for matrix (end of rowScale_) + double *inverseRowScale_; + /// Inverse column scale factors for matrix (end of columnScale_) + double *inverseColumnScale_; + /** Scale flag, 0 none, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic, + 5 geometric on rows */ + int scalingFlag_; + /** Status (i.e. basis) Region. I know that not all algorithms need a status + array, but it made sense for things like crossover and put + all permanent stuff in one place. No assumption is made + about what is in status array (although it might be good to reserve + bottom 3 bits (i.e. 0-7 numeric) for classic status). This + is number of columns + number of rows long (in that order). + */ + unsigned char *status_; + /// Integer information + char *integerType_; + /// User pointer for whatever reason + void *userPointer_; + /// Trusted user pointer e.g. for heuristics + ClpTrustedData *trustedUserPointer_; + /// Array of integer parameters + int intParam_[ClpLastIntParam]; + /// Number of iterations + int numberIterations_; + /** Solve type - 1 simplex, 2 simplex interface, 3 Interior.*/ + int solveType_; + /** Whats changed since last solve. This is a work in progress + It is designed so careful people can make go faster. + It is only used when startFinishOptions used in dual or primal. + Bit 1 - number of rows/columns has not changed (so work arrays valid) + 2 - matrix has not changed + 4 - if matrix has changed only by adding rows + 8 - if matrix has changed only by adding columns + 16 - row lbs not changed + 32 - row ubs not changed + 64 - column objective not changed + 128 - column lbs not changed + 256 - column ubs not changed + 512 - basis not changed (up to user to set this to 0) + top bits may be used internally + shift by 65336 is 3 all same, 1 all except col bounds + */ +#define ROW_COLUMN_COUNTS_SAME 1 +#define MATRIX_SAME 2 +#define MATRIX_JUST_ROWS_ADDED 4 +#define MATRIX_JUST_COLUMNS_ADDED 8 +#define ROW_LOWER_SAME 16 +#define ROW_UPPER_SAME 32 +#define OBJECTIVE_SAME 64 +#define COLUMN_LOWER_SAME 128 +#define COLUMN_UPPER_SAME 256 +#define BASIS_SAME 512 +#define ALL_SAME 65339 +#define ALL_SAME_EXCEPT_COLUMN_BOUNDS 65337 + unsigned int whatsChanged_; + /// Status of problem + int problemStatus_; + /// Secondary status of problem + int secondaryStatus_; + /// length of names (0 means no names) + int lengthNames_; + /// Number of threads (not very operational) + int numberThreads_; + /** For advanced options + See get and set for meaning + */ + unsigned int specialOptions_; + /// Message handler + CoinMessageHandler *handler_; + /// Flag to say if default handler (so delete) + bool defaultHandler_; + /// Thread specific random number generator + CoinThreadRandom randomNumberGenerator_; + /// Event handler + ClpEventHandler *eventHandler_; +#ifndef CLP_NO_STD + /// Row names + std::vector< std::string > rowNames_; + /// Column names + std::vector< std::string > columnNames_; +#endif + /// Messages + CoinMessages messages_; + /// Coin messages + CoinMessages coinMessages_; + /// Maximum number of columns in model + int maximumColumns_; + /// Maximum number of rows in model + int maximumRows_; + /// Maximum number of columns (internal arrays) in model + int maximumInternalColumns_; + /// Maximum number of rows (internal arrays) in model + int maximumInternalRows_; + /// Base packed matrix + CoinPackedMatrix baseMatrix_; + /// Base row copy + CoinPackedMatrix baseRowCopy_; + /// Saved row scale factors for matrix + double *savedRowScale_; + /// Saved column scale factors + double *savedColumnScale_; +#ifndef CLP_NO_STD + /// Array of string parameters + std::string strParam_[ClpLastStrParam]; +#endif + //@} +}; +/** This is a tiny class where data can be saved round calls. + */ +class ClpDataSave { + +public: + /**@name Constructors and destructor + */ + //@{ + /// Default constructor + ClpDataSave(); + + /// Copy constructor. + ClpDataSave(const ClpDataSave &); + /// Assignment operator. This copies the data + ClpDataSave &operator=(const ClpDataSave &rhs); + /// Destructor + ~ClpDataSave(); + + //@} + + ////////////////// data ////////////////// +public: + /**@name data - with same names as in other classes*/ + //@{ + double dualBound_; + double infeasibilityCost_; + double pivotTolerance_; + double zeroFactorizationTolerance_; + double zeroSimplexTolerance_; + double acceptablePivot_; + double objectiveScale_; + int sparseThreshold_; + int perturbation_; + int forceFactorization_; + int scalingFlag_; + unsigned int specialOptions_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNetworkMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNetworkMatrix.hpp new file mode 100644 index 000000000..20a911100 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNetworkMatrix.hpp @@ -0,0 +1,235 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpNetworkMatrix_H +#define ClpNetworkMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a simple network matrix as derived from ClpMatrixBase. + +If you want more sophisticated version then you could inherit from this. +Also you might want to allow networks with gain */ + +class ClpNetworkMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const + { + return true; + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const + { + return 2 * numberColumns_; + } + /** Number of columns. */ + virtual int getNumCols() const + { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const + { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const + { + return indices_; + } + + virtual const CoinBigIndex *getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const; + + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel); + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase *const *columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase *const *rows); +#ifndef SLIM_CLP + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); +#endif + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis( + const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex *dubiousWeights(const ClpSimplex *model, int *inputWeights) const; + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double &smallestNegative, double &largestNegative, + double &smallestPositive, double &largestPositive); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed format + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + virtual void releasePackedMatrix() const; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void times(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale, double *spare = NULL) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + //@} + + /**@name Other */ + //@{ + /// Return true if really network, false if has slacks + inline bool trueNetwork() const + { + return trueNetwork_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNetworkMatrix(); + /** Constructor from two arrays */ + ClpNetworkMatrix(int numberColumns, const int *head, + const int *tail); + /** Destructor */ + virtual ~ClpNetworkMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpNetworkMatrix(const ClpNetworkMatrix &); + /** The copy constructor from an CoinNetworkMatrix. */ + ClpNetworkMatrix(const CoinPackedMatrix &); + + ClpNetworkMatrix &operator=(const ClpNetworkMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpNetworkMatrix(const ClpNetworkMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// For fake CoinPackedMatrix + mutable CoinPackedMatrix *matrix_; + mutable int *lengths_; + /// Data -1, then +1 rows in pairs (row==-1 if one entry) + int *indices_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// True if all entries have two elements + bool trueNetwork_; + + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNode.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNode.hpp new file mode 100644 index 000000000..ca77ba9fd --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNode.hpp @@ -0,0 +1,364 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpNode_H +#define ClpNode_H + +#include "CoinPragma.hpp" + +// This implements all stuff for Clp fathom +/** This contains what is in a Clp "node" + + */ + +class ClpFactorization; +class ClpDualRowSteepest; +class ClpNodeStuff; +class ClpNode { + +public: + /**@name Useful methods */ + //@{ + /** Applies node to model + 0 - just tree bounds + 1 - tree bounds and basis etc + 2 - saved bounds and basis etc + */ + void applyNode(ClpSimplex *model, int doBoundsEtc); + /// Choose a new variable + void chooseVariable(ClpSimplex *model, ClpNodeStuff *info); + /// Fix on reduced costs + int fixOnReducedCosts(ClpSimplex *model); + /// Create odd arrays + void createArrays(ClpSimplex *model); + /// Clean up as crunch is different model + void cleanUpForCrunch(); + //@} + + /**@name Gets and sets */ + //@{ + /// Objective value + inline double objectiveValue() const + { + return objectiveValue_; + } + /// Set objective value + inline void setObjectiveValue(double value) + { + objectiveValue_ = value; + } + /// Primal solution + inline const double *primalSolution() const + { + return primalSolution_; + } + /// Dual solution + inline const double *dualSolution() const + { + return dualSolution_; + } + /// Initial value of integer variable + inline double branchingValue() const + { + return branchingValue_; + } + /// Sum infeasibilities + inline double sumInfeasibilities() const + { + return sumInfeasibilities_; + } + /// Number infeasibilities + inline int numberInfeasibilities() const + { + return numberInfeasibilities_; + } + /// Relative depth + inline int depth() const + { + return depth_; + } + /// Estimated solution value + inline double estimatedSolution() const + { + return estimatedSolution_; + } + /** Way for integer variable -1 down , +1 up */ + int way() const; + /// Return true if branch exhausted + bool fathomed() const; + /// Change state of variable i.e. go other way + void changeState(); + /// Sequence number of integer variable (-1 if none) + inline int sequence() const + { + return sequence_; + } + /// If odd arrays exist + inline bool oddArraysExist() const + { + return lower_ != NULL; + } + /// Status array + inline const unsigned char *statusArray() const + { + return status_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNode(); + /// Constructor from model + ClpNode(ClpSimplex *model, const ClpNodeStuff *stuff, int depth); + /// Does work of constructor (partly so gdb will work) + void gutsOfConstructor(ClpSimplex *model, const ClpNodeStuff *stuff, + int arraysExist, int depth); + /** Destructor */ + virtual ~ClpNode(); + //@} + + /**@name Copy methods (at present illegal - will abort) */ + //@{ + /** The copy constructor. */ + ClpNode(const ClpNode &); + /// Operator = + ClpNode &operator=(const ClpNode &); + //@} + +protected: + // For state of branch + typedef struct { + unsigned int firstBranch : 1; // nonzero if first branch on variable is up + unsigned int branch : 2; // 0 means do first branch next, 1 second, 2 finished + unsigned int spare : 29; + } branchState; + /**@name Data */ + //@{ + /// Initial value of integer variable + double branchingValue_; + /// Value of objective + double objectiveValue_; + /// Sum of infeasibilities + double sumInfeasibilities_; + /// Estimated solution value + double estimatedSolution_; + /// Factorization + ClpFactorization *factorization_; + /// Steepest edge weights + ClpDualRowSteepest *weights_; + /// Status vector + unsigned char *status_; + /// Primal solution + double *primalSolution_; + /// Dual solution + double *dualSolution_; + /// Integer lower bounds (only used in fathomMany) + int *lower_; + /// Integer upper bounds (only used in fathomMany) + int *upper_; + /// Pivot variables for factorization + int *pivotVariables_; + /// Variables fixed by reduced costs (at end of branch) 0x10000000 added if fixed to UB + int *fixed_; + /// State of branch + branchState branchState_; + /// Sequence number of integer variable (-1 if none) + int sequence_; + /// Number of infeasibilities + int numberInfeasibilities_; + /// Relative depth + int depth_; + /// Number fixed by reduced cost + int numberFixed_; + /// Flags - 1 duals scaled + int flags_; + /// Maximum number fixed by reduced cost + int maximumFixed_; + /// Maximum rows so far + int maximumRows_; + /// Maximum columns so far + int maximumColumns_; + /// Maximum Integers so far + int maximumIntegers_; + //@} +}; +class ClpNodeStuff { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpNodeStuff(); + /** Destructor */ + virtual ~ClpNodeStuff(); + //@} + + /**@name Copy methods (only copies ints etc, nulls arrays) */ + //@{ + /** The copy constructor. */ + ClpNodeStuff(const ClpNodeStuff &); + /// Operator = + ClpNodeStuff &operator=(const ClpNodeStuff &); + /// Zaps stuff 1 - arrays, 2 ints, 3 both + void zap(int type); + //@} + + /**@name Fill methods */ + //@{ + /** Fill with pseudocosts */ + void fillPseudoCosts(const double *down, const double *up, + const int *priority, + const int *numberDown, const int *numberUp, + const int *numberDownInfeasible, const int *numberUpInfeasible, + int number); + /// Update pseudo costs + void update(int way, int sequence, double change, bool feasible); + /// Return maximum number of nodes + int maximumNodes() const; + /// Return maximum space for nodes + int maximumSpace() const; + //@} + +public: + /**@name Data */ + //@{ + /// Integer tolerance + double integerTolerance_; + /// Integer increment + double integerIncrement_; + /// Small change in branch + double smallChange_; + /// Down pseudo costs + double *downPseudo_; + /// Up pseudo costs + double *upPseudo_; + /// Priority + int *priority_; + /// Number of times down + int *numberDown_; + /// Number of times up + int *numberUp_; + /// Number of times down infeasible + int *numberDownInfeasible_; + /// Number of times up infeasible + int *numberUpInfeasible_; + /// Copy of costs (local) + double *saveCosts_; + /// Array of ClpNodes + ClpNode **nodeInfo_; + /// Large model if crunched + ClpSimplex *large_; + /// Which rows in large model + int *whichRow_; + /// Which columns in large model + int *whichColumn_; +#ifndef NO_FATHOM_PRINT + /// Cbc's message handler + CoinMessageHandler *handler_; +#endif + /// Number bounds in large model + int nBound_; + /// Save of specialOptions_ (local) + int saveOptions_; + /** Options to pass to solver + 1 - create external reduced costs for columns + 2 - create external reduced costs for rows + 4 - create external row activity (columns always done) + Above only done if feasible + 32 - just create up to nDepth_+1 nodes + 65536 - set if activated + */ + int solverOptions_; + /// Maximum number of nodes to do + int maximumNodes_; + /// Number before trust from CbcModel + int numberBeforeTrust_; + /// State of search from CbcModel + int stateOfSearch_; + /// Number deep + int nDepth_; + /// Number nodes returned (-1 if fathom aborted) + int nNodes_; + /// Number of nodes explored + int numberNodesExplored_; + /// Number of iterations + int numberIterations_; + /// Type of presolve - 0 none, 1 crunch + int presolveType_; +#ifndef NO_FATHOM_PRINT + /// Depth passed in + int startingDepth_; + /// Node at which called + int nodeCalled_; +#endif + //@} +}; +class ClpHashValue { + +public: + /**@name Useful methods */ + //@{ + /// Return index or -1 if not found + int index(double value) const; + /// Add value to list and return index + int addValue(double value); + /// Number of different entries + inline int numberEntries() const + { + return numberHash_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpHashValue(); + /** Useful constructor. */ + ClpHashValue(ClpSimplex *model); + /** Destructor */ + virtual ~ClpHashValue(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpHashValue(const ClpHashValue &); + /// = + ClpHashValue &operator=(const ClpHashValue &); + //@} +private: + /**@name private stuff */ + //@{ + /** returns hash */ + int hash(double value) const; + /// Resizes + void resize(bool increaseMax); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Data + // for hashing + typedef struct { + double value; + int index, next; + } CoinHashLink; + /// Hash table + mutable CoinHashLink *hash_; + /// Number of entries in hash table + int numberHash_; + /// Maximum number of entries in hash table i.e. size + int maxHash_; + /// Last used space + int lastUsed_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNonLinearCost.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNonLinearCost.hpp new file mode 100644 index 000000000..5bf801c05 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpNonLinearCost.hpp @@ -0,0 +1,432 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpNonLinearCost_H +#define ClpNonLinearCost_H + +#include "CoinPragma.hpp" + +class ClpSimplex; +class CoinIndexedVector; + +/** Trivial class to deal with non linear costs + + I don't make any explicit assumptions about convexity but I am + sure I do make implicit ones. + + One interesting idea for normal LP's will be to allow non-basic + variables to come into basis as infeasible i.e. if variable at + lower bound has very large positive reduced cost (when problem + is infeasible) could it reduce overall problem infeasibility more + by bringing it into basis below its lower bound. + + Another feature would be to automatically discover when problems + are convex piecewise linear and re-formulate to use non-linear. + I did some work on this many years ago on "grade" problems, but + while it improved primal interior point algorithms were much better + for that particular problem. +*/ +/* status has original status and current status + 0 - below lower so stored is upper + 1 - in range + 2 - above upper so stored is lower + 4 - (for current) - same as original +*/ +#define CLP_BELOW_LOWER 0 +#define CLP_FEASIBLE 1 +#define CLP_ABOVE_UPPER 2 +#define CLP_SAME 4 +inline int originalStatus(unsigned char status) +{ + return (status & 15); +} +inline int currentStatus(unsigned char status) +{ + return (status >> 4); +} +inline void setOriginalStatus(unsigned char &status, int value) +{ + status = static_cast< unsigned char >(status & ~15); + status = static_cast< unsigned char >(status | value); +} +inline void setCurrentStatus(unsigned char &status, int value) +{ + status = static_cast< unsigned char >(status & ~(15 << 4)); + status = static_cast< unsigned char >(status | (value << 4)); +} +inline void setInitialStatus(unsigned char &status) +{ + status = static_cast< unsigned char >(CLP_FEASIBLE | (CLP_SAME << 4)); +} +inline void setSameStatus(unsigned char &status) +{ + status = static_cast< unsigned char >(status & ~(15 << 4)); + status = static_cast< unsigned char >(status | (CLP_SAME << 4)); +} +// Use second version to get more speed +//#define FAST_CLPNON +#ifndef FAST_CLPNON +#define CLP_METHOD1 ((method_ & 1) != 0) +#define CLP_METHOD2 ((method_ & 2) != 0) +#else +#define CLP_METHOD1 (false) +#define CLP_METHOD2 (true) +#endif +class ClpNonLinearCost { + +public: +public: + /**@name Constructors, destructor */ + //@{ + /// Default constructor. + ClpNonLinearCost(); + /** Constructor from simplex. + This will just set up wasteful arrays for linear, but + later may do dual analysis and even finding duplicate columns . + */ + ClpNonLinearCost(ClpSimplex *model, int method = 1); + /** Constructor from simplex and list of non-linearities (columns only) + First lower of each column has to match real lower + Last lower has to be <= upper (if == then cost ignored) + This could obviously be changed to make more user friendly + */ + ClpNonLinearCost(ClpSimplex *model, const int *starts, + const double *lower, const double *cost); + /// Destructor + ~ClpNonLinearCost(); + // Copy + ClpNonLinearCost(const ClpNonLinearCost &); + // Assignment + ClpNonLinearCost &operator=(const ClpNonLinearCost &); + //@} + + /**@name Actual work in primal */ + //@{ + /** Changes infeasible costs and computes number and cost of infeas + Puts all non-basic (non free) variables to bounds + and all free variables to zero if oldTolerance is non-zero + - but does not move those <= oldTolerance away*/ + void checkInfeasibilities(double oldTolerance = 0.0); + /** Changes infeasible costs for each variable + The indices are row indices and need converting to sequences + */ + void checkInfeasibilities(int numberInArray, const int *index); + /** Puts back correct infeasible costs for each variable + The input indices are row indices and need converting to sequences + for costs. + On input array is empty (but indices exist). On exit just + changed costs will be stored as normal CoinIndexedVector + */ + void checkChanged(int numberInArray, CoinIndexedVector *update); + /** Goes through one bound for each variable. + If multiplier*work[iRow]>0 goes down, otherwise up. + The indices are row indices and need converting to sequences + Temporary offsets may be set + Rhs entries are increased + */ + void goThru(int numberInArray, double multiplier, + const int *index, const double *work, + double *rhs); + /** Takes off last iteration (i.e. offsets closer to 0) + */ + void goBack(int numberInArray, const int *index, + double *rhs); + /** Puts back correct infeasible costs for each variable + The input indices are row indices and need converting to sequences + for costs. + At the end of this all temporary offsets are zero + */ + void goBackAll(const CoinIndexedVector *update); + /// Temporary zeroing of feasible costs + void zapCosts(); + /// Refreshes costs always makes row costs zero + void refreshCosts(const double *columnCosts); + /// Puts feasible bounds into lower and upper + void feasibleBounds(); + /// Refresh - assuming regions OK + void refresh(); + /// Refresh one- assuming regions OK + void refresh(int iSequence); + /** Sets bounds and cost for one variable + Returns change in cost + May need to be inline for speed */ + double setOne(int sequence, double solutionValue); + /** Sets bounds and infeasible cost and true cost for one variable + This is for gub and column generation etc */ + void setOne(int sequence, double solutionValue, double lowerValue, double upperValue, + double costValue = 0.0); + /** Sets bounds and cost for outgoing variable + may change value + Returns direction */ + int setOneOutgoing(int sequence, double &solutionValue); + /// Returns nearest bound + double nearest(int sequence, double solutionValue); + /** Returns change in cost - one down if alpha >0.0, up if <0.0 + Value is current - new + */ + inline double changeInCost(int sequence, double alpha) const + { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (alpha > 0.0) + returnValue = cost_[iRange] - cost_[iRange - 1]; + else + returnValue = cost_[iRange] - cost_[iRange + 1]; + } + if (CLP_METHOD2) { + returnValue = (alpha > 0.0) ? infeasibilityWeight_ : -infeasibilityWeight_; + } + return returnValue; + } + inline double changeUpInCost(int sequence) const + { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (iRange + 1 != start_[sequence + 1] && !infeasible(iRange + 1)) + returnValue = cost_[iRange] - cost_[iRange + 1]; + else + returnValue = -1.0e100; + } + if (CLP_METHOD2) { + returnValue = -infeasibilityWeight_; + } + return returnValue; + } + inline double changeDownInCost(int sequence) const + { + double returnValue = 0.0; + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (iRange != start_[sequence] && !infeasible(iRange - 1)) + returnValue = cost_[iRange] - cost_[iRange - 1]; + else + returnValue = 1.0e100; + } + if (CLP_METHOD2) { + returnValue = infeasibilityWeight_; + } + return returnValue; + } + /// This also updates next bound + inline double changeInCost(int sequence, double alpha, double &rhs) + { + double returnValue = 0.0; +#ifdef NONLIN_DEBUG + double saveRhs = rhs; +#endif + if (CLP_METHOD1) { + int iRange = whichRange_[sequence] + offset_[sequence]; + if (alpha > 0.0) { + assert(iRange - 1 >= start_[sequence]); + offset_[sequence]--; + rhs += lower_[iRange] - lower_[iRange - 1]; + returnValue = alpha * (cost_[iRange] - cost_[iRange - 1]); + } else { + assert(iRange + 1 < start_[sequence + 1] - 1); + offset_[sequence]++; + rhs += lower_[iRange + 2] - lower_[iRange + 1]; + returnValue = alpha * (cost_[iRange] - cost_[iRange + 1]); + } + } + if (CLP_METHOD2) { +#ifdef NONLIN_DEBUG + double saveRhs1 = rhs; + rhs = saveRhs; +#endif + unsigned char iStatus = status_[sequence]; + int iWhere = currentStatus(iStatus); + if (iWhere == CLP_SAME) + iWhere = originalStatus(iStatus); + // rhs always increases + if (iWhere == CLP_FEASIBLE) { + if (alpha > 0.0) { + // going below + iWhere = CLP_BELOW_LOWER; + rhs = COIN_DBL_MAX; + } else { + // going above + iWhere = CLP_ABOVE_UPPER; + rhs = COIN_DBL_MAX; + } + } else if (iWhere == CLP_BELOW_LOWER) { + assert(alpha < 0); + // going feasible + iWhere = CLP_FEASIBLE; + rhs += bound_[sequence] - model_->upperRegion()[sequence]; + } else { + assert(iWhere == CLP_ABOVE_UPPER); + // going feasible + iWhere = CLP_FEASIBLE; + rhs += model_->lowerRegion()[sequence] - bound_[sequence]; + } + setCurrentStatus(status_[sequence], iWhere); +#ifdef NONLIN_DEBUG + assert(saveRhs1 == rhs); +#endif + returnValue = fabs(alpha) * infeasibilityWeight_; + } + return returnValue; + } + /// Returns current lower bound + inline double lower(int sequence) const + { + return lower_[whichRange_[sequence] + offset_[sequence]]; + } + /// Returns current upper bound + inline double upper(int sequence) const + { + return lower_[whichRange_[sequence] + offset_[sequence] + 1]; + } + /// Returns current cost + inline double cost(int sequence) const + { + return cost_[whichRange_[sequence] + offset_[sequence]]; + } + /// Returns full status + inline int fullStatus(int sequence) const + { + return status_[sequence]; + } + /// Returns if changed from beginning of iteration + inline bool changed(int sequence) const + { + return (status_[sequence] & 64) == 0; + } + + //@} + + /**@name Gets and sets */ + //@{ + /// Number of infeasibilities + inline int numberInfeasibilities() const + { + return numberInfeasibilities_; + } + /// Change in cost + inline double changeInCost() const + { + return changeCost_; + } + /// Feasible cost + inline double feasibleCost() const + { + return feasibleCost_; + } + /// Feasible cost with offset and direction (i.e. for reporting) + double feasibleReportCost() const; + /// Sum of infeasibilities + inline double sumInfeasibilities() const + { + return sumInfeasibilities_; + } + /// Largest infeasibility + inline double largestInfeasibility() const + { + return largestInfeasibility_; + } + /// Average theta + inline double averageTheta() const + { + return averageTheta_; + } + inline void setAverageTheta(double value) + { + averageTheta_ = value; + } + inline void setChangeInCost(double value) + { + changeCost_ = value; + } + inline void setMethod(int value) + { + method_ = value; + } + /// See if may want to look both ways + inline bool lookBothWays() const + { + return bothWays_; + } + //@} + ///@name Private functions to deal with infeasible regions + inline bool infeasible(int i) const + { + return ((infeasible_[i >> 5] >> (i & 31)) & 1) != 0; + } + inline void setInfeasible(int i, bool trueFalse) + { + unsigned int &value = infeasible_[i >> 5]; + int bit = i & 31; + if (trueFalse) + value |= (1 << bit); + else + value &= ~(1 << bit); + } + inline unsigned char *statusArray() const + { + return status_; + } + /// For debug + void validate(); + //@} + +private: + /**@name Data members */ + //@{ + /// Change in cost because of infeasibilities + double changeCost_; + /// Feasible cost + double feasibleCost_; + /// Current infeasibility weight + double infeasibilityWeight_; + /// Largest infeasibility + double largestInfeasibility_; + /// Sum of infeasibilities + double sumInfeasibilities_; + /// Average theta - kept here as only for primal + double averageTheta_; + /// Number of rows (mainly for checking and copy) + int numberRows_; + /// Number of columns (mainly for checking and copy) + int numberColumns_; + /// Starts for each entry (columns then rows) + int *start_; + /// Range for each entry (columns then rows) + int *whichRange_; + /// Temporary range offset for each entry (columns then rows) + int *offset_; + /** Lower bound for each range (upper bound is next lower). + For various reasons there is always an infeasible range + at bottom - even if lower bound is - infinity */ + double *lower_; + /// Cost for each range + double *cost_; + /// Model + ClpSimplex *model_; + // Array to say which regions are infeasible + unsigned int *infeasible_; + /// Number of infeasibilities found + int numberInfeasibilities_; + // new stuff + /// Contains status at beginning and current + unsigned char *status_; + /// Bound which has been replaced in lower_ or upper_ + double *bound_; + /// Feasible cost array + double *cost2_; + /// Method 1 old, 2 new, 3 both! + int method_; + /// If all non-linear costs convex + bool convex_; + /// If we should look both ways for djs + bool bothWays_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpObjective.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpObjective.hpp new file mode 100644 index 000000000..59f9754ed --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpObjective.hpp @@ -0,0 +1,142 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpObjective_H +#define ClpObjective_H + +//############################################################################# +class ClpSimplex; +class ClpModel; + +/** Objective Abstract Base Class + +Abstract Base Class for describing an objective function + +*/ +class ClpObjective { + +public: + ///@name Stuff + //@{ + + /** Returns gradient. If Linear then solution may be NULL, + also returns an offset (to be added to current one) + If refresh is false then uses last solution + Uses model for scaling + includeLinear 0 - no, 1 as is, 2 as feasible + */ + virtual double *gradient(const ClpSimplex *model, + const double *solution, + double &offset, bool refresh, + int includeLinear = 2) + = 0; + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex *model, double *region, + bool useFeasibleCosts) + = 0; + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex *model, + const double *solution, + const double *change, + double maximumTheta, + double ¤tObj, + double &predictedObj, + double &thetaObj) + = 0; + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex *model, const double *solution) const = 0; + /// Resize objective + virtual void resize(int newNumberColumns) = 0; + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int *which) = 0; + /// Scale objective + virtual void reallyScale(const double *columnScale) = 0; + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char *which); + /// Say we have new primal solution - so may need to recompute + virtual void newXValues() {} + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpObjective(); + + /// Copy constructor + ClpObjective(const ClpObjective &); + + /// Assignment operator + ClpObjective &operator=(const ClpObjective &rhs); + + /// Destructor + virtual ~ClpObjective(); + + /// Clone + virtual ClpObjective *clone() const = 0; + /** Subset clone. Duplicates are allowed + and order is as given. + Derived classes need not provide this as it may not always make + sense */ + virtual ClpObjective *subsetClone(int numberColumns, + const int *whichColumns) const; + + //@} + + ///@name Other + //@{ + /// Returns type (above 63 is extra information) + inline int type() const + { + return type_; + } + /// Sets type (above 63 is extra information) + inline void setType(int value) + { + type_ = value; + } + /// Whether activated + inline int activated() const + { + return activated_; + } + /// Set whether activated + inline void setActivated(int value) + { + activated_ = value; + } + + /// Objective offset + inline double nonlinearOffset() const + { + return offset_; + } + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Value of non-linear part of objective + double offset_; + /// Type of objective - linear is 1 + int type_; + /// Whether activated + int activated_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowDantzig.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowDantzig.hpp new file mode 100644 index 000000000..8ff64a6f0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowDantzig.hpp @@ -0,0 +1,84 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +/* + Authors + + Jeremy Omer + + Last update: april 10, 2015 + + */ + +#ifndef ClpPEDualRowDantzig_H +#define ClpPEDualRowDantzig_H + +#include "ClpDualRowPivot.hpp" +#include "ClpDualRowDantzig.hpp" +#include "ClpSimplex.hpp" +#include "CoinIndexedVector.hpp" +#include "ClpFactorization.hpp" +#include "ClpNonLinearCost.hpp" +#include "ClpSimplexDual.hpp" +#include "ClpPackedMatrix.hpp" +#include "ClpPESimplex.hpp" + +class ClpPEDualRowDantzig : public ClpDualRowDantzig { + +public: + /// Default Constructor + ClpPEDualRowDantzig(double psi = 0.5); + + /// Copy constructor + ClpPEDualRowDantzig(const ClpPEDualRowDantzig &); + + /// Assignment operator + ClpPEDualRowDantzig &operator=(const ClpPEDualRowDantzig &rhs); + + /// Destructor + virtual ~ClpPEDualRowDantzig(); + + /// Clone + virtual ClpDualRowPivot *clone(bool copyData = true) const; + +public: + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /// Update the compatible variables and + /// call the base class method to update weights + virtual double updateWeights(CoinIndexedVector *input, + CoinIndexedVector *spare, + CoinIndexedVector *spare2, + CoinIndexedVector *updatedColumn); + + /** Save weights - this may initialize weights as well + This is as parent but may initialize ClpPESimplex + */ + virtual void saveWeights(ClpSimplex *model, int mode); + //@} + + //--------------------------------------------------------------------------- + +private: + /* this PESimplex object is used to identify the compatible variables */ + ClpPESimplex *modelPE_; + + /* psi is the factor used in the bi-dimensional pricing, it is < 1 and + 1/psi grows with the priority given to compatible variables */ + double psi_; + + /* useful counters for the update of the set of compatible variables */ + int iCurrent_; + int iInterval_; + + /* record if previous iterations concluded that compatibles should not be checked */ + bool updateCompatibles_; + int coDegenCompatibles_, coConsecutiveCompatibles_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowSteepest.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowSteepest.hpp new file mode 100644 index 000000000..79b4ccf6e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEDualRowSteepest.hpp @@ -0,0 +1,100 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +/* + Authors + + Jeremy Omer + + Last update: april 10, 2015 + + */ + +#ifndef ClpPEDualRowSteepest_H +#define ClpPEDualRowSteepest_H + +#include "ClpDualRowSteepest.hpp" +#include "ClpPESimplex.hpp" +class CoinIndexedVector; + +//############################################################################# + +/** Dual Row Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + +class ClpPEDualRowSteepest : public ClpDualRowSteepest { + +public: + /** Default Constructor + mode: 0 is uninitialized, 1 full, 2 is partial uninitialized, + 3 starts as 2 but may switch to 1. + By partial is meant that the weights are updated as normal + but only part of the infeasible basic variables are scanned. + This can be faster on very easy problems. + */ + ClpPEDualRowSteepest(double psi = 0.5, int mode = 3); + + /// Copy constructor + ClpPEDualRowSteepest(const ClpPEDualRowSteepest &); + + /// Assignment operator + ClpPEDualRowSteepest &operator=(const ClpPEDualRowSteepest &rhs); + + /// Destructor + virtual ~ClpPEDualRowSteepest(); + + /// Clone + virtual ClpDualRowPivot *clone(bool copyData = true) const; + +public: + ///@name Algorithmic methods + //@{ + + /// Returns pivot row, -1 if none + virtual int pivotRow(); + + /** Save weights - this may initialize weights as well + This is as parent but may initialize ClpPESimplex + */ + virtual void saveWeights(ClpSimplex *model, int mode); + /** Updates primal solution (and maybe list of candidates) + Uses input vector which it deletes + Computes change in objective function + As ordinary steepest but checks for zero moves + */ + virtual void updatePrimalSolution(CoinIndexedVector *input, + double theta, + double &changeInObjective); + //@} + + // Psi + inline double psi() const + { + return psi_; + } + + //--------------------------------------------------------------------------- + +private: + /* this PESimplex object is used to identify the compatible variables */ + ClpPESimplex *modelPE_; + + /* psi is the factor used in the bi-dimensional pricing, it is < 1 and + 1/psi grows with the priority given to compatible variables */ + double psi_; + + /* useful counters for the update of the set of compatible variables */ + int iCurrent_; + int iInterval_; + + /* record if previous iterations concluded that compatibles should not be checked */ + bool updateCompatibles_; + int coDegenCompatibles_, coConsecutiveCompatibles_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnDantzig.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnDantzig.hpp new file mode 100644 index 000000000..c067507d8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnDantzig.hpp @@ -0,0 +1,71 @@ +/* + Authors + + Jeremy Omer, Mehdi Towhidi + + Last update: april 10, 2015 + + */ + +#ifndef ClpPEPrimalColumnDantzig_H +#define ClpPEPrimalColumnDantzig_H + +#include "ClpPrimalColumnDantzig.hpp" +#include "ClpPrimalColumnPivot.hpp" +#include "ClpSimplex.hpp" +#include "CoinIndexedVector.hpp" +#include "ClpFactorization.hpp" +#include "ClpNonLinearCost.hpp" +#include "ClpSimplexPrimal.hpp" +#include "ClpPackedMatrix.hpp" +#include "ClpPESimplex.hpp" + +class ClpPEPrimalColumnDantzig : public ClpPrimalColumnDantzig { + +public: + /** constructors */ + ClpPEPrimalColumnDantzig(double psi = 0.5); + ClpPEPrimalColumnDantzig(const ClpPEPrimalColumnDantzig &); //copy constructor + + /** destructor */ + ~ClpPEPrimalColumnDantzig(); + + /** assignment operator */ + ClpPEPrimalColumnDantzig &operator=(const ClpPEPrimalColumnDantzig &rhs); + + /** clone */ + ClpPrimalColumnPivot *clone(bool copyData = true) const; + + virtual int pivotColumn(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + + //@} + /** Save weights - this may initialize weights as well + This is as parent but may initialize ClpPESimplex + */ + virtual void saveWeights(ClpSimplex *model, int mode); + //--------------------------------------------------------------------------- +private: + /* this PESimplex object is used to identify the compatible variables */ + ClpPESimplex *modelPE_; + + /* psi is the factor used in the bi-dimensional pricing, it is < 1 and + 1/psi grows with the priority given to compatible variables */ + double psi_; + + /* useful counters for the update of the set of compatible variables */ + int iCurrent_; + int iInterval_; + + /* record if previous iterations concluded that compatibles should not be checked */ + int coDegenCompatibles_; + int coConsecutiveCompatibles_; + bool updateCompatibles_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnSteepest.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnSteepest.hpp new file mode 100644 index 000000000..ac4983f4a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPEPrimalColumnSteepest.hpp @@ -0,0 +1,107 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +/* + Authors + + Jeremy Omer, Mehdi Towhidi + + Last update: april 10, 2015 + + */ + +#ifndef ClpPEPrimalColumnSteepest_H +#define ClpPEPrimalColumnSteepest_H + +#include "ClpPrimalColumnSteepest.hpp" +#include "ClpFactorization.hpp" +#include "ClpPESimplex.hpp" +#include + +//############################################################################# +class CoinIndexedVector; + +/** Primal Column Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + +class ClpPEPrimalColumnSteepest : public ClpPrimalColumnSteepest { +public: + ///@name Constructors and destructors + //@{ + /** Default Constructor + 0 is exact devex, 1 full steepest, 2 is partial exact devex + 3 switches between 0 and 2 depending on factorization + 4 starts as partial dantzig/devex but then may switch between 0 and 2. + By partial exact devex is meant that the weights are updated as normal + but only part of the nonbasic variables are scanned. + This can be faster on very easy problems. + */ + ClpPEPrimalColumnSteepest(double psi = 0.5, int mode = 3); + + /// Copy constructor + ClpPEPrimalColumnSteepest(const ClpPEPrimalColumnSteepest &rhs); + + /// Assignment operator + ClpPEPrimalColumnSteepest &operator=(const ClpPEPrimalColumnSteepest &rhs); + + /// Destructor + virtual ~ClpPEPrimalColumnSteepest(); + + /// Clone + virtual ClpPrimalColumnPivot *clone(bool copyData = true) const; + +public: + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none. + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + Parts of operation split out into separate functions for + profiling and speed + */ + virtual int pivotColumn(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + + //@} + /** Save weights - this may initialize weights as well + This is as parent but may initialize ClpPESimplex + */ + virtual void saveWeights(ClpSimplex *model, int mode); + /// Updates weights - as ordinary but checks for zero moves + virtual void updateWeights(CoinIndexedVector *input); + //--------------------------------------------------------------------------- + // Psi + inline double psi() const + { + return psi_; + } + +private: + /* this PESimplex object is used to identify the compatible variables */ + ClpPESimplex *modelPE_; + + /* psi is the factor used in the bi-dimensional pricing, it is < 1 and + 1/psi grows with the priority given to compatible variables */ + double psi_; + + /* useful counters for the update of the set of compatible variables */ + int iCurrent_; + int iInterval_; + + /* record if previous iterations concluded that compatibles should not be checked */ + int coDegenCompatibles_; + int coConsecutiveCompatibles_; + bool updateCompatibles_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPESimplex.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPESimplex.hpp new file mode 100644 index 000000000..530fc127e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPESimplex.hpp @@ -0,0 +1,231 @@ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +/* + Authors + + Jeremy Omer + + Last update: june 10, 2014 + + */ + +#ifndef ClpPESimplex_H +#define ClpPESimplex_H + +#include "ClpSimplex.hpp" +#include "CoinIndexedVector.hpp" +#include "ClpPackedMatrix.hpp" +#include "CoinTime.hpp" + +#include +#include + +// #define PE_DEBUG 0 + +/** SHARED METHODS FOR USEFUL ALGEBRAIC OPERATIONS */ + +/** inner product between a coin vector and a pointer */ +double PEdot(CoinIndexedVector &v1, const double *v2); + +/** inner product between two coin vectors + call the function with the sparser vector first for efficiency */ +double PEdot(CoinIndexedVector &v1, CoinIndexedVector &v2); + +/** compute the product x^T*[A I] for the indices "which" of [A I] */ +void PEtransposeTimesSubsetAll(ClpSimplex *model, int number, const int *which, + const double *COIN_RESTRICT x, double *COIN_RESTRICT y, + const double *COIN_RESTRICT rowScale, + const double *COIN_RESTRICT columnScale); + +/** BASE CLASS FOR THE IMPROVED SIMPLEX +*/ +class ClpPESimplex { + +public: + /** Constructor */ + ClpPESimplex(ClpSimplex *model); + + /** Destructor */ + ~ClpPESimplex(); + + /** BASIC GET METHODS */ +public: + inline int coPrimalDegenerates() { return coPrimalDegenerates_; } + inline int coDualDegenerates() { return coDualDegenerates_; } + inline int coCompatibleCols() { return coCompatibleCols_; } + inline int coCompatibleRows() { return coCompatibleRows_; } + + inline bool isCompatibleCol(int sequence) { return isCompatibleCol_[sequence]; } + inline bool isCompatibleRow(int row) + { + assert(row >= 0 && row < numberRows_); + return isCompatibleRow_[row]; + } + + inline ClpSimplex *clpModel() { return model_; } + // check seems to be same model - returns false if size changed + bool checkSize(); + /** PUBLIC METHODS RELATED TO COMPATIBILITY */ +public: + /** Updates the set of variables that are not at their bounds */ + void updatePrimalDegenerates(); + + /** Updates the set of dual degenerate variables */ + void updateDualDegenerates(); + + /** Identify the primal compatible columns + The input argument is a temporary array that is needed for the Clp's BTRAN */ + void identifyCompatibleCols(int number, const int *which, + CoinIndexedVector *spareRow2, + CoinIndexedVector *wPrimal); + + /** Identify the dual compatible rows */ + void identifyCompatibleRows(CoinIndexedVector *spare, + CoinIndexedVector *wDual); + + /** Update the dual compatible rows */ + void updateCompatibleRows(int sequence); + + /** DEBUG AND DISPLAY METHODS */ +public: +#if PE_DEBUG >= 1 + /** Print the set of variables within their bounds */ + void printPrimalDegenerates(); + + /** Print the set of primal compatible variables */ + void printCompatibleCols(); + + /** Check that a nonbasic variable is indeed compatible */ + bool checkCompatibilityCol(int sequence, CoinIndexedVector *spareRow2); +#endif + + /** Check that a basic row is indeed compatible */ + bool checkCompatibilityRow(int pivotRow); + + /** Tracking the degenerate iterations after compatible pivots */ + inline double lastObjectiveValue() { return lastObjectiveValue_; } + inline void updateLastObjectiveValue() { lastObjectiveValue_ = model_->objectiveValue(); } + inline bool isDegeneratePivot() { return fabs(model_->objectiveValue() - lastObjectiveValue_) < model_->dualTolerance(); } + inline bool isLastPivotCompatible() { return isLastPivotCompatible_; } + inline void isLastPivotCompatible(bool yesOrNo) { isLastPivotCompatible_ = yesOrNo; } + + /** Start and stop the timer, and print the total recorded time */ + inline void startTimer() { timeTmp_ = CoinCpuTime(); } + inline void stopTimer() { timeCompatibility_ += CoinCpuTime() - timeTmp_; } + void printTimer(std::ostream &out); + inline double timeMultRandom() { return timeMultRandom_; } + inline double timeLinearSystem() { return timeLinearSystem_; } + inline double timeCompatibility() { return timeCompatibility_; } + + /** Update and return the number of degenerate pivots and variables */ + inline void addDegeneratePivot() { coDegeneratePivots_++; } + inline int coDegeneratePivots() { return coDegeneratePivots_; } + inline void addDegeneratePivotConsecutive() { coDegeneratePivotsConsecutive_++; } + inline void resetDegeneratePivotsConsecutive() { coDegeneratePivotsConsecutive_ = 0; } + inline int coDegeneratePivotsConsecutive() { return coDegeneratePivotsConsecutive_; } + void updateDualDegeneratesAvg(int coPivots); + inline double coDualDegeneratesAvg() { return coDualDegeneratesAvg_; } + void updatePrimalDegeneratesAvg(int coPivots); + inline double coPrimalDegeneratesAvg() { return coPrimalDegeneratesAvg_; } + inline double coCompatibleRowsAvg() { return coCompatibleRowsAvg_; } + void updateCompatibleRowsAvg(int coPivots); + inline double coCompatibleColsAvg() { return coCompatibleColsAvg_; } + void updateCompatibleColsAvg(int coPivots); + inline int coCompatiblePivots() { return coCompatiblePivots_; } + inline void addCompatiblePivot() { coCompatiblePivots_++; } + inline int coDegenerateCompatiblePivots() { return coDegenerateCompatiblePivots_; } + inline void addDegenerateCompatiblePivot() { coDegenerateCompatiblePivots_++; } + + /* Get and update the number of compatible pivots that were done because of the priority factor */ + inline void addPriorityPivot() { coPriorityPivots_++; } + inline int coPriorityPivots() { return coPriorityPivots_; } + inline int doStatistics() const + { + return doStatistics_; + } + inline void setDoStatistics(int value) + { + doStatistics_ = value; + } + +protected: + /** Indices of the variables that were not at one of their bounds + during the last update (non primal degenerate variables) */ + int coPrimalDegenerates_; + int *primalDegenerates_; + bool *isPrimalDegenerate_; + + /** Indices of the non basic variables with a zero reduced cost + during the last update (ndual-degenerate variables) */ + int coDualDegenerates_; + int *dualDegenerates_; + bool *isDualDegenerate_; + + /** Table of booleans indicating whether each variable is primal + compatible (true) or not (false) */ + int coCompatibleCols_; + double *compatibilityCol_; + bool *isCompatibleCol_; + + /** Table of booleans indicating whether each constraint is dual + compatible (true) or not (false) */ + int coCompatibleRows_; + double *compatibilityRow_; + bool *isCompatibleRow_; + +private: + /** pointer to the original model that shall be solved */ + ClpSimplex *model_; + + /** tolerance used for the tests of degeneracy and compatibility (resp.) */ + double epsDegeneracy_; + double epsCompatibility_; + + /** size of the original model */ + int numberRows_; + int numberColumns_; + + /** w vectors that are used to identify the compatible columns and + rows. The name w, refers to the notations of the articles on + positive edge */ + // now passed in CoinIndexedVector *wPrimal_; + // now passed in CoinIndexedVector *wDual_; + + /** temporary vectors that are used to store colulns of the constraint + matrix or random numbers */ + // not usedCoinIndexedVector *tempColumn_; + double *tempRandom_; + + /** number of degenerate pivots and variables */ + int coPrimalDegeneratesAvg_; + int coDualDegeneratesAvg_; + int coCompatibleColsAvg_; + int coCompatibleRowsAvg_; + int coUpdateDegenerates_; + //int coIdentifyCompatibles_; + int coDegeneratePivots_; + int coCompatiblePivots_; + int coDegenerateCompatiblePivots_; + int coDegeneratePivotsConsecutive_; + + /** number of compatible pivots that were done because of the priority factor */ + int coPriorityPivots_; + /// Do statistics + int doStatistics_; + + /** tracking the degenerate iterations after compatible pivots */ + double lastObjectiveValue_; + bool isLastPivotCompatible_; + + /** Timer attribute recording the additional time spent in + identifying compatible variables */ + double timeCompatibility_; + double timeMultRandom_; + double timeLinearSystem_; + double timeTmp_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPackedMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPackedMatrix.hpp new file mode 100644 index 000000000..c1bfed033 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPackedMatrix.hpp @@ -0,0 +1,778 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPackedMatrix_H +#define ClpPackedMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" +#include "ClpPrimalColumnSteepest.hpp" + +/** This implements CoinPackedMatrix as derived from ClpMatrixBase. + + It adds a few methods that know about model as well as matrix + + For details see CoinPackedMatrix */ + +class ClpPackedMatrix2; +class ClpPackedMatrix3; +class CoinDoubleArrayWithLength; +class ClpPackedMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const + { + return matrix_; + } + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const + { + return matrix_->isColOrdered(); + } + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const + { + return matrix_->getNumElements(); + } + /** Number of columns. */ + virtual int getNumCols() const + { + return matrix_->getNumCols(); + } + /** Number of rows. */ + virtual int getNumRows() const + { + return matrix_->getNumRows(); + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const + { + return matrix_->getElements(); + } + /// Mutable elements + inline double *getMutableElements() const + { + return matrix_->getMutableElements(); + } + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const + { + return matrix_->getIndices(); + } + + virtual const CoinBigIndex *getVectorStarts() const + { + return matrix_->getVectorStarts(); + } + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const + { + return matrix_->getVectorLengths(); + } + /** The length of a single major-dimension vector. */ + virtual int getVectorLength(int index) const + { + return matrix_->getVectorSize(index); + } + + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel); +#ifndef CLP_NO_VECTOR + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase *const *columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase *const *rows); +#endif + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); + /** Replace the elements of a vector. The indices remain the same. + This is only needed if scaling and a row copy is used. + At most the number specified will be replaced. + The index is between 0 and major dimension of matrix */ + virtual void replaceVector(const int index, + const int numReplace, const double *newElements) + { + matrix_->replaceVector(index, numReplace, newElements); + } + /** Modify one element of packed matrix. An element may be added. + This works for either ordering If the new element is zero it will be + deleted unless keepZero true */ + virtual void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false) + { + matrix_->modifyCoefficient(row, column, newElement, keepZero); + } + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis(const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Creates scales for column copy (rowCopy in model may be modified) + returns non-zero if no scaling done */ + virtual int scale(ClpModel *model, ClpSimplex *simplex = NULL) const; + /** Scales rowCopy if column copy scaled + Only called if scales already exist */ + virtual void scaleRowCopy(ClpModel *model) const; + /// Creates scaled column copy if scales exist + void createScaledMatrix(ClpSimplex *model) const; + /** Realy really scales column copy + Only called if scales already exist. + Up to user ro delete */ + virtual ClpMatrixBase *scaledColumnCopy(ClpModel *model) const; + /** Checks if all elements are in valid range. Can just + return true if you are not paranoid. For Clp I will + probably expect no zeros. Code can modify matrix to get rid of + small elements. + check bits (can be turned off to save time) : + 1 - check if matrix has gaps + 2 - check if zero elements + 4 - check and compress duplicates + 8 - report on large and small + */ + virtual bool allElementsInRange(ClpModel *model, + double smallest, double largest, + int check = 15); + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double &smallestNegative, double &largestNegative, + double &smallestPositive, double &largestPositive); + + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Allow any parts of a created CoinPackedMatrix to be deleted + virtual void releasePackedMatrix() const {} + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex *dubiousWeights(const ClpSimplex *model, int *inputWeights) const; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + /// makes sure active columns correct + virtual int refresh(ClpSimplex *model); + // Really scale matrix + virtual void reallyScale(const double *rowScale, const double *columnScale); + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void times(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale, + double *spare = NULL) const; + /** Return y - pi * A in y. + @pre pi must be of size numRows() + @pre y must be of size numColumns() + This just does subset (but puts in correct place in y) */ + void transposeTimesSubset(int number, + const int *which, + const double *pi, double *y, + const double *rowScale, + const double *columnScale, + double *spare = NULL) const; + /** Return x * scalar * A in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x * scalar * A in z. + Note - If x packed mode - then z packed mode + This does by column and knows no gaps + Squashes small elements and knows about ClpSimplex */ + void transposeTimesByColumn(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x * scalar * A in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex *model, + const CoinIndexedVector *pi) const; + /** Updates two arrays for steepest and does devex weights + Returns nonzero if updates reduced cost and infeas - + new infeas in dj1 */ + virtual int transposeTimes2(const ClpSimplex *model, + const CoinIndexedVector *pi1, CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, + CoinIndexedVector *spare, + double *infeas, double *reducedCost, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /// Updates second array for steepest and does devex weights + virtual void subsetTimes2(const ClpSimplex *model, + CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, CoinIndexedVector *dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /// Sets up an effective RHS + void useEffectiveRhs(ClpSimplex *model); +#if COIN_LONG_WORK + // For long double versions + virtual void times(CoinWorkDouble scalar, + const CoinWorkDouble *x, CoinWorkDouble *y) const; + virtual void transposeTimes(CoinWorkDouble scalar, + const CoinWorkDouble *x, CoinWorkDouble *y) const; +#endif + //@} + + /**@name Other */ + //@{ + /// Returns CoinPackedMatrix (non const) + inline CoinPackedMatrix *matrix() const + { + return matrix_; + } + /** Just sets matrix_ to NULL so it can be used elsewhere. + used in GUB + */ + inline void setMatrixNull() + { + matrix_ = NULL; + } + /// Say we want special column copy + inline void makeSpecialColumnCopy() + { + flags_ |= 16; + } + /// Say we don't want special column copy + void releaseSpecialColumnCopy(); + /// Are there zeros? + inline bool zeros() const + { + return ((flags_ & 1) != 0); + } + /// Do we want special column copy + inline bool wantsSpecialColumnCopy() const + { + return ((flags_ & 16) != 0); + } + /// Flags + inline int flags() const + { + return flags_; + } + /// Sets flags_ correctly + inline void checkGaps() + { + flags_ = (matrix_->hasGaps()) ? (flags_ | 2) : (flags_ & (~2)); + } + /// number of active columns (normally same as number of columns) + inline int numberActiveColumns() const + { + return numberActiveColumns_; + } + /// Set number of active columns (normally same as number of columns) + inline void setNumberActiveColumns(int value) + { + numberActiveColumns_ = value; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix(); + /** Destructor */ + virtual ~ClpPackedMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix(const ClpPackedMatrix &); + /** The copy constructor from an CoinPackedMatrix. */ + ClpPackedMatrix(const CoinPackedMatrix &); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpPackedMatrix(const ClpPackedMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + ClpPackedMatrix(const CoinPackedMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + + /** This takes over ownership (for space reasons) */ + ClpPackedMatrix(CoinPackedMatrix *matrix); + + ClpPackedMatrix &operator=(const ClpPackedMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + /// Copy contents - resizing if necessary - otherwise re-use memory + virtual void copy(const ClpPackedMatrix *from); + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + /// make special row copy + void specialRowCopy(ClpSimplex *model, const ClpMatrixBase *rowCopy); + /// make special column copy + void specialColumnCopy(ClpSimplex *model); + /// Correct sequence in and out to give true value + virtual void correctSequence(const ClpSimplex *model, int &sequenceIn, int &sequenceOut); + //@} +private: + /// Meat of transposeTimes by column when not scaled + int gutsOfTransposeTimesUnscaled(const double *COIN_RESTRICT pi, + int *COIN_RESTRICT index, + double *COIN_RESTRICT array, + const double tolerance) const; + /// Meat of transposeTimes by column when scaled + int gutsOfTransposeTimesScaled(const double *COIN_RESTRICT pi, + const double *COIN_RESTRICT columnScale, + int *COIN_RESTRICT index, + double *COIN_RESTRICT array, + const double tolerance) const; + /// Meat of transposeTimes by column when not scaled and skipping + int gutsOfTransposeTimesUnscaled(const double *COIN_RESTRICT pi, + int *COIN_RESTRICT index, + double *COIN_RESTRICT array, + const unsigned char *status, + const double tolerance) const; + /** Meat of transposeTimes by column when not scaled and skipping + and doing part of dualColumn */ + int gutsOfTransposeTimesUnscaled(const double *COIN_RESTRICT pi, + int *COIN_RESTRICT index, + double *COIN_RESTRICT array, + const unsigned char *status, + int *COIN_RESTRICT spareIndex, + double *COIN_RESTRICT spareArray, + const double *COIN_RESTRICT reducedCost, + double &upperTheta, + double acceptablePivot, + double dualTolerance, + int &numberRemaining, + const double zeroTolerance) const; + /// Meat of transposeTimes by column when scaled and skipping + int gutsOfTransposeTimesScaled(const double *COIN_RESTRICT pi, + const double *COIN_RESTRICT columnScale, + int *COIN_RESTRICT index, + double *COIN_RESTRICT array, + const unsigned char *status, + const double tolerance) const; + /// Meat of transposeTimes by row n > K if packed - returns number nonzero + int gutsOfTransposeTimesByRowGEK(const CoinIndexedVector *COIN_RESTRICT piVector, + int *COIN_RESTRICT index, + double *COIN_RESTRICT output, + int numberColumns, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero + int gutsOfTransposeTimesByRowGE3(const CoinIndexedVector *COIN_RESTRICT piVector, + int *COIN_RESTRICT index, + double *COIN_RESTRICT output, + double *COIN_RESTRICT array2, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n > 2 if packed - returns number nonzero + int gutsOfTransposeTimesByRowGE3a(const CoinIndexedVector *COIN_RESTRICT piVector, + int *COIN_RESTRICT index, + double *COIN_RESTRICT output, + int *COIN_RESTRICT lookup, + char *COIN_RESTRICT marked, + const double tolerance, + const double scalar) const; + /// Meat of transposeTimes by row n == 2 if packed + void gutsOfTransposeTimesByRowEQ2(const CoinIndexedVector *piVector, CoinIndexedVector *output, + CoinIndexedVector *spareVector, const double tolerance, const double scalar) const; + /// Meat of transposeTimes by row n == 1 if packed + void gutsOfTransposeTimesByRowEQ1(const CoinIndexedVector *piVector, CoinIndexedVector *output, + const double tolerance, const double scalar) const; + /// Gets rid of special copies + void clearCopies(); + +protected: + /// Check validity + void checkFlags(int type) const; + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Data + CoinPackedMatrix *matrix_; + /// number of active columns (normally same as number of columns) + int numberActiveColumns_; + /** Flags - + 1 - has zero elements + 2 - has gaps + 4 - has special row copy + 8 - has special column copy + 16 - wants special column copy + */ + mutable int flags_; + /// Special row copy + ClpPackedMatrix2 *rowCopy_; + /// Special column copy + ClpPackedMatrix3 *columnCopy_; + //@} +}; +#ifdef THREAD +#include +typedef struct { + double acceptablePivot; + const ClpSimplex *model; + double *spare; + int *spareIndex; + double *arrayTemp; + int *indexTemp; + int *numberInPtr; + //double * bestPossiblePtr; + double *upperThetaPtr; + int *posFreePtr; + double *freePivotPtr; + int *numberOutPtr; + const unsigned short *count; + const double *pi; + const CoinBigIndex *rowStart; + const double *element; + const unsigned short *column; + int offset; + int numberInRowArray; + int numberLook; +} dualColumn0Struct; +#endif +class ClpPackedMatrix2 { + +public: + /**@name Useful methods */ + //@{ + /** Return x * -1 * A in z. + Note - x packed and z will be packed mode + Squashes small elements and knows about ClpSimplex */ + void transposeTimes(const ClpSimplex *model, + const CoinPackedMatrix *rowCopy, + const CoinIndexedVector *x, + CoinIndexedVector *spareArray, + CoinIndexedVector *z) const; + /// Returns true if copy has useful information + inline bool usefulInfo() const + { + return rowStart_ != NULL; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix2(); + /** Constructor from copy. */ + ClpPackedMatrix2(ClpSimplex *model, const CoinPackedMatrix *rowCopy); + /** Destructor */ + virtual ~ClpPackedMatrix2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix2(const ClpPackedMatrix2 &); + ClpPackedMatrix2 &operator=(const ClpPackedMatrix2 &); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of blocks + int numberBlocks_; + /// Number of rows + int numberRows_; + /// Column offset for each block (plus one at end) + int *offset_; + /// Counts of elements in each part of row + mutable unsigned short *count_; + /// Row starts + mutable CoinBigIndex *rowStart_; + /// columns within block + unsigned short *column_; + /// work arrays + double *work_; +#ifdef THREAD + pthread_t *threadId_; + dualColumn0Struct *info_; +#endif + //@} +}; +typedef struct { + CoinBigIndex startElements_; // point to data + CoinBigIndex startRows_; // point to data later + int startIndices_; // point to column_ + int numberInBlock_; + int numberScan_; // i.e. miss out basic and fixed + /* order is - + free or superbasic + at lower + at upper + fixed or basic */ + int firstAtLower_; + int firstAtUpper_; + int firstBasic_; // or fixed + int numberElements_; // number elements per column + int numberOnes_; // later +} blockStruct; +class ClpPackedMatrix3 { + +public: + /**@name Useful methods */ + //@{ + /** Return x * -1 * A in z. + Note - x packed and z will be packed mode + Squashes small elements and knows about ClpSimplex */ + void transposeTimes(const ClpSimplex *model, + const double *pi, + CoinIndexedVector *output) const; + /// This version does dualColumn0 + /// Updates two arrays for steepest + void transposeTimes(const ClpSimplex *model, + const double *pi, + CoinIndexedVector *output, + CoinIndexedVector *candidate, + const CoinIndexedVector *rowArray) const; + void transposeTimes2(const ClpSimplex *model, + const double *pi, CoinIndexedVector *dj1, + const double *piWeight, + double *COIN_RESTRICT infeas, + double *COIN_RESTRICT reducedCost, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPackedMatrix3(); + /** Constructor from copy. */ + ClpPackedMatrix3(ClpSimplex *model, const CoinPackedMatrix *columnCopy); + /** Destructor */ + virtual ~ClpPackedMatrix3(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPackedMatrix3(const ClpPackedMatrix3 &); + ClpPackedMatrix3 &operator=(const ClpPackedMatrix3 &); + //@} + /**@name Sort methods */ + //@{ + /** Sort blocks */ + void sortBlocks(const ClpSimplex *model); + /// Swap one variable + void swapOne(const ClpSimplex *model, const ClpPackedMatrix *matrix, + int iColumn); + /// Part of above + void swapOne(int iBlock, int kA, int kB); + /** Debug - check blocks */ + void checkBlocks(const ClpSimplex *model); + /** + type - 1 redo infeasible, 2 choose sequenceIn, 3 both + returns sequenceIn (or -1) for type 2 + */ + int redoInfeasibilities(const ClpSimplex *model, + ClpPrimalColumnSteepest *pivotChoose, + int type); + /// Get temporary array (aligned) + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Number of blocks + int numberBlocks_; + /// Number of columns + int numberColumns_; + /// Number of columns including gaps + int numberColumnsWithGaps_; +#if ABOCA_LITE + /// Number of chunks + int numberChunks_; +#endif + /// Number of elements (including gaps) + CoinBigIndex numberElements_; + /// Maximum size of any block + int maxBlockSize_; + /// Column indices and reverse lookup (within block) + int *column_; + /// Starts for odd/long vectors?? + CoinBigIndex *start_; + /// Rows + int *row_; + /// Elements + double *element_; + /// Temporary work area (aligned) + CoinDoubleArrayWithLength *temporary_; +#if ABOCA_LITE + /// Chunk ends (could have more than cpus) + int endChunk_[2 * ABOCA_LITE + 1]; +#endif + /// Blocks (ordinary start at 0 and go to first block) + blockStruct *block_; + /// If active + int ifActive_; + //@} +}; +#elif INCLUDE_MATRIX3_PRICING +int iColumn = *column; +column++; +if (fabs(value) > zeroTolerance) { + double thisWeight = weights[iColumn]; + double pivot = value * scaleFactor; + double pivotSquared = pivot * pivot; + thisWeight += pivotSquared * devex + pivot * modification; + if (thisWeight < DEVEX_TRY_NORM) { + if (referenceIn < 0.0) { + // steepest + thisWeight = CoinMax(DEVEX_TRY_NORM, DEVEX_ADD_ONE + pivotSquared); + } else { + // exact + thisWeight = referenceIn * pivotSquared; + if (reference(iColumn)) + thisWeight += 1.0; + thisWeight = CoinMax(thisWeight, DEVEX_TRY_NORM); + } + } + // out basic or fixed + weights[iColumn] = thisWeight; + value = reducedCost[iColumn] - value; + reducedCost[iColumn] = value; + unsigned char thisStatus = status[iColumn] & 7; + assert(thisStatus != 0 && thisStatus != 4); + if (thisStatus == 3) { + //} else if ((thisStatus&1)!=0) { + // basic or fixed + //value=0.0; + } else { + assert(thisStatus == 2); + value = -value; + } + if (value < dualTolerance) { + value *= value; + if (value > bestRatio * weights[iColumn]) { + bestSequence = iColumn; + bestRatio = value / weights[iColumn]; +#if NO_CHANGE_MULTIPLIER != 1 + bestRatio2 = bestRatio * NO_CHANGE_MULTIPLIER; +#endif + } + } +} else { + // interesting - was faster without this?! + value = reducedCost[iColumn]; + unsigned char thisStatus = status[iColumn] & 7; + assert(thisStatus != 0 && thisStatus != 4); + if (thisStatus == 3) { + } else if ((thisStatus & 1) != 0) { + // basic or fixed + value = 0.0; + } else { + value = -value; + } + if (value < dualTolerance) { + value *= value; + if (value > bestRatio2 * weights[iColumn]) { + bestSequence = iColumn; + bestRatio2 = value / weights[iColumn]; +#if NO_CHANGE_MULTIPLIER != 1 + bestRatio = bestRatio2 * INVERSE_MULTIPLIER; +#endif + } + } +} +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpParameters.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpParameters.hpp new file mode 100644 index 000000000..9be7b4820 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpParameters.hpp @@ -0,0 +1,132 @@ +/* $Id$ */ +// Copyright (C) 2000, 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _ClpParameters_H +#define _ClpParameters_H + +/** This is where to put any useful stuff. + +*/ +enum ClpIntParam { + /** The maximum number of iterations Clp can execute in the simplex methods + */ + ClpMaxNumIteration = 0, + /** The maximum number of iterations Clp can execute in hotstart before + terminating */ + ClpMaxNumIterationHotStart, + /** The name discipline; specifies how the solver will handle row and + column names. + - 0: Auto names: Names cannot be set by the client. Names of the form + Rnnnnnnn or Cnnnnnnn are generated on demand when a name for a + specific row or column is requested; nnnnnnn is derived from the row + or column index. Requests for a vector of names return a vector with + zero entries. + - 1: Lazy names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to the largest index of a name supplied by the client; + some entries in the vector may be null strings. + - 2: Full names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to match the constraint system, and all entries will + contain either the name specified by the client or a generated name. + */ + ClpNameDiscipline, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastIntParam +}; + +enum ClpDblParam { + /** Set Dual objective limit. This is to be used as a termination criteria + in methods where the dual objective monotonically changes (dual + simplex). */ + ClpDualObjectiveLimit, + /** Primal objective limit. This is to be used as a termination + criteria in methods where the primal objective monotonically changes + (e.g., primal simplex) */ + ClpPrimalObjectiveLimit, + /** The maximum amount the dual constraints can be violated and still be + considered feasible. */ + ClpDualTolerance, + /** The maximum amount the primal constraints can be violated and still be + considered feasible. */ + ClpPrimalTolerance, + /** Objective function constant. This the value of the constant term in + the objective function. */ + ClpObjOffset, + /// Maximum time in seconds - after, this action is as max iterations + ClpMaxSeconds, + /// Maximum wallclock running time in seconds - after, this action is as max iterations + ClpMaxWallSeconds, + /// Tolerance to use in presolve + ClpPresolveTolerance, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastDblParam +}; + +enum ClpStrParam { + /** Name of the problem. This is the found on the Name card of + an mps file. */ + ClpProbName = 0, + /** Just a marker, so that we can allocate a static sized array to store + parameters. */ + ClpLastStrParam +}; + +/// Copy (I don't like complexity of Coin version) +template < class T > +inline void +ClpDisjointCopyN(const T *array, const CoinBigIndex size, T *newArray) +{ + memcpy(reinterpret_cast< void * >(newArray), array, size * sizeof(T)); +} +/// And set +template < class T > +inline void +ClpFillN(T *array, const CoinBigIndex size, T value) +{ + CoinBigIndex i; + for (i = 0; i < size; i++) + array[i] = value; +} +/// This returns a non const array filled with input from scalar or actual array +template < class T > +inline T * +ClpCopyOfArray(const T *array, const CoinBigIndex size, T value) +{ + T *arrayNew = new T[size]; + if (array) + ClpDisjointCopyN(array, size, arrayNew); + else + ClpFillN(arrayNew, size, value); + return arrayNew; +} + +/// This returns a non const array filled with actual array (or NULL) +template < class T > +inline T * +ClpCopyOfArray(const T *array, const CoinBigIndex size) +{ + if (array) { + T *arrayNew = new T[size]; + ClpDisjointCopyN(array, size, arrayNew); + return arrayNew; + } else { + return NULL; + } +} +/// For a structure to be used by trusted code +typedef struct { + int typeStruct; // allocated as 1,2 etc + int typeCall; + void *data; +} ClpTrustedData; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPdcoBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPdcoBase.hpp new file mode 100644 index 000000000..db8041172 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPdcoBase.hpp @@ -0,0 +1,110 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPdcoBase_H +#define ClpPdcoBase_H + +#include "CoinPragma.hpp" + +#include "CoinPackedMatrix.hpp" +#include "CoinDenseVector.hpp" +class ClpInterior; + +/** Abstract base class for tailoring everything for Pcdo + + Since this class is abstract, no object of this type can be created. + + If a derived class provides all methods then all ClpPcdo algorithms + should work. + + Eventually we should be able to use ClpObjective and ClpMatrixBase. +*/ + +class ClpPdcoBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + virtual void matVecMult(ClpInterior *model, int mode, double *x, double *y) const = 0; + + virtual void getGrad(ClpInterior *model, CoinDenseVector< double > &x, CoinDenseVector< double > &grad) const = 0; + + virtual void getHessian(ClpInterior *model, CoinDenseVector< double > &x, CoinDenseVector< double > &H) const = 0; + + virtual double getObj(ClpInterior *model, CoinDenseVector< double > &x) const = 0; + + virtual void matPrecon(ClpInterior *model, double delta, double *x, double *y) const = 0; + + //@} + //@{ + ///@name Other + /// Clone + virtual ClpPdcoBase *clone() const = 0; + /// Returns type + inline int type() const + { + return type_; + }; + /// Sets type + inline void setType(int type) + { + type_ = type; + }; + /// Returns size of d1 + inline int sizeD1() const + { + return 1; + }; + /// Returns d1 as scalar + inline double getD1() const + { + return d1_; + }; + /// Returns size of d2 + inline int sizeD2() const + { + return 1; + }; + /// Returns d2 as scalar + inline double getD2() const + { + return d2_; + }; + //@} + +protected: + /**@name Constructors, destructor
+ NOTE: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + ClpPdcoBase(); + /** Destructor (has to be public) */ +public: + virtual ~ClpPdcoBase(); + +protected: + // Copy + ClpPdcoBase(const ClpPdcoBase &); + // Assignment + ClpPdcoBase &operator=(const ClpPdcoBase &); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Should be dense vectors + double d1_; + double d2_; + /// type (may be useful) + int type_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPlusMinusOneMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPlusMinusOneMatrix.hpp new file mode 100644 index 000000000..eeee2a8b8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPlusMinusOneMatrix.hpp @@ -0,0 +1,565 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPlusMinusOneMatrix_H +#define ClpPlusMinusOneMatrix_H + +#include "CoinPragma.hpp" + +#include "ClpMatrixBase.hpp" + +/** This implements a simple +- one matrix as derived from ClpMatrixBase. + +*/ + +class ClpPlusMinusOneMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const; + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const; + /** Number of columns. */ + virtual int getNumCols() const + { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const + { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const + { + return indices_; + } + // and for advanced use + int *getMutableIndices() const + { + return indices_; + } + + virtual const CoinBigIndex *getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const; + + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel); + /// Append Columns + virtual void appendCols(int number, const CoinPackedVectorBase *const *columns); + /// Append Rows + virtual void appendRows(int number, const CoinPackedVectorBase *const *rows); +#ifndef SLIM_CLP + /** Append a set of rows/columns to the end of the matrix. Returns number of errors + i.e. if any of the new rows/columns contain an index that's larger than the + number of columns-1/rows-1 (if numberOther>0) or duplicates + If 0 then rows, 1 if columns */ + virtual int appendMatrix(int number, int type, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); +#endif + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis( + const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Given positive integer weights for each row fills in sum of weights + for each column (and slack). + Returns weights vector + */ + virtual CoinBigIndex *dubiousWeights(const ClpSimplex *model, int *inputWeights) const; + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double &smallestNegative, double &largestNegative, + double &smallestPositive, double &largestPositive); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + virtual void releasePackedMatrix() const; + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + /// Just checks matrix valid - will say if dimensions not quite right if detail + void checkValid(bool detail) const; + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void times(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale, double *spare = NULL) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex *model, + const CoinIndexedVector *pi) const; + /** Updates two arrays for steepest and does devex weights + Returns nonzero if updates reduced cost and infeas - + new infeas in dj1 */ + virtual int transposeTimes2(const ClpSimplex *model, + const CoinIndexedVector *pi1, CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, + CoinIndexedVector *spare, + double *infeas, double *reducedCost, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /// Updates second array for steepest and does devex weights + virtual void subsetTimes2(const ClpSimplex *model, + CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, CoinIndexedVector *dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + //@} + + /**@name Other */ + //@{ + /// Return starts of +1s + inline CoinBigIndex *startPositive() const + { + return startPositive_; + } + /// Return starts of -1s + inline CoinBigIndex *startNegative() const + { + return startNegative_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPlusMinusOneMatrix(); + /** Destructor */ + virtual ~ClpPlusMinusOneMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPlusMinusOneMatrix(const ClpPlusMinusOneMatrix &); + /** The copy constructor from an CoinPlusMinusOneMatrix. + If not a valid matrix then getIndices will be NULL and + startPositive[0] will have number of +1, + startPositive[1] will have number of -1, + startPositive[2] will have number of others, + */ + ClpPlusMinusOneMatrix(const CoinPackedMatrix &); + /// Constructor from arrays + ClpPlusMinusOneMatrix(int numberRows, int numberColumns, + bool columnOrdered, const int *indices, + const CoinBigIndex *startPositive, const CoinBigIndex *startNegative); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpPlusMinusOneMatrix(const ClpPlusMinusOneMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + + ClpPlusMinusOneMatrix &operator=(const ClpPlusMinusOneMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + /// pass in copy (object takes ownership) + void passInCopy(int numberRows, int numberColumns, + bool columnOrdered, int *indices, + CoinBigIndex *startPositive, CoinBigIndex *startNegative); + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// For fake CoinPackedMatrix + mutable CoinPackedMatrix *matrix_; + mutable int *lengths_; + /// Start of +1's for each + CoinBigIndex *COIN_RESTRICT startPositive_; + /// Start of -1's for each + CoinBigIndex *COIN_RESTRICT startNegative_; + /// Data -1, then +1 rows in pairs (row==-1 if one entry) + int *COIN_RESTRICT indices_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; +#ifdef CLP_PLUS_ONE_MATRIX + /** Other flags (could have columnOrdered_?) + 1 bit - says just +1 + */ + mutable int otherFlags_; +#endif + /// True if column ordered + bool columnOrdered_; + + //@} +}; +#if CLP_POOL_MATRIX +/** This implements a matrix with few different coefficients + as derived from ClpMatrixBase. This version only up to 65K rows +*/ +#define CLP_POOL_SIZE 32 - CLP_POOL_MATRIX +#if CLP_POOL_MATRIX == 16 +typedef struct { + unsigned short row_; + unsigned short pool_; +} poolInfo; +#else +typedef struct { + unsigned int row_ : CLP_POOL_MATRIX; + unsigned short pool_ : CLP_POOL_SIZE; +} poolInfo; +#endif +#include "ClpPackedMatrix.hpp" +class ClpPoolMatrix : public ClpMatrixBase { + +public: + /**@name Useful methods */ + //@{ + /// Return a complete CoinPackedMatrix + virtual CoinPackedMatrix *getPackedMatrix() const; + /** Whether the packed matrix is column major ordered or not. */ + virtual bool isColOrdered() const; + /** Number of entries in the packed matrix. */ + virtual CoinBigIndex getNumElements() const; + /** Number of different entries in the packed matrix. */ + inline int getNumDifferentElements() const + { + return numberDifferent_; + } + /** Number of columns. */ + virtual int getNumCols() const + { + return numberColumns_; + } + /** Number of rows. */ + virtual int getNumRows() const + { + return numberRows_; + } + + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with vectorStarts and vectorLengths. */ + virtual const double *getElements() const; + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with vectorStarts and + vectorLengths. */ + virtual const int *getIndices() const; + // and for advanced use + int *getMutableIndices() const; + + virtual const CoinBigIndex *getVectorStarts() const; + /** The lengths of the major-dimension vectors. */ + virtual const int *getVectorLengths() const; + /** The length of a major-dimension vector. */ + virtual int getVectorLength(int index) const; + /** Delete the columns whose indices are listed in indDel. */ + virtual void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + virtual void deleteRows(const int numDel, const int *indDel); + /** Returns a new matrix in reverse order without gaps */ + virtual ClpMatrixBase *reverseOrderedCopy() const; + /// Returns number of elements in column part of basis + virtual int countBasis( + const int *whichColumn, + int &numberColumnBasic); + /// Fills in column part of basis + virtual void fillBasis(ClpSimplex *model, + const int *whichColumn, + int &numberColumnBasic, + int *row, int *start, + int *rowCount, int *columnCount, + CoinFactorizationDouble *element); + /** Returns largest and smallest elements of both signs. + Largest refers to largest absolute value. + */ + virtual void rangeOfElements(double &smallestNegative, double &largestNegative, + double &smallestPositive, double &largestPositive); + /** Unpacks a column into an CoinIndexedvector + */ + virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column) const; + /** Unpacks a column into an CoinIndexedvector + ** in packed foramt + Note that model is NOT const. Bounds and objective could + be modified if doing column generation (just for this variable) */ + virtual void unpackPacked(ClpSimplex *model, + CoinIndexedVector *rowArray, + int column) const; + /** Adds multiple of a column into an CoinIndexedvector + You can use quickAdd to add to vector */ + virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, + int column, double multiplier) const; + /** Adds multiple of a column into an array */ + virtual void add(const ClpSimplex *model, double *array, + int column, double multiplier) const; + /// Allow any parts of a created CoinMatrix to be deleted + virtual void releasePackedMatrix() const; + /** Set the dimensions of the matrix. In effect, append new empty + columns/rows to the matrix. A negative number for either dimension + means that that dimension doesn't change. Otherwise the new dimensions + MUST be at least as large as the current ones otherwise an exception + is thrown. */ + virtual void setDimensions(int numrows, int numcols); + /// Just checks matrix valid - will say if dimensions not quite right if detail + void checkValid(bool detail) const; + //@} + + /**@name Matrix times vector methods */ + //@{ + /** Return y + A * scalar *x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + virtual void times(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void times(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale) const; + /** Return y + x * scalar * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + virtual void transposeTimes(double scalar, + const double *x, double *y) const; + /// And for scaling + virtual void transposeTimes(double scalar, + const double *x, double *y, + const double *rowScale, + const double *columnScale, double *spare = NULL) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex */ + virtual void transposeTimes(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x * scalar * A + y in z. + Can use y as temporary array (will be empty at end) + Note - If x packed mode - then z packed mode + Squashes small elements and knows about ClpSimplex. + This version uses row copy*/ + virtual void transposeTimesByRow(const ClpSimplex *model, double scalar, + const CoinIndexedVector *x, + CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Return x *A in z but + just for indices in y. + Note - z always packed mode */ + virtual void subsetTransposeTimes(const ClpSimplex *model, + const CoinIndexedVector *x, + const CoinIndexedVector *y, + CoinIndexedVector *z) const; + /** Returns true if can combine transposeTimes and subsetTransposeTimes + and if it would be faster */ + virtual bool canCombine(const ClpSimplex *model, + const CoinIndexedVector *pi) const + { + return true; + } + /** Updates two arrays for steepest and does devex weights + Returns nonzero if updates reduced cost and infeas - + new infeas in dj1 */ + virtual int transposeTimes2(const ClpSimplex *model, + const CoinIndexedVector *pi1, CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, + CoinIndexedVector *spare, + double *infeas, double *reducedCost, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + /// Updates second array for steepest and does devex weights + virtual void subsetTimes2(const ClpSimplex *model, + CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, CoinIndexedVector *dj2, + double referenceIn, double devex, + // Array for exact devex to say what is in reference framework + unsigned int *reference, + double *weights, double scaleFactor); + //@} + + /**@name Other */ + //@{ + /// Return column starts + inline CoinBigIndex *columnStart() const + { + return columnStart_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + ClpPoolMatrix(); + /** Destructor */ + virtual ~ClpPoolMatrix(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + ClpPoolMatrix(const ClpPoolMatrix &); + /** The copy constructor from an CoinPoolMatrix. + */ + ClpPoolMatrix(const CoinPackedMatrix &); + /// Constructor from arrays + ClpPoolMatrix(int numberRows, int numberColumns, + const int *indices, const double *elements, + const CoinBigIndex *columnStart); + /// Constructor from arrays - handing over ownership + ClpPoolMatrix(int numberColumns, CoinBigIndex *columnStart, + poolInfo *stuff, double *elements); + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + ClpPoolMatrix(const ClpPoolMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + + ClpPoolMatrix &operator=(const ClpPoolMatrix &); + /// Clone + virtual ClpMatrixBase *clone() const; + /** Subset clone (without gaps). Duplicates are allowed + and order is as given */ + virtual ClpMatrixBase *subsetClone( + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns) const; + /// Says whether it can do partial pricing + virtual bool canDoPartialPricing() const; + /// Partial pricing + virtual void partialPricing(ClpSimplex *model, double start, double end, + int &bestSequence, int &numberWanted); + //@} + +protected: + /// Create matrix_ + ClpPackedMatrix *createMatrix() const; + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// For fake ClpPackedMatrix + mutable ClpPackedMatrix *matrix_; + mutable int *lengths_; + /// Unique values + double *COIN_RESTRICT elements_; + /// Column starts + CoinBigIndex *COIN_RESTRICT columnStart_; + /// Rows and values + poolInfo *COIN_RESTRICT stuff_; + /// Number of rows + int numberRows_; + /// Number of columns + int numberColumns_; + /// Number of different elements + int numberDifferent_; + + //@} +}; +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPresolve.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPresolve.hpp new file mode 100644 index 000000000..02eecbd82 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPresolve.hpp @@ -0,0 +1,379 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPresolve_H +#define ClpPresolve_H +#include "ClpSimplex.hpp" + +class CoinPresolveAction; +#include "CoinPresolveMatrix.hpp" +/** This is the Clp interface to CoinPresolve + +*/ +class ClpPresolve { +public: + /**@name Main Constructor, destructor */ + //@{ + /// Default constructor + ClpPresolve(); + + /// Virtual destructor + virtual ~ClpPresolve(); + //@} + /**@name presolve - presolves a model, transforming the model + * and saving information in the ClpPresolve object needed for postsolving. + * This underlying (protected) method is virtual; the idea is that in the future, + * one could override this method to customize how the various + * presolve techniques are applied. + + This version of presolve returns a pointer to a new presolved + model. NULL if infeasible or unbounded. + This should be paired with postsolve + below. The advantage of going back to original model is that it + will be exactly as it was i.e. 0.0 will not become 1.0e-19. + If keepIntegers is true then bounds may be tightened in + original. Bounds will be moved by up to feasibilityTolerance + to try and stay feasible. + Names will be dropped in presolved model if asked + */ + ClpSimplex *presolvedModel(ClpSimplex &si, + double feasibilityTolerance = 0.0, + bool keepIntegers = true, + int numberPasses = 5, + bool dropNames = false, + bool doRowObjective = false, + const char *prohibitedRows = NULL, + const char *prohibitedColumns = NULL); +#ifndef CLP_NO_STD + /** This version saves data in a file. The passed in model + is updated to be presolved model. + Returns non-zero if infeasible*/ + int presolvedModelToFile(ClpSimplex &si, std::string fileName, + double feasibilityTolerance = 0.0, + bool keepIntegers = true, + int numberPasses = 5, + bool dropNames = false, + bool doRowObjective = false); +#endif + /** Return pointer to presolved model, + Up to user to destroy */ + ClpSimplex *model() const; + /// Return pointer to original model + ClpSimplex *originalModel() const; + /// Set pointer to original model + void setOriginalModel(ClpSimplex *model); + + /// return pointer to original columns + const int *originalColumns() const; + /// return pointer to original rows + const int *originalRows() const; + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + */ + inline void setNonLinearValue(double value) + { + nonLinearValue_ = value; + } + inline double nonLinearValue() const + { + return nonLinearValue_; + } + /// Whether we want to do dual part of presolve + inline bool doDual() const + { + return (presolveActions_ & 1) == 0; + } + inline void setDoDual(bool doDual) + { + if (doDual) + presolveActions_ &= ~1; + else + presolveActions_ |= 1; + } + /// Whether we want to do singleton part of presolve + inline bool doSingleton() const + { + return (presolveActions_ & 2) == 0; + } + inline void setDoSingleton(bool doSingleton) + { + if (doSingleton) + presolveActions_ &= ~2; + else + presolveActions_ |= 2; + } + /// Whether we want to do doubleton part of presolve + inline bool doDoubleton() const + { + return (presolveActions_ & 4) == 0; + } + inline void setDoDoubleton(bool doDoubleton) + { + if (doDoubleton) + presolveActions_ &= ~4; + else + presolveActions_ |= 4; + } + /// Whether we want to do tripleton part of presolve + inline bool doTripleton() const + { + return (presolveActions_ & 8) == 0; + } + inline void setDoTripleton(bool doTripleton) + { + if (doTripleton) + presolveActions_ &= ~8; + else + presolveActions_ |= 8; + } + /// Whether we want to do tighten part of presolve + inline bool doTighten() const + { + return (presolveActions_ & 16) == 0; + } + inline void setDoTighten(bool doTighten) + { + if (doTighten) + presolveActions_ &= ~16; + else + presolveActions_ |= 16; + } + /// Whether we want to do forcing part of presolve + inline bool doForcing() const + { + return (presolveActions_ & 32) == 0; + } + inline void setDoForcing(bool doForcing) + { + if (doForcing) + presolveActions_ &= ~32; + else + presolveActions_ |= 32; + } + /// Whether we want to do impliedfree part of presolve + inline bool doImpliedFree() const + { + return (presolveActions_ & 64) == 0; + } + inline void setDoImpliedFree(bool doImpliedfree) + { + if (doImpliedfree) + presolveActions_ &= ~64; + else + presolveActions_ |= 64; + } + /// Whether we want to do dupcol part of presolve + inline bool doDupcol() const + { + return (presolveActions_ & 128) == 0; + } + inline void setDoDupcol(bool doDupcol) + { + if (doDupcol) + presolveActions_ &= ~128; + else + presolveActions_ |= 128; + } + /// Whether we want to do duprow part of presolve + inline bool doDuprow() const + { + return (presolveActions_ & 256) == 0; + } + inline void setDoDuprow(bool doDuprow) + { + if (doDuprow) + presolveActions_ &= ~256; + else + presolveActions_ |= 256; + } + /// Whether we want to do dependency part of presolve + inline bool doDependency() const + { + return (presolveActions_ & 32768) != 0; + } + inline void setDoDependency(bool doDependency) + { + if (doDependency) + presolveActions_ |= 32768; + else + presolveActions_ &= ~32768; + } + /// Whether we want to do transfer part of presolve + inline bool doTransfer() const + { + return (presolveActions_ & 65536) != 0; + } + inline void setDoTransfer(bool doTransfer) + { + if (doTransfer) + presolveActions_ |= 65536; + else + presolveActions_ &= ~65536; + } + /// Whether we want to do singleton column part of presolve + inline bool doSingletonColumn() const + { + return (presolveActions_ & 512) == 0; + } + inline void setDoSingletonColumn(bool doSingleton) + { + if (doSingleton) + presolveActions_ &= ~512; + else + presolveActions_ |= 512; + } + /// Whether we want to do gubrow part of presolve + inline bool doGubrow() const + { + return (presolveActions_ & 1024) == 0; + } + inline void setDoGubrow(bool doGubrow) + { + if (doGubrow) + presolveActions_ &= ~1024; + else + presolveActions_ |= 1024; + } + /// Whether we want to do twoxtwo part of presolve + inline bool doTwoxTwo() const + { + return (presolveActions_ & 2048) != 0; + } + inline void setDoTwoxtwo(bool doTwoxTwo) + { + if (!doTwoxTwo) + presolveActions_ &= ~2048; + else + presolveActions_ |= 2048; + } + /// Whether we want to allow duplicate intersections + inline bool doIntersection() const + { + return (presolveActions_ & 4096) != 0; + } + inline void setDoIntersection(bool doIntersection) + { + if (doIntersection) + presolveActions_ &= ~4096; + else + presolveActions_ |= 4096; + } + /** How much we want to zero small values from aggregation - ratio + 0 - 1.0e-12, 1 1.0e-11, 2 1.0e-10, 3 1.0e-9 */ + inline int zeroSmall() const + { + return (presolveActions_ & (8192 | 16384)) >> 13; + } + inline void setZeroSmall(int value) + { + presolveActions_ &= ~(8192 | 16384); + presolveActions_ |= value << 13; + } + /// Set whole group + inline int presolveActions() const + { + return presolveActions_ & 0xffffff; + } + inline void setPresolveActions(int action) + { + presolveActions_ = (presolveActions_ & 0xff000000) | (action & 0xffffff); + } + /// Substitution level + inline void setSubstitution(int value) + { + substitution_ = value; + } + /// Asks for statistics + inline void statistics() + { + presolveActions_ |= 0x80000000; + } + /// Return presolve status (0,1,2) + int presolveStatus() const; + + /**@name postsolve - postsolve the problem. If the problem + has not been solved to optimality, there are no guarantees. + If you are using an algorithm like simplex that has a concept + of "basic" rows/cols, then set updateStatus + + Note that if you modified the original problem after presolving, + then you must ``undo'' these modifications before calling postsolve. + This version updates original*/ + virtual void postsolve(bool updateStatus = true); + + /// Gets rid of presolve actions (e.g.when infeasible) + void destroyPresolve(); + + /**@name private or protected data */ +private: + /// Original model - must not be destroyed before postsolve + ClpSimplex *originalModel_; + + /// ClpPresolved model - up to user to destroy by deleteClpPresolvedModel + ClpSimplex *presolvedModel_; + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + One could also allow for cases where sign of coefficient is known. + */ + double nonLinearValue_; + /// Original column numbers + int *originalColumn_; + /// Original row numbers + int *originalRow_; + /// Row objective + double *rowObjective_; + /// The list of transformations applied. + const CoinPresolveAction *paction_; + + /// The postsolved problem will expand back to its former size + /// as postsolve transformations are applied. + /// It is efficient to allocate data structures for the final size + /// of the problem rather than expand them as needed. + /// These fields give the size of the original problem. + int ncols_; + int nrows_; + CoinBigIndex nelems_; + /// Number of major passes + int numberPasses_; + /// Substitution level + int substitution_; +#ifndef CLP_NO_STD + /// Name of saved model file + std::string saveFile_; +#endif + /** Whether we want to skip dual part of presolve etc. + 512 bit allows duplicate column processing on integer columns + and dual stuff on integers + */ + int presolveActions_; + +protected: + /// If you want to apply the individual presolve routines differently, + /// or perhaps add your own to the mix, + /// define a derived class and override this method + virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); + + /// Postsolving is pretty generic; just apply the transformations + /// in reverse order. + /// You will probably only be interested in overriding this method + /// if you want to add code to test for consistency + /// while debugging new presolve techniques. + virtual void postsolve(CoinPostsolveMatrix &prob); + /** This is main part of Presolve */ + virtual ClpSimplex *gutsOfPresolvedModel(ClpSimplex *originalModel, + double feasibilityTolerance, + bool keepIntegers, + int numberPasses, + bool dropNames, + bool doRowObjective, + const char *prohibitedRows = NULL, + const char *prohibitedColumns = NULL); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnDantzig.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnDantzig.hpp new file mode 100644 index 000000000..233c66d21 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnDantzig.hpp @@ -0,0 +1,74 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPrimalColumnDantzig_H +#define ClpPrimalColumnDantzig_H + +#include "ClpPrimalColumnPivot.hpp" + +//############################################################################# + +/** Primal Column Pivot Dantzig Algorithm Class + +This is simplest choice - choose largest infeasibility + +*/ + +class ClpPrimalColumnDantzig : public ClpPrimalColumnPivot { + +public: + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none. + Lumbers over all columns - slow + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + Can just do full price if you really want to be slow + */ + virtual int pivotColumn(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + + /// Just sets model + virtual void saveWeights(ClpSimplex *model, int) + { + model_ = model; + } + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpPrimalColumnDantzig(); + + /// Copy constructor + ClpPrimalColumnDantzig(const ClpPrimalColumnDantzig &); + + /// Assignment operator + ClpPrimalColumnDantzig &operator=(const ClpPrimalColumnDantzig &rhs); + + /// Destructor + virtual ~ClpPrimalColumnDantzig(); + + /// Clone + virtual ClpPrimalColumnPivot *clone(bool copyData = true) const; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnPivot.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnPivot.hpp new file mode 100644 index 000000000..fed36044a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnPivot.hpp @@ -0,0 +1,163 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPrimalcolumnPivot_H +#define ClpPrimalcolumnPivot_H + +class ClpSimplex; +class CoinIndexedVector; + +//############################################################################# + +/** Primal Column Pivot Abstract Base Class + +Abstract Base Class for describing an interface to an algorithm +to choose column pivot in primal simplex algorithm. For some algorithms +e.g. Dantzig choice then some functions may be null. For Dantzig +the only one of any importance is pivotColumn. + +If you wish to inherit from this look at ClpPrimalColumnDantzig.cpp +as that is simplest version. +*/ + +class ClpPrimalColumnPivot { + +public: + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none + + Normally updates reduced costs using result of last iteration + before selecting incoming column. + + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + + Inside pivotColumn the pivotRow_ and reduced cost from last iteration + are also used. + + So in the simplest case i.e. feasible we compute the row of the + tableau corresponding to last pivot and add a multiple of this + to current reduced costs. + + We can use other arrays to help updates + */ + virtual int pivotColumn(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2) + = 0; + + /// Updates weights - part 1 (may be empty) + virtual void updateWeights(CoinIndexedVector *input); + + /** Saves any weights round factorization as pivot rows may change + Will be empty unless steepest edge (will save model) + May also recompute infeasibility stuff + 1) before factorization + 2) after good factorization (if weights empty may initialize) + 3) after something happened but no factorization + (e.g. check for infeasible) + 4) as 2 but restore weights from previous snapshot + 5) forces some initialization e.g. weights + Also sets model + */ + virtual void saveWeights(ClpSimplex *model, int mode) = 0; + /** Signals pivot row choice: + -2 (default) - use normal pivot row choice + -1 to numberRows-1 - use this (will be checked) + way should be -1 to go to lower bound, +1 to upper bound + */ + virtual int pivotRow(double &way) + { + way = 0; + return -2; + } + /// Gets rid of all arrays (may be empty) + virtual void clearArrays(); + /// Returns true if would not find any column + virtual bool looksOptimal() const + { + return looksOptimal_; + } + /// Sets optimality flag (for advanced use) + virtual void setLooksOptimal(bool flag) + { + looksOptimal_ = flag; + } + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpPrimalColumnPivot(); + + /// Copy constructor + ClpPrimalColumnPivot(const ClpPrimalColumnPivot &); + + /// Assignment operator + ClpPrimalColumnPivot &operator=(const ClpPrimalColumnPivot &rhs); + + /// Destructor + virtual ~ClpPrimalColumnPivot(); + + /// Clone + virtual ClpPrimalColumnPivot *clone(bool copyData = true) const = 0; + + //@} + + ///@name Other + //@{ + /// Returns model + inline ClpSimplex *model() + { + return model_; + } + /// Sets model + inline void setModel(ClpSimplex *newmodel) + { + model_ = newmodel; + } + + /// Returns type (above 63 is extra information) + inline int type() + { + return type_; + } + + /** Returns number of extra columns for sprint algorithm - 0 means off. + Also number of iterations before recompute + */ + virtual int numberSprintColumns(int &numberIterations) const; + /// Switch off sprint idea + virtual void switchOffSprint(); + /// Called when maximum pivots changes + virtual void maximumPivotsChanged() {} + + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + //@{ + /// Pointer to model + ClpSimplex *model_; + /// Type of column pivot algorithm + int type_; + /// Says if looks optimal (normally computed) + bool looksOptimal_; + //@} +}; +#ifndef CLP_PRIMAL_SLACK_MULTIPLIER +#define CLP_PRIMAL_SLACK_MULTIPLIER 1.01 +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnSteepest.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnSteepest.hpp new file mode 100644 index 000000000..e6c250db6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpPrimalColumnSteepest.hpp @@ -0,0 +1,281 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpPrimalColumnSteepest_H +#define ClpPrimalColumnSteepest_H + +#include "ClpPrimalColumnPivot.hpp" +#include + +//############################################################################# +class CoinIndexedVector; + +/** Primal Column Pivot Steepest Edge Algorithm Class + +See Forrest-Goldfarb paper for algorithm + +*/ + +class ClpPrimalColumnSteepest : public ClpPrimalColumnPivot { + +public: + ///@name Algorithmic methods + //@{ + + /** Returns pivot column, -1 if none. + The Packed CoinIndexedVector updates has cost updates - for normal LP + that is just +-weight where a feasibility changed. It also has + reduced cost from last iteration in pivot row + Parts of operation split out into separate functions for + profiling and speed + */ + virtual int pivotColumn(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// For quadratic or funny nonlinearities + int pivotColumnOldMethod(CoinIndexedVector *updates, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Just update djs + void justDjs(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Update djs doing partial pricing (dantzig) + int partialPricing(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + int numberWanted, + int numberLook); + /// Update djs, weights for Devex using djs + void djsAndDevex(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /** Update djs, weights for Steepest using djs + sets best sequence (possibly) */ + void djsAndSteepest(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Update djs, weights for Devex using pivot row + void djsAndDevex2(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Update djs, weights for Steepest using pivot row + void djsAndSteepest2(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Update weights for Devex + void justDevex(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Update weights for Steepest + void justSteepest(CoinIndexedVector *updates, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + /// Updates two arrays for steepest + int transposeTimes2(const CoinIndexedVector *pi1, CoinIndexedVector *dj1, + const CoinIndexedVector *pi2, CoinIndexedVector *dj2, + CoinIndexedVector *spare, double scaleFactor); + + /// Updates weights - part 1 - also checks accuracy + virtual void updateWeights(CoinIndexedVector *input); + + /// Checks accuracy - just for debug + void checkAccuracy(int sequence, double relativeTolerance, + CoinIndexedVector *rowArray1, + CoinIndexedVector *rowArray2); + + /// Initialize weights + void initializeWeights(); + + /** Save weights - this may initialize weights as well + mode is - + 1) before factorization + 2) after factorization + 3) just redo infeasibilities + 4) restore weights + 5) at end of values pass (so need initialization) + */ + virtual void saveWeights(ClpSimplex *model, int mode); + /// redo infeasibilities + void redoInfeasibilities(); + /// Gets rid of last update + virtual void unrollWeights(); + /// Gets rid of all arrays + virtual void clearArrays(); + /// Returns true if would not find any column + virtual bool looksOptimal() const; + /// Called when maximum pivots changes + virtual void maximumPivotsChanged(); + //@} + + /**@name gets and sets */ + //@{ + /// Mode + inline int mode() const + { + return mode_; + } + /// Set mode + inline void setMode(int mode) + { + mode_ = mode; + } + /// square of infeasibility array (just for infeasible columns) + inline CoinIndexedVector *infeasible() const + { + return infeasible_; + } + /// Weights + inline const double *weights() const + { + return weights_; + } + /// alternate weight array + inline CoinIndexedVector *alternateWeights() const + { + return alternateWeights_; + } + /** Returns number of extra columns for sprint algorithm - 0 means off. + Also number of iterations before recompute + */ + virtual int numberSprintColumns(int &numberIterations) const; + /// Switch off sprint idea + virtual void switchOffSprint(); + + //@} + + /** enums for persistence + */ + enum Persistence { + normal = 0x00, // create (if necessary) and destroy + keep = 0x01 // create (if necessary) and leave + }; + + ///@name Constructors and destructors + //@{ + /** Default Constructor + 0 is exact devex, 1 full steepest, 2 is partial exact devex + 3 switches between 0 and 2 depending on factorization + 4 starts as partial dantzig/devex but then may switch between 0 and 2. + By partial exact devex is meant that the weights are updated as normal + but only part of the nonbasic variables are scanned. + This can be faster on very easy problems. + */ + ClpPrimalColumnSteepest(int mode = 3); + + /// Copy constructor + ClpPrimalColumnSteepest(const ClpPrimalColumnSteepest &rhs); + + /// Assignment operator + ClpPrimalColumnSteepest &operator=(const ClpPrimalColumnSteepest &rhs); + + /// Destructor + virtual ~ClpPrimalColumnSteepest(); + + /// Clone + virtual ClpPrimalColumnPivot *clone(bool copyData = true) const; + + //@} + + ///@name Private functions to deal with devex + /** reference would be faster using ClpSimplex's status_, + but I prefer to keep modularity. + */ + inline bool reference(int i) const + { + return ((reference_[i >> 5] >> (i & 31)) & 1) != 0; + } + inline void setReference(int i, bool trueFalse) + { + unsigned int &value = reference_[i >> 5]; + int bit = i & 31; + if (trueFalse) + value |= (1 << bit); + else + value &= ~(1 << bit); + } + /// Set/ get persistence + inline void setPersistence(Persistence life) + { + persistence_ = life; + } + inline Persistence persistence() const + { + return persistence_; + } + + //@} + //--------------------------------------------------------------------------- + +protected: + ///@name Protected member data + // Update weight + double devex_; + /// weight array + double *weights_; + /// square of infeasibility array (just for infeasible columns) + CoinIndexedVector *infeasible_; + /// alternate weight array (so we can unroll) + CoinIndexedVector *alternateWeights_; + /// save weight array (so we can use checkpoint) + double *savedWeights_; + // Array for exact devex to say what is in reference framework + unsigned int *reference_; + /** Status + 0) Normal + -1) Needs initialization + 1) Weights are stored by sequence number + */ + int state_; + /** + 0 is exact devex, 1 full steepest, 2 is partial exact devex + 3 switches between 0 and 2 depending on factorization + 4 starts as partial dantzig/devex but then may switch between 0 and 2. + 5 is always partial dantzig + By partial exact devex is meant that the weights are updated as normal + but only part of the nonbasic variables are scanned. + This can be faster on very easy problems. + + New dubious option is >=10 which does mini-sprint + + */ + int mode_; + /* Infeasibility state i.e. array of infeasibilities and sequenceIn- + 0 - correct + 1 - needs correcting + 2 - not known but column sequence has been chosen + */ + int infeasibilitiesState_; + /// Life of weights + Persistence persistence_; + /// Number of times switched from partial dantzig to 0/2 + int numberSwitched_; + // This is pivot row (or pivot sequence round re-factorization) + int pivotSequence_; + // This is saved pivot sequence + int savedPivotSequence_; + // This is saved outgoing variable + int savedSequenceOut_; + // Iteration when last rectified + int lastRectified_; + // Size of factorization at invert (used to decide algorithm) + int sizeFactorization_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpQuadraticObjective.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpQuadraticObjective.hpp new file mode 100644 index 000000000..b0d5e5624 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpQuadraticObjective.hpp @@ -0,0 +1,161 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef ClpQuadraticObjective_H +#define ClpQuadraticObjective_H + +#include "ClpObjective.hpp" +#include "CoinPackedMatrix.hpp" + +//############################################################################# + +/** Quadratic Objective Class + +*/ + +class ClpQuadraticObjective : public ClpObjective { + +public: + ///@name Stuff + //@{ + + /** Returns gradient. If Quadratic then solution may be NULL, + also returns an offset (to be added to current one) + If refresh is false then uses last solution + Uses model for scaling + includeLinear 0 - no, 1 as is, 2 as feasible + */ + virtual double *gradient(const ClpSimplex *model, + const double *solution, double &offset, bool refresh, + int includeLinear = 2); + /// Resize objective + /** Returns reduced gradient.Returns an offset (to be added to current one). + */ + virtual double reducedGradient(ClpSimplex *model, double *region, + bool useFeasibleCosts); + /** Returns step length which gives minimum of objective for + solution + theta * change vector up to maximum theta. + + arrays are numberColumns+numberRows + Also sets current objective, predicted and at maximumTheta + */ + virtual double stepLength(ClpSimplex *model, + const double *solution, + const double *change, + double maximumTheta, + double ¤tObj, + double &predictedObj, + double &thetaObj); + /// Return objective value (without any ClpModel offset) (model may be NULL) + virtual double objectiveValue(const ClpSimplex *model, const double *solution) const; + virtual void resize(int newNumberColumns); + /// Delete columns in objective + virtual void deleteSome(int numberToDelete, const int *which); + /// Scale objective + virtual void reallyScale(const double *columnScale); + /** Given a zeroed array sets nonlinear columns to 1. + Returns number of nonlinear columns + */ + virtual int markNonlinear(char *which); + + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + ClpQuadraticObjective(); + + /// Constructor from objective + ClpQuadraticObjective(const double *linearObjective, int numberColumns, + const CoinBigIndex *start, + const int *column, const double *element, + int numberExtendedColumns_ = -1); + + /** Copy constructor . + If type is -1 then make sure half symmetric, + if +1 then make sure full + */ + ClpQuadraticObjective(const ClpQuadraticObjective &rhs, int type = 0); + /** Subset constructor. Duplicates are allowed + and order is as given. + */ + ClpQuadraticObjective(const ClpQuadraticObjective &rhs, int numberColumns, + const int *whichColumns); + + /// Assignment operator + ClpQuadraticObjective &operator=(const ClpQuadraticObjective &rhs); + + /// Destructor + virtual ~ClpQuadraticObjective(); + + /// Clone + virtual ClpObjective *clone() const; + /** Subset clone. Duplicates are allowed + and order is as given. + */ + virtual ClpObjective *subsetClone(int numberColumns, + const int *whichColumns) const; + + /** Load up quadratic objective. This is stored as a CoinPackedMatrix */ + void loadQuadraticObjective(const int numberColumns, + const CoinBigIndex *start, + const int *column, const double *element, + int numberExtendedColumns = -1); + void loadQuadraticObjective(const CoinPackedMatrix &matrix); + /// Get rid of quadratic objective + void deleteQuadraticObjective(); + //@} + ///@name Gets and sets + //@{ + /// Quadratic objective + inline CoinPackedMatrix *quadraticObjective() const + { + return quadraticObjective_; + } + /// Linear objective + inline double *linearObjective() const + { + return objective_; + } + /// Length of linear objective which could be bigger + inline int numberExtendedColumns() const + { + return numberExtendedColumns_; + } + /// Number of columns in quadratic objective + inline int numberColumns() const + { + return numberColumns_; + } + /// If a full or half matrix + inline bool fullMatrix() const + { + return fullMatrix_; + } + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + /// Quadratic objective + CoinPackedMatrix *quadraticObjective_; + /// Objective + double *objective_; + /// Gradient + double *gradient_; + /// Useful to have number of columns about + int numberColumns_; + /// Also length of linear objective which could be bigger + int numberExtendedColumns_; + /// True if full symmetric matrix, false if half + bool fullMatrix_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplex.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplex.hpp new file mode 100644 index 000000000..b5cf8c2b0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplex.hpp @@ -0,0 +1,2137 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplex_H +#define ClpSimplex_H + +#include +#include +#include "ClpModel.hpp" +#include "ClpMatrixBase.hpp" +#include "ClpSolve.hpp" +#include "ClpConfig.h" +#include "CoinIndexedVector.hpp" +class ClpDualRowPivot; +class ClpPrimalColumnPivot; +class ClpFactorization; +class CoinFactorization; +class CoinIndexedVector; +class ClpNonLinearCost; +class ClpNodeStuff; +class CoinStructuredModel; +class OsiClpSolverInterface; +class CoinWarmStartBasis; +class ClpDisasterHandler; +class ClpConstraint; +/* + May want to use Clp defaults so that with ABC defined but not used + it behaves as Clp (and ABC used will be different than if not defined) + */ +#ifdef ABC_INHERIT +#ifndef CLP_INHERIT_MODE +#define CLP_INHERIT_MODE 1 +#endif +#ifndef ABC_CLP_DEFAULTS +#define ABC_CLP_DEFAULTS 0 +#endif +#else +#undef ABC_CLP_DEFAULTS +#define ABC_CLP_DEFAULTS 1 +#endif +#ifdef CLP_HAS_ABC +#include "AbcCommon.hpp" +class AbcTolerancesEtc; +class AbcSimplex; +#include "CoinAbcCommon.hpp" +#endif +#ifndef ABC_INHERIT +#if ABOCA_LITE +#ifndef FAKE_CILK +#include +#else +#undef cilk_for +#undef cilk_spawn +#undef cilk_sync +#define cilk_for for +#define cilk_spawn +#define cilk_sync +#endif +#ifndef LONG_REGION_2 +#define LONG_REGION_2 1 +#endif +#define SHORT_REGION 1 +#else +#define cilk_spawn +#define cilk_sync +#endif +#ifdef LONG_REGION_2 +#define SHORT_REGION 1 +#else +#define SHORT_REGION 2 +#endif +// for now keep simple +#undef LONG_REGION_2 +#undef SHORT_REGION +#define SHORT_REGION 2 +#else +//ABC_INHERIT +#define LONG_REGION_2 1 +#define SHORT_REGION 1 +#endif +/** This solves LPs using the simplex method + + It inherits from ClpModel and all its arrays are created at + algorithm time. Originally I tried to work with model arrays + but for simplicity of coding I changed to single arrays with + structural variables then row variables. Some coding is still + based on old style and needs cleaning up. + + For a description of algorithms: + + for dual see ClpSimplexDual.hpp and at top of ClpSimplexDual.cpp + for primal see ClpSimplexPrimal.hpp and at top of ClpSimplexPrimal.cpp + + There is an algorithm data member. + for primal variations + and - for dual variations + +*/ + +class ClpSimplex : public ClpModel { + friend void ClpSimplexUnitTest(const std::string &mpsDir); + +public: + /** enums for status of various sorts. + First 4 match CoinWarmStartBasis, + isFixed means fixed at lower bound and out of basis + */ + enum Status { + isFree = 0x00, + basic = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03, + superBasic = 0x04, + isFixed = 0x05 + }; + // For Dual + enum FakeBound { + noFake = 0x00, + lowerFake = 0x01, + upperFake = 0x02, + bothFake = 0x03 + }; + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSimplex(bool emptyMessages = false); + + /** Copy constructor. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) + */ + ClpSimplex(const ClpSimplex &rhs, int scalingMode = -1); + /** Copy constructor from model. May scale depending on mode + -1 leave mode as is + 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) + */ + ClpSimplex(const ClpModel &rhs, int scalingMode = -1); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + Can optionally modify rhs to take into account variables NOT in list + in this case duplicates are not allowed (also see getbackSolution) + */ + ClpSimplex(const ClpModel *wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns, + bool dropNames = true, bool dropIntegers = true, + bool fixOthers = false); + /** Subproblem constructor. A subset of whole model is created from the + row and column lists given. The new order is given by list order and + duplicates are allowed. Name and integer information can be dropped + Can optionally modify rhs to take into account variables NOT in list + in this case duplicates are not allowed (also see getbackSolution) + */ + ClpSimplex(const ClpSimplex *wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns, + bool dropNames = true, bool dropIntegers = true, + bool fixOthers = false); + /** This constructor modifies original ClpSimplex and stores + original stuff in created ClpSimplex. It is only to be used in + conjunction with originalModel */ + ClpSimplex(ClpSimplex *wholeModel, + int numberColumns, const int *whichColumns); + /** This copies back stuff from miniModel and then deletes miniModel. + Only to be used with mini constructor */ + void originalModel(ClpSimplex *miniModel); +#ifdef ABC_INHERIT + inline int abcState() const + { + return abcState_; + } + inline void setAbcState(int state) + { + abcState_ = state; + } + inline AbcSimplex *abcSimplex() const + { + return abcSimplex_; + } + inline void setAbcSimplex(AbcSimplex *simplex) + { + abcSimplex_ = simplex; + } + /// Returns 0 if dual can be skipped + int doAbcDual(); + /// Returns 0 if primal can be skipped + int doAbcPrimal(int ifValuesPass); +#endif + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + void setPersistenceFlag(int value); + /// Save a copy of model with certain state - normally without cuts + void makeBaseModel(); + /// Switch off base model + void deleteBaseModel(); + /// See if we have base model + inline ClpSimplex *baseModel() const + { + return baseModel_; + } + /** Reset to base model (just size and arrays needed) + If model NULL use internal copy + */ + void setToBaseModel(ClpSimplex *model = NULL); + /// Assignment operator. This copies the data + ClpSimplex &operator=(const ClpSimplex &rhs); + /// Destructor + ~ClpSimplex(); + // Ones below are just ClpModel with some changes + /** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ + void loadProblem(const ClpMatrixBase &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + + /** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /// This one is for after presolve to save memory + void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, const int *length, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + const double *rowObjective = NULL); + /** This loads a model from a coinModel object - returns number of errors. + If keepSolution true and size is same as current then + keeps current status and solution + */ + int loadProblem(CoinModel &modelObject, bool keepSolution = false); + /// Read an mps file from the given filename + int readMps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + /// Read GMPL files from the given filenames + int readGMPL(const char *filename, const char *dataName, + bool keepNames = false); + /// Read file in LP format from file with name filename. + /// See class CoinLpIO for description of this format. + int readLp(const char *filename, const double epsilon = 1e-5); + /** Write the problem into an Lp file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants.*/ + void writeLp(const char *filename, + const char *extension = "lp", + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + /** Borrow model. This is so we dont have to copy large amounts + of data around. It assumes a derived class wants to overwrite + an empty model with a real one - while it does an algorithm. + This is same as ClpModel one, but sets scaling on etc. */ + void borrowModel(ClpModel &otherModel); + void borrowModel(ClpSimplex &otherModel); + /// Pass in Event handler (cloned and deleted at end) + void passInEventHandler(const ClpEventHandler *eventHandler); + /// Puts solution back into small model + void getbackSolution(const ClpSimplex &smallModel, const int *whichRow, const int *whichColumn); + /** Load nonlinear part of problem from AMPL info + Returns 0 if linear + 1 if quadratic objective + 2 if quadratic constraints + 3 if nonlinear objective + 4 if nonlinear constraints + -1 on failure + */ + int loadNonLinear(void *info, int &numberConstraints, + ClpConstraint **&constraints); +#ifdef ABC_INHERIT + /// Loads tolerances etc + void loadTolerancesEtc(const AbcTolerancesEtc &data); + /// Unloads tolerances etc + void unloadTolerancesEtc(AbcTolerancesEtc &data); +#endif + //@} + + /**@name Functions most useful to user */ + //@{ + /** General solve algorithm which can do presolve. + See ClpSolve.hpp for options + */ + int initialSolve(ClpSolve &options); + /// Default initial solve + int initialSolve(); + /// Dual initial solve + int initialDualSolve(); + /// Primal initial solve + int initialPrimalSolve(); + /// Barrier initial solve + int initialBarrierSolve(); + /// Barrier initial solve, not to be followed by crossover + int initialBarrierNoCrossSolve(); + /** Dual algorithm - see ClpSimplexDual.hpp for method. + ifValuesPass==2 just does values pass and then stops. + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + */ + int dual(int ifValuesPass = 0, int startFinishOptions = 0); + // If using Debug + int dualDebug(int ifValuesPass = 0, int startFinishOptions = 0); + /** Primal algorithm - see ClpSimplexPrimal.hpp for method. + ifValuesPass==2 just does values pass and then stops. + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + */ + int primal(int ifValuesPass = 0, int startFinishOptions = 0); + /** Solves nonlinear problem using SLP - may be used as crash + for other algorithms when number of iterations small. + Also exits if all problematical variables are changing + less than deltaTolerance + */ + int nonlinearSLP(int numberPasses, double deltaTolerance); + /** Solves problem with nonlinear constraints using SLP - may be used as crash + for other algorithms when number of iterations small. + Also exits if all problematical variables are changing + less than deltaTolerance + */ + int nonlinearSLP(int numberConstraints, ClpConstraint **constraints, + int numberPasses, double deltaTolerance); + /** Solves using barrier (assumes you have good cholesky factor code). + Does crossover to simplex if asked*/ + int barrier(bool crossover = true); + /** Solves non-linear using reduced gradient. Phase = 0 get feasible, + =1 use solution */ + int reducedGradient(int phase = 0); + /// Solve using structure of model and maybe in parallel + int solve(CoinStructuredModel *model); +#ifdef ABC_INHERIT + /** solvetype 0 for dual, 1 for primal + startup 1 for values pass + interrupt whether to pass across interrupt handler + add 10 to return AbcSimplex + */ + AbcSimplex *dealWithAbc(int solveType, int startUp, bool interrupt = false); + //void dealWithAbc(int solveType,int startUp,bool interrupt=false); +#endif + /** This loads a model from a CoinStructuredModel object - returns number of errors. + If originalOrder then keep to order stored in blocks, + otherwise first column/rows correspond to first block - etc. + If keepSolution true and size is same as current then + keeps current status and solution + */ + int loadProblem(CoinStructuredModel &modelObject, + bool originalOrder = true, bool keepSolution = false); + /** + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + + return code as dual/primal + */ + int cleanup(int cleanupScaling); + /** Clean primal solution + If you expect solution to only have exact multiples of "exactMultiple" then + this tries moving solution values to nearest multiple. If still feasible + then the solution is replaced. + + This is designed for the case where values should be integral, but Clp may + have values at e.g. 1.0e-13 + Returns 0 if successful, n if n rhs violated + The dual version may be written if this gets used. + */ + int cleanPrimalSolution(double exactMultiple); + /** Dual ranging. + This computes increase/decrease in cost for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + For non-basic variables the information is trivial to compute and the change in cost is just minus the + reduced cost and the sequence number will be that of the non-basic variables. + For basic variables a ratio test is between the reduced costs for non-basic variables + and the row of the tableau corresponding to the basic variable. + The increase/decrease value is always >= 0.0 + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with + the value of variable if such a change in cost were made (the existing bounds are ignored) + + Returns non-zero if infeasible unbounded etc + */ + int dualRanging(int numberCheck, const int *which, + double *costIncrease, int *sequenceIncrease, + double *costDecrease, int *sequenceDecrease, + double *valueIncrease = NULL, double *valueDecrease = NULL); + /** Primal ranging. + This computes increase/decrease in value for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + This should only be used for non-basic variabls as otherwise information is pretty useless + For basic variables the sequence number will be that of the basic variables. + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + Returns non-zero if infeasible unbounded etc + */ + int primalRanging(int numberCheck, const int *which, + double *valueIncrease, int *sequenceIncrease, + double *valueDecrease, int *sequenceDecrease); + /** + Modifies coefficients etc and if necessary pivots in and out. + All at same status will be done (basis may go singular). + User can tell which others have been done (i.e. if status matches). + If called from outside will change status and return 0. + If called from event handler returns non-zero if user has to take action. + indices>=numberColumns are slacks (obviously no coefficients) + status array is (char) Status enum + */ + int modifyCoefficientsAndPivot(int number, + const int *which, + const CoinBigIndex *start, + const int *row, + const double *newCoefficient, + const unsigned char *newStatus = NULL, + const double *newLower = NULL, + const double *newUpper = NULL, + const double *newObjective = NULL); + /** Take out duplicate rows (includes scaled rows and intersections). + On exit whichRows has rows to delete - return code is number can be deleted + or -1 if would be infeasible. + If tolerance is -1.0 use primalTolerance for equality rows and infeasibility + If cleanUp not zero then spend more time trying to leave more stable row + and make row bounds exact multiple of cleanUp if close enough + */ + int outDuplicateRows(int numberLook, int *whichRows, bool noOverlaps = false, double tolerance = -1.0, + double cleanUp = 0.0); + /** Try simple crash like techniques to get closer to primal feasibility + returns final sum of infeasibilities */ + double moveTowardsPrimalFeasible(); + /** Try simple crash like techniques to remove super basic slacks + but only if > threshold */ + void removeSuperBasicSlacks(int threshold = 0); + /** Mini presolve (faster) + Char arrays must be numberRows and numberColumns long + on entry second part must be filled in as follows - + 0 - possible + >0 - take out and do something (depending on value - TBD) + -1 row/column can't vanish but can have entries removed/changed + -2 don't touch at all + on exit <=0 ones will be in presolved problem + struct will be created and will be long enough + (information on length etc in first entry) + user must delete struct + */ + ClpSimplex *miniPresolve(char *rowType, char *columnType, void **info); + /// After mini presolve + void miniPostsolve(const ClpSimplex *presolvedModel, void *info); + /// mini presolve and solve + void miniSolve(char *rowType, char *columnType, int algorithm, int startUp); + /** Write the basis in MPS format to the specified file. + If writeValues true writes values of structurals + (and adds VALUES to end of NAME card) + + Row and column names may be null. + formatType is +
    +
  • 0 - normal +
  • 1 - extra accuracy +
  • 2 - IEEE hex (later) +
+ + Returns non-zero on I/O error + */ + int writeBasis(const char *filename, + bool writeValues = false, + int formatType = 0) const; + /** Read a basis from the given filename, + returns -1 on file error, 0 if no values, 1 if values */ + int readBasis(const char *filename); + /// Returns a basis (to be deleted by user) + CoinWarmStartBasis *getBasis() const; + /// Passes in factorization + void setFactorization(ClpFactorization &factorization); + // Swaps factorization + ClpFactorization *swapFactorization(ClpFactorization *factorization); + /// Copies in factorization to existing one + void copyFactorization(ClpFactorization &factorization); + /** Tightens primal bounds to make dual faster. Unless + fixed or doTight>10, bounds are slightly looser than they could be. + This is to make dual go faster and is probably not needed + with a presolve. Returns non-zero if problem infeasible. + + Fudge for branch and bound - put bounds on columns of factor * + largest value (at continuous) - should improve stability + in branch and bound on infeasible branches (0.0 is off) + */ + int tightenPrimalBounds(double factor = 0.0, int doTight = 0, bool tightIntegers = false); + /** Crash - at present just aimed at dual, returns + -2 if dual preferred and crash basis created + -1 if dual preferred and all slack basis preferred + 0 if basis going in was not all slack + 1 if primal preferred and all slack basis preferred + 2 if primal preferred and crash basis created. + + if gap between bounds <="gap" variables can be flipped + ( If pivot -1 then can be made super basic!) + + If "pivot" is + -1 No pivoting - always primal + 0 No pivoting (so will just be choice of algorithm) + 1 Simple pivoting e.g. gub + 2 Mini iterations + */ + int crash(double gap, int pivot); + /// Sets row pivot choice algorithm in dual + void setDualRowPivotAlgorithm(ClpDualRowPivot &choice); + /// Sets column pivot choice algorithm in primal + void setPrimalColumnPivotAlgorithm(ClpPrimalColumnPivot &choice); + /// Create a hotstart point of the optimization process + void markHotStart(void *&saveStuff); + /// Optimize starting from the hotstart + void solveFromHotStart(void *saveStuff); + /// Delete the snapshot + void unmarkHotStart(void *saveStuff); + /** For strong branching. On input lower and upper are new bounds + while on output they are change in objective function values + (>1.0e50 infeasible). + Return code is 0 if nothing interesting, -1 if infeasible both + ways and +1 if infeasible one way (check values to see which one(s)) + Solutions are filled in as well - even down, odd up - also + status and number of iterations + */ + int strongBranching(int numberVariables, const int *variables, + double *newLower, double *newUpper, + double **outputSolution, + int *outputStatus, int *outputIterations, + bool stopOnFirstInfeasible = true, + bool alwaysFinish = false, + int startFinishOptions = 0); + /// Fathom - 1 if solution + int fathom(void *stuff); + /** Do up to N deep - returns + -1 - no solution nNodes_ valid nodes + >= if solution and that node gives solution + ClpNode array is 2**N long. Values for N and + array are in stuff (nNodes_ also in stuff) */ + int fathomMany(void *stuff); + /// Double checks OK + double doubleCheck(); + /// Starts Fast dual2 + int startFastDual2(ClpNodeStuff *stuff); + /// Like Fast dual + int fastDual2(ClpNodeStuff *stuff); + /// Stops Fast dual2 + void stopFastDual2(ClpNodeStuff *stuff); + /** Deals with crunch aspects + mode 0 - in + 1 - out with solution + 2 - out without solution + returns small model or NULL + */ + ClpSimplex *fastCrunch(ClpNodeStuff *stuff, int mode); + //@} + + /**@name Needed for functionality of OsiSimplexInterface */ + //@{ + /** Pivot in a variable and out a variable. Returns 0 if okay, + 1 if inaccuracy forced re-factorization, -1 if would be singular. + Also updates primal/dual infeasibilities. + Assumes sequenceIn_ and pivotRow_ set and also directionIn and Out. + */ + int pivot(); + + /** Pivot in a variable and choose an outgoing one. Assumes primal + feasible - will not go through a bound. Returns step length in theta + Returns ray in ray_ (or NULL if no pivot) + Return codes as before but -1 means no acceptable pivot + */ + int primalPivotResult(); + + /** Pivot out a variable and choose an incoing one. Assumes dual + feasible - will not go through a reduced cost. + Returns step length in theta + Return codes as before but -1 means no acceptable pivot + */ + int dualPivotResultPart1(); + /** Do actual pivot + state is 0 if need tableau column, 1 if in rowArray_[1] + */ + int pivotResultPart2(int algorithm, int state); + + /** Common bits of coding for dual and primal. Return 0 if okay, + 1 if bad matrix, 2 if very bad factorization + + startFinishOptions - bits + 1 - do not delete work areas and factorization at end + 2 - use old factorization if same number of rows + 4 - skip as much initialization of work areas as possible + (based on whatsChanged in clpmodel.hpp) ** work in progress + maybe other bits later + + */ + int startup(int ifValuesPass, int startFinishOptions = 0); + void finish(int startFinishOptions = 0); + + /** Factorizes and returns true if optimal. Used by user */ + bool statusOfProblem(bool initial = false); + /// If user left factorization frequency then compute + void defaultFactorizationFrequency(); + /// Copy across enabled stuff from one solver to another + void copyEnabledStuff(const ClpSimplex *rhs); + //@} + + /**@name most useful gets and sets */ + //@{ + /// If problem is primal feasible + inline bool primalFeasible() const + { + return (numberPrimalInfeasibilities_ == 0); + } + /// If problem is dual feasible + inline bool dualFeasible() const + { + return (numberDualInfeasibilities_ == 0); + } + /// factorization + inline ClpFactorization *factorization() const + { + return factorization_; + } + /// Sparsity on or off + bool sparseFactorization() const; + void setSparseFactorization(bool value); + /// Factorization frequency + int factorizationFrequency() const; + void setFactorizationFrequency(int value); + /// Dual bound + inline double dualBound() const + { + return dualBound_; + } + void setDualBound(double value); + /// Infeasibility cost + inline double infeasibilityCost() const + { + return infeasibilityCost_; + } + void setInfeasibilityCost(double value); + /** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ + /** Perturbation: + 50 - switch on perturbation + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + others are for playing + */ + inline int perturbation() const + { + return perturbation_; + } + void setPerturbation(int value); + /// Current (or last) algorithm + inline int algorithm() const + { + return algorithm_; + } + /// Set algorithm + inline void setAlgorithm(int value) + { + algorithm_ = value; + } + /// Return true if the objective limit test can be relied upon + bool isObjectiveLimitTestValid() const; + /// Sum of dual infeasibilities + inline double sumDualInfeasibilities() const + { + return sumDualInfeasibilities_; + } + inline void setSumDualInfeasibilities(double value) + { + sumDualInfeasibilities_ = value; + } + /// Sum of relaxed dual infeasibilities + inline double sumOfRelaxedDualInfeasibilities() const + { + return sumOfRelaxedDualInfeasibilities_; + } + inline void setSumOfRelaxedDualInfeasibilities(double value) + { + sumOfRelaxedDualInfeasibilities_ = value; + } + /// Number of dual infeasibilities + inline int numberDualInfeasibilities() const + { + return numberDualInfeasibilities_; + } + inline void setNumberDualInfeasibilities(int value) + { + numberDualInfeasibilities_ = value; + } + /// Number of dual infeasibilities (without free) + inline int numberDualInfeasibilitiesWithoutFree() const + { + return numberDualInfeasibilitiesWithoutFree_; + } + /// Sum of primal infeasibilities + inline double sumPrimalInfeasibilities() const + { + return sumPrimalInfeasibilities_; + } + inline void setSumPrimalInfeasibilities(double value) + { + sumPrimalInfeasibilities_ = value; + } + /// Sum of relaxed primal infeasibilities + inline double sumOfRelaxedPrimalInfeasibilities() const + { + return sumOfRelaxedPrimalInfeasibilities_; + } + inline void setSumOfRelaxedPrimalInfeasibilities(double value) + { + sumOfRelaxedPrimalInfeasibilities_ = value; + } + /// Number of primal infeasibilities + inline int numberPrimalInfeasibilities() const + { + return numberPrimalInfeasibilities_; + } + inline void setNumberPrimalInfeasibilities(int value) + { + numberPrimalInfeasibilities_ = value; + } + /** Save model to file, returns 0 if success. This is designed for + use outside algorithms so does not save iterating arrays etc. + It does not save any messaging information. + Does not save scaling values. + It does not know about all types of virtual functions. + */ + int saveModel(const char *fileName); + /** Restore model from file, returns 0 if success, + deletes current model */ + int restoreModel(const char *fileName); + + /** Just check solution (for external use) - sets sum of + infeasibilities etc. + If setToBounds 0 then primal column values not changed + and used to compute primal row activity values. If 1 or 2 + then status used - so all nonbasic variables set to + indicated bound and if any values changed (or ==2) basic values re-computed. + */ + void checkSolution(int setToBounds = 0); + /** Just check solution (for internal use) - sets sum of + infeasibilities etc. */ + void checkSolutionInternal(); + /// Check unscaled primal solution but allow for rounding error + void checkUnscaledSolution(); + /// Useful row length arrays (0,1,2,3,4,5) + inline CoinIndexedVector *rowArray(int index) const + { + return rowArray_[index]; + } + /// Useful column length arrays (0,1,2,3,4,5) + inline CoinIndexedVector *columnArray(int index) const + { + return columnArray_[index]; + } + //@} + + /******************** End of most useful part **************/ + /**@name Functions less likely to be useful to casual user */ + //@{ + /** Given an existing factorization computes and checks + primal and dual solutions. Uses input arrays for variables at + bounds. Returns feasibility states */ + int getSolution(const double *rowActivities, + const double *columnActivities); + /** Given an existing factorization computes and checks + primal and dual solutions. Uses current problem arrays for + bounds. Returns feasibility states */ + int getSolution(); + /** Constructs a non linear cost from list of non-linearities (columns only) + First lower of each column is taken as real lower + Last lower is taken as real upper and cost ignored + + Returns nonzero if bad data e.g. lowers not monotonic + */ + int createPiecewiseLinearCosts(const int *starts, + const double *lower, const double *gradient); + /// dual row pivot choice + inline ClpDualRowPivot *dualRowPivot() const + { + return dualRowPivot_; + } + /// primal column pivot choice + inline ClpPrimalColumnPivot *primalColumnPivot() const + { + return primalColumnPivot_; + } + /// Returns true if model looks OK + inline bool goodAccuracy() const + { + return (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7); + } + /** Return model - updates any scalars */ + void returnModel(ClpSimplex &otherModel); + /** Factorizes using current basis. + solveType - 1 iterating, 0 initial, -1 external + If 10 added then in primal values pass + Return codes are as from ClpFactorization unless initial factorization + when total number of singularities is returned. + Special case is numberRows_+1 -> all slack basis. + */ + int internalFactorize(int solveType); + /// Save data + ClpDataSave saveData(); + /// Restore data + void restoreData(ClpDataSave saved); + /// Clean up status + void cleanStatus(); + /// Factorizes using current basis. For external use + int factorize(); + /** Computes duals from scratch. If givenDjs then + allows for nonzero basic djs */ + void computeDuals(double *givenDjs); + /// Computes primals from scratch + void computePrimals(const double *rowActivities, + const double *columnActivities); + /** Adds multiple of a column into an array */ + void add(double *array, + int column, double multiplier) const; + /** + Unpacks one column of the matrix into indexed array + Uses sequenceIn_ + Also applies scaling if needed + */ + void unpack(CoinIndexedVector *rowArray) const; + /** + Unpacks one column of the matrix into indexed array + Slack if sequence>= numberColumns + Also applies scaling if needed + */ + void unpack(CoinIndexedVector *rowArray, int sequence) const; + /** + Unpacks one column of the matrix into indexed array + ** as packed vector + Uses sequenceIn_ + Also applies scaling if needed + */ + void unpackPacked(CoinIndexedVector *rowArray); + /** + Unpacks one column of the matrix into indexed array + ** as packed vector + Slack if sequence>= numberColumns + Also applies scaling if needed + */ + void unpackPacked(CoinIndexedVector *rowArray, int sequence); +#ifndef CLP_USER_DRIVEN +protected: +#endif + /** + This does basis housekeeping and does values for in/out variables. + Can also decide to re-factorize + */ + int housekeeping(double objectiveChange); + /** This sets largest infeasibility and most infeasible and sum + and number of infeasibilities (Primal) */ + void checkPrimalSolution(const double *rowActivities = NULL, + const double *columnActivies = NULL); + /** This sets largest infeasibility and most infeasible and sum + and number of infeasibilities (Dual) */ + void checkDualSolution(); + /** This sets sum and number of infeasibilities (Dual and Primal) */ + void checkBothSolutions(); + /** If input negative scales objective so maximum <= -value + and returns scale factor used. If positive unscales and also + redoes dual stuff + */ + double scaleObjective(double value); + /// Solve using Dantzig-Wolfe decomposition and maybe in parallel + int solveDW(CoinStructuredModel *model, ClpSolve &options); + /// Solve using Benders decomposition and maybe in parallel + int solveBenders(CoinStructuredModel *model, ClpSolve &options); + +public: + /** For advanced use. When doing iterative solves things can get + nasty so on values pass if incoming solution has largest + infeasibility < incomingInfeasibility throw out variables + from basis until largest infeasibility < allowedInfeasibility + or incoming largest infeasibility. + If allowedInfeasibility>= incomingInfeasibility this is + always possible altough you may end up with an all slack basis. + + Defaults are 1.0,10.0 + */ + void setValuesPassAction(double incomingInfeasibility, + double allowedInfeasibility); + /** Get a clean factorization - i.e. throw out singularities + may do more later */ + int cleanFactorization(int ifValuesPass); + //@} + /**@name most useful gets and sets */ + //@{ +public: + /// Initial value for alpha accuracy calculation (-1.0 off) + inline double alphaAccuracy() const + { + return alphaAccuracy_; + } + inline void setAlphaAccuracy(double value) + { + alphaAccuracy_ = value; + } + +public: + /// Objective value + //inline double objectiveValue() const { + //return (objectiveValue_-bestPossibleImprovement_)*optimizationDirection_ - dblParam_[ClpObjOffset]; + //} + /// Set disaster handler + inline void setDisasterHandler(ClpDisasterHandler *handler) + { + disasterArea_ = handler; + } + /// Get disaster handler + inline ClpDisasterHandler *disasterHandler() const + { + return disasterArea_; + } + /// Large bound value (for complementarity etc) + inline double largeValue() const + { + return largeValue_; + } + void setLargeValue(double value); + /// Largest error on Ax-b + inline double largestPrimalError() const + { + return largestPrimalError_; + } + /// Largest error on basic duals + inline double largestDualError() const + { + return largestDualError_; + } + /// Largest error on Ax-b + inline void setLargestPrimalError(double value) + { + largestPrimalError_ = value; + } + /// Largest error on basic duals + inline void setLargestDualError(double value) + { + largestDualError_ = value; + } + /// Get zero tolerance + inline double zeroTolerance() const + { + return zeroTolerance_; /*factorization_->zeroTolerance();*/ + } + /// Set zero tolerance + inline void setZeroTolerance(double value) + { + zeroTolerance_ = value; + } + /// Basic variables pivoting on which rows + inline int *pivotVariable() const + { + return pivotVariable_; + } + /// If automatic scaling on + inline bool automaticScaling() const + { + return automaticScale_ != 0; + } + inline void setAutomaticScaling(bool onOff) + { + automaticScale_ = onOff ? 1 : 0; + } + /// Current dual tolerance + inline double currentDualTolerance() const + { + return dualTolerance_; + } + inline void setCurrentDualTolerance(double value) + { + dualTolerance_ = value; + } + /// Current primal tolerance + inline double currentPrimalTolerance() const + { + return primalTolerance_; + } + inline void setCurrentPrimalTolerance(double value) + { + primalTolerance_ = value; + } + /// How many iterative refinements to do + inline int numberRefinements() const + { + return numberRefinements_; + } + void setNumberRefinements(int value); + /// Alpha (pivot element) for use by classes e.g. steepestedge + inline double alpha() const + { + return alpha_; + } + inline void setAlpha(double value) + { + alpha_ = value; + } + /// Reduced cost of last incoming for use by classes e.g. steepestedge + inline double dualIn() const + { + return dualIn_; + } + /// Set reduced cost of last incoming to force error + inline void setDualIn(double value) + { + dualIn_ = value; + } + /// Pivot Row for use by classes e.g. steepestedge + inline int pivotRow() const + { + return pivotRow_; + } + inline void setPivotRow(int value) + { + pivotRow_ = value; + } + /// value of incoming variable (in Dual) + double valueIncomingDual() const; + //@} + +#ifndef CLP_USER_DRIVEN +protected: +#endif + /**@name protected methods */ + //@{ + /** May change basis and then returns number changed. + Computation of solutions may be overriden by given pi and solution + */ + int gutsOfSolution(double *givenDuals, + const double *givenPrimals, + bool valuesPass = false); + /// Does most of deletion (0 = all, 1 = most, 2 most + factorization) + void gutsOfDelete(int type); + /// Does most of copying + void gutsOfCopy(const ClpSimplex &rhs); + /** puts in format I like (rowLower,rowUpper) also see StandardMatrix + 1 bit does rows (now and columns), (2 bit does column bounds), 4 bit does objective(s). + 8 bit does solution scaling in + 16 bit does rowArray and columnArray indexed vectors + and makes row copy if wanted, also sets columnStart_ etc + Also creates scaling arrays if needed. It does scaling if needed. + 16 also moves solutions etc in to work arrays + On 16 returns false if problem "bad" i.e. matrix or bounds bad + If startFinishOptions is -1 then called by user in getSolution + so do arrays but keep pivotVariable_ + */ + bool createRim(int what, bool makeRowCopy = false, int startFinishOptions = 0); + /// Does rows and columns + void createRim1(bool initial); + /// Does objective + void createRim4(bool initial); + /// Does rows and columns and objective + void createRim5(bool initial); + /** releases above arrays and does solution scaling out. May also + get rid of factorization data - + 0 get rid of nothing, 1 get rid of arrays, 2 also factorization + */ + void deleteRim(int getRidOfFactorizationData = 2); + /// Sanity check on input rim data (after scaling) - returns true if okay + bool sanityCheck(); + //@} +public: + /**@name public methods */ + //@{ + /** Return row or column sections - not as much needed as it + once was. These just map into single arrays */ + inline double *solutionRegion(int section) const + { + if (!section) + return rowActivityWork_; + else + return columnActivityWork_; + } + inline double *djRegion(int section) const + { + if (!section) + return rowReducedCost_; + else + return reducedCostWork_; + } + inline double *lowerRegion(int section) const + { + if (!section) + return rowLowerWork_; + else + return columnLowerWork_; + } + inline double *upperRegion(int section) const + { + if (!section) + return rowUpperWork_; + else + return columnUpperWork_; + } + inline double *costRegion(int section) const + { + if (!section) + return rowObjectiveWork_; + else + return objectiveWork_; + } + /// Return region as single array + inline double *solutionRegion() const + { + return solution_; + } + inline double *djRegion() const + { + return dj_; + } + inline double *lowerRegion() const + { + return lower_; + } + inline double *upperRegion() const + { + return upper_; + } + inline double *costRegion() const + { + return cost_; + } + inline Status getStatus(int sequence) const + { + return static_cast< Status >(status_[sequence] & 7); + } + inline void setStatus(int sequence, Status newstatus) + { + unsigned char &st_byte = status_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | newstatus); + } + /// Start or reset using maximumRows_ and Columns_ - true if change + bool startPermanentArrays(); + /** Normally the first factorization does sparse coding because + the factorization could be singular. This allows initial dense + factorization when it is known to be safe + */ + void setInitialDenseFactorization(bool onOff); + bool initialDenseFactorization() const; + /** Return sequence In or Out */ + inline int sequenceIn() const + { + return sequenceIn_; + } + inline int sequenceOut() const + { + return sequenceOut_; + } + /** Set sequenceIn or Out */ + inline void setSequenceIn(int sequence) + { + sequenceIn_ = sequence; + } + inline void setSequenceOut(int sequence) + { + sequenceOut_ = sequence; + } + /** Return direction In or Out */ + inline int directionIn() const + { + return directionIn_; + } + inline int directionOut() const + { + return directionOut_; + } + /** Set directionIn or Out */ + inline void setDirectionIn(int direction) + { + directionIn_ = direction; + } + inline void setDirectionOut(int direction) + { + directionOut_ = direction; + } + /// Value of Out variable + inline double valueOut() const + { + return valueOut_; + } + /// Lower of out variable + inline double lowerOut() const + { + return lowerOut_; + } + /// Upper of out variable + inline double upperOut() const + { + return upperOut_; + } + /// Set value of out variable + inline void setValueOut(double value) + { + valueOut_ = value; + } + /// Dual value of Out variable + inline double dualOut() const + { + return dualOut_; + } + /// Set dual value of out variable + inline void setDualOut(double value) + { + dualOut_ = value; + } + /// Set lower of out variable + inline void setLowerOut(double value) + { + lowerOut_ = value; + } + /// Set upper of out variable + inline void setUpperOut(double value) + { + upperOut_ = value; + } + /// Set theta of out variable + inline void setTheta(double value) + { + theta_ = value; + } + /// Returns 1 if sequence indicates column + inline int isColumn(int sequence) const + { + return sequence < numberColumns_ ? 1 : 0; + } + /// Returns sequence number within section + inline int sequenceWithin(int sequence) const + { + return sequence < numberColumns_ ? sequence : sequence - numberColumns_; + } + /// Return row or column values + inline double solution(int sequence) + { + return solution_[sequence]; + } + /// Return address of row or column values + inline double &solutionAddress(int sequence) + { + return solution_[sequence]; + } + inline double reducedCost(int sequence) + { + return dj_[sequence]; + } + inline double &reducedCostAddress(int sequence) + { + return dj_[sequence]; + } + inline double lower(int sequence) + { + return lower_[sequence]; + } + /// Return address of row or column lower bound + inline double &lowerAddress(int sequence) + { + return lower_[sequence]; + } + inline double upper(int sequence) + { + return upper_[sequence]; + } + /// Return address of row or column upper bound + inline double &upperAddress(int sequence) + { + return upper_[sequence]; + } + inline double cost(int sequence) + { + return cost_[sequence]; + } + /// Return address of row or column cost + inline double &costAddress(int sequence) + { + return cost_[sequence]; + } + /// Return original lower bound + inline double originalLower(int iSequence) const + { + if (iSequence < numberColumns_) + return columnLower_[iSequence]; + else + return rowLower_[iSequence - numberColumns_]; + } + /// Return original lower bound + inline double originalUpper(int iSequence) const + { + if (iSequence < numberColumns_) + return columnUpper_[iSequence]; + else + return rowUpper_[iSequence - numberColumns_]; + } + /// Theta (pivot change) + inline double theta() const + { + return theta_; + } + /// Lower Bound on In variable + inline double lowerIn() const + { + return lowerIn_; + } + /// Value of In variable + inline double valueIn() const + { + return valueIn_; + } + /// Upper Bound on In variable + inline double upperIn() const + { + return upperIn_; + } + /** Best possible improvement using djs (primal) or + obj change by flipping bounds to make dual feasible (dual) */ + inline double bestPossibleImprovement() const + { + return bestPossibleImprovement_; + } + /// Return pointer to details of costs + inline ClpNonLinearCost *nonLinearCost() const + { + return nonLinearCost_; + } + /// Set pointer to details of costs + void setNonLinearCost(ClpNonLinearCost &nonLinearCost); + /** Return more special options + 1 bit - if presolve says infeasible in ClpSolve return + 2 bit - if presolved problem infeasible return + 4 bit - keep arrays like upper_ around + 8 bit - no free or superBasic variables + 16 bit - if checking replaceColumn accuracy before updating + 32 bit - say optimal if primal feasible! + 64 bit - give up easily in dual (and say infeasible) + 128 bit - no objective, 0-1 and in B&B + 256 bit - in primal from dual or vice versa + 512 bit - alternative use of solveType_ + 1024 bit - don't do row copy of factorization + 2048 bit - perturb in complete fathoming + 4096 bit - try more for complete fathoming + 8192 bit - don't even think of using primal if user asks for dual (and vv) + 16384 bit - in initialSolve so be more flexible + 32768 bit - don't swap algorithms from dual if small infeasibility + 65536 bit - perturb in postsolve cleanup (even if < 10000 rows) + 131072 bit (*3) initial stateDualColumn + 524288 bit - stop when primal feasible + 1048576 bit - stop when primal feasible after n-1000000 iterations + 2097152 bit - no primal in fastDual2 if feasible + 4194304 bit - tolerances have been changed by code + 8388608 bit - tolerances are dynamic (at first) + 16777216 bit - if factorization kept can still declare optimal at once + */ + inline int moreSpecialOptions() const + { + return moreSpecialOptions_; + } + /// Get vector mode + inline int vectorMode() const + { + return vectorMode_; + } + /** Set more special options + 1 bit - if presolve says infeasible in ClpSolve return + 2 bit - if presolved problem infeasible return + 4 bit - keep arrays like upper_ around + 8 bit - no free or superBasic variables + 16 bit - if checking replaceColumn accuracy before updating + 32 bit - say optimal if primal feasible! + 64 bit - give up easily in dual (and say infeasible) + 128 bit - no objective, 0-1 and in B&B + 256 bit - in primal from dual or vice versa + 512 bit - alternative use of solveType_ + 1024 bit - don't do row copy of factorization + 2048 bit - perturb in complete fathoming + 4096 bit - try more for complete fathoming + 8192 bit - don't even think of using primal if user asks for dual (and vv) + 16384 bit - in initialSolve so be more flexible + 32768 bit - don't swap algorithms from dual if small infeasibility + 65536 bit - perturb in postsolve cleanup (even if < 10000 rows) + 131072 bit (*3) initial stateDualColumn + 524288 bit - stop when primal feasible + 1048576 bit - don't perturb even if long time + 2097152 bit - no primal in fastDual2 if feasible + 4194304 bit - tolerances have been changed by code + 8388608 bit - tolerances are dynamic (at first) + 16777216 bit - if factorization kept can still declare optimal at once + */ + inline void setMoreSpecialOptions(int value) + { + moreSpecialOptions_ = value; + } + /// Set vector mode + inline void setVectorMode(int value) + { + vectorMode_ = value; + } + //@} + /**@name status methods */ + //@{ + inline void setFakeBound(int sequence, FakeBound fakeBound) + { + unsigned char &st_byte = status_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~24); + st_byte = static_cast< unsigned char >(st_byte | (fakeBound << 3)); + } + inline FakeBound getFakeBound(int sequence) const + { + return static_cast< FakeBound >((status_[sequence] >> 3) & 3); + } + inline void setRowStatus(int sequence, Status newstatus) + { + unsigned char &st_byte = status_[sequence + numberColumns_]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | newstatus); + } + inline Status getRowStatus(int sequence) const + { + return static_cast< Status >(status_[sequence + numberColumns_] & 7); + } + inline void setColumnStatus(int sequence, Status newstatus) + { + unsigned char &st_byte = status_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & ~7); + st_byte = static_cast< unsigned char >(st_byte | newstatus); + } + inline Status getColumnStatus(int sequence) const + { + return static_cast< Status >(status_[sequence] & 7); + } + inline void setPivoted(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] | 32); + } + inline void clearPivoted(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~32); + } + inline bool pivoted(int sequence) const + { + return (((status_[sequence] >> 5) & 1) != 0); + } + /// To flag a variable (not inline to allow for column generation) + void setFlagged(int sequence); + inline void clearFlagged(int sequence) + { + status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~64); + } + inline bool flagged(int sequence) const + { + return ((status_[sequence] & 64) != 0); + } + /// To say row active in primal pivot row choice + inline void setActive(int iRow) + { + status_[iRow] = static_cast< unsigned char >(status_[iRow] | 128); + } + inline void clearActive(int iRow) + { + status_[iRow] = static_cast< unsigned char >(status_[iRow] & ~128); + } + inline bool active(int iRow) const + { + return ((status_[iRow] & 128) != 0); + } + /// To say perturbed + inline void setPerturbed(int iSequence) + { + status_[iSequence] = static_cast< unsigned char >(status_[iSequence] | 128); + } + inline void clearPerturbed(int iSequence) + { + status_[iSequence] = static_cast< unsigned char >(status_[iSequence] & ~128); + } + inline bool perturbed(int iSequence) const + { + return ((status_[iSequence] & 128) != 0); + } + /** Set up status array (can be used by OsiClp). + Also can be used to set up all slack basis */ + void createStatus(); + /** Sets up all slack basis and resets solution to + as it was after initial load or readMps */ + void allSlackBasis(bool resetSolution = false); + + /// So we know when to be cautious + inline int lastBadIteration() const + { + return lastBadIteration_; + } + /// Set so we know when to be cautious + inline void setLastBadIteration(int value) + { + lastBadIteration_ = value; + } + /// Progress flag - at present 0 bit says artificials out + inline int progressFlag() const + { + return (progressFlag_ & 3); + } + /// For dealing with all issues of cycling etc + inline ClpSimplexProgress *progress() + { + return &progress_; + } + /// Force re-factorization early value + inline int forceFactorization() const + { + return forceFactorization_; + } + /// Force re-factorization early + inline void forceFactorization(int value) + { + forceFactorization_ = value; + } + /// Raw objective value (so always minimize in primal) + inline double rawObjectiveValue() const + { + return objectiveValue_; + } + /// Compute objective value from solution and put in objectiveValue_ + void computeObjectiveValue(bool useWorkingSolution = false); + /// Compute minimization objective value from internal solution without perturbation + double computeInternalObjectiveValue(); + /** Infeasibility/unbounded ray (NULL returned if none/wrong) + Up to user to use delete [] on these arrays. */ + double *infeasibilityRay(bool fullRay = false) const; + /** Number of extra rows. These are ones which will be dynamically created + each iteration. This is for GUB but may have other uses. + */ + inline int numberExtraRows() const + { + return numberExtraRows_; + } + /** Maximum number of basic variables - can be more than number of rows if GUB + */ + inline int maximumBasic() const + { + return maximumBasic_; + } + /// Iteration when we entered dual or primal + inline int baseIteration() const + { + return baseIteration_; + } + /// Create C++ lines to get to current state + void generateCpp(FILE *fp, bool defaultFactor = false); + /// Gets clean and emptyish factorization + ClpFactorization *getEmptyFactorization(); + /// May delete or may make clean and emptyish factorization + void setEmptyFactorization(); + /// Move status and solution across + void moveInfo(const ClpSimplex &rhs, bool justStatus = false); + //@} + + ///@name Basis handling + // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal) + // *** At present only without scaling + // *** Slacks havve -1.0 element (so == row activity) - take care + ///Get a row of the tableau (slack part in slack if not NULL) + void getBInvARow(int row, double *z, double *slack = NULL); + + ///Get a row of the basis inverse + void getBInvRow(int row, double *z); + + ///Get a column of the tableau + void getBInvACol(int col, double *vec); + + ///Get a column of the basis inverse + void getBInvCol(int col, double *vec); + + /** Get basic indices (order of indices corresponds to the + order of elements in a vector retured by getBInvACol() and + getBInvCol()). + */ + void getBasics(int *index); + + //@} + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + void setObjectiveCoefficient(int elementIndex, double elementValue); + /** Set an objective function coefficient */ + inline void setObjCoeff(int elementIndex, double elementValue) + { + setObjectiveCoefficient(elementIndex, elementValue); + } + + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + void setColumnLower(int elementIndex, double elementValue); + + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + void setColumnUpper(int elementIndex, double elementValue); + + /** Set a single column lower and upper bound */ + void setColumnBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of columns simultaneously
+ The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + void setColumnSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + inline void setColLower(int elementIndex, double elementValue) + { + setColumnLower(elementIndex, elementValue); + } + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + inline void setColUpper(int elementIndex, double elementValue) + { + setColumnUpper(elementIndex, elementValue); + } + + /** Set a single column lower and upper bound */ + inline void setColBounds(int elementIndex, + double newlower, double newupper) + { + setColumnBounds(elementIndex, newlower, newupper); + } + + /** Set the bounds on a number of columns simultaneously
+ @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + inline void setColSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList) + { + setColumnSetBounds(indexFirst, indexLast, boundList); + } + + /** Set a single row lower bound
+ Use -DBL_MAX for -infinity. */ + void setRowLower(int elementIndex, double elementValue); + + /** Set a single row upper bound
+ Use DBL_MAX for infinity. */ + void setRowUpper(int elementIndex, double elementValue); + + /** Set a single row lower and upper bound */ + void setRowBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of rows simultaneously
+ @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + either bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + void setRowSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + /// Resizes rim part of model + void resize(int newNumberRows, int newNumberColumns); + + //@} + + ////////////////// data ////////////////// +protected: + /**@name data. Many arrays have a row part and a column part. + There is a single array with both - columns then rows and + then normally two arrays pointing to rows and columns. The + single array is the owner of memory + */ + //@{ + /** Best possible improvement using djs (primal) or + obj change by flipping bounds to make dual feasible (dual) */ + double bestPossibleImprovement_; + /// Zero tolerance + double zeroTolerance_; + /// Sequence of worst (-1 if feasible) + int columnPrimalSequence_; + /// Sequence of worst (-1 if feasible) + int rowPrimalSequence_; + /// "Best" objective value + double bestObjectiveValue_; + /// More special options - see set for details + int moreSpecialOptions_; + /// Iteration when we entered dual or primal + int baseIteration_; + /// Vector mode - try and use vector instructions + int vectorMode_; + /// Primal tolerance needed to make dual feasible (0 == Primal, <0 == Dual + int algorithm_; + /** Now for some reliability aids + This forces re-factorization early */ + int forceFactorization_; + /** Perturbation: + -50 to +50 - perturb by this power of ten (-6 sounds good) + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + */ + int perturbation_; + /// Saved status regions + unsigned char *saveStatus_; + /** Very wasteful way of dealing with infeasibilities in primal. + However it will allow non-linearities and use of dual + analysis. If it doesn't work it can easily be replaced. + */ + ClpNonLinearCost *nonLinearCost_; + /// So we know when to be cautious + int lastBadIteration_; + /// So we know when to open up again + int lastFlaggedIteration_; + /// Can be used for count of fake bounds (dual) or fake costs (primal) + int numberFake_; + /// Can be used for count of changed costs (dual) or changed bounds (primal) + int numberChanged_; + /// Progress flag - at present 0 bit says artificials out, 1 free in + int progressFlag_; + /// First free/super-basic variable (-1 if none) + int firstFree_; + /** Number of extra rows. These are ones which will be dynamically created + each iteration. This is for GUB but may have other uses. + */ + int numberExtraRows_; + /** Maximum number of basic variables - can be more than number of rows if GUB + */ + int maximumBasic_; + /// If may skip final factorize then allow up to this pivots (default 20) + int dontFactorizePivots_; + /** For advanced use. When doing iterative solves things can get + nasty so on values pass if incoming solution has largest + infeasibility < incomingInfeasibility throw out variables + from basis until largest infeasibility < allowedInfeasibility. + if allowedInfeasibility>= incomingInfeasibility this is + always possible altough you may end up with an all slack basis. + + Defaults are 1.0,10.0 + */ + double incomingInfeasibility_; + double allowedInfeasibility_; + /// Automatic scaling of objective and rhs and bounds + int automaticScale_; + /// Maximum perturbation array size (take out when code rewritten) + int maximumPerturbationSize_; + /// Perturbation array (maximumPerturbationSize_) + double *perturbationArray_; + /// A copy of model with certain state - normally without cuts + ClpSimplex *baseModel_; + /// For dealing with all issues of cycling etc + ClpSimplexProgress progress_; +#ifdef ABC_INHERIT + AbcSimplex *abcSimplex_; + int abcState_; +#define CLP_ABC_WANTED 1 +#define CLP_ABC_WANTED_PARALLEL 2 +#define CLP_ABC_FULL_DONE 8 + // bits 256,512,1024 for crash +#endif +#define CLP_ABC_BEEN_FEASIBLE 65536 + /// Number of degenerate pivots since last perturbed + int numberDegeneratePivots_; + +public: + /// Spare int array for passing information [0]!=0 switches on + mutable int spareIntArray_[4]; + /// Spare double array for passing information [0]!=0 switches on + mutable double spareDoubleArray_[4]; + +protected: + /// Allow OsiClp certain perks + friend class OsiClpSolverInterface; + /// And OsiCLP + friend class OsiCLPSolverInterface; + //@} +}; +//############################################################################# +/** A function that tests the methods in the ClpSimplex class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. + + It also does some testing of ClpFactorization class + */ +void ClpSimplexUnitTest(const std::string &mpsDir); + +// For Devex stuff +#define DEVEX_TRY_NORM 1.0e-4 +#define DEVEX_ADD_ONE 1.0 +#if defined(ABC_INHERIT) || defined(THREADS_IN_ANALYZE) +// Use pthreads +#include +typedef struct { + double result; + //const CoinIndexedVector * constVector; // can get rid of + //CoinIndexedVector * vectors[2]; // can get rid of + void *extraInfo; + void *extraInfo2; + int status; + int stuff[4]; +} CoinThreadInfo; +class CoinPthreadStuff { +public: + /**@name Constructors and destructor and copy */ + //@{ + /** Main constructor + */ + CoinPthreadStuff(int numberThreads = 0, + void *parallelManager(void *stuff) = NULL); + /// Assignment operator. This copies the data + CoinPthreadStuff &operator=(const CoinPthreadStuff &rhs); + /// Destructor + ~CoinPthreadStuff(); + /// set stop start + inline void setStopStart(int value) + { + stopStart_ = value; + } +#ifndef NUMBER_THREADS +#define NUMBER_THREADS 8 +#endif + // For waking up thread + inline pthread_mutex_t *mutexPointer(int which, int thread = 0) + { + return mutex_ + which + 3 * thread; + } +#ifdef PTHREAD_BARRIER_SERIAL_THREAD + inline pthread_barrier_t *barrierPointer() + { + return &barrier_; + } +#endif + inline int whichLocked(int thread = 0) const + { + return locked_[thread]; + } + inline CoinThreadInfo *threadInfoPointer(int thread = 0) + { + return threadInfo_ + thread; + } + void startParallelTask(int type, int iThread, void *info = NULL); + int waitParallelTask(int type, int &iThread, bool allowIdle); + void waitAllTasks(); + /// so thread can find out which one it is + int whichThread() const; + void sayIdle(int iThread); + //void startThreads(int numberThreads); + //void stopThreads(); + // For waking up thread + pthread_mutex_t mutex_[3 * (NUMBER_THREADS + 1)]; +#ifdef PTHREAD_BARRIER_SERIAL_THREAD + pthread_barrier_t barrier_; +#endif + CoinThreadInfo threadInfo_[NUMBER_THREADS + 1]; + pthread_t abcThread_[NUMBER_THREADS + 1]; + int locked_[NUMBER_THREADS + 1]; + int stopStart_; + int numberThreads_; +}; +void *clp_parallelManager(void *stuff); +#endif +typedef struct { + double upperTheta; + double bestPossible; + double acceptablePivot; + double tolerance; + double dualTolerance; + double theta; + double primalRatio; + double changeObj; + const double *COIN_RESTRICT cost; + double *COIN_RESTRICT solution; + double *COIN_RESTRICT reducedCost; + const double *COIN_RESTRICT lower; + const double *COIN_RESTRICT upper; + double *COIN_RESTRICT work; + int *COIN_RESTRICT index; + double *COIN_RESTRICT spare; + const unsigned char *COIN_RESTRICT status; + int *COIN_RESTRICT which; + double *COIN_RESTRICT infeas; + const int *COIN_RESTRICT pivotVariable; + const double *COIN_RESTRICT element; + const CoinBigIndex *COIN_RESTRICT start; + const int *COIN_RESTRICT row; + int numberAdded; + int numberInfeasibilities; + int numberRemaining; + int startColumn; + int numberToDo; + int numberColumns; +} clpTempInfo; +#ifndef ABC_INHERIT +#if ABOCA_LITE +void moveAndZero(clpTempInfo *info, int type, void *extra); +// 2 is owner of abcState_ +#ifdef ABCSTATE_LITE +#if ABCSTATE_LITE == 2 +int abcState_ = 0; +#else +extern int abcState_; +#endif +inline int abcState() +{ + return abcState_; +} +inline void setAbcState(int state) +{ + abcState_ = state; +} +#endif +#else +#define abcState 0 +#endif +#endif +#ifdef CLP_USER_DRIVEN +// expand as needed +typedef struct { + double alpha; + double totalThru; + double rhs; + double value; + double lower; + double upper; + double cost; + int type; + int row; + int sequence; + int printing; + int change; +} clpUserStruct; +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexDual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexDual.hpp new file mode 100644 index 000000000..8c18c86e4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexDual.hpp @@ -0,0 +1,304 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexDual_H +#define ClpSimplexDual_H + +#include "ClpSimplex.hpp" + +/** This solves LPs using the dual simplex method + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexDual : public ClpSimplex { + +public: + /**@name Description of algorithm */ + //@{ + /** Dual algorithm + + Method + + It tries to be a single phase approach with a weight of 1.0 being + given to getting optimal and a weight of updatedDualBound_ being + given to getting dual feasible. In this version I have used the + idea that this weight can be thought of as a fake bound. If the + distance between the lower and upper bounds on a variable is less + than the feasibility weight then we are always better off flipping + to other bound to make dual feasible. If the distance is greater + then we make up a fake bound updatedDualBound_ away from one bound. + If we end up optimal or primal infeasible, we check to see if + bounds okay. If so we have finished, if not we increase updatedDualBound_ + and continue (after checking if unbounded). I am undecided about + free variables - there is coding but I am not sure about it. At + present I put them in basis anyway. + + The code is designed to take advantage of sparsity so arrays are + seldom zeroed out from scratch or gone over in their entirety. + The only exception is a full scan to find outgoing variable for + Dantzig row choice. For steepest edge we keep an updated list + of infeasibilities (actually squares). + On easy problems we don't need full scan - just + pick first reasonable. + + One problem is how to tackle degeneracy and accuracy. At present + I am using the modification of costs which I put in OSL and some + of what I think is the dual analog of Gill et al. + I am still not sure of the exact details. + + The flow of dual is three while loops as follows: + + while (not finished) { + + while (not clean solution) { + + Factorize and/or clean up solution by flipping variables so + dual feasible. If looks finished check fake dual bounds. + Repeat until status is iterating (-1) or finished (0,1,2) + + } + + while (status==-1) { + + Iterate until no pivot in or out or time to re-factorize. + + Flow is: + + choose pivot row (outgoing variable). if none then + we are primal feasible so looks as if done but we need to + break and check bounds etc. + + Get pivot row in tableau + + Choose incoming column. If we don't find one then we look + primal infeasible so break and check bounds etc. (Also the + pivot tolerance is larger after any iterations so that may be + reason) + + If we do find incoming column, we may have to adjust costs to + keep going forwards (anti-degeneracy). Check pivot will be stable + and if unstable throw away iteration and break to re-factorize. + If minor error re-factorize after iteration. + + Update everything (this may involve flipping variables to stay + dual feasible. + + } + + } + + TODO's (or maybe not) + + At present we never check we are going forwards. I overdid that in + OSL so will try and make a last resort. + + Needs partial scan pivot out option. + + May need other anti-degeneracy measures, especially if we try and use + loose tolerances as a way to solve in fewer iterations. + + I like idea of dynamic scaling. This gives opportunity to decouple + different implications of scaling for accuracy, iteration count and + feasibility tolerance. + + for use of exotic parameter startFinishoptions see Clpsimplex.hpp + */ + + int dual(int ifValuesPass, int startFinishOptions = 0); + /** For strong branching. On input lower and upper are new bounds + while on output they are change in objective function values + (>1.0e50 infeasible). + Return code is 0 if nothing interesting, -1 if infeasible both + ways and +1 if infeasible one way (check values to see which one(s)) + Solutions are filled in as well - even down, odd up - also + status and number of iterations + */ + int strongBranching(int numberVariables, const int *variables, + double *newLower, double *newUpper, + double **outputSolution, + int *outputStatus, int *outputIterations, + bool stopOnFirstInfeasible = true, + bool alwaysFinish = false, + int startFinishOptions = 0); + /// This does first part of StrongBranching + ClpFactorization *setupForStrongBranching(char *arrays, int numberRows, + int numberColumns, bool solveLp = false); + /// This cleans up after strong branching + void cleanupAfterStrongBranching(ClpFactorization *factorization); + //@} + + /**@name Functions used in dual */ + //@{ + /** This has the flow between re-factorizations + Broken out for clarity and will be used by strong branching + + Reasons to come out: + -1 iterations etc + -2 inaccuracy + -3 slight inaccuracy (and done iterations) + +0 looks optimal (might be unbounded - but we will investigate) + +1 looks infeasible + +3 max iterations + + If givenPi not NULL then in values pass + */ + int whileIterating(double *&givenPi, int ifValuesPass); + /** The duals are updated by the given arrays. + Returns number of infeasibilities. + After rowArray and columnArray will just have those which + have been flipped. + Variables may be flipped between bounds to stay dual feasible. + The output vector has movement of primal + solution (row length array) */ + int updateDualsInDual(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + CoinIndexedVector *outputArray, + double theta, + double &objectiveChange, + bool fullRecompute); + /** The duals are updated by the given arrays. + This is in values pass - so no changes to primal is made + */ + void updateDualsInValuesPass(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + double theta); + /** While updateDualsInDual sees what effect is of flip + this does actual flipping. + */ + void flipBounds(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray); + /** + Row array has row part of pivot row + Column array has column part. + This chooses pivot column. + Spare arrays are used to save pivots which will go infeasible + We will check for basic so spare array will never overflow. + If necessary will modify costs + For speed, we may need to go to a bucket approach when many + variables are being flipped. + Returns best possible pivot value + */ + double dualColumn(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + CoinIndexedVector *spareArray, + CoinIndexedVector *spareArray2, + double accpetablePivot, + CoinBigIndex *dubiousWeights); + /// Does first bit of dualColumn + int dualColumn0(const CoinIndexedVector *rowArray, + const CoinIndexedVector *columnArray, + CoinIndexedVector *spareArray, + double acceptablePivot, + double &upperReturn, double &badFree); + /** + Row array has row part of pivot row + Column array has column part. + This sees what is best thing to do in dual values pass + if sequenceIn==sequenceOut can change dual on chosen row and leave variable in basis + */ + void checkPossibleValuesMove(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + double acceptablePivot); + /** + Row array has row part of pivot row + Column array has column part. + This sees what is best thing to do in branch and bound cleanup + If sequenceIn_ < 0 then can't do anything + */ + void checkPossibleCleanup(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + double acceptablePivot); + /** + This sees if we can move duals in dual values pass. + This is done before any pivoting + */ + void doEasyOnesInValuesPass(double *givenReducedCosts); + /** + Chooses dual pivot row + Would be faster with separate region to scan + and will have this (with square of infeasibility) when steepest + For easy problems we can just choose one of the first rows we look at + + If alreadyChosen >=0 then in values pass and that row has been + selected + */ + void dualRow(int alreadyChosen); + /** Checks if any fake bounds active - if so returns number and modifies + updatedDualBound_ and everything. + Free variables will be left as free + Returns number of bounds changed if >=0 + Returns -1 if not initialize and no effect + Fills in changeVector which can be used to see if unbounded + and cost of change vector + If 2 sets to original (just changed) + */ + int changeBounds(int initialize, CoinIndexedVector *outputArray, + double &changeCost); + /// Just checks if any fake bounds active - if so returns number + int checkFakeBounds() const; + /** As changeBounds but just changes new bounds for a single variable. + Returns true if change */ + bool changeBound(int iSequence); + /// Restores bound to original bound + void originalBound(int iSequence); + /** Checks if tentative optimal actually means unbounded in dual + Returns -3 if not, 2 if is unbounded */ + int checkUnbounded(CoinIndexedVector *ray, CoinIndexedVector *spare, + double changeCost); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInDual(int &lastCleaned, int type, + double *givenDjs, ClpDataSave &saveData, + int ifValuesPass); + /** Perturbs problem (method depends on perturbation()) + returns nonzero if should go to dual */ + int perturb(); + /** Fast iterations. Misses out a lot of initialization. + Normally stops on maximum iterations, first re-factorization + or tentative optimum. If looks interesting then continues as + normal. Returns 0 if finished properly, 1 otherwise. + */ + int fastDual(bool alwaysFinish = false); + /** Checks number of variables at fake bounds. This is used by fastDual + so can exit gracefully before end */ + int numberAtFakeBound(); + + /** Pivot in a variable and choose an outgoing one. Assumes dual + feasible - will not go through a reduced cost. Returns step length in theta + Return codes as before but -1 means no acceptable pivot + */ + int pivotResultPart1(); + /** Get next free , -1 if none */ + int nextSuperBasic(); + /** Startup part of dual (may be extended to other algorithms) + returns 0 if good, 1 if bad */ + int startupSolve(int ifValuesPass, double *saveDuals, int startFinishOptions); + void finishSolve(int startFinishOptions); + void gutsOfDual(int ifValuesPass, double *&saveDuals, int initialStatus, + ClpDataSave &saveData); + //int dual2(int ifValuesPass,int startFinishOptions=0); + void resetFakeBounds(int type); + + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexNonlinear.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexNonlinear.hpp new file mode 100644 index 000000000..4b5096b60 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexNonlinear.hpp @@ -0,0 +1,117 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexNonlinear_H +#define ClpSimplexNonlinear_H + +class ClpNonlinearInfo; +class ClpQuadraticObjective; +class ClpConstraint; + +#include "ClpSimplexPrimal.hpp" + +/** This solves non-linear LPs using the primal simplex method + + It inherits from ClpSimplexPrimal. It has no data of its own and + is never created - only cast from a ClpSimplexPrimal object at algorithm time. + If needed create new class and pass around + +*/ + +class ClpSimplexNonlinear : public ClpSimplexPrimal { + +public: + /**@name Description of algorithm */ + //@{ + /** Primal algorithms for reduced gradient + At present we have two algorithms: + + */ + /// A reduced gradient method. + int primal(); + /** Primal algorithm for quadratic + Using a semi-trust region approach as for pooling problem + This is in because I have it lying around + */ + int primalSLP(int numberPasses, double deltaTolerance, + int otherOptions = 0); + /// May use a cut approach for solving any LP + int primalDualCuts(char *rowsIn, int startUp, int algorithm); + /** Primal algorithm for nonlinear constraints + Using a semi-trust region approach as for pooling problem + This is in because I have it lying around + + */ + int primalSLP(int numberConstraints, ClpConstraint **constraints, + int numberPasses, double deltaTolerance); + + /** Creates direction vector. note longArray is long enough + for rows and columns. If numberNonBasic 0 then is updated + otherwise mode is ignored and those are used. + Norms are only for those > 1.0e3*dualTolerance + If mode is nonzero then just largest dj */ + void directionVector(CoinIndexedVector *longArray, + CoinIndexedVector *spare1, CoinIndexedVector *spare2, + int mode, + double &normFlagged, double &normUnflagged, + int &numberNonBasic); + /// Main part. + int whileIterating(int &pivotMode); + /** + longArray has direction + pivotMode - + 0 - use all dual infeasible variables + 1 - largest dj + while >= 10 trying startup phase + Returns 0 - can do normal iteration (basis change) + 1 - no basis change + 2 - if wants singleton + 3 - if time to re-factorize + If sequenceIn_ >=0 then that will be incoming variable + */ + int pivotColumn(CoinIndexedVector *longArray, + CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + CoinIndexedVector *spare, + int &pivotMode, + double &solutionError, + double *array1); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInPrimal(int &lastCleaned, int type, + ClpSimplexProgress *progress, + bool doFactorization, + double &bestObjectiveWhenFlagged); + /** Do last half of an iteration. + Return codes + Reasons to come out normal mode + -1 normal + -2 factorize now - good iteration + -3 slight inaccuracy - refactorize - iteration done + -4 inaccuracy - refactorize - no iteration + -5 something flagged - go round again + +2 looks unbounded + +3 max iterations (iteration done) + + */ + int pivotNonlinearResult(); + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexOther.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexOther.hpp new file mode 100644 index 000000000..36d01104b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexOther.hpp @@ -0,0 +1,282 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexOther_H +#define ClpSimplexOther_H + +#include "ClpSimplex.hpp" + +/** This is for Simplex stuff which is neither dual nor primal + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexOther : public ClpSimplex { + +public: + /**@name Methods */ + //@{ + /** Dual ranging. + This computes increase/decrease in cost for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + For non-basic variables the information is trivial to compute and the change in cost is just minus the + reduced cost and the sequence number will be that of the non-basic variables. + For basic variables a ratio test is between the reduced costs for non-basic variables + and the row of the tableau corresponding to the basic variable. + The increase/decrease value is always >= 0.0 + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + If valueIncrease/Decrease not NULL (both must be NULL or both non NULL) then these are filled with + the value of variable if such a change in cost were made (the existing bounds are ignored) + + When here - guaranteed optimal + */ + void dualRanging(int numberCheck, const int *which, + double *costIncrease, int *sequenceIncrease, + double *costDecrease, int *sequenceDecrease, + double *valueIncrease = NULL, double *valueDecrease = NULL); + /** Primal ranging. + This computes increase/decrease in value for each given variable and corresponding + sequence numbers which would change basis. Sequence numbers are 0..numberColumns + and numberColumns.. for artificials/slacks. + This should only be used for non-basic variabls as otherwise information is pretty useless + For basic variables the sequence number will be that of the basic variables. + + Up to user to provide correct length arrays where each array is of length numberCheck. + which contains list of variables for which information is desired. All other + arrays will be filled in by function. If fifth entry in which is variable 7 then fifth entry in output arrays + will be information for variable 7. + + When here - guaranteed optimal + */ + void primalRanging(int numberCheck, const int *which, + double *valueIncrease, int *sequenceIncrease, + double *valueDecrease, int *sequenceDecrease); + /** Parametrics + This is an initial slow version. + The code uses current bounds + theta * change (if change array not NULL) + and similarly for objective. + It starts at startingTheta and returns ending theta in endingTheta. + If reportIncrement 0.0 it will report on any movement + If reportIncrement >0.0 it will report at startingTheta+k*reportIncrement. + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, if error on ranges -1, otherwise 0. + Normal report is just theta and objective but + if event handler exists it may do more + On exit endingTheta is maximum reached (can be used for next startingTheta) + */ + int parametrics(double startingTheta, double &endingTheta, double reportIncrement, + const double *changeLowerBound, const double *changeUpperBound, + const double *changeLowerRhs, const double *changeUpperRhs, + const double *changeObjective); + /** Version of parametrics which reads from file + See CbcClpParam.cpp for details of format + Returns -2 if unable to open file */ + int parametrics(const char *dataFile); + /** Parametrics + This is an initial slow version. + The code uses current bounds + theta * change (if change array not NULL) + It starts at startingTheta and returns ending theta in endingTheta. + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, if error on ranges -1, otherwise 0. + Event handler may do more + On exit endingTheta is maximum reached (can be used for next startingTheta) + */ + int parametrics(double startingTheta, double &endingTheta, + const double *changeLowerBound, const double *changeUpperBound, + const double *changeLowerRhs, const double *changeUpperRhs); + int parametricsObj(double startingTheta, double &endingTheta, + const double *changeObjective); + /// Finds best possible pivot + double bestPivot(bool justColumns = false); + typedef struct { + double startingTheta; + double endingTheta; + double maxTheta; + double acceptableMaxTheta; // if this far then within tolerances + double *lowerChange; // full array of lower bound changes + int *lowerList; // list of lower bound changes + double *upperChange; // full array of upper bound changes + int *upperList; // list of upper bound changes + char *markDone; // mark which ones looked at + int *backwardBasic; // from sequence to pivot row + int *lowerActive; + double *lowerGap; + double *lowerCoefficient; + int *upperActive; + double *upperGap; + double *upperCoefficient; + int unscaledChangesOffset; + bool firstIteration; // so can update rhs for accuracy + } parametricsData; + +private: + /** Parametrics - inner loop + This first attempt is when reportIncrement non zero and may + not report endingTheta correctly + If it can not reach input endingTheta return code will be 1 for infeasible, + 2 for unbounded, otherwise 0. + Normal report is just theta and objective but + if event handler exists it may do more + */ + int parametricsLoop(parametricsData ¶mData, double reportIncrement, + const double *changeLower, const double *changeUpper, + const double *changeObjective, ClpDataSave &data, + bool canTryQuick); + int parametricsLoop(parametricsData ¶mData, + ClpDataSave &data, bool canSkipFactorization = false); + int parametricsObjLoop(parametricsData ¶mData, + ClpDataSave &data, bool canSkipFactorization = false); + /** Refactorizes if necessary + Checks if finished. Updates status. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + */ + void statusOfProblemInParametrics(int type, ClpDataSave &saveData); + void statusOfProblemInParametricsObj(int type, ClpDataSave &saveData); + /** This has the flow between re-factorizations + + Reasons to come out: + -1 iterations etc + -2 inaccuracy + -3 slight inaccuracy (and done iterations) + +0 looks optimal (might be unbounded - but we will investigate) + +1 looks infeasible + +3 max iterations + */ + int whileIterating(parametricsData ¶mData, double reportIncrement, + const double *changeObjective); + /** Computes next theta and says if objective or bounds (0= bounds, 1 objective, -1 none). + theta is in theta_. + type 1 bounds, 2 objective, 3 both. + */ + int nextTheta(int type, double maxTheta, parametricsData ¶mData, + const double *changeObjective); + int whileIteratingObj(parametricsData ¶mData); + int nextThetaObj(double maxTheta, parametricsData ¶mData); + /// Restores bound to original bound + void originalBound(int iSequence, double theta, const double *changeLower, + const double *changeUpper); + /// Compute new rowLower_ etc (return negative if infeasible - otherwise largest change) + double computeRhsEtc(parametricsData ¶mData); + /// Redo lower_ from rowLower_ etc + void redoInternalArrays(); + /** + Row array has row part of pivot row + Column array has column part. + This is used in dual ranging + */ + void checkDualRatios(CoinIndexedVector *rowArray, + CoinIndexedVector *columnArray, + double &costIncrease, int &sequenceIncrease, double &alphaIncrease, + double &costDecrease, int &sequenceDecrease, double &alphaDecrease); + /** + Row array has pivot column + This is used in primal ranging + */ + void checkPrimalRatios(CoinIndexedVector *rowArray, + int direction); + /// Returns new value of whichOther when whichIn enters basis + double primalRanging1(int whichIn, int whichOther); + +public: + /** Write the basis in MPS format to the specified file. + If writeValues true writes values of structurals + (and adds VALUES to end of NAME card) + + Row and column names may be null. + formatType is +
    +
  • 0 - normal +
  • 1 - extra accuracy +
  • 2 - IEEE hex (later) +
+ + Returns non-zero on I/O error + */ + int writeBasis(const char *filename, + bool writeValues = false, + int formatType = 0) const; + /// Read a basis from the given filename + int readBasis(const char *filename); + /** Creates dual of a problem if looks plausible + (defaults will always create model) + fractionRowRanges is fraction of rows allowed to have ranges + fractionColumnRanges is fraction of columns allowed to have ranges + */ + ClpSimplex *dualOfModel(double fractionRowRanges = 1.0, double fractionColumnRanges = 1.0) const; + /** Restores solution from dualized problem + non-zero return code indicates minor problems + */ + int restoreFromDual(const ClpSimplex *dualProblem, + bool checkAccuracy = false); + /** Sets solution in dualized problem + non-zero return code indicates minor problems + */ + int setInDual(ClpSimplex *dualProblem); + /** Does very cursory presolve. + rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. + */ + ClpSimplex *crunch(double *rhs, int *whichRows, int *whichColumns, + int &nBound, bool moreBounds = false, bool tightenBounds = false); + /** After very cursory presolve. + rhs is numberRows, whichRows is 3*numberRows and whichColumns is 2*numberColumns. + */ + void afterCrunch(const ClpSimplex &small, + const int *whichRows, const int *whichColumns, + int nBound); + /** Returns gub version of model or NULL + whichRows has to be numberRows + whichColumns has to be numberRows+numberColumns */ + ClpSimplex *gubVersion(int *whichRows, int *whichColumns, + int neededGub, + int factorizationFrequency = 50); + /// Sets basis from original + void setGubBasis(ClpSimplex &original, const int *whichRows, + const int *whichColumns); + /// Restores basis to original + void getGubBasis(ClpSimplex &original, const int *whichRows, + const int *whichColumns) const; + /// Quick try at cleaning up duals if postsolve gets wrong + void cleanupAfterPostsolve(); + /** Tightens integer bounds - returns number tightened or -1 if infeasible + */ + int tightenIntegerBounds(double *rhsSpace); + /** Expands out all possible combinations for a knapsack + If buildObj NULL then just computes space needed - returns number elements + On entry numberOutput is maximum allowed, on exit it is number needed or + -1 (as will be number elements) if maximum exceeded. numberOutput will have at + least space to return values which reconstruct input. + Rows returned will be original rows but no entries will be returned for + any rows all of whose entries are in knapsack. So up to user to allow for this. + If reConstruct >=0 then returns number of entrie which make up item "reConstruct" + in expanded knapsack. Values in buildRow and buildElement; + */ + int expandKnapsack(int knapsackRow, int &numberOutput, + double *buildObj, CoinBigIndex *buildStart, + int *buildRow, double *buildElement, int reConstruct = -1) const; + /// Create a string of commands to guess at best strategy for model + /// At present mode is ignored + char *guess(int mode) const; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexPrimal.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexPrimal.hpp new file mode 100644 index 000000000..b4dfc8a7a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSimplexPrimal.hpp @@ -0,0 +1,244 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSimplexPrimal_H +#define ClpSimplexPrimal_H + +#include "ClpSimplex.hpp" + +/** This solves LPs using the primal simplex method + + It inherits from ClpSimplex. It has no data of its own and + is never created - only cast from a ClpSimplex object at algorithm time. + +*/ + +class ClpSimplexPrimal : public ClpSimplex { + +public: + /**@name Description of algorithm */ + //@{ + /** Primal algorithm + + Method + + It tries to be a single phase approach with a weight of 1.0 being + given to getting optimal and a weight of infeasibilityCost_ being + given to getting primal feasible. In this version I have tried to + be clever in a stupid way. The idea of fake bounds in dual + seems to work so the primal analogue would be that of getting + bounds on reduced costs (by a presolve approach) and using + these for being above or below feasible region. I decided to waste + memory and keep these explicitly. This allows for non-linear + costs! I have not tested non-linear costs but will be glad + to do something if a reasonable example is provided. + + The code is designed to take advantage of sparsity so arrays are + seldom zeroed out from scratch or gone over in their entirety. + The only exception is a full scan to find incoming variable for + Dantzig row choice. For steepest edge we keep an updated list + of dual infeasibilities (actually squares). + On easy problems we don't need full scan - just + pick first reasonable. This method has not been coded. + + One problem is how to tackle degeneracy and accuracy. At present + I am using the modification of costs which I put in OSL and which was + extended by Gill et al. I am still not sure whether we will also + need explicit perturbation. + + The flow of primal is three while loops as follows: + + while (not finished) { + + while (not clean solution) { + + Factorize and/or clean up solution by changing bounds so + primal feasible. If looks finished check fake primal bounds. + Repeat until status is iterating (-1) or finished (0,1,2) + + } + + while (status==-1) { + + Iterate until no pivot in or out or time to re-factorize. + + Flow is: + + choose pivot column (incoming variable). if none then + we are primal feasible so looks as if done but we need to + break and check bounds etc. + + Get pivot column in tableau + + Choose outgoing row. If we don't find one then we look + primal unbounded so break and check bounds etc. (Also the + pivot tolerance is larger after any iterations so that may be + reason) + + If we do find outgoing row, we may have to adjust costs to + keep going forwards (anti-degeneracy). Check pivot will be stable + and if unstable throw away iteration and break to re-factorize. + If minor error re-factorize after iteration. + + Update everything (this may involve changing bounds on + variables to stay primal feasible. + + } + + } + + TODO's (or maybe not) + + At present we never check we are going forwards. I overdid that in + OSL so will try and make a last resort. + + Needs partial scan pivot in option. + + May need other anti-degeneracy measures, especially if we try and use + loose tolerances as a way to solve in fewer iterations. + + I like idea of dynamic scaling. This gives opportunity to decouple + different implications of scaling for accuracy, iteration count and + feasibility tolerance. + + for use of exotic parameter startFinishoptions see Clpsimplex.hpp + */ + + int primal(int ifValuesPass = 0, int startFinishOptions = 0); + //@} + + /**@name For advanced users */ + //@{ + /// Do not change infeasibility cost and always say optimal + void alwaysOptimal(bool onOff); + bool alwaysOptimal() const; + /** Normally outgoing variables can go out to slightly negative + values (but within tolerance) - this is to help stability and + and degeneracy. This can be switched off + */ + void exactOutgoing(bool onOff); + bool exactOutgoing() const; + //@} + + /**@name Functions used in primal */ + //@{ + /** This has the flow between re-factorizations + + Returns a code to say where decision to exit was made + Problem status set to: + + -2 re-factorize + -4 Looks optimal/infeasible + -5 Looks unbounded + +3 max iterations + + valuesOption has original value of valuesPass + */ + int whileIterating(int valuesOption); + + /** Do last half of an iteration. This is split out so people can + force incoming variable. If solveType_ is 2 then this may + re-factorize while normally it would exit to re-factorize. + Return codes + Reasons to come out (normal mode/user mode): + -1 normal + -2 factorize now - good iteration/ NA + -3 slight inaccuracy - refactorize - iteration done/ same but factor done + -4 inaccuracy - refactorize - no iteration/ NA + -5 something flagged - go round again/ pivot not possible + +2 looks unbounded + +3 max iterations (iteration done) + + With solveType_ ==2 this should + Pivot in a variable and choose an outgoing one. Assumes primal + feasible - will not go through a bound. Returns step length in theta + Returns ray in ray_ + */ + int pivotResult(int ifValuesPass = 0); + + /** The primals are updated by the given array. + Returns number of infeasibilities. + After rowArray will have cost changes for use next iteration + */ + int updatePrimalsInPrimal(CoinIndexedVector *rowArray, + double theta, + double &objectiveChange, + int valuesPass); + /** + Row array has pivot column + This chooses pivot row. + Rhs array is used for distance to next bound (for speed) + For speed, we may need to go to a bucket approach when many + variables go through bounds + If valuesPass non-zero then compute dj for direction + */ + void primalRow(CoinIndexedVector *rowArray, + CoinIndexedVector *rhsArray, + CoinIndexedVector *spareArray, + int valuesPass); + /** + Chooses primal pivot column + updateArray has cost updates (also use pivotRow_ from last iteration) + Would be faster with separate region to scan + and will have this (with square of infeasibility) when steepest + For easy problems we can just choose one of the first columns we look at + */ + void primalColumn(CoinIndexedVector *updateArray, + CoinIndexedVector *spareRow1, + CoinIndexedVector *spareRow2, + CoinIndexedVector *spareColumn1, + CoinIndexedVector *spareColumn2); + + /** Checks if tentative optimal actually means unbounded in primal + Returns -3 if not, 2 if is unbounded */ + int checkUnbounded(CoinIndexedVector *ray, CoinIndexedVector *spare, + double changeCost); + /** Refactorizes if necessary + Checks if finished. Updates status. + lastCleaned refers to iteration at which some objective/feasibility + cleaning too place. + + type - 0 initial so set up save arrays etc + - 1 normal -if good update save + - 2 restoring from saved + saveModel is normally NULL but may not be if doing Sprint + */ + void statusOfProblemInPrimal(int &lastCleaned, int type, + ClpSimplexProgress *progress, + bool doFactorization, + int ifValuesPass, + ClpSimplex *saveModel = NULL); + /// Perturbs problem (method depends on perturbation()) + void perturb(int type); + /// Take off effect of perturbation and say whether to try dual + bool unPerturb(); + /// Unflag all variables and return number unflagged + int unflag(); + /** Get next superbasic -1 if none, + Normal type is 1 + If type is 3 then initializes sorted list + if 2 uses list. + */ + int nextSuperBasic(int superBasicType, CoinIndexedVector *columnArray); + + /// Create primal ray + void primalRay(CoinIndexedVector *rowArray); + /// Clears all bits and clears rowArray[1] etc + void clearAll(); + + /// Sort of lexicographic resolve + int lexSolve(); + + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSolve.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSolve.hpp new file mode 100644 index 000000000..a0a033e0a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/ClpSolve.hpp @@ -0,0 +1,505 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). +/* + Authors + + John Forrest + + */ +#ifndef ClpSolve_H +#define ClpSolve_H + +/** + This is a very simple class to guide algorithms. It is used to tidy up + passing parameters to initialSolve and maybe for output from that + +*/ + +class ClpSolve { + +public: + /** enums for solve function */ + enum SolveType { + useDual = 0, + usePrimal, + usePrimalorSprint, + useBarrier, + useBarrierNoCross, + automatic, + tryDantzigWolfe, + tryBenders, + notImplemented + }; + enum PresolveType { + presolveOn = 0, + presolveOff, + presolveNumber, + presolveNumberCost + }; + + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSolve(); + /// Constructor when you really know what you are doing + ClpSolve(SolveType method, PresolveType presolveType, + int numberPasses, int options[6], + int extraInfo[6], int independentOptions[3]); + /// Generates code for above constructor + void generateCpp(FILE *fp); + /// Copy constructor. + ClpSolve(const ClpSolve &); + /// Assignment operator. This copies the data + ClpSolve &operator=(const ClpSolve &rhs); + /// Destructor + ~ClpSolve(); + //@} + + /**@name Functions most useful to user */ + //@{ + /** Special options - bits + 0 4 - use crash (default allslack in dual, idiot in primal) + 8 - all slack basis in primal + 2 16 - switch off interrupt handling + 3 32 - do not try and make plus minus one matrix + 64 - do not use sprint even if problem looks good + */ + /** which translation is: + which: + 0 - startup in Dual (nothing if basis exists).: + 0 - no basis + 1 - crash + 2 - use initiative about idiot! but no crash + 1 - startup in Primal (nothing if basis exists): + 0 - use initiative + 1 - use crash + 2 - use idiot and look at further info + 3 - use sprint and look at further info + 4 - use all slack + 5 - use initiative but no idiot + 6 - use initiative but no sprint + 7 - use initiative but no crash + 8 - do allslack or idiot + 9 - do allslack or sprint + 10 - slp before + 11 - no nothing and primal(0) + 2 - interrupt handling - 0 yes, 1 no (for threadsafe) + 3 - whether to make +- 1matrix - 0 yes, 1 no + 4 - for barrier + 0 - dense cholesky + 1 - Wssmp allowing some long columns + 2 - Wssmp not allowing long columns + 3 - Wssmp using KKT + 4 - Using Florida ordering + 8 - bit set to do scaling + 16 - set to be aggressive with gamma/delta? + 32 - Use KKT + 5 - for presolve + 1 - switch off dual stuff + 6 - extra switches + + */ + void setSpecialOption(int which, int value, int extraInfo = -1); + int getSpecialOption(int which) const; + + /// Solve types + void setSolveType(SolveType method, int extraInfo = -1); + SolveType getSolveType(); + + // Presolve types + void setPresolveType(PresolveType amount, int extraInfo = -1); + PresolveType getPresolveType(); + int getPresolvePasses() const; + /// Extra info for idiot (or sprint) + int getExtraInfo(int which) const; + /** Say to return at once if infeasible, + default is to solve */ + void setInfeasibleReturn(bool trueFalse); + inline bool infeasibleReturn() const + { + return independentOptions_[0] != 0; + } + /// Whether we want to do dual part of presolve + inline bool doDual() const + { + return (independentOptions_[1] & 1) == 0; + } + inline void setDoDual(bool doDual_) + { + if (doDual_) + independentOptions_[1] &= ~1; + else + independentOptions_[1] |= 1; + } + /// Whether we want to do singleton part of presolve + inline bool doSingleton() const + { + return (independentOptions_[1] & 2) == 0; + } + inline void setDoSingleton(bool doSingleton_) + { + if (doSingleton_) + independentOptions_[1] &= ~2; + else + independentOptions_[1] |= 2; + } + /// Whether we want to do doubleton part of presolve + inline bool doDoubleton() const + { + return (independentOptions_[1] & 4) == 0; + } + inline void setDoDoubleton(bool doDoubleton_) + { + if (doDoubleton_) + independentOptions_[1] &= ~4; + else + independentOptions_[1] |= 4; + } + /// Whether we want to do tripleton part of presolve + inline bool doTripleton() const + { + return (independentOptions_[1] & 8) == 0; + } + inline void setDoTripleton(bool doTripleton_) + { + if (doTripleton_) + independentOptions_[1] &= ~8; + else + independentOptions_[1] |= 8; + } + /// Whether we want to do tighten part of presolve + inline bool doTighten() const + { + return (independentOptions_[1] & 16) == 0; + } + inline void setDoTighten(bool doTighten_) + { + if (doTighten_) + independentOptions_[1] &= ~16; + else + independentOptions_[1] |= 16; + } + /// Whether we want to do forcing part of presolve + inline bool doForcing() const + { + return (independentOptions_[1] & 32) == 0; + } + inline void setDoForcing(bool doForcing_) + { + if (doForcing_) + independentOptions_[1] &= ~32; + else + independentOptions_[1] |= 32; + } + /// Whether we want to do impliedfree part of presolve + inline bool doImpliedFree() const + { + return (independentOptions_[1] & 64) == 0; + } + inline void setDoImpliedFree(bool doImpliedfree) + { + if (doImpliedfree) + independentOptions_[1] &= ~64; + else + independentOptions_[1] |= 64; + } + /// Whether we want to do dupcol part of presolve + inline bool doDupcol() const + { + return (independentOptions_[1] & 128) == 0; + } + inline void setDoDupcol(bool doDupcol_) + { + if (doDupcol_) + independentOptions_[1] &= ~128; + else + independentOptions_[1] |= 128; + } + /// Whether we want to do duprow part of presolve + inline bool doDuprow() const + { + return (independentOptions_[1] & 256) == 0; + } + inline void setDoDuprow(bool doDuprow_) + { + if (doDuprow_) + independentOptions_[1] &= ~256; + else + independentOptions_[1] |= 256; + } + /// Whether we want to do singleton column part of presolve + inline bool doSingletonColumn() const + { + return (independentOptions_[1] & 512) == 0; + } + inline void setDoSingletonColumn(bool doSingleton_) + { + if (doSingleton_) + independentOptions_[1] &= ~512; + else + independentOptions_[1] |= 512; + } + /// Whether we want to kill small substitutions + inline bool doKillSmall() const + { + return (independentOptions_[1] & 8192) == 0; + } + inline void setDoKillSmall(bool doKill) + { + if (doKill) + independentOptions_[1] &= ~8192; + else + independentOptions_[1] |= 8192; + } + /// Set whole group + inline int presolveActions() const + { + return independentOptions_[1] & 0xffffff; + } + inline void setPresolveActions(int action) + { + independentOptions_[1] = (independentOptions_[1] & 0xff000000) | (action & 0xffffff); + } + /// Largest column for substitution (normally 3) + inline int substitution() const + { + return independentOptions_[2]; + } + inline void setSubstitution(int value) + { + independentOptions_[2] = value; + } + inline void setIndependentOption(int type, int value) + { + independentOptions_[type] = value; + } + inline int independentOption(int type) const + { + return independentOptions_[type]; + } + //@} + + ////////////////// data ////////////////// +private: + /**@name data. + */ + //@{ + /// Solve type + SolveType method_; + /// Presolve type + PresolveType presolveType_; + /// Amount of presolve + int numberPasses_; + /// Options - last is switch for OsiClp + int options_[7]; + /// Extra information + int extraInfo_[7]; + /** Extra algorithm dependent options + 0 - if set return from clpsolve if infeasible + 1 - To be copied over to presolve options + 2 - max substitution level + If Dantzig Wolfe/benders 0 is number blocks, 2 is #passes (notional) + */ + int independentOptions_[3]; + //@} +}; + +/// For saving extra information to see if looping. +class ClpSimplexProgress { + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + ClpSimplexProgress(); + + /// Constructor from model + ClpSimplexProgress(ClpSimplex *model); + + /// Copy constructor. + ClpSimplexProgress(const ClpSimplexProgress &); + + /// Assignment operator. This copies the data + ClpSimplexProgress &operator=(const ClpSimplexProgress &rhs); + /// Destructor + ~ClpSimplexProgress(); + /// Resets as much as possible + void reset(); + /// Fill from model + void fillFromModel(ClpSimplex *model); + + //@} + + /**@name Check progress */ + //@{ + /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, + >=0 if give up and use as problem status + */ + int looping(); + /// Start check at beginning of whileIterating + void startCheck(); + /// Returns cycle length in whileIterating + int cycle(int in, int out, int wayIn, int wayOut); + + /// Returns previous objective (if -1) - current if (0) + double lastObjective(int back = 1) const; + /// Set real primal infeasibility and move back + void setInfeasibility(double value); + /// Returns real primal infeasibility (if -1) - current if (0) + double lastInfeasibility(int back = 1) const; + /// Returns number of primal infeasibilities (if -1) - current if (0) + int numberInfeasibilities(int back = 1) const; + /// Modify objective e.g. if dual infeasible in dual + void modifyObjective(double value); + /// Returns previous iteration number (if -1) - current if (0) + int lastIterationNumber(int back = 1) const; + /// clears all iteration numbers (to switch off panic) + void clearIterationNumbers(); + /// Odd state + inline void newOddState() + { + oddState_ = -oddState_ - 1; + } + inline void endOddState() + { + oddState_ = abs(oddState_); + } + inline void clearOddState() + { + oddState_ = 0; + } + inline int oddState() const + { + return oddState_; + } + /// number of bad times + inline int badTimes() const + { + return numberBadTimes_; + } + inline void clearBadTimes() + { + numberBadTimes_ = 0; + } + /// number of really bad times + inline int reallyBadTimes() const + { + return numberReallyBadTimes_; + } + inline void incrementReallyBadTimes() + { + numberReallyBadTimes_++; + } + /// number of times flagged + inline int timesFlagged() const + { + return numberTimesFlagged_; + } + inline void clearTimesFlagged() + { + numberTimesFlagged_ = 0; + } + inline void incrementTimesFlagged() + { + numberTimesFlagged_++; + } + + //@} + /**@name Data */ +#define CLP_PROGRESS 5 + //#define CLP_PROGRESS_WEIGHT 10 + //@{ + /// Objective values + double objective_[CLP_PROGRESS]; + /// Sum of infeasibilities for algorithm + double infeasibility_[CLP_PROGRESS]; + /// Sum of real primal infeasibilities for primal + double realInfeasibility_[CLP_PROGRESS]; +#ifdef CLP_PROGRESS_WEIGHT + /// Objective values for weights + double objectiveWeight_[CLP_PROGRESS_WEIGHT]; + /// Sum of infeasibilities for algorithm for weights + double infeasibilityWeight_[CLP_PROGRESS_WEIGHT]; + /// Sum of real primal infeasibilities for primal for weights + double realInfeasibilityWeight_[CLP_PROGRESS_WEIGHT]; + /// Drop for weights + double drop_; + /// Best? for weights + double best_; +#endif + /// Initial weight for weights + double initialWeight_; +#define CLP_CYCLE 12 + /// For cycle checking + //double obj_[CLP_CYCLE]; + int in_[CLP_CYCLE]; + int out_[CLP_CYCLE]; + char way_[CLP_CYCLE]; + /// Pointer back to model so we can get information + ClpSimplex *model_; + /// Number of infeasibilities + int numberInfeasibilities_[CLP_PROGRESS]; + /// Iteration number at which occurred + int iterationNumber_[CLP_PROGRESS]; +#ifdef CLP_PROGRESS_WEIGHT + /// Number of infeasibilities for weights + int numberInfeasibilitiesWeight_[CLP_PROGRESS_WEIGHT]; + /// Iteration number at which occurred for weights + int iterationNumberWeight_[CLP_PROGRESS_WEIGHT]; +#endif + /// Number of times checked (so won't stop too early) + int numberTimes_; + /// Number of times it looked like loop + int numberBadTimes_; + /// Number really bad times + int numberReallyBadTimes_; + /// Number of times no iterations as flagged + int numberTimesFlagged_; + /// If things are in an odd state + int oddState_; + //@} +}; + +#include "ClpConfig.h" +#if CLP_HAS_ABC +#include "AbcCommon.hpp" +/// For saving extra information to see if looping. +class AbcSimplexProgress : public ClpSimplexProgress { + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + AbcSimplexProgress(); + + /// Constructor from model + AbcSimplexProgress(ClpSimplex *model); + + /// Copy constructor. + AbcSimplexProgress(const AbcSimplexProgress &); + + /// Assignment operator. This copies the data + AbcSimplexProgress &operator=(const AbcSimplexProgress &rhs); + /// Destructor + ~AbcSimplexProgress(); + + //@} + + /**@name Check progress */ + //@{ + /** Returns -1 if okay, -n+1 (n number of times bad) if bad but action taken, + >=0 if give up and use as problem status + */ + int looping(); + + //@} + /**@name Data */ + //@} +}; +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Clp_C_Interface.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Clp_C_Interface.h new file mode 100644 index 000000000..6b668d748 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Clp_C_Interface.h @@ -0,0 +1,554 @@ +/* $Id$ */ +/* + Copyright (C) 2002, 2003 International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef ClpSimplexC_H +#define ClpSimplexC_H + +/* include all defines and ugly stuff */ +#include "Coin_C_defines.h" + +/* accidentally used a bool for Clp_modifyCoefficient, so need to include stdbool.h + * Clp_modifyCoefficient signature will change to use int with Clp 1.18 + * stdbool.h is available with C99 + * __STDC_VERSION__ isn't available when compiling C++ - look at C++ version instead + */ +#if (defined(__cplusplus) && __cplusplus >= 199901L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +#include +#endif + +#if defined(CLP_EXTERN_C) +typedef struct { + ClpSolve options; +} Clp_Solve; +#else +typedef void Clp_Solve; +#endif + +/** This is a first "C" interface to Clp. + It has similarities to the OSL V3 interface + and only has most common functions +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/**@name Version info + * + * A Clp library has a version number of the form .., + * where each of major, minor, and release are nonnegative integers. + * For a checkout of the Clp stable branch, release is 9999. + * For a checkout of the Clp development branch, major, minor, and release are 9999. + */ +/*@{*/ +/** Clp library version number as string. */ +COINLIBAPI const char *COINLINKAGE Clp_Version(void); +/** Major number of Clp library version. */ +COINLIBAPI int COINLINKAGE Clp_VersionMajor(void); +/** Minor number of Clp library version. */ +COINLIBAPI int COINLINKAGE Clp_VersionMinor(void); +/** Release number of Clp library version. */ +COINLIBAPI int COINLINKAGE Clp_VersionRelease(void); +/*@}*/ + +/**@name Constructors and destructor + These do not have an exact analogue in C++. + The user does not need to know structure of Clp_Simplex or Clp_Solve. + + For (almost) all Clp_* functions outside this group there is an exact C++ + analogue created by taking the first parameter out, removing the Clp_ + from name and applying the method to an object of type ClpSimplex. + + Similarly, for all ClpSolve_* functions there is an exact C++ + analogue created by taking the first parameter out, removing the ClpSolve_ + from name and applying the method to an object of type ClpSolve. + */ +/*@{*/ + +/** Default constructor */ +COINLIBAPI Clp_Simplex *COINLINKAGE Clp_newModel(void); +/** Destructor */ +COINLIBAPI void COINLINKAGE Clp_deleteModel(Clp_Simplex *model); +/** Default constructor */ +COINLIBAPI Clp_Solve *COINLINKAGE ClpSolve_new(void); +/** Destructor */ +COINLIBAPI void COINLINKAGE ClpSolve_delete(Clp_Solve *solve); +/*@}*/ + +/**@name Load model - loads some stuff and initializes others */ +/*@{*/ +/** Loads a problem (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ +/** Just like the other loadProblem() method except that the matrix is + given in a standard column major ordered format (without gaps). */ +COINLIBAPI void COINLINKAGE Clp_loadProblem(Clp_Simplex *model, const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + +/* read quadratic part of the objective (the matrix part) */ +COINLIBAPI void COINLINKAGE +Clp_loadQuadraticObjective(Clp_Simplex *model, + const int numberColumns, + const CoinBigIndex *start, + const int *column, + const double *element); +/** Read an mps file from the given filename */ +COINLIBAPI int COINLINKAGE Clp_readMps(Clp_Simplex *model, const char *filename, + int keepNames, + int ignoreErrors); +/** Write an mps file to the given filename */ +/** Format type is 0 = normal, 1 = extra or 2 = hex. + Number across is 1 or 2. + Use objSense = -1D to flip the objective function around. */ +COINLIBAPI int COINLINKAGE Clp_writeMps(Clp_Simplex *model, const char *filename, + int formatType, + int numberAcross, + double objSense); +/** Copy in integer informations */ +COINLIBAPI void COINLINKAGE Clp_copyInIntegerInformation(Clp_Simplex *model, const char *information); +/** Drop integer informations */ +COINLIBAPI void COINLINKAGE Clp_deleteIntegerInformation(Clp_Simplex *model); +/** Resizes rim part of model */ +COINLIBAPI void COINLINKAGE Clp_resize(Clp_Simplex *model, int newNumberRows, int newNumberColumns); +/** Deletes rows */ +COINLIBAPI void COINLINKAGE Clp_deleteRows(Clp_Simplex *model, int number, const int *which); +/** Add rows */ +COINLIBAPI void COINLINKAGE Clp_addRows(Clp_Simplex *model, int number, const double *rowLower, + const double *rowUpper, + const CoinBigIndex *rowStarts, const int *columns, + const double *elements); + +/** Deletes columns */ +COINLIBAPI void COINLINKAGE Clp_deleteColumns(Clp_Simplex *model, int number, const int *which); +/** Add columns */ +COINLIBAPI void COINLINKAGE Clp_addColumns(Clp_Simplex *model, int number, const double *columnLower, + const double *columnUpper, + const double *objective, + const CoinBigIndex *columnStarts, const int *rows, + const double *elements); +/** Change row lower bounds */ +COINLIBAPI void COINLINKAGE Clp_chgRowLower(Clp_Simplex *model, const double *rowLower); +/** Change row upper bounds */ +COINLIBAPI void COINLINKAGE Clp_chgRowUpper(Clp_Simplex *model, const double *rowUpper); +/** Change column lower bounds */ +COINLIBAPI void COINLINKAGE Clp_chgColumnLower(Clp_Simplex *model, const double *columnLower); +/** Change column upper bounds */ +COINLIBAPI void COINLINKAGE Clp_chgColumnUpper(Clp_Simplex *model, const double *columnUpper); +/** Change objective coefficients */ +COINLIBAPI void COINLINKAGE Clp_chgObjCoefficients(Clp_Simplex *model, const double *objIn); +/** Change matrix coefficients + * + * \note Clp 1.18 will change the type of @param keepZero to int. + */ +#if (defined(__cplusplus) && __cplusplus >= 199901L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +COINLIBAPI void COINLINKAGE Clp_modifyCoefficient(Clp_Simplex *model, int row, int column, double newElement, + bool keepZero); +#endif +/** Drops names - makes lengthnames 0 and names empty */ +COINLIBAPI void COINLINKAGE Clp_dropNames(Clp_Simplex *model); +/** Copies in names */ +COINLIBAPI void COINLINKAGE Clp_copyNames(Clp_Simplex *model, const char *const *rowNames, + const char *const *columnNames); + +/*@}*/ +/**@name gets and sets - you will find some synonyms at the end of this file */ +/*@{*/ +/** Number of rows */ +COINLIBAPI int COINLINKAGE Clp_numberRows(Clp_Simplex *model); +/** Number of columns */ +COINLIBAPI int COINLINKAGE Clp_numberColumns(Clp_Simplex *model); +/** Primal tolerance to use */ +COINLIBAPI double COINLINKAGE Clp_primalTolerance(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setPrimalTolerance(Clp_Simplex *model, double value); +/** Dual tolerance to use */ +COINLIBAPI double COINLINKAGE Clp_dualTolerance(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setDualTolerance(Clp_Simplex *model, double value); +/** Dual objective limit */ +COINLIBAPI double COINLINKAGE Clp_dualObjectiveLimit(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setDualObjectiveLimit(Clp_Simplex *model, double value); +/** Objective offset */ +COINLIBAPI double COINLINKAGE Clp_objectiveOffset(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setObjectiveOffset(Clp_Simplex *model, double value); +/** Fills in array with problem name */ +COINLIBAPI void COINLINKAGE Clp_problemName(Clp_Simplex *model, int maxNumberCharacters, char *array); +/* Sets problem name. Must have \0 at end. */ +COINLIBAPI int COINLINKAGE +Clp_setProblemName(Clp_Simplex *model, int maxNumberCharacters, char *array); +/** Number of iterations */ +COINLIBAPI int COINLINKAGE Clp_numberIterations(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setNumberIterations(Clp_Simplex *model, int numberIterations); +/** Maximum number of iterations */ +COINLIBAPI int maximumIterations(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setMaximumIterations(Clp_Simplex *model, int value); +/** Maximum time in seconds (from when set called) */ +COINLIBAPI double COINLINKAGE Clp_maximumSeconds(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setMaximumSeconds(Clp_Simplex *model, double value); +/** Returns true if hit maximum iterations (or time) */ +COINLIBAPI int COINLINKAGE Clp_hitMaximumIterations(Clp_Simplex *model); +/** Status of problem: + 0 - optimal + 1 - primal infeasible + 2 - dual infeasible + 3 - stopped on iterations etc + 4 - stopped due to errors + */ +COINLIBAPI int COINLINKAGE Clp_status(Clp_Simplex *model); +/** Set problem status */ +COINLIBAPI void COINLINKAGE Clp_setProblemStatus(Clp_Simplex *model, int problemStatus); +/** Secondary status of problem - may get extended + 0 - none + 1 - primal infeasible because dual limit reached + 2 - scaled problem optimal - unscaled has primal infeasibilities + 3 - scaled problem optimal - unscaled has dual infeasibilities + 4 - scaled problem optimal - unscaled has both dual and primal infeasibilities + */ +COINLIBAPI int COINLINKAGE Clp_secondaryStatus(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setSecondaryStatus(Clp_Simplex *model, int status); +/** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ +COINLIBAPI double COINLINKAGE Clp_optimizationDirection(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setOptimizationDirection(Clp_Simplex *model, double value); +/** Primal row solution */ +COINLIBAPI double *COINLINKAGE Clp_primalRowSolution(Clp_Simplex *model); +/** Primal column solution */ +COINLIBAPI double *COINLINKAGE Clp_primalColumnSolution(Clp_Simplex *model); +/** Dual row solution */ +COINLIBAPI double *COINLINKAGE Clp_dualRowSolution(Clp_Simplex *model); +/** Reduced costs */ +COINLIBAPI double *COINLINKAGE Clp_dualColumnSolution(Clp_Simplex *model); +/** Row lower */ +COINLIBAPI double *COINLINKAGE Clp_rowLower(Clp_Simplex *model); +/** Row upper */ +COINLIBAPI double *COINLINKAGE Clp_rowUpper(Clp_Simplex *model); +/** Objective */ +COINLIBAPI double *COINLINKAGE Clp_objective(Clp_Simplex *model); +/** Column Lower */ +COINLIBAPI double *COINLINKAGE Clp_columnLower(Clp_Simplex *model); +/** Column Upper */ +COINLIBAPI double *COINLINKAGE Clp_columnUpper(Clp_Simplex *model); +/** Number of elements in matrix */ +COINLIBAPI CoinBigIndex COINLINKAGE Clp_getNumElements(Clp_Simplex *model); +/* Column starts in matrix */ +COINLIBAPI const CoinBigIndex *COINLINKAGE Clp_getVectorStarts(Clp_Simplex *model); +/* Row indices in matrix */ +COINLIBAPI const int *COINLINKAGE Clp_getIndices(Clp_Simplex *model); +/* Column vector lengths in matrix */ +COINLIBAPI const int *COINLINKAGE Clp_getVectorLengths(Clp_Simplex *model); +/* Element values in matrix */ +COINLIBAPI const double *COINLINKAGE Clp_getElements(Clp_Simplex *model); +/** Objective value */ +COINLIBAPI double COINLINKAGE Clp_objectiveValue(Clp_Simplex *model); +/** Integer information */ +COINLIBAPI char *COINLINKAGE Clp_integerInformation(Clp_Simplex *model); +/** Gives Infeasibility ray. + * + * Use Clp_freeRay to free the returned array. + * + * @return infeasibility ray, or NULL returned if none/wrong. + */ +COINLIBAPI double *COINLINKAGE Clp_infeasibilityRay(Clp_Simplex *model); +/** Gives ray in which the problem is unbounded. + * + * Use Clp_freeRay to free the returned array. + * + * @return unbounded ray, or NULL returned if none/wrong. + */ +COINLIBAPI double *COINLINKAGE Clp_unboundedRay(Clp_Simplex *model); +/** Frees a infeasibility or unbounded ray. */ +COINLIBAPI void COINLINKAGE Clp_freeRay(Clp_Simplex *model, double *ray); +/** See if status array exists (partly for OsiClp) */ +COINLIBAPI int COINLINKAGE Clp_statusExists(Clp_Simplex *model); +/** Return address of status array (char[numberRows+numberColumns]) */ +COINLIBAPI unsigned char *COINLINKAGE Clp_statusArray(Clp_Simplex *model); +/** Copy in status vector */ +COINLIBAPI void COINLINKAGE Clp_copyinStatus(Clp_Simplex *model, const unsigned char *statusArray); +/* status values are as in ClpSimplex.hpp i.e. 0 - free, 1 basic, 2 at upper, + 3 at lower, 4 superbasic, (5 fixed) */ +/* Get variable basis info */ +COINLIBAPI int COINLINKAGE Clp_getColumnStatus(Clp_Simplex *model, int sequence); +/* Get row basis info */ +COINLIBAPI int COINLINKAGE Clp_getRowStatus(Clp_Simplex *model, int sequence); +/* Set variable basis info (and value if at bound) */ +COINLIBAPI void COINLINKAGE Clp_setColumnStatus(Clp_Simplex *model, + int sequence, int value); +/* Set row basis info (and value if at bound) */ +COINLIBAPI void COINLINKAGE Clp_setRowStatus(Clp_Simplex *model, + int sequence, int value); + +/** User pointer for whatever reason */ +COINLIBAPI void COINLINKAGE Clp_setUserPointer(Clp_Simplex *model, void *pointer); +COINLIBAPI void *COINLINKAGE Clp_getUserPointer(Clp_Simplex *model); +/*@}*/ +/**@name Message handling. Call backs are handled by ONE function */ +/*@{*/ +/** Pass in Callback function. + Message numbers up to 1000000 are Clp, Coin ones have 1000000 added */ +COINLIBAPI void COINLINKAGE Clp_registerCallBack(Clp_Simplex *model, + clp_callback userCallBack); +/** Unset Callback function */ +COINLIBAPI void COINLINKAGE Clp_clearCallBack(Clp_Simplex *model); +/** Amount of print out: + 0 - none + 1 - just final + 2 - just factorizations + 3 - as 2 plus a bit more + 4 - verbose + above that 8,16,32 etc just for selective debug + */ +COINLIBAPI void COINLINKAGE Clp_setLogLevel(Clp_Simplex *model, int value); +COINLIBAPI int COINLINKAGE Clp_logLevel(Clp_Simplex *model); +/** length of names (0 means no names0 */ +COINLIBAPI int COINLINKAGE Clp_lengthNames(Clp_Simplex *model); +/** Fill in array (at least lengthNames+1 long) with a row name */ +COINLIBAPI void COINLINKAGE Clp_rowName(Clp_Simplex *model, int iRow, char *name); +/** Fill in array (at least lengthNames+1 long) with a column name */ +COINLIBAPI void COINLINKAGE Clp_columnName(Clp_Simplex *model, int iColumn, char *name); +/** Set row name - Nice if they are short - 8 chars or less I think */ +COINLIBAPI void COINLINKAGE Clp_setRowName(Clp_Simplex *model, int iRow, char *name); +/** Set column name - Nice if they are short - 8 chars or less I think */ +COINLIBAPI void COINLINKAGE Clp_setColumnName(Clp_Simplex *model, int iColumn, char *name); + +/*@}*/ + +/**@name Functions most useful to user */ +/*@{*/ +/** General solve algorithm which can do presolve. + See ClpSolve.hpp for options + */ +COINLIBAPI int COINLINKAGE Clp_initialSolve(Clp_Simplex *model); +/** Pass solve options. (Exception to direct analogue rule) */ +COINLIBAPI int COINLINKAGE Clp_initialSolveWithOptions(Clp_Simplex *model, Clp_Solve *); +/** Dual initial solve */ +COINLIBAPI int COINLINKAGE Clp_initialDualSolve(Clp_Simplex *model); +/** Primal initial solve */ +COINLIBAPI int COINLINKAGE Clp_initialPrimalSolve(Clp_Simplex *model); +/** Barrier initial solve */ +COINLIBAPI int COINLINKAGE Clp_initialBarrierSolve(Clp_Simplex *model); +/** Barrier initial solve, no crossover */ +COINLIBAPI int COINLINKAGE Clp_initialBarrierNoCrossSolve(Clp_Simplex *model); +/** Dual algorithm - see ClpSimplexDual.hpp for method */ +COINLIBAPI int COINLINKAGE Clp_dual(Clp_Simplex *model, int ifValuesPass); +/** Primal algorithm - see ClpSimplexPrimal.hpp for method */ +COINLIBAPI int COINLINKAGE Clp_primal(Clp_Simplex *model, int ifValuesPass); +#ifndef SLIM_CLP +/** Solve the problem with the idiot code */ +COINLIBAPI void COINLINKAGE Clp_idiot(Clp_Simplex *model, int tryhard); +#endif +/** Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */ +COINLIBAPI void COINLINKAGE Clp_scaling(Clp_Simplex *model, int mode); +/** Gets scalingFlag */ +COINLIBAPI int COINLINKAGE Clp_scalingFlag(Clp_Simplex *model); +/** Crash - at present just aimed at dual, returns + -2 if dual preferred and crash basis created + -1 if dual preferred and all slack basis preferred + 0 if basis going in was not all slack + 1 if primal preferred and all slack basis preferred + 2 if primal preferred and crash basis created. + + if gap between bounds <="gap" variables can be flipped + + If "pivot" is + 0 No pivoting (so will just be choice of algorithm) + 1 Simple pivoting e.g. gub + 2 Mini iterations + */ +COINLIBAPI int COINLINKAGE Clp_crash(Clp_Simplex *model, double gap, int pivot); +/*@}*/ + +/**@name most useful gets and sets */ +/*@{*/ +/** If problem is primal feasible */ +COINLIBAPI int COINLINKAGE Clp_primalFeasible(Clp_Simplex *model); +/** If problem is dual feasible */ +COINLIBAPI int COINLINKAGE Clp_dualFeasible(Clp_Simplex *model); +/** Dual bound */ +COINLIBAPI double COINLINKAGE Clp_dualBound(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setDualBound(Clp_Simplex *model, double value); +/** Infeasibility cost */ +COINLIBAPI double COINLINKAGE Clp_infeasibilityCost(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setInfeasibilityCost(Clp_Simplex *model, double value); +/** Perturbation: + 50 - switch on perturbation + 100 - auto perturb if takes too long (1.0e-6 largest nonzero) + 101 - we are perturbed + 102 - don't try perturbing again + default is 100 + others are for playing + */ +COINLIBAPI int COINLINKAGE Clp_perturbation(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setPerturbation(Clp_Simplex *model, int value); +/** Current (or last) algorithm */ +COINLIBAPI int COINLINKAGE Clp_algorithm(Clp_Simplex *model); +/** Set algorithm */ +COINLIBAPI void COINLINKAGE Clp_setAlgorithm(Clp_Simplex *model, int value); +/** Sum of dual infeasibilities */ +COINLIBAPI double COINLINKAGE Clp_sumDualInfeasibilities(Clp_Simplex *model); +/** Number of dual infeasibilities */ +COINLIBAPI int COINLINKAGE Clp_numberDualInfeasibilities(Clp_Simplex *model); +/** Sum of primal infeasibilities */ +COINLIBAPI double COINLINKAGE Clp_sumPrimalInfeasibilities(Clp_Simplex *model); +/** Number of primal infeasibilities */ +COINLIBAPI int COINLINKAGE Clp_numberPrimalInfeasibilities(Clp_Simplex *model); +/** Save model to file, returns 0 if success. This is designed for + use outside algorithms so does not save iterating arrays etc. + It does not save any messaging information. + Does not save scaling values. + It does not know about all types of virtual functions. + */ +COINLIBAPI int COINLINKAGE Clp_saveModel(Clp_Simplex *model, const char *fileName); +/** Restore model from file, returns 0 if success, + deletes current model */ +COINLIBAPI int COINLINKAGE Clp_restoreModel(Clp_Simplex *model, const char *fileName); + +/** Just check solution (for external use) - sets sum of + infeasibilities etc */ +COINLIBAPI void COINLINKAGE Clp_checkSolution(Clp_Simplex *model); +/*@}*/ + +/******************** End of most useful part **************/ +/**@name gets and sets - some synonyms */ +/*@{*/ +/** Number of rows */ +COINLIBAPI int COINLINKAGE Clp_getNumRows(Clp_Simplex *model); +/** Number of columns */ +COINLIBAPI int COINLINKAGE Clp_getNumCols(Clp_Simplex *model); +/** Number of iterations */ +COINLIBAPI int COINLINKAGE Clp_getIterationCount(Clp_Simplex *model); +/** Are there a numerical difficulties? */ +COINLIBAPI int COINLINKAGE Clp_isAbandoned(Clp_Simplex *model); +/** Is optimality proven? */ +COINLIBAPI int COINLINKAGE Clp_isProvenOptimal(Clp_Simplex *model); +/** Is primal infeasiblity proven? */ +COINLIBAPI int COINLINKAGE Clp_isProvenPrimalInfeasible(Clp_Simplex *model); +/** Is dual infeasiblity proven? */ +COINLIBAPI int COINLINKAGE Clp_isProvenDualInfeasible(Clp_Simplex *model); +/** Is the given primal objective limit reached? */ +COINLIBAPI int COINLINKAGE Clp_isPrimalObjectiveLimitReached(Clp_Simplex *model); +/** Is the given dual objective limit reached? */ +COINLIBAPI int COINLINKAGE Clp_isDualObjectiveLimitReached(Clp_Simplex *model); +/** Iteration limit reached? */ +COINLIBAPI int COINLINKAGE Clp_isIterationLimitReached(Clp_Simplex *model); +/** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ +COINLIBAPI double COINLINKAGE Clp_getObjSense(Clp_Simplex *model); +/** Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore */ +COINLIBAPI void COINLINKAGE Clp_setObjSense(Clp_Simplex *model, double objsen); +/** Primal row solution */ +COINLIBAPI const double *COINLINKAGE Clp_getRowActivity(Clp_Simplex *model); +/** Primal column solution */ +COINLIBAPI const double *COINLINKAGE Clp_getColSolution(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setColSolution(Clp_Simplex *model, const double *input); +/** Dual row solution */ +COINLIBAPI const double *COINLINKAGE Clp_getRowPrice(Clp_Simplex *model); +/** Reduced costs */ +COINLIBAPI const double *COINLINKAGE Clp_getReducedCost(Clp_Simplex *model); +/** Row lower */ +COINLIBAPI const double *COINLINKAGE Clp_getRowLower(Clp_Simplex *model); +/** Row upper */ +COINLIBAPI const double *COINLINKAGE Clp_getRowUpper(Clp_Simplex *model); +/** Objective */ +COINLIBAPI const double *COINLINKAGE Clp_getObjCoefficients(Clp_Simplex *model); +/** Column Lower */ +COINLIBAPI const double *COINLINKAGE Clp_getColLower(Clp_Simplex *model); +/** Column Upper */ +COINLIBAPI const double *COINLINKAGE Clp_getColUpper(Clp_Simplex *model); +/** Objective value */ +COINLIBAPI double COINLINKAGE Clp_getObjValue(Clp_Simplex *model); +/** Print model for debugging purposes */ +COINLIBAPI void COINLINKAGE Clp_printModel(Clp_Simplex *model, const char *prefix); +/* Small element value - elements less than this set to zero, + default is 1.0e-20 */ +COINLIBAPI double COINLINKAGE Clp_getSmallElementValue(Clp_Simplex *model); +COINLIBAPI void COINLINKAGE Clp_setSmallElementValue(Clp_Simplex *model, double value); +/*@}*/ + +/**@name Get and set ClpSolve options + */ +/*@{*/ +COINLIBAPI void COINLINKAGE ClpSolve_setSpecialOption(Clp_Solve *, int which, int value, int extraInfo); +COINLIBAPI int COINLINKAGE ClpSolve_getSpecialOption(Clp_Solve *, int which); + +/** method: (see ClpSolve::SolveType) + 0 - dual simplex + 1 - primal simplex + 2 - primal or sprint + 3 - barrier + 4 - barrier no crossover + 5 - automatic + 6 - not implemented + -- pass extraInfo == -1 for default behavior */ +COINLIBAPI void COINLINKAGE ClpSolve_setSolveType(Clp_Solve *, int method, int extraInfo); +COINLIBAPI int COINLINKAGE ClpSolve_getSolveType(Clp_Solve *); + +/** amount: (see ClpSolve::PresolveType) + 0 - presolve on + 1 - presolve off + 2 - presolve number + 3 - presolve number cost + -- pass extraInfo == -1 for default behavior */ +COINLIBAPI void COINLINKAGE ClpSolve_setPresolveType(Clp_Solve *, int amount, int extraInfo); +COINLIBAPI int COINLINKAGE ClpSolve_getPresolveType(Clp_Solve *); + +COINLIBAPI int COINLINKAGE ClpSolve_getPresolvePasses(Clp_Solve *); +COINLIBAPI int COINLINKAGE ClpSolve_getExtraInfo(Clp_Solve *, int which); +COINLIBAPI void COINLINKAGE ClpSolve_setInfeasibleReturn(Clp_Solve *, int trueFalse); +COINLIBAPI int COINLINKAGE ClpSolve_infeasibleReturn(Clp_Solve *); + +COINLIBAPI int COINLINKAGE ClpSolve_doDual(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoDual(Clp_Solve *, int doDual); + +COINLIBAPI int COINLINKAGE ClpSolve_doSingleton(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoSingleton(Clp_Solve *, int doSingleton); + +COINLIBAPI int COINLINKAGE ClpSolve_doDoubleton(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoDoubleton(Clp_Solve *, int doDoubleton); + +COINLIBAPI int COINLINKAGE ClpSolve_doTripleton(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoTripleton(Clp_Solve *, int doTripleton); + +COINLIBAPI int COINLINKAGE ClpSolve_doTighten(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoTighten(Clp_Solve *, int doTighten); + +COINLIBAPI int COINLINKAGE ClpSolve_doForcing(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoForcing(Clp_Solve *, int doForcing); + +COINLIBAPI int COINLINKAGE ClpSolve_doImpliedFree(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoImpliedFree(Clp_Solve *, int doImpliedFree); + +COINLIBAPI int COINLINKAGE ClpSolve_doDupcol(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoDupcol(Clp_Solve *, int doDupcol); + +COINLIBAPI int COINLINKAGE ClpSolve_doDuprow(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoDuprow(Clp_Solve *, int doDuprow); + +COINLIBAPI int COINLINKAGE ClpSolve_doSingletonColumn(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setDoSingletonColumn(Clp_Solve *, int doSingleton); + +COINLIBAPI int COINLINKAGE ClpSolve_presolveActions(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setPresolveActions(Clp_Solve *, int action); + +COINLIBAPI int COINLINKAGE ClpSolve_substitution(Clp_Solve *); +COINLIBAPI void COINLINKAGE ClpSolve_setSubstitution(Clp_Solve *, int value); + +/*@}*/ +#ifdef __cplusplus +} +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinAlloc.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinAlloc.hpp new file mode 100644 index 000000000..f47ddd632 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinAlloc.hpp @@ -0,0 +1,179 @@ +/* $Id$ */ +// Copyright (C) 2007, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinAlloc_hpp +#define CoinAlloc_hpp + +#include "CoinUtilsConfig.h" +#include + +#if !defined(COINUTILS_MEMPOOL_MAXPOOLED) +#define COINUTILS_MEMPOOL_MAXPOOLED -1 +#endif + +#if (COINUTILS_MEMPOOL_MAXPOOLED >= 0) + +#ifndef COINUTILS_MEMPOOL_ALIGNMENT +#define COINUTILS_MEMPOOL_ALIGNMENT 16 +#endif + +/* Note: + This memory pool implementation assumes that sizeof(size_t) and + sizeof(void*) are both <= COINUTILS_MEMPOOL_ALIGNMENT. + Choosing an alignment of 4 will cause segfault on 64-bit platforms and may + lead to bad performance on 32-bit platforms. So 8 is a mnimum recommended + alignment. Probably 16 does not waste too much space either and may be even + better for performance. One must play with it. +*/ + +//############################################################################# + +#if (COINUTILS_MEMPOOL_ALIGNMENT == 16) +static const std::size_t CoinAllocPtrShift = 4; +static const std::size_t CoinAllocRoundMask = ~((std::size_t)15); +#elif (COINUTILS_MEMPOOL_ALIGNMENT == 8) +static const std::size_t CoinAllocPtrShift = 3; +static const std::size_t CoinAllocRoundMask = ~((std::size_t)7); +#else +#error "COINUTILS_MEMPOOL_ALIGNMENT must be defined as 8 or 16 (or this code needs to be changed :-)" +#endif + +//############################################################################# + +#ifndef COIN_MEMPOOL_SAVE_BLOCKHEADS +#define COIN_MEMPOOL_SAVE_BLOCKHEADS 0 +#endif + +//############################################################################# + +class CoinMempool { +private: +#if (COIN_MEMPOOL_SAVE_BLOCKHEADS == 1) + char **block_heads; + std::size_t block_num; + std::size_t max_block_num; +#endif +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_t mutex_; +#endif + int last_block_size_; + char *first_free_; + const std::size_t entry_size_; + +private: + CoinMempool(const CoinMempool &); + CoinMempool &operator=(const CoinMempool &); + +private: + char *allocate_new_block(); + inline void lock_mutex() + { +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_lock(&mutex_); +#endif + } + inline void unlock_mutex() + { +#if defined(COINUTILS_PTHREADS) && (COINUTILS_PTHREAD == 1) + pthread_mutex_unlock(&mutex_); +#endif + } + +public: + CoinMempool(std::size_t size = 0); + ~CoinMempool(); + + char *alloc(); + inline void dealloc(char *p) + { + char **pp = (char **)p; + lock_mutex(); + *pp = first_free_; + first_free_ = p; + unlock_mutex(); + } +}; + +//############################################################################# + +/** A memory pool allocator. + + If a request arrives for allocating \c n bytes then it is first + rounded up to the nearest multiple of \c sizeof(void*) (this is \c + n_roundup), then one more \c sizeof(void*) is added to this + number. If the result is no more than maxpooled_ then + the appropriate pool is used to get a chunk of memory, if not, + then malloc is used. In either case, the size of the allocated + chunk is written into the first \c sizeof(void*) bytes and a + pointer pointing afterwards is returned. +*/ + +class CoinAlloc { +private: + CoinMempool *pool_; + int maxpooled_; + +public: + CoinAlloc(); + ~CoinAlloc() {} + + inline void *alloc(const std::size_t n) + { + if (maxpooled_ <= 0) { + return std::malloc(n); + } + char *p = NULL; + const std::size_t to_alloc = ((n + COINUTILS_MEMPOOL_ALIGNMENT - 1) & CoinAllocRoundMask) + COINUTILS_MEMPOOL_ALIGNMENT; + CoinMempool *pool = NULL; + if (maxpooled_ > 0 && to_alloc >= (size_t)maxpooled_) { + p = static_cast< char * >(std::malloc(to_alloc)); + if (p == NULL) + throw std::bad_alloc(); + } else { + pool = pool_ + (to_alloc >> CoinAllocPtrShift); + p = pool->alloc(); + } + *((CoinMempool **)p) = pool; + return static_cast< void * >(p + COINUTILS_MEMPOOL_ALIGNMENT); + } + + inline void dealloc(void *p) + { + if (maxpooled_ <= 0) { + std::free(p); + return; + } + if (p) { + char *base = static_cast< char * >(p) - COINUTILS_MEMPOOL_ALIGNMENT; + CoinMempool *pool = *((CoinMempool **)base); + if (!pool) { + std::free(base); + } else { + pool->dealloc(base); + } + } + } +}; + +extern CoinAlloc CoinAllocator; + +//############################################################################# + +#if defined(COINUTILS_MEMPOOL_OVERRIDE_NEW) && (COINUTILS_MEMPOOL_OVERRIDE_NEW == 1) +void *operator new(std::size_t size) throw(std::bad_alloc); +void *operator new[](std::size_t) throw(std::bad_alloc); +void operator delete(void *)throw(); +void operator delete[](void *) throw(); +void *operator new(std::size_t, const std::nothrow_t &) throw(); +void *operator new[](std::size_t, const std::nothrow_t &) throw(); +void operator delete(void *, const std::nothrow_t &)throw(); +void operator delete[](void *, const std::nothrow_t &) throw(); +#endif + +#endif /*(COINUTILS_MEMPOOL_MAXPOOLED >= 0)*/ +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinBuild.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinBuild.hpp new file mode 100644 index 000000000..8f3f6ba0d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinBuild.hpp @@ -0,0 +1,159 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinBuild_H +#define CoinBuild_H + +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" +#include "CoinFinite.hpp" + +/** + In many cases it is natural to build a model by adding one row at a time. In Coin this + is inefficient so this class gives some help. An instance of CoinBuild can be built up + more efficiently and then added to the Clp/OsiModel in one go. + + It may be more efficient to have fewer arrays and re-allocate them but this should + give a large gain over addRow. + + I have now extended it to columns. + +*/ + +class CoinBuild { + +public: + /**@name Useful methods */ + //@{ + /// add a row + void addRow(int numberInRow, const int *columns, + const double *elements, double rowLower = -COIN_DBL_MAX, + double rowUpper = COIN_DBL_MAX); + /// add a column + void addColumn(int numberInColumn, const int *rows, + const double *elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, double objectiveValue = 0.0); + /// add a column + inline void addCol(int numberInColumn, const int *rows, + const double *elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, double objectiveValue = 0.0) + { + addColumn(numberInColumn, rows, elements, columnLower, columnUpper, objectiveValue); + } + /// Return number of rows or maximum found so far + inline int numberRows() const + { + return (type_ == 0) ? numberItems_ : numberOther_; + } + /// Return number of columns or maximum found so far + inline int numberColumns() const + { + return (type_ == 1) ? numberItems_ : numberOther_; + } + /// Return number of elements + inline CoinBigIndex numberElements() const + { + return numberElements_; + } + /** Returns number of elements in a row and information in row + */ + int row(int whichRow, double &rowLower, double &rowUpper, + const int *&indices, const double *&elements) const; + /** Returns number of elements in current row and information in row + Used as rows may be stored in a chain + */ + int currentRow(double &rowLower, double &rowUpper, + const int *&indices, const double *&elements) const; + /// Set current row + void setCurrentRow(int whichRow); + /// Returns current row number + int currentRow() const; + /** Returns number of elements in a column and information in column + */ + int column(int whichColumn, + double &columnLower, double &columnUpper, double &objectiveValue, + const int *&indices, const double *&elements) const; + /** Returns number of elements in current column and information in column + Used as columns may be stored in a chain + */ + int currentColumn(double &columnLower, double &columnUpper, double &objectiveValue, + const int *&indices, const double *&elements) const; + /// Set current column + void setCurrentColumn(int whichColumn); + /// Returns current column number + int currentColumn() const; + /// Returns type + inline int type() const + { + return type_; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinBuild(); + /** Constructor with type 0==for addRow, 1== for addColumn. */ + CoinBuild(int type); + /** Destructor */ + ~CoinBuild(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinBuild(const CoinBuild &); + /// = + CoinBuild &operator=(const CoinBuild &); + //@} +private: + /// Set current + void setMutableCurrent(int which) const; + /// add a item + void addItem(int numberInItem, const int *indices, + const double *elements, + double itemLower, + double itemUpper, double objectiveValue); + /** Returns number of elements in a item and information in item + */ + int item(int whichItem, + double &itemLower, double &itemUpper, double &objectiveValue, + const int *&indices, const double *&elements) const; + /** Returns number of elements in current item and information in item + Used as items may be stored in a chain + */ + int currentItem(double &itemLower, double &itemUpper, double &objectiveValue, + const int *&indices, const double *&elements) const; + /// Set current item + void setCurrentItem(int whichItem); + /// Returns current item number + int currentItem() const; + +private: + /**@name Data members */ + //@{ + /// Current number of items + int numberItems_; + /// Current number of other dimension i.e. Columns if addRow (i.e. max) + int numberOther_; + /// Current number of elements + CoinBigIndex numberElements_; + /// Current item pointer + mutable double *currentItem_; + /// First item pointer + double *firstItem_; + /// Last item pointer + double *lastItem_; + /// Type of build - 0 for row, 1 for column, -1 unset + int type_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseFactorization.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseFactorization.hpp new file mode 100644 index 000000000..fc5e086a2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseFactorization.hpp @@ -0,0 +1,452 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + Authors + + John Forrest + + */ +#ifndef CoinDenseFactorization_H +#define CoinDenseFactorization_H + +#include +#include +#include +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinFactorization.hpp" +#if COIN_FACTORIZATION_DENSE_CODE == 2 +#undef COIN_FACTORIZATION_DENSE_CODE +#endif +class CoinPackedMatrix; +/// Abstract base class which also has some scalars so can be used from Dense or Simp +class CoinOtherFactorization { + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinOtherFactorization(); + /// Copy constructor + CoinOtherFactorization(const CoinOtherFactorization &other); + + /// Destructor + virtual ~CoinOtherFactorization(); + /// = copy + CoinOtherFactorization &operator=(const CoinOtherFactorization &other); + + /// Clone + virtual CoinOtherFactorization *clone() const = 0; + //@} + + /**@name general stuff such as status */ + //@{ + /// Returns status + inline int status() const + { + return status_; + } + /// Sets status + inline void setStatus(int value) + { + status_ = value; + } + /// Returns number of pivots since factorization + inline int pivots() const + { + return numberPivots_; + } + /// Sets number of pivots since factorization + inline void setPivots(int value) + { + numberPivots_ = value; + } + /// Set number of Rows after factorization + inline void setNumberRows(int value) + { + numberRows_ = value; + } + /// Number of Rows after factorization + inline int numberRows() const + { + return numberRows_; + } + /// Total number of columns in factorization + inline int numberColumns() const + { + return numberColumns_; + } + /// Number of good columns in factorization + inline int numberGoodColumns() const + { + return numberGoodU_; + } + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) + { + relaxCheck_ = value; + } + inline double getAccuracyCheck() const + { + return relaxCheck_; + } + /// Maximum number of pivots between factorizations + inline int maximumPivots() const + { + return maximumPivots_; + } + /// Set maximum pivots + virtual void maximumPivots(int value); + + /// Pivot tolerance + inline double pivotTolerance() const + { + return pivotTolerance_; + } + void pivotTolerance(double value); + /// Zero tolerance + inline double zeroTolerance() const + { + return zeroTolerance_; + } + void zeroTolerance(double value); +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + inline double slackValue() const + { + return slackValue_; + } + void slackValue(double value); +#endif + /// Returns array to put basis elements in + virtual CoinFactorizationDouble *elements() const; + /// Returns pivot row + virtual int *pivotRow() const; + /// Returns work area + virtual CoinFactorizationDouble *workArea() const; + /// Returns int work area + virtual int *intWorkArea() const; + /// Number of entries in each row + virtual int *numberInRow() const; + /// Number of entries in each column + virtual int *numberInColumn() const; + /// Returns array to put basis starts in + virtual int *starts() const; + /// Returns permute back + virtual int *permuteBack() const; + /** Get solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + inline int solveMode() const + { + return solveMode_; + } + /** Set solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + inline void setSolveMode(int value) + { + solveMode_ = value; + } + /// Returns true if wants tableauColumn in replaceColumn + virtual bool wantsTableauColumn() const; + /** Useful information for factorization + 0 - iteration number + whereFrom is 0 for factorize and 1 for replaceColumn + */ + virtual void setUsefulInformation(const int *info, int whereFrom); + /// Get rid of all memory + virtual void clearArrays() {} + //@} + /**@name virtual general stuff such as permutation */ + //@{ + /// Returns array to put basis indices in + virtual int *indices() const = 0; + /// Returns permute in + virtual int *permute() const = 0; + /// Total number of elements in factorization + virtual int numberElements() const = 0; + //@} + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas(int numberRows, + int numberColumns, + int maximumL, + int maximumU) + = 0; + + /// PreProcesses column ordered copy of basis + virtual void preProcess() = 0; + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor() = 0; + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int *sequence, int *pivotVariable) = 0; + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int *sequence, int numberColumns) = 0; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8) + = 0; + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) + = 0; + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const = 0; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermute = false) + = 0; + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const = 0; + //@} + + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Pivot tolerance + double pivotTolerance_; + /// Zero tolerance + double zeroTolerance_; +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + double slackValue_; +#else +#ifndef slackValue_ +#define slackValue_ -1.0 +#endif +#endif + /// Relax check on accuracy in replaceColumn + double relaxCheck_; + /// Number of elements after factorization + int factorElements_; + /// Number of Rows in factorization + int numberRows_; + /// Number of Columns in factorization + int numberColumns_; + /// Number factorized in U (not row singletons) + int numberGoodU_; + /// Maximum number of pivots before factorization + int maximumPivots_; + /// Number pivots since last factorization + int numberPivots_; + /// Status of factorization + int status_; + /// Maximum rows ever (i.e. use to copy arrays etc) + int maximumRows_; + /// Maximum length of iterating area + int maximumSpace_; + /// Pivot row + int *pivotRow_; + /** Elements of factorization and updates + length is maxR*maxR+maxSpace + will always be long enough so can have nR*nR ints in maxSpace + */ + CoinFactorizationDouble *elements_; + /// Work area of numberRows_ + CoinFactorizationDouble *workArea_; + /** Solve mode e.g. 0 C++ code, 1 Lapack, 2 choose + If 4 set then values pass + if 8 set then has iterated + */ + int solveMode_; + //@} +}; +/** This deals with Factorization and Updates + This is a simple dense version so other people can write a better one + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + +class CoinDenseFactorization : public CoinOtherFactorization { + friend void CoinDenseFactorizationUnitTest(const std::string &mpsDir); + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinDenseFactorization(); + /// Copy constructor + CoinDenseFactorization(const CoinDenseFactorization &other); + + /// Destructor + virtual ~CoinDenseFactorization(); + /// = copy + CoinDenseFactorization &operator=(const CoinDenseFactorization &other); + /// Clone + virtual CoinOtherFactorization *clone() const; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas(int numberRows, + int numberColumns, + int maximumL, + int maximumU); + + /// PreProcesses column ordered copy of basis + virtual void preProcess(); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor(); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int *sequence, int *pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int *sequence, int numberColumns); + //@} + + /**@name general stuff such as number of elements */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements() const + { + return numberRows_ * (numberColumns_ + numberPivots_); + } + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual inline int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool = false) + { + return updateColumn(regionSparse, regionSparse2); + } + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermute = false); + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { + gutsOfDestructor(); + } + /// Returns array to put basis indices in + virtual inline int *indices() const + { + return reinterpret_cast< int * >(elements_ + numberRows_ * numberRows_); + } + /// Returns permute in + virtual inline int *permute() const + { + return NULL; /*pivotRow_*/ + ; + } + //@} + + /// The real work of desstructor + void gutsOfDestructor(); + /// The real work of constructor + void gutsOfInitialize(); + /// The real work of copy + void gutsOfCopy(const CoinDenseFactorization &other); + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseVector.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseVector.hpp new file mode 100644 index 000000000..35557861c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDenseVector.hpp @@ -0,0 +1,401 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinDenseVector_H +#define CoinDenseVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include +#include +#include "CoinHelperFunctions.hpp" + +//############################################################################# +/** A function that tests the methods in the CoinDenseVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +template < typename T > +void CoinDenseVectorUnitTest(T dummy); + +//############################################################################# +/** Dense Vector + +Stores a dense (or expanded) vector of floating point values. +Type of vector elements is controlled by templating. +(Some working quantities such as accumulated sums +are explicitly declared of type double). This allows the +components of the vector integer, single or double precision. + +Here is a sample usage: +@verbatim + const int ne = 4; + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its value + CoinDenseVector r(ne,el); + + // access each element + assert( r.getElements()[0]==10. ); + assert( r.getElements()[1]==40. ); + assert( r.getElements()[2]== 1. ); + assert( r.getElements()[3]==50. ); + + // Test for equality + CoinDenseVector r1; + r1=r; + + // Add dense vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinDenseVector add = r + r1; + assert( add[0] == 10.+10. ); + assert( add[1] == 40.+40. ); + assert( add[2] == 1.+ 1. ); + assert( add[3] == 50.+50. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +template < typename T > +class CoinDenseVector { +private: + /**@name Private member data */ + //@{ + /// Size of element vector + int nElements_; + ///Vector elements + T *elements_; + //@} + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getNumElements() const { return nElements_; } + inline int size() const { return nElements_; } + /// Get element values + inline const T *getElements() const { return elements_; } + /// Get element values + inline T *getElements() { return elements_; } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Reset the vector (i.e. set all elemenets to zero) + void clear(); + /** Assignment operator */ + CoinDenseVector &operator=(const CoinDenseVector &); + /** Member of array operator */ + T &operator[](int index) const; + + /** Set vector size, and elements. + Size is the length of the elements vector. + The element vector is copied into this class instance's + member data. */ + void setVector(int size, const T *elems); + + /** Elements set to have the same scalar value */ + void setConstant(int size, T elems); + + /** Set an existing element in the dense vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, T element); + /** Resize the dense vector to be the first newSize elements. + If length is decreased, vector is truncated. If increased + new entries, set to new default element */ + void resize(int newSize, T fill = T()); + + /** Append a dense vector to this dense vector */ + void append(const CoinDenseVector &); + //@} + + /**@name norms, sum and scale */ + //@{ + /// 1-norm of vector + inline T oneNorm() const + { + T norm = 0; + for (int i = 0; i < nElements_; i++) + norm += CoinAbs(elements_[i]); + return norm; + } + /// 2-norm of vector + inline double twoNorm() const + { + double norm = 0.; + for (int i = 0; i < nElements_; i++) + norm += elements_[i] * elements_[i]; + // std namespace removed because it was causing a compile + // problem with Microsoft Visual C++ + return /*std::*/ sqrt(norm); + } + /// infinity-norm of vector + inline T infNorm() const + { + T norm = 0; + for (int i = 0; i < nElements_; i++) + norm = CoinMax(norm, CoinAbs(elements_[i])); + return norm; + } + /// sum of vector elements + inline T sum() const + { + T sume = 0; + for (int i = 0; i < nElements_; i++) + sume += elements_[i]; + return sume; + } + /// scale vector elements + inline void scale(T factor) + { + for (int i = 0; i < nElements_; i++) + elements_[i] *= factor; + return; + } + //@} + + /**@name Arithmetic operators. */ + //@{ + /// add value to every entry + void operator+=(T value); + /// subtract value from every entry + void operator-=(T value); + /// multiply every entry by value + void operator*=(T value); + /// divide every entry by value + void operator/=(T value); + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinDenseVector(); + /** Alternate Constructors - set elements to vector of Ts */ + CoinDenseVector(int size, const T *elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinDenseVector(int size, T element = T()); + /** Copy constructors */ + CoinDenseVector(const CoinDenseVector &); + + /** Destructor */ + ~CoinDenseVector(); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfSetVector(int size, const T *elems); + /// Set all elements to a given value + void gutsOfSetConstant(int size, T value); + //@} +}; + +//############################################################################# + +/**@name Arithmetic operators on dense vectors. + + NOTE: Because these methods return an object (they can't + return a reference, though they could return a pointer...) they are + very inefficient... + */ +//@{ +/// Return the sum of two dense vectors +template < typename T > +inline CoinDenseVector< T > operator+(const CoinDenseVector< T > &op1, + const CoinDenseVector< T > &op2) +{ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] + elements2[i]; + return op3; +} + +/// Return the difference of two dense vectors +template < typename T > +inline CoinDenseVector< T > operator-(const CoinDenseVector< T > &op1, + const CoinDenseVector< T > &op2) +{ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] - elements2[i]; + return op3; +} + +/// Return the element-wise product of two dense vectors +template < typename T > +inline CoinDenseVector< T > operator*(const CoinDenseVector< T > &op1, + const CoinDenseVector< T > &op2) +{ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] * elements2[i]; + return op3; +} + +/// Return the element-wise ratio of two dense vectors +template < typename T > +inline CoinDenseVector< T > operator/(const CoinDenseVector< T > &op1, + const CoinDenseVector< T > &op2) +{ + assert(op1.size() == op2.size()); + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + const T *elements2 = op2.getElements(); + T *elements3 = op3.getElements(); + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] / elements2[i]; + return op3; +} +//@} + +/**@name Arithmetic operators on dense vector and a constant. + These functions create a dense vector as a result. That dense vector will + have the same indices as op1 and the specified operation is + done entry-wise with the given value. */ +//@{ +/// Return the sum of a dense vector and a constant +template < typename T > +inline CoinDenseVector< T > operator+(const CoinDenseVector< T > &op1, T value) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] + dvalue; + return op3; +} + +/// Return the difference of a dense vector and a constant +template < typename T > +inline CoinDenseVector< T > operator-(const CoinDenseVector< T > &op1, T value) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] - dvalue; + return op3; +} + +/// Return the element-wise product of a dense vector and a constant +template < typename T > +inline CoinDenseVector< T > operator*(const CoinDenseVector< T > &op1, T value) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] * dvalue; + return op3; +} + +/// Return the element-wise ratio of a dense vector and a constant +template < typename T > +inline CoinDenseVector< T > operator/(const CoinDenseVector< T > &op1, T value) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] / dvalue; + return op3; +} + +/// Return the sum of a constant and a dense vector +template < typename T > +inline CoinDenseVector< T > operator+(T value, const CoinDenseVector< T > &op1) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] + dvalue; + return op3; +} + +/// Return the difference of a constant and a dense vector +template < typename T > +inline CoinDenseVector< T > operator-(T value, const CoinDenseVector< T > &op1) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = dvalue - elements1[i]; + return op3; +} + +/// Return the element-wise product of a constant and a dense vector +template < typename T > +inline CoinDenseVector< T > operator*(T value, const CoinDenseVector< T > &op1) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = elements1[i] * dvalue; + return op3; +} + +/// Return the element-wise ratio of a a constant and dense vector +template < typename T > +inline CoinDenseVector< T > operator/(T value, const CoinDenseVector< T > &op1) +{ + int size = op1.size(); + CoinDenseVector< T > op3(size); + const T *elements1 = op1.getElements(); + T *elements3 = op3.getElements(); + double dvalue = value; + for (int i = 0; i < size; i++) + elements3[i] = dvalue / elements1[i]; + return op3; +} +//@} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDistance.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDistance.hpp new file mode 100644 index 000000000..bcf9cc3bd --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinDistance.hpp @@ -0,0 +1,51 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinDistance_H +#define CoinDistance_H + +#include + +//------------------------------------------------------------------- +// +// Attempt to provide an std::distance function +// that will work on multiple platforms +// +//------------------------------------------------------------------- + +/** CoinDistance + +This is the Coin implementation of the std::function that is +designed to work on multiple platforms. +*/ +template < class ForwardIterator, class Distance > +void coinDistance(ForwardIterator first, ForwardIterator last, + Distance &n) +{ +#if defined(__SUNPRO_CC) + n = 0; + std::distance(first, last, n); +#else + n = std::distance(first, last); +#endif +} + +template < class ForwardIterator > +size_t coinDistance(ForwardIterator first, ForwardIterator last) +{ + size_t retVal; +#if defined(__SUNPRO_CC) + retVal = 0; + std::distance(first, last, retVal); +#else + retVal = std::distance(first, last); +#endif + return retVal; +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinError.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinError.hpp new file mode 100644 index 000000000..909baacd9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinError.hpp @@ -0,0 +1,274 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinError_H +#define CoinError_H + +#include +#include +#include +#include + +#include "CoinUtilsConfig.h" +#include "CoinPragma.hpp" + +/** A function to block the popup windows that windows creates when the code + crashes */ +void WindowsErrorPopupBlocker(); + +//------------------------------------------------------------------- +// +// Error class used to throw exceptions +// +// Errors contain: +// +//------------------------------------------------------------------- + +/** Error Class thrown by an exception + +This class is used when exceptions are thrown. +It contains: +
    +
  • message text +
  • name of method throwing exception +
  • name of class throwing exception or hint +
  • name of file if assert +
  • line number +
+ For asserts class=> optional hint +*/ +class CoinError { + friend void CoinErrorUnitTest(); + +private: + CoinError() + : message_() + , method_() + , class_() + , file_() + , lineNumber_() + { + // nothing to do here + } + +public: + //------------------------------------------------------------------- + // Get methods + //------------------------------------------------------------------- + /**@name Get error attributes */ + //@{ + /// get message text + inline const std::string &message() const + { + return message_; + } + /// get name of method instantiating error + inline const std::string &methodName() const + { + return method_; + } + /// get name of class instantiating error (or hint for assert) + inline const std::string &className() const + { + return class_; + } + /// get name of file for assert + inline const std::string &fileName() const + { + return file_; + } + /// get line number of assert (-1 if not assert) + inline int lineNumber() const + { + return lineNumber_; + } + /// Just print (for asserts) + inline void print(bool doPrint = true) const + { + if (!doPrint) + return; + if (lineNumber_ < 0) { + std::cout << message_ << " in " << class_ << "::" << method_ << std::endl; + } else { + std::cout << file_ << ":" << lineNumber_ << " method " << method_ + << " : assertion \'" << message_ << "\' failed." << std::endl; + if (class_ != "") + std::cout << "Possible reason: " << class_ << std::endl; + } + } + //@} + + /**@name Constructors and destructors */ + //@{ + /// Alternate Constructor + CoinError( + std::string message__, + std::string methodName__, + std::string className__, + std::string fileName_ = std::string(), + int line = -1) + : message_(message__) + , method_(methodName__) + , class_(className__) + , file_(fileName_) + , lineNumber_(line) + { + print(printErrors_); + } + + /// Copy constructor + CoinError(const CoinError &source) + : message_(source.message_) + , method_(source.method_) + , class_(source.class_) + , file_(source.file_) + , lineNumber_(source.lineNumber_) + { + // nothing to do here + } + + /// Assignment operator + CoinError &operator=(const CoinError &rhs) + { + if (this != &rhs) { + message_ = rhs.message_; + method_ = rhs.method_; + class_ = rhs.class_; + file_ = rhs.file_; + lineNumber_ = rhs.lineNumber_; + } + return *this; + } + + /// Destructor + virtual ~CoinError() + { + // nothing to do here + } + //@} + +private: + /**@name Private member data */ + //@{ + /// message test + std::string message_; + /// method name + std::string method_; + /// class name or hint + std::string class_; + /// file name + std::string file_; + /// Line number + int lineNumber_; + //@} + +public: + /// Whether to print every error + static bool printErrors_; +}; + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef __GNUC_PREREQ +#define __GNUC_PREREQ(maj, min) (0) +#endif + +#ifndef COIN_ASSERT +#define CoinAssertDebug(expression) assert(expression) +#define CoinAssertDebugHint(expression, hint) assert(expression) +#define CoinAssert(expression) assert(expression) +#define CoinAssertHint(expression, hint) assert(expression) +#else +#ifdef NDEBUG +#define CoinAssertDebug(expression) \ + { \ + } +#define CoinAssertDebugHint(expression, hint) \ + { \ + } +#else +#if defined(__GNUC__) && __GNUC_PREREQ(2, 6) +#define CoinAssertDebug(expression) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + "", __FILE__, __LINE__); \ + } \ + } +#define CoinAssertDebugHint(expression, hint) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + hint, __FILE__, __LINE__); \ + } \ + } +#else +#define CoinAssertDebug(expression) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + "", __FILE__, __LINE__); \ + } \ + } +#define CoinAssertDebugHint(expression, hint) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + hint, __FILE__, __LINE__); \ + } \ + } +#endif +#endif +#if defined(__GNUC__) && __GNUC_PREREQ(2, 6) +#define CoinAssert(expression) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + "", __FILE__, __LINE__); \ + } \ + } +#define CoinAssertHint(expression, hint) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), __PRETTY_FUNCTION__, \ + hint, __FILE__, __LINE__); \ + } \ + } +#else +#define CoinAssert(expression) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + "", __FILE__, __LINE__); \ + } \ + } +#define CoinAssertHint(expression, hint) \ + { \ + if (!(expression)) { \ + throw CoinError(__STRING(expression), "", \ + hint, __FILE__, __LINE__); \ + } \ + } +#endif +#endif + +//############################################################################# +/** A function that tests the methods in the CoinError class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CoinErrorUnitTest(); + +#ifdef __LINE__ +#define CoinErrorFL(x, y, z) CoinError((x), (y), (z), __FILE__, __LINE__) +#endif + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFactorization.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFactorization.hpp new file mode 100644 index 000000000..3bc803a4d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFactorization.hpp @@ -0,0 +1,2178 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + Authors + + John Forrest + + */ +#ifndef CoinFactorization_H +#define CoinFactorization_H +#define EXTRA_U_SPACE 4 +//#define COIN_ONE_ETA_COPY 100 + +#include +#include +#include +#include +#include +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" + +class CoinPackedMatrix; +/** This deals with Factorization and Updates + + This class started with a parallel simplex code I was writing in the + mid 90's. The need for parallelism led to many complications and + I have simplified as much as I could to get back to this. + + I was aiming at problems where I might get speed-up so I was looking at dense + problems or ones with structure. This led to permuting input and output + vectors and to increasing the number of rows each rank-one update. This is + still in as a minor overhead. + + I have also put in handling for hyper-sparsity. I have taken out + all outer loop unrolling, dense matrix handling and most of the + book-keeping for slacks. Also I always use FTRAN approach to updating + even if factorization fairly dense. All these could improve performance. + + I blame some of the coding peculiarities on the history of the code + but mostly it is just because I can't do elegant code (or useful + comments). + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + +class CoinFactorization { + friend void CoinFactorizationUnitTest(const std::string &mpsDir); + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinFactorization(); + /// Copy constructor + CoinFactorization(const CoinFactorization &other); + + /// Destructor + ~CoinFactorization(); + /// Delete all stuff (leaves as after CoinFactorization()) + void almostDestructor(); + /// Debug show object (shows one representation) + void show_self() const; + /// Debug - save on file - 0 if no error + int saveFactorization(const char *file) const; + /** Debug - restore from file - 0 if no error on file. + If factor true then factorizes as if called from ClpFactorization + */ + int restoreFactorization(const char *file, bool factor = false); + /// Debug - sort so can compare + void sort() const; + /// = copy + CoinFactorization &operator=(const CoinFactorization &other); + //@} + + /**@name Do factorization */ + //@{ + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize(const CoinPackedMatrix &matrix, + int rowIsBasic[], int columnIsBasic[], + double areaFactor = 0.0); + /** When given as triplets. + Actually does factorization. maximumL is guessed maximum size of L part of + final factorization, maximumU of U part. These are multiplied by + areaFactor which can be computed by user or internally. + Arrays are copied in. I could add flag to delete arrays to save a + bit of memory. + If status okay, permutation has pivot rows - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -99 memory */ + int factorize(int numberRows, + int numberColumns, + int numberElements, + int maximumL, + int maximumU, + const int indicesRow[], + const int indicesColumn[], const double elements[], + int permutation[], + double areaFactor = 0.0); + /** Two part version for maximum flexibility + This part creates arrays for user to fill. + estimateNumberElements is safe estimate of number + returns 0 -okay, -99 memory */ + int factorizePart1(int numberRows, + int numberColumns, + int estimateNumberElements, + int *indicesRow[], + int *indicesColumn[], + CoinFactorizationDouble *elements[], + double areaFactor = 0.0); + /** This is part two of factorization + Arrays belong to factorization and were returned by part 1 + If status okay, permutation has pivot rows - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -99 memory */ + int factorizePart2(int permutation[], int exactNumberElements); + /// Condition number - product of pivots after factorization + double conditionNumber() const; + + //@} + + /**@name general stuff such as permutation or status */ + //@{ + /// Returns status + inline int status() const + { + return status_; + } + /// Sets status + inline void setStatus(int value) + { + status_ = value; + } + /// Returns number of pivots since factorization + inline int pivots() const + { + return numberPivots_; + } + /// Sets number of pivots since factorization + inline void setPivots(int value) + { + numberPivots_ = value; + } + /// Returns address of permute region + inline int *permute() const + { + return permute_.array(); + } + /// Returns address of pivotColumn region (also used for permuting) + inline int *pivotColumn() const + { + return pivotColumn_.array(); + } + /// Returns address of pivot region + inline CoinFactorizationDouble *pivotRegion() const + { + return pivotRegion_.array(); + } + /// Returns address of permuteBack region + inline int *permuteBack() const + { + return permuteBack_.array(); + } + /// Returns address of lastRow region + inline int *lastRow() const + { + return lastRow_.array(); + } + /** Returns address of pivotColumnBack region (also used for permuting) + Now uses firstCount to save memory allocation */ + inline int *pivotColumnBack() const + { + //return firstCount_.array(); + return pivotColumnBack_.array(); + } + /// Start of each row in L + inline int *startRowL() const + { + return startRowL_.array(); + } + + /// Start of each column in L + inline int *startColumnL() const + { + return startColumnL_.array(); + } + + /// Index of column in row for L + inline int *indexColumnL() const + { + return indexColumnL_.array(); + } + + /// Row indices of L + inline int *indexRowL() const + { + return indexRowL_.array(); + } + + /// Elements in L (row copy) + inline CoinFactorizationDouble *elementByRowL() const + { + return elementByRowL_.array(); + } + + /// Number of Rows after iterating + inline int numberRowsExtra() const + { + return numberRowsExtra_; + } + /// Set number of Rows after factorization + inline void setNumberRows(int value) + { + numberRows_ = value; + } + /// Number of Rows after factorization + inline int numberRows() const + { + return numberRows_; + } + /// Number in L + inline int numberL() const + { + return numberL_; + } + + /// Base of L + inline int baseL() const + { + return baseL_; + } + /// Maximum of Rows after iterating + inline int maximumRowsExtra() const + { + return maximumRowsExtra_; + } + /// Total number of columns in factorization + inline int numberColumns() const + { + return numberColumns_; + } + /// Total number of elements in factorization + inline int numberElements() const + { + return totalElements_; + } + /// Length of FT vector + inline int numberForrestTomlin() const + { + return numberInColumn_.array()[numberColumnsExtra_]; + } + /// Number of good columns in factorization + inline int numberGoodColumns() const + { + return numberGoodU_; + } + /// Whether larger areas needed + inline double areaFactor() const + { + return areaFactor_; + } + inline void areaFactor(double value) + { + areaFactor_ = value; + } + /// Returns areaFactor but adjusted for dense + double adjustedAreaFactor() const; + /// Allows change of pivot accuracy check 1.0 == none >1.0 relaxed + inline void relaxAccuracyCheck(double value) + { + relaxCheck_ = value; + } + inline double getAccuracyCheck() const + { + return relaxCheck_; + } + /// Level of detail of messages + inline int messageLevel() const + { + return messageLevel_; + } + void messageLevel(int value); + /// Maximum number of pivots between factorizations + inline int maximumPivots() const + { + return maximumPivots_; + } + void maximumPivots(int value); + + /// Gets dense threshold + inline int denseThreshold() const + { + return denseThreshold_; + } + /// Sets dense threshold + inline void setDenseThreshold(int value) + { + denseThreshold_ = value; + } + /// Pivot tolerance + inline double pivotTolerance() const + { + return pivotTolerance_; + } + void pivotTolerance(double value); + /// Zero tolerance + inline double zeroTolerance() const + { + return zeroTolerance_; + } + void zeroTolerance(double value); +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + inline double slackValue() const + { + return slackValue_; + } + void slackValue(double value); +#endif + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + /// true if Forrest Tomlin update, false if PFI + inline bool forrestTomlin() const + { + return doForrestTomlin_; + } + inline void setForrestTomlin(bool value) + { + doForrestTomlin_ = value; + } + /// True if FT update and space + inline bool spaceForForrestTomlin() const + { + int start = startColumnU_.array()[maximumColumnsExtra_]; + int space = lengthAreaU_ - (start + numberRowsExtra_); + return (space >= 0) && doForrestTomlin_; + } + //@} + + /**@name some simple stuff */ + //@{ + + /// Returns number of dense rows + inline int numberDense() const + { + return numberDense_; + } + + /// Returns number in U area + inline int numberElementsU() const + { + return lengthU_; + } + /// Setss number in U area + inline void setNumberElementsU(int value) + { + lengthU_ = value; + } + /// Returns length of U area + inline int lengthAreaU() const + { + return lengthAreaU_; + } + /// Returns number in L area + inline int numberElementsL() const + { + return lengthL_; + } + /// Returns length of L area + inline int lengthAreaL() const + { + return lengthAreaL_; + } + /// Returns number in R area + inline int numberElementsR() const + { + return lengthR_; + } + /// Number of compressions done + inline int numberCompressions() const + { + return numberCompressions_; + } + /// Number of entries in each row + inline int *numberInRow() const + { + return numberInRow_.array(); + } + /// Number of entries in each column + inline int *numberInColumn() const + { + return numberInColumn_.array(); + } + /// Elements of U + inline CoinFactorizationDouble *elementU() const + { + return elementU_.array(); + } + /// Row indices of U + inline int *indexRowU() const + { + return indexRowU_.array(); + } + /// Start of each column in U + inline int *startColumnU() const + { + return startColumnU_.array(); + } + /// Maximum number of Columns after iterating + inline int maximumColumnsExtra() + { + return maximumColumnsExtra_; + } + /** L to U bias + 0 - U bias, 1 - some U bias, 2 some L bias, 3 L bias + */ + inline int biasLU() const + { + return biasLU_; + } + inline void setBiasLU(int value) + { + biasLU_ = value; + } + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + inline int persistenceFlag() const + { + return persistenceFlag_; + } + void setPersistenceFlag(int value); + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + int replaceColumn(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); + /** Combines BtranU and delete elements + If deleted is NULL then delete elements + otherwise store where elements are + */ + void replaceColumnU(CoinIndexedVector *regionSparse, + int *deleted, + int internalPivotRow); +#ifdef ABC_USE_COIN_FACTORIZATION + /** returns empty fake vector carved out of existing + later - maybe use associated arrays */ + CoinIndexedVector *fakeVector(CoinIndexedVector *vector, + int already = 0) const; + void deleteFakeVector(CoinIndexedVector *vector, + CoinIndexedVector *fakeVector) const; + /** Checks if can replace one Column to basis, + returns update alpha + Fills in region for use later + partial update already in U */ + double checkReplacePart1(CoinIndexedVector *regionSparse, + int pivotRow); + /** Checks if can replace one Column to basis, + returns update alpha + Fills in region for use later + partial update in vector */ + double checkReplacePart1(CoinIndexedVector *regionSparse, + CoinIndexedVector *partialUpdate, + int pivotRow); + /** Checks if can replace one Column in basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room, 5 max pivots */ + int checkReplacePart2(int pivotRow, + double btranAlpha, + double ftranAlpha, + double ftAlpha, + double acceptablePivot = 1.0e-8); + /** Replaces one Column to basis, + partial update already in U */ + void replaceColumnPart3(CoinIndexedVector *regionSparse, + int pivotRow, + double alpha); + /** Replaces one Column to basis, + partial update in vector */ + void replaceColumnPart3(CoinIndexedVector *regionSparse, + CoinIndexedVector *partialUpdate, + int pivotRow, + double alpha); + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + long regions + */ + int updateColumnFT(CoinIndexedVector ®ionSparse); + int updateColumnFTPart1(CoinIndexedVector ®ionSparse); + void updateColumnFTPart2(CoinIndexedVector ®ionSparse); + /** Updates one column (FTRAN) - long region + Tries to do FT update + puts partial update in vector */ + void updateColumnFT(CoinIndexedVector ®ionSparseFT, + CoinIndexedVector &partialUpdate, + int which); + /** Updates one column (FTRAN) long region */ + int updateColumn(CoinIndexedVector ®ionSparse) const; + /** Updates one column (FTRAN) from regionFT + Tries to do FT update + number returned is negative if no room. + Also updates regionOther - long region*/ + int updateTwoColumnsFT(CoinIndexedVector ®ionSparseFT, + CoinIndexedVector ®ionSparseOther); + /** Updates one column (BTRAN) - long region*/ + int updateColumnTranspose(CoinIndexedVector ®ionSparse) const; + /** Updates one column (FTRAN) - long region */ + void updateColumnCpu(CoinIndexedVector ®ionSparse, int whichCpu) const; + /** Updates one column (BTRAN) - long region */ + void updateColumnTransposeCpu(CoinIndexedVector ®ionSparse, int whichCpu) const; + /** Updates one full column (FTRAN) - long region */ + void updateFullColumn(CoinIndexedVector ®ionSparse) const; + /** Updates one full column (BTRAN) - long region */ + void updateFullColumnTranspose(CoinIndexedVector ®ionSparse) const; + /** Updates one column for dual steepest edge weights (FTRAN) - long region */ + void updateWeights(CoinIndexedVector ®ionSparse) const; + /// Returns true if wants tableauColumn in replaceColumn + inline bool wantsTableauColumn() const + { + return false; + } + /// Pivot tolerance + inline double minimumPivotTolerance() const + { + return pivotTolerance_; + } + inline void minimumPivotTolerance(double value) + { + pivotTolerance(value); + } + /// Says parallel + inline void setParallelMode(int value) + { + parallelMode_ = value; + } + /// Sets solve mode + inline void setSolveMode(int value) + { + parallelMode_ &= 3; + parallelMode_ |= (value << 2); + } + /// Sets solve mode + inline int solveMode() const + { + return parallelMode_ >> 2; + } + /// Update partial Ftran by R update + void updatePartialUpdate(CoinIndexedVector &partialUpdate); + /// Makes a non-singular basis by replacing variables + void makeNonSingular(int *COIN_RESTRICT sequence); +#endif +#if ABOCA_LITE_FACTORIZATION + /// Does btranU part of replaceColumn (skipping entries) + void replaceColumn1(CoinIndexedVector *regionSparse, int pivotRow); + /// Does replaceColumn - having already done btranU + int replaceColumn2(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck); +#endif + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2); + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /** Updates one column (FTRAN) from region2 + Tries to do FT update + number returned is negative if no room. + Also updates region3 + region1 starts as zero and is zero at end */ + int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermuteRegion3 = false); + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + /// Part of twocolumnsTranspose + void updateOneColumnTranspose(CoinIndexedVector *regionWork, int &statistics) const; + /** Updates two columns (BTRAN) from regionSparse2 and 3 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output - same for 3 + */ + void updateTwoColumnsTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + int type) const; + /** makes a row copy of L for speed and to allow very sparse problems */ + void goSparse(); + /** get sparse threshold */ + inline int sparseThreshold() const + { + return sparseThreshold_; + } + /** set sparse threshold */ + void sparseThreshold(int value); + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization (return code number elements) + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { + gutsOfDestructor(); + } + //@} + + /**@name various updates - none of which have been written! */ + //@{ + + /** Adds given elements to Basis and updates factorization, + can increase size of basis. Returns rank */ + int add(int numberElements, + int indicesRow[], + int indicesColumn[], double elements[]); + + /** Adds one Column to basis, + can increase size of basis. Returns rank */ + int addColumn(int numberElements, + int indicesRow[], double elements[]); + + /** Adds one Row to basis, + can increase size of basis. Returns rank */ + int addRow(int numberElements, + int indicesColumn[], double elements[]); + + /// Deletes one Column from basis, returns rank + int deleteColumn(int Row); + /// Deletes one Row from basis, returns rank + int deleteRow(int Row); + + /** Replaces one Row in basis, + At present assumes just a singleton on row is in basis + returns 0=OK, 1=Probably OK, 2=singular, 3 no space */ + int replaceRow(int whichRow, int numberElements, + const int indicesColumn[], const double elements[]); + /// Takes out all entries for given rows + void emptyRows(int numberToEmpty, const int which[]); + //@} + /**@name used by ClpFactorization */ + /// See if worth going sparse + void checkSparse(); + /// For statistics +#if 0 //def CLP_FACTORIZATION_INSTRUMENT + inline bool collectStatistics() const + { return collectStatistics_;} + /// For statistics + inline void setCollectStatistics(bool onOff) const + { collectStatistics_ = onOff;} +#else + inline bool collectStatistics() const + { + return true; + } + /// For statistics + inline void setCollectStatistics(bool onOff) const + { + } +#endif + /// The real work of constructors etc 0 just scalars, 1 bit normal + void gutsOfDestructor(int type = 1); + /// 1 bit - tolerances etc, 2 more, 4 dummy arrays + void gutsOfInitialize(int type); + void gutsOfCopy(const CoinFactorization &other); + + /// Reset all sparsity etc statistics + void resetStatistics(); + + //@} + + /**@name used by factorization */ + /// Gets space for a factorization, called by constructors + void getAreas(int numberRows, + int numberColumns, + int maximumL, + int maximumU); + + /** PreProcesses raw triplet data. + state is 0 - triplets, 1 - some counts etc , 2 - .. */ + void preProcess(int state, + int possibleDuplicates = -1); + /// Does most of factorization + int factor(); + +protected: + /** Does sparse phase of factorization + return code is <0 error, 0= finished */ + int factorSparse(); + /** Does sparse phase of factorization (for smaller problems) + return code is <0 error, 0= finished */ + int factorSparseSmall(); + /** Does sparse phase of factorization (for larger problems) + return code is <0 error, 0= finished */ + int factorSparseLarge(); + /** Does dense phase of factorization + return code is <0 error, 0= finished */ + int factorDense(); + + /// Pivots when just one other row so faster? + bool pivotOneOtherRow(int pivotRow, + int pivotColumn); + /// Does one pivot on Row Singleton in factorization + bool pivotRowSingleton(int pivotRow, + int pivotColumn); + /// Does one pivot on Column Singleton in factorization + bool pivotColumnSingleton(int pivotRow, + int pivotColumn); + + /** Gets space for one Column with given length, + may have to do compression (returns True if successful), + also moves existing vector, + extraNeeded is over and above present */ + bool getColumnSpace(int iColumn, + int extraNeeded); + + /** Reorders U so contiguous and in order (if there is space) + Returns true if it could */ + bool reorderU(); + /** getColumnSpaceIterateR. Gets space for one extra R element in Column + may have to do compression (returns true) + also moves existing vector */ + bool getColumnSpaceIterateR(int iColumn, double value, + int iRow); + /** getColumnSpaceIterate. Gets space for one extra U element in Column + may have to do compression (returns true) + also moves existing vector. + Returns -1 if no memory or where element was put + Used by replaceRow (turns off R version) */ + int getColumnSpaceIterate(int iColumn, double value, + int iRow); + /** Gets space for one Row with given length, + may have to do compression (returns True if successful), + also moves existing vector */ + bool getRowSpace(int iRow, int extraNeeded); + + /** Gets space for one Row with given length while iterating, + may have to do compression (returns True if successful), + also moves existing vector */ + bool getRowSpaceIterate(int iRow, + int extraNeeded); + /// Checks that row and column copies look OK + void checkConsistency(); + /// Adds a link in chain of equal counts + inline void addLink(int index, int count) + { + int *nextCount = nextCount_.array(); + int *firstCount = firstCount_.array(); + int *lastCount = lastCount_.array(); + int next = firstCount[count]; + lastCount[index] = -2 - count; + if (next < 0) { + //first with that count + firstCount[count] = index; + nextCount[index] = -1; + } else { + firstCount[count] = index; + nextCount[index] = next; + lastCount[next] = index; + } + } + /// Deletes a link in chain of equal counts + inline void deleteLink(int index) + { + int *nextCount = nextCount_.array(); + int *firstCount = firstCount_.array(); + int *lastCount = lastCount_.array(); + int next = nextCount[index]; + int last = lastCount[index]; + if (last >= 0) { + nextCount[last] = next; + } else { + int count = -last - 2; + + firstCount[count] = next; + } + if (next >= 0) { + lastCount[next] = last; + } + nextCount[index] = -2; + lastCount[index] = -2; + return; + } + /// Separate out links with same row/column count + void separateLinks(int count, bool rowsFirst); + /// Cleans up at end of factorization + void cleanup(); + + /// Updates part of column (FTRANL) + void updateColumnL(CoinIndexedVector *region, int *indexIn) const; + /// Updates part of column (FTRANL) when densish + void updateColumnLDensish(CoinIndexedVector *region, int *indexIn) const; + /// Updates part of column (FTRANL) when sparse + void updateColumnLSparse(CoinIndexedVector *region, int *indexIn) const; + /// Updates part of column (FTRANL) when sparsish + void updateColumnLSparsish(CoinIndexedVector *region, int *indexIn) const; + + /// Updates part of column (FTRANR) without FT update + void updateColumnR(CoinIndexedVector *region) const; + /** Updates part of column (FTRANR) with FT update. + Also stores update after L and R */ + void updateColumnRFT(CoinIndexedVector *region, int *indexIn); + + /// Updates part of column (FTRANU) + void updateColumnU(CoinIndexedVector *region, int *indexIn) const; + + /// Updates part of column (FTRANU) when sparse + void updateColumnUSparse(CoinIndexedVector *regionSparse, + int *indexIn) const; + /// Updates part of column (FTRANU) when sparsish + void updateColumnUSparsish(CoinIndexedVector *regionSparse, + int *indexIn) const; + /// Updates part of column (FTRANU) + int updateColumnUDensish(double *COIN_RESTRICT region, + int *COIN_RESTRICT regionIndex) const; + /// Updates part of 2 columns (FTRANU) real work + void updateTwoColumnsUDensish( + int &numberNonZero1, + double *COIN_RESTRICT region1, + int *COIN_RESTRICT index1, + int &numberNonZero2, + double *COIN_RESTRICT region2, + int *COIN_RESTRICT index2) const; + /// Updates part of column PFI (FTRAN) (after rest) + void updateColumnPFI(CoinIndexedVector *regionSparse) const; + /// Permutes back at end of updateColumn + void permuteBack(CoinIndexedVector *regionSparse, + CoinIndexedVector *outVector) const; + + /// Updates part of column transpose PFI (BTRAN) (before rest) + void updateColumnTransposePFI(CoinIndexedVector *region) const; + /** Updates part of column transpose (BTRANU), + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeU(CoinIndexedVector *region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when sparsish, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUSparsish(CoinIndexedVector *region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when densish, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUDensish(CoinIndexedVector *region, + int smallestIndex) const; + /** Updates part of column transpose (BTRANU) when sparse, + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUSparse(CoinIndexedVector *region) const; + /** Updates part of column transpose (BTRANU) by column + assumes index is sorted i.e. region is correct */ + void updateColumnTransposeUByColumn(CoinIndexedVector *region, + int smallestIndex) const; + + /// Updates part of column transpose (BTRANR) + void updateColumnTransposeR(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANR) when dense + void updateColumnTransposeRDensish(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANR) when sparse + void updateColumnTransposeRSparse(CoinIndexedVector *region) const; + + /// Updates part of column transpose (BTRANL) + void updateColumnTransposeL(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANL) when densish by column + void updateColumnTransposeLDensish(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANL) when densish by row + void updateColumnTransposeLByRow(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANL) when sparsish by row + void updateColumnTransposeLSparsish(CoinIndexedVector *region) const; + /// Updates part of column transpose (BTRANL) when sparse (by Row) + void updateColumnTransposeLSparse(CoinIndexedVector *region) const; + +public: + /** Replaces one Column to basis for PFI + returns 0=OK, 1=Probably OK, 2=singular, 3=no room. + In this case region is not empty - it is incoming variable (updated) + */ + int replaceColumnPFI(CoinIndexedVector *regionSparse, + int pivotRow, double alpha); + +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; + /********************************* START LARGE TEMPLATE ********/ +#ifdef INT_IS_8 +#define COINFACTORIZATION_BITS_PER_INT 64 +#define COINFACTORIZATION_SHIFT_PER_INT 6 +#define COINFACTORIZATION_MASK_PER_INT 0x3f +#else +#define COINFACTORIZATION_BITS_PER_INT 32 +#define COINFACTORIZATION_SHIFT_PER_INT 5 +#define COINFACTORIZATION_MASK_PER_INT 0x1f +#endif + template < class T > + inline bool + pivot(int pivotRow, + int pivotColumn, + int pivotRowPosition, + int pivotColumnPosition, + CoinFactorizationDouble work[], + unsigned int workArea2[], + int increment2, + T markRow[], + int largeInteger) + { + int *indexColumnU = indexColumnU_.array(); + int *startColumnU = startColumnU_.array(); + int *numberInColumn = numberInColumn_.array(); + CoinFactorizationDouble *elementU = elementU_.array(); + int *indexRowU = indexRowU_.array(); + int *startRowU = startRowU_.array(); + int *numberInRow = numberInRow_.array(); + CoinFactorizationDouble *elementL = elementL_.array(); + int *indexRowL = indexRowL_.array(); + int *saveColumn = saveColumn_.array(); + int *nextRow = nextRow_.array(); + int *lastRow = lastRow_.array(); + + //store pivot columns (so can easily compress) + int numberInPivotRow = numberInRow[pivotRow] - 1; + int startColumn = startColumnU[pivotColumn]; + int numberInPivotColumn = numberInColumn[pivotColumn] - 1; + int endColumn = startColumn + numberInPivotColumn + 1; + int put = 0; + int startRow = startRowU[pivotRow]; + int endRow = startRow + numberInPivotRow + 1; + + if (pivotColumnPosition < 0) { + for (pivotColumnPosition = startRow; pivotColumnPosition < endRow; pivotColumnPosition++) { + int iColumn = indexColumnU[pivotColumnPosition]; + if (iColumn != pivotColumn) { + saveColumn[put++] = iColumn; + } else { + break; + } + } + } else { + for (int i = startRow; i < pivotColumnPosition; i++) { + saveColumn[put++] = indexColumnU[i]; + } + } + assert(pivotColumnPosition < endRow); + assert(indexColumnU[pivotColumnPosition] == pivotColumn); + pivotColumnPosition++; + for (; pivotColumnPosition < endRow; pivotColumnPosition++) { + saveColumn[put++] = indexColumnU[pivotColumnPosition]; + } + //take out this bit of indexColumnU + int next = nextRow[pivotRow]; + int last = lastRow[pivotRow]; + + nextRow[last] = next; + lastRow[next] = last; + nextRow[pivotRow] = numberGoodU_; //use for permute + lastRow[pivotRow] = -2; + numberInRow[pivotRow] = 0; + //store column in L, compress in U and take column out + int l = lengthL_; + + if (l + numberInPivotColumn > lengthAreaL_) { + //need more memory + if ((messageLevel_ & 4) != 0) + printf("more memory needed in middle of invert\n"); + return false; + } + //l+=currentAreaL_->elementByColumn-elementL; + int lSave = l; + + int *startColumnL = startColumnL_.array(); + startColumnL[numberGoodL_] = l; //for luck and first time + numberGoodL_++; + startColumnL[numberGoodL_] = l + numberInPivotColumn; + lengthL_ += numberInPivotColumn; + if (pivotRowPosition < 0) { + for (pivotRowPosition = startColumn; pivotRowPosition < endColumn; pivotRowPosition++) { + int iRow = indexRowU[pivotRowPosition]; + if (iRow != pivotRow) { + indexRowL[l] = iRow; + elementL[l] = elementU[pivotRowPosition]; + markRow[iRow] = static_cast< T >(l - lSave); + l++; + //take out of row list + int start = startRowU[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumnU[where] != pivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + } else { + break; + } + } + } else { + int i; + + for (i = startColumn; i < pivotRowPosition; i++) { + int iRow = indexRowU[i]; + + markRow[iRow] = static_cast< T >(l - lSave); + indexRowL[l] = iRow; + elementL[l] = elementU[i]; + l++; + //take out of row list + int start = startRowU[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumnU[where] != pivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + assert(numberInRow[iRow] >= 0); + } + } + assert(pivotRowPosition < endColumn); + assert(indexRowU[pivotRowPosition] == pivotRow); + CoinFactorizationDouble pivotElement = elementU[pivotRowPosition]; + CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; + + pivotRegion_.array()[numberGoodU_] = pivotMultiplier; + pivotRowPosition++; + for (; pivotRowPosition < endColumn; pivotRowPosition++) { + int iRow = indexRowU[pivotRowPosition]; + + markRow[iRow] = static_cast< T >(l - lSave); + indexRowL[l] = iRow; + elementL[l] = elementU[pivotRowPosition]; + l++; + //take out of row list + int start = startRowU[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumnU[where] != pivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + assert(numberInRow[iRow] >= 0); + } + markRow[pivotRow] = static_cast< T >(largeInteger); + //compress pivot column (move pivot to front including saved) + numberInColumn[pivotColumn] = 0; + //use end of L for temporary space + int *indexL = &indexRowL[lSave]; + CoinFactorizationDouble *multipliersL = &elementL[lSave]; + + //adjust + int j; + + for (j = 0; j < numberInPivotColumn; j++) { + multipliersL[j] *= pivotMultiplier; + } + //zero out fill + int iErase; + for (iErase = 0; iErase < increment2 * numberInPivotRow; + iErase++) { + workArea2[iErase] = 0; + } + int added = numberInPivotRow * numberInPivotColumn; + unsigned int *temp2 = workArea2; + int *nextColumn = nextColumn_.array(); + + //pack down and move to work + int jColumn; + for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) { + int iColumn = saveColumn[jColumn]; + int startColumn = startColumnU[iColumn]; + int endColumn = startColumn + numberInColumn[iColumn]; + int iRow = indexRowU[startColumn]; + CoinFactorizationDouble value = elementU[startColumn]; + double largest; + int put = startColumn; + int positionLargest = -1; + CoinFactorizationDouble thisPivotValue = 0.0; + + //compress column and find largest not updated + bool checkLargest; + int mark = markRow[iRow]; + + if (mark == largeInteger + 1) { + largest = fabs(value); + positionLargest = put; + put++; + checkLargest = false; + } else { + //need to find largest + largest = 0.0; + checkLargest = true; + if (mark != largeInteger) { + //will be updated + work[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + int i; + for (i = startColumn + 1; i < endColumn; i++) { + iRow = indexRowU[i]; + value = elementU[i]; + int mark = markRow[iRow]; + + if (mark == largeInteger + 1) { + //keep + indexRowU[put] = iRow; + elementU[put] = value; + if (checkLargest) { + double absValue = fabs(value); + + if (absValue > largest) { + largest = absValue; + positionLargest = put; + } + } + put++; + } else if (mark != largeInteger) { + //will be updated + work[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + //slot in pivot + elementU[put] = elementU[startColumn]; + indexRowU[put] = indexRowU[startColumn]; + if (positionLargest == startColumn) { + positionLargest = put; //follow if was largest + } + put++; + elementU[startColumn] = thisPivotValue; + indexRowU[startColumn] = pivotRow; + //clean up counts + startColumn++; + numberInColumn[iColumn] = put - startColumn; + int *numberInColumnPlus = numberInColumnPlus_.array(); + numberInColumnPlus[iColumn]++; + startColumnU[iColumn]++; + //how much space have we got + int next = nextColumn[iColumn]; + int space; + + space = startColumnU[next] - put - numberInColumnPlus[next]; + //assume no zero elements + if (numberInPivotColumn > space) { + //getColumnSpace also moves fixed part + if (!getColumnSpace(iColumn, numberInPivotColumn)) { + return false; + } + //redo starts + if (positionLargest >= 0) + positionLargest = positionLargest + startColumnU[iColumn] - startColumn; + startColumn = startColumnU[iColumn]; + put = startColumn + numberInColumn[iColumn]; + } + double tolerance = zeroTolerance_; + + int *nextCount = nextCount_.array(); + for (j = 0; j < numberInPivotColumn; j++) { + value = work[j] - thisPivotValue * multipliersL[j]; + double absValue = fabs(value); + + if (absValue > tolerance) { + work[j] = 0.0; + assert(put < lengthAreaU_); + elementU[put] = value; + indexRowU[put] = indexL[j]; + if (absValue > largest) { + largest = absValue; + positionLargest = put; + } + put++; + } else { + work[j] = 0.0; + added--; + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + if (temp2[word] & (1 << bit)) { + //take out of row list + iRow = indexL[j]; + int start = startRowU[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumnU[where] != iColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumnU[where] = indexColumnU[end - 1]; + numberInRow[iRow]--; + } else { + //make sure won't be added + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + } + } + } + numberInColumn[iColumn] = put - startColumn; + //move largest + if (positionLargest >= 0) { + value = elementU[positionLargest]; + iRow = indexRowU[positionLargest]; + elementU[positionLargest] = elementU[startColumn]; + indexRowU[positionLargest] = indexRowU[startColumn]; + elementU[startColumn] = value; + indexRowU[startColumn] = iRow; + } + //linked list for column + if (nextCount[iColumn + numberRows_] != -2) { + //modify linked list + deleteLink(iColumn + numberRows_); + addLink(iColumn + numberRows_, numberInColumn[iColumn]); + } + temp2 += increment2; + } + //get space for row list + unsigned int *putBase = workArea2; + int bigLoops = numberInPivotColumn >> COINFACTORIZATION_SHIFT_PER_INT; + int i = 0; + + // do linked lists and update counts + while (bigLoops) { + bigLoops--; + int bit; + for (bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + number += test; + } + int next = nextRow[iRow]; + int space; + + space = startRowU[next] - startRowU[iRow]; + number += numberInRow[iRow]; + if (space < number) { + if (!getRowSpace(iRow, number)) { + return false; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + int end = startRowU[iRow] + number; + int saveIndex = indexColumnU[startRowU[next]]; + + //add in + for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + indexColumnU[end] = saveColumn[jColumn]; + end += test; + } + //put back next one in case zapped + indexColumnU[startRowU[next]] = saveIndex; + markRow[iRow] = static_cast< T >(largeInteger + 1); + number = end - startRowU[iRow]; + numberInRow[iRow] = number; + deleteLink(iRow); + addLink(iRow, number); + } + putBase++; + } /* endwhile */ + int bit; + + for (bit = 0; i < numberInPivotColumn; i++, bit++) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + number += test; + } + int next = nextRow[iRow]; + int space; + + space = startRowU[next] - startRowU[iRow]; + number += numberInRow[iRow]; + if (space < number) { + if (!getRowSpace(iRow, number)) { + return false; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + int end = startRowU[iRow] + number; + int saveIndex; + + saveIndex = indexColumnU[startRowU[next]]; + + //add in + for (jColumn = 0; jColumn < numberInPivotRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + + indexColumnU[end] = saveColumn[jColumn]; + end += test; + } + indexColumnU[startRowU[next]] = saveIndex; + markRow[iRow] = static_cast< T >(largeInteger + 1); + number = end - startRowU[iRow]; + numberInRow[iRow] = number; + deleteLink(iRow); + addLink(iRow, number); + } + markRow[pivotRow] = static_cast< T >(largeInteger + 1); + //modify linked list for pivots + deleteLink(pivotRow); + deleteLink(pivotColumn + numberRows_); + totalElements_ += added; + return true; + } + + /********************************* END LARGE TEMPLATE ********/ + //@} + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Pivot tolerance + double pivotTolerance_; + /// Zero tolerance + double zeroTolerance_; +#ifndef COIN_FAST_CODE + /// Whether slack value is +1 or -1 + double slackValue_; +#else +#ifndef slackValue_ +#define slackValue_ -1.0 +#endif +#endif + /// How much to multiply areas by + double areaFactor_; + /// Relax check on accuracy in replaceColumn + double relaxCheck_; + /// Number of Rows in factorization + int numberRows_; + /// Number of Rows after iterating + int numberRowsExtra_; + /// Maximum number of Rows after iterating + int maximumRowsExtra_; + /// Number of Columns in factorization + int numberColumns_; + /// Number of Columns after iterating + int numberColumnsExtra_; + /// Maximum number of Columns after iterating + int maximumColumnsExtra_; + /// Number factorized in U (not row singletons) + int numberGoodU_; + /// Number factorized in L + int numberGoodL_; + /// Maximum number of pivots before factorization + int maximumPivots_; + /// Number pivots since last factorization + int numberPivots_; + /// Number of elements in U (to go) + /// or while iterating total overall + int totalElements_; + /// Number of elements after factorization + int factorElements_; + /// Pivot order for each Column + CoinIntArrayWithLength pivotColumn_; + /// Permutation vector for pivot row order + CoinIntArrayWithLength permute_; + /// DePermutation vector for pivot row order + CoinIntArrayWithLength permuteBack_; + /// Inverse Pivot order for each Column + CoinIntArrayWithLength pivotColumnBack_; + /// Status of factorization + int status_; + + /** 0 - no increasing rows - no permutations, + 1 - no increasing rows but permutations + 2 - increasing rows + - taken out as always 2 */ + //int increasingRows_; + + /// Number of trials before rejection + int numberTrials_; + /// Start of each Row as pointer + CoinIntArrayWithLength startRowU_; + + /// Number in each Row + CoinIntArrayWithLength numberInRow_; + + /// Number in each Column + CoinIntArrayWithLength numberInColumn_; + + /// Number in each Column including pivoted + CoinIntArrayWithLength numberInColumnPlus_; + + /** First Row/Column with count of k, + can tell which by offset - Rows then Columns */ + CoinIntArrayWithLength firstCount_; + + /// Next Row/Column with count + CoinIntArrayWithLength nextCount_; + + /// Previous Row/Column with count + CoinIntArrayWithLength lastCount_; + + /// Next Column in memory order + CoinIntArrayWithLength nextColumn_; + + /// Previous Column in memory order + CoinIntArrayWithLength lastColumn_; + + /// Next Row in memory order + CoinIntArrayWithLength nextRow_; + + /// Previous Row in memory order + CoinIntArrayWithLength lastRow_; + + /// Columns left to do in a single pivot + CoinIntArrayWithLength saveColumn_; + + /// Marks rows to be updated + CoinIntArrayWithLength markRow_; + + /// Detail in messages + int messageLevel_; + + /// Larger of row and column size + int biggerDimension_; + + /// Base address for U (may change) + CoinIntArrayWithLength indexColumnU_; + + /// Pivots for L + CoinIntArrayWithLength pivotRowL_; + + /// Inverses of pivot values + CoinFactorizationDoubleArrayWithLength pivotRegion_; + + /// Number of slacks at beginning of U + int numberSlacks_; + + /// Number in U + int numberU_; + + /// Maximum space used in U + int maximumU_; + + /// Base of U is always 0 + //int baseU_; + + /// Length of U + int lengthU_; + + /// Length of area reserved for U + int lengthAreaU_; + + /// Elements of U + CoinFactorizationDoubleArrayWithLength elementU_; + + /// Row indices of U + CoinIntArrayWithLength indexRowU_; + + /// Start of each column in U + CoinIntArrayWithLength startColumnU_; + + /// Converts rows to columns in U + CoinIntArrayWithLength convertRowToColumnU_; + + /// Number in L + int numberL_; + + /// Base of L + int baseL_; + + /// Length of L + int lengthL_; + + /// Length of area reserved for L + int lengthAreaL_; + + /// Elements of L + CoinFactorizationDoubleArrayWithLength elementL_; + + /// Row indices of L + CoinIntArrayWithLength indexRowL_; + + /// Start of each column in L + CoinIntArrayWithLength startColumnL_; + + /// true if Forrest Tomlin update, false if PFI + bool doForrestTomlin_; + + /// Number in R + int numberR_; + + /// Length of R stuff + int lengthR_; + + /// length of area reserved for R + int lengthAreaR_; + + /// Elements of R + CoinFactorizationDouble *elementR_; + + /// Row indices for R + int *indexRowR_; + + /// Start of columns for R + CoinIntArrayWithLength startColumnR_; + + /// Dense area + double *denseArea_; + + /// Dense area - actually used (for alignment etc) + double *denseAreaAddress_; + + /// Dense permutation + int *densePermute_; + + /// Number of dense rows + int numberDense_; + + /// Dense threshold + int denseThreshold_; + + /// First work area + CoinFactorizationDoubleArrayWithLength workArea_; + + /// Second work area + CoinUnsignedIntArrayWithLength workArea2_; + + /// Number of compressions done + int numberCompressions_; + +public: + /// Below are all to collect + mutable double ftranCountInput_; + mutable double ftranCountAfterL_; + mutable double ftranCountAfterR_; + mutable double ftranCountAfterU_; + mutable double btranCountInput_; + mutable double btranCountAfterU_; + mutable double btranCountAfterR_; + mutable double btranCountAfterL_; + + /// We can roll over factorizations + mutable int numberFtranCounts_; + mutable int numberBtranCounts_; + + /// While these are average ratios collected over last period + double ftranAverageAfterL_; + double ftranAverageAfterR_; + double ftranAverageAfterU_; + double btranAverageAfterU_; + double btranAverageAfterR_; + double btranAverageAfterL_; + +protected: + /// For statistics +#if 0 + mutable bool collectStatistics_; +#else +#define collectStatistics_ 1 +#endif + + /// Below this use sparse technology - if 0 then no L row copy + int sparseThreshold_; + + /// And one for "sparsish" + int sparseThreshold2_; + + /// Start of each row in L + CoinIntArrayWithLength startRowL_; + + /// Index of column in row for L + CoinIntArrayWithLength indexColumnL_; + + /// Elements in L (row copy) + CoinFactorizationDoubleArrayWithLength elementByRowL_; + + /// Sparse regions + mutable CoinIntArrayWithLength sparse_; +#if ABOCA_LITE_FACTORIZATION + /// Offset to second version of sparse + int sparseOffset_; +#endif + /** L to U bias + 0 - U bias, 1 - some U bias, 2 some L bias, 3 L bias + */ + int biasLU_; + /** Array persistence flag + If 0 then as now (delete/new) + 1 then only do arrays if bigger needed + 2 as 1 but give a bit extra if bigger needed + */ + int persistenceFlag_; +#ifdef ABC_USE_COIN_FACTORIZATION + /// Says if parallel + int parallelMode_; +#endif + //@} +}; +// Dense coding +#ifdef INTEL_COMPILER +#define COIN_FACTORIZATION_DENSE_CODE 3 +#endif +#ifdef COIN_HAS_LAPACK +#ifndef COIN_FACTORIZATION_DENSE_CODE +#define COIN_FACTORIZATION_DENSE_CODE 1 +#endif +#endif +#ifdef COIN_FACTORIZATION_DENSE_CODE +/* Type of Fortran integer translated into C */ +#ifndef ipfint +//typedef ipfint FORTRAN_INTEGER_TYPE ; +typedef int ipfint; +typedef const int cipfint; +#endif +#endif +#endif +// Extra for ugly include +#ifdef UGLY_COIN_FACTOR_CODING +#define FAC_UNSET (FAC_SET + 1) +{ + goodPivot = false; + //store pivot columns (so can easily compress) + int startColumnThis = startColumn[iPivotColumn]; + int endColumn = startColumnThis + numberDoColumn + 1; + int put = 0; + int startRowThis = startRow[iPivotRow]; + int endRow = startRowThis + numberDoRow + 1; + if (pivotColumnPosition < 0) { + for (pivotColumnPosition = startRowThis; pivotColumnPosition < endRow; pivotColumnPosition++) { + int iColumn = indexColumn[pivotColumnPosition]; + if (iColumn != iPivotColumn) { + saveColumn[put++] = iColumn; + } else { + break; + } + } + } else { + for (int i = startRowThis; i < pivotColumnPosition; i++) { + saveColumn[put++] = indexColumn[i]; + } + } + assert(pivotColumnPosition < endRow); + assert(indexColumn[pivotColumnPosition] == iPivotColumn); + pivotColumnPosition++; + for (; pivotColumnPosition < endRow; pivotColumnPosition++) { + saveColumn[put++] = indexColumn[pivotColumnPosition]; + } + //take out this bit of indexColumn + int next = nextRow[iPivotRow]; + int last = lastRow[iPivotRow]; + + nextRow[last] = next; + lastRow[next] = last; + nextRow[iPivotRow] = numberGoodU_; //use for permute + lastRow[iPivotRow] = -2; + numberInRow[iPivotRow] = 0; + //store column in L, compress in U and take column out + int l = lengthL_; + // **** HORRID coding coming up but a goto seems best! + { + if (l + numberDoColumn > lengthAreaL_) { + //need more memory + if ((messageLevel_ & 4) != 0) + printf("more memory needed in middle of invert\n"); + goto BAD_PIVOT; + } + //l+=currentAreaL_->elementByColumn-elementL; + int lSave = l; + + int *startColumnL = startColumnL_.array(); + startColumnL[numberGoodL_] = l; //for luck and first time + numberGoodL_++; + startColumnL[numberGoodL_] = l + numberDoColumn; + lengthL_ += numberDoColumn; + if (pivotRowPosition < 0) { + for (pivotRowPosition = startColumnThis; pivotRowPosition < endColumn; pivotRowPosition++) { + int iRow = indexRow[pivotRowPosition]; + if (iRow != iPivotRow) { + indexRowL[l] = iRow; + elementL[l] = element[pivotRowPosition]; + markRow[iRow] = l - lSave; + l++; + //take out of row list + int start = startRow[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumn[where] != iPivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + } else { + break; + } + } + } else { + int i; + + for (i = startColumnThis; i < pivotRowPosition; i++) { + int iRow = indexRow[i]; + + markRow[iRow] = l - lSave; + indexRowL[l] = iRow; + elementL[l] = element[i]; + l++; + //take out of row list + int start = startRow[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumn[where] != iPivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + assert(numberInRow[iRow] >= 0); + } + } + assert(pivotRowPosition < endColumn); + assert(indexRow[pivotRowPosition] == iPivotRow); + CoinFactorizationDouble pivotElement = element[pivotRowPosition]; + CoinFactorizationDouble pivotMultiplier = 1.0 / pivotElement; + + pivotRegion_.array()[numberGoodU_] = pivotMultiplier; + pivotRowPosition++; + for (; pivotRowPosition < endColumn; pivotRowPosition++) { + int iRow = indexRow[pivotRowPosition]; + + markRow[iRow] = l - lSave; + indexRowL[l] = iRow; + elementL[l] = element[pivotRowPosition]; + l++; + //take out of row list + int start = startRow[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumn[where] != iPivotColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + assert(numberInRow[iRow] >= 0); + } + markRow[iPivotRow] = FAC_SET; + //compress pivot column (move pivot to front including saved) + numberInColumn[iPivotColumn] = 0; + //use end of L for temporary space + int *indexL = &indexRowL[lSave]; + CoinFactorizationDouble *multipliersL = &elementL[lSave]; + + //adjust + int j; + + for (j = 0; j < numberDoColumn; j++) { + multipliersL[j] *= pivotMultiplier; + } + //zero out fill + int iErase; + for (iErase = 0; iErase < increment2 * numberDoRow; + iErase++) { + workArea2[iErase] = 0; + } + int added = numberDoRow * numberDoColumn; + unsigned int *temp2 = workArea2; + int *nextColumn = nextColumn_.array(); + + //pack down and move to work + int jColumn; + for (jColumn = 0; jColumn < numberDoRow; jColumn++) { + int iColumn = saveColumn[jColumn]; + int startColumnThis = startColumn[iColumn]; + int endColumn = startColumnThis + numberInColumn[iColumn]; + int iRow = indexRow[startColumnThis]; + CoinFactorizationDouble value = element[startColumnThis]; + double largest; + int put = startColumnThis; + int positionLargest = -1; + CoinFactorizationDouble thisPivotValue = 0.0; + + //compress column and find largest not updated + bool checkLargest; + int mark = markRow[iRow]; + + if (mark == FAC_UNSET) { + largest = fabs(value); + positionLargest = put; + put++; + checkLargest = false; + } else { + //need to find largest + largest = 0.0; + checkLargest = true; + if (mark != FAC_SET) { + //will be updated + workArea[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + int i; + for (i = startColumnThis + 1; i < endColumn; i++) { + iRow = indexRow[i]; + value = element[i]; + int mark = markRow[iRow]; + + if (mark == FAC_UNSET) { + //keep + indexRow[put] = iRow; + element[put] = value; + if (checkLargest) { + double absValue = fabs(value); + + if (absValue > largest) { + largest = absValue; + positionLargest = put; + } + } + put++; + } else if (mark != FAC_SET) { + //will be updated + workArea[mark] = value; + int word = mark >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = mark & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + added--; + } else { + thisPivotValue = value; + } + } + //slot in pivot + element[put] = element[startColumnThis]; + indexRow[put] = indexRow[startColumnThis]; + if (positionLargest == startColumnThis) { + positionLargest = put; //follow if was largest + } + put++; + element[startColumnThis] = thisPivotValue; + indexRow[startColumnThis] = iPivotRow; + //clean up counts + startColumnThis++; + numberInColumn[iColumn] = put - startColumnThis; + int *numberInColumnPlus = numberInColumnPlus_.array(); + numberInColumnPlus[iColumn]++; + startColumn[iColumn]++; + //how much space have we got + int next = nextColumn[iColumn]; + int space; + + space = startColumn[next] - put - numberInColumnPlus[next]; + //assume no zero elements + if (numberDoColumn > space) { + //getColumnSpace also moves fixed part + if (!getColumnSpace(iColumn, numberDoColumn)) { + goto BAD_PIVOT; + } + //redo starts + positionLargest = positionLargest + startColumn[iColumn] - startColumnThis; + startColumnThis = startColumn[iColumn]; + put = startColumnThis + numberInColumn[iColumn]; + } + double tolerance = zeroTolerance_; + + int *nextCount = nextCount_.array(); + for (j = 0; j < numberDoColumn; j++) { + value = workArea[j] - thisPivotValue * multipliersL[j]; + double absValue = fabs(value); + + if (absValue > tolerance) { + workArea[j] = 0.0; + element[put] = value; + indexRow[put] = indexL[j]; + if (absValue > largest) { + largest = absValue; + positionLargest = put; + } + put++; + } else { + workArea[j] = 0.0; + added--; + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + if (temp2[word] & (1 << bit)) { + //take out of row list + iRow = indexL[j]; + int start = startRow[iRow]; + int end = start + numberInRow[iRow]; + int where = start; + + while (indexColumn[where] != iColumn) { + where++; + } /* endwhile */ +#if DEBUG_COIN + if (where >= end) { + abort(); + } +#endif + indexColumn[where] = indexColumn[end - 1]; + numberInRow[iRow]--; + } else { + //make sure won't be added + int word = j >> COINFACTORIZATION_SHIFT_PER_INT; + int bit = j & COINFACTORIZATION_MASK_PER_INT; + + temp2[word] = temp2[word] | (1 << bit); //say already in counts + } + } + } + numberInColumn[iColumn] = put - startColumnThis; + //move largest + if (positionLargest >= 0) { + value = element[positionLargest]; + iRow = indexRow[positionLargest]; + element[positionLargest] = element[startColumnThis]; + indexRow[positionLargest] = indexRow[startColumnThis]; + element[startColumnThis] = value; + indexRow[startColumnThis] = iRow; + } + //linked list for column + if (nextCount[iColumn + numberRows_] != -2) { + //modify linked list + deleteLink(iColumn + numberRows_); + addLink(iColumn + numberRows_, numberInColumn[iColumn]); + } + temp2 += increment2; + } + //get space for row list + unsigned int *putBase = workArea2; + int bigLoops = numberDoColumn >> COINFACTORIZATION_SHIFT_PER_INT; + int i = 0; + + // do linked lists and update counts + while (bigLoops) { + bigLoops--; + int bit; + for (bit = 0; bit < COINFACTORIZATION_BITS_PER_INT; i++, bit++) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for (jColumn = 0; jColumn < numberDoRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + number += test; + } + int next = nextRow[iRow]; + int space; + + space = startRow[next] - startRow[iRow]; + number += numberInRow[iRow]; + if (space < number) { + if (!getRowSpace(iRow, number)) { + goto BAD_PIVOT; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + int end = startRow[iRow] + number; + int saveIndex = indexColumn[startRow[next]]; + + //add in + for (jColumn = 0; jColumn < numberDoRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + indexColumn[end] = saveColumn[jColumn]; + end += test; + } + //put back next one in case zapped + indexColumn[startRow[next]] = saveIndex; + markRow[iRow] = FAC_UNSET; + number = end - startRow[iRow]; + numberInRow[iRow] = number; + deleteLink(iRow); + addLink(iRow, number); + } + putBase++; + } /* endwhile */ + int bit; + + for (bit = 0; i < numberDoColumn; i++, bit++) { + unsigned int *putThis = putBase; + int iRow = indexL[i]; + + //get space + int number = 0; + int jColumn; + + for (jColumn = 0; jColumn < numberDoRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + number += test; + } + int next = nextRow[iRow]; + int space; + + space = startRow[next] - startRow[iRow]; + number += numberInRow[iRow]; + if (space < number) { + if (!getRowSpace(iRow, number)) { + goto BAD_PIVOT; + } + } + // now do + putThis = putBase; + next = nextRow[iRow]; + number = numberInRow[iRow]; + int end = startRow[iRow] + number; + int saveIndex; + + saveIndex = indexColumn[startRow[next]]; + + //add in + for (jColumn = 0; jColumn < numberDoRow; jColumn++) { + unsigned int test = *putThis; + + putThis += increment2; + test = 1 - ((test >> bit) & 1); + + indexColumn[end] = saveColumn[jColumn]; + end += test; + } + indexColumn[startRow[next]] = saveIndex; + markRow[iRow] = FAC_UNSET; + number = end - startRow[iRow]; + numberInRow[iRow] = number; + deleteLink(iRow); + addLink(iRow, number); + } + markRow[iPivotRow] = FAC_UNSET; + //modify linked list for pivots + deleteLink(iPivotRow); + deleteLink(iPivotColumn + numberRows_); + totalElements_ += added; + goodPivot = true; + // **** UGLY UGLY UGLY + } +BAD_PIVOT: + + ; +} +#undef FAC_UNSET +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFileIO.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFileIO.hpp new file mode 100644 index 000000000..52952cb0e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFileIO.hpp @@ -0,0 +1,185 @@ +/* $Id$ */ +// Copyright (C) 2005, COIN-OR. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinFileIO_H +#define CoinFileIO_H + +#include + +/// Base class for FileIO classes. +class CoinFileIOBase { +public: + /// Constructor. + /// @param fileName The name of the file used by this object. + CoinFileIOBase(const std::string &fileName); + + /// Destructor. + ~CoinFileIOBase(); + + /// Return the name of the file used by this object. + const char *getFileName() const; + + /// Return the method of reading being used + inline std::string getReadType() const + { + return readType_.c_str(); + } + +protected: + std::string readType_; + +private: + CoinFileIOBase(); + CoinFileIOBase(const CoinFileIOBase &); + + std::string fileName_; +}; + +/// Abstract base class for file input classes. +class CoinFileInput : public CoinFileIOBase { +public: + /// indicates whether CoinFileInput supports gzip'ed files + static bool haveGzipSupport(); + /// indicates whether CoinFileInput supports bzip2'ed files + static bool haveBzip2Support(); + + /// Factory method, that creates a CoinFileInput (more precisely + /// a subclass of it) for the file specified. This method reads the + /// first few bytes of the file and determines if this is a compressed + /// or a plain file and returns the correct subclass to handle it. + /// If the file does not exist or uses a compression not compiled in + /// an exception is thrown. + /// @param fileName The file that should be read. + static CoinFileInput *create(const std::string &fileName); + + /// Constructor (don't use this, use the create method instead). + /// @param fileName The name of the file used by this object. + CoinFileInput(const std::string &fileName); + + /// Destructor. + virtual ~CoinFileInput(); + + /// Read a block of data from the file, similar to fread. + /// @param buffer Address of a buffer to store the data into. + /// @param size Number of bytes to read (buffer should be large enough). + /// @return Number of bytes read. + virtual int read(void *buffer, int size) = 0; + + /// Reads up to (size-1) characters an stores them into the buffer, + /// similar to fgets. + /// Reading ends, when EOF or a newline occurs or (size-1) characters have + /// been read. The resulting string is terminated with '\0'. If reading + /// ends due to an encoutered newline, the '\n' is put into the buffer, + /// before the '\0' is appended. + /// @param buffer The buffer to put the string into. + /// @param size The size of the buffer in characters. + /// @return buffer on success, or 0 if no characters have been read. + virtual char *gets(char *buffer, int size) = 0; +}; + +/// This reads plain text files +class CoinPlainFileInput : public CoinFileInput { +public: + CoinPlainFileInput(const std::string &fileName); + /// When already opened + CoinPlainFileInput(FILE *fp); + virtual ~CoinPlainFileInput(); + + virtual int read(void *buffer, int size); + + virtual char *gets(char *buffer, int size); + +private: + FILE *f_; +}; + +/// Abstract base class for file output classes. +class CoinFileOutput : public CoinFileIOBase { +public: + /// The compression method. + enum Compression { + COMPRESS_NONE = 0, ///< No compression. + COMPRESS_GZIP = 1, ///< gzip compression. + COMPRESS_BZIP2 = 2 ///< bzip2 compression. + }; + + /// Returns whether the specified compression method is supported + /// (i.e. was compiled into COIN). + static bool compressionSupported(Compression compression); + + /// Factory method, that creates a CoinFileOutput (more precisely + /// a subclass of it) for the file specified. If the compression method + /// is not supported an exception is thrown (so use compressionSupported + /// first, if this is a problem). The reason for not providing direct + /// access to the subclasses (and using such a method instead) is that + /// depending on the build configuration some of the classes are not + /// available (or functional). This way we can handle all required ifdefs + /// here instead of polluting other files. + /// @param fileName The file that should be read. + /// @param compression Compression method used. + static CoinFileOutput *create(const std::string &fileName, + Compression compression); + + /// Constructor (don't use this, use the create method instead). + /// @param fileName The name of the file used by this object. + CoinFileOutput(const std::string &fileName); + + /// Destructor. + virtual ~CoinFileOutput(); + + /// Write a block of data to the file, similar to fwrite. + /// @param buffer Address of a buffer containing the data to be written. + /// @param size Number of bytes to write. + /// @return Number of bytes written. + virtual int write(const void *buffer, int size) = 0; + + /// Write a string to the file (like fputs). + /// Just as with fputs no trailing newline is inserted! + /// The terminating '\0' is not written to the file. + /// The default implementation determines the length of the string + /// and calls write on it. + /// @param s The zero terminated string to be written. + /// @return true on success, false on error. + virtual bool puts(const char *s); + + /// Convenience method: just a 'puts(s.c_str())'. + inline bool puts(const std::string &s) + { + return puts(s.c_str()); + } +}; + +/*! \relates CoinFileInput + \brief Test if the given string looks like an absolute file path + + The criteria are: + - unix: string begins with `/' + - windows: string begins with `\' or with `drv:' (drive specifier) +*/ +bool fileAbsPath(const std::string &path); + +/*! \relates CoinFileInput + \brief Test if the file is readable, using likely versions of the file + name, and return the name that worked. + + The file name is constructed from \p name using the following rules: +
    +
  • An absolute path is not modified. +
  • If the name begins with `~', an attempt is made to replace `~' + with the value of the environment variable HOME. +
  • If a default prefix (\p dfltPrefix) is provided, it is + prepended to the name. +
+ If the constructed file name cannot be opened, and CoinUtils was built + with support for compressed files, fileCoinReadable will try any + standard extensions for supported compressed files. + + The value returned in \p name is the file name that actually worked. +*/ +bool fileCoinReadable(std::string &name, + const std::string &dfltPrefix = std::string("")); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFinite.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFinite.hpp new file mode 100644 index 000000000..5eed9877c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFinite.hpp @@ -0,0 +1,37 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* Defines COIN_DBL_MAX and relatives and provides CoinFinite and CoinIsnan. */ + +#ifndef CoinFinite_H +#define CoinFinite_H + +#include + +//============================================================================= +// Smallest positive double value and Plus infinity (double and int) + +#if 1 +const double COIN_DBL_MIN = (std::numeric_limits< double >::min)(); +const double COIN_DBL_MAX = (std::numeric_limits< double >::max)(); +const int COIN_INT_MAX = (std::numeric_limits< int >::max)(); +const double COIN_INT_MAX_AS_DOUBLE = (std::numeric_limits< int >::max)(); +#else +#define COIN_DBL_MIN (std::numeric_limits< double >::min()) +#define COIN_DBL_MAX (std::numeric_limits< double >::max()) +#define COIN_INT_MAX (std::numeric_limits< int >::max()) +#define COIN_INT_MAX_AS_DOUBLE (std::numeric_limits< int >::max()) +#endif + +/** checks if a double value is finite (not infinity and not NaN) */ +extern bool CoinFinite(double val); + +/** checks if a double value is not a number */ +extern bool CoinIsnan(double val); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFloatEqual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFloatEqual.hpp new file mode 100644 index 000000000..c5fe3aa66 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinFloatEqual.hpp @@ -0,0 +1,204 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinFloatEqual_H +#define CoinFloatEqual_H + +#include +#include + +#include "CoinFinite.hpp" + +/*! \file CoinFloatEqual.hpp + \brief Function objects for testing equality of real numbers. + + Two objects are provided; one tests for equality to an absolute tolerance, + one to a scaled tolerance. The tests will handle IEEE floating point, but + note that infinity == infinity. Mathematicians are rolling in their graves, + but this matches the behaviour for the common practice of using + DBL_MAX (numeric_limits::max(), or similar + large finite number) as infinity. + +

+ Example usage: + @verbatim + double d1 = 3.14159 ; + double d2 = d1 ; + double d3 = d1+.0001 ; + + CoinAbsFltEq eq1 ; + CoinAbsFltEq eq2(.001) ; + + assert( eq1(d1,d2) ) ; + assert( !eq1(d1,d3) ) ; + assert( eq2(d1,d3) ) ; + @endverbatim + CoinRelFltEq follows the same pattern. */ + +/*! \brief Equality to an absolute tolerance + + Operands are considered equal if their difference is within an epsilon ; + the test does not consider the relative magnitude of the operands. +*/ + +class CoinAbsFltEq { +public: + //! Compare function + + inline bool operator()(const double f1, const double f2) const + + { + if (CoinIsnan(f1) || CoinIsnan(f2)) + return false; + if (f1 == f2) + return true; + return (fabs(f1 - f2) < epsilon_); + } + + /*! \name Constructors and destructors */ + //@{ + + /*! \brief Default constructor + + Default tolerance is 1.0e-10. + */ + + CoinAbsFltEq() + : epsilon_(1.e-10) + { + } + + //! Alternate constructor with epsilon as a parameter + + CoinAbsFltEq(const double epsilon) + : epsilon_(epsilon) + { + } + + //! Destructor + + virtual ~CoinAbsFltEq() {} + + //! Copy constructor + + CoinAbsFltEq(const CoinAbsFltEq &src) + : epsilon_(src.epsilon_) + { + } + + //! Assignment + + CoinAbsFltEq &operator=(const CoinAbsFltEq &rhs) + + { + if (this != &rhs) + epsilon_ = rhs.epsilon_; + return (*this); + } + + //@} + +private: + /*! \name Private member data */ + //@{ + + //! Equality tolerance. + + double epsilon_; + + //@} +}; + +/*! \brief Equality to a scaled tolerance + + Operands are considered equal if their difference is within a scaled + epsilon calculated as epsilon_*(1+CoinMax(|f1|,|f2|)). +*/ + +class CoinRelFltEq { +public: + //! Compare function + + inline bool operator()(const double f1, const double f2) const + + { + if (CoinIsnan(f1) || CoinIsnan(f2)) + return false; + if (f1 == f2) + return true; + if (!CoinFinite(f1) || !CoinFinite(f2)) + return false; + + double tol = (fabs(f1) > fabs(f2)) ? fabs(f1) : fabs(f2); + + return (fabs(f1 - f2) <= epsilon_ * (1 + tol)); + } + + /*! \name Constructors and destructors */ + //@{ + +#ifndef COIN_FLOAT + /*! Default constructor + + Default tolerance is 1.0e-10. + */ + CoinRelFltEq() + : epsilon_(1.e-10) + { + } +#else + /*! Default constructor + + Default tolerance is 1.0e-6. + */ + CoinRelFltEq() + : epsilon_(1.e-6) {}; // as float +#endif + + //! Alternate constructor with epsilon as a parameter + + CoinRelFltEq(const double epsilon) + : epsilon_(epsilon) + { + } + + //! Destructor + + virtual ~CoinRelFltEq() {} + + //! Copy constructor + + CoinRelFltEq(const CoinRelFltEq &src) + : epsilon_(src.epsilon_) + { + } + + //! Assignment + + CoinRelFltEq &operator=(const CoinRelFltEq &rhs) + + { + if (this != &rhs) + epsilon_ = rhs.epsilon_; + return (*this); + } + + //@} + +private: + /*! \name Private member data */ + //@{ + + //! Base equality tolerance + + double epsilon_; + + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinHelperFunctions.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinHelperFunctions.hpp new file mode 100644 index 000000000..19dec19b4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinHelperFunctions.hpp @@ -0,0 +1,1270 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinHelperFunctions_H +#define CoinHelperFunctions_H + +#include "CoinUtilsConfig.h" + +#if defined(_MSC_VER) +#include +#include +#define getcwd _getcwd +#include +#else +#include +#endif +//#define USE_MEMCPY + +#include +#include +#include +#include "CoinTypes.hpp" +#include "CoinError.hpp" + +// Compilers can produce better code if they know about __restrict +#ifndef COIN_RESTRICT +#ifdef COIN_USE_RESTRICT +#define COIN_RESTRICT __restrict +#else +#define COIN_RESTRICT +#endif +#endif + +//############################################################################# + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The arrays are given by pointers to their + first entries and by the size of the source array. Overlapping arrays are + handled correctly. */ + +template < class T > +inline void +CoinCopyN(const T *from, const CoinBigIndex size, T *to) +{ + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinCopyN", ""); +#endif + + CoinBigIndex n = (size + 7) / 8; + if (to > from) { + const T *downfrom = from + size; + T *downto = to + size; + // Use Duff's device to copy + switch (size % 8) { + case 0: + do { + *--downto = *--downfrom; + case 7: + *--downto = *--downfrom; + case 6: + *--downto = *--downfrom; + case 5: + *--downto = *--downfrom; + case 4: + *--downto = *--downfrom; + case 3: + *--downto = *--downfrom; + case 2: + *--downto = *--downfrom; + case 1: + *--downto = *--downfrom; + } while (--n > 0); + } + } else { + // Use Duff's device to copy + --from; + --to; + switch (size % 8) { + case 0: + do { + *++to = *++from; + case 7: + *++to = *++from; + case 6: + *++to = *++from; + case 5: + *++to = *++from; + case 4: + *++to = *++from; + case 3: + *++to = *++from; + case 2: + *++to = *++from; + case 1: + *++to = *++from; + } while (--n > 0); + } + } +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location using Duff's + device (for a speedup of ~2). The source array is given by its first and + "after last" entry; the target array is given by its first entry. + Overlapping arrays are handled correctly. + + All of the various CoinCopyN variants use an int for size. On 64-bit + architectures, the address diff last-first will be a 64-bit quantity. + Given that everything else uses an int, I'm going to choose to kick + the difference down to int. -- lh, 100823 -- +*/ +template < class T > +inline void +CoinCopy(const T *first, const T *last, T *to) +{ + CoinCopyN(first, static_cast< CoinBigIndex >(last - first), to); +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinMemcpyN which can be used for atomic data */ +template < class T > +inline void +CoinDisjointCopyN(const T *from, const CoinBigIndex size, T *to) +{ +#ifndef _MSC_VER + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinDisjointCopyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinDisjointCopyN", ""); +#endif + + for (CoinBigIndex n = size / 8; n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: + to[6] = from[6]; + case 6: + to[5] = from[5]; + case 5: + to[4] = from[4]; + case 4: + to[3] = from[3]; + case 3: + to[2] = from[2]; + case 2: + to[1] = from[1]; + case 1: + to[0] = from[0]; + case 0: + break; + } +#else + CoinCopyN(from, size, to); +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template < class T > +inline void +CoinDisjointCopy(const T *first, const T *last, + T *to) +{ + CoinDisjointCopyN(first, static_cast< CoinBigIndex >(last - first), to); +} + +//----------------------------------------------------------------------------- + +/*! \brief Return an array of length \p size filled with input from \p array, + or null if \p array is null. +*/ + +template < class T > +inline T * +CoinCopyOfArray(const T *array, const CoinBigIndex size) +{ + if (array) { + T *arrayNew = new T[size]; + std::memcpy(arrayNew, array, size * sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + +/*! \brief Return an array of length \p size filled with first copySize from \p array, + or null if \p array is null. +*/ + +template < class T > +inline T * +CoinCopyOfArrayPartial(const T *array, const CoinBigIndex size, const CoinBigIndex copySize) +{ + if (array || size) { + T *arrayNew = new T[size]; + assert(copySize <= size); + std::memcpy(arrayNew, array, copySize * sizeof(T)); + return arrayNew; + } else { + return NULL; + } +} + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with (scalar) \p value if \p array is null +*/ + +template < class T > +inline T * +CoinCopyOfArray(const T *array, const CoinBigIndex size, T value) +{ + T *arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew, array, size * sizeof(T)); + } else { + CoinBigIndex i; + for (i = 0; i < size; i++) + arrayNew[i] = value; + } + return arrayNew; +} + +/*! \brief Return an array of length \p size filled with input from \p array, + or filled with zero if \p array is null +*/ + +template < class T > +inline T * +CoinCopyOfArrayOrZero(const T *array, const CoinBigIndex size) +{ + T *arrayNew = new T[size]; + if (array) { + std::memcpy(arrayNew, array, size * sizeof(T)); + } else { + std::memset(arrayNew, 0, size * sizeof(T)); + } + return arrayNew; +} + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The arrays are given by pointers to their first + entries and by the size of the source array. + + Note JJF - the speed claim seems to be false on IA32 so I have added + alternative coding if USE_MEMCPY defined*/ +#ifndef COIN_USE_RESTRICT +template < class T > +inline void +CoinMemcpyN(const T *from, const CoinBigIndex size, T *to) +{ +#ifndef _MSC_VER +#ifdef USE_MEMCPY + // Use memcpy - seems a lot faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif +#endif + std::memcpy(to, from, size * sizeof(T)); +#else + if (size == 0 || from == to) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to copy negative number of entries", + "CoinMemcpyN", ""); +#endif + +#if 0 + /* There is no point to do this test. If to and from are from different + blocks then dist is undefined, so this can crash correct code. It's + better to trust the user that the arrays are really disjoint. */ + const long dist = to - from; + if (-size < dist && dist < size) + throw CoinError("overlapping arrays", "CoinMemcpyN", ""); +#endif + + for (CoinBigIndex n = static_cast(size>>3); n > 0; --n, from += 8, to += 8) { + to[0] = from[0]; + to[1] = from[1]; + to[2] = from[2]; + to[3] = from[3]; + to[4] = from[4]; + to[5] = from[5]; + to[6] = from[6]; + to[7] = from[7]; + } + switch (size % 8) { + case 7: + to[6] = from[6]; + case 6: + to[5] = from[5]; + case 5: + to[4] = from[4]; + case 4: + to[3] = from[3]; + case 3: + to[2] = from[2]; + case 2: + to[1] = from[1]; + case 1: + to[0] = from[0]; + case 0: + break; + } +#endif +#else + CoinCopyN(from, size, to); +#endif +} +#else +template < class T > +inline void +CoinMemcpyN(const T *COIN_RESTRICT from, CoinBigIndex size, T *COIN_RESTRICT to) +{ +#ifdef USE_MEMCPY + std::memcpy(to, from, size * sizeof(T)); +#else + T *COIN_RESTRICT put = to; + const T *COIN_RESTRICT get = from; + for (; 0 < size; --size) + *put++ = *get++; +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/** This helper function copies an array to another location. The two arrays + must not overlap (otherwise an exception is thrown). For speed 8 entries + are copied at a time. The source array is given by its first and "after + last" entry; the target array is given by its first entry. */ +template < class T > +inline void +CoinMemcpy(const T *first, const T *last, + T *to) +{ + CoinMemcpyN(first, static_cast< CoinBigIndex >(last - first), to); +} + +//############################################################################# + +/** This helper function fills an array with a given value. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have added + CoinZero to allow for memset. */ +template < class T > +inline void +CoinFillN(T *to, const CoinBigIndex size, const T value) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinFillN", ""); +#endif +#if 1 + for (CoinBigIndex n = size / 8; n > 0; --n, to += 8) { + to[0] = value; + to[1] = value; + to[2] = value; + to[3] = value; + to[4] = value; + to[5] = value; + to[6] = value; + to[7] = value; + } + switch (size % 8) { + case 7: + to[6] = value; + // fall through + case 6: + to[5] = value; + // fall through + case 5: + to[4] = value; + // fall through + case 4: + to[3] = value; + // fall through + case 3: + to[2] = value; + // fall through + case 2: + to[1] = value; + // fall through + case 1: + to[0] = value; + // fall through + case 0: + break; + } +#else + // Use Duff's device to fill + CoinBigIndex n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: + do { + *++to = value; + case 7: + *++to = value; + case 6: + *++to = value; + case 5: + *++to = value; + case 4: + *++to = value; + case 3: + *++to = value; + case 2: + *++to = value; + case 1: + *++to = value; + } while (--n > 0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template < class T > +inline void +CoinFill(T *first, T *last, const T value) +{ + CoinFillN(first, last - first, value); +} + +//############################################################################# + +/** This helper function fills an array with zero. For speed 8 entries + are filled at a time. The array is given by a pointer to its first entry + and its size. + + Note JJF - the speed claim seems to be false on IA32 so I have allowed + for memset as an alternative */ +template < class T > +inline void +CoinZeroN(T *to, const CoinBigIndex size) +{ +#ifdef USE_MEMCPY + // Use memset - seems faster on Intel with gcc +#ifndef NDEBUG + // Some debug so check + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif + memset(to, 0, size * sizeof(T)); +#else + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("trying to fill negative number of entries", + "CoinZeroN", ""); +#endif +#if 1 + for (CoinBigIndex n = size / 8; n > 0; --n, to += 8) { + to[0] = 0; + to[1] = 0; + to[2] = 0; + to[3] = 0; + to[4] = 0; + to[5] = 0; + to[6] = 0; + to[7] = 0; + } + switch (size % 8) { + case 7: + to[6] = 0; + case 6: + to[5] = 0; + case 5: + to[4] = 0; + case 4: + to[3] = 0; + case 3: + to[2] = 0; + case 2: + to[1] = 0; + case 1: + to[0] = 0; + case 0: + break; + } +#else + // Use Duff's device to fill + CoinBigIndex n = (size + 7) / 8; + --to; + switch (size % 8) { + case 0: + do { + *++to = 0; + case 7: + *++to = 0; + case 6: + *++to = 0; + case 5: + *++to = 0; + case 4: + *++to = 0; + case 3: + *++to = 0; + case 2: + *++to = 0; + case 1: + *++to = 0; + } while (--n > 0); + } +#endif +#endif +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckDoubleZero(double *to, const CoinBigIndex size) +{ + CoinBigIndex n = 0; + for (CoinBigIndex j = 0; j < size; j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n", + static_cast< int >(size), static_cast< int >(n)); + } +} +/// This Debug helper function checks an array is all zero +inline void +CoinCheckIntZero(int *to, const CoinBigIndex size) +{ + CoinBigIndex n = 0; + for (CoinBigIndex j = 0; j < size; j++) { + if (to[j]) + n++; + } + if (n) { + printf("array of length %d should be zero has %d nonzero\n", + static_cast< int >(size), + static_cast< int >(n)); + } +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with a given value. For speed 8 + entries are filled at a time. The array is given by its first and "after + last" entry. */ +template < class T > +inline void +CoinZero(T *first, T *last) +{ + CoinZeroN(first, last - first); +} + +//############################################################################# + +/** Returns strdup or NULL if original NULL */ +inline char *CoinStrdup(const char *name) +{ + char *dup = NULL; + if (name) { + const int len = static_cast< int >(strlen(name)); + dup = static_cast< char * >(malloc(len + 1)); + CoinMemcpyN(name, len, dup); + dup[len] = 0; + } + return dup; +} + +//############################################################################# + +/** Return the larger (according to operator<() of the arguments. + This function was introduced because for some reason compiler tend to + handle the max() function differently. */ +template < class T > +inline T +CoinMax(const T x1, const T x2) +{ + return (x1 > x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the smaller (according to operator<() of the arguments. + This function was introduced because for some reason compiler tend to + handle the min() function differently. */ +template < class T > +inline T +CoinMin(const T x1, const T x2) +{ + return (x1 < x2) ? x1 : x2; +} + +//----------------------------------------------------------------------------- + +/** Return the absolute value of the argument. This function was introduced + because for some reason compiler tend to handle the abs() function + differently. */ +template < class T > +inline T +CoinAbs(const T value) +{ + return value < 0 ? -value : value; +} + +//############################################################################# + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by a pointer to its first entry + and by its size. */ +template < class T > +inline bool +CoinIsSorted(const T *first, const CoinBigIndex size) +{ + if (size == 0) + return true; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIsSorted", ""); +#endif +#if 1 + // size1 is the number of comparisons to be made + const CoinBigIndex size1 = size - 1; + for (CoinBigIndex n = size1 / 8; n > 0; --n, first += 8) { + if (first[8] < first[7]) + return false; + if (first[7] < first[6]) + return false; + if (first[6] < first[5]) + return false; + if (first[5] < first[4]) + return false; + if (first[4] < first[3]) + return false; + if (first[3] < first[2]) + return false; + if (first[2] < first[1]) + return false; + if (first[1] < first[0]) + return false; + } + + switch (size1 % 8) { + case 7: + if (first[7] < first[6]) + return false; + case 6: + if (first[6] < first[5]) + return false; + case 5: + if (first[5] < first[4]) + return false; + case 4: + if (first[4] < first[3]) + return false; + case 3: + if (first[3] < first[2]) + return false; + case 2: + if (first[2] < first[1]) + return false; + case 1: + if (first[1] < first[0]) + return false; + case 0: + break; + } +#else + const T *next = first; + const T *last = first + size; + for (++next; next != last; first = next, ++next) + if (*next < *first) + return false; +#endif + return true; +} + +//----------------------------------------------------------------------------- + +/** This helper function tests whether the entries of an array are sorted + according to operator<. The array is given by its first and "after + last" entry. */ +template < class T > +inline bool +CoinIsSorted(const T *first, const T *last) +{ + return CoinIsSorted(first, static_cast< CoinBigIndex >(last - first)); +} + +//############################################################################# + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by a + pointer to its first entry and its size. */ +template < class T > +inline void +CoinIotaN(T *first, const CoinBigIndex size, T init) +{ + if (size == 0) + return; + +#ifndef NDEBUG + if (size < 0) + throw CoinError("negative number of entries", "CoinIotaN", ""); +#endif +#if 1 + for (CoinBigIndex n = size / 8; n > 0; --n, first += 8, init += 8) { + first[0] = init; + first[1] = init + 1; + first[2] = init + 2; + first[3] = init + 3; + first[4] = init + 4; + first[5] = init + 5; + first[6] = init + 6; + first[7] = init + 7; + } + switch (size % 8) { + case 7: + first[6] = init + 6; + case 6: + first[5] = init + 5; + case 5: + first[4] = init + 4; + case 4: + first[3] = init + 3; + case 3: + first[2] = init + 2; + case 2: + first[1] = init + 1; + case 1: + first[0] = init; + case 0: + break; + } +#else + // Use Duff's device to fill + CoinBigIndex n = (size + 7) / 8; + --first; + --init; + switch (size % 8) { + case 0: + do { + *++first = ++init; + case 7: + *++first = ++init; + case 6: + *++first = ++init; + case 5: + *++first = ++init; + case 4: + *++first = ++init; + case 3: + *++first = ++init; + case 2: + *++first = ++init; + case 1: + *++first = ++init; + } while (--n > 0); + } +#endif +} + +//----------------------------------------------------------------------------- + +/** This helper function fills an array with the values init, init+1, init+2, + etc. For speed 8 entries are filled at a time. The array is given by its + first and "after last" entry. */ +template < class T > +inline void +CoinIota(T *first, const T *last, T init) +{ + CoinIotaN(first, last - first, init); +} + +//############################################################################# + +/** This helper function deletes certain entries from an array. The array is + given by pointers to its first and "after last" entry (first two + arguments). The positions of the entries to be deleted are given in the + integer array specified by the last two arguments (again, first and "after + last" entry). */ +template < class T > +inline T * +CoinDeleteEntriesFromArray(T *arrayFirst, T *arrayLast, + const int *firstDelPos, const int *lastDelPos) +{ + CoinBigIndex delNum = static_cast< CoinBigIndex >(lastDelPos - firstDelPos); + if (delNum == 0) + return arrayLast; + + if (delNum < 0) + throw CoinError("trying to delete negative number of entries", + "CoinDeleteEntriesFromArray", ""); + + int *delSortedPos = NULL; + if (!(CoinIsSorted(firstDelPos, lastDelPos) && std::adjacent_find(firstDelPos, lastDelPos) == lastDelPos)) { + // the positions of the to be deleted is either not sorted or not unique + delSortedPos = new int[delNum]; + CoinDisjointCopy(firstDelPos, lastDelPos, delSortedPos); + std::sort(delSortedPos, delSortedPos + delNum); + delNum = static_cast< CoinBigIndex >(std::unique(delSortedPos, + delSortedPos + delNum) + - delSortedPos); + } + const int *delSorted = delSortedPos ? delSortedPos : firstDelPos; + + const CoinBigIndex last = delNum - 1; + int size = delSorted[0]; + for (CoinBigIndex i = 0; i < last; ++i) { + const int copyFirst = delSorted[i] + 1; + const int copyLast = delSorted[i + 1]; + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + } + const int copyFirst = delSorted[last] + 1; + const int copyLast = static_cast< int >(arrayLast - arrayFirst); + CoinCopy(arrayFirst + copyFirst, arrayFirst + copyLast, + arrayFirst + size); + size += copyLast - copyFirst; + + if (delSortedPos) + delete[] delSortedPos; + + return arrayFirst + size; +} + +//############################################################################# + +#define COIN_OWN_RANDOM_32 + +#if defined COIN_OWN_RANDOM_32 +/* Thanks to Stefano Gliozzi for providing an operating system + independent random number generator. */ + +/*! \brief Return a random number between 0 and 1 + + A platform-independent linear congruential generator. For a given seed, the + generated sequence is always the same regardless of the (32-bit) + architecture. This allows to build & test in different environments, getting + in most cases the same optimization path. + + Set \p isSeed to true and supply an integer seed to set the seed + (vid. #CoinSeedRandom) + + \todo Anyone want to volunteer an upgrade for 64-bit architectures? +*/ +inline double CoinDrand48(bool isSeed = false, unsigned int seed = 1) +{ + static unsigned int last = 123456; + if (isSeed) { + last = seed; + } else { + last = 1664525 * last + 1013904223; + return ((static_cast< double >(last)) / 4294967296.0); + } + return (0.0); +} + +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) +{ + CoinDrand48(true, iseed); +} + +#else // COIN_OWN_RANDOM_32 + +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return rand() / (double)RAND_MAX; } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand(iseed + 69822); } + +#else + +/// Return a random number between 0 and 1 +inline double CoinDrand48() { return drand48(); } +/// Set the seed for the random number generator +inline void CoinSeedRandom(int iseed) { srand48(iseed + 69822); } + +#endif + +#endif // COIN_OWN_RANDOM_32 + +//############################################################################# + +/** This function figures out whether file names should contain slashes or + backslashes as directory separator */ +inline char CoinFindDirSeparator() +{ + int size = 1000; + char *buf = 0; + while (true) { + buf = new char[size]; + if (getcwd(buf, size)) + break; + delete[] buf; + buf = 0; + size = 2 * size; + } + // if first char is '/' then it's unix and the dirsep is '/'. otherwise we + // assume it's dos and the dirsep is '\' + char dirsep = buf[0] == '/' ? '/' : '\\'; + delete[] buf; + return dirsep; +} +//############################################################################# + +inline int CoinStrNCaseCmp(const char *s0, const char *s1, + const size_t len) +{ + for (size_t i = 0; i < len; ++i) { + if (s0[i] == 0) { + return s1[i] == 0 ? 0 : -1; + } + if (s1[i] == 0) { + return 1; + } + const int c0 = std::tolower(s0[i]); + const int c1 = std::tolower(s1[i]); + if (c0 < c1) + return -1; + if (c0 > c1) + return 1; + } + return 0; +} + +//############################################################################# + +/// Swap the arguments. +template < class T > +inline void CoinSwap(T &x, T &y) +{ + T t = x; + x = y; + y = t; +} + +//############################################################################# + +/** This helper function copies an array to file + Returns 0 if OK, 1 if bad write. +*/ + +template < class T > +inline int +CoinToFile(const T *array, CoinBigIndex size, FILE *fp) +{ + CoinBigIndex numberWritten; + if (array && size) { + numberWritten = static_cast< CoinBigIndex >(fwrite(&size, sizeof(int), 1, fp)); + if (numberWritten != 1) + return 1; + numberWritten = static_cast< CoinBigIndex >(fwrite(array, sizeof(T), size_t(size), fp)); + if (numberWritten != size) + return 1; + } else { + size = 0; + numberWritten = static_cast< CoinBigIndex >(fwrite(&size, sizeof(int), 1, fp)); + if (numberWritten != 1) + return 1; + } + return 0; +} + +//############################################################################# + +/** This helper function copies an array from file and creates with new. + Passed in array is ignored i.e. not deleted. + But if NULL and size does not match and newSize 0 then leaves as NULL and 0 + Returns 0 if OK, 1 if bad read, 2 if size did not match. +*/ + +template < class T > +inline int +CoinFromFile(T *&array, CoinBigIndex size, FILE *fp, CoinBigIndex &newSize) +{ + CoinBigIndex numberRead; + numberRead = static_cast< CoinBigIndex >(fread(&newSize, sizeof(int), 1, fp)); + if (numberRead != 1) + return 1; + int returnCode = 0; + if (size != newSize && (newSize || array)) + returnCode = 2; + if (newSize) { + array = new T[newSize]; + numberRead = static_cast< CoinBigIndex >(fread(array, sizeof(T), newSize, fp)); + if (numberRead != newSize) + returnCode = 1; + } else { + array = NULL; + } + return returnCode; +} + +//############################################################################# + +/// Cube Root +#if 0 +inline double CoinCbrt(double x) +{ +#if defined(_MSC_VER) + return pow(x,(1./3.)); +#else + return cbrt(x); +#endif +} +#endif + +//----------------------------------------------------------------------------- + +/// This helper returns "sizeof" as an int +#define CoinSizeofAsInt(type) (static_cast< int >(sizeof(type))) +/// This helper returns "strlen" as an int +inline int +CoinStrlenAsInt(const char *string) +{ + return static_cast< int >(strlen(string)); +} + +/** Class for thread specific random numbers +*/ +#if defined COIN_OWN_RANDOM_32 +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { + seed_ = 12345678; + } + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + seed_ = seed; + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom &rhs) + { + seed_ = rhs.seed_; + } + // Assignment + CoinThreadRandom &operator=(const CoinThreadRandom &rhs) + { + if (this != &rhs) { + seed_ = rhs.seed_; + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(int seed) + { + seed_ = seed; + } + /** Get seed. */ + inline unsigned int getSeed() const + { + return seed_; + } + /// return a random number + inline double randomDouble() const + { + double retVal; + seed_ = 1664525 * (seed_) + 1013904223; + retVal = ((static_cast< double >(seed_)) / 4294967296.0); + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n = 0) + { + if (!n) + n = seed_ & 255; + for (int i = 0; i < n; i++) + randomDouble(); + } + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned int seed_; + //@} +}; +#else +class CoinThreadRandom { +public: + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + CoinThreadRandom() + { + seed_[0] = 50000; + seed_[1] = 40000; + seed_[2] = 30000; + } + /** Constructor wih seed. */ + CoinThreadRandom(const unsigned short seed[3]) + { + memcpy(seed_, seed, 3 * sizeof(unsigned short)); + } + /** Constructor wih seed. */ + CoinThreadRandom(int seed) + { + union { + int i[2]; + unsigned short int s[4]; + } put; + put.i[0] = seed; + put.i[1] = seed; + memcpy(seed_, put.s, 3 * sizeof(unsigned short)); + } + /** Destructor */ + ~CoinThreadRandom() {} + // Copy + CoinThreadRandom(const CoinThreadRandom &rhs) + { + memcpy(seed_, rhs.seed_, 3 * sizeof(unsigned short)); + } + // Assignment + CoinThreadRandom &operator=(const CoinThreadRandom &rhs) + { + if (this != &rhs) { + memcpy(seed_, rhs.seed_, 3 * sizeof(unsigned short)); + } + return *this; + } + + //@} + + /**@name Sets/gets */ + + //@{ + /** Set seed. */ + inline void setSeed(const unsigned short seed[3]) + { + memcpy(seed_, seed, 3 * sizeof(unsigned short)); + } + /** Set seed. */ + inline void setSeed(int seed) + { + union { + int i[2]; + unsigned short int s[4]; + } put; + put.i[0] = seed; + put.i[1] = seed; + memcpy(seed_, put.s, 3 * sizeof(unsigned short)); + } + /// return a random number + inline double randomDouble() const + { + double retVal; +#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN32__) + retVal = rand(); + retVal = retVal / (double)RAND_MAX; +#else + retVal = erand48(seed_); +#endif + return retVal; + } + /// make more random (i.e. for startup) + inline void randomize(int n = 0) + { + if (!n) { + n = seed_[0] + seed_[1] + seed_[2]; + n &= 255; + } + for (int i = 0; i < n; i++) + randomDouble(); + } + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Current seed + mutable unsigned short seed_[3]; + //@} +}; +#endif +#ifndef COIN_DETAIL +#define COIN_DETAIL_PRINT(s) \ + { \ + } +#else +#define COIN_DETAIL_PRINT(s) s +#endif +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinIndexedVector.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinIndexedVector.hpp new file mode 100644 index 000000000..41cb8fbd4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinIndexedVector.hpp @@ -0,0 +1,1437 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinIndexedVector_H +#define CoinIndexedVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include "CoinFinite.hpp" +#ifndef CLP_NO_VECTOR +#include "CoinPackedVectorBase.hpp" +#endif +#include "CoinSort.hpp" +#include "CoinHelperFunctions.hpp" +#include + +#ifndef COIN_FLOAT +#define COIN_INDEXED_TINY_ELEMENT 1.0e-50 +#define COIN_INDEXED_REALLY_TINY_ELEMENT 1.0e-100 +#else +#define COIN_INDEXED_TINY_ELEMENT 1.0e-35 +#define COIN_INDEXED_REALLY_TINY_ELEMENT 1.0e-39 +#endif + +/** Indexed Vector + +This stores values unpacked but apart from that is a bit like CoinPackedVector. +It is designed to be lightweight in normal use. + +It now has a "packed" mode when it is even more like CoinPackedVector + +Indices array has capacity_ extra chars which are zeroed and can +be used for any purpose - but must be re-zeroed + +Stores vector of indices and associated element values. +Supports sorting of indices. + +Does not support negative indices. + +Does NOT support testing for duplicates + +*** getElements is no longer supported + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 } + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its valuex1 + CoinIndexedVector r(ne,inx,el); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // sort Elements in increasing order + r.sortIncrElement(); + + // access each index and element + assert( r.getIndices ()[0]== 0 ); + assert( r.getIndices ()[1]== 1 ); + assert( r.getIndices ()[2]== 4 ); + assert( r.getIndices ()[3]== 2 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Tests for equality and equivalence + CoinIndexedVector r1; + r1=r; + assert( r==r1 ); + assert( r.equivalent(r1) ); + r.sortIncrElement(); + assert( r!=r1 ); + assert( r.equivalent(r1) ); + + // Add indexed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinIndexedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinIndexedVector { + friend void CoinIndexedVectorUnitTest(); + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline int getNumElements() const { return nElements_; } + /// Get indices of elements + inline const int *getIndices() const { return indices_; } + /// Get element values + // ** No longer supported virtual const double * getElements() const ; + /// Get indices of elements + inline int *getIndices() { return indices_; } + /** Get the vector as a dense vector. This is normal storage method. + The user should not not delete [] this. + */ + inline double *denseVector() const { return elements_; } + /// For very temporary use when user needs to borrow a dense vector + inline void setDenseVector(double *array) + { + elements_ = array; + } + /// For very temporary use when user needs to borrow an index vector + inline void setIndexVector(int *array) + { + indices_ = array; + } + /** Access the i'th element of the full storage vector. + */ + double &operator[](int i) const; + + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Set the size + inline void setNumElements(int value) + { + nElements_ = value; + if (!nElements_) + packedMode_ = false; + } + /// Reset the vector (as if were just created an empty vector). This leaves arrays! + void clear(); + /// Reset the vector (as if were just created an empty vector) + void empty(); + /// Clear even if in a bad way + void reallyClear(); + /** Assignment operator. */ + CoinIndexedVector &operator=(const CoinIndexedVector &); +#ifndef CLP_NO_VECTOR + /** Assignment operator from a CoinPackedVectorBase.
+ NOTE: This assumes no duplicates */ + CoinIndexedVector &operator=(const CoinPackedVectorBase &rhs); +#endif + /** Copy the contents of one vector into another. If multiplier is 1 + It is the equivalent of = but if vectors are same size does + not re-allocate memory just clears and copies */ + void copy(const CoinIndexedVector &rhs, double multiplier = 1.0); + + /** Borrow ownership of the arguments to this vector. + Size is the length of the unpacked elements vector. */ + void borrowVector(int size, int numberIndices, int *inds, double *elems); + + /** Return ownership of the arguments to this vector. + State after is empty . + */ + void returnVector(); + + /** Set vector numberIndices, indices, and elements. + NumberIndices is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. Assumed to have no duplicates */ + void setVector(int numberIndices, const int *inds, const double *elems); + + /** Set vector size, indices, and elements. + Size is the length of the unpacked elements vector. + The indices and elements vectors are copied into this class instance's + member data. We do not check for duplicate indices */ + void setVector(int size, int numberIndices, const int *inds, const double *elems); + + /** Elements set to have the same scalar value */ + void setConstant(int size, const int *inds, double elems); + + /** Indices are not specified and are taken to be 0,1,...,size-1 */ + void setFull(int size, const double *elems); + + /** Set an existing element in the indexed vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, double element); + + /// Insert an element into the vector + void insert(int index, double element); + /// Insert a nonzero element into the vector + inline void quickInsert(int index, double element) + { + assert(!elements_[index]); + indices_[nElements_++] = index; + assert(nElements_ <= capacity_); + elements_[index] = element; + } + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny */ + void add(int index, double element); + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny. + This version does no checking */ + inline void quickAdd(int index, double element) + { + if (elements_[index]) { + element += elements_[index]; + if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + elements_[index] = element; + } else { + elements_[index] = 1.0e-100; + } + } else if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + indices_[nElements_++] = index; + assert(nElements_ <= capacity_); + elements_[index] = element; + } + } + /** Insert or if exists add an element into the vector + Any resulting zero elements will be made tiny. + This knows element is nonzero + This version does no checking */ + inline void quickAddNonZero(int index, double element) + { + assert(element); + if (elements_[index]) { + element += elements_[index]; + if ((element > 0 ? element : -element) >= COIN_INDEXED_TINY_ELEMENT) { + elements_[index] = element; + } else { + elements_[index] = COIN_DBL_MIN; + } + } else { + indices_[nElements_++] = index; + assert(nElements_ <= capacity_); + elements_[index] = element; + } + } + /** Makes nonzero tiny. + This version does no checking */ + inline void zero(int index) + { + if (elements_[index]) + elements_[index] = COIN_DBL_MIN; + } + /** set all small values to zero and return number remaining + - < tolerance => 0.0 */ + int clean(double tolerance); + /// Same but packs down + int cleanAndPack(double tolerance); + /// Same but packs down and is safe (i.e. if order is odd) + int cleanAndPackSafe(double tolerance); + /// Mark as packed + inline void setPacked() + { + packedMode_ = true; + } +#ifndef NDEBUG + /// For debug check vector is clear i.e. no elements + void checkClear(); + /// For debug check vector is clean i.e. elements match indices + void checkClean(); +#else + inline void checkClear() {}; + inline void checkClean() {}; +#endif + /// Scan dense region and set up indices (returns number found) + int scan(); + /** Scan dense region from start to < end and set up indices + returns number found + */ + int scan(int start, int end); + /** Scan dense region and set up indices (returns number found). + Only ones >= tolerance */ + int scan(double tolerance); + /** Scan dense region from start to < end and set up indices + returns number found. Only >= tolerance + */ + int scan(int start, int end, double tolerance); + /// These are same but pack down + int scanAndPack(); + int scanAndPack(int start, int end); + int scanAndPack(double tolerance); + int scanAndPack(int start, int end, double tolerance); + /// Create packed array + void createPacked(int number, const int *indices, + const double *elements); + /// Create unpacked array + void createUnpacked(int number, const int *indices, + const double *elements); + /// Create unpacked singleton + void createOneUnpackedElement(int index, double element); + /// This is mainly for testing - goes from packed to indexed + void expand(); +#ifndef CLP_NO_VECTOR + /// Append a CoinPackedVector to the end + void append(const CoinPackedVectorBase &caboose); +#endif + /// Append a CoinIndexedVector to the end (with extra space) + void append(const CoinIndexedVector &caboose); + /// Append a CoinIndexedVector to the end and modify indices + void append(CoinIndexedVector &other, int adjustIndex, bool zapElements = false); + + /// Swap values in positions i and j of indices and elements + void swap(int i, int j); + + /// Throw away all entries in rows >= newSize + void truncate(int newSize); + /// Print out + void print() const; + //@} + /**@name Arithmetic operators. */ + //@{ + /// add value to every entry + void operator+=(double value); + /// subtract value from every entry + void operator-=(double value); + /// multiply every entry by value + void operator*=(double value); + /// divide every entry by value (** 0 vanishes) + void operator/=(double value); + //@} + + /**@name Comparison operators on two indexed vectors */ + //@{ +#ifndef CLP_NO_VECTOR + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinPackedVectorBase &rhs) const; + /// Not equal + bool operator!=(const CoinPackedVectorBase &rhs) const; +#endif + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinIndexedVector &rhs) const; + /// Not equal + bool operator!=(const CoinIndexedVector &rhs) const; + /// Equal with a tolerance (returns -1 or position of inequality). + int isApproximatelyEqual(const CoinIndexedVector &rhs, double tolerance = 1.0e-8) const; + //@} + + /**@name Index methods */ + //@{ + /// Get value of maximum index + int getMaxIndex() const; + /// Get value of minimum index + int getMinIndex() const; + //@} + + /**@name Sorting */ + //@{ + /** Sort the indexed storage vector (increasing indices). */ + void sort() + { + std::sort(indices_, indices_ + nElements_); + } + + void sortIncrIndex() + { + std::sort(indices_, indices_ + nElements_); + } + + void sortDecrIndex(); + + void sortIncrElement(); + + void sortDecrElement(); + void sortPacked(); + + //@} + + //############################################################################# + + /**@name Arithmetic operators on packed vectors. + + NOTE: These methods operate on those positions where at + least one of the arguments has a value listed. At those positions the + appropriate operation is executed, Otherwise the result of the operation is + considered 0.
+ NOTE 2: Because these methods return an object (they can't + return a reference, though they could return a pointer...) they are + very inefficient... + */ + //@{ + /// Return the sum of two indexed vectors + CoinIndexedVector operator+( + const CoinIndexedVector &op2); + + /// Return the difference of two indexed vectors + CoinIndexedVector operator-( + const CoinIndexedVector &op2); + + /// Return the element-wise product of two indexed vectors + CoinIndexedVector operator*( + const CoinIndexedVector &op2); + + /// Return the element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes) + CoinIndexedVector operator/( + const CoinIndexedVector &op2); + /// The sum of two indexed vectors + void operator+=(const CoinIndexedVector &op2); + + /// The difference of two indexed vectors + void operator-=(const CoinIndexedVector &op2); + + /// The element-wise product of two indexed vectors + void operator*=(const CoinIndexedVector &op2); + + /// The element-wise ratio of two indexed vectors (0.0/0.0 => 0.0) (0 vanishes) + void operator/=(const CoinIndexedVector &op2); + //@} + + /**@name Memory usage */ + //@{ + /** Reserve space. + If one knows the eventual size of the indexed vector, + then it may be more efficient to reserve the space. + */ + void reserve(int n); + /** capacity returns the size which could be accomodated without + having to reallocate storage. + */ + inline int capacity() const { return capacity_; } + inline void setCapacity(int value) + { + capacity_ = value; + } + /// Sets packed mode + inline void setPackedMode(bool yesNo) + { + packedMode_ = yesNo; + } + /// Gets packed mode + inline bool packedMode() const + { + return packedMode_; + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinIndexedVector(); + /** Alternate Constructors - set elements to vector of doubles */ + CoinIndexedVector(int size, const int *inds, const double *elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinIndexedVector(int size, const int *inds, double element); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinIndexedVector(int size, const double *elements); + /** Alternate Constructors - just size */ + CoinIndexedVector(int size); + /** Copy constructor. */ + CoinIndexedVector(const CoinIndexedVector &); + /** Copy constructor.2 */ + CoinIndexedVector(const CoinIndexedVector *); +#ifndef CLP_NO_VECTOR + /** Copy constructor from a PackedVectorBase. */ + CoinIndexedVector(const CoinPackedVectorBase &rhs); +#endif + /** Destructor */ + ~CoinIndexedVector(); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfSetVector(int size, + const int *inds, const double *elems); + void gutsOfSetVector(int size, int numberIndices, + const int *inds, const double *elems); + void gutsOfSetPackedVector(int size, int numberIndices, + const int *inds, const double *elems); + /// + void gutsOfSetConstant(int size, + const int *inds, double value); + //@} + +protected: + /**@name Private member data */ + //@{ + /// Vector indices + int *indices_; + ///Vector elements + double *elements_; + /// Size of indices and packed elements vectors + int nElements_; + /// Amount of memory allocated for indices_, and elements_. + int capacity_; + /// Offset to get where new allocated array + int offset_; + /// If true then is operating in packed mode + bool packedMode_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CoinIndexedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CoinIndexedVectorUnitTest(); +/** Pointer with length in bytes + + This has a pointer to an array and the number of bytes in array. + If number of bytes==-1 then + CoinConditionalNew deletes existing pointer and returns new pointer + of correct size (and number bytes still -1). + CoinConditionalDelete deletes existing pointer and NULLs it. + So behavior is as normal (apart from New deleting pointer which will have + no effect with good coding practices. + If number of bytes >=0 then + CoinConditionalNew just returns existing pointer if array big enough + otherwise deletes existing pointer, allocates array with spare 1%+64 bytes + and updates number of bytes + CoinConditionalDelete sets number of bytes = -size-2 and then array + returns NULL +*/ +class CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return static_cast< CoinBigIndex >(size_); + } + /// Get the size + inline CoinBigIndex rawSize() const + { + return static_cast< CoinBigIndex >(size_); + } + /// See if persistence already on + inline bool switchedOn() const + { + return size_ != -1; + } + /// Get the capacity (just read it) + inline CoinBigIndex capacity() const + { + return (size_ > -2) ? static_cast< CoinBigIndex >(size_) : static_cast< CoinBigIndex >((-size_) - 2); + } + /// Set the capacity to >=0 if <=-2 + inline void setCapacity() + { + if (size_ <= -2) + size_ = (-size_) - 2; + } + /// Get Array + inline const char *array() const + { + return (size_ > -2) ? array_ : NULL; + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value; + } +#if COIN_BIG_INDEX + /// Set the size + inline void setSize(long long value) + { + size_ = value; + } +#endif + /// Set the size to -1 + inline void switchOff() + { + size_ = -1; + } + /// Set the size to -2 and alignment + inline void switchOn(int alignment = 3) + { + size_ = -2; + alignment_ = alignment; + } + /// Does what is needed to set persistence + void setPersistence(int flag, int currentLength); + /// Zero out array + void clear(); + /// Swaps memory between two members + void swap(CoinArrayWithLength &other); + /// Extend a persistent array keeping data (size in bytes) + void extend(int newSize); +#if COIN_BIG_INDEX + /// Extend a persistent array keeping data (size in bytes) + void extend(long long newSize); +#endif + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + char *conditionalNew(CoinBigIndex sizeWanted); + /// Conditionally deletes + void conditionalDelete(); + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinArrayWithLength() + : array_(NULL) + , size_(-1) + , offset_(0) + , alignment_(0) + { + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinArrayWithLength(CoinBigIndex size) + : size_(-1) + , offset_(0) + , alignment_(0) + { + array_ = new char[size]; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + mode>0 size_ set to size and zeroed + if size<=0 just does alignment + If abs(mode) >2 then align on that as power of 2 + */ + CoinArrayWithLength(CoinBigIndex size, int mode); + /** Copy constructor. */ + CoinArrayWithLength(const CoinArrayWithLength &rhs); + /** Copy constructor.2 */ + CoinArrayWithLength(const CoinArrayWithLength *rhs); + /** Assignment operator. */ + CoinArrayWithLength &operator=(const CoinArrayWithLength &rhs); + /** Assignment with length (if -1 use internal length) */ + void copy(const CoinArrayWithLength &rhs, int numberBytes = -1); + /** Assignment with length - does not copy */ + void allocate(const CoinArrayWithLength &rhs, CoinBigIndex numberBytes); + /** Destructor */ + ~CoinArrayWithLength(); + /// Get array with alignment + void getArray(CoinBigIndex size); + /// Really get rid of array with alignment + void reallyFreeArray(); + /// Get enough space (if more needed then do at least needed) + void getCapacity(CoinBigIndex numberBytes, CoinBigIndex numberIfNeeded = -1); + //@} + +protected: + /**@name Private member data */ + //@{ + /// Array + char *array_; + /// Size of array in bytes + CoinBigIndex size_; + /// Offset of array + int offset_; + /// Alignment wanted (power of 2) + int alignment_; + //@} +}; +/// double * version + +class CoinDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(double); + } + /// Get Array + inline double *array() const + { + return reinterpret_cast< double * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(double); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline double *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< double * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(double)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinDoubleArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinDoubleArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(double)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(double), mode) + { + } + /** Copy constructor. */ + inline CoinDoubleArrayWithLength(const CoinDoubleArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinDoubleArrayWithLength(const CoinDoubleArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinDoubleArrayWithLength &operator=(const CoinDoubleArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// CoinFactorizationDouble * version + +class CoinFactorizationDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(CoinFactorizationDouble); + } + /// Get Array + inline CoinFactorizationDouble *array() const + { + return reinterpret_cast< CoinFactorizationDouble * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(CoinFactorizationDouble); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline CoinFactorizationDouble *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< CoinFactorizationDouble * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(CoinFactorizationDouble)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinFactorizationDoubleArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinFactorizationDoubleArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(CoinFactorizationDouble)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinFactorizationDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(CoinFactorizationDouble), mode) + { + } + /** Copy constructor. */ + inline CoinFactorizationDoubleArrayWithLength(const CoinFactorizationDoubleArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinFactorizationDoubleArrayWithLength(const CoinFactorizationDoubleArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinFactorizationDoubleArrayWithLength &operator=(const CoinFactorizationDoubleArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// CoinFactorizationLongDouble * version + +class CoinFactorizationLongDoubleArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(long double); + } + /// Get Array + inline long double *array() const + { + return reinterpret_cast< long double * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(long double); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline long double *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< long double * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(long double)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinFactorizationLongDoubleArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinFactorizationLongDoubleArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(long double)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinFactorizationLongDoubleArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(long double), mode) + { + } + /** Copy constructor. */ + inline CoinFactorizationLongDoubleArrayWithLength(const CoinFactorizationLongDoubleArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinFactorizationLongDoubleArrayWithLength(const CoinFactorizationLongDoubleArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinFactorizationLongDoubleArrayWithLength &operator=(const CoinFactorizationLongDoubleArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// int * version + +class CoinIntArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(int); + } + /// Get Array + inline int *array() const + { + return reinterpret_cast< int * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(int); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline int *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< int * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(int)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinIntArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinIntArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(int)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinIntArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(int), mode) + { + } + /** Copy constructor. */ + inline CoinIntArrayWithLength(const CoinIntArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinIntArrayWithLength(const CoinIntArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinIntArrayWithLength &operator=(const CoinIntArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// CoinBigIndex * version + +class CoinBigIndexArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(CoinBigIndex); + } + /// Get Array + inline CoinBigIndex *array() const + { + return reinterpret_cast< CoinBigIndex * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(CoinBigIndex value) + { + size_ = value * CoinSizeofAsInt(CoinBigIndex); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline CoinBigIndex *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< CoinBigIndex * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(CoinBigIndex)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinBigIndexArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinBigIndexArrayWithLength(CoinBigIndex size) + { + array_ = new char[size * CoinSizeofAsInt(CoinBigIndex)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinBigIndexArrayWithLength(CoinBigIndex size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(CoinBigIndex), mode) + { + } + /** Copy constructor. */ + inline CoinBigIndexArrayWithLength(const CoinBigIndexArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinBigIndexArrayWithLength(const CoinBigIndexArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinBigIndexArrayWithLength &operator=(const CoinBigIndexArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// unsigned int * version + +class CoinUnsignedIntArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(unsigned int); + } + /// Get Array + inline unsigned int *array() const + { + return reinterpret_cast< unsigned int * >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(unsigned int); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline unsigned int *conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< unsigned int * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(unsigned int)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinUnsignedIntArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinUnsignedIntArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(unsigned int)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinUnsignedIntArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(unsigned int), mode) + { + } + /** Copy constructor. */ + inline CoinUnsignedIntArrayWithLength(const CoinUnsignedIntArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinUnsignedIntArrayWithLength(const CoinUnsignedIntArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinUnsignedIntArrayWithLength &operator=(const CoinUnsignedIntArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// void * version + +class CoinVoidStarArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / CoinSizeofAsInt(void *); + } + /// Get Array + inline void **array() const + { + return reinterpret_cast< void ** >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * CoinSizeofAsInt(void *); + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline void **conditionalNew(CoinBigIndex sizeWanted) + { + return reinterpret_cast< void ** >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*CoinSizeofAsInt(void *)) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinVoidStarArrayWithLength() + { + array_ = NULL; + size_ = -1; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinVoidStarArrayWithLength(int size) + { + array_ = new char[size * CoinSizeofAsInt(void *)]; + size_ = -1; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinVoidStarArrayWithLength(int size, int mode) + : CoinArrayWithLength(size * CoinSizeofAsInt(void *), mode) + { + } + /** Copy constructor. */ + inline CoinVoidStarArrayWithLength(const CoinVoidStarArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinVoidStarArrayWithLength(const CoinVoidStarArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinVoidStarArrayWithLength &operator=(const CoinVoidStarArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} +}; +/// arbitrary version + +class CoinArbitraryArrayWithLength : public CoinArrayWithLength { + +public: + /**@name Get methods. */ + //@{ + /// Get the size + inline CoinBigIndex getSize() const + { + return size_ / lengthInBytes_; + } + /// Get Array + inline void **array() const + { + return reinterpret_cast< void ** >((size_ > -2) ? array_ : NULL); + } + //@} + + /**@name Set methods */ + //@{ + /// Set the size + inline void setSize(int value) + { + size_ = value * lengthInBytes_; + } + //@} + + /**@name Condition methods */ + //@{ + /// Conditionally gets new array + inline char *conditionalNew(CoinBigIndex length, CoinBigIndex sizeWanted) + { + lengthInBytes_ = length; + return reinterpret_cast< char * >(CoinArrayWithLength::conditionalNew(sizeWanted >= 0 ? static_cast< long long >((sizeWanted)*lengthInBytes_) : -1)); + } + //@} + + /**@name Constructors and destructors */ + //@{ + /** Default constructor - NULL*/ + inline CoinArbitraryArrayWithLength(int length = 1) + { + array_ = NULL; + size_ = -1; + lengthInBytes_ = length; + } + /** Alternate Constructor - length in bytes - size_ -1 */ + inline CoinArbitraryArrayWithLength(int length, int size) + { + array_ = new char[size * length]; + size_ = -1; + lengthInBytes_ = length; + } + /** Alternate Constructor - length in bytes + mode - 0 size_ set to size + 1 size_ set to size and zeroed + */ + inline CoinArbitraryArrayWithLength(int length, int size, int mode) + : CoinArrayWithLength(size * length, mode) + { + lengthInBytes_ = length; + } + /** Copy constructor. */ + inline CoinArbitraryArrayWithLength(const CoinArbitraryArrayWithLength &rhs) + : CoinArrayWithLength(rhs) + { + } + /** Copy constructor.2 */ + inline CoinArbitraryArrayWithLength(const CoinArbitraryArrayWithLength *rhs) + : CoinArrayWithLength(rhs) + { + } + /** Assignment operator. */ + inline CoinArbitraryArrayWithLength &operator=(const CoinArbitraryArrayWithLength &rhs) + { + CoinArrayWithLength::operator=(rhs); + return *this; + } + //@} + +protected: + /**@name Private member data */ + //@{ + /// Length in bytes + CoinBigIndex lengthInBytes_; + //@} +}; +class CoinPartitionedVector : public CoinIndexedVector { + +public: +#ifndef COIN_PARTITIONS +#define COIN_PARTITIONS 8 +#endif + /**@name Get methods. */ + //@{ + /// Get the size of a partition + inline int getNumElements(int partition) const + { + assert(partition < COIN_PARTITIONS); + return numberElementsPartition_[partition]; + } + /// Get number of partitions + inline int getNumPartitions() const + { + return numberPartitions_; + } + /// Get the size + inline int getNumElements() const { return nElements_; } + /// Get starts + inline int startPartition(int partition) const + { + assert(partition <= COIN_PARTITIONS); + return startPartition_[partition]; + } + /// Get starts + inline const int *startPartitions() const + { + return startPartition_; + } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Set the size of a partition + inline void setNumElementsPartition(int partition, int value) + { + assert(partition < COIN_PARTITIONS); + if (numberPartitions_) + numberElementsPartition_[partition] = value; + } + /// Set the size of a partition (just for a tiny while) + inline void setTempNumElementsPartition(int partition, int value) + { + assert(partition < COIN_PARTITIONS); + numberElementsPartition_[partition] = value; + } + /// Add up number of elements in partitions + void computeNumberElements(); + /// Add up number of elements in partitions and pack and get rid of partitions + void compact(); + /** Reserve space. + */ + void reserve(int n); + /// Setup partitions (needs end as well) + void setPartitions(int number, const int *starts); + /// Reset the vector (as if were just created an empty vector). Gets rid of partitions + void clearAndReset(); + /// Reset the vector (as if were just created an empty vector). Keeps partitions + void clearAndKeep(); + /// Clear a partition. + void clearPartition(int partition); +#ifndef NDEBUG + /// For debug check vector is clear i.e. no elements + void checkClear(); + /// For debug check vector is clean i.e. elements match indices + void checkClean(); +#else + inline void checkClear() {}; + inline void checkClean() {}; +#endif + /// Scan dense region and set up indices (returns number found) + int scan(int partition, double tolerance = 0.0); + /** Scan dense region from start to < end and set up indices + returns number found + */ + /// Print out + void print() const; + //@} + + /**@name Sorting */ + //@{ + /** Sort the indexed storage vector (increasing indices). */ + void sort(); + //@} + + /**@name Constructors and destructors (not all wriiten) */ + //@{ + /** Default constructor */ + CoinPartitionedVector(); + /** Alternate Constructors - set elements to vector of doubles */ + CoinPartitionedVector(int size, const int *inds, const double *elems); + /** Alternate Constructors - set elements to same scalar value */ + CoinPartitionedVector(int size, const int *inds, double element); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinPartitionedVector(int size, const double *elements); + /** Alternate Constructors - just size */ + CoinPartitionedVector(int size); + /** Copy constructor. */ + CoinPartitionedVector(const CoinPartitionedVector &); + /** Copy constructor.2 */ + CoinPartitionedVector(const CoinPartitionedVector *); + /** Assignment operator. */ + CoinPartitionedVector &operator=(const CoinPartitionedVector &); + /** Destructor */ + ~CoinPartitionedVector(); + //@} +protected: + /**@name Private member data */ + //@{ + /// Starts + int startPartition_[COIN_PARTITIONS + 1]; + /// Size of indices in a partition + int numberElementsPartition_[COIN_PARTITIONS]; + /// Number of partitions (0 means off) + int numberPartitions_; + //@} +}; +inline double *roundUpDouble(double *address) +{ + // align on 64 byte boundary + CoinInt64 xx = reinterpret_cast< CoinInt64 >(address); + int iBottom = static_cast< int >(xx & 63); + if (iBottom) + return address + ((64 - iBottom) >> 3); + else + return address; +} +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinLpIO.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinLpIO.hpp new file mode 100644 index 000000000..37ed07220 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinLpIO.hpp @@ -0,0 +1,836 @@ +/* $Id$ */ +// Last edit: 11/5/08 +// +// Name: CoinLpIO.hpp; Support for Lp files +// Author: Francois Margot +// Tepper School of Business +// Carnegie Mellon University, Pittsburgh, PA 15213 +// email: fmargot@andrew.cmu.edu +// Date: 12/28/03 +//----------------------------------------------------------------------------- +// Copyright (C) 2003, Francois Margot, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinLpIO_H +#define CoinLpIO_H + +#include + +#include "CoinPackedMatrix.hpp" +#include "CoinMessage.hpp" +#include "CoinFileIO.hpp" +class CoinSet; + +const int MAX_OBJECTIVES = 2; + +typedef int COINColumnIndex; + +/** Class to read and write Lp files + + Lp file format: + +/ this is a comment
+\ this too
+ Min
+ obj: x0 + x1 + 3 x2 - 4.5 xyr + 1
+ s.t.
+ cons1: x0 - x2 - 2.3 x4 <= 4.2 / this is another comment
+ c2: x1 + x2 >= 1
+ cc: x1 + x2 + xyr = 2
+ Bounds
+ 0 <= x1 <= 3
+ 1 >= x2
+ x3 = 1
+ -2 <= x4 <= Inf
+ xyr free
+ Integers
+ x0
+ Generals
+ x1 xyr
+ Binaries
+ x2
+ End + +Notes:

    +
  • Keywords are: Min, Max, Minimize, Maximize, s.t., Subject To, + Bounds, Integers, Generals, Binaries, Semis, End, Free, Inf. +
  • Keywords are not case sensitive and may be in plural or singular form. + They should not be used as objective, row or column names. +
  • Bounds, Integers, Generals, Binaries sections are optional. +
  • Generals and Integers are synonymous. +
  • Bounds section (if any) must come before Integers, Generals, and + Binaries sections. +
  • Row names must be followed by ':' without blank space. + Row names are optional. If row names are present, + they must be distinct (if the k-th constraint has no given name, its name + is set automatically to "consk" for k=0,...,). + For valid row names, see the method is_invalid_name(). +
  • Column names must be followed by a blank space. They must be distinct. + For valid column names, see the method is_invalid_name(). +
  • Multiple objectives may be specified, but when there are multiple + objectives, they must have names (to indicate where each one starts). +
  • The objective function names must be followed by ':' without blank space. + If there is a single objective, the objective function name is optional. + If no name is given, the name is set to "obj" by default. + For valid objective function names, see the method is_invalid_name(). +
  • Ranged constraints are written as two constraints. + If a name is given for a ranged constraint, the upper bound constraint + has that name and the lower bound constraint has that name with "_low" + as suffix. This should be kept in mind when assigning names to ranged + constraint, as the resulting name must be distinct from all the other + names and be considered valid by the method is_invalid_name(). +
  • At most one term related to any single variable may appear in the + objective function; if more than one term are present, only the last + one is taken into account. + At most one constant term may appear in the objective function; + if present, it must appear last. +
  • Default bounds are 0 for lower bound and +infinity for upper bound. +
  • Free variables get default lower bound -infinity and + default upper bound +infinity. Writing "x0 Free" in an + LP file means "set lower bound on x0 to -infinity". +
  • If more than one upper (resp. lower) bound on a variable appears in + the Bounds section, the last one is the one taken into + account. The bounds for a binary variable are set to 0/1 only if this + bound is stronger than the bound obtained from the Bounds section. +
  • Numbers larger than DBL_MAX (or larger than 1e+400) in the input file + might crash the code. +
  • A comment must start with '\' or '/'. That symbol must either be + the first character of a line or be preceded by a blank space. The + comment ends at the end of the + line. Comments are skipped while reading an Lp file and they may be + inserted anywhere. +
+*/ +class CoinLpIO { + friend void CoinLpIOUnitTest(const std::string &lpDir); + +public: + /**@name Constructor and Destructor */ + //@{ + /// Default Constructor + CoinLpIO(); + + /// Does the heavy lifting for destruct and assignment. + void gutsOfDestructor(); + + /// Does the heavy lifting for copy and assignment + void gutsOfCopy(const CoinLpIO &); + + /// assignment operator + CoinLpIO &operator=(const CoinLpIO &rhs); + + /// Copy constructor + CoinLpIO(const CoinLpIO &); + + /// Destructor + ~CoinLpIO(); + + /** Free the vector previous_names_[section] and set + card_previous_names_[section] to 0. + section = 0 for row names, + section = 1 for column names. + */ + void freePreviousNames(const int section); + + /// Free all memory (except memory related to hash tables and objName_). + void freeAll(); + //@} + + /** A quick inlined function to convert from lb/ub style constraint + definition to sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char &sense, double &right, double &range) const; + + /**@name Queries */ + //@{ + + /// Get the problem name + const char *getProblemName() const; + + /// Set problem name + void setProblemName(const char *name); + + /// Get number of columns + int getNumCols() const; + + /// Get number of rows + int getNumRows() const; + + /// Get number of nonzero elements + CoinBigIndex getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + const double *getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + const double *getColUpper() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + const double *getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + const double *getRowUpper() const; + /** Get pointer to array[getNumRows()] of constraint senses. +
    +
  • 'L': <= constraint +
  • 'E': = constraint +
  • 'G': >= constraint +
  • 'R': ranged constraint +
  • 'N': free constraint +
+ */ + const char *getRowSense() const; + + /** Get pointer to array[getNumRows()] of constraint right-hand sides. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint right-hand side (rhs) is set as +
    +
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] +
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0 +
+ */ + const double *getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint range (rowrange) is set as +
    +
  • if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] +
  • if rowsense()[i] != 'R' then + rowrange()[i] is 0.0 +
+ Put another way, only ranged constraints have a nontrivial value for + rowrange. + */ + const double *getRowRange() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const int getNumObjectives() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const double *getObjCoefficients() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients for objective j + const double *getObjCoefficients(int j) const; + + /// Get pointer to row-wise copy of the coefficient matrix + const CoinPackedMatrix *getMatrixByRow() const; + + /// Get pointer to column-wise copy of the coefficient matrix + const CoinPackedMatrix *getMatrixByCol() const; + + /// Get objective function name + const char *getObjName() const; + + /// Get objective function name for objective j + const char *getObjName(int j) const; + + /// Get pointer to array[*card_prev] of previous row names. + /// The value of *card_prev might be different than getNumRows()+1 if + /// non distinct + /// row names were present or if no previous names were saved or if + /// the object was holding a different problem before. + void getPreviousRowNames(char const *const *prev, + int *card_prev) const; + + /// Get pointer to array[*card_prev] of previous column names. + /// The value of *card_prev might be different than getNumCols() if non + /// distinct column names were present of if no previous names were saved, + /// or if the object was holding a different problem before. + void getPreviousColNames(char const *const *prev, + int *card_prev) const; + + /// Get pointer to array[getNumRows()+1] of row names, including + /// objective function name as last entry. + char const *const *getRowNames() const; + + /// Get pointer to array[getNumCols()] of column names + char const *const *getColNames() const; + + /// Return the row name for the specified index. + /// Return the objective function name if index = getNumRows(). + /// Return 0 if the index is out of range or if row names are not defined. + const char *rowName(int index) const; + + /// Return the column name for the specified index. + /// Return 0 if the index is out of range or if column names are not + /// defined. + const char *columnName(int index) const; + + /// Return the index for the specified row name. + /// Return getNumRows() for the objective function name. + /// Return -1 if the name is not found. + int rowIndex(const char *name) const; + + /// Return the index for the specified column name. + /// Return -1 if the name is not found. + int columnIndex(const char *name) const; + + ///Returns the (constant) objective offset + double objectiveOffset() const; + + ///Returns the (constant) objective offset for objective j + double objectiveOffset(int j) const; + + /// Set objective offset + inline void setObjectiveOffset(double value) + { + objectiveOffset_[0] = value; + } + /// Return true if maximization problem reformulated as minimization + inline bool wasMaximization() const + { + return wasMaximization_; + } + + /// Set objective offset + inline void setObjectiveOffset(double value, int j) + { + objectiveOffset_[j] = value; + } + + /// Return true if a column is an integer (binary or general + /// integer) variable + bool isInteger(int columnNumber) const; + + /// Get characteristic vector of integer variables + const char *integerColumns() const; + //@} + + /**@name Parameters */ + //@{ + /// Get infinity + double getInfinity() const; + + /// Set infinity. Any number larger is considered infinity. + /// Default: DBL_MAX + void setInfinity(const double); + + /// Get epsilon + double getEpsilon() const; + + /// Set epsilon. + /// Default: 1e-5. + void setEpsilon(const double); + + /// Get numberAcross, the number of monomials to be printed per line + int getNumberAcross() const; + + /// Set numberAcross. + /// Default: 10. + void setNumberAcross(const int); + + /// Get decimals, the number of digits to write after the decimal point + int getDecimals() const; + + /// Set decimals. + /// Default: 5 + void setDecimals(const int); + //@} + + /**@name Public methods */ + //@{ + /** Set the data of the object. + Set it from the coefficient matrix m, the lower bounds + collb, the upper bounds colub, objective function obj_coeff, + integrality vector integrality, lower/upper bounds on the constraints. + The sense of optimization of the objective function is assumed to be + a minimization. + Numbers larger than DBL_MAX (or larger than 1e+400) + might crash the code. There are two version. The second one is for + setting multiple objectives. + */ + void setLpDataWithoutRowAndColNames( + const CoinPackedMatrix &m, + const double *collb, const double *colub, + const double *obj_coeff, + const char *integrality, + const double *rowlb, const double *rowub); + + void setLpDataWithoutRowAndColNames( + const CoinPackedMatrix &m, + const double *collb, const double *colub, + const double *obj_coeff[MAX_OBJECTIVES], + int num_objectives, + const char *integrality, + const double *rowlb, const double *rowub); + + /** Return 0 if buff is a valid name for a row, a column or objective + function, return a positive number otherwise. + If parameter ranged = true, the name is intended for a ranged + constraint.
+ Return 1 if the name has more than 100 characters (96 characters + for a ranged constraint name, as "_low" will be added to the name).
+ Return 2 if the name starts with a number.
+ Return 3 if the name is not built with + the letters a to z, A to Z, the numbers 0 to 9 or the characters + " ! # $ % & ( ) . ; ? @ _ ' ` { } ~
+ Return 4 if the name is a keyword.
+ Return 5 if the name is empty or NULL. */ + int is_invalid_name(const char *buff, const bool ranged) const; + + /** Return 0 if each of the card_vnames entries of vnames is a valid name, + return a positive number otherwise. The return value, if not 0, is the + return value of is_invalid_name() for the last invalid name + in vnames. If check_ranged = true, the names are row names and + names for ranged constaints must be checked for additional restrictions + since "_low" will be added to the name if an Lp file is written. + When check_ranged = true, card_vnames must have getNumRows()+1 entries, + with entry vnames[getNumRows()] being the + name of the objective function. + For a description of valid names and return values, see the method + is_invalid_name(). + + This method must not be called with check_ranged = true before + setLpDataWithoutRowAndColNames() has been called, since access + to the indices of all the ranged constraints is required. + */ + int are_invalid_names(char const *const *vnames, + const int card_vnames, + const bool check_ranged) const; + + /// Set objective function name to the default "obj" and row + /// names to the default "cons0", "cons1", ... + void setDefaultRowNames(); + + /// Set column names to the default "x0", "x1", ... + void setDefaultColNames(); + + /** Set the row and column names. + The array rownames must either be NULL or have exactly getNumRows()+1 + distinct entries, + each of them being a valid name (see is_invalid_name()) and the + last entry being the intended name for the objective function. + If rownames is NULL, existing row names and objective function + name are not changed. + If rownames is deemed invalid, default row names and objective function + name are used (see setDefaultRowNames()). The memory location of + array rownames (or its entries) should not be related + to the memory location of the array (or entries) obtained from + getRowNames() or getPreviousRowNames(), as the call to + setLpDataRowAndColNames() modifies the corresponding arrays. + Unpredictable results + are obtained if this requirement is ignored. + + Similar remarks apply to the array colnames, which must either be + NULL or have exactly getNumCols() entries. + */ + void setLpDataRowAndColNames(char const *const *const rownames, + char const *const *const colnames); + + /** Write the data in Lp format in the file with name filename. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + Write objective function name and row names if useRowNames = true. + + Ranged constraints are written as two constraints. + If row names are used, the upper bound constraint has the + name of the original ranged constraint and the + lower bound constraint has for name the original name with + "_low" as suffix. If doing so creates two identical row names, + default row names are used (see setDefaultRowNames()). + */ + int writeLp(const char *filename, + const double epsilon, + const int numberAcross, + const int decimals, + const bool useRowNames = true); + + /** Write the data in Lp format in the file pointed to by the paramater fp. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + Write objective function name and row names if useRowNames = true. + + Ranged constraints are written as two constraints. + If row names are used, the upper bound constraint has the + name of the original ranged constraint and the + lower bound constraint has for name the original name with + "_low" as suffix. If doing so creates two identical row names, + default row names are used (see setDefaultRowNames()). + */ + int writeLp(FILE *fp, + const double epsilon, + const int numberAcross, + const int decimals, + const bool useRowNames = true); + + /// Write the data in Lp format in the file with name filename. + /// Write objective function name and row names if useRowNames = true. + int writeLp(const char *filename, const bool useRowNames = true); + + /// Write the data in Lp format in the file pointed to by the parameter fp. + /// Write objective function name and row names if useRowNames = true. + int writeLp(FILE *fp, const bool useRowNames = true); + + /// Read the data in Lp format from the file with name filename, using + /// the given value for epsilon. If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(const char *filename, const double epsilon); + + /// Read the data in Lp format from the file with name filename. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(const char *filename); + + /// Read the data in Lp format from the file stream, using + /// the given value for epsilon. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(FILE *fp, const double epsilon); + + /// Read the data in Lp format from the file stream. + /// If the original problem is + /// a maximization problem, the objective function is immediadtly + /// flipped to get a minimization problem. + void readLp(FILE *fp); + + /// Does work of readLp + void readLp(); + /// Dump the data. Low level method for debugging. + void print() const; + + /// Load in SOS stuff + void loadSOS(int numberSets, const CoinSet *sets); + + /// Load in SOS stuff + void loadSOS(int numberSets, const CoinSet **sets); + + /// Number of SOS sets + inline int numberSets() const + { + return numberSets_; + } + + /// Set information + inline CoinSet **setInformation() const + { + return set_; + } + //@} + /**@name Message handling */ + //@{ + /** Pass in Message handler + + Supply a custom message handler. It will not be destroyed when the + CoinMpsIO object is destroyed. + */ + void passInMessageHandler(CoinMessageHandler *handler); + + /// Set the language for messages. + void newLanguage(CoinMessages::Language language); + + /// Set the language for messages. + inline void setLanguage(CoinMessages::Language language) { newLanguage(language); } + + /// Return the message handler + inline CoinMessageHandler *messageHandler() const { return handler_; } + + /// Return the messages + inline CoinMessages messages() { return messages_; } + /// Return the messages pointer + inline CoinMessages *messagesPointer() { return &messages_; } + //@} + +protected: + /// Problem name + char *problemName_; + + /// Message handler + CoinMessageHandler *handler_; + /** Flag to say if the message handler is the default handler. + + If true, the handler will be destroyed when the CoinMpsIO + object is destroyed; if false, it will not be destroyed. + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + + /// Number of rows + int numberRows_; + + /// Number of columns + int numberColumns_; + + /// Number of elements + CoinBigIndex numberElements_; + + /// Pointer to column-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByColumn_; + + /// Pointer to row-wise copy of problem matrix coefficients. + CoinPackedMatrix *matrixByRow_; + + /// Pointer to dense vector of row lower bounds + double *rowlower_; + + /// Pointer to dense vector of row upper bounds + double *rowupper_; + + /// Pointer to dense vector of column lower bounds + double *collower_; + + /// Pointer to dense vector of column upper bounds + double *colupper_; + + /// Pointer to dense vector of row rhs + mutable double *rhs_; + + /** Pointer to dense vector of slack variable upper bounds for ranged + constraints (undefined for non-ranged constraints) + */ + mutable double *rowrange_; + + /// Pointer to dense vector of row senses + mutable char *rowsense_; + + /// Pointer to dense vector of objective coefficients + double *objective_[MAX_OBJECTIVES]; + + /// Number of objectives + int num_objectives_; + + /// Constant offset for objective value + double objectiveOffset_[MAX_OBJECTIVES]; + + /// Pointer to dense vector specifying if a variable is continuous + /// (0) or integer (1). Added (3) sc (4) sc int. + char *integerType_; + + /// Pointer to sets + CoinSet **set_; + + /// Number of sets + int numberSets_; + + /// Current file name + char *fileName_; + + /// Value to use for infinity + double infinity_; + + /// Value to use for epsilon + double epsilon_; + + /// Number of monomials printed in a row + int numberAcross_; + + /// Number of decimals printed for coefficients + int decimals_; + + /// Objective function name + char *objName_[MAX_OBJECTIVES]; + + /// Maximization reformulation flag + bool wasMaximization_; + + /** Row names (including objective function name) + and column names when stopHash() for the corresponding + section was last called or for initial names (deemed invalid) + read from a file.
+ section = 0 for row names, + section = 1 for column names. */ + char **previous_names_[2]; + + /// card_previous_names_[section] holds the number of entries in the vector + /// previous_names_[section]. + /// section = 0 for row names, + /// section = 1 for column names. + int card_previous_names_[2]; + + /// Row names (including objective function name) + /// and column names (linked to Hash tables). + /// section = 0 for row names, + /// section = 1 for column names. + char **names_[2]; + + typedef struct { + int index, next; + } CoinHashLink; + + /// Maximum number of entries in a hash table section. + /// section = 0 for row names, + /// section = 1 for column names. + int maxHash_[2]; + + /// Number of entries in a hash table section. + /// section = 0 for row names, + /// section = 1 for column names. + int numberHash_[2]; + + /// Hash tables with two sections. + /// section = 0 for row names (including objective function name), + /// section = 1 for column names. + mutable CoinHashLink *hash_[2]; + + /// Current buffer (needed so can get rid of blanks with : + mutable char inputBuffer_[1028]; + /// Current buffer length (negative if not got eol) + mutable int bufferLength_; + /// Current buffer position + mutable int bufferPosition_; + /// File handler + CoinFileInput *input_; + /// If already inserted one End + mutable bool eofFound_; + /// Get next string (returns number in) + int fscanfLpIO(char *buff) const; + /// Get next line into inputBuffer_ (returns number in) + int newCardLpIO() const; + + /// Build the hash table for the given names. The parameter number is + /// the cardinality of parameter names. Remove duplicate names. + /// + /// section = 0 for row names, + /// section = 1 for column names. + void startHash(char const *const *const names, + const COINColumnIndex number, + int section); + + /// Delete hash storage. If section = 0, it also frees objName_. + /// section = 0 for row names, + /// section = 1 for column names. + void stopHash(int section); + + /// Return the index of the given name, return -1 if the name is not found. + /// Return getNumRows() for the objective function name. + /// section = 0 for row names (including objective function name), + /// section = 1 for column names. + COINColumnIndex findHash(const char *name, int section) const; + + /// Insert thisName in the hash table if not present yet; does nothing + /// if the name is already in. + /// section = 0 for row names, + /// section = 1 for column names. + void insertHash(const char *thisName, int section); + + /// Write a coefficient. + /// print_1 = 0 : do not print the value 1. + void out_coeff(FILE *fp, double v, int print_1) const; + + /// Locate the objective function. + /// Return 1 if found the keyword "Minimize" or one of its variants, + /// -1 if found keyword "Maximize" or one of its variants. + int find_obj() const; + + /// Return an integer indicating if the keyword "subject to" or one + /// of its variants has been read. + /// Return 1 if buff is the keyword "s.t" or one of its variants. + /// Return 2 if buff is the keyword "subject" or one of its variants. + /// Return 0 otherwise. + int is_subject_to(const char *buff) const; + + /// Return 1 if the first character of buff is a number. + /// Return 0 otherwise. + int first_is_number(const char *buff) const; + + /// Return 1 if the first character of buff is '/' or '\'. + /// Return 0 otherwise. + int is_comment(const char *buff) const; + + /// Read the file fp until buff contains an end of line + void skip_comment(char *buff) const; + + /// Return 1 if buff is the keyword "free" or one of its variants. + /// Return 0 otherwise. + int is_free(const char *buff) const; + + /// Return 1 if buff is the keyword "inf" or one of its variants. + /// Return 0 otherwise. + int is_inf(const char *buff) const; + + /// Return an integer indicating the inequality sense read. + /// Return 0 if buff is '<='. + /// Return 1 if buff is '='. + /// Return 2 if buff is '>='. + /// Return -1 otherwise. + int is_sense(const char *buff) const; + + /// Return an integer indicating if one of the keywords "Bounds", "Integers", + /// "Generals", "Binaries", "Semi-continuous", "Sos", "End", or one + /// of their variants has been read. (note Semi-continuous not coded) + /// Return 1 if buff is the keyword "Bounds" or one of its variants. + /// Return 2 if buff is the keyword "Integers" or "Generals" or one of their + /// variants. + /// Return 3 if buff is the keyword "Binaries" or one of its variants. + /// Return 4 if buff is the keyword "Semi-continuous" or one of its variants. + /// Return 5 if buff is the keyword "Sos" or one of its variants. + /// Return 6 if buff is the keyword "End" or one of its variants. + /// Return 0 otherwise. + int is_keyword(const char *buff) const; + + /// Read a monomial of the objective function. + /// Return 1 if "subject to" or one of its variants has been read. + int read_monom_obj(double *coeff, char **name, int *cnt, + char **obj_name, int *num_objectives, int *obj_starts); + + /// Read a monomial of a constraint. + /// Return a positive number if the sense of the inequality has been + /// read (see method is_sense() for the return code). + /// Return -1 otherwise. + int read_monom_row(char *start_str, double *coeff, char **name, + int cnt_coeff) const; + + /// Reallocate vectors related to number of coefficients. + void realloc_coeff(double **coeff, char ***colNames, int *maxcoeff) const; + + /// Reallocate vectors related to rows. + void realloc_row(char ***rowNames, CoinBigIndex **start, double **rhs, + double **rowlow, double **rowup, int *maxrow) const; + + /// Reallocate vectors related to columns. + void realloc_col(double **collow, double **colup, char **is_int, + int *maxcol) const; + + /// Read a constraint. + void read_row(char *buff, double **pcoeff, char ***pcolNames, + int *cnt_coeff, int *maxcoeff, + double *rhs, double *rowlow, double *rowup, + int *cnt_row, double inf) const; + + /** Check that current objective name and all row names are distinct + including row names obtained by adding "_low" for ranged constraints. + If there is a conflict in the names, they are replaced by default + row names (see setDefaultRowNames()). + + This method must not be called before + setLpDataWithoutRowAndColNames() has been called, since access + to the indices of all the ranged constraints is required. + + This method must not be called before + setLpDataRowAndColNames() has been called, since access + to all the row names is required. + */ + void checkRowNames(); + + /** Check that current column names are distinct. + If not, they are replaced by default + column names (see setDefaultColNames()). + + This method must not be called before + setLpDataRowAndColNames() has been called, since access + to all the column names is required. + */ + void checkColNames(); +}; + +void CoinLpIOUnitTest(const std::string &lpDir); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessage.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessage.hpp new file mode 100644 index 000000000..5d8775569 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessage.hpp @@ -0,0 +1,95 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinMessage_H +#define CoinMessage_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +/*! \file + + This file contains the enum for the standard set of Coin messages and a + class definition whose sole purpose is to supply a constructor. The text + ot the messages is defined in CoinMessage.cpp, + + CoinMessageHandler.hpp contains the generic facilities for message + handling. +*/ + +#include "CoinMessageHandler.hpp" + +/*! \brief Symbolic names for the standard set of COIN messages */ + +enum COIN_Message { + COIN_MPS_LINE = 0, + COIN_MPS_STATS, + COIN_MPS_ILLEGAL, + COIN_MPS_BADIMAGE, + COIN_MPS_DUPOBJ, + COIN_MPS_DUPROW, + COIN_MPS_NOMATCHROW, + COIN_MPS_NOMATCHCOL, + COIN_MPS_FILE, + COIN_MPS_BADFILE1, + COIN_MPS_BADFILE2, + COIN_MPS_EOF, + COIN_MPS_RETURNING, + COIN_MPS_CHANGED, + COIN_SOLVER_MPS, + COIN_PRESOLVE_COLINFEAS, + COIN_PRESOLVE_ROWINFEAS, + COIN_PRESOLVE_COLUMNBOUNDA, + COIN_PRESOLVE_COLUMNBOUNDB, + COIN_PRESOLVE_NONOPTIMAL, + COIN_PRESOLVE_STATS, + COIN_PRESOLVE_INFEAS, + COIN_PRESOLVE_UNBOUND, + COIN_PRESOLVE_INFEASUNBOUND, + COIN_PRESOLVE_INTEGERMODS, + COIN_PRESOLVE_POSTSOLVE, + COIN_PRESOLVE_NEEDS_CLEANING, + COIN_PRESOLVE_PASS, +#if PRESOLVE_DEBUG + COIN_PRESOLDBG_FIRSTCHECK, + COIN_PRESOLDBG_RCOSTACC, + COIN_PRESOLDBG_RCOSTSTAT, + COIN_PRESOLDBG_STATSB, + COIN_PRESOLDBG_DUALSTAT, +#endif + COIN_GENERAL_INFO, + COIN_GENERAL_INFO2, + COIN_GENERAL_WARNING, + COIN_DUMMY_END +}; + +/*! \class CoinMessage + \brief The standard set of Coin messages + + This class provides convenient access to the standard set of Coin messages. + In a nutshell, it's a CoinMessages object with a constructor that + preloads the standard Coin messages. +*/ + +class CoinMessage : public CoinMessages { + +public: + /**@name Constructors etc */ + //@{ + /*! \brief Constructor + + Build a CoinMessages object and load it with the standard set of + Coin messages. + */ + CoinMessage(Language language = us_en); + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessageHandler.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessageHandler.hpp new file mode 100644 index 000000000..8d053f9ee --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMessageHandler.hpp @@ -0,0 +1,717 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinMessageHandler_H +#define CoinMessageHandler_H + +#include "CoinUtilsConfig.h" +#include "CoinPragma.hpp" +#include "CoinTypes.hpp" + +#include +#include +#include +#include + +/** \file CoinMessageHandler.hpp + \brief This is a first attempt at a message handler. + + The COIN Project is in favo(u)r of multi-language support. This implementation + of a message handler tries to make it as lightweight as possible in the sense + that only a subset of messages need to be defined --- the rest default to US + English. + + The default handler at present just prints to stdout or to a FILE pointer + + \todo + This needs to be worked over for correct operation with ISO character codes. +*/ + +/* + I (jjf) am strongly in favo(u)r of language support for an open + source project, but I have tried to make it as lightweight as + possible in the sense that only a subset of messages need to be + defined - the rest default to US English. There will be different + sets of messages for each component - so at present there is a + Clp component and a Coin component. + + Because messages are only used in a controlled environment and have no + impact on code and are tested by other tests I have included tests such + as language and derivation in other unit tests. +*/ +/* + Where there are derived classes I (jjf) have started message numbers at 1001. +*/ + +/** \brief Class for one massaged message. + + A message consists of a text string with formatting codes (#message_), + an integer identifier (#externalNumber_) which also determines the severity + level (#severity_) of the message, and a detail (logging) level (#detail_). + + CoinOneMessage is just a container to hold this information. The + interpretation is set by CoinMessageHandler, which see. + */ + +class CoinOneMessage { + +public: + /**@name Constructors etc */ + //@{ + /** Default constructor. */ + CoinOneMessage(); + /** Normal constructor */ + CoinOneMessage(int externalNumber, char detail, + const char *message); + /** Destructor */ + ~CoinOneMessage(); + /** The copy constructor */ + CoinOneMessage(const CoinOneMessage &); + /** assignment operator. */ + CoinOneMessage &operator=(const CoinOneMessage &); + //@} + + /**@name Useful stuff */ + //@{ + /// Replace message text (e.g., text in a different language) + void replaceMessage(const char *message); + //@} + + /**@name Get and set methods */ + //@{ + /** Get message ID number */ + inline int externalNumber() const + { + return externalNumber_; + } + /** \brief Set message ID number + + In the default CoinMessageHandler, this number is printed in the message + prefix and is used to determine the message severity level. + */ + inline void setExternalNumber(int number) + { + externalNumber_ = number; + } + /// Severity + inline char severity() const + { + return severity_; + } + /// Set detail level + inline void setDetail(int level) + { + detail_ = static_cast< char >(level); + } + /// Get detail level + inline int detail() const + { + return detail_; + } + /// Return the message text + inline char *message() const + { + return message_; + } + //@} + + /**@name member data */ + //@{ + /// number to print out (also determines severity) + int externalNumber_; + /// Will only print if detail matches + char detail_; + /// Severity + char severity_; + /// Messages (in correct language) (not all 400 may exist) + mutable char message_[400]; + //@} +}; + +/** \brief Class to hold and manipulate an array of massaged messages. + + Note that the message index used to reference a message in the array of + messages is completely distinct from the external ID number stored with the + message. +*/ + +class CoinMessages { + +public: + /** \brief Supported languages + + These are the languages that are supported. At present only + us_en is serious and the rest are for testing. + */ + enum Language { + us_en = 0, + uk_en, + it + }; + + /**@name Constructors etc */ + //@{ + /** Constructor with number of messages. */ + CoinMessages(int numberMessages = 0); + /** Destructor */ + ~CoinMessages(); + /** The copy constructor */ + CoinMessages(const CoinMessages &); + /** assignment operator. */ + CoinMessages &operator=(const CoinMessages &); + //@} + + /**@name Useful stuff */ + //@{ + /*! \brief Installs a new message in the specified index position + + Any existing message is replaced, and a copy of the specified message is + installed. + */ + void addMessage(int messageNumber, const CoinOneMessage &message); + /*! \brief Replaces the text of the specified message + + Any existing text is deleted and the specified text is copied into the + specified message. + */ + void replaceMessage(int messageNumber, const char *message); + /** Language. Need to think about iso codes */ + inline Language language() const + { + return language_; + } + /** Set language */ + void setLanguage(Language newlanguage) + { + language_ = newlanguage; + } + /// Change detail level for one message + void setDetailMessage(int newLevel, int messageNumber); + /** \brief Change detail level for several messages + + messageNumbers is expected to contain the indices of the messages to be + changed. + If numberMessages >= 10000 or messageNumbers is NULL, the detail level + is changed on all messages. + */ + void setDetailMessages(int newLevel, int numberMessages, + int *messageNumbers); + /** Change detail level for all messages with low <= ID number < high */ + void setDetailMessages(int newLevel, int low, int high); + + /// Returns class + inline int getClass() const + { + return class_; + } + /// Moves to compact format + void toCompact(); + /// Moves from compact format + void fromCompact(); + //@} + + /**@name member data */ + //@{ + /// Number of messages + int numberMessages_; + /// Language + Language language_; + /// Source (null-terminated string, maximum 4 characters). + char source_[5]; + /// Class - see later on before CoinMessageHandler + int class_; + /** Length of fake CoinOneMessage array. + First you get numberMessages_ pointers which point to stuff + */ + int lengthMessages_; + /// Messages + CoinOneMessage **message_; + //@} +}; + +// for convenience eol +enum CoinMessageMarker { + CoinMessageEol = 0, + CoinMessageNewline = 1 +}; + +/** Base class for message handling + + The default behavior is described here: messages are printed, and (if the + severity is sufficiently high) execution will be aborted. Inherit and + redefine the methods #print and #checkSeverity to augment the behaviour. + + Messages can be printed with or without a prefix; the prefix will consist + of a source string, the external ID number, and a letter code, + e.g., Clp6024W. + A prefix makes the messages look less nimble but is very useful + for "grep" etc. + +

Usage

+ + The general approach to using the COIN messaging facility is as follows: +
    +
  • Define your messages. For each message, you must supply an external + ID number, a log (detail) level, and a format string. Typically, you + define a convenience structure for this, something that's easy to + use to create an array of initialised message definitions at compile + time. +
  • Create a CoinMessages object, sized to accommodate the number of + messages you've defined. (Incremental growth will happen if + necessary as messages are loaded, but it's inefficient.) +
  • Load the messages into the CoinMessages object. Typically this + entails creating a CoinOneMessage object for each message and + passing it as a parameter to CoinMessages::addMessage(). You specify + the message's internal ID as the other parameter to addMessage. +
  • Create and use a CoinMessageHandler object to print messages. +
+ See, for example, CoinMessage.hpp and CoinMessage.cpp for an example of + the first three steps. `Format codes' below has a simple example of + printing a message. + +

External ID numbers and severity

+ + CoinMessageHandler assumes the following relationship between the + external ID number of a message and the severity of the message: + \li <3000 are informational ('I') + \li <6000 warnings ('W') + \li <9000 non-fatal errors ('E') + \li >=9000 aborts the program (after printing the message) ('S') + +

Log (detail) levels

+ + The default behaviour is that a message will print if its detail level + is less than or equal to the handler's log level. If all you want to + do is set a single log level for the handler, use #setLogLevel(int). + + If you want to get fancy, here's how it really works: There's an array, + #logLevels_, which you can manipulate with #setLogLevel(int,int). Each + entry logLevels_[i] specifies the log level for messages of class i (see + CoinMessages::class_). If logLevels_[0] is set to the magic number -1000 + you get the simple behaviour described above, whatever the class of the + messages. If logLevels_[0] is set to a valid log level (>= 0), then + logLevels_[i] really is the log level for messages of class i. + +

Format codes

+ + CoinMessageHandler can print integers (normal, long, and long long), + doubles, characters, and strings. See the descriptions of the + various << operators. + + When processing a standard message with a format string, the formatting + codes specified in the format string will be passed to the sprintf + function, along with the argument. When generating a message with no + format string, each << operator uses a simple format code appropriate for + its argument. Consult the documentation for the standard printf facility + for further information on format codes. + + The special format code `%?' provides a hook to enable or disable + printing. For each `%?' code, there must be a corresponding call to + printing(bool). This provides a way to define optional parts in + messages, delineated by the code `%?' in the format string. Printing can + be suppressed for these optional parts, but any operands must still be + supplied. For example, given the message string + \verbatim + "A message with%? an optional integer %d and%? a double %g." + \endverbatim + installed in CoinMessages \c exampleMsgs with index 5, and + \c CoinMessageHandler \c hdl, the code + \code + hdl.message(5,exampleMsgs) ; + hdl.printing(true) << 42 ; + hdl.printing(true) << 53.5 << CoinMessageEol ; + \endcode + will print + \verbatim + A message with an optional integer 42 and a double 53.5. + \endverbatim + while + \code + hdl.message(5,exampleMsgs) ; + hdl.printing(false) << 42 ; + hdl.printing(true) << 53.5 << CoinMessageEol ; + \endcode + will print + \verbatim + A message with a double 53.5. + \endverbatim + + For additional examples of usage, see CoinMessageHandlerUnitTest in + CoinMessageHandlerTest.cpp. +*/ + +class CoinMessageHandler { + + friend bool CoinMessageHandlerUnitTest(); + +public: + /**@name Virtual methods that the derived classes may provide */ + //@{ + /** Print message, return 0 normally. + */ + virtual int print(); + /** Check message severity - if too bad then abort + */ + virtual void checkSeverity(); + //@} + + /**@name Constructors etc */ + //@{ + /// Constructor + CoinMessageHandler(); + /// Constructor to put to file pointer (won't be closed) + CoinMessageHandler(FILE *fp); + /** Destructor */ + virtual ~CoinMessageHandler(); + /** The copy constructor */ + CoinMessageHandler(const CoinMessageHandler &); + /** Assignment operator. */ + CoinMessageHandler &operator=(const CoinMessageHandler &); + /// Clone + virtual CoinMessageHandler *clone() const; + //@} + /**@name Get and set methods */ + //@{ + /// Get detail level of a message. + inline int detail(int messageNumber, const CoinMessages &normalMessage) const + { + return normalMessage.message_[messageNumber]->detail(); + } + /** Get current log (detail) level. */ + inline int logLevel() const + { + return logLevel_; + } + /** \brief Set current log (detail) level. + + If the log level is equal or greater than the detail level of a message, + the message will be printed. A rough convention for the amount of output + expected is + - 0 - none + - 1 - minimal + - 2 - normal low + - 3 - normal high + - 4 - verbose + + Please assign log levels to messages accordingly. Log levels of 8 and + above (8,16,32, etc.) are intended for selective debugging. + The logical AND of the log level specified in the message and the current + log level is used to determine if the message is printed. (In other words, + you're using individual bits to determine which messages are printed.) + */ + void setLogLevel(int value); + /** Get alternative log level. */ + inline int logLevel(int which) const + { + return logLevels_[which]; + } + /*! \brief Set alternative log level value. + + Can be used to store alternative log level information within the handler. + */ + void setLogLevel(int which, int value); + + /// Set the number of significant digits for printing floating point numbers + void setPrecision(unsigned int new_precision); + /// Current number of significant digits for printing floating point numbers + inline int precision() { return (g_precision_); } + + /// Switch message prefix on or off. + void setPrefix(bool yesNo); + /// Current setting for printing message prefix. + bool prefix() const; + /*! \brief Values of double fields already processed. + + As the parameter for a double field is processed, the value is saved + and can be retrieved using this function. + */ + inline double doubleValue(int position) const + { + return doubleValue_[position]; + } + /*! \brief Number of double fields already processed. + + Incremented each time a field of type double is processed. + */ + inline int numberDoubleFields() const + { + return static_cast< int >(doubleValue_.size()); + } + /*! \brief Values of integer fields already processed. + + As the parameter for a integer field is processed, the value is saved + and can be retrieved using this function. + */ + inline CoinBigIndex intValue(int position) const + { + return longValue_[position]; + } + /*! \brief Number of integer fields already processed. + + Incremented each time a field of type integer is processed. + */ + inline int numberIntFields() const + { + return static_cast< int >(longValue_.size()); + } + /*! \brief Values of char fields already processed. + + As the parameter for a char field is processed, the value is saved + and can be retrieved using this function. + */ + inline char charValue(int position) const + { + return charValue_[position]; + } + /*! \brief Number of char fields already processed. + + Incremented each time a field of type char is processed. + */ + inline int numberCharFields() const + { + return static_cast< int >(charValue_.size()); + } + /*! \brief Values of string fields already processed. + + As the parameter for a string field is processed, the value is saved + and can be retrieved using this function. + */ + inline std::string stringValue(int position) const + { + return stringValue_[position]; + } + /*! \brief Number of string fields already processed. + + Incremented each time a field of type string is processed. + */ + inline int numberStringFields() const + { + return static_cast< int >(stringValue_.size()); + } + + /// Current message + inline CoinOneMessage currentMessage() const + { + return currentMessage_; + } + /// Source of current message + inline std::string currentSource() const + { + return source_; + } + /// Output buffer + inline const char *messageBuffer() const + { + return messageBuffer_; + } + /// Highest message number (indicates any errors) + inline int highestNumber() const + { + return highestNumber_; + } + /// Get current file pointer + inline FILE *filePointer() const + { + return fp_; + } + /// Set new file pointer + inline void setFilePointer(FILE *fp) + { + fp_ = fp; + } + //@} + + /**@name Actions to create a message */ + //@{ + /*! \brief Start a message + + Look up the specified message. A prefix will be generated if enabled. + The message will be printed if the current log level is equal or greater + than the log level of the message. + */ + CoinMessageHandler &message(int messageNumber, + const CoinMessages &messages); + + /*! \brief Start or continue a message + + With detail = -1 (default), does nothing except return a reference to the + handler. (I.e., msghandler.message() << "foo" is precisely equivalent + to msghandler << "foo".) If \p msgDetail is >= 0, is will be used + as the detail level to determine whether the message should print + (assuming class 0). + + This can be used with any of the << operators. One use is to start + a message which will be constructed entirely from scratch. Another + use is continuation of a message after code that interrupts the usual + sequence of << operators. + */ + CoinMessageHandler &message(int detail = -1); + + /*! \brief Print a complete message + + Generate a standard prefix and append \c msg `as is'. This is intended as + a transition mechanism. The standard prefix is generated (if enabled), + and \c msg is appended. The message must be ended with a CoinMessageEol + marker. Attempts to add content with << will have no effect. + + The default value of \p detail will not change printing status. If + \p detail is >= 0, it will be used as the detail level to determine + whether the message should print (assuming class 0). + + */ + CoinMessageHandler &message(int externalNumber, const char *source, + const char *msg, + char severity, int detail = -1); + + /*! \brief Process an integer parameter value. + + The default format code is `%d'. + */ + CoinMessageHandler &operator<<(int intvalue); +#if COIN_BIG_INDEX == 1 + /*! \brief Process a long integer parameter value. + + The default format code is `%ld'. + */ + CoinMessageHandler &operator<<(long longvalue); +#endif +#if COIN_BIG_INDEX == 2 + /*! \brief Process a long long integer parameter value. + + The default format code is `%ld'. + */ + CoinMessageHandler &operator<<(long long longvalue); +#endif + /*! \brief Process a double parameter value. + + The default format code is `%d'. + */ + CoinMessageHandler &operator<<(double doublevalue); + /*! \brief Process a STL string parameter value. + + The default format code is `%g'. + */ + CoinMessageHandler &operator<<(const std::string &stringvalue); + /*! \brief Process a char parameter value. + + The default format code is `%s'. + */ + CoinMessageHandler &operator<<(char charvalue); + /*! \brief Process a C-style string parameter value. + + The default format code is `%c'. + */ + CoinMessageHandler &operator<<(const char *stringvalue); + /*! \brief Process a marker. + + The default format code is `%s'. + */ + CoinMessageHandler &operator<<(CoinMessageMarker); + /** Finish (and print) the message. + + Equivalent to using the CoinMessageEol marker. + */ + int finish(); + /*! \brief Enable or disable printing of an optional portion of a message. + + Optional portions of a message are delimited by `%?' markers, and + printing processes one %? marker. If \c onOff is true, the subsequent + portion of the message (to the next %? marker or the end of the format + string) will be printed. If \c onOff is false, printing is suppressed. + Parameters must still be supplied, whether printing is suppressed or not. + See the class documentation for an example. + */ + CoinMessageHandler &printing(bool onOff); + + //@} + + /** Log levels will be by type and will then use type + given in CoinMessage::class_ + + - 0 - Branch and bound code or similar + - 1 - Solver + - 2 - Stuff in Coin directory + - 3 - Cut generators + */ +#define COIN_NUM_LOG 4 +/// Maximum length of constructed message (characters) +#define COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE 1000 +protected: + /**@name Protected member data */ + //@{ + /// values in message + std::vector< double > doubleValue_; + std::vector< CoinBigIndex > longValue_; + std::vector< char > charValue_; + std::vector< std::string > stringValue_; + /// Log level + int logLevel_; + /// Log levels + int logLevels_[COIN_NUM_LOG]; + /// Whether we want prefix (may get more subtle so is int) + int prefix_; + /// Current message + CoinOneMessage currentMessage_; + /// Internal number for use with enums + int internalNumber_; + /// Format string for message (remainder) + char *format_; + /// Output buffer + char messageBuffer_[COIN_MESSAGE_HANDLER_MAX_BUFFER_SIZE]; + /// Position in output buffer + char *messageOut_; + /// Current source of message + std::string source_; + /** 0 - Normal. + 1 - Put in values, move along format, but don't print. + 2 - A complete message was provided; nothing more to do but print + when CoinMessageEol is processed. Any << operators are treated + as noops. + 3 - do nothing except look for CoinMessageEol (i.e., the message + detail level was not sufficient to cause it to print). + */ + int printStatus_; + /// Highest message number (indicates any errors) + int highestNumber_; + /// File pointer + FILE *fp_; + /// Current format for floating point numbers + char g_format_[8]; + /// Current number of significant digits for floating point numbers + int g_precision_; + //@} + +private: + /** The body of the copy constructor and the assignment operator */ + void gutsOfCopy(const CoinMessageHandler &rhs); + + /*! \brief Internal function to locate next format code. + + Intended for internal use. Side effects modify the format string. + */ + char *nextPerCent(char *start, const bool initial = false); + + /*! \brief Internal printing function. + + Makes it easier to split up print into clean, print and check severity + */ + int internalPrint(); + + /// Decide if this message should print. + void calcPrintStatus(int msglvl, int msgclass); +}; + +//############################################################################# +/** A function that tests the methods in the CoinMessageHandler class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +bool CoinMessageHandlerUnitTest(); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModel.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModel.hpp new file mode 100644 index 000000000..6482648c5 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModel.hpp @@ -0,0 +1,1214 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinModel_H +#define CoinModel_H + +#include "CoinModelUseful.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinFinite.hpp" +class CoinBaseModel { + +public: + /**@name Constructors, destructor */ + //@{ + /// Default Constructor + CoinBaseModel(); + + /// Copy constructor + CoinBaseModel(const CoinBaseModel &rhs); + + /// Assignment operator + CoinBaseModel &operator=(const CoinBaseModel &rhs); + + /// Clone + virtual CoinBaseModel *clone() const = 0; + + /// Destructor + virtual ~CoinBaseModel(); + //@} + + /**@name For getting information */ + //@{ + /// Return number of rows + inline int numberRows() const + { + return numberRows_; + } + /// Return number of columns + inline int numberColumns() const + { + return numberColumns_; + } + /// Return number of elements + virtual CoinBigIndex numberElements() const = 0; + /** Returns the (constant) objective offset + This is the RHS entry for the objective row + */ + inline double objectiveOffset() const + { + return objectiveOffset_; + } + /// Set objective offset + inline void setObjectiveOffset(double value) + { + objectiveOffset_ = value; + } + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const + { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { + optimizationDirection_ = value; + } + /// Get print level 0 - off, 1 - errors, 2 - more + inline int logLevel() const + { + return logLevel_; + } + /// Set print level 0 - off, 1 - errors, 2 - more + void setLogLevel(int value); + /// Return the problem name + inline const char *getProblemName() const + { + return problemName_.c_str(); + } + /// Set problem name + void setProblemName(const char *name); + /// Set problem name + void setProblemName(const std::string &name); + /// Return the row block name + inline const std::string &getRowBlock() const + { + return rowBlockName_; + } + /// Set row block name + inline void setRowBlock(const std::string &name) + { + rowBlockName_ = name; + } + /// Return the column block name + inline const std::string &getColumnBlock() const + { + return columnBlockName_; + } + /// Set column block name + inline void setColumnBlock(const std::string &name) + { + columnBlockName_ = name; + } + /// Pass in message handler + void setMessageHandler(CoinMessageHandler *handler); + //@} + +protected: + /**@name Data members */ + //@{ + /// Current number of rows + int numberRows_; + /// Current number of columns + int numberColumns_; + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + double optimizationDirection_; + /// Objective offset to be passed on + double objectiveOffset_; + /// Problem name + std::string problemName_; + /// Rowblock name + std::string rowBlockName_; + /// Columnblock name + std::string columnBlockName_; + /// Message handler (Passed in) + CoinMessageHandler *handler_; + /// Messages + CoinMessages messages_; + + /** Print level. + I could have gone for full message handling but this should normally + be silent and lightweight. + -1 - use passed in message handler + 0 - no output + 1 - on errors + 2 - more detailed + */ + int logLevel_; + //@} + /// data +}; + +/** + This is a simple minded model which is stored in a format which makes + it easier to construct and modify but not efficient for algorithms. It has + to be passed across to ClpModel or OsiSolverInterface by addRows, addCol(umn)s + or loadProblem. + + It may have up to four parts - + 1) A matrix of doubles (or strings - see note A) + 2) Column information including integer information and names + 3) Row information including names + 4) Quadratic objective (not implemented - but see A) + + This class is meant to make it more efficient to build a model. It is at + its most efficient when all additions are done as addRow or as addCol but + not mixed. If only 1 and 2 exist then solver.addColumns may be used to pass to solver, + if only 1 and 3 exist then solver.addRows may be used. Otherwise solver.loadProblem + must be used. + + If addRows and addColumns are mixed or if individual elements are set then the + speed will drop to some extent and more memory will be used. + + It is also possible to iterate over existing elements and to access columns and rows + by name. Again each of these use memory and cpu time. However memory is unlikely + to be critical as most algorithms will use much more. + + Notes: + A) Although this could be used to pass nonlinear information around the + only use at present is to have named values e.g. value1 which can then be + set to a value after model is created. I have no idea whether that could + be useful but I thought it might be fun. + Quadratic terms are allowed in strings! A solver could try and use this + if so - the convention is that 0.5* quadratic is stored + + B) This class could be useful for modeling. +*/ + +class CoinModel : public CoinBaseModel { + +public: + /**@name Useful methods for building model */ + //@{ + /** add a row - numberInRow may be zero */ + void addRow(int numberInRow, const int *columns, + const double *elements, double rowLower = -COIN_DBL_MAX, + double rowUpper = COIN_DBL_MAX, const char *name = NULL); + /// add a column - numberInColumn may be zero */ + void addColumn(int numberInColumn, const int *rows, + const double *elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, double objectiveValue = 0.0, + const char *name = NULL, bool isInteger = false); + /// add a column - numberInColumn may be zero */ + inline void addCol(int numberInColumn, const int *rows, + const double *elements, + double columnLower = 0.0, + double columnUpper = COIN_DBL_MAX, double objectiveValue = 0.0, + const char *name = NULL, bool isInteger = false) + { + addColumn(numberInColumn, rows, elements, columnLower, columnUpper, objectiveValue, + name, isInteger); + } + /// Sets value for row i and column j + inline void operator()(int i, int j, double value) + { + setElement(i, j, value); + } + /// Sets value for row i and column j + void setElement(int i, int j, double value); + /** Gets sorted row - user must provide enough space + (easiest is allocate number of columns). + If column or element NULL then just returns number + Returns number of elements + */ + int getRow(int whichRow, int *column, double *element); + /** Gets sorted column - user must provide enough space + (easiest is allocate number of rows). + If row or element NULL then just returns number + Returns number of elements + */ + int getColumn(int whichColumn, int *column, double *element); + /// Sets quadratic value for column i and j + void setQuadraticElement(int i, int j, double value); + /// Sets value for row i and column j as string + inline void operator()(int i, int j, const char *value) + { + setElement(i, j, value); + } + /// Sets value for row i and column j as string + void setElement(int i, int j, const char *value); + /// Associates a string with a value. Returns string id (or -1 if does not exist) + int associateElement(const char *stringValue, double value); + /** Sets rowLower (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowLower(int whichRow, double rowLower); + /** Sets rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowUpper(int whichRow, double rowUpper); + /** Sets rowLower and rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowBounds(int whichRow, double rowLower, double rowUpper); + /** Sets name (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowName(int whichRow, const char *rowName); + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnLower(int whichColumn, double columnLower); + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnUpper(int whichColumn, double columnUpper); + /** Sets columnLower and columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnBounds(int whichColumn, double columnLower, double columnUpper); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnObjective(int whichColumn, double columnObjective); + /** Sets name (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnName(int whichColumn, const char *columnName); + /** Sets integer state (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnIsInteger(int whichColumn, bool columnIsInteger); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setObjective(int whichColumn, double columnObjective) + { + setColumnObjective(whichColumn, columnObjective); + } + /** Sets integer state (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setIsInteger(int whichColumn, bool columnIsInteger) + { + setColumnIsInteger(whichColumn, columnIsInteger); + } + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setInteger(int whichColumn) + { + setColumnIsInteger(whichColumn, true); + } + /** Sets continuous (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setContinuous(int whichColumn) + { + setColumnIsInteger(whichColumn, false); + } + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColLower(int whichColumn, double columnLower) + { + setColumnLower(whichColumn, columnLower); + } + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColUpper(int whichColumn, double columnUpper) + { + setColumnUpper(whichColumn, columnUpper); + } + /** Sets columnLower and columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColBounds(int whichColumn, double columnLower, double columnUpper) + { + setColumnBounds(whichColumn, columnLower, columnUpper); + } + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColObjective(int whichColumn, double columnObjective) + { + setColumnObjective(whichColumn, columnObjective); + } + /** Sets name (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColName(int whichColumn, const char *columnName) + { + setColumnName(whichColumn, columnName); + } + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setColIsInteger(int whichColumn, bool columnIsInteger) + { + setColumnIsInteger(whichColumn, columnIsInteger); + } + /** Sets rowLower (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowLower(int whichRow, const char *rowLower); + /** Sets rowUpper (if row does not exist then + all rows up to this are defined with default values and no elements) + */ + void setRowUpper(int whichRow, const char *rowUpper); + /** Sets columnLower (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnLower(int whichColumn, const char *columnLower); + /** Sets columnUpper (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnUpper(int whichColumn, const char *columnUpper); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnObjective(int whichColumn, const char *columnObjective); + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + void setColumnIsInteger(int whichColumn, const char *columnIsInteger); + /** Sets columnObjective (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setObjective(int whichColumn, const char *columnObjective) + { + setColumnObjective(whichColumn, columnObjective); + } + /** Sets integer (if column does not exist then + all columns up to this are defined with default values and no elements) + */ + inline void setIsInteger(int whichColumn, const char *columnIsInteger) + { + setColumnIsInteger(whichColumn, columnIsInteger); + } + /** Deletes all entries in row and bounds. Will be ignored by + writeMps etc and will be packed down if asked for. */ + void deleteRow(int whichRow); + /** Deletes all entries in column and bounds and objective. Will be ignored by + writeMps etc and will be packed down if asked for. */ + void deleteColumn(int whichColumn); + /** Deletes all entries in column and bounds. If last column the number of columns + will be decremented and true returned. */ + inline void deleteCol(int whichColumn) + { + deleteColumn(whichColumn); + } + /// Takes element out of matrix - returning position (<0 if not there); + CoinBigIndex deleteElement(int row, int column); + /// Takes element out of matrix when position known + void deleteThisElement(int row, int column, CoinBigIndex position); + /** Packs down all rows i.e. removes empty rows permanently. Empty rows + have no elements and feasible bounds. returns number of rows deleted. */ + int packRows(); + /** Packs down all columns i.e. removes empty columns permanently. Empty columns + have no elements and no objective. returns number of columns deleted. */ + int packColumns(); + /** Packs down all columns i.e. removes empty columns permanently. Empty columns + have no elements and no objective. returns number of columns deleted. */ + inline int packCols() + { + return packColumns(); + } + /** Packs down all rows and columns. i.e. removes empty rows and columns permanently. + Empty rows have no elements and feasible bounds. + Empty columns have no elements and no objective. + returns number of rows+columns deleted. */ + int pack(); + + /** Sets columnObjective array + */ + void setObjective(int numberColumns, const double *objective); + /** Sets columnLower array + */ + void setColumnLower(int numberColumns, const double *columnLower); + /** Sets columnLower array + */ + inline void setColLower(int numberColumns, const double *columnLower) + { + setColumnLower(numberColumns, columnLower); + } + /** Sets columnUpper array + */ + void setColumnUpper(int numberColumns, const double *columnUpper); + /** Sets columnUpper array + */ + inline void setColUpper(int numberColumns, const double *columnUpper) + { + setColumnUpper(numberColumns, columnUpper); + } + /** Sets rowLower array + */ + void setRowLower(int numberRows, const double *rowLower); + /** Sets rowUpper array + */ + void setRowUpper(int numberRows, const double *rowUpper); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written +
    +
  • 0: plain text (default) +
  • 1: gzip compressed (.gz is appended to \c filename) +
  • 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) +
+ If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file +
    +
  • 0: normal precision (default) +
  • 1: extra accuracy +
  • 2: IEEE hex +
+ + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + not const as may change model e.g. fill in default bounds + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, bool keepStrings = false); + + /** Check two models against each other. Return nonzero if different. + Ignore names if that set. + May modify both models by cleaning up + */ + int differentModel(CoinModel &other, bool ignoreNames); + //@} + + /**@name For structured models */ + //@{ + /// Pass in CoinPackedMatrix (and switch off element updates) + void passInMatrix(const CoinPackedMatrix &matrix); + /** Convert elements to CoinPackedMatrix (and switch off element updates). + Returns number of errors */ + int convertMatrix(); + /// Return a pointer to CoinPackedMatrix (or NULL) + inline const CoinPackedMatrix *packedMatrix() const + { + return packedMatrix_; + } + /// Return pointers to original rows (for decomposition) + inline const int *originalRows() const + { + return rowType_; + } + /// Return pointers to original columns (for decomposition) + inline const int *originalColumns() const + { + return columnType_; + } + //@} + + /**@name For getting information */ + //@{ + /// Return number of elements + inline CoinBigIndex numberElements() const + { + return numberElements_; + } + /// Return elements as triples + inline const CoinModelTriple *elements() const + { + return elements_; + } + /// Returns value for row i and column j + inline double operator()(int i, int j) const + { + return getElement(i, j); + } + /// Returns value for row i and column j + double getElement(int i, int j) const; + /// Returns value for row rowName and column columnName + inline double operator()(const char *rowName, const char *columnName) const + { + return getElement(rowName, columnName); + } + /// Returns value for row rowName and column columnName + double getElement(const char *rowName, const char *columnName) const; + /// Returns quadratic value for columns i and j + double getQuadraticElement(int i, int j) const; + /** Returns value for row i and column j as string. + Returns NULL if does not exist. + Returns "Numeric" if not a string + */ + const char *getElementAsString(int i, int j) const; + /** Returns pointer to element for row i column j. + Only valid until next modification. + NULL if element does not exist */ + double *pointer(int i, int j) const; + /** Returns position in elements for row i column j. + Only valid until next modification. + -1 if element does not exist */ + CoinBigIndex position(int i, int j) const; + + /** Returns first element in given row - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink firstInRow(int whichRow) const; + /** Returns last element in given row - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInRow(int whichRow) const; + /** Returns first element in given column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink firstInColumn(int whichColumn) const; + /** Returns last element in given column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInColumn(int whichColumn) const; + /** Returns next element in current row or column - index is -1 if none. + Index is given by .index and value by .value. + User could also tell because input.next would be NULL + */ + CoinModelLink next(CoinModelLink ¤t) const; + /** Returns previous element in current row or column - index is -1 if none. + Index is given by .index and value by .value. + User could also tell because input.previous would be NULL + May not be correct if matrix updated. + */ + CoinModelLink previous(CoinModelLink ¤t) const; + /** Returns first element in given quadratic column - index is -1 if none. + Index is given by .index and value by .value + May not be correct if matrix updated. + */ + CoinModelLink firstInQuadraticColumn(int whichColumn) const; + /** Returns last element in given quadratic column - index is -1 if none. + Index is given by .index and value by .value + */ + CoinModelLink lastInQuadraticColumn(int whichColumn) const; + /** Gets rowLower (if row does not exist then -COIN_DBL_MAX) + */ + double getRowLower(int whichRow) const; + /** Gets rowUpper (if row does not exist then +COIN_DBL_MAX) + */ + double getRowUpper(int whichRow) const; + /** Gets name (if row does not exist then NULL) + */ + const char *getRowName(int whichRow) const; + inline double rowLower(int whichRow) const + { + return getRowLower(whichRow); + } + /** Gets rowUpper (if row does not exist then COIN_DBL_MAX) + */ + inline double rowUpper(int whichRow) const + { + return getRowUpper(whichRow); + } + /** Gets name (if row does not exist then NULL) + */ + inline const char *rowName(int whichRow) const + { + return getRowName(whichRow); + } + /** Gets columnLower (if column does not exist then 0.0) + */ + double getColumnLower(int whichColumn) const; + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + double getColumnUpper(int whichColumn) const; + /** Gets columnObjective (if column does not exist then 0.0) + */ + double getColumnObjective(int whichColumn) const; + /** Gets name (if column does not exist then NULL) + */ + const char *getColumnName(int whichColumn) const; + /** Gets if integer (if column does not exist then false) + */ + bool getColumnIsInteger(int whichColumn) const; + /** Gets columnLower (if column does not exist then 0.0) + */ + inline double columnLower(int whichColumn) const + { + return getColumnLower(whichColumn); + } + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline double columnUpper(int whichColumn) const + { + return getColumnUpper(whichColumn); + } + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double columnObjective(int whichColumn) const + { + return getColumnObjective(whichColumn); + } + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double objective(int whichColumn) const + { + return getColumnObjective(whichColumn); + } + /** Gets name (if column does not exist then NULL) + */ + inline const char *columnName(int whichColumn) const + { + return getColumnName(whichColumn); + } + /** Gets if integer (if column does not exist then false) + */ + inline bool columnIsInteger(int whichColumn) const + { + return getColumnIsInteger(whichColumn); + } + /** Gets if integer (if column does not exist then false) + */ + inline bool isInteger(int whichColumn) const + { + return getColumnIsInteger(whichColumn); + } + /** Gets columnLower (if column does not exist then 0.0) + */ + inline double getColLower(int whichColumn) const + { + return getColumnLower(whichColumn); + } + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline double getColUpper(int whichColumn) const + { + return getColumnUpper(whichColumn); + } + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline double getColObjective(int whichColumn) const + { + return getColumnObjective(whichColumn); + } + /** Gets name (if column does not exist then NULL) + */ + inline const char *getColName(int whichColumn) const + { + return getColumnName(whichColumn); + } + /** Gets if integer (if column does not exist then false) + */ + inline bool getColIsInteger(int whichColumn) const + { + return getColumnIsInteger(whichColumn); + } + /** Gets rowLower (if row does not exist then -COIN_DBL_MAX) + */ + const char *getRowLowerAsString(int whichRow) const; + /** Gets rowUpper (if row does not exist then +COIN_DBL_MAX) + */ + const char *getRowUpperAsString(int whichRow) const; + inline const char *rowLowerAsString(int whichRow) const + { + return getRowLowerAsString(whichRow); + } + /** Gets rowUpper (if row does not exist then COIN_DBL_MAX) + */ + inline const char *rowUpperAsString(int whichRow) const + { + return getRowUpperAsString(whichRow); + } + /** Gets columnLower (if column does not exist then 0.0) + */ + const char *getColumnLowerAsString(int whichColumn) const; + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + const char *getColumnUpperAsString(int whichColumn) const; + /** Gets columnObjective (if column does not exist then 0.0) + */ + const char *getColumnObjectiveAsString(int whichColumn) const; + /** Gets if integer (if column does not exist then false) + */ + const char *getColumnIsIntegerAsString(int whichColumn) const; + /** Gets columnLower (if column does not exist then 0.0) + */ + inline const char *columnLowerAsString(int whichColumn) const + { + return getColumnLowerAsString(whichColumn); + } + /** Gets columnUpper (if column does not exist then COIN_DBL_MAX) + */ + inline const char *columnUpperAsString(int whichColumn) const + { + return getColumnUpperAsString(whichColumn); + } + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline const char *columnObjectiveAsString(int whichColumn) const + { + return getColumnObjectiveAsString(whichColumn); + } + /** Gets columnObjective (if column does not exist then 0.0) + */ + inline const char *objectiveAsString(int whichColumn) const + { + return getColumnObjectiveAsString(whichColumn); + } + /** Gets if integer (if column does not exist then false) + */ + inline const char *columnIsIntegerAsString(int whichColumn) const + { + return getColumnIsIntegerAsString(whichColumn); + } + /** Gets if integer (if column does not exist then false) + */ + inline const char *isIntegerAsString(int whichColumn) const + { + return getColumnIsIntegerAsString(whichColumn); + } + /// Row index from row name (-1 if no names or no match) + int row(const char *rowName) const; + /// Column index from column name (-1 if no names or no match) + int column(const char *columnName) const; + /// Returns type + inline int type() const + { + return type_; + } + /// returns unset value + inline double unsetValue() const + { + return -1.23456787654321e-97; + } + /// Creates a packed matrix - return number of errors + int createPackedMatrix(CoinPackedMatrix &matrix, + const double *associated); + /** Fills in startPositive and startNegative with counts for +-1 matrix. + If not +-1 then startPositive[0]==-1 otherwise counts and + startPositive[numberColumns]== size + - return number of errors + */ + int countPlusMinusOne(CoinBigIndex *startPositive, CoinBigIndex *startNegative, + const double *associated); + /** Creates +-1 matrix given startPositive and startNegative counts for +-1 matrix. + */ + void createPlusMinusOne(CoinBigIndex *startPositive, CoinBigIndex *startNegative, + int *indices, + const double *associated); + /// Creates copies of various arrays - return number of errors + int createArrays(double *&rowLower, double *&rowUpper, + double *&columnLower, double *&columnUpper, + double *&objective, int *&integerType, + double *&associated); + /// Says if strings exist + inline bool stringsExist() const + { + return string_.numberItems() != 0; + } + /// Return string array + inline const CoinModelHash *stringArray() const + { + return &string_; + } + /// Returns associated array + inline double *associatedArray() const + { + return associated_; + } + /// Return rowLower array + inline double *rowLowerArray() const + { + return rowLower_; + } + /// Return rowUpper array + inline double *rowUpperArray() const + { + return rowUpper_; + } + /// Return columnLower array + inline double *columnLowerArray() const + { + return columnLower_; + } + /// Return columnUpper array + inline double *columnUpperArray() const + { + return columnUpper_; + } + /// Return objective array + inline double *objectiveArray() const + { + return objective_; + } + /// Return integerType array + inline int *integerTypeArray() const + { + return integerType_; + } + /// Return row names array + inline const CoinModelHash *rowNames() const + { + return &rowName_; + } + /// Return column names array + inline const CoinModelHash *columnNames() const + { + return &columnName_; + } + /// Reset row names + inline void zapRowNames() + { + rowName_ = CoinModelHash(); + } + /// Reset column names + inline void zapColumnNames() + { + columnName_ = CoinModelHash(); + } + /// Returns array of 0 or nonzero if can be a cut (or returns NULL) + inline const int *cutMarker() const + { + return cut_; + } + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const + { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { + optimizationDirection_ = value; + } + /// Return pointer to more information + inline void *moreInfo() const + { + return moreInfo_; + } + /// Set pointer to more information + inline void setMoreInfo(void *info) + { + moreInfo_ = info; + } + /** Returns which parts of model are set + 1 - matrix + 2 - rhs + 4 - row names + 8 - column bounds and/or objective + 16 - column names + 32 - integer types + */ + int whatIsSet() const; + //@} + + /**@name for block models - matrix will be CoinPackedMatrix */ + //@{ + /*! \brief Load in a problem by copying the arguments. The constraints on + the rows are given by lower and upper bounds. + + If a pointer is 0 then the following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ + Note that the default values for rowub and rowlb produce the + constraint -infty <= ax <= infty. This is probably not what you want. + */ + void loadBlock(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + /*! \brief Load in a problem by copying the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + If a pointer is 0 then the following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • obj: all variables have 0 objective coefficient +
  • rowsen: all rows are >= +
  • rowrhs: all right hand sides are 0 +
  • rowrng: 0 for the ranged rows +
+ + Note that the default values for rowsen, rowrhs, and rowrng produce the + constraint ax >= 0. + */ + void loadBlock(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by lower and upper bounds. + + The matrix vectors must be gap-free. Note that start must + have numcols+1 entries so that the length of the last column + can be calculated as start[numcols]-start[numcols-1]. + + See the previous loadBlock method using rowlb and rowub for default + argument values. + */ + void loadBlock(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by sense/rhs/range triplets. + + The matrix vectors must be gap-free. Note that start must + have numcols+1 entries so that the length of the last column + can be calculated as start[numcols]-start[numcols-1]. + + See the previous loadBlock method using sense/rhs/range for default + argument values. + */ + void loadBlock(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModel(); + /** Constructor with sizes. */ + CoinModel(int firstRows, int firstColumns, CoinBigIndex firstElements, bool noNames = false); + /** Read a problem in MPS or GAMS format from the given filename. + */ + CoinModel(const char *fileName, int allowStrings = 0); + /** Read a problem from AMPL nl file + NOTE - as I can't work out configure etc the source code is in Cbc_ampl.cpp! + */ + CoinModel(int nonLinear, const char *fileName, const void *info); + /// From arrays + CoinModel(int numberRows, int numberColumns, + const CoinPackedMatrix *matrix, + const double *rowLower, const double *rowUpper, + const double *columnLower, const double *columnUpper, + const double *objective); + /// Clone + virtual CoinBaseModel *clone() const; + + /** Destructor */ + virtual ~CoinModel(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModel(const CoinModel &); + /// = + CoinModel &operator=(const CoinModel &); + //@} + + /**@name For debug */ + //@{ + /// Checks that links are consistent + void validateLinks() const; + //@} +private: + /// Resize + void resize(int maximumRows, int maximumColumns, CoinBigIndex maximumElements); + /// Fill in default row information + void fillRows(int which, bool forceCreation, bool fromAddRow = false); + /// Fill in default column information + void fillColumns(int which, bool forceCreation, bool fromAddColumn = false); + /** Fill in default linked list information (1= row, 2 = column) + Marked as const as list is mutable */ + void fillList(int which, CoinModelLinkedList &list, int type) const; + /** Create a linked list and synchronize free + type 1 for row 2 for column + Marked as const as list is mutable */ + void createList(int type) const; + /// Adds one string, returns index + int addString(const char *string); + /** Gets a double from a string possibly containing named strings, + returns unset if not found + */ + double getDoubleFromString(CoinYacc &info, const char *string); + /// Frees value memory + void freeStringMemory(CoinYacc &info); + +public: + /// Fills in all associated - returning number of errors + int computeAssociated(double *associated); + /** Gets correct form for a quadratic row - user to delete + If row is not quadratic then returns which other variables are involved + with tiny (1.0e-100) elements and count of total number of variables which could not + be put in quadratic form + */ + CoinPackedMatrix *quadraticRow(int rowNumber, double *linear, + int &numberBad) const; + /// Replaces a quadratic row + void replaceQuadraticRow(int rowNumber, const double *linear, const CoinPackedMatrix *quadraticPart); + /** If possible return a model where if all variables marked nonzero are fixed + the problem will be linear. At present may only work if quadratic. + Returns NULL if not possible + */ + CoinModel *reorder(const char *mark) const; + /** Expands out all possible combinations for a knapsack + If buildObj NULL then just computes space needed - returns number elements + On entry numberOutput is maximum allowed, on exit it is number needed or + -1 (as will be number elements) if maximum exceeded. numberOutput will have at + least space to return values which reconstruct input. + Rows returned will be original rows but no entries will be returned for + any rows all of whose entries are in knapsack. So up to user to allow for this. + If reConstruct >=0 then returns number of entrie which make up item "reConstruct" + in expanded knapsack. Values in buildRow and buildElement; + */ + int expandKnapsack(int knapsackRow, int &numberOutput, double *buildObj, CoinBigIndex *buildStart, + int *buildRow, double *buildElement, int reConstruct = -1) const; + /// Sets cut marker array + void setCutMarker(int size, const int *marker); + /// Sets priority array + void setPriorities(int size, const int *priorities); + /// priorities (given for all columns (-1 if not integer) + inline const int *priorities() const + { + return priority_; + } + /// For decomposition set original row and column indices + void setOriginalIndices(const int *row, const int *column); + +private: + /** Read a problem from AMPL nl file + so not constructor so gdb will work + */ + void gdb(int nonLinear, const char *fileName, const void *info); + /// returns jColumn (-2 if linear term, -1 if unknown) and coefficient + int decodeBit(char *phrase, char *&nextPhrase, double &coefficient, bool ifFirst) const; + /// Aborts with message about packedMatrix + void badType() const; + /**@name Data members */ + //@{ + /// Maximum number of rows + int maximumRows_; + /// Maximum number of columns + int maximumColumns_; + /// Current number of elements + CoinBigIndex numberElements_; + /// Maximum number of elements + CoinBigIndex maximumElements_; + /// Current number of quadratic elements + CoinBigIndex numberQuadraticElements_; + /// Maximum number of quadratic elements + CoinBigIndex maximumQuadraticElements_; + /// Row lower + double *rowLower_; + /// Row upper + double *rowUpper_; + /// Row names + CoinModelHash rowName_; + /** Row types. + Has information - at present + bit 0 - rowLower is a string + bit 1 - rowUpper is a string + NOTE - if converted to CoinPackedMatrix - may be indices of + original rows (i.e. when decomposed) + */ + int *rowType_; + /// Objective + double *objective_; + /// Column Lower + double *columnLower_; + /// Column Upper + double *columnUpper_; + /// Column names + CoinModelHash columnName_; + /// Integer information + int *integerType_; + /// Strings + CoinModelHash string_; + /** Column types. + Has information - at present + bit 0 - columnLower is a string + bit 1 - columnUpper is a string + bit 2 - objective is a string + bit 3 - integer setting is a string + NOTE - if converted to CoinPackedMatrix - may be indices of + original columns (i.e. when decomposed) + */ + int *columnType_; + /// If simple then start of each row/column + CoinBigIndex *start_; + /// Actual elements + CoinModelTriple *elements_; + /// Actual elements as CoinPackedMatrix + CoinPackedMatrix *packedMatrix_; + /// Hash for elements + mutable CoinModelHash2 hashElements_; + /// Linked list for rows + mutable CoinModelLinkedList rowList_; + /// Linked list for columns + mutable CoinModelLinkedList columnList_; + /// Actual quadratic elements (always linked lists) + CoinModelTriple *quadraticElements_; + /// Hash for quadratic elements + mutable CoinModelHash2 hashQuadraticElements_; + /// Array for sorting indices + int *sortIndices_; + /// Array for sorting elements + double *sortElements_; + /// Size of sort arrays + int sortSize_; + /// Linked list for quadratic rows + mutable CoinModelLinkedList quadraticRowList_; + /// Linked list for quadratic columns + mutable CoinModelLinkedList quadraticColumnList_; + /// Size of associated values + int sizeAssociated_; + /// Associated values + double *associated_; + /// Number of SOS - all these are done in one go e.g. from ampl + int numberSOS_; + /// SOS starts + int *startSOS_; + /// SOS members + int *memberSOS_; + /// SOS type + int *typeSOS_; + /// SOS priority + int *prioritySOS_; + /// SOS reference + double *referenceSOS_; + /// priorities (given for all columns (-1 if not integer) + int *priority_; + /// Nonzero if row is cut - done in one go e.g. from ampl + int *cut_; + /// Pointer to more information + void *moreInfo_; + /** Type of build - + -1 unset, + 0 for row, + 1 for column, + 2 linked. + 3 matrix is CoinPackedMatrix (and at present can't be modified); + */ + mutable int type_; + /// True if no names EVER being used (for users who know what they are doing) + bool noNames_; + /** Links present (could be tested by sizes of objects) + 0 - none, + 1 - row links, + 2 - column links, + 3 - both + */ + mutable int links_; + //@} +}; +/// Just function of single variable x +double getFunctionValueFromString(const char *string, const char *x, double xValue); +/// faster version +double getDoubleFromString(CoinYacc &info, const char *string, const char *x, double xValue); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModelUseful.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModelUseful.hpp new file mode 100644 index 000000000..e0708854d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinModelUseful.hpp @@ -0,0 +1,518 @@ +/* $Id$ */ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinModelUseful_H +#define CoinModelUseful_H + +#include +#include +#include +#include +#include +#include +#include + +#include "CoinTypes.hpp" +#include "CoinPragma.hpp" + +/** + This is for various structures/classes needed by CoinModel. + + CoinModelLink + CoinModelLinkedList + CoinModelHash +*/ +/// for going through row or column + +class CoinModelLink { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelLink(); + /** Destructor */ + ~CoinModelLink(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelLink(const CoinModelLink &); + /// = + CoinModelLink &operator=(const CoinModelLink &); + //@} + + /**@name Sets and gets method */ + //@{ + /// Get row + inline int row() const + { + return row_; + } + /// Get column + inline int column() const + { + return column_; + } + /// Get value + inline double value() const + { + return value_; + } + /// Get value + inline double element() const + { + return value_; + } + /// Get position + inline CoinBigIndex position() const + { + return position_; + } + /// Get onRow + inline bool onRow() const + { + return onRow_; + } + /// Set row + inline void setRow(int row) + { + row_ = row; + } + /// Set column + inline void setColumn(int column) + { + column_ = column; + } + /// Set value + inline void setValue(double value) + { + value_ = value; + } + /// Set value + inline void setElement(double value) + { + value_ = value; + } + /// Set position + inline void setPosition(CoinBigIndex position) + { + position_ = position; + } + /// Set onRow + inline void setOnRow(bool onRow) + { + onRow_ = onRow; + } + //@} + +private: + /**@name Data members */ + //@{ + /// Row + int row_; + /// Column + int column_; + /// Value as double + double value_; + /// Position in data + CoinBigIndex position_; + /// If on row chain + bool onRow_; + //@} +}; + +/// for linked lists +// for specifying triple +typedef struct { + // top bit is nonzero if string + // rest is row + unsigned int row; + //CoinModelRowIndex row; + int column; + double value; // If string then index into strings +} CoinModelTriple; +inline int rowInTriple(const CoinModelTriple &triple) +{ + return triple.row & 0x7fffffff; +} +inline void setRowInTriple(CoinModelTriple &triple, int iRow) +{ + triple.row = iRow | (triple.row & 0x80000000); +} +inline bool stringInTriple(const CoinModelTriple &triple) +{ + return (triple.row & 0x80000000) != 0; +} +inline void setStringInTriple(CoinModelTriple &triple, bool string) +{ + triple.row = (string ? 0x80000000 : 0) | (triple.row & 0x7fffffff); +} +inline void setRowAndStringInTriple(CoinModelTriple &triple, + int iRow, bool string) +{ + triple.row = (string ? 0x80000000 : 0) | iRow; +} +/// for names and hashing +// for hashing +typedef struct { + int index, next; +} CoinModelHashLink; +typedef struct { + CoinBigIndex index, next; +} CoinModelHashLink2; + +/* Function type. */ +typedef double (*func_t)(double); + +/// For string evaluation +/* Data type for links in the chain of symbols. */ +struct symrec { + char *name; /* name of symbol */ + int type; /* type of symbol: either VAR or FNCT */ + union { + double var; /* value of a VAR */ + func_t fnctptr; /* value of a FNCT */ + } value; + struct symrec *next; /* link field */ +}; + +typedef struct symrec symrec; + +class CoinYacc { +private: + CoinYacc(const CoinYacc &rhs); + CoinYacc &operator=(const CoinYacc &rhs); + +public: + CoinYacc() + : symtable(NULL) + , symbuf(NULL) + , length(0) + , unsetValue(0) + { + } + ~CoinYacc() + { + if (length) { + free(symbuf); + symbuf = NULL; + } + symrec *s = symtable; + while (s) { + free(s->name); + symtable = s; + s = s->next; + free(symtable); + } + } + +public: + symrec *symtable; + char *symbuf; + int length; + double unsetValue; +}; + +class CoinModelHash { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelHash(); + /** Destructor */ + ~CoinModelHash(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelHash(const CoinModelHash &); + /// = + CoinModelHash &operator=(const CoinModelHash &); + //@} + + /**@name sizing (just increases) */ + //@{ + /// Resize hash (also re-hashs) + void resize(int maxItems, bool forceReHash = false); + /// Number of items i.e. rows if just row names + inline int numberItems() const + { + return numberItems_; + } + /// Set number of items + void setNumberItems(int number); + /// Maximum number of items + inline int maximumItems() const + { + return maximumItems_; + } + /// Names + inline const char *const *names() const + { + return names_; + } + //@} + + /**@name hashing */ + //@{ + /// Returns index or -1 + int hash(const char *name) const; + /// Adds to hash + void addHash(int index, const char *name); + /// Deletes from hash + void deleteHash(int index); + /// Returns name at position (or NULL) + const char *name(int which) const; + /// Returns non const name at position (or NULL) + char *getName(int which) const; + /// Sets name at position (does not create) + void setName(int which, char *name); + /// Validates + void validateHash() const; + +private: + /// Returns a hash value + int hashValue(const char *name) const; + +public: + //@} +private: + /**@name Data members */ + //@{ + /// Names + char **names_; + /// hash + CoinModelHashLink *hash_; + /// Number of items + int numberItems_; + /// Maximum number of items + int maximumItems_; + /// Last slot looked at + int lastSlot_; + //@} +}; +/// For int,int hashing +class CoinModelHash2 { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelHash2(); + /** Destructor */ + ~CoinModelHash2(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelHash2(const CoinModelHash2 &); + /// = + CoinModelHash2 &operator=(const CoinModelHash2 &); + //@} + + /**@name sizing (just increases) */ + //@{ + /// Resize hash (also re-hashs) + void resize(CoinBigIndex maxItems, const CoinModelTriple *triples, bool forceReHash = false); + /// Number of items + inline CoinBigIndex numberItems() const + { + return numberItems_; + } + /// Set number of items + void setNumberItems(CoinBigIndex number); + /// Maximum number of items + inline CoinBigIndex maximumItems() const + { + return maximumItems_; + } + //@} + + /**@name hashing */ + //@{ + /// Returns index or -1 + CoinBigIndex hash(int row, int column, const CoinModelTriple *triples) const; + /// Adds to hash + void addHash(CoinBigIndex index, int row, int column, const CoinModelTriple *triples); + /// Deletes from hash + void deleteHash(CoinBigIndex index, int row, int column); + +private: + /// Returns a hash value + CoinBigIndex hashValue(int row, int column) const; + +public: + //@} +private: + /**@name Data members */ + //@{ + /// hash + CoinModelHashLink2 *hash_; + /// Number of items + CoinBigIndex numberItems_; + /// Maximum number of items + CoinBigIndex maximumItems_; + /// Last slot looked at + CoinBigIndex lastSlot_; + //@} +}; +class CoinModelLinkedList { + +public: + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinModelLinkedList(); + /** Destructor */ + ~CoinModelLinkedList(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinModelLinkedList(const CoinModelLinkedList &); + /// = + CoinModelLinkedList &operator=(const CoinModelLinkedList &); + //@} + + /**@name sizing (just increases) */ + //@{ + /** Resize list - for row list maxMajor is maximum rows. + */ + void resize(int maxMajor, CoinBigIndex maxElements); + /** Create list - for row list maxMajor is maximum rows. + type 0 row list, 1 column list + */ + void create(int maxMajor, CoinBigIndex maxElements, + int numberMajor, int numberMinor, + int type, + CoinBigIndex numberElements, const CoinModelTriple *triples); + /// Number of major items i.e. rows if just row links + inline int numberMajor() const + { + return numberMajor_; + } + /// Maximum number of major items i.e. rows if just row links + inline int maximumMajor() const + { + return maximumMajor_; + } + /// Number of elements + inline CoinBigIndex numberElements() const + { + return numberElements_; + } + /// Maximum number of elements + inline CoinBigIndex maximumElements() const + { + return maximumElements_; + } + /// First on free chain + inline CoinBigIndex firstFree() const + { + return first_[maximumMajor_]; + } + /// Last on free chain + inline CoinBigIndex lastFree() const + { + return last_[maximumMajor_]; + } + /// First on chain + inline CoinBigIndex first(int which) const + { + return first_[which]; + } + /// Last on chain + inline CoinBigIndex last(int which) const + { + return last_[which]; + } + /// Next array + inline const CoinBigIndex *next() const + { + return next_; + } + /// Previous array + inline const CoinBigIndex *previous() const + { + return previous_; + } + //@} + + /**@name does work */ + //@{ + /** Adds to list - easy case i.e. add row to row list + Returns where chain starts + */ + CoinBigIndex addEasy(int majorIndex, CoinBigIndex numberOfElements, const int *indices, + const double *elements, CoinModelTriple *triples, + CoinModelHash2 &hash); + /** Adds to list - hard case i.e. add row to column list + */ + void addHard(int minorIndex, CoinBigIndex numberOfElements, const int *indices, + const double *elements, CoinModelTriple *triples, + CoinModelHash2 &hash); + /** Adds to list - hard case i.e. add row to column list + This is when elements have been added to other copy + */ + void addHard(CoinBigIndex first, const CoinModelTriple *triples, + CoinBigIndex firstFree, CoinBigIndex lastFree, const CoinBigIndex *nextOther); + /** Deletes from list - same case i.e. delete row from row list + */ + void deleteSame(int which, CoinModelTriple *triples, + CoinModelHash2 &hash, bool zapTriples); + /** Deletes from list - other case i.e. delete row from column list + This is when elements have been deleted from other copy + */ + void updateDeleted(int which, CoinModelTriple *triples, + CoinModelLinkedList &otherList); + /** Deletes one element from Row list + */ + void deleteRowOne(CoinBigIndex position, CoinModelTriple *triples, + CoinModelHash2 &hash); + /** Update column list for one element when + one element deleted from row copy + */ + void updateDeletedOne(CoinBigIndex position, const CoinModelTriple *triples); + /// Fills first,last with -1 + void fill(int first, int last); + /** Puts in free list from other list */ + void synchronize(CoinModelLinkedList &other); + /// Checks that links are consistent + void validateLinks(const CoinModelTriple *triples) const; + //@} +private: + /**@name Data members */ + //@{ + /// Previous - maximumElements long + CoinBigIndex *previous_; + /// Next - maximumElements long + CoinBigIndex *next_; + /// First - maximumMajor+1 long (last free element chain) + CoinBigIndex *first_; + /// Last - maximumMajor+1 long (last free element chain) + CoinBigIndex *last_; + /// Number of major items i.e. rows if just row links + int numberMajor_; + /// Maximum number of major items i.e. rows if just row links + int maximumMajor_; + /// Number of elements + CoinBigIndex numberElements_; + /// Maximum number of elements + CoinBigIndex maximumElements_; + /// 0 row list, 1 column list + int type_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMpsIO.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMpsIO.hpp new file mode 100644 index 000000000..ec97d9d7c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinMpsIO.hpp @@ -0,0 +1,1142 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinMpsIO_H +#define CoinMpsIO_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include + +#include "CoinUtilsConfig.h" +#include "CoinPackedMatrix.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinFileIO.hpp" +class CoinModel; + +/// The following lengths are in decreasing order (for 64 bit etc) +/// Large enough to contain element index +/// This is already defined as CoinBigIndex +/// Large enough to contain column index +typedef int COINColumnIndex; + +/// Large enough to contain row index (or basis) +typedef int COINRowIndex; + +// We are allowing free format - but there is a limit! +// User can override by using CXXFLAGS += -DCOIN_MAX_FIELD_LENGTH=nnn +#ifndef COIN_MAX_FIELD_LENGTH +#define COIN_MAX_FIELD_LENGTH 160 +#endif +#define MAX_CARD_LENGTH 5 * COIN_MAX_FIELD_LENGTH + 80 + +enum COINSectionType { COIN_NO_SECTION, + COIN_NAME_SECTION, + COIN_ROW_SECTION, + COIN_COLUMN_SECTION, + COIN_RHS_SECTION, + COIN_RANGES_SECTION, + COIN_BOUNDS_SECTION, + COIN_ENDATA_SECTION, + COIN_EOF_SECTION, + COIN_QUADRATIC_SECTION, + COIN_CONIC_SECTION, + COIN_QUAD_SECTION, + COIN_SOS_SECTION, + COIN_BASIS_SECTION, + COIN_UNKNOWN_SECTION +}; + +enum COINMpsType { COIN_N_ROW, + COIN_E_ROW, + COIN_L_ROW, + COIN_G_ROW, + COIN_BLANK_COLUMN, + COIN_S1_COLUMN, + COIN_S2_COLUMN, + COIN_S3_COLUMN, + COIN_INTORG, + COIN_INTEND, + COIN_SOSEND, + COIN_UNSET_BOUND, + COIN_UP_BOUND, + COIN_FX_BOUND, + COIN_LO_BOUND, + COIN_FR_BOUND, + COIN_MI_BOUND, + COIN_PL_BOUND, + COIN_BV_BOUND, + COIN_UI_BOUND, + COIN_LI_BOUND, + COIN_BOTH_BOUNDS_SET, + COIN_SC_BOUND, + COIN_S1_BOUND, + COIN_S2_BOUND, + COIN_BS_BASIS, + COIN_XL_BASIS, + COIN_XU_BASIS, + COIN_LL_BASIS, + COIN_UL_BASIS, + COIN_UNKNOWN_MPS_TYPE +}; +class CoinMpsIO; +/// Very simple code for reading MPS data +class CoinMpsCardReader { + +public: + /**@name Constructor and destructor */ + //@{ + /// Constructor expects file to be open + /// This one takes gzFile if fp null + CoinMpsCardReader(CoinFileInput *input, CoinMpsIO *reader); + + /// Destructor + ~CoinMpsCardReader(); + //@} + + /**@name card stuff */ + //@{ + /// Read to next section + COINSectionType readToNextSection(); + /// Gets next field and returns section type e.g. COIN_COLUMN_SECTION + COINSectionType nextField(); + /** Gets next field for .gms file and returns type. + -1 - EOF + 0 - what we expected (and processed so pointer moves past) + 1 - not what we expected + leading blanks always ignored + input types + 0 - anything - stops on non blank card + 1 - name (in columnname) + 2 - value + 3 - value name pair + 4 - equation type + 5 - ; + */ + int nextGmsField(int expectedType); + /// Returns current section type + inline COINSectionType whichSection() const + { + return section_; + } + /// Sets current section type + inline void setWhichSection(COINSectionType section) + { + section_ = section; + } + /// Sees if free format. + inline bool freeFormat() const + { + return freeFormat_; + } + /// Sets whether free format. Mainly for blank RHS etc + inline void setFreeFormat(bool yesNo) + { + freeFormat_ = yesNo; + } + /// Only for first field on card otherwise BLANK_COLUMN + /// e.g. COIN_E_ROW + inline COINMpsType mpsType() const + { + return mpsType_; + } + /// Reads and cleans card - taking out trailing blanks - return 1 if EOF + int cleanCard(); + /// Returns row name of current field + inline const char *rowName() const + { + return rowName_; + } + /// Returns column name of current field + inline const char *columnName() const + { + return columnName_; + } + /// Returns value in current field + inline double value() const + { + return value_; + } + /// Returns value as string in current field + inline const char *valueString() const + { + return valueString_; + } + /// Whole card (for printing) + inline const char *card() const + { + return card_; + } + /// Whole card - so we look at it (not const so nextBlankOr will work for gms reader) + inline char *mutableCard() + { + return card_; + } + /// set position (again so gms reader will work) + inline void setPosition(char *position) + { + position_ = position; + } + /// get position (again so gms reader will work) + inline char *getPosition() const + { + return position_; + } + /// Returns card number + inline CoinBigIndex cardNumber() const + { + return cardNumber_; + } + /// Returns file input + inline CoinFileInput *fileInput() const + { + return input_; + } + /// Sets whether strings allowed + inline void setStringsAllowed() + { + stringsAllowed_ = true; + } + //@} + + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Current value + double value_; + /// Current card image + char card_[MAX_CARD_LENGTH]; + /// Current position within card image + char *position_; + /// End of card + char *eol_; + /// Current COINMpsType + COINMpsType mpsType_; + /// Current row name + char rowName_[COIN_MAX_FIELD_LENGTH]; + /// Current column name + char columnName_[COIN_MAX_FIELD_LENGTH]; + /// File input + CoinFileInput *input_; + /// Which section we think we are in + COINSectionType section_; + /// Card number + CoinBigIndex cardNumber_; + /// Whether free format. Just for blank RHS etc + bool freeFormat_; + /// Whether IEEE - 0 no, 1 INTEL, 2 not INTEL + int ieeeFormat_; + /// If all names <= 8 characters then allow embedded blanks + bool eightChar_; + /// MpsIO + CoinMpsIO *reader_; + /// Message handler + CoinMessageHandler *handler_; + /// Messages + CoinMessages messages_; + /// Current element as characters (only if strings allowed) + char valueString_[COIN_MAX_FIELD_LENGTH]; + /// Whether strings allowed + bool stringsAllowed_; + //@} +public: + /**@name methods */ + //@{ + /// type - 0 normal, 1 INTEL IEEE, 2 other IEEE + double osi_strtod(char *ptr, char **output, int type); + /// remove blanks + static void strcpyAndCompress(char *to, const char *from); + /// + static char *nextBlankOr(char *image); + /// For strings + double osi_strtod(char *ptr, char **output); + //@} +}; + +//############################################################################# +#ifdef USE_SBB +class SbbObject; +class SbbModel; +#endif +/// Very simple class for containing data on set +class CoinSet { + +public: + /**@name Constructor and destructor */ + //@{ + /// Default constructor + CoinSet(); + /// Constructor + CoinSet(int numberEntries, const int *which); + + /// Copy constructor + CoinSet(const CoinSet &); + + /// Assignment operator + CoinSet &operator=(const CoinSet &rhs); + + /// Destructor + virtual ~CoinSet(); + //@} + + /**@name gets */ + //@{ + /// Returns number of entries + inline int numberEntries() const + { + return numberEntries_; + } + /// Sets number of entries + inline void setNumberEntries(int number) + { + numberEntries_ = number; + } + /// Returns type of set - 1 =SOS1, 2 =SOS2 + inline int setType() const + { + return setType_; + } + /// Sets type of set - 1 =SOS1, 2 =SOS2 + inline void setSetType(int type) + { + setType_ = type; + } + /// Returns list of variables + inline const int *which() const + { + return which_; + } + /// Returns weights + inline const double *weights() const + { + return weights_; + } + /// Returns modifiable list of variables + inline int *modifiableWhich() const + { + return which_; + } + /// Returns modifiable weights + inline double *modifiableWeights() const + { + return weights_; + } + //@} + +#ifdef USE_SBB + /**@name Use in sbb */ + //@{ + /// returns an object of type SbbObject + virtual SbbObject *sbbObject(SbbModel *model) const + { + return NULL; + } + //@} +#endif + + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Number of entries + int numberEntries_; + /// type of set + int setType_; + /// Which variables are in set + int *which_; + /// Weights + double *weights_; + //@} +}; + +//############################################################################# +/// Very simple class for containing SOS set +class CoinSosSet : public CoinSet { + +public: + /**@name Constructor and destructor */ + //@{ + /// Constructor + CoinSosSet(int numberEntries, const int *which, const double *weights, int type); + + /// Destructor + virtual ~CoinSosSet(); + //@} + +#ifdef USE_SBB + /**@name Use in sbb */ + //@{ + /// returns an object of type SbbObject + virtual SbbObject *sbbObject(SbbModel *model) const; + //@} +#endif + + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + //@} +}; + +//############################################################################# + +/** MPS IO Interface + + This class can be used to read in mps files without a solver. After + reading the file, the CoinMpsIO object contains all relevant data, which + may be more than a particular OsiSolverInterface allows for. Items may + be deleted to allow for flexibility of data storage. + + The implementation makes the CoinMpsIO object look very like a dummy solver, + as the same conventions are used. +*/ + +class CoinMpsIO { + friend void CoinMpsIOUnitTest(const std::string &mpsDir); + +public: + /** @name Methods to retrieve problem information + + These methods return information about the problem held by the CoinMpsIO + object. + + Querying an object that has no data associated with it result in zeros for + the number of rows and columns, and NULL pointers from the methods that + return vectors. Const pointers returned from any data-query method are + always valid +*/ + //@{ + /// Get number of columns + int getNumCols() const; + + /// Get number of rows + int getNumRows() const; + + /// Get number of nonzero elements + CoinBigIndex getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + const double *getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + const double *getColUpper() const; + + /** Get pointer to array[getNumRows()] of constraint senses. +
    +
  • 'L': <= constraint +
  • 'E': = constraint +
  • 'G': >= constraint +
  • 'R': ranged constraint +
  • 'N': free constraint +
+ */ + const char *getRowSense() const; + + /** Get pointer to array[getNumRows()] of constraint right-hand sides. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint right-hand side (rhs) is set as +
    +
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] +
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0 +
+ */ + const double *getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. + + Given constraints with upper (rowupper) and/or lower (rowlower) bounds, + the constraint range (rowrange) is set as +
    +
  • if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] +
  • if rowsense()[i] != 'R' then + rowrange()[i] is 0.0 +
+ Put another way, only range constraints have a nontrivial value for + rowrange. + */ + const double *getRowRange() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + const double *getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + const double *getRowUpper() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + const double *getObjCoefficients() const; + + /// Get pointer to row-wise copy of the coefficient matrix + const CoinPackedMatrix *getMatrixByRow() const; + + /// Get pointer to column-wise copy of the coefficient matrix + const CoinPackedMatrix *getMatrixByCol() const; + + /// Return true if column is a continuous variable + bool isContinuous(int colNumber) const; + + /** Return true if a column is an integer variable + + Note: This function returns true if the the column + is a binary or general integer variable. + */ + bool isInteger(int columnNumber) const; + + /** Return 1 if a column is an integer variable, 2 if semi-continuous + + Note: This function returns 1 if the the column + is a binary or general integer variable. + */ + int isIntegerOrSemiContinuous(int columnNumber) const; + + /** Returns array[getNumCols()] specifying if a variable is integer. + + At present, simply coded as zero (continuous) and non-zero (integer) + May be extended at a later date. + */ + const char *integerColumns() const; + + /** Returns the row name for the specified index. + + Returns 0 if the index is out of range. + */ + const char *rowName(int index) const; + + /** Returns the column name for the specified index. + + Returns 0 if the index is out of range. + */ + const char *columnName(int index) const; + + /** Returns the index for the specified row name + + Returns -1 if the name is not found. + Returns numberRows for the objective row and > numberRows for + dropped free rows. + */ + int rowIndex(const char *name) const; + + /** Returns the index for the specified column name + + Returns -1 if the name is not found. + */ + int columnIndex(const char *name) const; + + /** Returns the (constant) objective offset + + This is the RHS entry for the objective row + */ + double objectiveOffset() const; + /// Set objective offset + inline void setObjectiveOffset(double value) + { + objectiveOffset_ = value; + } + + /// Return the problem name + const char *getProblemName() const; + + /// Return the objective name + const char *getObjectiveName() const; + + /// Return the RHS vector name + const char *getRhsName() const; + + /// Return the range vector name + const char *getRangeName() const; + + /// Return the bound vector name + const char *getBoundName() const; + /// Number of string elements + inline int numberStringElements() const + { + return numberStringElements_; + } + /// String element + inline const char *stringElement(int i) const + { + return stringElements_[i]; + } + //@} + + /** @name Methods to set problem information + + Methods to load a problem into the CoinMpsIO object. +*/ + //@{ + + /// Set the problem data + void setMpsData(const CoinPackedMatrix &m, const double infinity, + const double *collb, const double *colub, + const double *obj, const char *integrality, + const double *rowlb, const double *rowub, + char const *const *const colnames, + char const *const *const rownames); + void setMpsData(const CoinPackedMatrix &m, const double infinity, + const double *collb, const double *colub, + const double *obj, const char *integrality, + const double *rowlb, const double *rowub, + const std::vector< std::string > &colnames, + const std::vector< std::string > &rownames); + void setMpsData(const CoinPackedMatrix &m, const double infinity, + const double *collb, const double *colub, + const double *obj, const char *integrality, + const char *rowsen, const double *rowrhs, + const double *rowrng, + char const *const *const colnames, + char const *const *const rownames); + void setMpsData(const CoinPackedMatrix &m, const double infinity, + const double *collb, const double *colub, + const double *obj, const char *integrality, + const char *rowsen, const double *rowrhs, + const double *rowrng, + const std::vector< std::string > &colnames, + const std::vector< std::string > &rownames); + + /** Pass in an array[getNumCols()] specifying if a variable is integer. + + At present, simply coded as zero (continuous) and non-zero (integer) + May be extended at a later date. + */ + void copyInIntegerInformation(const char *integerInformation); + + /// Set problem name + void setProblemName(const char *name); + + /// Set objective name + void setObjectiveName(const char *name); + + //@} + + /** @name Parameter set/get methods + + Methods to set and retrieve MPS IO parameters. +*/ + + //@{ + /// Set infinity + void setInfinity(double value); + + /// Get infinity + double getInfinity() const; + + /// Set default upper bound for integer variables + void setDefaultBound(int value); + + /// Get default upper bound for integer variables + int getDefaultBound() const; + /// Whether to allow string elements + inline int allowStringElements() const + { + return allowStringElements_; + } + /// Whether to allow string elements (0 no, 1 yes, 2 yes and try flip) + inline void setAllowStringElements(int yesNo) + { + allowStringElements_ = yesNo; + } + /** Small element value - elements less than this set to zero on input + default is 1.0e-14 */ + inline double getSmallElementValue() const + { + return smallElement_; + } + inline void setSmallElementValue(double value) + { + smallElement_ = value; + } + //@} + + /** @name Methods for problem input and output + + Methods to read and write MPS format problem files. + + The read and write methods return the number of errors that occurred during + the IO operation, or -1 if no file is opened. + + \note + If the CoinMpsIO class was compiled with support for libz then + readMps will automatically try to append .gz to the file name and open it as + a compressed file if the specified file name cannot be opened. + (Automatic append of the .bz2 suffix when libbz is used is on the TODO list.) + + \todo + Allow for file pointers and positioning +*/ + + //@{ + /// Set the current file name for the CoinMpsIO object + void setFileName(const char *name); + + /// Get the current file name for the CoinMpsIO object + const char *getFileName() const; + + /** Read a problem in MPS format from the given filename. + + Use "stdin" or "-" to read from stdin. + */ + int readMps(const char *filename, const char *extension = "mps"); + + /** Read a problem in MPS format from the given filename. + + Use "stdin" or "-" to read from stdin. + But do sets as well + */ + int readMps(const char *filename, const char *extension, + int &numberSets, CoinSet **&sets); + + /** Read a problem in MPS format from a previously opened file + + More precisely, read a problem using a CoinMpsCardReader object already + associated with this CoinMpsIO object. + + \todo + Provide an interface that will allow a client to associate a + CoinMpsCardReader object with a CoinMpsIO object by setting the + cardReader_ field. + */ + int readMps(); + /// and + int readMps(int &numberSets, CoinSet **&sets); + /** Read a basis in MPS format from the given filename. + If VALUES on NAME card and solution not NULL fills in solution + status values as for CoinWarmStartBasis (but one per char) + -1 file error, 0 normal, 1 has solution values + + Use "stdin" or "-" to read from stdin. + + If sizes of names incorrect - read without names + */ + int readBasis(const char *filename, const char *extension, + double *solution, unsigned char *rowStatus, unsigned char *columnStatus, + const std::vector< std::string > &colnames, int numberColumns, + const std::vector< std::string > &rownames, int numberRows); + + /** Read a problem in GAMS format from the given filename. + + Use "stdin" or "-" to read from stdin. + if convertObjective then massages objective column + */ + int readGms(const char *filename, const char *extension = "gms", bool convertObjective = false); + + /** Read a problem in GAMS format from the given filename. + + Use "stdin" or "-" to read from stdin. + But do sets as well + */ + int readGms(const char *filename, const char *extension, + int &numberSets, CoinSet **&sets); + + /** Read a problem in GAMS format from a previously opened file + + More precisely, read a problem using a CoinMpsCardReader object already + associated with this CoinMpsIO object. + + */ + // Not for now int readGms(); + /// and + int readGms(int &numberSets, CoinSet **&sets); + /** Read a problem in GMPL (subset of AMPL) format from the given filenames. + */ + int readGMPL(const char *modelName, const char *dataName = NULL, bool keepNames = false); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written +
    +
  • 0: plain text (default) +
  • 1: gzip compressed (.gz is appended to \c filename) +
  • 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) +
+ If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file +
    +
  • 0: normal precision (default) +
  • 1: extra accuracy +
  • 2: IEEE hex +
+ + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + \param quadratic specifies quadratic objective to be output + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, + CoinPackedMatrix *quadratic = NULL, + int numberSOS = 0, const CoinSet *setInfo = NULL) const; + + /// Return card reader object so can see what last card was e.g. QUADOBJ + inline const CoinMpsCardReader *reader() const + { + return cardReader_; + } + + /** Read in a quadratic objective from the given filename. + + If filename is NULL (or the same as the currently open file) then + reading continues from the current file. + If not, the file is closed and the specified file is opened. + + Code should be added to + general MPS reader to read this if QSECTION + Data is assumed to be Q and objective is c + 1/2 xT Q x + No assumption is made for symmetry, positive definite, etc. + No check is made for duplicates or non-triangular if checkSymmetry==0. + If 1 checks lower triangular (so off diagonal should be 2*Q) + if 2 makes lower triangular and assumes full Q (but adds off diagonals) + + Arrays should be deleted by delete [] + + Returns number of errors: +
    +
  • -1: bad file +
  • -2: no Quadratic section +
  • -3: an empty section +
  • +n: then matching errors etc (symmetry forced) +
  • -4: no matching errors but fails triangular test + (triangularity forced) +
+ columnStart is numberColumns+1 long, others numberNonZeros + */ + int readQuadraticMps(const char *filename, + CoinBigIndex *&columnStart, int *&column, double *&elements, + int checkSymmetry); + + /** Read in a list of cones from the given filename. + + If filename is NULL (or the same as the currently open file) then + reading continues from the current file. + If not, the file is closed and the specified file is opened. + + Code should be added to + general MPS reader to read this if CSECTION + No checking is done that in unique cone + + Arrays should be deleted by delete [] + + Returns number of errors, -1 bad file, -2 no conic section, + -3 empty section + + columnStart is numberCones+1 long, other number of columns in matrix + + coneType is 1 for QUAD, 2 for RQUAD (numberCones long) +*/ + int readConicMps(const char *filename, + int *&columnStart, int *&column, int *&coneType, int &numberCones); + /// Set whether to move objective from matrix + inline void setConvertObjective(bool trueFalse) + { + convertObjective_ = trueFalse; + } + /// copies in strings from a CoinModel - returns number + int copyStringElements(const CoinModel *model); + //@} + + /** @name Constructors and destructors */ + //@{ + /// Default Constructor + CoinMpsIO(); + + /// Copy constructor + CoinMpsIO(const CoinMpsIO &); + + /// Assignment operator + CoinMpsIO &operator=(const CoinMpsIO &rhs); + + /// Destructor + ~CoinMpsIO(); + //@} + + /**@name Message handling */ + //@{ + /** Pass in Message handler + + Supply a custom message handler. It will not be destroyed when the + CoinMpsIO object is destroyed. + */ + void passInMessageHandler(CoinMessageHandler *handler); + + /// Set the language for messages. + void newLanguage(CoinMessages::Language language); + + /// Set the language for messages. + inline void setLanguage(CoinMessages::Language language) { newLanguage(language); } + + /// Return the message handler + inline CoinMessageHandler *messageHandler() const { return handler_; } + + /// Return the messages + inline CoinMessages messages() { return messages_; } + /// Return the messages pointer + inline CoinMessages *messagesPointer() { return &messages_; } + //@} + + /**@name Methods to release storage + + These methods allow the client to reduce the storage used by the CoinMpsIO + object be selectively releasing unneeded problem information. +*/ + //@{ + /** Release all information which can be re-calculated. + + E.g., row sense, copies of rows, hash tables for names. + */ + void releaseRedundantInformation(); + + /// Release all row information (lower, upper) + void releaseRowInformation(); + + /// Release all column information (lower, upper, objective) + void releaseColumnInformation(); + + /// Release integer information + void releaseIntegerInformation(); + + /// Release row names + void releaseRowNames(); + + /// Release column names + void releaseColumnNames(); + + /// Release matrix information + void releaseMatrixInformation(); + //@} + +protected: + /**@name Miscellaneous helper functions */ + //@{ + + /// Utility method used several times to implement public methods + void + setMpsDataWithoutRowAndColNames( + const CoinPackedMatrix &m, const double infinity, + const double *collb, const double *colub, + const double *obj, const char *integrality, + const double *rowlb, const double *rowub); + void + setMpsDataColAndRowNames( + const std::vector< std::string > &colnames, + const std::vector< std::string > &rownames); + void + setMpsDataColAndRowNames( + char const *const *const colnames, + char const *const *const rownames); + + /// Does the heavy lifting for destruct and assignment. + void gutsOfDestructor(); + + /// Does the heavy lifting for copy and assignment. + void gutsOfCopy(const CoinMpsIO &); + + /// Clears problem data from the CoinMpsIO object. + void freeAll(); + + /** A quick inlined function to convert from lb/ub style constraint + definition to sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char &sense, double &right, double &range) const; + /** A quick inlined function to convert from sense/rhs/range stryle + constraint definition to lb/ub style */ + inline void + convertSenseToBound(const char sense, const double right, + const double range, + double &lower, double &upper) const; + + /** Deal with a filename + + As the name says. + Returns +1 if the file name is new, 0 if it's the same as before + (i.e., matches fileName_), and -1 if there's an error and the file + can't be opened. + Handles automatic append of .gz suffix when compiled with libz. + + \todo + Add automatic append of .bz2 suffix when compiled with libbz. + */ + + int dealWithFileName(const char *filename, const char *extension, + CoinFileInput *&input); + /** Add string to list + iRow==numberRows is objective, nr+1 is lo, nr+2 is up + iColumn==nc is rhs (can't cope with ranges at present) + */ + void addString(int iRow, int iColumn, const char *value); + /// Decode string + void decodeString(int iString, int &iRow, int &iColumn, const char *&value) const; + //@} + + // for hashing + typedef struct { + int index, next; + } CoinHashLink; + + /**@name Hash table methods */ + //@{ + /// Creates hash list for names (section = 0 for rows, 1 columns) + void startHash(char **names, const int number, int section); + /// This one does it when names are already in + void startHash(int section) const; + /// Deletes hash storage + void stopHash(int section); + /// Finds match using hash, -1 not found + int findHash(const char *name, int section) const; + //@} + + /**@name Cached problem information */ + //@{ + /// Problem name + char *problemName_; + + /// Objective row name + char *objectiveName_; + + /// Right-hand side vector name + char *rhsName_; + + /// Range vector name + char *rangeName_; + + /// Bounds vector name + char *boundName_; + + /// Number of rows + int numberRows_; + + /// Number of columns + int numberColumns_; + + /// Number of coefficients + CoinBigIndex numberElements_; + + /// Pointer to dense vector of row sense indicators + mutable char *rowsense_; + + /// Pointer to dense vector of row right-hand side values + mutable double *rhs_; + + /** Pointer to dense vector of slack variable upper bounds for range + constraints (undefined for non-range rows) + */ + mutable double *rowrange_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByRow_; + + /// Pointer to column-wise copy of problem matrix coefficients. + CoinPackedMatrix *matrixByColumn_; + + /// Pointer to dense vector of row lower bounds + double *rowlower_; + + /// Pointer to dense vector of row upper bounds + double *rowupper_; + + /// Pointer to dense vector of column lower bounds + double *collower_; + + /// Pointer to dense vector of column upper bounds + double *colupper_; + + /// Pointer to dense vector of objective coefficients + double *objective_; + + /// Constant offset for objective value (i.e., RHS value for OBJ row) + double objectiveOffset_; + + /** Pointer to dense vector specifying if a variable is continuous + (0) or integer (1). + */ + char *integerType_; + + /** Row and column names + Linked to hash table sections (0 - row names, 1 column names) + */ + char **names_[2]; + //@} + + /** @name Hash tables */ + //@{ + /// Current file name + char *fileName_; + + /// Number of entries in a hash table section + int numberHash_[2]; + + /// Hash tables (two sections, 0 - row names, 1 - column names) + mutable CoinHashLink *hash_[2]; + //@} + + /** @name CoinMpsIO object parameters */ + //@{ + /// Upper bound when no bounds for integers + int defaultBound_; + + /// Value to use for infinity + double infinity_; + /// Small element value + double smallElement_; + + /// Message handler + CoinMessageHandler *handler_; + /** Flag to say if the message handler is the default handler. + + If true, the handler will be destroyed when the CoinMpsIO + object is destroyed; if false, it will not be destroyed. + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + /// Card reader + CoinMpsCardReader *cardReader_; + /// If .gms file should it be massaged to move objective + bool convertObjective_; + /// Whether to allow string elements + int allowStringElements_; + /// Maximum number of string elements + int maximumStringElements_; + /// Number of string elements + int numberStringElements_; + /// String elements + char **stringElements_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CoinMpsIO class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. Also, if this method is compiled with + optimization, the compilation takes 10-15 minutes and the machine pages + (has 256M core memory!)... */ +void CoinMpsIOUnitTest(const std::string &mpsDir); +// Function to return number in most efficient way +// section is 0 for columns, 1 for rhs,ranges and 2 for bounds +/* formatType is + 0 - normal and 8 character names + 1 - extra accuracy + 2 - IEEE hex - INTEL + 3 - IEEE hex - not INTEL +*/ +void CoinConvertDouble(int section, int formatType, double value, char outputValue[24]); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinOslFactorization.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinOslFactorization.hpp new file mode 100644 index 000000000..3a41e3348 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinOslFactorization.hpp @@ -0,0 +1,287 @@ +/* $Id$ */ +// Copyright (C) 1987, 2009, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + Authors + + John Forrest + + */ +#ifndef CoinOslFactorization_H +#define CoinOslFactorization_H +#include +#include +#include +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinDenseFactorization.hpp" +class CoinPackedMatrix; +/** This deals with Factorization and Updates + This is ripped off from OSL!!!!!!!!! + + I am assuming that 32 bits is enough for number of rows or columns, but CoinBigIndex + may be redefined to get 64 bits. + */ + +typedef struct { + int suc, pre; +} EKKHlink; +typedef struct _EKKfactinfo { + double drtpiv; + double demark; + double zpivlu; + double zeroTolerance; + double areaFactor; + int *xrsadr; + int *xcsadr; + int *xrnadr; + int *xcnadr; + int *krpadr; + int *kcpadr; + int *mpermu; + int *bitArray; + int *back; + char *nonzero; + double *trueStart; + mutable double *kadrpm; + int *R_etas_index; + int *R_etas_start; + double *R_etas_element; + + int *xecadr; + int *xeradr; + double *xeeadr; + double *xe2adr; + EKKHlink *kp1adr; + EKKHlink *kp2adr; + double *kw1adr; + double *kw2adr; + double *kw3adr; + int *hpivcoR; + int nrow; + int nrowmx; + int firstDoRow; + int firstLRow; + int maxinv; + int nnetas; + int iterin; + int iter0; + int invok; + int nbfinv; + int num_resets; + int nnentl; + int nnentu; +#ifdef CLP_REUSE_ETAS + int save_nnentu; +#endif + int ndenuc; + int npivots; /* use as xpivsq in factorization */ + int kmxeta; + int xnetal; + int first_dense; + int last_dense; + int iterno; + int numberSlacks; + int lastSlack; + int firstNonSlack; + int xnetalval; + int lstart; + int if_sparse_update; + mutable int packedMode; + int switch_off_sparse_update; + int nuspike; + bool rows_ok; /* replaces test using mrstrt[1] */ +#ifdef CLP_REUSE_ETAS + mutable int reintro; +#endif + int nR_etas; + int sortedEta; /* if vector for F-T is sorted */ + int lastEtaCount; + int ifvsol; + int eta_size; + int last_eta_size; + int maxNNetas; +} EKKfactinfo; + +class CoinOslFactorization : public CoinOtherFactorization { + friend void CoinOslFactorizationUnitTest(const std::string &mpsDir); + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinOslFactorization(); + /// Copy constructor + CoinOslFactorization(const CoinOslFactorization &other); + + /// Destructor + virtual ~CoinOslFactorization(); + /// = copy + CoinOslFactorization &operator=(const CoinOslFactorization &other); + /// Clone + virtual CoinOtherFactorization *clone() const; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas(int numberRows, + int numberColumns, + int maximumL, + int maximumU); + + /// PreProcesses column ordered copy of basis + virtual void preProcess(); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor(); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int *sequence, int *pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int *sequence, int numberColumns); + /** When part of LP - given by basic variables. + Actually does factorization. + Arrays passed in have non negative value to say basic. + If status is okay, basic variables have pivot row - this is only needed + If status is singular, then basic variables have pivot row + and ones thrown out have -1 + returns 0 -okay, -1 singular, -2 too many in basis, -99 memory */ + int factorize(const CoinPackedMatrix &matrix, + int rowIsBasic[], int columnIsBasic[], + double areaFactor = 0.0); + //@} + + /**@name general stuff such as number of elements */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements() const + { + return numberRows_ * (numberColumns_ + numberPivots_); + } + /// Returns array to put basis elements in + virtual CoinFactorizationDouble *elements() const; + /// Returns pivot row + virtual int *pivotRow() const; + /// Returns work area + virtual CoinFactorizationDouble *workArea() const; + /// Returns int work area + virtual int *intWorkArea() const; + /// Number of entries in each row + virtual int *numberInRow() const; + /// Number of entries in each column + virtual int *numberInColumn() const; + /// Returns array to put basis starts in + virtual int *starts() const; + /// Returns permute back + virtual int *permuteBack() const; + /// Returns true if wants tableauColumn in replaceColumn + virtual bool wantsTableauColumn() const; + /** Useful information for factorization + 0 - iteration number + whereFrom is 0 for factorize and 1 for replaceColumn + */ + virtual void setUsefulInformation(const int *info, int whereFrom); + /// Set maximum pivots + virtual void maximumPivots(int value); + + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + /// Condition number - product of pivots after factorization + double conditionNumber() const; + /// Get rid of all memory + virtual void clearArrays(); + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false); + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermute = false); + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + //inline void clearArrays() + //{ gutsOfDestructor();} + /// Returns array to put basis indices in + virtual int *indices() const; + /// Returns permute in + virtual inline int *permute() const + { + return NULL; /*pivotRow_*/ + ; + } + //@} + + /// The real work of desstructor + void gutsOfDestructor(bool clearFact = true); + /// The real work of constructor + void gutsOfInitialize(bool zapFact = true); + /// The real work of copy + void gutsOfCopy(const CoinOslFactorization &other); + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// Osl factorization data + EKKfactinfo factInfo_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedMatrix.hpp new file mode 100644 index 000000000..c8ff9c461 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedMatrix.hpp @@ -0,0 +1,956 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedMatrix_H +#define CoinPackedMatrix_H + +#include "CoinError.hpp" +#include "CoinTypes.hpp" +#ifndef CLP_NO_VECTOR +#include "CoinPackedVectorBase.hpp" +#include "CoinShallowPackedVector.hpp" +#else +class CoinRelFltEq; +#endif + +/** Sparse Matrix Base Class + + This class is intended to represent sparse matrices using row-major + or column-major ordering. The representation is very efficient for + adding, deleting, or retrieving major-dimension vectors. Adding + a minor-dimension vector is less efficient, but can be helped by + providing "extra" space as described in the next paragraph. Deleting + a minor-dimension vector requires inspecting all coefficients in the + matrix. Retrieving a minor-dimension vector would incur the same cost + and is not supported (except in the sense that you can write a loop to + retrieve all coefficients one at a time). Consider physically transposing + the matrix, or keeping a second copy with the other major-vector ordering. + + The sparse represention can be completely compact or it can have "extra" + space available at the end of each major vector. Incorporating extra + space into the sparse matrix representation can improve performance in + cases where new data needs to be inserted into the packed matrix against + the major-vector orientation (e.g, inserting a row into a matrix stored + in column-major order). + + For example if the matrix: + @verbatim + 3 1 0 -2 -1 0 0 -1 + 0 2 1.1 0 0 0 0 0 + 0 0 1 0 0 1 0 0 + 0 0 0 2.8 0 0 -1.2 0 + 5.6 0 0 0 1 0 0 1.9 + + was stored by rows (with no extra space) in + CoinPackedMatrix r then: + r.getElements() returns a vector containing: + 3 1 -2 -1 -1 2 1.1 1 1 2.8 -1.2 5.6 1 1.9 + r.getIndices() returns a vector containing: + 0 1 3 4 7 1 2 2 5 3 6 0 4 7 + r.getVectorStarts() returns a vector containing: + 0 5 7 9 11 14 + r.getNumElements() returns 14. + r.getMajorDim() returns 5. + r.getVectorSize(0) returns 5. + r.getVectorSize(1) returns 2. + r.getVectorSize(2) returns 2. + r.getVectorSize(3) returns 2. + r.getVectorSize(4) returns 3. + + If stored by columns (with no extra space) then: + c.getElements() returns a vector containing: + 3 5.6 1 2 1.1 1 -2 2.8 -1 1 1 -1.2 -1 1.9 + c.getIndices() returns a vector containing: + 0 4 0 1 1 2 0 3 0 4 2 3 0 4 + c.getVectorStarts() returns a vector containing: + 0 2 4 6 8 10 11 12 14 + c.getNumElements() returns 14. + c.getMajorDim() returns 8. + @endverbatim + + Compiling this class with CLP_NO_VECTOR defined will excise all methods + which use CoinPackedVectorBase, CoinPackedVector, or CoinShallowPackedVector + as parameters or return types. + + Compiling this class with COIN_FAST_CODE defined removes index range checks. +*/ +class CoinPackedMatrix { + friend void CoinPackedMatrixUnitTest(); + +public: + //--------------------------------------------------------------------------- + /**@name Query members */ + //@{ + /** Return the current setting of the extra gap. */ + inline double getExtraGap() const { return extraGap_; } + /** Return the current setting of the extra major. */ + inline double getExtraMajor() const { return extraMajor_; } + + /** Reserve sufficient space for appending major-ordered vectors. + If create is true, empty columns are created (for column generation) */ + void reserve(const int newMaxMajorDim, const CoinBigIndex newMaxSize, + bool create = false); + /** Clear the data, but do not free any arrays */ + void clear(); + + /** Whether the packed matrix is column major ordered or not. */ + inline bool isColOrdered() const { return colOrdered_; } + + /** Whether the packed matrix has gaps or not. */ + inline bool hasGaps() const { return (size_ < start_[majorDim_]); } + + /** Number of entries in the packed matrix. */ + inline CoinBigIndex getNumElements() const { return size_; } + + /** Number of columns. */ + inline int getNumCols() const + { + return colOrdered_ ? majorDim_ : minorDim_; + } + + /** Number of rows. */ + inline int getNumRows() const + { + return colOrdered_ ? minorDim_ : majorDim_; + } + + /*! \brief A vector containing the elements in the packed matrix. + + Returns #elements_. Note that there might be gaps in this vector, + entries that do not belong to any major-dimension vector. To get + the actual elements one should look at this vector together with + vectorStarts (#start_) and vectorLengths (#length_). + */ + inline const double *getElements() const { return element_; } + + /*! \brief A vector containing the minor indices of the elements in + the packed matrix. + + Returns #index_. Note that there might be gaps in this list, + entries that do not belong to any major-dimension vector. To get + the actual elements one should look at this vector together with + vectorStarts (#start_) and vectorLengths (#length_). + */ + inline const int *getIndices() const { return index_; } + + /*! \brief The size of the vectorStarts array + + See #start_. + */ + inline int getSizeVectorStarts() const + { + return ((majorDim_ > 0) ? (majorDim_ + 1) : (0)); + } + + /*! \brief The size of the vectorLengths array + + See #length_. + */ + inline int getSizeVectorLengths() const { return majorDim_; } + + /*! \brief The positions where the major-dimension vectors start in + elements and indices. + + See #start_. + */ + inline const CoinBigIndex *getVectorStarts() const { return start_; } + + /*! \brief The lengths of the major-dimension vectors. + + See #length_. + */ + inline const int *getVectorLengths() const { return length_; } + + /** The position of the first element in the i'th major-dimension vector. + */ + CoinBigIndex getVectorFirst(const int i) const + { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorFirst", "CoinPackedMatrix"); +#endif + return start_[i]; + } + /** The position of the last element (well, one entry past the + last) in the i'th major-dimension vector. */ + CoinBigIndex getVectorLast(const int i) const + { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorLast", "CoinPackedMatrix"); +#endif + return start_[i] + length_[i]; + } + /** The length of i'th vector. */ + inline int getVectorSize(const int i) const + { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vectorSize", "CoinPackedMatrix"); +#endif + return length_[i]; + } +#ifndef CLP_NO_VECTOR + /** Return the i'th vector in matrix. */ + const CoinShallowPackedVector getVector(int i) const + { +#ifndef COIN_FAST_CODE + if (i < 0 || i >= majorDim_) + throw CoinError("bad index", "vector", "CoinPackedMatrix"); +#endif + return CoinShallowPackedVector(length_[i], + index_ + start_[i], + element_ + start_[i], + false); + } +#endif + /** Returns an array containing major indices. The array is + getNumElements long and if getVectorStarts() is 0,2,5 then + the array would start 0,0,1,1,1,2... + This method is provided to go back from a packed format + to a triple format. It returns NULL if there are gaps in + matrix so user should use removeGaps() if there are any gaps. + It does this as this array has to match getElements() and + getIndices() and because it makes no sense otherwise. + The returned array is allocated with new int[], + free it with delete[]. */ + int *getMajorIndices() const; + //@} + + //--------------------------------------------------------------------------- + /**@name Modifying members */ + //@{ + /*! \brief Set the dimensions of the matrix. + + The method name is deceptive; the effect is to append empty columns + and/or rows to the matrix to reach the specified dimensions. + A negative number for either dimension means that that dimension + doesn't change. An exception will be thrown if the specified dimensions + are smaller than the current dimensions. + */ + void setDimensions(int numrows, int numcols); + + /** Set the extra gap to be allocated to the specified value. */ + void setExtraGap(const double newGap); + /** Set the extra major to be allocated to the specified value. */ + void setExtraMajor(const double newMajor); +#ifndef CLP_NO_VECTOR + /*! Append a column to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the column vector specifies a nonexistent row index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendCol(const CoinPackedVectorBase &vec); +#endif + /*! Append a column to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the column vector specifies a nonexistent row index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendCol(const int vecsize, + const int *vecind, const double *vecelem); +#ifndef CLP_NO_VECTOR + /*! Append a set of columns to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if any of the column vectors specify a nonexistent row index. Otherwise + the method assumes that every index fits into the matrix. + */ + void appendCols(const int numcols, + const CoinPackedVectorBase *const *cols); +#endif + /*! Append a set of columns to the end of the matrix. + + Returns the number of errors (nonexistent or duplicate row index). + No error checking is performed if \p numberRows < 0. + */ + int appendCols(const int numcols, + const CoinBigIndex *columnStarts, const int *row, + const double *element, int numberRows = -1); +#ifndef CLP_NO_VECTOR + /*! Append a row to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the row vector specifies a nonexistent column index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendRow(const CoinPackedVectorBase &vec); +#endif + /*! Append a row to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if the row vector specifies a nonexistent column index. Otherwise the + method assumes that every index fits into the matrix. + */ + void appendRow(const int vecsize, + const int *vecind, const double *vecelem); +#ifndef CLP_NO_VECTOR + /*! Append a set of rows to the end of the matrix. + + When compiled with COIN_DEBUG defined this method throws an exception + if any of the row vectors specify a nonexistent column index. Otherwise + the method assumes that every index fits into the matrix. + */ + void appendRows(const int numrows, + const CoinPackedVectorBase *const *rows); +#endif + /*! Append a set of rows to the end of the matrix. + + Returns the number of errors (nonexistent or duplicate column index). + No error checking is performed if \p numberColumns < 0. + */ + int appendRows(const int numrows, + const CoinBigIndex *rowStarts, const int *column, + const double *element, int numberColumns = -1); + + /** Append the argument to the "right" of the current matrix. Imagine this + as adding new columns (don't worry about how the matrices are ordered, + that is taken care of). An exception is thrown if the number of rows + is different in the matrices. */ + void rightAppendPackedMatrix(const CoinPackedMatrix &matrix); + /** Append the argument to the "bottom" of the current matrix. Imagine this + as adding new rows (don't worry about how the matrices are ordered, + that is taken care of). An exception is thrown if the number of columns + is different in the matrices. */ + void bottomAppendPackedMatrix(const CoinPackedMatrix &matrix); + + /** Delete the columns whose indices are listed in indDel. */ + void deleteCols(const int numDel, const int *indDel); + /** Delete the rows whose indices are listed in indDel. */ + void deleteRows(const int numDel, const int *indDel); + + /** Replace the elements of a vector. The indices remain the same. + At most the number specified will be replaced. + The index is between 0 and major dimension of matrix */ + void replaceVector(const int index, + const int numReplace, const double *newElements); + /** Modify one element of packed matrix. An element may be added. + This works for either ordering + If the new element is zero it will be deleted unless + keepZero true */ + void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false); + /** Return one element of packed matrix. + This works for either ordering + If it is not present will return 0.0 */ + double getCoefficient(int row, int column) const; + + /** Eliminate all elements in matrix whose + absolute value is less than threshold. + The column starts are not affected. Returns number of elements + eliminated. Elements eliminated are at end of each vector + */ + CoinBigIndex compress(double threshold); + /** Eliminate all duplicate AND small elements in matrix + The column starts are not affected. Returns number of elements + eliminated. + */ + CoinBigIndex eliminateDuplicates(double threshold); + /** Sort all columns so indices are increasing.in each column */ + void orderMatrix(); + /** Really clean up matrix. + a) eliminate all duplicate AND small elements in matrix + b) remove all gaps and set extraGap_ and extraMajor_ to 0.0 + c) reallocate arrays and make max lengths equal to lengths + d) orders elements + returns number of elements eliminated + */ + CoinBigIndex cleanMatrix(double threshold = 1.0e-20); + //@} + + //--------------------------------------------------------------------------- + /**@name Methods that reorganize the whole matrix */ + //@{ + /** Remove the gaps from the matrix if there were any + Can also remove small elements fabs() <= removeValue*/ + void removeGaps(double removeValue = -1.0); + + /** Extract a submatrix from matrix. Those major-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. Does not allow duplicates. */ + void submatrixOf(const CoinPackedMatrix &matrix, + const int numMajor, const int *indMajor); + /** Extract a submatrix from matrix. Those major-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. Allows duplicates and keeps order. */ + void submatrixOfWithDuplicates(const CoinPackedMatrix &matrix, + const int numMajor, const int *indMajor); +#if 0 + /** Extract a submatrix from matrix. Those major/minor-dimension vectors of + the matrix comprise the submatrix whose indices are given in the + arguments. */ + void submatrixOf(const CoinPackedMatrix& matrix, + const int numMajor, const int * indMajor, + const int numMinor, const int * indMinor); +#endif + + /** Copy method. This method makes an exact replica of the argument, + including the extra space parameters. */ + void copyOf(const CoinPackedMatrix &rhs); + /** Copy the arguments to the matrix. If len is a NULL pointer + then the matrix is assumed to have no gaps in it and len + will be created accordingly. */ + void copyOf(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double *elem, const int *ind, + const CoinBigIndex *start, const int *len, + const double extraMajor = 0.0, const double extraGap = 0.0); + /** Copy method. This method makes an exact replica of the argument, + including the extra space parameters. + If there is room it will re-use arrays */ + void copyReuseArrays(const CoinPackedMatrix &rhs); + + /*! \brief Make a reverse-ordered copy. + + This method makes an exact replica of the argument with the major + vector orientation changed from row (column) to column (row). + The extra space parameters are also copied and reversed. + (Cf. #reverseOrdering, which does the same thing in place.) + */ + void reverseOrderedCopyOf(const CoinPackedMatrix &rhs); + + /** Assign the arguments to the matrix. If len is a NULL + pointer then the matrix is assumed to have no gaps in it and + len will be created accordingly.
+ NOTE 1: After this method returns the pointers + passed to the method will be NULL pointers!
+ NOTE 2: When the matrix is eventually destructed the + arrays will be deleted by delete[]. Hence one should use + this method ONLY if all array swere allocated by new[]! */ + void assignMatrix(const bool colordered, + const int minor, const int major, + const CoinBigIndex numels, + double *&elem, int *&ind, + CoinBigIndex *&start, int *&len, + const int maxmajor = -1, const CoinBigIndex maxsize = -1); + + /** Assignment operator. This copies out the data, but uses the current + matrix's extra space parameters. */ + CoinPackedMatrix &operator=(const CoinPackedMatrix &rhs); + + /*! \brief Reverse the ordering of the packed matrix. + + Change the major vector orientation of the matrix data structures from + row (column) to column (row). (Cf. #reverseOrderedCopyOf, which does + the same thing but produces a new matrix.) + */ + void reverseOrdering(); + + /*! \brief Transpose the matrix. + + \note + If you start with a column-ordered matrix and invoke transpose, you + will have a row-ordered transposed matrix. To change the major vector + orientation (e.g., to transform a column-ordered matrix to a + column-ordered transposed matrix), invoke transpose() followed by + #reverseOrdering(). + */ + void transpose(); + + /*! \brief Swap the content of two packed matrices. */ + void swap(CoinPackedMatrix &matrix); + + //@} + + //--------------------------------------------------------------------------- + /**@name Matrix times vector methods */ + //@{ + /** Return A * x in y. + @pre x must be of size numColumns() + @pre y must be of size numRows() */ + void times(const double *x, double *y) const; +#ifndef CLP_NO_VECTOR + /** Return A * x in y. Same as the previous + method, just x is given in the form of a packed vector. */ + void times(const CoinPackedVectorBase &x, double *y) const; +#endif + /** Return x * A in y. + @pre x must be of size numRows() + @pre y must be of size numColumns() */ + void transposeTimes(const double *x, double *y) const; +#ifndef CLP_NO_VECTOR + /** Return x * A in y. Same as the previous + method, just x is given in the form of a packed vector. */ + void transposeTimes(const CoinPackedVectorBase &x, double *y) const; +#endif + //@} + + //--------------------------------------------------------------------------- + /**@name Helper functions used internally, but maybe useful externally. + + These methods do not worry about testing whether the packed matrix is + row or column major ordered; they operate under the assumption that the + correct version is invoked. In fact, a number of other methods simply + just call one of these after testing the ordering of the matrix. */ + //@{ + + //------------------------------------------------------------------------- + /**@name Queries */ + //@{ + /** Count the number of entries in every minor-dimension vector and + return an array containing these lengths. The returned array is + allocated with new int[], free it with + delete[]. */ + int *countOrthoLength() const; + /** Count the number of entries in every minor-dimension vector and + fill in an array containing these lengths. */ + void countOrthoLength(int *counts) const; + /** Major dimension. For row ordered matrix this would be the number of + rows. */ + inline int getMajorDim() const { return majorDim_; } + /** Set major dimension. For row ordered matrix this would be the number of + rows. Use with great care.*/ + inline void setMajorDim(int value) { majorDim_ = value; } + /** Minor dimension. For row ordered matrix this would be the number of + columns. */ + inline int getMinorDim() const { return minorDim_; } + /** Set minor dimension. For row ordered matrix this would be the number of + columns. Use with great care.*/ + inline void setMinorDim(int value) { minorDim_ = value; } + /** Current maximum for major dimension. For row ordered matrix this many + rows can be added without reallocating the vector related to the + major dimension (start_ and length_). */ + inline int getMaxMajorDim() const { return maxMajorDim_; } + + /** Dump the matrix on stdout. When in dire straits this method can + help. */ + void dumpMatrix(const char *fname = NULL) const; + + /// Print a single matrix element. + void printMatrixElement(const int row_val, const int col_val) const; + //@} + + //------------------------------------------------------------------------- + /*! @name Append vectors + + \details + When compiled with COIN_DEBUG defined these methods throw an exception + if the major (minor) vector contains an index that's invalid for the + minor (major) dimension. Otherwise the methods assume that every index + fits into the matrix. + */ + //@{ +#ifndef CLP_NO_VECTOR + /** Append a major-dimension vector to the end of the matrix. */ + void appendMajorVector(const CoinPackedVectorBase &vec); +#endif + /** Append a major-dimension vector to the end of the matrix. */ + void appendMajorVector(const int vecsize, const int *vecind, + const double *vecelem); +#ifndef CLP_NO_VECTOR + /** Append several major-dimensonvectors to the end of the matrix */ + void appendMajorVectors(const int numvecs, + const CoinPackedVectorBase *const *vecs); + + /** Append a minor-dimension vector to the end of the matrix. */ + void appendMinorVector(const CoinPackedVectorBase &vec); +#endif + /** Append a minor-dimension vector to the end of the matrix. */ + void appendMinorVector(const int vecsize, const int *vecind, + const double *vecelem); +#ifndef CLP_NO_VECTOR + /** Append several minor-dimension vectors to the end of the matrix */ + void appendMinorVectors(const int numvecs, + const CoinPackedVectorBase *const *vecs); +#endif + /*! \brief Append a set of rows (columns) to the end of a column (row) + ordered matrix. + + This case is when we know there are no gaps and majorDim_ will not + change. + + \todo + This method really belongs in the group of protected methods with + #appendMinor; there are no safeties here even with COIN_DEBUG. + Apparently this method was needed in ClpPackedMatrix and giving it + proper visibility was too much trouble. Should be moved. + */ + void appendMinorFast(const int number, + const CoinBigIndex *starts, const int *index, + const double *element); + //@} + + //------------------------------------------------------------------------- + /*! \name Append matrices + + \details + We'll document these methods assuming that the current matrix is + column major ordered (Hence in the ...SameOrdered() + methods the argument is column ordered, in the + OrthoOrdered() methods the argument is row ordered.) + */ + //@{ + /** Append the columns of the argument to the right end of this matrix. + @pre minorDim_ == matrix.minorDim_
+ This method throws an exception if the minor dimensions are not the + same. */ + void majorAppendSameOrdered(const CoinPackedMatrix &matrix); + /** Append the columns of the argument to the bottom end of this matrix. + @pre majorDim_ == matrix.majorDim_
+ This method throws an exception if the major dimensions are not the + same. */ + void minorAppendSameOrdered(const CoinPackedMatrix &matrix); + /** Append the rows of the argument to the right end of this matrix. + @pre minorDim_ == matrix.majorDim_
+ This method throws an exception if the minor dimension of the + current matrix is not the same as the major dimension of the + argument matrix. */ + void majorAppendOrthoOrdered(const CoinPackedMatrix &matrix); + /** Append the rows of the argument to the bottom end of this matrix. + @pre majorDim_ == matrix.minorDim_
+ This method throws an exception if the major dimension of the + current matrix is not the same as the minor dimension of the + argument matrix. */ + void minorAppendOrthoOrdered(const CoinPackedMatrix &matrix); + //@} + + //----------------------------------------------------------------------- + /**@name Delete vectors */ + //@{ + /** Delete the major-dimension vectors whose indices are listed in + indDel. */ + void deleteMajorVectors(const int numDel, const int *indDel); + /** Delete the minor-dimension vectors whose indices are listed in + indDel. */ + void deleteMinorVectors(const int numDel, const int *indDel); + //@} + + //----------------------------------------------------------------------- + /**@name Various dot products. */ + //@{ + /** Return A * x (multiplied from the "right" direction) in + y. + @pre x must be of size majorDim() + @pre y must be of size minorDim() */ + void timesMajor(const double *x, double *y) const; +#ifndef CLP_NO_VECTOR + /** Return A * x (multiplied from the "right" direction) in + y. Same as the previous method, just x is + given in the form of a packed vector. */ + void timesMajor(const CoinPackedVectorBase &x, double *y) const; +#endif + /** Return A * x (multiplied from the "right" direction) in + y. + @pre x must be of size minorDim() + @pre y must be of size majorDim() */ + void timesMinor(const double *x, double *y) const; +#ifndef CLP_NO_VECTOR + /** Return A * x (multiplied from the "right" direction) in + y. Same as the previous method, just x is + given in the form of a packed vector. */ + void timesMinor(const CoinPackedVectorBase &x, double *y) const; +#endif + //@} + //@} + + //-------------------------------------------------------------------------- + /**@name Logical Operations. */ + //@{ +#ifndef CLP_NO_VECTOR + /*! \brief Test for equivalence. + + Two matrices are equivalent if they are both row- or column-ordered, + they have the same dimensions, and each (major) vector is equivalent. + The operator used to test for equality can be specified using the + \p FloatEqual template parameter. + */ + template < class FloatEqual > + bool + isEquivalent(const CoinPackedMatrix &rhs, const FloatEqual &eq) const + { + // Both must be column order or both row ordered and must be of same size + if ((isColOrdered() ^ rhs.isColOrdered()) || (getNumCols() != rhs.getNumCols()) || (getNumRows() != rhs.getNumRows()) || (getNumElements() != rhs.getNumElements())) + return false; + + for (int i = getMajorDim() - 1; i >= 0; --i) { + CoinShallowPackedVector pv = getVector(i); + CoinShallowPackedVector rhsPv = rhs.getVector(i); + if (!pv.isEquivalent(rhsPv, eq)) + return false; + } + return true; + } + + /*! \brief Test for equivalence and report differences + + Equivalence is defined as for #isEquivalent. In addition, this method will + print differences to std::cerr. Intended for use in unit tests and + for debugging. + */ + bool isEquivalent2(const CoinPackedMatrix &rhs) const; +#else + /*! \brief Test for equivalence. + + Two matrices are equivalent if they are both row- or column-ordered, + they have the same dimensions, and each (major) vector is equivalent. + This method is optimised for speed. CoinPackedVector#isEquivalent is + replaced with more efficient code for repeated comparison of + equal-length vectors. The CoinRelFltEq operator is used. + */ + bool isEquivalent(const CoinPackedMatrix &rhs, const CoinRelFltEq &eq) const; +#endif + /*! \brief Test for equivalence. + + The test for element equality is the default CoinRelFltEq operator. + */ + bool isEquivalent(const CoinPackedMatrix &rhs) const; + //@} + + //-------------------------------------------------------------------------- + /*! \name Non-const methods + + These are to be used with great care when doing column generation, etc. + */ + //@{ + /** A vector containing the elements in the packed matrix. Note that there + might be gaps in this list, entries that do not belong to any + major-dimension vector. To get the actual elements one should look at + this vector together with #start_ and #length_. */ + inline double *getMutableElements() const { return element_; } + /** A vector containing the minor indices of the elements in the packed + matrix. Note that there might be gaps in this list, entries that do not + belong to any major-dimension vector. To get the actual elements one + should look at this vector together with #start_ and + #length_. */ + inline int *getMutableIndices() const { return index_; } + + /** The positions where the major-dimension vectors start in #element_ and + #index_. */ + inline CoinBigIndex *getMutableVectorStarts() const { return start_; } + /** The lengths of the major-dimension vectors. */ + inline int *getMutableVectorLengths() const { return length_; } + /// Change the size of the bulk store after modifying - be careful + inline void setNumElements(CoinBigIndex value) + { + size_ = value; + } + /*! NULLify element array + + Used when space is very tight. Does not free the space! + */ + inline void nullElementArray() { element_ = NULL; } + + /*! NULLify start array + + Used when space is very tight. Does not free the space! + */ + inline void nullStartArray() { start_ = NULL; } + + /*! NULLify length array + + Used when space is very tight. Does not free the space! + */ + inline void nullLengthArray() { length_ = NULL; } + + /*! NULLify index array + + Used when space is very tight. Does not free the space! + */ + inline void nullIndexArray() { index_ = NULL; } + //@} + + //-------------------------------------------------------------------------- + /*! \name Constructors and destructors */ + //@{ + /// Default Constructor creates an empty column ordered packed matrix + CoinPackedMatrix(); + + /// A constructor where the ordering and the gaps are specified + CoinPackedMatrix(const bool colordered, + const double extraMajor, const double extraGap); + + CoinPackedMatrix(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double *elem, const int *ind, + const CoinBigIndex *start, const int *len, + const double extraMajor, const double extraGap); + + CoinPackedMatrix(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double *elem, const int *ind, + const CoinBigIndex *start, const int *len); + + /** Create packed matrix from triples. + If colordered is true then the created matrix will be column ordered. + Duplicate matrix elements are allowed. The created matrix will have + the sum of the duplicates.
+ For example if:
+ rowIndices[0]=2; colIndices[0]=5; elements[0]=2.0
+ rowIndices[1]=2; colIndices[1]=5; elements[1]=0.5
+ then the created matrix will contain a value of 2.5 in row 2 and column 5.
+ The matrix is created without gaps. + */ + CoinPackedMatrix(const bool colordered, + const int *rowIndices, + const int *colIndices, + const double *elements, + CoinBigIndex numels); + + /// Copy constructor + CoinPackedMatrix(const CoinPackedMatrix &m); + + /*! \brief Copy constructor with fine tuning + + This constructor allows for the specification of an exact amount of extra + space and/or reverse ordering. + + \p extraForMajor is the exact number of spare major vector slots after + any possible reverse ordering. If \p extraForMajor < 0, all gaps and small + elements will be removed from the copy, otherwise gaps and small elements + are preserved. + + \p extraElements is the exact number of spare element entries. + + The usual multipliers, #extraMajor_ and #extraGap_, are set to zero. + */ + CoinPackedMatrix(const CoinPackedMatrix &m, + int extraForMajor, int extraElements, + bool reverseOrdering = false); + + /** Subset constructor (without gaps). Duplicates are allowed + and order is as given */ + CoinPackedMatrix(const CoinPackedMatrix &wholeModel, + int numberRows, const int *whichRows, + int numberColumns, const int *whichColumns); + + /// Destructor + virtual ~CoinPackedMatrix(); + //@} + + /*! \name Debug Utilities */ + //@{ + /*! \brief Scan the matrix for anomalies. + + Returns the number of anomalies. Scans the structure for gaps, + obviously bogus indices and coefficients, and inconsistencies. Gaps + are not an error unless #hasGaps() says the matrix should be + gap-free. Zeroes are not an error unless \p zeroesAreError is set to + true. + + Values for verbosity are: + - 0: No messages, just the return value + - 1: Messages about errors + - 2: If there are no errors, a message indicating the matrix was + checked is printed (positive confirmation). + - 3: Adds a bit more information about the matrix. + - 4: Prints warnings about zeroes even if they're not considered + errors. + + Obviously bogus coefficients are coefficients that are NaN or have + absolute value greater than 1e50. Zeros have absolute value less + than 1e-50. + */ + int verifyMtx(int verbosity = 1, bool zeroesAreError = false) const; + //@} + + //-------------------------------------------------------------------------- +protected: + void gutsOfDestructor(); + void gutsOfCopyOf(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double *elem, const int *ind, + const CoinBigIndex *start, const int *len, + const double extraMajor = 0.0, const double extraGap = 0.0); + /// When no gaps we can do faster + void gutsOfCopyOfNoGaps(const bool colordered, + const int minor, const int major, + const double *elem, const int *ind, + const CoinBigIndex *start); + void gutsOfOpEqual(const bool colordered, + const int minor, const int major, const CoinBigIndex numels, + const double *elem, const int *ind, + const CoinBigIndex *start, const int *len); + void resizeForAddingMajorVectors(const int numVec, const int *lengthVec); + void resizeForAddingMinorVectors(const int *addedEntries); + + /*! \brief Append a set of rows (columns) to the end of a row (colum) + ordered matrix. + + If \p numberOther > 0 the method will check if any of the new rows + (columns) contain duplicate indices or invalid indices and return the + number of errors. A valid minor index must satisfy + \code 0 <= k < numberOther \endcode + If \p numberOther < 0 no checking is performed. + */ + int appendMajor(const int number, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); + /*! \brief Append a set of rows (columns) to the end of a column (row) + ordered matrix. + + If \p numberOther > 0 the method will check if any of the new rows + (columns) contain duplicate indices or indices outside the current + range for the major dimension and return the number of violations. + If \p numberOther <= 0 the major dimension will be expanded as + necessary and there are no checks for duplicate indices. + */ + int appendMinor(const int number, + const CoinBigIndex *starts, const int *index, + const double *element, int numberOther = -1); + +private: + inline CoinBigIndex getLastStart() const + { + return majorDim_ == 0 ? 0 : start_[majorDim_]; + } + + //-------------------------------------------------------------------------- +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /** A flag indicating whether the matrix is column or row major ordered. */ + bool colOrdered_; + /** This much times more space should be allocated for each major-dimension + vector (with respect to the number of entries in the vector) when the + matrix is resized. The purpose of these gaps is to allow fast insertion + of new minor-dimension vectors. */ + double extraGap_; + /** his much times more space should be allocated for major-dimension + vectors when the matrix is resized. The purpose of these gaps is to + allow fast addition of new major-dimension vectors. */ + double extraMajor_; + + /** List of nonzero element values. The entries in the gaps between + major-dimension vectors are undefined. */ + double *element_; + /** List of nonzero element minor-dimension indices. The entries in the gaps + between major-dimension vectors are undefined. */ + int *index_; + /** Starting positions of major-dimension vectors. */ + CoinBigIndex *start_; + /** Lengths of major-dimension vectors. */ + int *length_; + + /// number of vectors in matrix + int majorDim_; + /// size of other dimension + int minorDim_; + /// the number of nonzero entries + CoinBigIndex size_; + + /// max space allocated for major-dimension + int maxMajorDim_; + /// max space allocated for entries + CoinBigIndex maxSize_; + //@} +}; + +//############################################################################# +/*! \brief Test the methods in the CoinPackedMatrix class. + + The only reason for it not to be a member method is that this way + it doesn't have to be compiled into the library. And that's a gain, + because the library should be compiled with optimization on, but this + method should be compiled with debugging. +*/ +void CoinPackedMatrixUnitTest(); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVector.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVector.hpp new file mode 100644 index 000000000..ba4ce8b19 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVector.hpp @@ -0,0 +1,670 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedVector_H +#define CoinPackedVector_H + +#include + +#include "CoinPragma.hpp" +#include "CoinPackedVectorBase.hpp" +#include "CoinSort.hpp" + +#ifdef COIN_FAST_CODE +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_NOTEST_DUPLICATE +#endif +#endif + +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE true +#else +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE false +#endif +/** Sparse Vector + +Stores vector of indices and associated element values. +Supports sorting of vector while maintaining the original indices. + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 } + double el[ne] = { 10., 40., 1., 50. } + + // Create vector and set its value + CoinPackedVector r(ne,inx,el); + + // access each index and element + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access original position of index + assert( r.originalPosition()[0]==0 ); + assert( r.originalPosition()[1]==1 ); + assert( r.originalPosition()[2]==2 ); + assert( r.originalPosition()[3]==3 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // sort Elements in increasing order + r.sortIncrElement(); + + // access each index and element + assert( r.indices ()[0]== 0 ); + assert( r.elements()[0]== 1. ); + assert( r.indices ()[1]== 1 ); + assert( r.elements()[1]==10. ); + assert( r.indices ()[2]== 4 ); + assert( r.elements()[2]==40. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access original position of index + assert( r.originalPosition()[0]==2 ); + assert( r.originalPosition()[1]==0 ); + assert( r.originalPosition()[2]==1 ); + assert( r.originalPosition()[3]==3 ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Restore orignal sort order + r.sortOriginalOrder(); + + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // Tests for equality and equivalence + CoinPackedVector r1; + r1=r; + assert( r==r1 ); + assert( r.equivalent(r1) ); + r.sortIncrElement(); + assert( r!=r1 ); + assert( r.equivalent(r1) ); + + // Add packed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinPackedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinPackedVector : public CoinPackedVectorBase { + friend void CoinPackedVectorUnitTest(); + +public: + /**@name Get methods. */ + //@{ + /// Get the size + virtual int getNumElements() const { return nElements_; } + /// Get indices of elements + virtual const int *getIndices() const { return indices_; } + /// Get element values + virtual const double *getElements() const { return elements_; } + /// Get indices of elements + int *getIndices() { return indices_; } + /// Get the size + inline int getVectorNumElements() const { return nElements_; } + /// Get indices of elements + inline const int *getVectorIndices() const { return indices_; } + /// Get element values + inline const double *getVectorElements() const { return elements_; } + /// Get element values + double *getElements() { return elements_; } + /** Get pointer to int * vector of original postions. + If the packed vector has not been sorted then this + function returns the vector: 0, 1, 2, ..., size()-1. */ + const int *getOriginalPosition() const { return origIndices_; } + //@} + + //------------------------------------------------------------------- + // Set indices and elements + //------------------------------------------------------------------- + /**@name Set methods */ + //@{ + /// Reset the vector (as if were just created an empty vector) + void clear(); + /** Assignment operator.
+ NOTE: This operator keeps the current + testForDuplicateIndex setting, and affter copying the data + it acts accordingly. */ + CoinPackedVector &operator=(const CoinPackedVector &); + /** Assignment operator from a CoinPackedVectorBase.
+ NOTE: This operator keeps the current + testForDuplicateIndex setting, and affter copying the data + it acts accordingly. */ + CoinPackedVector &operator=(const CoinPackedVectorBase &rhs); + + /** Assign the ownership of the arguments to this vector. + Size is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. The last argument indicates whether this vector will have + to be tested for duplicate indices. + */ + void assignVector(int size, int *&inds, double *&elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Set vector size, indices, and elements. + Size is the length of both the indices and elements vectors. + The indices and elements vectors are copied into this class instance's + member data. The last argument specifies whether this vector will have + to be checked for duplicate indices whenever that can happen. */ + void setVector(int size, const int *inds, const double *elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Elements set to have the same scalar value */ + void setConstant(int size, const int *inds, double elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Indices are not specified and are taken to be 0,1,...,size-1 */ + void setFull(int size, const double *elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Indices are not specified and are taken to be 0,1,...,size-1, + but only where non zero*/ + void setFullNonZero(int size, const double *elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + + /** Set an existing element in the packed vector + The first argument is the "index" into the elements() array + */ + void setElement(int index, double element); + + /// Insert an element into the vector + void insert(int index, double element); + /// Append a CoinPackedVector to the end + void append(const CoinPackedVectorBase &caboose); + + /// Swap values in positions i and j of indices and elements + void swap(int i, int j); + + /** Resize the packed vector to be the first newSize elements. + Problem with truncate: what happens with origIndices_ ??? */ + void truncate(int newSize); + //@} + + /**@name Arithmetic operators. */ + //@{ + /// add value to every entry + void operator+=(double value); + /// subtract value from every entry + void operator-=(double value); + /// multiply every entry by value + void operator*=(double value); + /// divide every entry by value + void operator/=(double value); + //@} + + /**@name Sorting */ + //@{ + /** Sort the packed storage vector. + Typcical usages: +
 
+       packedVector.sort(CoinIncrIndexOrdered());   //increasing indices
+       packedVector.sort(CoinIncrElementOrdered()); // increasing elements
+       
+ */ + template < class CoinCompare3 > + void sort(const CoinCompare3 &tc) + { + CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + tc); + } + + void sortIncrIndex() + { + CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + CoinFirstLess_3< int, int, double >()); + } + + void sortDecrIndex() + { + CoinSort_3(indices_, indices_ + nElements_, origIndices_, elements_, + CoinFirstGreater_3< int, int, double >()); + } + + void sortIncrElement() + { + CoinSort_3(elements_, elements_ + nElements_, origIndices_, indices_, + CoinFirstLess_3< double, int, int >()); + } + + void sortDecrElement() + { + CoinSort_3(elements_, elements_ + nElements_, origIndices_, indices_, + CoinFirstGreater_3< double, int, int >()); + } + + /** Sort in original order. + If the vector has been sorted, then this method restores + to its orignal sort order. + */ + void sortOriginalOrder(); + //@} + + /**@name Memory usage */ + //@{ + /** Reserve space. + If one knows the eventual size of the packed vector, + then it may be more efficient to reserve the space. + */ + void reserve(int n); + /** capacity returns the size which could be accomodated without + having to reallocate storage. + */ + int capacity() const { return capacity_; } + //@} + /**@name Constructors and destructors */ + //@{ + /** Default constructor */ + CoinPackedVector(bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** \brief Alternate Constructors - set elements to vector of doubles + + This constructor copies the vectors provided as parameters. + */ + CoinPackedVector(int size, const int *inds, const double *elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** \brief Alternate Constructors - set elements to vector of doubles + + This constructor takes ownership of the vectors passed as parameters. + \p inds and \p elems will be NULL on return. + */ + CoinPackedVector(int capacity, int size, int *&inds, double *&elems, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Alternate Constructors - set elements to same scalar value */ + CoinPackedVector(int size, const int *inds, double element, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Alternate Constructors - construct full storage with indices 0 through + size-1. */ + CoinPackedVector(int size, const double *elements, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /** Copy constructor. */ + CoinPackedVector(const CoinPackedVector &); + /** Copy constructor from a PackedVectorBase. */ + CoinPackedVector(const CoinPackedVectorBase &rhs); + /** Destructor */ + virtual ~CoinPackedVector(); + //@} + +private: + /**@name Private methods */ + //@{ + /// Copy internal date + void gutsOfSetVector(int size, + const int *inds, const double *elems, + bool testForDuplicateIndex, + const char *method); + /// + void gutsOfSetConstant(int size, + const int *inds, double value, + bool testForDuplicateIndex, + const char *method); + //@} + +private: + /**@name Private member data */ + //@{ + /// Vector indices + int *indices_; + ///Vector elements + double *elements_; + /// Size of indices and elements vectors + int nElements_; + /// original unsorted indices + int *origIndices_; + /// Amount of memory allocated for indices_, origIndices_, and elements_. + int capacity_; + //@} +}; + +//############################################################################# + +/**@name Arithmetic operators on packed vectors. + + NOTE: These methods operate on those positions where at + least one of the arguments has a value listed. At those positions the + appropriate operation is executed, Otherwise the result of the operation is + considered 0.
+ NOTE 2: There are two kind of operators here. One is used + like "c = binaryOp(a, b)", the other is used like "binaryOp(c, a, b)", but + they are really the same. The first is much more natural to use, but it + involves the creation of a temporary object (the function *must* return an + object), while the second form puts the result directly into the argument + "c". Therefore, depending on the circumstances, the second form can be + significantly faster. + */ +//@{ +template < class BinaryFunction > +void binaryOp(CoinPackedVector &retVal, + const CoinPackedVectorBase &op1, double value, + BinaryFunction bf) +{ + retVal.clear(); + const int s = op1.getNumElements(); + if (s > 0) { + retVal.reserve(s); + const int *inds = op1.getIndices(); + const double *elems = op1.getElements(); + for (int i = 0; i < s; ++i) { + retVal.insert(inds[i], bf(value, elems[i])); + } + } +} + +template < class BinaryFunction > +inline void +binaryOp(CoinPackedVector &retVal, + double value, const CoinPackedVectorBase &op2, + BinaryFunction bf) +{ + binaryOp(retVal, op2, value, bf); +} + +template < class BinaryFunction > +void binaryOp(CoinPackedVector &retVal, + const CoinPackedVectorBase &op1, const CoinPackedVectorBase &op2, + BinaryFunction bf) +{ + retVal.clear(); + const int s1 = op1.getNumElements(); + const int s2 = op2.getNumElements(); + /* + Replaced || with &&, in response to complaint from Sven deVries, who + rightly points out || is not appropriate for additive operations. && + should be ok as long as binaryOp is understood not to create something + from nothing. -- lh, 04.06.11 +*/ + if (s1 == 0 && s2 == 0) + return; + + retVal.reserve(s1 + s2); + + const int *inds1 = op1.getIndices(); + const double *elems1 = op1.getElements(); + const int *inds2 = op2.getIndices(); + const double *elems2 = op2.getElements(); + + int i; + // loop once for each element in op1 + for (i = 0; i < s1; ++i) { + const int index = inds1[i]; + const int pos2 = op2.findIndex(index); + const double val = bf(elems1[i], pos2 == -1 ? 0.0 : elems2[pos2]); + // if (val != 0.0) // *THINK* : should we put in only nonzeros? + retVal.insert(index, val); + } + // loop once for each element in operand2 + for (i = 0; i < s2; ++i) { + const int index = inds2[i]; + // if index exists in op1, then element was processed in prior loop + if (op1.isExistingIndex(index)) + continue; + // Index does not exist in op1, so the element value must be zero + const double val = bf(0.0, elems2[i]); + // if (val != 0.0) // *THINK* : should we put in only nonzeros? + retVal.insert(index, val); + } +} + +//----------------------------------------------------------------------------- + +template < class BinaryFunction > +CoinPackedVector +binaryOp(const CoinPackedVectorBase &op1, double value, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, value, bf); + return retVal; +} + +template < class BinaryFunction > +CoinPackedVector +binaryOp(double value, const CoinPackedVectorBase &op2, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op2, value, bf); + return retVal; +} + +template < class BinaryFunction > +CoinPackedVector +binaryOp(const CoinPackedVectorBase &op1, const CoinPackedVectorBase &op2, + BinaryFunction bf) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, bf); + return retVal; +} + +//----------------------------------------------------------------------------- +/// Return the sum of two packed vectors +inline CoinPackedVector operator+(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::plus< double >()); + return retVal; +} + +/// Return the difference of two packed vectors +inline CoinPackedVector operator-(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::minus< double >()); + return retVal; +} + +/// Return the element-wise product of two packed vectors +inline CoinPackedVector operator*(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::multiplies< double >()); + return retVal; +} + +/// Return the element-wise ratio of two packed vectors +inline CoinPackedVector operator/(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + CoinPackedVector retVal; + retVal.setTestForDuplicateIndex(true); + binaryOp(retVal, op1, op2, std::divides< double >()); + return retVal; +} +//@} + +/// Returns the dot product of two CoinPackedVector objects whose elements are +/// doubles. Use this version if the vectors are *not* guaranteed to be sorted. +inline double sparseDotProduct(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + int len, i; + double acc = 0.0; + CoinPackedVector retVal; + + CoinPackedVector retval = op1 * op2; + len = retval.getNumElements(); + double *CParray = retval.getElements(); + + for (i = 0; i < len; i++) { + acc += CParray[i]; + } + return acc; +} + +/// Returns the dot product of two sorted CoinPackedVector objects. +/// The vectors should be sorted in ascending order of indices. +inline double sortedSparseDotProduct(const CoinPackedVectorBase &op1, + const CoinPackedVectorBase &op2) +{ + int i, j, len1, len2; + double acc = 0.0; + + const double *v1val = op1.getElements(); + const double *v2val = op2.getElements(); + const int *v1ind = op1.getIndices(); + const int *v2ind = op2.getIndices(); + + len1 = op1.getNumElements(); + len2 = op2.getNumElements(); + + i = 0; + j = 0; + + while (i < len1 && j < len2) { + if (v1ind[i] == v2ind[j]) { + acc += v1val[i] * v2val[j]; + i++; + j++; + } else if (v2ind[j] < v1ind[i]) { + j++; + } else { + i++; + } // end if-else-elseif + } // end while + return acc; +} + +//----------------------------------------------------------------------------- + +/**@name Arithmetic operators on packed vector and a constant.
+ These functions create a packed vector as a result. That packed vector will + have the same indices as op1 and the specified operation is + done entry-wise with the given value. */ +//@{ +/// Return the sum of a packed vector and a constant +inline CoinPackedVector +operator+(const CoinPackedVectorBase &op1, double value) +{ + CoinPackedVector retVal(op1); + retVal += value; + return retVal; +} + +/// Return the difference of a packed vector and a constant +inline CoinPackedVector +operator-(const CoinPackedVectorBase &op1, double value) +{ + CoinPackedVector retVal(op1); + retVal -= value; + return retVal; +} + +/// Return the element-wise product of a packed vector and a constant +inline CoinPackedVector +operator*(const CoinPackedVectorBase &op1, double value) +{ + CoinPackedVector retVal(op1); + retVal *= value; + return retVal; +} + +/// Return the element-wise ratio of a packed vector and a constant +inline CoinPackedVector +operator/(const CoinPackedVectorBase &op1, double value) +{ + CoinPackedVector retVal(op1); + retVal /= value; + return retVal; +} + +//----------------------------------------------------------------------------- + +/// Return the sum of a constant and a packed vector +inline CoinPackedVector +operator+(double value, const CoinPackedVectorBase &op1) +{ + CoinPackedVector retVal(op1); + retVal += value; + return retVal; +} + +/// Return the difference of a constant and a packed vector +inline CoinPackedVector +operator-(double value, const CoinPackedVectorBase &op1) +{ + CoinPackedVector retVal(op1); + const int size = retVal.getNumElements(); + double *elems = retVal.getElements(); + for (int i = 0; i < size; ++i) { + elems[i] = value - elems[i]; + } + return retVal; +} + +/// Return the element-wise product of a constant and a packed vector +inline CoinPackedVector +operator*(double value, const CoinPackedVectorBase &op1) +{ + CoinPackedVector retVal(op1); + retVal *= value; + return retVal; +} + +/// Return the element-wise ratio of a a constant and packed vector +inline CoinPackedVector +operator/(double value, const CoinPackedVectorBase &op1) +{ + CoinPackedVector retVal(op1); + const int size = retVal.getNumElements(); + double *elems = retVal.getElements(); + for (int i = 0; i < size; ++i) { + elems[i] = value / elems[i]; + } + return retVal; +} +//@} + +//############################################################################# +/** A function that tests the methods in the CoinPackedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CoinPackedVectorUnitTest(); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVectorBase.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVectorBase.hpp new file mode 100644 index 000000000..a68d6b671 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPackedVectorBase.hpp @@ -0,0 +1,274 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPackedVectorBase_H +#define CoinPackedVectorBase_H + +#include +#include +#include "CoinPragma.hpp" +#include "CoinError.hpp" + +class CoinPackedVector; + +/** Abstract base class for various sparse vectors. + + Since this class is abstract, no object of this type can be created. The + sole purpose of this class is to provide access to a constant + packed vector. All members of this class are const methods, they can't + change the object. */ + +class CoinPackedVectorBase { + +public: + /**@name Virtual methods that the derived classes must provide */ + //@{ + /// Get length of indices and elements vectors + virtual int getNumElements() const = 0; + /// Get indices of elements + virtual const int *getIndices() const = 0; + /// Get element values + virtual const double *getElements() const = 0; + //@} + + /**@name Methods related to whether duplicate-index checking is performed. + + If the checking for duplicate indices is turned off, then + some CoinPackedVector methods may not work correctly if there + are duplicate indices. + Turning off the checking for duplicate indices may result in + better run time performance. + */ + //@{ + /** \brief Set to the argument value whether to test for duplicate indices + in the vector whenever they can occur. + + Calling this method with \p test set to true will trigger an immediate + check for duplicate indices. + */ + void setTestForDuplicateIndex(bool test) const; + /** \brief Set to the argument value whether to test for duplicate indices + in the vector whenever they can occur BUT we know that right + now the vector has no duplicate indices. + + Calling this method with \p test set to true will not trigger + an immediate check for duplicate indices; instead, it's assumed that + the result of the test will be true. + */ + void setTestForDuplicateIndexWhenTrue(bool test) const; + /** Returns true if the vector should be tested for duplicate indices when + they can occur. */ + bool testForDuplicateIndex() const { return testForDuplicateIndex_; } + /// Just sets test stuff false without a try etc + inline void setTestsOff() const + { + testForDuplicateIndex_ = false; + testedDuplicateIndex_ = false; + } + //@} + + /**@name Methods for getting info on the packed vector as a full vector */ + //@{ + /** Get the vector as a dense vector. The argument specifies how long this + dense vector is.
+ NOTE: The user needs to delete[] this + pointer after it's not needed anymore. + */ + double *denseVector(int denseSize) const; + /** Access the i'th element of the full storage vector. + If the i'th is not stored, then zero is returned. The initial use of + this method has some computational and storage overhead associated with + it.
+ NOTE: This is very expensive. It is probably + much better to use denseVector(). + */ + double operator[](int i) const; + //@} + + /**@name Index methods */ + //@{ + /// Get value of maximum index + int getMaxIndex() const; + /// Get value of minimum index + int getMinIndex() const; + + /// Throw an exception if there are duplicate indices + void duplicateIndex(const char *methodName = NULL, + const char *className = NULL) const; + + /** Return true if the i'th element of the full storage vector exists in + the packed storage vector.*/ + bool isExistingIndex(int i) const; + + /** Return the position of the i'th element of the full storage vector. + If index does not exist then -1 is returned */ + int findIndex(int i) const; + + //@} + + /**@name Comparison operators on two packed vectors */ + //@{ + /** Equal. Returns true if vectors have same length and corresponding + element of each vector is equal. */ + bool operator==(const CoinPackedVectorBase &rhs) const; + /// Not equal + bool operator!=(const CoinPackedVectorBase &rhs) const; + +#if 0 + // LL: This should be implemented eventually. It is useful to have. + /** Lexicographic comparisons of two packed vectors. Returns + negative/0/positive depending on whether \c this is + smaller/equal.greater than \c rhs */ + int lexCompare(const CoinPackedVectorBase& rhs); +#endif + + /** This method establishes an ordering on packed vectors. It is complete + ordering, but not the same as lexicographic ordering. However, it is + quick and dirty to compute and thus it is useful to keep packed vectors + in a heap when all we care is to quickly check whether a particular + vector is already in the heap or not. Returns negative/0/positive + depending on whether \c this is smaller/equal.greater than \c rhs. */ + int compare(const CoinPackedVectorBase &rhs) const; + + /** equivalent - If shallow packed vector A & B are equivalent, then they + are still equivalent no matter how they are sorted. + In this method the FloatEqual function operator can be specified. The + default equivalence test is that the entries are relatively equal.
+ NOTE: This is a relatively expensive method as it + sorts the two shallow packed vectors. + */ + template < class FloatEqual > + bool + isEquivalent(const CoinPackedVectorBase &rhs, const FloatEqual &eq) const + { + if (getNumElements() != rhs.getNumElements()) + return false; + + duplicateIndex("equivalent", "CoinPackedVector"); + rhs.duplicateIndex("equivalent", "CoinPackedVector"); + + std::map< int, double > mv; + const int *inds = getIndices(); + const double *elems = getElements(); + int i; + for (i = getNumElements() - 1; i >= 0; --i) { + mv.insert(std::make_pair(inds[i], elems[i])); + } + + std::map< int, double > mvRhs; + inds = rhs.getIndices(); + elems = rhs.getElements(); + for (i = getNumElements() - 1; i >= 0; --i) { + mvRhs.insert(std::make_pair(inds[i], elems[i])); + } + + std::map< int, double >::const_iterator mvI = mv.begin(); + std::map< int, double >::const_iterator mvIlast = mv.end(); + std::map< int, double >::const_iterator mvIrhs = mvRhs.begin(); + while (mvI != mvIlast) { + if (mvI->first != mvIrhs->first || !eq(mvI->second, mvIrhs->second)) + return false; + ++mvI; + ++mvIrhs; + } + return true; + } + + bool isEquivalent(const CoinPackedVectorBase &rhs) const; + //@} + + /**@name Arithmetic operators. */ + //@{ + /// Create the dot product with a full vector + double dotProduct(const double *dense) const; + + /// Return the 1-norm of the vector + double oneNorm() const; + + /// Return the square of the 2-norm of the vector + double normSquare() const; + + /// Return the 2-norm of the vector + double twoNorm() const; + + /// Return the infinity-norm of the vector + double infNorm() const; + + /// Sum elements of vector. + double sum() const; + //@} + +protected: + /**@name Constructors, destructor + NOTE: All constructors are protected. There's no need + to expose them, after all, this is an abstract class. */ + //@{ + /** Default constructor. */ + CoinPackedVectorBase(); + +public: + /** Destructor */ + virtual ~CoinPackedVectorBase(); + //@} + +private: + /**@name Disabled methods */ + //@{ + /** The copy constructor.
+ This must be at least protected, but we make it private. The reason is + that when, say, a shallow packed vector is created, first the + underlying class, it this one is constructed. However, at that point we + don't know how much of the data members of this class we need to copy + over. Therefore the copy constructor is not used. */ + CoinPackedVectorBase(const CoinPackedVectorBase &); + /** This class provides const access to packed vectors, so there's + no need to provide an assignment operator. */ + CoinPackedVectorBase &operator=(const CoinPackedVectorBase &); + //@} + +protected: + /**@name Protected methods */ + //@{ + /// Find Maximum and Minimum Indices + void findMaxMinIndices() const; + + /// Return indexSetPtr_ (create it if necessary). + std::set< int > *indexSet(const char *methodName = NULL, + const char *className = NULL) const; + + /// Delete the indexSet + void clearIndexSet() const; + void clearBase() const; + void copyMaxMinIndex(const CoinPackedVectorBase &x) const + { + maxIndex_ = x.maxIndex_; + minIndex_ = x.minIndex_; + } + //@} + +private: + /**@name Protected member data */ + //@{ + /// Contains max index value or -infinity + mutable int maxIndex_; + /// Contains minimum index value or infinity + mutable int minIndex_; + /** Store the indices in a set. This set is only created if it is needed. + Its primary use is testing for duplicate indices. + */ + mutable std::set< int > *indexSetPtr_; + /** True if the vector should be tested for duplicate indices when they can + occur. */ + mutable bool testForDuplicateIndex_; + /** True if the vector has already been tested for duplicate indices. Most + of the operations in CoinPackedVector preserves this flag. */ + mutable bool testedDuplicateIndex_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinParam.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinParam.hpp new file mode 100644 index 000000000..718b4eafe --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinParam.hpp @@ -0,0 +1,644 @@ +/* $Id$ */ +#ifndef CoinParam_H +#define CoinParam_H + +/* + Copyright (C) 2002, International Business Machines + Corporation and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ + +/*! \file CoinParam.hpp + \brief Declaration of a class for command line parameters. +*/ + +#include +#include +#include + +/*! \class CoinParam + \brief A base class for `keyword value' command line parameters. + + The underlying paradigm is that a parameter specifies an action to be + performed on a target object. The base class provides two function + pointers, a `push' function and a `pull' function. By convention, a push + function will set some value in the target object or perform some action + using the target object. A `pull' function will retrieve some value from + the target object. This is only a convention, however; CoinParam and + associated utilities make no use of these functions and have no hardcoded + notion of how they should be used. + + The action to be performed, and the target object, will be specific to a + particular application. It is expected that users will derive + application-specific parameter classes from this base class. A derived + class will typically add fields and methods to set/get a code for the + action to be performed (often, an enum class) and the target object (often, + a pointer or reference). + + Facilities provided by the base class and associated utility routines + include: +
    +
  • Support for common parameter types with numeric, string, or + keyword values. +
  • Support for short and long help messages. +
  • Pointers to `push' and `pull' functions as described above. +
  • Command line parsing and keyword matching. +
+ All utility routines are declared in the #CoinParamUtils namespace. + + The base class recognises five types of parameters: actions (which require + no value); numeric parameters with integer or real (double) values; keyword + parameters, where the value is one of a defined set of value-keywords; + and string parameters (where the value is a string). + The base class supports the definition of a valid range, a default value, + and short and long help messages for a parameter. + + As defined by the #CoinParamFunc typedef, push and pull functions + should take a single parameter, a pointer to a CoinParam. Typically this + object will actually be a derived class as described above, and the + implementation function will have access to all capabilities of CoinParam and + of the derived class. + + When specified as command line parameters, the expected syntax is `-keyword + value' or `-keyword=value'. You can also use the Gnu double-dash style, + `--keyword'. Spaces around the `=' will \e not work. + + The keyword (name) for a parameter can be defined with an `!' to mark the + minimal match point. For example, allow!ableGap will be considered matched + by the strings `allow', `allowa', `allowab', \e etc. Similarly, the + value-keyword strings for keyword parameters can be defined with `!' to + mark the minimal match point. Matching of keywords and value-keywords is + \e not case sensitive. +*/ + +class CoinParam { + +public: + /*! \name Subtypes */ + //@{ + + /*! \brief Enumeration for the types of parameters supported by CoinParam + + CoinParam provides support for several types of parameters: +
    +
  • Action parameters, which require no value. +
  • Integer and double numeric parameters, with upper and lower bounds. +
  • String parameters that take an arbitrary string value. +
  • Keyword parameters that take a defined set of string (value-keyword) + values. Value-keywords are associated with integers in the order in + which they are added, starting from zero. +
+ */ + typedef enum { coinParamInvalid = 0, + coinParamAct, + coinParamInt, + coinParamDbl, + coinParamStr, + coinParamKwd } CoinParamType; + + /*! \brief Type declaration for push and pull functions. + + By convention, a return code of 0 indicates execution without error, >0 + indicates nonfatal error, and <0 indicates fatal error. This is only + convention, however; the base class makes no use of the push and pull + functions and has no hardcoded interpretation of the return code. + */ + typedef int (*CoinParamFunc)(CoinParam *param); + + //@} + + /*! \name Constructors and Destructors + + Be careful how you specify parameters for the constructors! Some compilers + are entirely too willing to convert almost anything to bool. +*/ + //@{ + + /*! \brief Default constructor */ + + CoinParam(); + + /*! \brief Constructor for a parameter with a double value + + The default value is 0.0. Be careful to clearly indicate that \p lower and + \p upper are real (double) values to distinguish this constructor from the + constructor for an integer parameter. + */ + CoinParam(std::string name, std::string help, + double lower, double upper, double dflt = 0.0, + bool display = true); + + /*! \brief Constructor for a parameter with an integer value + + The default value is 0. + */ + CoinParam(std::string name, std::string help, + int lower, int upper, int dflt = 0, + bool display = true); + + /*! \brief Constructor for a parameter with keyword values + + The string supplied as \p firstValue becomes the first value-keyword. + Additional value-keywords can be added using appendKwd(). It's necessary + to specify both the first value-keyword (\p firstValue) and the default + value-keyword index (\p dflt) in order to distinguish this constructor + from the constructors for string and action parameters. + + Value-keywords are associated with an integer, starting with zero and + increasing as each keyword is added. The value-keyword given as \p + firstValue will be associated with the integer zero. The integer supplied + for \p dflt can be any value, as long as it will be valid once all + value-keywords have been added. + */ + CoinParam(std::string name, std::string help, + std::string firstValue, int dflt, bool display = true); + + /*! \brief Constructor for a string parameter + + For some compilers, the default value (\p dflt) must be specified + explicitly with type std::string to distinguish the constructor for a + string parameter from the constructor for an action parameter. For + example, use std::string("default") instead of simply "default", or use a + variable of type std::string. + */ + CoinParam(std::string name, std::string help, + std::string dflt, bool display = true); + + /*! \brief Constructor for an action parameter */ + + CoinParam(std::string name, std::string help, + bool display = true); + + /*! \brief Copy constructor */ + + CoinParam(const CoinParam &orig); + + /*! \brief Clone */ + + virtual CoinParam *clone(); + + /*! \brief Assignment */ + + CoinParam &operator=(const CoinParam &rhs); + + /*! \brief Destructor */ + + virtual ~CoinParam(); + + //@} + + /*! \name Methods to query and manipulate the value(s) of a parameter */ + //@{ + + /*! \brief Add an additional value-keyword to a keyword parameter */ + + void appendKwd(std::string kwd); + + /*! \brief Return the integer associated with the specified value-keyword + + Returns -1 if no value-keywords match the specified string. + */ + int kwdIndex(std::string kwd) const; + + /*! \brief Return the value-keyword that is the current value of the + keyword parameter + */ + std::string kwdVal() const; + + /*! \brief Set the value of the keyword parameter using the integer + associated with a value-keyword. + + If \p printIt is true, the corresponding value-keyword string will be + echoed to std::cout. + */ + void setKwdVal(int value, bool printIt = false); + + /*! \brief Set the value of the keyword parameter using a value-keyword + string. + + The given string will be tested against the set of value-keywords for + the parameter using the shortest match rules. + */ + void setKwdVal(const std::string value); + + /*! \brief Prints the set of value-keywords defined for this keyword + parameter + */ + void printKwds() const; + + /*! \brief Set the value of a string parameter */ + + void setStrVal(std::string value); + + /*! \brief Get the value of a string parameter */ + + std::string strVal() const; + + /*! \brief Set the value of a double parameter */ + + void setDblVal(double value); + + /*! \brief Get the value of a double parameter */ + + double dblVal() const; + + /*! \brief Set the value of a integer parameter */ + + void setIntVal(int value); + + /*! \brief Get the value of a integer parameter */ + + int intVal() const; + + /*! \brief Add a short help string to a parameter */ + + inline void setShortHelp(const std::string help) { shortHelp_ = help; } + + /*! \brief Retrieve the short help string */ + + inline std::string shortHelp() const { return (shortHelp_); } + + /*! \brief Add a long help message to a parameter + + See printLongHelp() for a description of how messages are broken into + lines. + */ + inline void setLongHelp(const std::string help) { longHelp_ = help; } + + /*! \brief Retrieve the long help message */ + + inline std::string longHelp() const { return (longHelp_); } + + /*! \brief Print long help + + Prints the long help string, plus the valid range and/or keywords if + appropriate. The routine makes a best effort to break the message into + lines appropriate for an 80-character line. Explicit line breaks in the + message will be observed. The short help string will be used if + long help is not available. + */ + void printLongHelp() const; + + //@} + + /*! \name Methods to query and manipulate a parameter object */ + //@{ + + /*! \brief Return the type of the parameter */ + + inline CoinParamType type() const { return (type_); } + + /*! \brief Set the type of the parameter */ + + inline void setType(CoinParamType type) { type_ = type; } + + /*! \brief Return the parameter keyword (name) string */ + + inline std::string name() const { return (name_); } + + /*! \brief Set the parameter keyword (name) string */ + + inline void setName(std::string name) + { + name_ = name; + processName(); + } + + /*! \brief Check if the specified string matches the parameter keyword (name) + string + + Returns 1 if the string matches and meets the minimum match length, + 2 if the string matches but doesn't meet the minimum match length, + and 0 if the string doesn't match. Matches are \e not case-sensitive. + */ + int matches(std::string input) const; + + /*! \brief Return the parameter keyword (name) string formatted to show + the minimum match length + + For example, if the parameter name was defined as allow!ableGap, the + string returned by matchName would be allow(ableGap). + */ + std::string matchName() const; + + /*! \brief Set visibility of parameter + + Intended to control whether the parameter is shown when a list of + parameters is processed. Used by CoinParamUtils::printHelp when printing + help messages for a list of parameters. + */ + inline void setDisplay(bool display) { display_ = display; } + + /*! \brief Get visibility of parameter */ + + inline bool display() const { return (display_); } + + /*! \brief Get push function */ + + inline CoinParamFunc pushFunc() { return (pushFunc_); } + + /*! \brief Set push function */ + + inline void setPushFunc(CoinParamFunc func) { pushFunc_ = func; } + + /*! \brief Get pull function */ + + inline CoinParamFunc pullFunc() { return (pullFunc_); } + + /*! \brief Set pull function */ + + inline void setPullFunc(CoinParamFunc func) { pullFunc_ = func; } + + //@} + +private: + /*! \name Private methods */ + //@{ + + /*! Process a name for efficient matching */ + void processName(); + + //@} + + /*! \name Private parameter data */ + //@{ + /// Parameter type (see #CoinParamType) + CoinParamType type_; + + /// Parameter name + std::string name_; + + /// Length of parameter name + size_t lengthName_; + + /*! \brief Minimum length required to declare a match for the parameter + name. + */ + size_t lengthMatch_; + + /// Lower bound on value for a double parameter + double lowerDblValue_; + + /// Upper bound on value for a double parameter + double upperDblValue_; + + /// Double parameter - current value + double dblValue_; + + /// Lower bound on value for an integer parameter + int lowerIntValue_; + + /// Upper bound on value for an integer parameter + int upperIntValue_; + + /// Integer parameter - current value + int intValue_; + + /// String parameter - current value + std::string strValue_; + + /// Set of valid value-keywords for a keyword parameter + std::vector< std::string > definedKwds_; + + /*! \brief Current value for a keyword parameter (index into #definedKwds_) + */ + int currentKwd_; + + /// Push function + CoinParamFunc pushFunc_; + + /// Pull function + CoinParamFunc pullFunc_; + + /// Short help + std::string shortHelp_; + + /// Long help + std::string longHelp_; + + /// Display when processing lists of parameters? + bool display_; + //@} +}; + +/*! \relatesalso CoinParam + \brief A type for a parameter vector. +*/ +typedef std::vector< CoinParam * > CoinParamVec; + +/*! \relatesalso CoinParam + \brief A stream output function for a CoinParam object. +*/ +std::ostream &operator<<(std::ostream &s, const CoinParam ¶m); + +/* + Bring in the utility functions for parameter handling (CbcParamUtils). +*/ + +/*! \brief Utility functions for processing CoinParam parameters. + + The functions in CoinParamUtils support command line or interactive + parameter processing and a help facility. Consult the `Related Functions' + section of the CoinParam class documentation for individual function + documentation. +*/ +namespace CoinParamUtils { +/*! \relatesalso CoinParam + \brief Take command input from the file specified by src. + + Use stdin for \p src to specify interactive prompting for commands. + */ +void setInputSrc(FILE *src); + +/*! \relatesalso CoinParam + \brief Returns true if command line parameters are being processed. + */ +bool isCommandLine(); + +/*! \relatesalso CoinParam + \brief Returns true if parameters are being obtained from stdin. + */ +bool isInteractive(); + +/*! \relatesalso CoinParam + \brief Attempt to read a string from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if a string is parsed + without error, 2 if no field is present. + */ +std::string getStringField(int argc, const char *argv[], int *valid); + +/*! \relatesalso CoinParam + \brief Attempt to read an integer from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if an integer is parsed + without error, 1 if there's a parse error, and 2 if no field is present. + */ +int getIntField(int argc, const char *argv[], int *valid); + +/*! \relatesalso CoinParam + \brief Attempt to read a real (double) from the input. + + \p argc and \p argv are used only if isCommandLine() would return true. + If \p valid is supplied, it will be set to 0 if a real number is parsed + without error, 1 if there's a parse error, and 2 if no field is present. + */ +double getDoubleField(int argc, const char *argv[], int *valid); + +/*! \relatesalso CoinParam + \brief Scan a parameter vector for parameters whose keyword (name) string + matches \p name using minimal match rules. + + \p matchNdx is set to the index of the last parameter that meets the + minimal match criteria (but note there should be at most one matching + parameter if the parameter vector is properly configured). \p shortCnt + is set to the number of short matches (should be zero for a properly + configured parameter vector if a minimal match is found). The return + value is the number of matches satisfying the minimal match requirement + (should be 0 or 1 in a properly configured vector). + */ +int matchParam(const CoinParamVec ¶mVec, std::string name, + int &matchNdx, int &shortCnt); + +/*! \relatesalso CoinParam + \brief Get the next command keyword (name) + + To be precise, return the next field from the current command input + source, after a bit of processing. In command line mode (isCommandLine() + returns true) the next field will normally be of the form `-keyword' or + `--keyword' (\e i.e., a parameter keyword), and the string returned would + be `keyword'. In interactive mode (isInteractive() returns true), the + user will be prompted if necessary. It is assumed that the user knows + not to use the `-' or `--' prefixes unless specifying parameters on the + command line. + + There are a number of special cases if we're in command line mode. The + order of processing of the raw string goes like this: +
    +
  • A stand-alone `-' is forced to `stdin'. +
  • A stand-alone '--' is returned as a word; interpretation is up to + the client. +
  • A prefix of '-' or '--' is stripped from the string. +
+ If the result is the string `stdin', command processing shifts to + interactive mode and the user is immediately prompted for a new command. + + Whatever results from the above sequence is returned to the user as the + return value of the function. An empty string indicates end of input. + + \p prompt will be used only if it's necessary to prompt the user in + interactive mode. + */ + +std::string getCommand(int argc, const char *argv[], + const std::string prompt, std::string *pfx = 0); + +/*! \relatesalso CoinParam + \brief Look up the command keyword (name) in the parameter vector. + Print help if requested. + + In the most straightforward use, \p name is a string without `?', and the + value returned is the index in \p paramVec of the single parameter that + matched \p name. One or more '?' characters at the end of \p name is a + query for information. The routine prints short (one '?') or long (more + than one '?') help messages for a query. Help is also printed in the case + where the name is ambiguous (some of the matches did not meet the minimal + match length requirement). + + Note that multiple matches meeting the minimal match requirement is a + configuration error. The mimimal match length for the parameters + involved is too short. + + If provided as parameters, on return +
    +
  • \p matchCnt will be set to the number of matches meeting the + minimal match requirement +
  • \p shortCnt will be set to the number of matches that did not + meet the miminal match requirement +
  • \p queryCnt will be set to the number of '?' characters at the + end of the name +
+ + The return values are: +
    +
  • >0: index in \p paramVec of the single unique match for \p name +
  • -1: a query was detected (one or more '?' characters at the end + of \p name +
  • -2: one or more short matches, not a query +
  • -3: no matches, not a query +
  • -4: multiple matches meeting the minimal match requirement + (configuration error) +
+ */ +int lookupParam(std::string name, CoinParamVec ¶mVec, + int *matchCnt = 0, int *shortCnt = 0, int *queryCnt = 0); + +/*! \relatesalso CoinParam + \brief Utility to print a long message as filled lines of text + + The routine makes a best effort to break lines without exceeding the + standard 80 character line length. Explicit newlines in \p msg will + be obeyed. + */ +void printIt(const char *msg); + +/*! \relatesalso CoinParam + \brief Utility routine to print help given a short match or explicit + request for help. + + The two really are related, in that a query (a string that ends with + one or more `?' characters) will often result in a short match. The + routine expects that \p name matches a single parameter, and does not + look for multiple matches. + + If called with \p matchNdx < 0, the routine will look up \p name in \p + paramVec and print the full name from the parameter. If called with \p + matchNdx > 0, it just prints the name from the specified parameter. If + the name is a query, short (one '?') or long (more than one '?') help + is printed. + + */ +void shortOrHelpOne(CoinParamVec ¶mVec, int matchNdx, std::string name, int numQuery); + +/*! \relatesalso CoinParam + \brief Utility routine to print help given multiple matches. + + If the name is not a query, or asks for short help (\e i.e., contains + zero or one '?' characters), the list of matching names is printed. If + the name asks for long help (contains two or more '?' characters), + short help is printed for each matching name. + */ +void shortOrHelpMany(CoinParamVec ¶mVec, + std::string name, int numQuery); + +/*! \relatesalso CoinParam + \brief Print a generic `how to use the command interface' help message. + + The message is hard coded to match the behaviour of the parsing utilities. + */ +void printGenericHelp(); + +/*! \relatesalso CoinParam + \brief Utility routine to print help messages for one or more + parameters. + + Intended as a utility to implement explicit `help' commands. Help will be + printed for all parameters in \p paramVec from \p firstParam to \p + lastParam, inclusive. If \p shortHelp is true, short help messages will + be printed. If \p longHelp is true, long help messages are printed. \p + shortHelp overrules \p longHelp. If neither is true, only command + keywords are printed. \p prefix is printed before each line; it's an + imperfect attempt at indentation. + */ +void printHelp(CoinParamVec ¶mVec, int firstParam, int lastParam, + std::string prefix, + bool shortHelp, bool longHelp, bool hidden); +} + +#endif /* CoinParam_H */ + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPragma.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPragma.hpp new file mode 100644 index 000000000..8933e2b41 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPragma.hpp @@ -0,0 +1,29 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPragma_H +#define CoinPragma_H + +//------------------------------------------------------------------- +// +// This is a file which can contain Pragma's that are +// generally applicable to any source file. +// +//------------------------------------------------------------------- + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +// Turn off compiler warning: +// "empty controlled statement found; is this the intent?" +#pragma warning(disable : 4390) +// Turn off compiler warning about deprecated functions +#pragma warning(disable : 4996) +#endif + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDoubleton.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDoubleton.hpp new file mode 100644 index 000000000..b2f646a6a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDoubleton.hpp @@ -0,0 +1,76 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveDoubleton_H +#define CoinPresolveDoubleton_H + +#define DOUBLETON 5 + +/*! \class doubleton_action + \brief Solve ax+by=c for y and substitute y out of the problem. + + This moves the bounds information for y onto x, making y free and allowing + us to substitute it away. + \verbatim + a x + b y = c + l1 <= x <= u1 + l2 <= y <= u2 ==> + + l2 <= (c - a x) / b <= u2 + b/-a > 0 ==> (b l2 - c) / -a <= x <= (b u2 - c) / -a + b/-a < 0 ==> (b u2 - c) / -a <= x <= (b l2 - c) / -a + \endverbatim +*/ +class doubleton_action : public CoinPresolveAction { +public: + struct action { + + double clox; + double cupx; + double costx; + + double costy; + + double rlo; + + double coeffx; + double coeffy; + + double *colel; + + int icolx; + int icoly; + int row; + int ncolx; + int ncoly; + }; + + const int nactions_; + const action *const actions_; + +private: + doubleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("doubleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~doubleton_action(); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDual.hpp new file mode 100644 index 000000000..7e6a92817 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDual.hpp @@ -0,0 +1,84 @@ +/* $Id$ */ + +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveDual_H +#define CoinPresolveDual_H + +/*! \class remove_dual_action + \brief Attempt to fix variables by bounding reduced costs + + The reduced cost of x_j is d_j = c_j - y*a_j (1). Assume minimization, + so that at optimality d_j >= 0 for x_j nonbasic at lower bound, and + d_j <= 0 for x_j nonbasic at upper bound. + + For a slack variable s_i, c_(n+i) = 0 and a_(n+i) is a unit vector, hence + d_(n+i) = -y_i. If s_i has a finite lower bound and no upper bound, we + must have y_i <= 0 at optimality. Similarly, if s_i has no lower bound and a + finite upper bound, we must have y_i >= 0. + + For a singleton variable x_j, d_j = c_j - y_i*a_ij. Given x_j with a + single finite bound, we can bound d_j greater or less than 0 at + optimality, and that allows us to calculate an upper or lower bound on y_i + (depending on the bound on d_j and the sign of a_ij). + + Now we have bounds on some subset of the y_i, and we can use these to + calculate upper and lower bounds on the d_j, using bound propagation on + (1). If we can manage to bound some d_j as strictly positive or strictly + negative, then at optimality the corresponding variable must be nonbasic + at its lower or upper bound, respectively. If the required bound is lacking, + the problem is unbounded. +*/ + +class remove_dual_action : public CoinPresolveAction { + +public: + /// Destructor + ~remove_dual_action(); + + /// Name + inline const char *name() const { return ("remove_dual_action"); } + + /*! \brief Attempt to fix variables by bounding reduced costs + + Always scans all variables. Propagates bounds on reduced costs until there's + no change or until some set of variables can be fixed. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + /*! \brief Postsolve + + In addition to fixing variables (handled by make_fixed_action), we may + need use our own postsolve to restore constraint bounds. + */ + void postsolve(CoinPostsolveMatrix *prob) const; + +private: + /// Postsolve (bound restore) instruction + struct action { + double rlo_; ///< restored row lower bound + double rup_; ///< restored row upper bound + int ndx_; ///< row index + }; + + /// Constructor with postsolve actions. + remove_dual_action(int nactions, const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + + /// Count of bound restore entries + const int nactions_; + /// Bound restore entries + const action *actions_; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDupcol.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDupcol.hpp new file mode 100644 index 000000000..d697da750 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveDupcol.hpp @@ -0,0 +1,259 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveDupcol_H +#define CoinPresolveDupcol_H + +#include "CoinPresolveMatrix.hpp" + +/*! + \file +*/ + +#define DUPCOL 10 + +/*! \class dupcol_action + \brief Detect and remove duplicate columns + + The general technique is to sum the coefficients a_(*,j) of each column. + Columns with identical sums are duplicates. The obvious problem is that, + e.g., [1 0 1 0] and [0 1 0 1] both add to 2. To minimize the + chances of false positives, the coefficients of each row are multipled by + a random number r_i, so that we sum r_i*a_ij. + + Candidate columns are checked to confirm they are identical. Where the + columns have the same objective coefficient, the two are combined. If the + columns have different objective coefficients, complications ensue. In order + to remove the duplicate, it must be possible to fix the variable at a bound. +*/ + +class dupcol_action : public CoinPresolveAction { + dupcol_action(); + dupcol_action(const dupcol_action &rhs); + dupcol_action &operator=(const dupcol_action &rhs); + + struct action { + double thislo; + double thisup; + double lastlo; + double lastup; + int ithis; + int ilast; + + double *colels; + int nincol; + }; + + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + + dupcol_action(int nactions, const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~dupcol_action(); +}; + +/*! \class duprow_action + \brief Detect and remove duplicate rows + + The algorithm to detect duplicate rows is as outlined for dupcol_action. + + If the feasible interval for one constraint is strictly contained in the + other, the tighter (contained) constraint is kept. If the feasible + intervals are disjoint, the problem is infeasible. If the feasible + intervals overlap, both constraints are kept. + + duprow_action is definitely a work in progress; #postsolve is + unimplemented. + This doesn't matter as it uses useless_constraint. +*/ + +class duprow_action : public CoinPresolveAction { + struct action { + int row; + double lbound; + double ubound; + }; + + //const int nactions_; + //const action *const actions_; + + duprow_action() + : CoinPresolveAction(NULL) + //, nactions_(0) + //, actions_(NULL) + { + } + duprow_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + //, nactions_(nactions) + //, actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + //~duprow_action() { delete[]actions_; } +}; + +class duprow3_action : public CoinPresolveAction { + struct action { + int row; + double lbound; + double ubound; + }; + + //const int nactions_; + //const action *const actions_; + + duprow3_action() + : CoinPresolveAction(NULL) + //, nactions_(0) + //, actions_(NULL) + { + } + duprow3_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + //, nactions_(nactions) + //, actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + //~duprow_action() { delete[]actions_; } +}; + +/*! \class gubrow_action + \brief Detect and remove entries whose sum is known + + If we have an equality row where all entries same then + For other rows where all entries for that equality row are same + then we can delete entries and modify rhs + gubrow_action is definitely a work in progress; #postsolve is + unimplemented. +*/ + +class gubrow_action : public CoinPresolveAction { + struct action { + double rhs; + // last is row itself + int *deletedRow; + double *rowels; + int *indices; // indices in gub row + int nDrop; + int ninrow; + }; + + const int nactions_; + const action *const actions_; + + //gubrow_action():CoinPresolveAction(NULL),nactions_(0),actions_(NULL) {} + gubrow_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~gubrow_action(); +}; + +/*! \class twoxtwo_action + \brief Detect interesting 2 by 2 blocks + + If a variable has two entries and for each row there are only + two entries with same other variable then we can get rid of + one constraint and modify costs. + + This is a work in progress - I need more examples +*/ + +class twoxtwo_action : public CoinPresolveAction { + struct action { + double lbound_row; + double ubound_row; + double lbound_col; + double ubound_col; + double cost_col; + double cost_othercol; + int row; + int col; + int othercol; + }; + + const int nactions_; + const action *const actions_; + + twoxtwo_action() + : CoinPresolveAction(NULL) + , nactions_(0) + , actions_(NULL) + { + } + twoxtwo_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + ~twoxtwo_action() { delete[] actions_; } +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveEmpty.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveEmpty.hpp new file mode 100644 index 000000000..94efeda21 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveEmpty.hpp @@ -0,0 +1,120 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveEmpty_H +#define CoinPresolveEmpty_H + +/*! \file + + Drop/reinsert empty rows/columns. +*/ + +const int DROP_ROW = 3; +const int DROP_COL = 4; + +/*! \class drop_empty_cols_action + \brief Physically removes empty columns in presolve, and reinserts + empty columns in postsolve. + + Physical removal of rows and columns should be the last activities + performed during presolve. Do them exactly once. The row-major matrix + is not maintained by this transform. + + To physically drop the columns, CoinPrePostsolveMatrix::mcstrt_ and + CoinPrePostsolveMatrix::hincol_ are compressed, along with column bounds, + objective, and (if present) the column portions of the solution. This + renumbers the columns. drop_empty_cols_action::presolve will reconstruct + CoinPresolveMatrix::clink_. + + \todo Confirm correct behaviour with solution in presolve. +*/ + +class drop_empty_cols_action : public CoinPresolveAction { +private: + const int nactions_; + + struct action { + double clo; + double cup; + double cost; + double sol; + int jcol; + }; + const action *const actions_; + + drop_empty_cols_action(int nactions, + const action *const actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("drop_empty_cols_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const int *ecols, + int necols, + const CoinPresolveAction *); + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_empty_cols_action() { deleteAction(actions_, action *); } +}; + +/*! \class drop_empty_rows_action + \brief Physically removes empty rows in presolve, and reinserts + empty rows in postsolve. + + Physical removal of rows and columns should be the last activities + performed during presolve. Do them exactly once. The row-major matrix + is not maintained by this transform. + + To physically drop the rows, the rows are renumbered, excluding empty + rows. This involves rewriting CoinPrePostsolveMatrix::hrow_ and compressing + the row bounds and (if present) the row portions of the solution. + + \todo Confirm behaviour when a solution is present in presolve. +*/ +class drop_empty_rows_action : public CoinPresolveAction { +private: + struct action { + double rlo; + double rup; + int row; + int fill_row; // which row was moved into position row to fill it + }; + + const int nactions_; + const action *const actions_; + + drop_empty_rows_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("drop_empty_rows_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_empty_rows_action() { deleteAction(actions_, action *); } +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveFixed.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveFixed.hpp new file mode 100644 index 000000000..a3e679c23 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveFixed.hpp @@ -0,0 +1,185 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveFixed_H +#define CoinPresolveFixed_H +#define FIXED_VARIABLE 1 + +/*! \class remove_fixed_action + \brief Excise fixed variables from the model. + + Implements the action of virtually removing one or more fixed variables + x_j from the model by substituting the value sol_j in each constraint. + Specifically, for each constraint i where a_ij != 0, rlo_i and rup_i + are adjusted by -a_ij*sol_j and a_ij is set to 0. + + There is an implicit assumption that the variable already has the correct + value. If this isn't true, corrections to row activity may be incorrect. + If you want to guard against this possibility, consider make_fixed_action. + + Actual removal of the empty column from the matrix is handled by + drop_empty_cols_action. Correction of the objective function is done there. +*/ +class remove_fixed_action : public CoinPresolveAction { +public: + /*! \brief Structure to hold information necessary to reintroduce a + column into the problem representation. + */ + struct action { + int col; ///< column index of variable + int start; ///< start of coefficients in #colels_ and #colrows_ + double sol; ///< value of variable + }; + /// Array of row indices for coefficients of excised columns + int *colrows_; + /// Array of coefficients of excised columns + double *colels_; + /// Number of entries in #actions_ + int nactions_; + /// Vector specifying variable(s) affected by this object + action *actions_; + +private: + /*! \brief Constructor */ + remove_fixed_action(int nactions, + action *actions, + double *colels, + int *colrows, + const CoinPresolveAction *next); + +public: + /// Returns string "remove_fixed_action". + const char *name() const; + + /*! \brief Excise the specified columns. + + Remove the specified columns (\p nfcols, \p fcols) from the problem + representation (\p prob), leaving the appropriate postsolve object + linked as the head of the list of postsolve objects (currently headed + by \p next). + */ + static const remove_fixed_action *presolve(CoinPresolveMatrix *prob, + int *fcols, + int nfcols, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + /// Destructor + virtual ~remove_fixed_action(); +}; + +/*! \relates remove_fixed_action + \brief Scan the problem for fixed columns and remove them. + + A front end to collect a list of columns with equal bounds and hand them to + remove_fixed_action::presolve() for processing. +*/ + +const CoinPresolveAction *remove_fixed(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +/*! \class make_fixed_action + \brief Fix a variable at a specified bound. + + Implements the action of fixing a variable by forcing both bounds to the same + value and forcing the value of the variable to match. + + If the bounds are already equal, and the value of the variable is already + correct, consider remove_fixed_action. +*/ +class make_fixed_action : public CoinPresolveAction { + + /// Structure to preserve the bound overwritten when fixing a variable + struct action { + double bound; ///< Value of bound overwritten to fix variable. + int col; ///< column index of variable + }; + + /// Number of preserved bounds + int nactions_; + /// Vector of preserved bounds, one for each variable fixed in this object + const action *actions_; + + /*! \brief True to fix at lower bound, false to fix at upper bound. + + Note that this applies to all variables fixed in this object. + */ + const bool fix_to_lower_; + + /*! \brief The postsolve object with the information required to repopulate + the fixed columns. + */ + const remove_fixed_action *faction_; + + /*! \brief Constructor */ + make_fixed_action(int nactions, const action *actions, bool fix_to_lower, + const remove_fixed_action *faction, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + , fix_to_lower_(fix_to_lower) + , faction_(faction) + { + } + +public: + /// Returns string "make_fixed_action". + const char *name() const; + + /*! \brief Perform actions to fix variables and return postsolve object + + For each specified variable (\p nfcols, \p fcols), fix the variable to + the specified bound (\p fix_to_lower) by setting the variable's bounds + to be equal in \p prob. Create a postsolve object, link it at the head of + the list of postsolve objects (\p next), and return the object. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + int *fcols, + int nfcols, + bool fix_to_lower, + const CoinPresolveAction *next); + + /*! \brief Postsolve (unfix variables) + + Back out the variables fixed by the presolve side of this object. + */ + void postsolve(CoinPostsolveMatrix *prob) const; + + /// Destructor + virtual ~make_fixed_action() + { + deleteAction(actions_, action *); + delete faction_; + } +}; + +/*! \relates make_fixed_action + \brief Scan variables and fix any with equal bounds + + A front end to collect a list of columns with equal bounds and hand them to + make_fixed_action::presolve() for processing. +*/ + +const CoinPresolveAction *make_fixed(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +/*! \brief Transfer costs from singleton variables + \relates make_fixed_action + + Transfers costs from singleton variables in equalities onto the other + variables. Will also transfer costs from one integer variable to other + integer variables with zero cost if there's a net gain in integer variables + with non-zero cost. + + The relation to make_fixed_action is tenuous, but this transform should be + attempted before the initial round of variable fixing. +*/ +void transferCosts(CoinPresolveMatrix *prob); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveForcing.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveForcing.hpp new file mode 100644 index 000000000..f5d0b56a6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveForcing.hpp @@ -0,0 +1,69 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveForcing_H +#define CoinPresolveForcing_H + +#include "CoinPresolveMatrix.hpp" + +/*! + \file +*/ + +#define IMPLIED_BOUND 7 + +/*! \class forcing_constraint_action + \brief Detect and process forcing constraints and useless constraints + + A constraint is useless if the bounds on the variables prevent the constraint + from ever being violated. + + A constraint is a forcing constraint if the bounds on the constraint force + the value of an involved variable to one of its bounds. A constraint can + force more than one variable. +*/ +class forcing_constraint_action : public CoinPresolveAction { + forcing_constraint_action(); + forcing_constraint_action(const forcing_constraint_action &rhs); + forcing_constraint_action &operator=(const forcing_constraint_action &rhs); + +public: + struct action { + const int *rowcols; + const double *bounds; + int row; + int nlo; + int nup; + }; + +private: + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + +public: + forcing_constraint_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~forcing_constraint_action(); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveImpliedFree.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveImpliedFree.hpp new file mode 100644 index 000000000..a2e2353e6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveImpliedFree.hpp @@ -0,0 +1,66 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveImpliedFree_H +#define CoinPresolveImpliedFree_H + +/*! + \file +*/ + +#define IMPLIED_FREE 9 + +/*! \class implied_free_action + \brief Detect and process implied free variables + + Consider a singleton variable x (i.e., a variable involved in only + one constraint). Suppose that the bounds on that constraint, combined with + the bounds on the other variables involved in the constraint, are such that + even the worst case values of the other variables still imply bounds for x + which are tighter than the variable's original bounds. Since x can never + reach its upper or lower bounds, it is an implied free variable. Both x and + the constraint can be deleted from the problem. + + A similar transform for the case where the variable is not a natural column + singleton is handled by #subst_constraint_action. +*/ +class implied_free_action : public CoinPresolveAction { + struct action { + int row, col; + double clo, cup; + double rlo, rup; + const double *rowels; + const double *costs; + int ninrow; + }; + + const int nactions_; + const action *const actions_; + + implied_free_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + int &fillLevel); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~implied_free_action(); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveIsolated.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveIsolated.hpp new file mode 100644 index 000000000..d90cc7d67 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveIsolated.hpp @@ -0,0 +1,59 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveIsolated_H +#define CoinPresolveIsolated_H + +#include "CoinPresolveMatrix.hpp" + +class isolated_constraint_action : public CoinPresolveAction { + isolated_constraint_action(); + isolated_constraint_action(const isolated_constraint_action &rhs); + isolated_constraint_action &operator=(const isolated_constraint_action &rhs); + + double rlo_; + double rup_; + int row_; + int ninrow_; + // the arrays are owned by the class and must be deleted at destruction + const int *rowcols_; + const double *rowels_; + const double *costs_; + + isolated_constraint_action(double rlo, + double rup, + int row, + int ninrow, + const int *rowcols, + const double *rowels, + const double *costs, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , rlo_(rlo) + , rup_(rup) + , row_(row) + , ninrow_(ninrow) + , rowcols_(rowcols) + , rowels_(rowels) + , costs_(costs) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + int row, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~isolated_constraint_action(); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMatrix.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMatrix.hpp new file mode 100644 index 000000000..5a826ce64 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMatrix.hpp @@ -0,0 +1,1996 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveMatrix_H +#define CoinPresolveMatrix_H + +#include "CoinPragma.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinMessage.hpp" +#include "CoinTime.hpp" + +#include +#include +#include +#include +#include + +//# define COIN_PRESOLVE_TUNING 2 +#if PRESOLVE_DEBUG > 0 +#include "CoinFinite.hpp" +#endif + +/*! \file + + Declarations for CoinPresolveMatrix and CoinPostsolveMatrix and their + common base class CoinPrePostsolveMatrix. Also declarations for + CoinPresolveAction and a number of non-member utility functions. +*/ + +#if defined(_MSC_VER) +// Avoid MS Compiler problem in recognizing type to delete +// by casting to type. +// Is this still necessary? -- lh, 111202 -- +#define deleteAction(array, type) delete[]((type)array) +#else +#define deleteAction(array, type) delete[] array +#endif + +/* + Define PRESOLVE_DEBUG and PRESOLVE_CONSISTENCY on the configure command + line or in a Makefile! See comments in CoinPresolvePsdebug.hpp. +*/ +#if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 + +#define PRESOLVE_STMT(s) s + +#define PRESOLVEASSERT(x) \ + ((x) ? 1 : ((std::cerr << "FAILED ASSERTION at line " << __LINE__ << ": " #x "\n"), abort(), 0)) + +inline void DIE(const char *s) +{ + std::cout << s; + abort(); +} + +/*! \brief Indicate column or row present at start of postsolve + + This code is used during postsolve in [cr]done to indicate columns and rows + that are present in the presolved system (i.e., present at the start of + postsolve processing). + + \todo + There are a bunch of these code definitions, scattered through presolve + files. They should be collected in one place. +*/ +#define PRESENT_IN_REDUCED '\377' + +#else + +#define PRESOLVEASSERT(x) \ + { \ + } +#define PRESOLVE_STMT(s) \ + { \ + } + +inline void DIE(const char *) {} + +#endif + +/* + Unclear why these are separate from standard debug. +*/ +#ifndef PRESOLVE_DETAIL +#define PRESOLVE_DETAIL_PRINT(s) \ + { \ + } +#else +#define PRESOLVE_DETAIL_PRINT(s) s +#endif + +/*! \brief Zero tolerance + + OSL had a fixed zero tolerance; we still use that here. +*/ +const double ZTOLDP = 1e-12; +/*! \brief Alternate zero tolerance + + Use a different one if we are doing doubletons, etc. +*/ +const double ZTOLDP2 = 1e-10; + +/// The usual finite infinity +#define PRESOLVE_INF COIN_DBL_MAX +/// And a small infinity +#define PRESOLVE_SMALL_INF 1.0e20 +/// Check for infinity using finite infinity +#define PRESOLVEFINITE(n) (-PRESOLVE_INF < (n) && (n) < PRESOLVE_INF) + +class CoinPostsolveMatrix; + +/*! \class CoinPresolveAction + \brief Abstract base class of all presolve routines. + + The details will make more sense after a quick overview of the grand plan: + A presolve object is handed a problem object, which it is expected to + modify in some useful way. Assuming that it succeeds, the presolve object + should create a postsolve object, i.e., an object that contains + instructions for backing out the presolve transform to recover the original + problem. These postsolve objects are accumulated in a linked list, with each + successive presolve action adding its postsolve action to the head of the + list. The end result of all this is a presolved problem object, and a list + of postsolve objects. The presolved problem object is then handed to a + solver for optimization, and the problem object augmented with the + results. The list of postsolve objects is then traversed. Each of them + (un)modifies the problem object, with the end result being the original + problem, augmented with solution information. + + The problem object representation is CoinPrePostsolveMatrix and subclasses. + Check there for details. The \c CoinPresolveAction class and subclasses + represent the presolve and postsolve objects. + + In spite of the name, the only information held in a \c CoinPresolveAction + object is the information needed to postsolve (i.e., the information + needed to back out the presolve transformation). This information is not + expected to change, so the fields are all \c const. + + A subclass of \c CoinPresolveAction, implementing a specific pre/postsolve + action, is expected to declare a static function that attempts to perform a + presolve transformation. This function will be handed a CoinPresolveMatrix + to transform, and a pointer to the head of the list of postsolve objects. + If the transform is successful, the function will create a new + \c CoinPresolveAction object, link it at the head of the list of postsolve + objects, and return a pointer to the postsolve object it has just created. + Otherwise, it should return 0. It is expected that these static functions + will be the only things that can create new \c CoinPresolveAction objects; + this is expressed by making each subclass' constructor(s) private. + + Every subclass must also define a \c postsolve method. + This function will be handed a CoinPostsolveMatrix to transform. + + It is the client's responsibility to implement presolve and postsolve driver + routines. See OsiPresolve for examples. + + \note Since the only fields in a \c CoinPresolveAction are \c const, anything + one can do with a variable declared \c CoinPresolveAction* can also be + done with a variable declared \c const \c CoinPresolveAction* It is + expected that all derived subclasses of \c CoinPresolveAction also have + this property. +*/ +class CoinPresolveAction { +public: + /*! \brief Stub routine to throw exceptions. + + Exceptions are inefficient, particularly with g++. Even with xlC, the + use of exceptions adds a long prologue to a routine. Therefore, rather + than use throw directly in the routine, I use it in a stub routine. + */ + static void throwCoinError(const char *error, const char *ps_routine) + { + throw CoinError(error, ps_routine, "CoinPresolve"); + } + + /*! \brief The next presolve transformation + + Set at object construction. + */ + const CoinPresolveAction *next; + + /*! \brief Construct a postsolve object and add it to the transformation list. + + This is an `add to head' operation. This object will point to the + one passed as the parameter. + */ + CoinPresolveAction(const CoinPresolveAction *next) + : next(next) + { + } + /// modify next (when building rather than passing) + inline void setNext(const CoinPresolveAction *nextAction) + { + next = nextAction; + } + + /*! \brief A name for debug printing. + + It is expected that the name is not stored in the transform itself. + */ + virtual const char *name() const = 0; + + /*! \brief Apply the postsolve transformation for this particular + presolve action. + */ + virtual void postsolve(CoinPostsolveMatrix *prob) const = 0; + + /*! \brief Virtual destructor. */ + virtual ~CoinPresolveAction() {} +}; + +/* + These are needed for OSI-aware constructors associated with + CoinPrePostsolveMatrix, CoinPresolveMatrix, and CoinPostsolveMatrix. +*/ +class ClpSimplex; +class OsiSolverInterface; + +/* + CoinWarmStartBasis is required for methods in CoinPrePostsolveMatrix + that accept/return a CoinWarmStartBasis object. +*/ +class CoinWarmStartBasis; + +/*! \class CoinPrePostsolveMatrix + \brief Collects all the information about the problem that is needed + in both presolve and postsolve. + + In a bit more detail, a column-major representation of the constraint + matrix and upper and lower bounds on variables and constraints, plus row + and column solutions, reduced costs, and status. There's also a set of + arrays holding the original row and column numbers. + + As presolve and postsolve transform the matrix, it will occasionally be + necessary to expand the number of entries in a column. There are two + aspects: +
    +
  • During postsolve, the constraint system is expected to grow as + the smaller presolved system is transformed back to the original + system. +
  • During both pre- and postsolve, transforms can increase the number + of coefficients in a row or column. (See the + variable substitution, doubleton, and tripleton transforms.) +
+ + The first is addressed by the members #ncols0_, #nrows0_, and #nelems0_. + These should be set (via constructor parameters) to values large enough + for the largest size taken on by the constraint system. Typically, this + will be the size of the original constraint system. + + The second is addressed by a generous allocation of extra (empty) space + for the arrays used to hold coefficients and row indices. When columns + must be expanded, they are moved into the empty space. When it is used up, + the arrays are compacted. When compaction fails to produce sufficient + space, presolve/postsolve will fail. + + CoinPrePostsolveMatrix isn't really intended to be used `bare' --- the + expectation is that it'll be used through CoinPresolveMatrix or + CoinPostsolveMatrix. Some of the functions needed to load a problem are + defined in the derived classes. + + When CoinPresolve is applied when reoptimising, we need to be prepared to + accept a basis and modify it in step with the presolve actions (otherwise + we throw away all the advantages of warm start for reoptimization). But + other solution components (#acts_, #rowduals_, #sol_, and #rcosts_) are + needed only for postsolve, where they're used in places to determine the + proper action(s) when restoring rows or columns. If presolve is provided + with a solution, it will modify it in step with the presolve actions. + Moving the solution components from CoinPrePostsolveMatrix to + CoinPostsolveMatrix would break a lot of code. It's not clear that it's + worth it, and it would preclude upgrades to the presolve side that might + make use of any of these. -- lh, 080501 -- + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ + +class CoinPrePostsolveMatrix { +public: + /*! \name Constructors & Destructors */ + + //@{ + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. On + the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPrePostsolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc); + + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPrePostsolveMatrix(const OsiSolverInterface *si, + int ncols_, + int nrows_, + CoinBigIndex nelems_); + + /*! ClpOsi constructor + + See Clp code for the definition. + */ + CoinPrePostsolveMatrix(const ClpSimplex *si, + int ncols_, + int nrows_, + CoinBigIndex nelems_, + double bulkRatio); + + /// Destructor + ~CoinPrePostsolveMatrix(); + //@} + + /*! \brief Enum for status of various sorts + + Matches CoinWarmStartBasis::Status and adds superBasic. Most code that + converts between CoinPrePostsolveMatrix::Status and + CoinWarmStartBasis::Status will break if this correspondence is broken. + + superBasic is an unresolved problem: there's no analogue in + CoinWarmStartBasis::Status. + */ + enum Status { + isFree = 0x00, + basic = 0x01, + atUpperBound = 0x02, + atLowerBound = 0x03, + superBasic = 0x04 + }; + + /*! \name Functions to work with variable status + + Functions to work with the CoinPrePostsolveMatrix::Status enum and + related vectors. + + \todo + Why are we futzing around with three bit status? A holdover from the + packed arrays of CoinWarmStartBasis? Big swaths of the presolve code + manipulates colstat_ and rowstat_ as unsigned char arrays using simple + assignment to set values. + */ + //@{ + + /// Set row status (i.e., status of artificial for this row) + inline void setRowStatus(int sequence, Status status) + { + unsigned char &st_byte = rowstat_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & (~7)); + st_byte = static_cast< unsigned char >(st_byte | status); + } + /// Get row status + inline Status getRowStatus(int sequence) const + { + return static_cast< Status >(rowstat_[sequence] & 7); + } + /// Check if artificial for this row is basic + inline bool rowIsBasic(int sequence) const + { + return (static_cast< Status >(rowstat_[sequence] & 7) == basic); + } + /// Set column status (i.e., status of primal variable) + inline void setColumnStatus(int sequence, Status status) + { + unsigned char &st_byte = colstat_[sequence]; + st_byte = static_cast< unsigned char >(st_byte & (~7)); + st_byte = static_cast< unsigned char >(st_byte | status); + +#ifdef PRESOLVE_DEBUG + switch (status) { + case isFree: { + if (clo_[sequence] > -PRESOLVE_INF || cup_[sequence] < PRESOLVE_INF) { + std::cout << "Bad status: Var " << sequence + << " isFree, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl; + } + break; + } + case basic: { + break; + } + case atUpperBound: { + if (cup_[sequence] >= PRESOLVE_INF) { + std::cout << "Bad status: Var " << sequence + << " atUpperBound, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl; + } + break; + } + case atLowerBound: { + if (clo_[sequence] <= -PRESOLVE_INF) { + std::cout << "Bad status: Var " << sequence + << " atLowerBound, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl; + } + break; + } + case superBasic: { + if (clo_[sequence] <= -PRESOLVE_INF && cup_[sequence] >= PRESOLVE_INF) { + std::cout << "Bad status: Var " << sequence + << " superBasic, lb = " << clo_[sequence] + << ", ub = " << cup_[sequence] << std::endl; + } + break; + } + default: { + assert(false); + break; + } + } +#endif + } + /// Get column (structural variable) status + inline Status getColumnStatus(int sequence) const + { + return static_cast< Status >(colstat_[sequence] & 7); + } + /// Check if column (structural variable) is basic + inline bool columnIsBasic(int sequence) const + { + return (static_cast< Status >(colstat_[sequence] & 7) == basic); + } + /*! \brief Set status of row (artificial variable) to the correct nonbasic + status given bounds and current value + */ + void setRowStatusUsingValue(int iRow); + /*! \brief Set status of column (structural variable) to the correct + nonbasic status given bounds and current value + */ + void setColumnStatusUsingValue(int iColumn); + /*! \brief Set column (structural variable) status vector */ + void setStructuralStatus(const char *strucStatus, int lenParam); + /*! \brief Set row (artificial variable) status vector */ + void setArtificialStatus(const char *artifStatus, int lenParam); + /*! \brief Set the status of all variables from a basis */ + void setStatus(const CoinWarmStartBasis *basis); + /*! \brief Get status in the form of a CoinWarmStartBasis */ + CoinWarmStartBasis *getStatus(); + /*! \brief Return a print string for status of a column (structural + variable) + */ + const char *columnStatusString(int j) const; + /*! \brief Return a print string for status of a row (artificial + variable) + */ + const char *rowStatusString(int i) const; + //@} + + /*! \name Functions to load problem and solution information + + These functions can be used to load portions of the problem definition + and solution. See also the CoinPresolveMatrix and CoinPostsolveMatrix + classes. + */ + //@{ + /// Set the objective function offset for the original system. + void setObjOffset(double offset); + /*! \brief Set the objective sense (max/min) + + Coded as 1.0 for min, -1.0 for max. + Yes, there's a method, and a matching attribute. No, you really + don't want to set this to maximise. + */ + void setObjSense(double objSense); + /// Set the primal feasibility tolerance + void setPrimalTolerance(double primTol); + /// Set the dual feasibility tolerance + void setDualTolerance(double dualTol); + /// Set column lower bounds + void setColLower(const double *colLower, int lenParam); + /// Set column upper bounds + void setColUpper(const double *colUpper, int lenParam); + /// Set column solution + void setColSolution(const double *colSol, int lenParam); + /// Set objective coefficients + void setCost(const double *cost, int lenParam); + /// Set reduced costs + void setReducedCost(const double *redCost, int lenParam); + /// Set row lower bounds + void setRowLower(const double *rowLower, int lenParam); + /// Set row upper bounds + void setRowUpper(const double *rowUpper, int lenParam); + /// Set row solution + void setRowPrice(const double *rowSol, int lenParam); + /// Set row activity + void setRowActivity(const double *rowAct, int lenParam); + //@} + + /*! \name Functions to retrieve problem and solution information */ + //@{ + /// Get current number of columns + inline int getNumCols() const + { + return (ncols_); + } + /// Get current number of rows + inline int getNumRows() const + { + return (nrows_); + } + /// Get current number of non-zero coefficients + inline CoinBigIndex getNumElems() const + { + return (nelems_); + } + /// Get column start vector for column-major packed matrix + inline const CoinBigIndex *getColStarts() const + { + return (mcstrt_); + } + /// Get column length vector for column-major packed matrix + inline const int *getColLengths() const + { + return (hincol_); + } + /// Get vector of row indices for column-major packed matrix + inline const int *getRowIndicesByCol() const + { + return (hrow_); + } + /// Get vector of elements for column-major packed matrix + inline const double *getElementsByCol() const + { + return (colels_); + } + /// Get column lower bounds + inline const double *getColLower() const + { + return (clo_); + } + /// Get column upper bounds + inline const double *getColUpper() const + { + return (cup_); + } + /// Get objective coefficients + inline const double *getCost() const + { + return (cost_); + } + /// Get row lower bounds + inline const double *getRowLower() const + { + return (rlo_); + } + /// Get row upper bounds + inline const double *getRowUpper() const + { + return (rup_); + } + /// Get column solution (primal variable values) + inline const double *getColSolution() const + { + return (sol_); + } + /// Get row activity (constraint lhs values) + inline const double *getRowActivity() const + { + return (acts_); + } + /// Get row solution (dual variables) + inline const double *getRowPrice() const + { + return (rowduals_); + } + /// Get reduced costs + inline const double *getReducedCost() const + { + return (rcosts_); + } + /// Count empty columns + inline int countEmptyCols() + { + int empty = 0; + for (int i = 0; i < ncols_; i++) + if (hincol_[i] == 0) + empty++; + return (empty); + } + //@} + + /*! \name Message handling */ + //@{ + /// Return message handler + inline CoinMessageHandler *messageHandler() const + { + return handler_; + } + /*! \brief Set message handler + + The client retains responsibility for the handler --- it will not be + destroyed with the \c CoinPrePostsolveMatrix object. + */ + inline void setMessageHandler(CoinMessageHandler *handler) + { + if (defaultHandler_ == true) { + delete handler_; + defaultHandler_ = false; + } + handler_ = handler; + } + /// Return messages + inline CoinMessages messages() const + { + return messages_; + } + //@} + + /*! \name Current and Allocated Size + + During pre- and postsolve, the matrix will change in size. During presolve + it will shrink; during postsolve it will grow. Hence there are two sets of + size variables, one for the current size and one for the allocated size. + (See the general comments for the CoinPrePostsolveMatrix class for more + information.) + */ + //@{ + + /// current number of columns + int ncols_; + /// current number of rows + int nrows_; + /// current number of coefficients + CoinBigIndex nelems_; + + /// Allocated number of columns + int ncols0_; + /// Allocated number of rows + int nrows0_; + /// Allocated number of coefficients + CoinBigIndex nelems0_; + /*! \brief Allocated size of bulk storage for row indices and coefficients + + This is the space allocated for hrow_ and colels_. This must be large + enough to allow columns to be copied into empty space when they need to + be expanded. For efficiency (to minimize the number of times the + representation must be compressed) it's recommended that this be at least + 2*nelems0_. + */ + CoinBigIndex bulk0_; + /// Ratio of bulk0_ to nelems0_; default is 2. + double bulkRatio_; + //@} + + /*! \name Problem representation + + The matrix is the common column-major format: A pair of vectors with + positional correspondence to hold coefficients and row indices, and a + second pair of vectors giving the starting position and length of each + column in the first pair. + */ + //@{ + /// Vector of column start positions in #hrow_, #colels_ + CoinBigIndex *mcstrt_; + /// Vector of column lengths + int *hincol_; + /// Row indices (positional correspondence with #colels_) + int *hrow_; + /// Coefficients (positional correspondence with #hrow_) + double *colels_; + + /// Objective coefficients + double *cost_; + /// Original objective offset + double originalOffset_; + + /// Column (primal variable) lower bounds + double *clo_; + /// Column (primal variable) upper bounds + double *cup_; + + /// Row (constraint) lower bounds + double *rlo_; + /// Row (constraint) upper bounds + double *rup_; + + /*! \brief Original column numbers + + Over the current range of column numbers in the presolved problem, + the entry for column j will contain the index of the corresponding + column in the original problem. + */ + int *originalColumn_; + /*! \brief Original row numbers + + Over the current range of row numbers in the presolved problem, the + entry for row i will contain the index of the corresponding row in + the original problem. + */ + int *originalRow_; + + /// Primal feasibility tolerance + double ztolzb_; + /// Dual feasibility tolerance + double ztoldj_; + + /*! \brief Maximization/minimization + + Yes, there's a variable here. No, you really don't want to set this to + maximise. See the main notes for CoinPresolveMatrix. + */ + double maxmin_; + //@} + + /*! \name Problem solution information + + The presolve phase will work without any solution information + (appropriate for initial optimisation) or with solution information + (appropriate for reoptimisation). When solution information is supplied, + presolve will maintain it to the best of its ability. #colstat_ is + checked to determine the presence/absence of status information. #sol_ is + checked for primal solution information, and #rowduals_ for dual solution + information. + + The postsolve phase requires the complete solution information from the + presolved problem (status, primal and dual solutions). It will be + transformed into a correct solution for the original problem. + */ + //@{ + /*! \brief Vector of primal variable values + + If #sol_ exists, it is assumed that primal solution information should be + updated and that #acts_ also exists. + */ + double *sol_; + /*! \brief Vector of dual variable values + + If #rowduals_ exists, it is assumed that dual solution information should + be updated and that #rcosts_ also exists. + */ + double *rowduals_; + /*! \brief Vector of constraint left-hand-side values (row activity) + + Produced by evaluating constraints according to #sol_. Updated iff + #sol_ exists. + */ + double *acts_; + /*! \brief Vector of reduced costs + + Produced by evaluating dual constraints according to #rowduals_. Updated + iff #rowduals_ exists. + */ + double *rcosts_; + + /*! \brief Status of primal variables + + Coded with CoinPrePostSolveMatrix::Status, one code per char. colstat_ and + #rowstat_ MUST be allocated as a single vector. This is to maintain + compatibility with ClpPresolve and OsiPresolve, which do it this way. + */ + unsigned char *colstat_; + + /*! \brief Status of constraints + + More accurately, the status of the logical variable associated with the + constraint. Coded with CoinPrePostSolveMatrix::Status, one code per char. + Note that this must be allocated as a single vector with #colstat_. + */ + unsigned char *rowstat_; + //@} + + /*! \name Message handling + + Uses the standard COIN approach: a default handler is installed, and the + CoinPrePostsolveMatrix object takes responsibility for it. If the client + replaces the handler with one of their own, it becomes their + responsibility. + */ + //@{ + /// Message handler + CoinMessageHandler *handler_; + /// Indicates if the current #handler_ is default (true) or not (false). + bool defaultHandler_; + /// Standard COIN messages + CoinMessage messages_; + //@} +}; + +/*! \relates CoinPrePostsolveMatrix + \brief Generate a print string for a status code. +*/ +const char *statusName(CoinPrePostsolveMatrix::Status status); + +/*! \class presolvehlink + \brief Links to aid in packed matrix modification + + Currently, the matrices held by the CoinPrePostsolveMatrix and + CoinPresolveMatrix objects are represented in the same way as a + CoinPackedMatrix. In the course of presolve and postsolve transforms, it + will happen that a major-dimension vector needs to increase in size. In + order to check whether there is enough room to add another coefficient in + place, it helps to know the next vector (in memory order) in the bulk + storage area. To do that, a linked list of major-dimension vectors is + maintained; the "pre" and "suc" fields give the previous and next vector, + in memory order (that is, the vector whose mcstrt_ or mrstrt_ entry is + next smaller or larger). + + Consider a column-major matrix with ncols columns. By definition, + presolvehlink[ncols].pre points to the column in the last occupied + position of the bulk storage arrays. There is no easy way to find the + column which occupies the first position (there is no presolvehlink[-1] to + consult). If the column that initially occupies the first position is + moved for expansion, there is no way to reclaim the space until the bulk + storage is compacted. The same holds for the last and first rows of a + row-major matrix, of course. +*/ + +class presolvehlink { +public: + int pre, suc; +}; + +#define NO_LINK -66666666 + +/*! \relates presolvehlink + \brief unlink vector i + + Remove vector i from the ordering. +*/ +inline void PRESOLVE_REMOVE_LINK(presolvehlink *link, int i) +{ + int ipre = link[i].pre; + int isuc = link[i].suc; + if (ipre >= 0) { + link[ipre].suc = isuc; + } + if (isuc >= 0) { + link[isuc].pre = ipre; + } + link[i].pre = NO_LINK, link[i].suc = NO_LINK; +} + +/*! \relates presolvehlink + \brief insert vector i after vector j + + Insert vector i between j and j.suc. +*/ +inline void PRESOLVE_INSERT_LINK(presolvehlink *link, int i, int j) +{ + int isuc = link[j].suc; + link[j].suc = i; + link[i].pre = j; + if (isuc >= 0) { + link[isuc].pre = i; + } + link[i].suc = isuc; +} + +/*! \relates presolvehlink + \brief relink vector j in place of vector i + + Replace vector i in the ordering with vector j. This is equivalent to +
+     int pre = link[i].pre;
+     PRESOLVE_REMOVE_LINK(link,i);
+     PRESOLVE_INSERT_LINK(link,j,pre);
+   
+ But, this routine will work even if i happens to be first in the order. +*/ +inline void PRESOLVE_MOVE_LINK(presolvehlink *link, int i, int j) +{ + int ipre = link[i].pre; + int isuc = link[i].suc; + if (ipre >= 0) { + link[ipre].suc = j; + } + if (isuc >= 0) { + link[isuc].pre = j; + } + link[i].pre = NO_LINK, link[i].suc = NO_LINK; +} + +/*! \class CoinPresolveMatrix + \brief Augments CoinPrePostsolveMatrix with information about the problem + that is only needed during presolve. + + For problem manipulation, this class adds a row-major matrix + representation, linked lists that allow for easy manipulation of the matrix + when applying presolve transforms, and vectors to track row and column + processing status (changed, needs further processing, change prohibited) + + For problem representation, this class adds information about variable type + (integer or continuous), an objective offset, and a feasibility tolerance. + + NOTE that the #anyInteger_ and #anyProhibited_ flags are independent + of the vectors used to track this information for individual variables + (#integerType_ and #rowChanged_ and #colChanged_, respectively). + + NOTE also that at the end of presolve the column-major and row-major + matrix representations are loosely packed (i.e., there may be gaps + between columns in the bulk storage arrays). + + NOTE that while you might think that CoinPresolve is prepared to + handle minimisation or maximisation, it's unlikely that this still works. + This is a good thing: better to convert objective coefficients and duals + once, before starting presolve, rather than doing it over and over in + each transform that considers dual variables. + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ + +class CoinPresolveMatrix : public CoinPrePostsolveMatrix { +public: + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. + On the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPresolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc); + + /*! \brief Clp OSI constructor + + See Clp code for the definition. + */ + CoinPresolveMatrix(int ncols0, + double maxmin, + // end prepost members + + ClpSimplex *si, + + // rowrep + int nrows, + CoinBigIndex nelems, + bool doStatus, + double nonLinearVariable, + double bulkRatio); + + /*! \brief Update the model held by a Clp OSI */ + void update_model(ClpSimplex *si, + int nrows0, + int ncols0, + CoinBigIndex nelems0); + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPresolveMatrix(int ncols0, + double maxmin, + // end prepost members + OsiSolverInterface *si, + // rowrep + int nrows, + CoinBigIndex nelems, + bool doStatus, + double nonLinearVariable, + const char *prohibited, + const char *rowProhibited = NULL); + + /*! \brief Update the model held by a generic OSI */ + void update_model(OsiSolverInterface *si, + int nrows0, + int ncols0, + CoinBigIndex nelems0); + + /// Destructor + ~CoinPresolveMatrix(); + + /*! \brief Initialize a CoinPostsolveMatrix object, destroying the + CoinPresolveMatrix object. + + See CoinPostsolveMatrix::assignPresolveToPostsolve. + */ + friend void assignPresolveToPostsolve(CoinPresolveMatrix *&preObj); + + /*! \name Functions to load the problem representation + */ + //@{ + /*! \brief Load the cofficient matrix. + + Load the coefficient matrix before loading the other vectors (bounds, + objective, variable type) required to define the problem. + */ + void setMatrix(const CoinPackedMatrix *mtx); + + /// Count number of empty rows + inline int countEmptyRows() + { + int empty = 0; + for (int i = 0; i < nrows_; i++) + if (hinrow_[i] == 0) + empty++; + return (empty); + } + + /*! \brief Set variable type information for a single variable + + Set \p variableType to 0 for continous, 1 for integer. + Does not manipulate the #anyInteger_ flag. + */ + inline void setVariableType(int i, int variableType) + { + if (integerType_ == 0) + integerType_ = new unsigned char[ncols0_]; + integerType_[i] = static_cast< unsigned char >(variableType); + } + + /*! \brief Set variable type information for all variables + + Set \p variableType[i] to 0 for continuous, 1 for integer. + Does not manipulate the #anyInteger_ flag. + */ + void setVariableType(const unsigned char *variableType, int lenParam); + + /*! \brief Set the type of all variables + + allIntegers should be true to set the type to integer, false to set the + type to continuous. + */ + void setVariableType(bool allIntegers, int lenParam); + + /// Set a flag for presence (true) or absence (false) of integer variables + inline void setAnyInteger(bool anyInteger = true) + { + anyInteger_ = anyInteger; + } + //@} + + /*! \name Functions to retrieve problem information + */ + //@{ + + /// Get row start vector for row-major packed matrix + inline const CoinBigIndex *getRowStarts() const + { + return (mrstrt_); + } + /// Get vector of column indices for row-major packed matrix + inline const int *getColIndicesByRow() const + { + return (hcol_); + } + /// Get vector of elements for row-major packed matrix + inline const double *getElementsByRow() const + { + return (rowels_); + } + + /*! \brief Check for integrality of the specified variable. + + Consults the #integerType_ vector if present; fallback is the + #anyInteger_ flag. + */ + inline bool isInteger(int i) const + { + if (integerType_ == 0) { + return (anyInteger_); + } else if (integerType_[i] == 1) { + return (true); + } else { + return (false); + } + } + + /*! \brief Check if there are any integer variables + + Consults the #anyInteger_ flag + */ + inline bool anyInteger() const + { + return (anyInteger_); + } + /// Picks up any special options + inline int presolveOptions() const + { + return presolveOptions_; + } + /// Sets any special options (see #presolveOptions_) + inline void setPresolveOptions(int value) + { + presolveOptions_ = value; + } + //@} + + /*! \name Matrix storage management links + + Linked lists, modelled after the linked lists used in OSL + factorization. They are used for management of the bulk coefficient + and minor index storage areas. + */ + //@{ + /// Linked list for the column-major representation. + presolvehlink *clink_; + /// Linked list for the row-major representation. + presolvehlink *rlink_; + //@} + + /// Objective function offset introduced during presolve + double dobias_; + + /// Adjust objective function constant offset + inline void change_bias(double change_amount) + { + dobias_ += change_amount; +#if PRESOLVE_DEBUG > 2 + assert(fabs(change_amount) < 1.0e50); + if (change_amount) + PRESOLVE_STMT(printf("changing bias by %g to %g\n", + change_amount, dobias_)); +#endif + } + + /*! \name Row-major representation + + Common row-major format: A pair of vectors with positional + correspondence to hold coefficients and column indices, and a second pair + of vectors giving the starting position and length of each row in + the first pair. + */ + //@{ + /// Vector of row start positions in #hcol, #rowels_ + CoinBigIndex *mrstrt_; + /// Vector of row lengths + int *hinrow_; + /// Coefficients (positional correspondence with #hcol_) + double *rowels_; + /// Column indices (positional correspondence with #rowels_) + int *hcol_; + //@} + + /// Tracks integrality of columns (1 for integer, 0 for continuous) + unsigned char *integerType_; + /*! \brief Flag to say if any variables are integer + + Note that this flag is not manipulated by the various + \c setVariableType routines. + */ + bool anyInteger_; + /// Print statistics for tuning + bool tuning_; + /// Say we want statistics - also set time + void statistics(); + /// Start time of presolve + double startTime_; + + /// Bounds can be moved by this to retain feasibility + double feasibilityTolerance_; + /// Return feasibility tolerance + inline double feasibilityTolerance() + { + return (feasibilityTolerance_); + } + /// Set feasibility tolerance + inline void setFeasibilityTolerance(double val) + { + feasibilityTolerance_ = val; + } + + /*! \brief Output status: 0 = feasible, 1 = infeasible, 2 = unbounded + + Actually implemented as single bit flags: 1^0 = infeasible, 1^1 = + unbounded. + */ + int status_; + /// Returns problem status (0 = feasible, 1 = infeasible, 2 = unbounded) + inline int status() + { + return (status_); + } + /// Set problem status + inline void setStatus(int status) + { + status_ = (status & 0x3); + } + + /*! \brief Presolve pass number + + Should be incremented externally by the method controlling application of + presolve transforms. + Used to control the execution of testRedundant (evoked by the + implied_free transform). + */ + int pass_; + /// Set pass number + inline void setPass(int pass = 0) + { + pass_ = pass; + } + + /*! \brief Maximum substitution level + + Used to control the execution of subst from implied_free + */ + int maxSubstLevel_; + /// Set Maximum substitution level (normally 3) + inline void setMaximumSubstitutionLevel(int level) + { + maxSubstLevel_ = level; + } + + /*! \name Row and column processing status + + Information used to determine if rows or columns can be changed and + if they require further processing due to changes. + + There are four major lists: the [row,col]ToDo list, and the + [row,col]NextToDo list. In general, a transform processes entries from + the ToDo list and adds entries to the NextToDo list. + + There are two vectors, [row,col]Changed, which track the status of + individual rows and columns. + */ + //@{ + /*! \brief Column change status information + + Coded using the following bits: +
    +
  • 0x01: Column has changed +
  • 0x02: preprocessing prohibited +
  • 0x04: Column has been used +
  • 0x08: Column originally had infinite ub +
+ */ + unsigned char *colChanged_; + /// Input list of columns to process + int *colsToDo_; + /// Length of #colsToDo_ + int numberColsToDo_; + /// Output list of columns to process next + int *nextColsToDo_; + /// Length of #nextColsToDo_ + int numberNextColsToDo_; + + /*! \brief Row change status information + + Coded using the following bits: +
    +
  • 0x01: Row has changed +
  • 0x02: preprocessing prohibited +
  • 0x04: Row has been used +
+ */ + unsigned char *rowChanged_; + /// Input list of rows to process + int *rowsToDo_; + /// Length of #rowsToDo_ + int numberRowsToDo_; + /// Output list of rows to process next + int *nextRowsToDo_; + /// Length of #nextRowsToDo_ + int numberNextRowsToDo_; + /*! \brief Fine control over presolve actions + + Set/clear the following bits to allow or suppress actions: + - 0x01 allow duplicate column tests for integer variables + - 0x02 not used + - 0x04 set to inhibit x+y+z=1 mods + - 0x08 not used + - 0x10 set to allow stuff which won't unroll easily (overlapping + duplicate rows; opportunistic fixing of variables from bound + propagation). + - 0x04000 allow presolve transforms to arbitrarily ignore infeasibility + and set arbitrary feasible bounds. + - 0x10000 instructs implied_free_action to be `more lightweight'; will + return without doing anything after 15 presolve passes. + - 0x(2,4,6)0000 instructs implied_free_action to remove small created elements + - 0x80000000 set by presolve to say dupcol_action compressed columns + */ + int presolveOptions_; + /*! Flag to say if any rows or columns are marked as prohibited + + Note that this flag is not manipulated by any of the + various \c set*Prohibited routines. + */ + bool anyProhibited_; + //@} + + /*! \name Scratch work arrays + + Preallocated work arrays are useful to avoid having to allocate and free + work arrays in individual presolve methods. + + All are allocated from #setMatrix by #initializeStuff, freed from + #~CoinPresolveMatrix. You can use #deleteStuff followed by + #initializeStuff to remove and recreate them. + */ + //@{ + /// Preallocated scratch work array, 3*nrows_ + int *usefulRowInt_; + /// Preallocated scratch work array, 2*nrows_ + double *usefulRowDouble_; + /// Preallocated scratch work array, 2*ncols_ + int *usefulColumnInt_; + /// Preallocated scratch work array, ncols_ + double *usefulColumnDouble_; + /// Array of random numbers (max row,column) + double *randomNumber_; + + /// Work array for count of infinite contributions to row lhs upper bound + int *infiniteUp_; + /// Work array for sum of finite contributions to row lhs upper bound + double *sumUp_; + /// Work array for count of infinite contributions to row lhs lower bound + int *infiniteDown_; + /// Work array for sum of finite contributions to row lhs lower bound + double *sumDown_; + //@} + + /*! \brief Recompute row lhs bounds + + Calculate finite contributions to row lhs upper and lower bounds + and count infinite contributions. Returns the number of rows found + to be infeasible. + + If \p whichRow < 0, bounds are recomputed for all rows. + + As of 110611, this seems to be a work in progress in the sense that it's + barely used by the existing presolve code. + */ + int recomputeSums(int whichRow); + + /// Allocate scratch arrays + void initializeStuff(); + /// Free scratch arrays + void deleteStuff(); + + /*! \name Functions to manipulate row and column processing status */ + //@{ + + /*! \brief Initialise the column ToDo lists + + Places all columns in the #colsToDo_ list except for columns marked + as prohibited (viz. #colChanged_). + */ + void initColsToDo(); + + /*! \brief Step column ToDo lists + + Moves columns on the #nextColsToDo_ list to the #colsToDo_ list, emptying + #nextColsToDo_. Returns the number of columns transferred. + */ + int stepColsToDo(); + + /// Return the number of columns on the #colsToDo_ list + inline int numberColsToDo() + { + return (numberColsToDo_); + } + + /// Has column been changed? + inline bool colChanged(int i) const + { + return (colChanged_[i] & 1) != 0; + } + /// Mark column as not changed + inline void unsetColChanged(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] & (~1)); + } + /// Mark column as changed. + inline void setColChanged(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] | (1)); + } + /// Mark column as changed and add to list of columns to process next + inline void addCol(int i) + { + if ((colChanged_[i] & 1) == 0) { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] | (1)); + nextColsToDo_[numberNextColsToDo_++] = i; + } + } + /// Test if column is eligible for preprocessing + inline bool colProhibited(int i) const + { + return (colChanged_[i] & 2) != 0; + } + /*! \brief Test if column is eligible for preprocessing + + The difference between this method and #colProhibited() is that this + method first tests #anyProhibited_ before examining the specific entry + for the specified column. + */ + inline bool colProhibited2(int i) const + { + if (!anyProhibited_) + return false; + else + return (colChanged_[i] & 2) != 0; + } + /// Mark column as ineligible for preprocessing + inline void setColProhibited(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] | (2)); + } + /*! \brief Test if column is marked as used + + This is for doing faster lookups to see where two columns have entries + in common. + */ + inline bool colUsed(int i) const + { + return (colChanged_[i] & 4) != 0; + } + /// Mark column as used + inline void setColUsed(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] | (4)); + } + /// Mark column as unused + inline void unsetColUsed(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] & (~4)); + } + /// Has column infinite ub (originally) + inline bool colInfinite(int i) const + { + return (colChanged_[i] & 8) != 0; + } + /// Mark column as not infinite ub (originally) + inline void unsetColInfinite(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] & (~8)); + } + /// Mark column as infinite ub (originally) + inline void setColInfinite(int i) + { + colChanged_[i] = static_cast< unsigned char >(colChanged_[i] | (8)); + } + + /*! \brief Initialise the row ToDo lists + + Places all rows in the #rowsToDo_ list except for rows marked + as prohibited (viz. #rowChanged_). + */ + void initRowsToDo(); + + /*! \brief Step row ToDo lists + + Moves rows on the #nextRowsToDo_ list to the #rowsToDo_ list, emptying + #nextRowsToDo_. Returns the number of rows transferred. + */ + int stepRowsToDo(); + + /// Return the number of rows on the #rowsToDo_ list + inline int numberRowsToDo() + { + return (numberRowsToDo_); + } + + /// Has row been changed? + inline bool rowChanged(int i) const + { + return (rowChanged_[i] & 1) != 0; + } + /// Mark row as not changed + inline void unsetRowChanged(int i) + { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] & (~1)); + } + /// Mark row as changed + inline void setRowChanged(int i) + { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] | (1)); + } + /// Mark row as changed and add to list of rows to process next + inline void addRow(int i) + { + if ((rowChanged_[i] & 1) == 0) { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] | (1)); + nextRowsToDo_[numberNextRowsToDo_++] = i; + } + } + /// Test if row is eligible for preprocessing + inline bool rowProhibited(int i) const + { + return (rowChanged_[i] & 2) != 0; + } + /*! \brief Test if row is eligible for preprocessing + + The difference between this method and #rowProhibited() is that this + method first tests #anyProhibited_ before examining the specific entry + for the specified row. + */ + inline bool rowProhibited2(int i) const + { + if (!anyProhibited_) + return false; + else + return (rowChanged_[i] & 2) != 0; + } + /// Mark row as ineligible for preprocessing + inline void setRowProhibited(int i) + { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] | (2)); + } + /*! \brief Test if row is marked as used + + This is for doing faster lookups to see where two rows have entries + in common. It can be used anywhere as long as it ends up zeroed out. + */ + inline bool rowUsed(int i) const + { + return (rowChanged_[i] & 4) != 0; + } + /// Mark row as used + inline void setRowUsed(int i) + { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] | (4)); + } + /// Mark row as unused + inline void unsetRowUsed(int i) + { + rowChanged_[i] = static_cast< unsigned char >(rowChanged_[i] & (~4)); + } + + /// Check if there are any prohibited rows or columns + inline bool anyProhibited() const + { + return anyProhibited_; + } + /// Set a flag for presence of prohibited rows or columns + inline void setAnyProhibited(bool val = true) + { + anyProhibited_ = val; + } + //@} +}; + +/*! \class CoinPostsolveMatrix + \brief Augments CoinPrePostsolveMatrix with information about the problem + that is only needed during postsolve. + + The notable point is that the matrix representation is threaded. The + representation is column-major and starts with the standard two pairs of + arrays: one pair to hold the row indices and coefficients, the second pair + to hold the column starting positions and lengths. But the row indices and + coefficients for a column do not necessarily occupy a contiguous block in + their respective arrays. Instead, a link array gives the position of the + next (row index,coefficient) pair. If the row index and value of a + coefficient a occupy position kp in their arrays, then the position of + the next coefficient a is found as kq = link[kp]. + + This threaded representation allows for efficient expansion of columns as + rows are reintroduced during postsolve transformations. The basic packed + structures are allocated to the expected size of the postsolved matrix, + and as new coefficients are added, their location is simply added to the + thread for the column. + + There is no provision to convert the threaded representation to a packed + representation. In the context of postsolve, it's not required. (You did + keep a copy of the original matrix, eh?) + + The constructors that take an OSI or ClpSimplex as a parameter really should + not be here, but for historical reasons they will likely remain for the + forseeable future. -- lh, 111202 -- +*/ +class CoinPostsolveMatrix : public CoinPrePostsolveMatrix { +public: + /*! \brief `Native' constructor + + This constructor creates an empty object which must then be loaded. + On the other hand, it doesn't assume that the client is an + OsiSolverInterface. + */ + CoinPostsolveMatrix(int ncols_alloc, int nrows_alloc, + CoinBigIndex nelems_alloc); + + /*! \brief Clp OSI constructor + + See Clp code for the definition. + */ + CoinPostsolveMatrix(ClpSimplex *si, + + int ncols0, + int nrows0, + CoinBigIndex nelems0, + + double maxmin_, + // end prepost members + + double *sol, + double *acts, + + unsigned char *colstat, + unsigned char *rowstat); + + /*! \brief Generic OSI constructor + + See OSI code for the definition. + */ + CoinPostsolveMatrix(OsiSolverInterface *si, + + int ncols0, + int nrows0, + CoinBigIndex nelems0, + + double maxmin_, + // end prepost members + + double *sol, + double *acts, + + unsigned char *colstat, + unsigned char *rowstat); + + /*! \brief Load an empty CoinPostsolveMatrix from a CoinPresolveMatrix + + This routine transfers the contents of the CoinPrePostsolveMatrix + object from the CoinPresolveMatrix object to the CoinPostsolveMatrix + object and completes initialisation of the CoinPostsolveMatrix object. + The empty shell of the CoinPresolveMatrix object is destroyed. + + The routine expects an empty CoinPostsolveMatrix object. If handed a loaded + object, a lot of memory will leak. + */ + void assignPresolveToPostsolve(CoinPresolveMatrix *&preObj); + + /// Destructor + ~CoinPostsolveMatrix(); + + /*! \name Column thread structures + + As mentioned in the class documentation, the entries for a given column + do not necessarily occupy a contiguous block of space. The #link_ array + is used to maintain the threading. There is one thread for each column, + and a single thread for all free entries in #hrow_ and #colels_. + + The allocated size of #link_ must be at least as large as the allocated + size of #hrow_ and #colels_. + */ + //@{ + + /*! \brief First entry in free entries thread */ + CoinBigIndex free_list_; + /// Allocated size of #link_ + CoinBigIndex maxlink_; + /*! \brief Thread array + + Within a thread, link_[k] points to the next entry in the thread. + */ + CoinBigIndex *link_; + + //@} + + /*! \name Debugging aids + + These arrays are allocated only when CoinPresolve is compiled with + PRESOLVE_DEBUG defined. They hold codes which track the reason that + a column or row is added to the problem during postsolve. + */ + //@{ + char *cdone_; + char *rdone_; + //@} + + /// debug + void check_nbasic(); +}; + +/*! \defgroup MtxManip Presolve Matrix Manipulation Functions + + Functions to work with the loosely packed and threaded packed matrix + structures used during presolve and postsolve. +*/ +//@{ + +/*! \relates CoinPrePostsolveMatrix + \brief Initialise linked list for major vector order in bulk storage +*/ + +void presolve_make_memlists(/*CoinBigIndex *starts,*/ int *lengths, + presolvehlink *link, int n); + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a major-dimension vector k has room for one more + coefficient. + + You can use this directly, or use the inline wrappers presolve_expand_col + and presolve_expand_row +*/ +bool presolve_expand_major(CoinBigIndex *majstrts, double *majels, + int *minndxs, int *majlens, + presolvehlink *majlinks, int nmaj, int k); + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a column (colx) in a column-major matrix has room for + one more coefficient +*/ + +inline bool presolve_expand_col(CoinBigIndex *mcstrt, double *colels, + int *hrow, int *hincol, + presolvehlink *clink, int ncols, int colx) +{ + return presolve_expand_major(mcstrt, colels, + hrow, hincol, clink, ncols, colx); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Make sure a row (rowx) in a row-major matrix has room for one + more coefficient +*/ + +inline bool presolve_expand_row(CoinBigIndex *mrstrt, double *rowels, + int *hcol, int *hinrow, + presolvehlink *rlink, int nrows, int rowx) +{ + return presolve_expand_major(mrstrt, rowels, + hcol, hinrow, rlink, nrows, rowx); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a minor index in a major vector. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will abort if the entry does not exist. Can be + used directly or via the inline wrappers presolve_find_row and + presolve_find_col. +*/ +inline CoinBigIndex presolve_find_minor(int tgt, + CoinBigIndex ks, CoinBigIndex ke, + const int *minndxs) +{ + CoinBigIndex k; + for (k = ks; k < ke; k++) +#ifndef NDEBUG + { + if (minndxs[k] == tgt) + return (k); + } + DIE("FIND_MINOR"); + + abort(); + return -1; +#else + { + if (minndxs[k] == tgt) + break; + } + return (k); +#endif +} + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a row in a column in a column-major matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row(int row, CoinBigIndex kcs, + CoinBigIndex kce, const int *hrow) +{ + return presolve_find_minor(row, kcs, kce, hrow); +} + +/*! \relates CoinPostsolveMatrix + \brief Find position of a column in a row in a row-major matrix. + + The routine returns the position \c k in \p hcol for the specified \p col. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_col(int col, CoinBigIndex krs, + CoinBigIndex kre, const int *hcol) +{ + return presolve_find_minor(col, krs, kre, hcol); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a minor index in a major vector. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. A return value of \p ke means the entry does not + exist. Can be used directly or via the inline wrappers + presolve_find_row1 and presolve_find_col1. +*/ +CoinBigIndex presolve_find_minor1(int tgt, CoinBigIndex ks, CoinBigIndex ke, + const int *minndxs); + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a row in a column in a column-major matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + A return value of \p kce means the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row1(int row, CoinBigIndex kcs, + CoinBigIndex kce, const int *hrow) +{ + return presolve_find_minor1(row, kcs, kce, hrow); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Find position of a column in a row in a row-major matrix. + + The routine returns the position \c k in \p hcol for the specified \p col. + A return value of \p kre means the entry does not exist. +*/ +inline CoinBigIndex presolve_find_col1(int col, CoinBigIndex krs, + CoinBigIndex kre, const int *hcol) +{ + return presolve_find_minor1(col, krs, kre, hcol); +} + +/*! \relates CoinPostsolveMatrix + \brief Find position of a minor index in a major vector in a threaded + matrix. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will abort if the entry does not exist. Can be + used directly or via the inline wrapper presolve_find_row2. +*/ +CoinBigIndex presolve_find_minor2(int tgt, CoinBigIndex ks, int majlen, + const int *minndxs, + const CoinBigIndex *majlinks); + +/*! \relates CoinPostsolveMatrix + \brief Find position of a row in a column in a column-major threaded + matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will abort if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row2(int row, CoinBigIndex kcs, int collen, + const int *hrow, + const CoinBigIndex *clinks) +{ + return presolve_find_minor2(row, kcs, collen, hrow, clinks); +} + +/*! \relates CoinPostsolveMatrix + \brief Find position of a minor index in a major vector in a threaded + matrix. + + The routine returns the position \c k in \p minndxs for the specified + minor index \p tgt. It will return -1 if the entry does not exist. + Can be used directly or via the inline wrappers presolve_find_row3. +*/ +CoinBigIndex presolve_find_minor3(int tgt, CoinBigIndex ks, int majlen, + const int *minndxs, + const CoinBigIndex *majlinks); + +/*! \relates CoinPostsolveMatrix + \brief Find position of a row in a column in a column-major threaded + matrix. + + The routine returns the position \c k in \p hrow for the specified \p row. + It will return -1 if the entry does not exist. +*/ +inline CoinBigIndex presolve_find_row3(int row, CoinBigIndex kcs, int collen, + const int *hrow, + const CoinBigIndex *clinks) +{ + return presolve_find_minor3(row, kcs, collen, hrow, clinks); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for a minor index from a major vector. + + Deletes the entry for \p minndx from the major vector \p majndx. + Specifically, the relevant entries are removed from the minor index + (\p minndxs) and coefficient (\p els) arrays and the vector length (\p + majlens) is decremented. Loose packing is maintained by swapping the last + entry in the row into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_major(int majndx, int minndx, + const CoinBigIndex *majstrts, + int *majlens, int *minndxs, double *els) +{ + const CoinBigIndex ks = majstrts[majndx]; + const CoinBigIndex ke = ks + majlens[majndx]; + + const CoinBigIndex kmi = presolve_find_minor(minndx, ks, ke, minndxs); + + minndxs[kmi] = minndxs[ke - 1]; + els[kmi] = els[ke - 1]; + majlens[majndx]--; + + return; +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete marked entries + + Removes the entries specified in \p marked, compressing the major vector + to maintain loose packing. \p marked is cleared in the process. +*/ +inline void presolve_delete_many_from_major(int majndx, char *marked, + const CoinBigIndex *majstrts, + int *majlens, int *minndxs, double *els) +{ + const CoinBigIndex ks = majstrts[majndx]; + const CoinBigIndex ke = ks + majlens[majndx]; + CoinBigIndex put = ks; + for (CoinBigIndex k = ks; k < ke; k++) { + int iMinor = minndxs[k]; + if (!marked[iMinor]) { + minndxs[put] = iMinor; + els[put++] = els[k]; + } else { + marked[iMinor] = 0; + } + } + majlens[majndx] = static_cast< int >(put - ks); + return; +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for row \p row from column \p col in a + column-major matrix + + Deletes the entry for \p row from the major vector for \p col. + Specifically, the relevant entries are removed from the row index (\p + hrow) and coefficient (\p colels) arrays and the vector length (\p + hincol) is decremented. Loose packing is maintained by swapping the last + entry in the row into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_col(int row, int col, + const CoinBigIndex *mcstrt, + int *hincol, int *hrow, double *colels) +{ + presolve_delete_from_major(col, row, mcstrt, hincol, hrow, colels); +} + +/*! \relates CoinPrePostsolveMatrix + \brief Delete the entry for column \p col from row \p row in a + row-major matrix + + Deletes the entry for \p col from the major vector for \p row. + Specifically, the relevant entries are removed from the column index (\p + hcol) and coefficient (\p rowels) arrays and the vector length (\p + hinrow) is decremented. Loose packing is maintained by swapping the last + entry in the column into the position occupied by the deleted entry. +*/ +inline void presolve_delete_from_row(int row, int col, + const CoinBigIndex *mrstrt, + int *hinrow, int *hcol, double *rowels) +{ + presolve_delete_from_major(row, col, mrstrt, hinrow, hcol, rowels); +} + +/*! \relates CoinPostsolveMatrix + \brief Delete the entry for a minor index from a major vector in a + threaded matrix. + + Deletes the entry for \p minndx from the major vector \p majndx. + Specifically, the relevant entries are removed from the minor index (\p + minndxs) and coefficient (\p els) arrays and the vector length (\p + majlens) is decremented. The thread for the major vector is relinked + around the deleted entry and the space is returned to the free list. +*/ +void presolve_delete_from_major2(int majndx, int minndx, + CoinBigIndex *majstrts, int *majlens, + int *minndxs, CoinBigIndex *majlinks, + CoinBigIndex *free_listp); + +/*! \relates CoinPostsolveMatrix + \brief Delete the entry for row \p row from column \p col in a + column-major threaded matrix + + Deletes the entry for \p row from the major vector for \p col. + Specifically, the relevant entries are removed from the row index (\p + hrow) and coefficient (\p colels) arrays and the vector length (\p + hincol) is decremented. The thread for the major vector is relinked + around the deleted entry and the space is returned to the free list. +*/ +inline void presolve_delete_from_col2(int row, int col, CoinBigIndex *mcstrt, + int *hincol, int *hrow, + CoinBigIndex *clinks, CoinBigIndex *free_listp) +{ + presolve_delete_from_major2(col, row, mcstrt, hincol, hrow, clinks, free_listp); +} + +//@} + +/*! \defgroup PresolveUtilities Presolve Utility Functions + + Utilities used by multiple presolve transform objects. +*/ +//@{ + +/*! \brief Duplicate a major-dimension vector; optionally omit the entry + with minor index \p tgt. + + Designed to copy a major-dimension vector from the paired coefficient + (\p elems) and minor index (\p indices) arrays used in the standard + packed matrix representation. Copies \p length entries starting at + \p offset. + + If \p tgt is specified, the entry with minor index == \p tgt is + omitted from the copy. +*/ +double *presolve_dupmajor(const double *elems, const int *indices, + int length, CoinBigIndex offset, int tgt = -1); + +/// Initialize a vector with random numbers +void coin_init_random_vec(double *work, int n); + +//@} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMonitor.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMonitor.hpp new file mode 100644 index 000000000..9b8dfc4e0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveMonitor.hpp @@ -0,0 +1,105 @@ + +#ifndef CoinPresolveMonitor_H +#define CoinPresolveMonitor_H + +/*! + \brief Monitor a row or column for modification + + The purpose of this class is to monitor a row or column for modifications + during presolve and postsolve. Each object can monitor one row or + column. The initial copy of the row or column is loaded by the constructor. + Each subsequent call to checkAndTell() compares the current state of the row + or column with the stored state and reports any modifications. + + Internally the row or column is held as a CoinPackedVector so that it's + possible to follow a row or column through presolve (CoinPresolveMatrix) + and postsolve (CoinPostsolveMatrix). + + Do not underestimate the amount of work required here. Extracting a row from + the CoinPostsolve matrix requires a scan of every element in the matrix. + That's one scan by the constructor and one scan with every call to modify. + But that's precisely why it's virtually impossible to debug presolve without + aids. + + Parameter overloads for CoinPresolveMatrix and CoinPostsolveMatrix are a + little clumsy, but not a problem in use. The alternative is to add methods + to the CoinPresolveMatrix and CoinPostsolveMatrix classes that will only be + used for debugging. That's not too attractive either. +*/ +class CoinPresolveMonitor { +public: + /*! \brief Default constructor + + Creates an empty monitor. + */ + CoinPresolveMonitor(); + + /*! \brief Initialise from a CoinPresolveMatrix + + Load the initial row or column from a CoinPresolveMatrix. Set \p isRow + true for a row, false for a column. + */ + CoinPresolveMonitor(const CoinPresolveMatrix *mtx, bool isRow, int k); + + /*! \brief Initialise from a CoinPostsolveMatrix + + Load the initial row or column from a CoinPostsolveMatrix. Set \p isRow + true for a row, false for a column. + */ + CoinPresolveMonitor(const CoinPostsolveMatrix *mtx, bool isRow, int k); + + /*! \brief Compare the present row or column against the stored copy and + report differences. + + Load the current row or column from a CoinPresolveMatrix and compare. + Differences are printed to std::cout. + */ + void checkAndTell(const CoinPresolveMatrix *mtx); + + /*! \brief Compare the present row or column against the stored copy and + report differences. + + Load the current row or column from a CoinPostsolveMatrix and compare. + Differences are printed to std::cout. + */ + void checkAndTell(const CoinPostsolveMatrix *mtx); + +private: + /// Extract a row from a CoinPresolveMatrix + CoinPackedVector *extractRow(int i, const CoinPresolveMatrix *mtx) const; + + /// Extract a column from a CoinPresolveMatrix + CoinPackedVector *extractCol(int j, const CoinPresolveMatrix *mtx) const; + + /// Extract a row from a CoinPostsolveMatrix + CoinPackedVector *extractRow(int i, const CoinPostsolveMatrix *mtx) const; + + /// Extract a column from a CoinPostsolveMatrix + CoinPackedVector *extractCol(int j, const CoinPostsolveMatrix *mtx) const; + + /// Worker method underlying the public checkAndTell methods. + void checkAndTell(CoinPackedVector *curVec, double lb, double ub); + + /// True to monitor a row, false to monitor a column + bool isRow_; + + /// Row or column index + int ndx_; + + /*! The original row or column + + Sorted in increasing order of indices. + */ + CoinPackedVector *origVec_; + + /// Original row or column lower bound + double lb_; + + /// Original row or column upper bound + double ub_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolvePsdebug.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolvePsdebug.hpp new file mode 100644 index 000000000..87fa38bbe --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolvePsdebug.hpp @@ -0,0 +1,169 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolvePsdebug_H +#define CoinPresolvePsdebug_H + +/* + The current idea of the relation between PRESOLVE_DEBUG and + PRESOLVE_CONSISTENCY is that PRESOLVE_CONSISTENCY triggers the consistency + checks and PRESOLVE_DEBUG triggers consistency checks and output. + This isn't always true in the code, but that's the goal. Really, + the whole compile-time scheme should be replaced with something more + user-friendly (control variables that can be changed during the run). + + Also floating about are PRESOLVE_SUMMARY and COIN_PRESOLVE_TUNING. + -- lh, 111208 -- +*/ +/*! \defgroup PresolveDebugFunctions Presolve Debug Functions + + These functions implement consistency checks on data structures involved + in presolve and postsolve and on the components of the lp solution. + + To use these functions, include CoinPresolvePsdebug.hpp in your file and + define the compile-time constants PRESOLVE_SUMMARY, PRESOLVE_DEBUG, and + PRESOLVE_CONSISTENCY. A value is needed (i.e., PRESOLVE_DEBUG=1). + In a few places, higher values will get you a bit more output. + + ******** + + Define the symbols PRESOLVE_DEBUG and PRESOLVE_CONSISTENCY on the configure + command line (use ADD_CXXFLAGS), in a Makefile, or similar and do a full + rebuild (including any presolve driver code). If the symbols are not + consistently nonzero across *all* presolve code, you'll get something + between garbage and a core dump! Debugging adds messages to CoinMessage + and allocates and maintains arrays that hold debug information. + + That said, given that you've configured and built with PRESOLVE_DEBUG and + PRESOLVE_CONSISTENCY nonzero everywhere, it's safe to adjust PRESOLVE_DEBUG + to values in the range 1..n in individual files to increase or decrease the + amount of output. + + The suggested approach for PRESOLVE_DEBUG is to define it to 1 in the build + and then increase it in individual presolve code files to get more detail. + + ******** +*/ +//@{ + +/*! \relates CoinPresolveMatrix + \brief Check column-major and/or row-major matrices for duplicate + entries in the major vectors. + + By default, scans both the column- and row-major matrices. Set doCol (doRow) + to false to suppress the column (row) scan. +*/ +void presolve_no_dups(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true); + +/*! \relates CoinPresolveMatrix + \brief Check the links which track storage order for major vectors in + the bulk storage area. + + By default, scans both the column- and row-major matrix. Set doCol = false to + suppress the column-major scan. Set doRow = false to suppres the row-major + scan. +*/ +void presolve_links_ok(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true); + +/*! \relates CoinPresolveMatrix + \brief Check for explicit zeros in the column- and/or row-major matrices. + + By default, scans both the column- and row-major matrices. Set doCol (doRow) + to false to suppress the column (row) scan. +*/ +void presolve_no_zeros(const CoinPresolveMatrix *preObj, + bool doCol = true, bool doRow = true); + +/*! \relates CoinPresolveMatrix + \brief Checks for equivalence of the column- and row-major matrices. + + Normally the routine will test for coefficient presence and value. Set + \p chkvals to false to suppress the check for equal value. +*/ +void presolve_consistent(const CoinPresolveMatrix *preObj, + bool chkvals = true); + +/*! \relates CoinPostsolveMatrix + \brief Checks that column threads agree with column lengths +*/ +void presolve_check_threads(const CoinPostsolveMatrix *obj); + +/*! \relates CoinPostsolveMatrix + \brief Checks the free list + + Scans the thread of free locations in the bulk store and checks that all + entries are reasonable (0 <= index < bulk0_). If chkElemCnt is true, it + also checks that the total number of entries in the matrix plus the + locations on the free list total to the size of the bulk store. Postsolve + routines do not maintain an accurate element count, but this is useful + for checking a newly constructed postsolve matrix. +*/ +void presolve_check_free_list(const CoinPostsolveMatrix *obj, + bool chkElemCnt = false); + +/*! \relates CoinPostsolveMatrix + \brief Check stored reduced costs for accuracy and consistency with + variable status. + + The routine will check the value of the reduced costs for architectural + variables (CoinPrePostsolveMatrix::rcosts_). It performs an accuracy check + by recalculating the reduced cost from scratch. It will also check the + value for consistency with the status information in + CoinPrePostsolveMatrix::colstat_. +*/ +void presolve_check_reduced_costs(const CoinPostsolveMatrix *obj); + +/*! \relates CoinPostsolveMatrix + \brief Check the dual variables for consistency with row activity. + + The routine checks that the value of the dual variable is consistent + with the state of the constraint (loose, tight at lower bound, or tight at + upper bound). +*/ +void presolve_check_duals(const CoinPostsolveMatrix *postObj); + +/*! \relates CoinPresolveMatrix + \brief Check primal solution and architectural variable status. + + The architectural variables can be checked for bogus values, feasibility, + and valid status. The row activity is checked for bogus values, accuracy, + and feasibility. By default, row activity is not checked (presolve is + sloppy about maintaining it). See the definitions in + CoinPresolvePsdebug.cpp for more information. +*/ +void presolve_check_sol(const CoinPresolveMatrix *preObj, + int chkColSol = 2, int chkRowAct = 1, + int chkStatus = 1); + +/*! \relates CoinPostsolveMatrix + \brief Check primal solution and architectural variable status. + + The architectural variables can be checked for bogus values, feasibility, + and valid status. The row activity is checked for bogus values, accuracy, + and feasibility. See the definitions in CoinPresolvePsdebug.cpp for more + information. +*/ +void presolve_check_sol(const CoinPostsolveMatrix *postObj, + int chkColSol = 2, int chkRowAct = 2, + int chkStatus = 1); + +/*! \relates CoinPresolveMatrix + \brief Check for the proper number of basic variables. +*/ +void presolve_check_nbasic(const CoinPresolveMatrix *preObj); + +/*! \relates CoinPostsolveMatrix + \brief Check for the proper number of basic variables. +*/ +void presolve_check_nbasic(const CoinPostsolveMatrix *postObj); + +//@} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSingleton.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSingleton.hpp new file mode 100644 index 000000000..a8da83df2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSingleton.hpp @@ -0,0 +1,115 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveSingleton_H +#define CoinPresolveSingleton_H +#define SLACK_DOUBLETON 2 +#define SLACK_SINGLETON 8 + +/*! + \file +*/ + +//const int MAX_SLACK_DOUBLETONS = 1000; + +/*! \class slack_doubleton_action + \brief Convert an explicit bound constraint to a column bound + + This transform looks for explicit bound constraints for a variable and + transfers the bound to the appropriate column bound array. + The constraint is removed from the constraint system. +*/ +class slack_doubleton_action : public CoinPresolveAction { + struct action { + double clo; + double cup; + + double rlo; + double rup; + + double coeff; + + int col; + int row; + }; + + const int nactions_; + const action *const actions_; + + slack_doubleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("slack_doubleton_action"); } + + /*! \brief Convert explicit bound constraints to column bounds. + + Not now There is a hard limit (#MAX_SLACK_DOUBLETONS) on the number of + constraints processed in a given call. \p notFinished is set to true + if candidates remain. + */ + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + bool ¬Finished); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~slack_doubleton_action() { deleteAction(actions_, action *); } +}; +/*! \class slack_singleton_action + \brief For variables with one entry + + If we have a variable with one entry and no cost then we can + transform the row from E to G etc. + If there is a row objective region then we may be able to do + this even with a cost. +*/ +class slack_singleton_action : public CoinPresolveAction { + struct action { + double clo; + double cup; + + double rlo; + double rup; + + double coeff; + + int col; + int row; + }; + + const int nactions_; + const action *const actions_; + + slack_singleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("slack_singleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + double *rowObjective); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~slack_singleton_action() { deleteAction(actions_, action *); } +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSubst.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSubst.hpp new file mode 100644 index 000000000..8cf9fed63 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveSubst.hpp @@ -0,0 +1,103 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveSubst_H +#define CoinPresolveSubst_H + +/*! + \file +*/ + +#define SUBST_ROW 21 + +#include "CoinPresolveMatrix.hpp" + +/*! \class subst_constraint_action + \brief Detect and process implied free variables + + Consider a variable x. Suppose that we can find an equality such that the + bound on the equality, combined with + the bounds on the other variables involved in the equality, are such that + even the worst case values of the other variables still imply bounds for x + which are tighter than the variable's original bounds. Since x can never + reach its upper or lower bounds, it is an implied free variable. By solving + the equality for x and substituting for x in every other constraint + entangled with x, we can make x into a column singleton. Now x is an implied + free column singleton and both x and the equality can be removed. + + A similar transform for the case where the variable is a natural column + singleton is handled by #implied_free_action. In the current presolve + architecture, #implied_free_action is responsible for detecting implied free + variables that are natural column singletons or can be reduced to column + singletons. #implied_free_action calls subst_constraint_action to process + variables that must be reduced to column singletons. +*/ +class subst_constraint_action : public CoinPresolveAction { +private: + subst_constraint_action(); + subst_constraint_action(const subst_constraint_action &rhs); + subst_constraint_action &operator=(const subst_constraint_action &rhs); + + struct action { + double *rlos; + double *rups; + + double *coeffxs; + int *rows; + + int *ninrowxs; + int *rowcolsxs; + double *rowelsxs; + + const double *costsx; + int col; + int rowy; + + int nincol; + }; + + const int nactions_; + // actions_ is owned by the class and must be deleted at destruction + const action *const actions_; + + subst_constraint_action(int nactions, + action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const int *implied_free, + const int *which, + int numberFree, + const CoinPresolveAction *next, + int fill_level); + static const CoinPresolveAction *presolveX(CoinPresolveMatrix *prob, + const CoinPresolveAction *next, + int fillLevel); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~subst_constraint_action(); +}; + +/*static*/ void implied_bounds(const double *els, + const double *clo, const double *cup, + const int *hcol, + CoinBigIndex krs, CoinBigIndex kre, + double *maxupp, double *maxdownp, + int jcol, + double rlo, double rup, + double *iclb, double *icub); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTighten.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTighten.hpp new file mode 100644 index 000000000..c648135d8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTighten.hpp @@ -0,0 +1,58 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveTighten_H +#define CoinPresolveTighten_H + +#include "CoinPresolveMatrix.hpp" + +// This action has no separate class; +// instead, it decides which columns can be made fixed +// and calls make_fixed_action::presolve. +const CoinPresolveAction *tighten_zero_cost(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +#define DO_TIGHTEN 30 + +class do_tighten_action : public CoinPresolveAction { + do_tighten_action(); + do_tighten_action(const do_tighten_action &rhs); + do_tighten_action &operator=(const do_tighten_action &rhs); + + struct action { + int *rows; + double *lbound; + double *ubound; + int col; + int nrows; + int direction; // just for assertions + }; + + const int nactions_; + const action *const actions_; + + do_tighten_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const; + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~do_tighten_action(); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTripleton.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTripleton.hpp new file mode 100644 index 000000000..a07172e76 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveTripleton.hpp @@ -0,0 +1,69 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveTripleton_H +#define CoinPresolveTripleton_H +#define TRIPLETON 11 +/** We are only going to do this if it does not increase number of elements?. + It could be generalized to more than three but it seems unlikely it would + help. + + As it is adapted from doubleton icoly is one dropped. + */ +class tripleton_action : public CoinPresolveAction { +public: + struct action { + int icolx; + int icolz; + int row; + + int icoly; + double cloy; + double cupy; + double costy; + double clox; + double cupx; + double costx; + + double rlo; + double rup; + + double coeffx; + double coeffy; + double coeffz; + + double *colel; + + int ncolx; + int ncoly; + }; + + const int nactions_; + const action *const actions_; + +private: + tripleton_action(int nactions, + const action *actions, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nactions_(nactions) + , actions_(actions) + { + } + +public: + const char *name() const { return ("tripleton_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~tripleton_action(); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveUseless.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveUseless.hpp new file mode 100644 index 000000000..bcd6c5271 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveUseless.hpp @@ -0,0 +1,63 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveUseless_H +#define CoinPresolveUseless_H +#define USELESS 20 + +class useless_constraint_action : public CoinPresolveAction { + struct action { + double rlo; + double rup; + const int *rowcols; + const double *rowels; + int row; + int ninrow; + }; + + const int nactions_; + const action *const actions_; + + useless_constraint_action(int nactions, + const action *actions, + const CoinPresolveAction *next); + +public: + const char *name() const; + + // These rows are asserted to be useless, + // that is, given a solution the row activity + // must be in range. + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + const int *useless_rows, + int nuseless_rows, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~useless_constraint_action(); +}; + +/*! \relates useless_constraint_action + \brief Scan constraints looking for useless constraints + + A front end to identify useless constraints and hand them to + useless_constraint_action::presolve() for processing. + + In a bit more detail, the routine implements a greedy algorithm that + identifies a set of necessary constraints. A constraint is necessary if it + implies a tighter bound on a variable than the original column bound. These + tighter column bounds are then used to calculate row activity and identify + constraints that are useless given the presence of the necessary + constraints. +*/ + +const CoinPresolveAction *testRedundant(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveZeros.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveZeros.hpp new file mode 100644 index 000000000..eb894ca01 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinPresolveZeros.hpp @@ -0,0 +1,65 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinPresolveZeros_H +#define CoinPresolveZeros_H + +/*! \file + + Drop/reintroduce explicit zeros. +*/ + +#define DROP_ZERO 8 + +/*! \brief Tracking information for an explicit zero coefficient + + \todo Why isn't this a nested class in drop_zero_coefficients_action? + That would match the structure of other presolve classes. +*/ + +struct dropped_zero { + int row; + int col; +}; + +/*! \brief Removal of explicit zeros + + The presolve action for this class removes explicit zeros from the constraint + matrix. The postsolve action puts them back. +*/ +class drop_zero_coefficients_action : public CoinPresolveAction { + + const int nzeros_; + const dropped_zero *const zeros_; + + drop_zero_coefficients_action(int nzeros, + const dropped_zero *zeros, + const CoinPresolveAction *next) + : CoinPresolveAction(next) + , nzeros_(nzeros) + , zeros_(zeros) + { + } + +public: + const char *name() const { return ("drop_zero_coefficients_action"); } + + static const CoinPresolveAction *presolve(CoinPresolveMatrix *prob, + int *checkcols, + int ncheckcols, + const CoinPresolveAction *next); + + void postsolve(CoinPostsolveMatrix *prob) const; + + virtual ~drop_zero_coefficients_action() { deleteAction(zeros_, dropped_zero *); } +}; + +const CoinPresolveAction *drop_zero_coefficients(CoinPresolveMatrix *prob, + const CoinPresolveAction *next); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinRational.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinRational.hpp new file mode 100644 index 000000000..4a7ee3701 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinRational.hpp @@ -0,0 +1,43 @@ +// Authors: Matthew Saltzman and Ted Ralphs +// Copyright 2015, Matthew Saltzman and Ted Ralphs +// Licensed under the Eclipse Public License 1.0 + +#ifndef CoinRational_H +#define CoinRational_H + +#include + +//Small class for rational numbers +class CoinRational { + +public: + long getDenominator() { return denominator_; } + long getNumerator() { return numerator_; } + + CoinRational() + : numerator_(0) + , denominator_(1) {}; + + CoinRational(long n, long d) + : numerator_(n) + , denominator_(d) {}; + + CoinRational(double val, double maxdelta, long maxdnom) + { + if (!nearestRational_(val, maxdelta, maxdnom)) { + numerator_ = 0; + denominator_ = 1; + } + }; + +private: + long numerator_; + long denominator_; + + bool nearestRational_(double val, double maxdelta, long maxdnom); +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSearchTree.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSearchTree.hpp new file mode 100644 index 000000000..2599841da --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSearchTree.hpp @@ -0,0 +1,523 @@ +/* $Id$ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSearchTree_H +#define CoinSearchTree_H + +#include +#include +#include +#include + +#include "CoinFinite.hpp" +#include "CoinHelperFunctions.hpp" + +// #define DEBUG_PRINT + +//############################################################################# + +class BitVector128 { + friend bool operator<(const BitVector128 &b0, const BitVector128 &b1); + +private: + unsigned int bits_[4]; + +public: + BitVector128(); + BitVector128(unsigned int bits[4]); + ~BitVector128() {} + void set(unsigned int bits[4]); + void setBit(int i); + void clearBit(int i); + std::string str() const; +}; + +bool operator<(const BitVector128 &b0, const BitVector128 &b1); + +//############################################################################# + +/** A class from which the real tree nodes should be derived from. Some of the + data that undoubtedly exist in the real tree node is replicated here for + fast access. This class is used in the various comparison functions. */ +class CoinTreeNode { +protected: + CoinTreeNode() + : depth_(-1) + , fractionality_(-1) + , quality_(-COIN_DBL_MAX) + , true_lower_bound_(-COIN_DBL_MAX) + , preferred_() + { + } + CoinTreeNode(int d, + int f = -1, + double q = -COIN_DBL_MAX, + double tlb = -COIN_DBL_MAX, + BitVector128 p = BitVector128()) + : depth_(d) + , fractionality_(f) + , quality_(q) + , true_lower_bound_(tlb) + , preferred_(p) + { + } + CoinTreeNode(const CoinTreeNode &x) + : depth_(x.depth_) + , fractionality_(x.fractionality_) + , quality_(x.quality_) + , true_lower_bound_(x.true_lower_bound_) + , preferred_(x.preferred_) + { + } + CoinTreeNode &operator=(const CoinTreeNode &x) + { + if (this != &x) { + depth_ = x.depth_; + fractionality_ = x.fractionality_; + quality_ = x.quality_; + true_lower_bound_ = x.true_lower_bound_; + preferred_ = x.preferred_; + } + return *this; + } + +private: + /// The depth of the node in the tree + int depth_; + /** A measure of fractionality, e.g., the number of unsatisfied + integrality requirements */ + int fractionality_; + /** Some quality for the node. For normal branch-and-cut problems the LP + relaxation value will do just fine. It is probably an OK approximation + even if column generation is done. */ + double quality_; + /** A true lower bound on the node. May be -infinity. For normal + branch-and-cut problems the LP relaxation value is OK. It is different + when column generation is done. */ + double true_lower_bound_; + /** */ + BitVector128 preferred_; + +public: + virtual ~CoinTreeNode() {} + + inline int getDepth() const { return depth_; } + inline int getFractionality() const { return fractionality_; } + inline double getQuality() const { return quality_; } + inline double getTrueLB() const { return true_lower_bound_; } + inline BitVector128 getPreferred() const { return preferred_; } + + inline void setDepth(int d) { depth_ = d; } + inline void setFractionality(int f) { fractionality_ = f; } + inline void setQuality(double q) { quality_ = q; } + inline void setTrueLB(double tlb) { true_lower_bound_ = tlb; } + inline void setPreferred(BitVector128 p) { preferred_ = p; } +}; + +//============================================================================== + +class CoinTreeSiblings { +private: + CoinTreeSiblings(); + CoinTreeSiblings &operator=(const CoinTreeSiblings &); + +private: + int current_; + int numSiblings_; + CoinTreeNode **siblings_; + +public: + CoinTreeSiblings(const int n, CoinTreeNode **nodes) + : current_(0) + , numSiblings_(n) + , siblings_(new CoinTreeNode *[n]) + { + CoinDisjointCopyN(nodes, n, siblings_); + } + CoinTreeSiblings(const CoinTreeSiblings &s) + : current_(s.current_) + , numSiblings_(s.numSiblings_) + , siblings_(new CoinTreeNode *[s.numSiblings_]) + { + CoinDisjointCopyN(s.siblings_, s.numSiblings_, siblings_); + } + ~CoinTreeSiblings() { delete[] siblings_; } + inline CoinTreeNode *currentNode() const { return siblings_[current_]; } + /** returns false if cannot be advanced */ + inline bool advanceNode() { return ++current_ != numSiblings_; } + inline int toProcess() const { return numSiblings_ - current_; } + inline int size() const { return numSiblings_; } + inline void printPref() const + { + for (int i = 0; i < numSiblings_; ++i) { + std::string pref = siblings_[i]->getPreferred().str(); + printf("prefs of sibligs: sibling[%i]: %s\n", i, pref.c_str()); + } + } +}; + +//############################################################################# + +/** Function objects to compare search tree nodes. The comparison function + must return true if the first argument is "better" than the second one, + i.e., it should be processed first. */ +/*@{*/ +/** Depth First Search. */ +struct CoinSearchTreeComparePreferred { + static inline const char *name() { return "CoinSearchTreeComparePreferred"; } + inline bool operator()(const CoinTreeSiblings *x, + const CoinTreeSiblings *y) const + { + const CoinTreeNode *xNode = x->currentNode(); + const CoinTreeNode *yNode = y->currentNode(); + const BitVector128 xPref = xNode->getPreferred(); + const BitVector128 yPref = yNode->getPreferred(); + bool retval = true; + if (xPref < yPref) { + retval = true; + } else if (yPref < xPref) { + retval = false; + } else { + retval = xNode->getQuality() < yNode->getQuality(); + } +#ifdef DEBUG_PRINT + printf("Comparing xpref (%s) and ypref (%s) : %s\n", + xpref.str().c_str(), ypref.str().c_str(), retval ? "T" : "F"); +#endif + return retval; + } +}; + +//----------------------------------------------------------------------------- +/** Depth First Search. */ +struct CoinSearchTreeCompareDepth { + static inline const char *name() { return "CoinSearchTreeCompareDepth"; } + inline bool operator()(const CoinTreeSiblings *x, + const CoinTreeSiblings *y) const + { +#if 1 + return x->currentNode()->getDepth() >= y->currentNode()->getDepth(); +#else + if (x->currentNode()->getDepth() > y->currentNode()->getDepth()) + return 1; + if (x->currentNode()->getDepth() == y->currentNode()->getDepth() && x->currentNode()->getQuality() <= y->currentNode()->getQuality()) + return 1; + return 0; +#endif + } +}; + +//----------------------------------------------------------------------------- +/* Breadth First Search */ +struct CoinSearchTreeCompareBreadth { + static inline const char *name() { return "CoinSearchTreeCompareBreadth"; } + inline bool operator()(const CoinTreeSiblings *x, + const CoinTreeSiblings *y) const + { + return x->currentNode()->getDepth() < y->currentNode()->getDepth(); + } +}; + +//----------------------------------------------------------------------------- +/** Best first search */ +struct CoinSearchTreeCompareBest { + static inline const char *name() { return "CoinSearchTreeCompareBest"; } + inline bool operator()(const CoinTreeSiblings *x, + const CoinTreeSiblings *y) const + { + return x->currentNode()->getQuality() < y->currentNode()->getQuality(); + } +}; + +//############################################################################# + +class CoinSearchTreeBase { +private: + CoinSearchTreeBase(const CoinSearchTreeBase &); + CoinSearchTreeBase &operator=(const CoinSearchTreeBase &); + +protected: + std::vector< CoinTreeSiblings * > candidateList_; + int numInserted_; + int size_; + +protected: + CoinSearchTreeBase() + : candidateList_() + , numInserted_(0) + , size_(0) + { + } + + virtual void realpop() = 0; + virtual void realpush(CoinTreeSiblings *s) = 0; + virtual void fixTop() = 0; + +public: + virtual ~CoinSearchTreeBase() {} + virtual const char *compName() const = 0; + + inline const std::vector< CoinTreeSiblings * > &getCandidates() const + { + return candidateList_; + } + inline bool empty() const { return candidateList_.empty(); } + inline int size() const { return size_; } + inline int numInserted() const { return numInserted_; } + inline CoinTreeNode *top() const + { + if (size_ == 0 || candidateList_.size() == 0) + return NULL; +#ifdef DEBUG_PRINT + char output[44]; + output[43] = 0; + candidateList_.front()->currentNode()->getPreferred().print(output); + printf("top's pref: %s\n", output); +#endif + return candidateList_.front()->currentNode(); + } + /** pop will advance the \c next pointer among the siblings on the top and + then moves the top to its correct position. #realpop is the method + that actually removes the element from the heap */ + inline void pop() + { + CoinTreeSiblings *s = candidateList_.front(); + if (!s->advanceNode()) { + realpop(); + delete s; + } else { + fixTop(); + } + --size_; + } + inline void push(int numNodes, CoinTreeNode **nodes, + const bool incrInserted = true) + { + CoinTreeSiblings *s = new CoinTreeSiblings(numNodes, nodes); + realpush(s); + if (incrInserted) { + numInserted_ += numNodes; + } + size_ += numNodes; + } + inline void push(const CoinTreeSiblings &sib, + const bool incrInserted = true) + { + CoinTreeSiblings *s = new CoinTreeSiblings(sib); +#ifdef DEBUG_PRINT + s->printPref(); +#endif + realpush(s); + if (incrInserted) { + numInserted_ += sib.toProcess(); + } + size_ += sib.toProcess(); + } +}; + +//############################################################################# + +// #define CAN_TRUST_STL_HEAP +#ifdef CAN_TRUST_STL_HEAP + +template < class Comp > +class CoinSearchTree : public CoinSearchTreeBase { +private: + Comp comp_; + +protected: + virtual void realpop() + { + candidateList_.pop_back(); + } + virtual void fixTop() + { + CoinTreeSiblings *s = top(); + realpop(); + push(s, false); + } + virtual void realpush(CoinTreeSiblings *s) + { + nodes_.push_back(s); + std::push_heap(candidateList_.begin(), candidateList_.end(), comp_); + } + +public: + CoinSearchTree() + : CoinSearchTreeBase() + , comp_() + { + } + CoinSearchTree(const CoinSearchTreeBase &t) + : CoinSearchTreeBase() + , comp_() + { + candidateList_ = t.getCandidates(); + std::make_heap(candidateList_.begin(), candidateList_.end(), comp_); + numInserted_ = t.numInserted_; + size_ = t.size_; + } + ~CoinSearchTree() {} + const char *compName() const { return Comp::name(); } +}; + +#else + +template < class Comp > +class CoinSearchTree : public CoinSearchTreeBase { +private: + Comp comp_; + +protected: + virtual void realpop() + { + candidateList_[0] = candidateList_.back(); + candidateList_.pop_back(); + fixTop(); + } + /** After changing data in the top node, fix the heap */ + virtual void fixTop() + { + const size_t size = candidateList_.size(); + if (size > 1) { + CoinTreeSiblings **candidates = &candidateList_[0]; + CoinTreeSiblings *s = candidates[0]; + --candidates; + size_t pos = 1; + size_t ch; + for (ch = 2; ch < size; pos = ch, ch *= 2) { + if (comp_(candidates[ch + 1], candidates[ch])) + ++ch; + if (comp_(s, candidates[ch])) + break; + candidates[pos] = candidates[ch]; + } + if (ch == size) { + if (comp_(candidates[ch], s)) { + candidates[pos] = candidates[ch]; + pos = ch; + } + } + candidates[pos] = s; + } + } + virtual void realpush(CoinTreeSiblings *s) + { + candidateList_.push_back(s); + CoinTreeSiblings **candidates = &candidateList_[0]; + --candidates; + size_t pos = candidateList_.size(); + size_t ch; + for (ch = pos / 2; ch != 0; pos = ch, ch /= 2) { + if (comp_(candidates[ch], s)) + break; + candidates[pos] = candidates[ch]; + } + candidates[pos] = s; + } + +public: + CoinSearchTree() + : CoinSearchTreeBase() + , comp_() + { + } + CoinSearchTree(const CoinSearchTreeBase &t) + : CoinSearchTreeBase() + , comp_() + { + candidateList_ = t.getCandidates(); + std::sort(candidateList_.begin(), candidateList_.end(), comp_); + numInserted_ = t.numInserted(); + size_ = t.size(); + } + virtual ~CoinSearchTree() {} + const char *compName() const { return Comp::name(); } +}; + +#endif + +//############################################################################# + +enum CoinNodeAction { + CoinAddNodeToCandidates, + CoinTestNodeForDiving, + CoinDiveIntoNode +}; + +class CoinSearchTreeManager { +private: + CoinSearchTreeManager(const CoinSearchTreeManager &); + CoinSearchTreeManager &operator=(const CoinSearchTreeManager &); + +private: + CoinSearchTreeBase *candidates_; + int numSolution; + /** Whether there is an upper bound or not. The upper bound may have come + as input, not necessarily from a solution */ + bool hasUB_; + + /** variable used to test whether we need to reevaluate search strategy */ + bool recentlyReevaluatedSearchStrategy_; + +public: + CoinSearchTreeManager() + : candidates_(NULL) + , numSolution(0) + , recentlyReevaluatedSearchStrategy_(true) + { + } + virtual ~CoinSearchTreeManager() + { + delete candidates_; + } + + inline void setTree(CoinSearchTreeBase *t) + { + delete candidates_; + candidates_ = t; + } + inline CoinSearchTreeBase *getTree() const + { + return candidates_; + } + + inline bool empty() const { return candidates_->empty(); } + inline size_t size() const { return candidates_->size(); } + inline size_t numInserted() const { return candidates_->numInserted(); } + inline CoinTreeNode *top() const { return candidates_->top(); } + inline void pop() { candidates_->pop(); } + inline void push(CoinTreeNode *node, const bool incrInserted = true) + { + candidates_->push(1, &node, incrInserted); + } + inline void push(const CoinTreeSiblings &s, const bool incrInserted = true) + { + candidates_->push(s, incrInserted); + } + inline void push(const int n, CoinTreeNode **nodes, + const bool incrInserted = true) + { + candidates_->push(n, nodes, incrInserted); + } + + inline CoinTreeNode *bestQualityCandidate() const + { + return candidates_->top(); + } + inline double bestQuality() const + { + return candidates_->top()->getQuality(); + } + void newSolution(double solValue); + void reevaluateSearchStrategy(); +}; + +//############################################################################# + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinShallowPackedVector.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinShallowPackedVector.hpp new file mode 100644 index 000000000..e1ecb283e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinShallowPackedVector.hpp @@ -0,0 +1,149 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinShallowPackedVector_H +#define CoinShallowPackedVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include "CoinError.hpp" +#include "CoinPackedVectorBase.hpp" + +/** Shallow Sparse Vector + +This class is for sparse vectors where the indices and +elements are stored elsewhere. This class only maintains +pointers to the indices and elements. Since this class +does not own the index and element data it provides +read only access to to the data. An CoinSparsePackedVector +must be used when the sparse vector's data will be altered. + +This class stores pointers to the vectors. +It does not actually contain the vectors. + +Here is a sample usage: +@verbatim + const int ne = 4; + int inx[ne] = { 1, 4, 0, 2 }; + double el[ne] = { 10., 40., 1., 50. }; + + // Create vector and set its value + CoinShallowPackedVector r(ne,inx,el); + + // access each index and element + assert( r.indices ()[0]== 1 ); + assert( r.elements()[0]==10. ); + assert( r.indices ()[1]== 4 ); + assert( r.elements()[1]==40. ); + assert( r.indices ()[2]== 0 ); + assert( r.elements()[2]== 1. ); + assert( r.indices ()[3]== 2 ); + assert( r.elements()[3]==50. ); + + // access as a full storage vector + assert( r[ 0]==1. ); + assert( r[ 1]==10.); + assert( r[ 2]==50.); + assert( r[ 3]==0. ); + assert( r[ 4]==40.); + + // Tests for equality and equivalence + CoinShallowPackedVector r1; + r1=r; + assert( r==r1 ); + r.sort(CoinIncrElementOrdered()); + assert( r!=r1 ); + + // Add packed vectors. + // Similarly for subtraction, multiplication, + // and division. + CoinPackedVector add = r + r1; + assert( add[0] == 1.+ 1. ); + assert( add[1] == 10.+10. ); + assert( add[2] == 50.+50. ); + assert( add[3] == 0.+ 0. ); + assert( add[4] == 40.+40. ); + assert( r.sum() == 10.+40.+1.+50. ); +@endverbatim +*/ +class CoinShallowPackedVector : public CoinPackedVectorBase { + friend void CoinShallowPackedVectorUnitTest(); + +public: + /**@name Get methods */ + //@{ + /// Get length of indices and elements vectors + virtual int getNumElements() const { return nElements_; } + /// Get indices of elements + virtual const int *getIndices() const { return indices_; } + /// Get element values + virtual const double *getElements() const { return elements_; } + //@} + + /**@name Set methods */ + //@{ + /// Reset the vector (as if were just created an empty vector) + void clear(); + /** Assignment operator. */ + CoinShallowPackedVector &operator=(const CoinShallowPackedVector &x); + /** Assignment operator from a CoinPackedVectorBase. */ + CoinShallowPackedVector &operator=(const CoinPackedVectorBase &x); + /** just like the explicit constructor */ + void setVector(int size, const int *indices, const double *elements, + bool testForDuplicateIndex = true); + //@} + + /**@name Methods to create, set and destroy */ + //@{ + /** Default constructor. */ + CoinShallowPackedVector(bool testForDuplicateIndex = true); + /** Explicit Constructor. + Set vector size, indices, and elements. Size is the length of both the + indices and elements vectors. The indices and elements vectors are not + copied into this class instance. The ShallowPackedVector only maintains + the pointers to the indices and elements vectors.
+ The last argument specifies whether the creator of the object knows in + advance that there are no duplicate indices. + */ + CoinShallowPackedVector(int size, + const int *indices, const double *elements, + bool testForDuplicateIndex = true); + /** Copy constructor from the base class. */ + CoinShallowPackedVector(const CoinPackedVectorBase &); + /** Copy constructor. */ + CoinShallowPackedVector(const CoinShallowPackedVector &); + /** Destructor. */ + virtual ~CoinShallowPackedVector() {} + /// Print vector information. + void print(); + //@} + +private: + /**@name Private member data */ + //@{ + /// Vector indices + const int *indices_; + ///Vector elements + const double *elements_; + /// Size of indices and elements vectors + int nElements_; + //@} +}; + +//############################################################################# +/** A function that tests the methods in the CoinShallowPackedVector class. The + only reason for it not to be a member method is that this way it doesn't + have to be compiled into the library. And that's a gain, because the + library should be compiled with optimization on, but this method should be + compiled with debugging. */ +void CoinShallowPackedVectorUnitTest(); + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSignal.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSignal.hpp new file mode 100644 index 000000000..c49b442a7 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSignal.hpp @@ -0,0 +1,127 @@ +/* $Id$ */ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CoinSignal_hpp +#define _CoinSignal_hpp + +// This file is fully docified. +// There's nothing to docify... + +//############################################################################# + +#include + +//############################################################################# + +#if defined(_MSC_VER) +typedef void(__cdecl *CoinSighandler_t)(int); +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if (defined(__GNUC__) && defined(__linux__)) +typedef sighandler_t CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__CYGWIN__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__MINGW32__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__OpenBSD__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__FreeBSD__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(__NetBSD__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//----------------------------------------------------------------------------- + +#if defined(_AIX) +#if defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif +#endif + +//----------------------------------------------------------------------------- + +#if defined(__hpux) +#define CoinSighandler_t_defined +#if defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#else +extern "C" { +typedef void (*CoinSighandler_t)(int); +} +#endif +#endif + +//----------------------------------------------------------------------------- + +#if defined(__sun) +#if defined(__SUNPRO_CC) +#include +extern "C" { +typedef void (*CoinSighandler_t)(int); +} +#define CoinSighandler_t_defined +#endif +#if defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif +#endif + +//----------------------------------------------------------------------------- + +#if defined(__MACH__) && defined(__GNUC__) +typedef __decltype(SIG_DFL) CoinSighandler_t; +#define CoinSighandler_t_defined +#endif + +//############################################################################# + +#ifndef CoinSighandler_t_defined +#warning("OS and/or compiler is not recognized. Defaulting to:"); +#warning("extern 'C' {") +#warning(" typedef void (*CoinSighandler_t) (int);") +#warning("}") +extern "C" { +typedef void (*CoinSighandler_t)(int); +} +#endif + +//############################################################################# + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSimpFactorization.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSimpFactorization.hpp new file mode 100644 index 000000000..7462c9213 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSimpFactorization.hpp @@ -0,0 +1,432 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/* + This is a simple factorization of the LP Basis + */ +#ifndef CoinSimpFactorization_H +#define CoinSimpFactorization_H + +#include +#include +#include +#include "CoinTypes.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinDenseFactorization.hpp" +class CoinPackedMatrix; + +/// pointers used during factorization +class FactorPointers { +public: + double *rowMax; + int *firstRowKnonzeros; + int *prevRow; + int *nextRow; + int *firstColKnonzeros; + int *prevColumn; + int *nextColumn; + int *newCols; + //constructor + FactorPointers(int numRows, int numCols, int *UrowLengths_, int *UcolLengths_); + // destructor + ~FactorPointers(); +}; + +class CoinSimpFactorization : public CoinOtherFactorization { + friend void CoinSimpFactorizationUnitTest(const std::string &mpsDir); + +public: + /**@name Constructors and destructor and copy */ + //@{ + /// Default constructor + CoinSimpFactorization(); + /// Copy constructor + CoinSimpFactorization(const CoinSimpFactorization &other); + + /// Destructor + virtual ~CoinSimpFactorization(); + /// = copy + CoinSimpFactorization &operator=(const CoinSimpFactorization &other); + /// Clone + virtual CoinOtherFactorization *clone() const; + //@} + + /**@name Do factorization - public */ + //@{ + /// Gets space for a factorization + virtual void getAreas(int numberRows, + int numberColumns, + int maximumL, + int maximumU); + + /// PreProcesses column ordered copy of basis + virtual void preProcess(); + /** Does most of factorization returning status + 0 - OK + -99 - needs more memory + -1 - singular - use numberGoodColumns and redo + */ + virtual int factor(); + /// Does post processing on valid factorization - putting variables on correct rows + virtual void postProcess(const int *sequence, int *pivotVariable); + /// Makes a non-singular basis by replacing variables + virtual void makeNonSingular(int *sequence, int numberColumns); + //@} + + /**@name general stuff such as status */ + //@{ + /// Total number of elements in factorization + virtual inline int numberElements() const + { + return numberRows_ * (numberColumns_ + numberPivots_); + } + /// Returns maximum absolute value in factorization + double maximumCoefficient() const; + //@} + + /**@name rank one updates which do exist */ + //@{ + + /** Replaces one Column to basis, + returns 0=OK, 1=Probably OK, 2=singular, 3=no room + If checkBeforeModifying is true will do all accuracy checks + before modifying factorization. Whether to set this depends on + speed considerations. You could just do this on first iteration + after factorization and thereafter re-factorize + partial update already in U */ + virtual int replaceColumn(CoinIndexedVector *regionSparse, + int pivotRow, + double pivotCheck, + bool checkBeforeModifying = false, + double acceptablePivot = 1.0e-8); + //@} + + /**@name various uses of factorization (return code number elements) + which user may want to know about */ + //@{ + /** Updates one column (FTRAN) from regionSparse2 + Tries to do FT update + number returned is negative if no room + regionSparse starts as zero and is zero at end. + Note - if regionSparse2 packed on input - will be packed on output + */ + + virtual int updateColumnFT(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false); + + /** This version has same effect as above with FTUpdate==false + so number returned is always >=0 */ + virtual int updateColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false) const; + /// does FTRAN on two columns + virtual int updateTwoColumnsFT(CoinIndexedVector *regionSparse1, + CoinIndexedVector *regionSparse2, + CoinIndexedVector *regionSparse3, + bool noPermute = false); + /// does updatecolumn if save==true keeps column for replace column + int upColumn(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2, + bool noPermute = false, bool save = false) const; + /** Updates one column (BTRAN) from regionSparse2 + regionSparse starts as zero and is zero at end + Note - if regionSparse2 packed on input - will be packed on output + */ + virtual int updateColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + /// does updateColumnTranspose, the other is a wrapper + int upColumnTranspose(CoinIndexedVector *regionSparse, + CoinIndexedVector *regionSparse2) const; + //@} + /// *** Below this user may not want to know about + + /**@name various uses of factorization + which user may not want to know about (left over from my LP code) */ + //@{ + /// Get rid of all memory + inline void clearArrays() + { + gutsOfDestructor(); + } + /// Returns array to put basis indices in + inline int *indices() const + { + return reinterpret_cast< int * >(elements_ + numberRows_ * numberRows_); + } + /// Returns permute in + virtual inline int *permute() const + { + return pivotRow_; + } + //@} + + /// The real work of destructor + void gutsOfDestructor(); + /// The real work of constructor + void gutsOfInitialize(); + /// The real work of copy + void gutsOfCopy(const CoinSimpFactorization &other); + + /// calls factorization + void factorize(int numberOfRows, + int numberOfColumns, + const int colStarts[], + const int indicesRow[], + const double elements[]); + /// main loop of factorization + int mainLoopFactor(FactorPointers &pointers); + /// copies L by rows + void copyLbyRows(); + /// copies U by columns + void copyUbyColumns(); + /// finds a pivot element using Markowitz count + int findPivot(FactorPointers &pointers, int &r, int &s, bool &ifSlack); + /// finds a pivot in a shortest column + int findPivotShCol(FactorPointers &pointers, int &r, int &s); + /// finds a pivot in the first column available + int findPivotSimp(FactorPointers &pointers, int &r, int &s); + /// does Gauss elimination + void GaussEliminate(FactorPointers &pointers, int &r, int &s); + /// finds short row that intersects a given column + int findShortRow(const int column, const int length, int &minRow, + int &minRowLength, FactorPointers &pointers); + /// finds short column that intersects a given row + int findShortColumn(const int row, const int length, int &minCol, + int &minColLength, FactorPointers &pointers); + /// finds maximum absolute value in a row + double findMaxInRrow(const int row, FactorPointers &pointers); + /// does pivoting + void pivoting(const int pivotRow, const int pivotColumn, + const double invPivot, FactorPointers &pointers); + /// part of pivoting + void updateCurrentRow(const int pivotRow, const int row, + const double multiplier, FactorPointers &pointers, + int &newNonZeros); + /// allocates more space for L + void increaseLsize(); + /// allocates more space for a row of U + void increaseRowSize(const int row, const int newSize); + /// allocates more space for a column of U + void increaseColSize(const int column, const int newSize, const bool b); + /// allocates more space for rows of U + void enlargeUrow(const int numNewElements); + /// allocates more space for columns of U + void enlargeUcol(const int numNewElements, const bool b); + /// finds a given row in a column + int findInRow(const int row, const int column); + /// finds a given column in a row + int findInColumn(const int column, const int row); + /// declares a row inactive + void removeRowFromActSet(const int row, FactorPointers &pointers); + /// declares a column inactive + void removeColumnFromActSet(const int column, FactorPointers &pointers); + /// allocates space for U + void allocateSpaceForU(); + /// allocates several working arrays + void allocateSomeArrays(); + /// initializes some numbers + void initialSomeNumbers(); + /// solves L x = b + void Lxeqb(double *b) const; + /// same as above but with two rhs + void Lxeqb2(double *b1, double *b2) const; + /// solves U x = b + void Uxeqb(double *b, double *sol) const; + /// same as above but with two rhs + void Uxeqb2(double *b1, double *sol1, double *sol2, double *b2) const; + /// solves x L = b + void xLeqb(double *b) const; + /// solves x U = b + void xUeqb(double *b, double *sol) const; + /// updates factorization after a Simplex iteration + int LUupdate(int newBasicCol); + /// creates a new eta vector + void newEta(int row, int numNewElements); + /// makes a copy of row permutations + void copyRowPermutations(); + /// solves H x = b, where H is a product of eta matrices + void Hxeqb(double *b) const; + /// same as above but with two rhs + void Hxeqb2(double *b1, double *b2) const; + /// solves x H = b + void xHeqb(double *b) const; + /// does FTRAN + void ftran(double *b, double *sol, bool save) const; + /// same as above but with two columns + void ftran2(double *b1, double *sol1, double *b2, double *sol2) const; + /// does BTRAN + void btran(double *b, double *sol) const; + ///--------------------------------------- + + //@} +protected: + /** Returns accuracy status of replaceColumn + returns 0=OK, 1=Probably OK, 2=singular */ + int checkPivot(double saveFromU, double oldPivot) const; + ////////////////// data ////////////////// +protected: + /**@name data */ + //@{ + /// work array (should be initialized to zero) + double *denseVector_; + /// work array + double *workArea2_; + /// work array + double *workArea3_; + /// array of labels (should be initialized to zero) + int *vecLabels_; + /// array of indices + int *indVector_; + + /// auxiliary vector + double *auxVector_; + /// auxiliary vector + int *auxInd_; + + /// vector to keep for LUupdate + double *vecKeep_; + /// indices of this vector + int *indKeep_; + /// number of nonzeros + mutable int keepSize_; + + /// Starts of the rows of L + int *LrowStarts_; + /// Lengths of the rows of L + int *LrowLengths_; + /// L by rows + double *Lrows_; + /// indices in the rows of L + int *LrowInd_; + /// Size of Lrows_; + int LrowSize_; + /// Capacity of Lrows_ + int LrowCap_; + + /// Starts of the columns of L + int *LcolStarts_; + /// Lengths of the columns of L + int *LcolLengths_; + /// L by columns + double *Lcolumns_; + /// indices in the columns of L + int *LcolInd_; + /// numbers of elements in L + int LcolSize_; + /// maximum capacity of L + int LcolCap_; + + /// Starts of the rows of U + int *UrowStarts_; + /// Lengths of the rows of U + int *UrowLengths_; +#ifdef COIN_SIMP_CAPACITY + /// Capacities of the rows of U + int *UrowCapacities_; +#endif + /// U by rows + double *Urows_; + /// Indices in the rows of U + int *UrowInd_; + /// maximum capacity of Urows + int UrowMaxCap_; + /// number of used places in Urows + int UrowEnd_; + /// first row in U + int firstRowInU_; + /// last row in U + int lastRowInU_; + /// previous row in U + int *prevRowInU_; + /// next row in U + int *nextRowInU_; + + /// Starts of the columns of U + int *UcolStarts_; + /// Lengths of the columns of U + int *UcolLengths_; +#ifdef COIN_SIMP_CAPACITY + /// Capacities of the columns of U + int *UcolCapacities_; +#endif + /// U by columns + double *Ucolumns_; + /// Indices in the columns of U + int *UcolInd_; + /// previous column in U + int *prevColInU_; + /// next column in U + int *nextColInU_; + /// first column in U + int firstColInU_; + /// last column in U + int lastColInU_; + /// maximum capacity of Ucolumns_ + int UcolMaxCap_; + /// last used position in Ucolumns_ + int UcolEnd_; + /// indicator of slack variables + int *colSlack_; + + /// inverse values of the elements of diagonal of U + double *invOfPivots_; + + /// permutation of columns + int *colOfU_; + /// position of column after permutation + int *colPosition_; + /// permutations of rows + int *rowOfU_; + /// position of row after permutation + int *rowPosition_; + /// permutations of rows during LUupdate + int *secRowOfU_; + /// position of row after permutation during LUupdate + int *secRowPosition_; + + /// position of Eta vector + int *EtaPosition_; + /// Starts of eta vectors + int *EtaStarts_; + /// Lengths of eta vectors + int *EtaLengths_; + /// columns of eta vectors + int *EtaInd_; + /// elements of eta vectors + double *Eta_; + /// number of elements in Eta_ + int EtaSize_; + /// last eta row + int lastEtaRow_; + /// maximum number of eta vectors + int maxEtaRows_; + /// Capacity of Eta_ + int EtaMaxCap_; + + /// minimum storage increase + int minIncrease_; + /// maximum size for the diagonal of U after update + double updateTol_; + /// do Shul heuristic + bool doSuhlHeuristic_; + /// maximum of U + double maxU_; + /// bound on the growth rate + double maxGrowth_; + /// maximum of A + double maxA_; + /// maximum number of candidates for pivot + int pivotCandLimit_; + /// number of slacks in basis + int numberSlacks_; + /// number of slacks in irst basis + int firstNumberSlacks_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSmartPtr.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSmartPtr.hpp new file mode 100644 index 000000000..44b89c460 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSmartPtr.hpp @@ -0,0 +1,548 @@ +// Copyright (C) 2004, 2006 International Business Machines and others. +// All Rights Reserved. +// This code is published under the Eclipse Public License. +// +// $Id$ +// +// Authors: Carl Laird, Andreas Waechter IBM 2004-08-13 +// Removed lots of debugging stuff and reformatted: Laszlo Ladanyi, IBM +#ifndef CoinSmartPtr_hpp +#define CoinSmartPtr_hpp + +#include +#include +#include +#include + +namespace Coin { + +//######################################################################### + +/** ReferencedObject class. + * This is part of the implementation of an intrusive smart pointer + * design. This class stores the reference count of all the smart + * pointers that currently reference it. See the documentation for + * the SmartPtr class for more details. + * + * A SmartPtr behaves much like a raw pointer, but manages the lifetime + * of an object, deleting the object automatically. This class implements + * a reference-counting, intrusive smart pointer design, where all + * objects pointed to must inherit off of ReferencedObject, which + * stores the reference count. Although this is intrusive (native types + * and externally authored classes require wrappers to be referenced + * by smart pointers), it is a safer design. A more detailed discussion of + * these issues follows after the usage information. + * + * Usage Example: + * Note: to use the SmartPtr, all objects to which you point MUST + * inherit off of ReferencedObject. + * + * \verbatim + * + * In MyClass.hpp... + * + * #include "CoinSmartPtr.hpp" + + * + * class MyClass : public Coin::ReferencedObject // must derive from ReferencedObject + * { + * ... + * } + * + * In my_usage.cpp... + * + * #include "CoinSmartPtr.hpp" + * #include "MyClass.hpp" + * + * void func(AnyObject& obj) + * { + * Coin::SmartPtr ptr_to_myclass = new MyClass(...); + * // ptr_to_myclass now points to a new MyClass, + * // and the reference count is 1 + * + * ... + * + * obj.SetMyClass(ptr_to_myclass); + * // Here, let's assume that AnyObject uses a + * // SmartPtr internally here. + * // Now, both ptr_to_myclass and the internal + * // SmartPtr in obj point to the same MyClass object + * // and its reference count is 2. + * + * ... + * + * // No need to delete ptr_to_myclass, this + * // will be done automatically when the + * // reference count drops to zero. + * + * } + * + * \endverbatim + * + * Other Notes: + * The SmartPtr implements both dereference operators -> & *. + * The SmartPtr does NOT implement a conversion operator to + * the raw pointer. Use the GetRawPtr() method when this + * is necessary. Make sure that the raw pointer is NOT + * deleted. + * The SmartPtr implements the comparison operators == & != + * for a variety of types. Use these instead of + * \verbatim + * if (GetRawPtr(smrt_ptr) == ptr) // Don't use this + * \endverbatim + * SmartPtr's, as currently implemented, do NOT handle circular references. + * For example: consider a higher level object using SmartPtrs to point + * to A and B, but A and B also point to each other (i.e. A has a + * SmartPtr to B and B has a SmartPtr to A). In this scenario, when the + * higher level object is finished with A and B, their reference counts + * will never drop to zero (since they reference each other) and they + * will not be deleted. This can be detected by memory leak tools like + * valgrind. If the circular reference is necessary, the problem can be + * overcome by a number of techniques: + * + * 1) A and B can have a method that "releases" each other, that is + * they set their internal SmartPtrs to NULL. + * \verbatim + * void AClass::ReleaseCircularReferences() + * { + * smart_ptr_to_B = NULL; + * } + * \endverbatim + * Then, the higher level class can call these methods before + * it is done using A & B. + * + * 2) Raw pointers can be used in A and B to reference each other. + * Here, an implicit assumption is made that the lifetime is + * controlled by the higher level object and that A and B will + * both exist in a controlled manner. Although this seems + * dangerous, in many situations, this type of referencing + * is very controlled and this is reasonably safe. + * + * 3) This SmartPtr class could be redesigned with the Weak/Strong + * design concept. Here, the SmartPtr is identified as being + * Strong (controls lifetime of the object) or Weak (merely + * referencing the object). The Strong SmartPtr increments + * (and decrements) the reference count in ReferencedObject + * but the Weak SmartPtr does not. In the example above, + * the higher level object would have Strong SmartPtrs to + * A and B, but A and B would have Weak SmartPtrs to each + * other. Then, when the higher level object was done with + * A and B, they would be deleted. The Weak SmartPtrs in A + * and B would not decrement the reference count and would, + * of course, not delete the object. This idea is very similar + * to item (2), where it is implied that the sequence of events + * is controlled such that A and B will not call anything using + * their pointers following the higher level delete (i.e. in + * their destructors!). This is somehow safer, however, because + * code can be written (however expensive) to perform run-time + * detection of this situation. For example, the ReferencedObject + * could store pointers to all Weak SmartPtrs that are referencing + * it and, in its destructor, tell these pointers that it is + * dying. They could then set themselves to NULL, or set an + * internal flag to detect usage past this point. + * + * Comments on Non-Intrusive Design: + * In a non-intrusive design, the reference count is stored somewhere other + * than the object being referenced. This means, unless the reference + * counting pointer is the first referencer, it must get a pointer to the + * referenced object from another smart pointer (so it has access to the + * reference count location). In this non-intrusive design, if we are + * pointing to an object with a smart pointer (or a number of smart + * pointers), and we then give another smart pointer the address through + * a RAW pointer, we will have two independent, AND INCORRECT, reference + * counts. To avoid this pitfall, we use an intrusive reference counting + * technique where the reference count is stored in the object being + * referenced. + */ +class ReferencedObject { +public: + ReferencedObject() + : reference_count_(0) + { + } + virtual ~ReferencedObject() { assert(reference_count_ == 0); } + inline int ReferenceCount() const { return reference_count_; } + inline void AddRef() const { ++reference_count_; } + inline void ReleaseRef() const { --reference_count_; } + +private: + mutable int reference_count_; +}; + +//######################################################################### + +//#define IP_DEBUG_SMARTPTR +#if COIN_IPOPT_CHECKLEVEL > 2 +#define IP_DEBUG_SMARTPTR +#endif +#ifdef IP_DEBUG_SMARTPTR +#include "IpDebug.hpp" +#endif + +/** Template class for Smart Pointers. + * A SmartPtr behaves much like a raw pointer, but manages the lifetime + * of an object, deleting the object automatically. This class implements + * a reference-counting, intrusive smart pointer design, where all + * objects pointed to must inherit off of ReferencedObject, which + * stores the reference count. Although this is intrusive (native types + * and externally authored classes require wrappers to be referenced + * by smart pointers), it is a safer design. A more detailed discussion of + * these issues follows after the usage information. + * + * Usage Example: + * Note: to use the SmartPtr, all objects to which you point MUST + * inherit off of ReferencedObject. + * + * \verbatim + * + * In MyClass.hpp... + * + * #include "CoinSmartPtr.hpp" + * + * class MyClass : public Coin::ReferencedObject // must derive from ReferencedObject + * { + * ... + * } + * + * In my_usage.cpp... + * + * #include "CoinSmartPtr.hpp" + * #include "MyClass.hpp" + * + * void func(AnyObject& obj) + * { + * SmartPtr ptr_to_myclass = new MyClass(...); + * // ptr_to_myclass now points to a new MyClass, + * // and the reference count is 1 + * + * ... + * + * obj.SetMyClass(ptr_to_myclass); + * // Here, let's assume that AnyObject uses a + * // SmartPtr internally here. + * // Now, both ptr_to_myclass and the internal + * // SmartPtr in obj point to the same MyClass object + * // and its reference count is 2. + * + * ... + * + * // No need to delete ptr_to_myclass, this + * // will be done automatically when the + * // reference count drops to zero. + * + * } + * + * \endverbatim + * + * It is not necessary to use SmartPtr's in all cases where an + * object is used that has been allocated "into" a SmartPtr. It is + * possible to just pass objects by reference or regular pointers, + * even if lower down in the stack a SmartPtr is to be held on to. + * Everything should work fine as long as a pointer created by "new" + * is immediately passed into a SmartPtr, and if SmartPtr's are used + * to hold on to objects. + * + * Other Notes: + * The SmartPtr implements both dereference operators -> & *. + * The SmartPtr does NOT implement a conversion operator to + * the raw pointer. Use the GetRawPtr() method when this + * is necessary. Make sure that the raw pointer is NOT + * deleted. + * The SmartPtr implements the comparison operators == & != + * for a variety of types. Use these instead of + * \verbatim + * if (GetRawPtr(smrt_ptr) == ptr) // Don't use this + * \endverbatim + * SmartPtr's, as currently implemented, do NOT handle circular references. + * For example: consider a higher level object using SmartPtrs to point to + * A and B, but A and B also point to each other (i.e. A has a SmartPtr + * to B and B has a SmartPtr to A). In this scenario, when the higher + * level object is finished with A and B, their reference counts will + * never drop to zero (since they reference each other) and they + * will not be deleted. This can be detected by memory leak tools like + * valgrind. If the circular reference is necessary, the problem can be + * overcome by a number of techniques: + * + * 1) A and B can have a method that "releases" each other, that is + * they set their internal SmartPtrs to NULL. + * \verbatim + * void AClass::ReleaseCircularReferences() + * { + * smart_ptr_to_B = NULL; + * } + * \endverbatim + * Then, the higher level class can call these methods before + * it is done using A & B. + * + * 2) Raw pointers can be used in A and B to reference each other. + * Here, an implicit assumption is made that the lifetime is + * controlled by the higher level object and that A and B will + * both exist in a controlled manner. Although this seems + * dangerous, in many situations, this type of referencing + * is very controlled and this is reasonably safe. + * + * 3) This SmartPtr class could be redesigned with the Weak/Strong + * design concept. Here, the SmartPtr is identified as being + * Strong (controls lifetime of the object) or Weak (merely + * referencing the object). The Strong SmartPtr increments + * (and decrements) the reference count in ReferencedObject + * but the Weak SmartPtr does not. In the example above, + * the higher level object would have Strong SmartPtrs to + * A and B, but A and B would have Weak SmartPtrs to each + * other. Then, when the higher level object was done with + * A and B, they would be deleted. The Weak SmartPtrs in A + * and B would not decrement the reference count and would, + * of course, not delete the object. This idea is very similar + * to item (2), where it is implied that the sequence of events + * is controlled such that A and B will not call anything using + * their pointers following the higher level delete (i.e. in + * their destructors!). This is somehow safer, however, because + * code can be written (however expensive) to perform run-time + * detection of this situation. For example, the ReferencedObject + * could store pointers to all Weak SmartPtrs that are referencing + * it and, in its destructor, tell these pointers that it is + * dying. They could then set themselves to NULL, or set an + * internal flag to detect usage past this point. + * + * Comments on Non-Intrusive Design: + * In a non-intrusive design, the reference count is stored somewhere other + * than the object being referenced. This means, unless the reference + * counting pointer is the first referencer, it must get a pointer to the + * referenced object from another smart pointer (so it has access to the + * reference count location). In this non-intrusive design, if we are + * pointing to an object with a smart pointer (or a number of smart + * pointers), and we then give another smart pointer the address through + * a RAW pointer, we will have two independent, AND INCORRECT, reference + * counts. To avoid this pitfall, we use an intrusive reference counting + * technique where the reference count is stored in the object being + * referenced. + */ +template < class T > +class SmartPtr { +public: + /** Returns the raw pointer contained. Use to get the value of the + * raw ptr (i.e. to pass to other methods/functions, etc.) Note: This + * method does NOT copy, therefore, modifications using this value + * modify the underlying object contained by the SmartPtr, NEVER + * delete this returned value. + */ + T *GetRawPtr() const { return ptr_; } + + /** Returns true if the SmartPtr is NOT NULL. + * Use this to check if the SmartPtr is not null + * This is preferred to if(GetRawPtr(sp) != NULL) + */ + bool IsValid() const { return ptr_ != NULL; } + + /** Returns true if the SmartPtr is NULL. + * Use this to check if the SmartPtr IsNull. + * This is preferred to if(GetRawPtr(sp) == NULL) + */ + bool IsNull() const { return ptr_ == NULL; } + +private: + /**@name Private Data/Methods */ + //@{ + /** Actual raw pointer to the object. */ + T *ptr_; + + /** Release the currently referenced object. */ + void ReleasePointer_() + { + if (ptr_) { + ptr_->ReleaseRef(); + if (ptr_->ReferenceCount() == 0) { + delete ptr_; + } + ptr_ = NULL; + } + } + + /** Set the value of the internal raw pointer from another raw + * pointer, releasing the previously referenced object if necessary. */ + SmartPtr< T > &SetFromRawPtr_(T *rhs) + { + ReleasePointer_(); // Release any old pointer + if (rhs != NULL) { + rhs->AddRef(); + ptr_ = rhs; + } + return *this; + } + + /** Set the value of the internal raw pointer from a SmartPtr, + * releasing the previously referenced object if necessary. */ + inline SmartPtr< T > &SetFromSmartPtr_(const SmartPtr< T > &rhs) + { + SetFromRawPtr_(rhs.GetRawPtr()); + return (*this); + } + + //@} + +public: +#define dbg_smartptr_verbosity 0 + + /**@name Constructors/Destructors */ + //@{ + /** Default constructor, initialized to NULL */ + SmartPtr() + : ptr_(NULL) + { + } + + /** Copy constructor, initialized from copy */ + SmartPtr(const SmartPtr< T > ©) + : ptr_(NULL) + { + (void)SetFromSmartPtr_(copy); + } + + /** Constructor, initialized from T* ptr */ + SmartPtr(T *ptr) + : ptr_(NULL) + { + (void)SetFromRawPtr_(ptr); + } + + /** Destructor, automatically decrements the reference count, deletes + * the object if necessary.*/ + ~SmartPtr() + { + ReleasePointer_(); + } + //@} + + /**@name Overloaded operators. */ + //@{ + /** Overloaded arrow operator, allows the user to call + * methods using the contained pointer. */ + T *operator->() const + { +#if COIN_COINUTILS_CHECKLEVEL > 0 + assert(ptr_); +#endif + return ptr_; + } + + /** Overloaded dereference operator, allows the user + * to dereference the contained pointer. */ + T &operator*() const + { +#if COIN_IPOPT_CHECKLEVEL > 0 + assert(ptr_); +#endif + return *ptr_; + } + + /** Overloaded equals operator, allows the user to + * set the value of the SmartPtr from a raw pointer */ + SmartPtr< T > &operator=(T *rhs) + { + return SetFromRawPtr_(rhs); + } + + /** Overloaded equals operator, allows the user to + * set the value of the SmartPtr from another + * SmartPtr */ + SmartPtr< T > &operator=(const SmartPtr< T > &rhs) + { + return SetFromSmartPtr_(rhs); + } + + /** Overloaded equality comparison operator, allows the + * user to compare the value of two SmartPtrs */ + template < class U1, class U2 > + friend bool operator==(const SmartPtr< U1 > &lhs, const SmartPtr< U2 > &rhs); + + /** Overloaded equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template < class U1, class U2 > + friend bool operator==(const SmartPtr< U1 > &lhs, U2 *raw_rhs); + + /** Overloaded equality comparison operator, allows the + * user to compare the value of a raw pointer with a SmartPtr. */ + template < class U1, class U2 > + friend bool operator==(U1 *lhs, const SmartPtr< U2 > &raw_rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of two SmartPtrs */ + template < class U1, class U2 > + friend bool operator!=(const SmartPtr< U1 > &lhs, const SmartPtr< U2 > &rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template < class U1, class U2 > + friend bool operator!=(const SmartPtr< U1 > &lhs, U2 *raw_rhs); + + /** Overloaded in-equality comparison operator, allows the + * user to compare the value of a SmartPtr with a raw pointer. */ + template < class U1, class U2 > + friend bool operator!=(U1 *lhs, const SmartPtr< U2 > &raw_rhs); + //@} +}; + +template < class U1, class U2 > +bool ComparePointers(const U1 *lhs, const U2 *rhs) +{ + if (lhs == rhs) { + return true; + } + // If lhs and rhs point to the same object with different interfaces + // U1 and U2, we cannot guarantee that the value of the pointers will + // be equivalent. We can guarantee this if we convert to void*. + return static_cast< const void * >(lhs) == static_cast< const void * >(rhs); +} + +} // namespace Coin + +//############################################################################# + +/**@name SmartPtr friends that are overloaded operators, so they are not in + the Coin namespace. */ +//@{ +template < class U1, class U2 > +bool operator==(const Coin::SmartPtr< U1 > &lhs, const Coin::SmartPtr< U2 > &rhs) +{ + return Coin::ComparePointers(lhs.GetRawPtr(), rhs.GetRawPtr()); +} + +template < class U1, class U2 > +bool operator==(const Coin::SmartPtr< U1 > &lhs, U2 *raw_rhs) +{ + return Coin::ComparePointers(lhs.GetRawPtr(), raw_rhs); +} + +template < class U1, class U2 > +bool operator==(U1 *raw_lhs, const Coin::SmartPtr< U2 > &rhs) +{ + return Coin::ComparePointers(raw_lhs, rhs.GetRawPtr()); +} + +template < class U1, class U2 > +bool operator!=(const Coin::SmartPtr< U1 > &lhs, const Coin::SmartPtr< U2 > &rhs) +{ + return !operator==(lhs, rhs); +} + +template < class U1, class U2 > +bool operator!=(const Coin::SmartPtr< U1 > &lhs, U2 *raw_rhs) +{ + return !operator==(lhs, raw_rhs); +} + +template < class U1, class U2 > +bool operator!=(U1 *raw_lhs, const Coin::SmartPtr< U2 > &rhs) +{ + return !operator==(raw_lhs, rhs); +} +//@} + +#define CoinReferencedObject Coin::ReferencedObject +#define CoinSmartPtr Coin::SmartPtr +#define CoinComparePointers Coin::ComparePointers + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSnapshot.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSnapshot.hpp new file mode 100644 index 000000000..1a06cccb3 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSnapshot.hpp @@ -0,0 +1,572 @@ +/* $Id$ */ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSnapshot_H +#define CoinSnapshot_H + +class CoinPackedMatrix; +#include "CoinTypes.hpp" + +//############################################################################# + +/** NON Abstract Base Class for interfacing with cut generators or branching code or .. + It is designed to be snapshot of a problem at a node in tree + + The class may or may not own the arrays - see owned_ + + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return arrays. +*/ + +class CoinSnapshot { + +public: + //--------------------------------------------------------------------------- + /**@name Problem query methods + + The Matrix pointers may be NULL + */ + //@{ + /// Get number of columns + inline int getNumCols() const + { + return numCols_; + } + + /// Get number of rows + inline int getNumRows() const + { + return numRows_; + } + + /// Get number of nonzero elements + inline int getNumElements() const + { + return numElements_; + } + + /// Get number of integer variables + inline int getNumIntegers() const + { + return numIntegers_; + } + + /// Get pointer to array[getNumCols()] of column lower bounds + inline const double *getColLower() const + { + return colLower_; + } + + /// Get pointer to array[getNumCols()] of column upper bounds + inline const double *getColUpper() const + { + return colUpper_; + } + + /// Get pointer to array[getNumRows()] of row lower bounds + inline const double *getRowLower() const + { + return rowLower_; + } + + /// Get pointer to array[getNumRows()] of row upper bounds + inline const double *getRowUpper() const + { + return rowUpper_; + } + + /** Get pointer to array[getNumRows()] of row right-hand sides + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + inline const double *getRightHandSide() const + { + return rightHandSide_; + } + + /// Get pointer to array[getNumCols()] of objective function coefficients + inline const double *getObjCoefficients() const + { + return objCoefficients_; + } + + /// Get objective function sense (1 for min (default), -1 for max) + inline double getObjSense() const + { + return objSense_; + } + + /// Return true if variable is continuous + inline bool isContinuous(int colIndex) const + { + return colType_[colIndex] == 'C'; + } + + /// Return true if variable is binary + inline bool isBinary(int colIndex) const + { + return colType_[colIndex] == 'B'; + } + + /// Return true if column is integer. + inline bool isInteger(int colIndex) const + { + return colType_[colIndex] == 'B' || colType_[colIndex] == 'I'; + } + + /// Return true if variable is general integer + inline bool isIntegerNonBinary(int colIndex) const + { + return colType_[colIndex] == 'I'; + } + + /// Return true if variable is binary and not fixed at either bound + inline bool isFreeBinary(int colIndex) const + { + return colType_[colIndex] == 'B' && colUpper_[colIndex] > colLower_[colIndex]; + } + + /// Get colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + inline const char *getColType() const + { + return colType_; + } + + /// Get pointer to row-wise copy of current matrix + inline const CoinPackedMatrix *getMatrixByRow() const + { + return matrixByRow_; + } + + /// Get pointer to column-wise copy of current matrix + inline const CoinPackedMatrix *getMatrixByCol() const + { + return matrixByCol_; + } + + /// Get pointer to row-wise copy of "original" matrix + inline const CoinPackedMatrix *getOriginalMatrixByRow() const + { + return originalMatrixByRow_; + } + + /// Get pointer to column-wise copy of "original" matrix + inline const CoinPackedMatrix *getOriginalMatrixByCol() const + { + return originalMatrixByCol_; + } + //@} + + /**@name Solution query methods */ + //@{ + /// Get pointer to array[getNumCols()] of primal variable values + inline const double *getColSolution() const + { + return colSolution_; + } + + /// Get pointer to array[getNumRows()] of dual variable values + inline const double *getRowPrice() const + { + return rowPrice_; + } + + /// Get a pointer to array[getNumCols()] of reduced costs + inline const double *getReducedCost() const + { + return reducedCost_; + } + + /// Get pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + inline const double *getRowActivity() const + { + return rowActivity_; + } + + /// Get pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + inline const double *getDoNotSeparateThis() const + { + return doNotSeparateThis_; + } + //@} + + /**@name Other scalar get methods */ + //@{ + /// Get solver's value for infinity + inline double getInfinity() const + { + return infinity_; + } + + /** Get objective function value - includinbg any offset i.e. + sum c sub j * x subj - objValue = objOffset */ + inline double getObjValue() const + { + return objValue_; + } + + /// Get objective offset i.e. sum c sub j * x subj -objValue = objOffset + inline double getObjOffset() const + { + return objOffset_; + } + + /// Get dual tolerance + inline double getDualTolerance() const + { + return dualTolerance_; + } + + /// Get primal tolerance + inline double getPrimalTolerance() const + { + return primalTolerance_; + } + + /// Get integer tolerance + inline double getIntegerTolerance() const + { + return integerTolerance_; + } + + /// Get integer upper bound i.e. best solution * getObjSense + inline double getIntegerUpperBound() const + { + return integerUpperBound_; + } + + /// Get integer lower bound i.e. best possible solution * getObjSense + inline double getIntegerLowerBound() const + { + return integerLowerBound_; + } + //@} + + //--------------------------------------------------------------------------- + + /**@name Method to input a problem */ + //@{ + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ All solution type arrays will be deleted + */ + void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub, + bool makeRowCopy = false); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Methods to set data */ + //@{ + /// Set number of columns + inline void setNumCols(int value) + { + numCols_ = value; + } + + /// Set number of rows + inline void setNumRows(int value) + { + numRows_ = value; + } + + /// Set number of nonzero elements + inline void setNumElements(int value) + { + numElements_ = value; + } + + /// Set number of integer variables + inline void setNumIntegers(int value) + { + numIntegers_ = value; + } + + /// Set pointer to array[getNumCols()] of column lower bounds + void setColLower(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumCols()] of column upper bounds + void setColUpper(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumRows()] of row lower bounds + void setRowLower(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumRows()] of row upper bounds + void setRowUpper(const double *array, bool copyIn = true); + + /** Set pointer to array[getNumRows()] of row right-hand sides + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + void setRightHandSide(const double *array, bool copyIn = true); + + /** Create array[getNumRows()] of row right-hand sides + using existing information + This gives same results as OsiSolverInterface for useful cases + If getRowUpper()[i] != infinity then + getRightHandSide()[i] == getRowUpper()[i] + else + getRightHandSide()[i] == getRowLower()[i] + */ + void createRightHandSide(); + + /// Set pointer to array[getNumCols()] of objective function coefficients + void setObjCoefficients(const double *array, bool copyIn = true); + + /// Set objective function sense (1 for min (default), -1 for max) + inline void setObjSense(double value) + { + objSense_ = value; + } + + /// Set colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + void setColType(const char *array, bool copyIn = true); + + /// Set pointer to row-wise copy of current matrix + void setMatrixByRow(const CoinPackedMatrix *matrix, bool copyIn = true); + + /// Create row-wise copy from MatrixByCol + void createMatrixByRow(); + + /// Set pointer to column-wise copy of current matrix + void setMatrixByCol(const CoinPackedMatrix *matrix, bool copyIn = true); + + /// Set pointer to row-wise copy of "original" matrix + void setOriginalMatrixByRow(const CoinPackedMatrix *matrix, bool copyIn = true); + + /// Set pointer to column-wise copy of "original" matrix + void setOriginalMatrixByCol(const CoinPackedMatrix *matrix, bool copyIn = true); + + /// Set pointer to array[getNumCols()] of primal variable values + void setColSolution(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumRows()] of dual variable values + void setRowPrice(const double *array, bool copyIn = true); + + /// Set a pointer to array[getNumCols()] of reduced costs + void setReducedCost(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + void setRowActivity(const double *array, bool copyIn = true); + + /// Set pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + void setDoNotSeparateThis(const double *array, bool copyIn = true); + + /// Set solver's value for infinity + inline void setInfinity(double value) + { + infinity_ = value; + } + + /// Set objective function value (including any rhs offset) + inline void setObjValue(double value) + { + objValue_ = value; + } + + /// Set objective offset i.e. sum c sub j * x subj -objValue = objOffset + inline void setObjOffset(double value) + { + objOffset_ = value; + } + + /// Set dual tolerance + inline void setDualTolerance(double value) + { + dualTolerance_ = value; + } + + /// Set primal tolerance + inline void setPrimalTolerance(double value) + { + primalTolerance_ = value; + } + + /// Set integer tolerance + inline void setIntegerTolerance(double value) + { + integerTolerance_ = value; + } + + /// Set integer upper bound i.e. best solution * getObjSense + inline void setIntegerUpperBound(double value) + { + integerUpperBound_ = value; + } + + /// Set integer lower bound i.e. best possible solution * getObjSense + inline void setIntegerLowerBound(double value) + { + integerLowerBound_ = value; + } + //@} + + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors + //@{ + /// Default Constructor + CoinSnapshot(); + + /// Copy constructor + CoinSnapshot(const CoinSnapshot &); + + /// Assignment operator + CoinSnapshot &operator=(const CoinSnapshot &rhs); + + /// Destructor + virtual ~CoinSnapshot(); + + //@} + +private: + ///@name private functions + //@{ + /** Does main work of destructor - type (or'ed) + 1 - NULLify pointers + 2 - delete pointers + 4 - initialize scalars (tolerances etc) + 8 - initialize scalars (objValue etc0 + */ + void gutsOfDestructor(int type); + /// Does main work of copy + void gutsOfCopy(const CoinSnapshot &rhs); + //@} + + ///@name Private member data + + /// objective function sense (1 for min (default), -1 for max) + double objSense_; + + /// solver's value for infinity + double infinity_; + + /// objective function value (including any rhs offset) + double objValue_; + + /// objective offset i.e. sum c sub j * x subj -objValue = objOffset + double objOffset_; + + /// dual tolerance + double dualTolerance_; + + /// primal tolerance + double primalTolerance_; + + /// integer tolerance + double integerTolerance_; + + /// integer upper bound i.e. best solution * getObjSense + double integerUpperBound_; + + /// integer lower bound i.e. best possible solution * getObjSense + double integerLowerBound_; + + /// pointer to array[getNumCols()] of column lower bounds + const double *colLower_; + + /// pointer to array[getNumCols()] of column upper bounds + const double *colUpper_; + + /// pointer to array[getNumRows()] of row lower bounds + const double *rowLower_; + + /// pointer to array[getNumRows()] of row upper bounds + const double *rowUpper_; + + /// pointer to array[getNumRows()] of rhs side values + const double *rightHandSide_; + + /// pointer to array[getNumCols()] of objective function coefficients + const double *objCoefficients_; + + /// colType array ('B', 'I', or 'C' for Binary, Integer and Continuous) + const char *colType_; + + /// pointer to row-wise copy of current matrix + const CoinPackedMatrix *matrixByRow_; + + /// pointer to column-wise copy of current matrix + const CoinPackedMatrix *matrixByCol_; + + /// pointer to row-wise copy of "original" matrix + const CoinPackedMatrix *originalMatrixByRow_; + + /// pointer to column-wise copy of "original" matrix + const CoinPackedMatrix *originalMatrixByCol_; + + /// pointer to array[getNumCols()] of primal variable values + const double *colSolution_; + + /// pointer to array[getNumRows()] of dual variable values + const double *rowPrice_; + + /// a pointer to array[getNumCols()] of reduced costs + const double *reducedCost_; + + /// pointer to array[getNumRows()] of row activity levels (constraint matrix times the solution vector). + const double *rowActivity_; + + /// pointer to array[getNumCols()] of primal variable values which should not be separated (for debug) + const double *doNotSeparateThis_; + + /// number of columns + int numCols_; + + /// number of rows + int numRows_; + + /// number of nonzero elements + int numElements_; + + /// number of integer variables + int numIntegers_; + + /// To say whether arrays etc are owned by CoinSnapshot + typedef struct { + unsigned int colLower : 1; + unsigned int colUpper : 1; + unsigned int rowLower : 1; + unsigned int rowUpper : 1; + unsigned int rightHandSide : 1; + unsigned int objCoefficients : 1; + unsigned int colType : 1; + unsigned int matrixByRow : 1; + unsigned int matrixByCol : 1; + unsigned int originalMatrixByRow : 1; + unsigned int originalMatrixByCol : 1; + unsigned int colSolution : 1; + unsigned int rowPrice : 1; + unsigned int reducedCost : 1; + unsigned int rowActivity : 1; + unsigned int doNotSeparateThis : 1; + } coinOwned; + coinOwned owned_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSort.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSort.hpp new file mode 100644 index 000000000..63ecf4eed --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinSort.hpp @@ -0,0 +1,753 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinSort_H +#define CoinSort_H + +#include +#include +#include +#include "CoinDistance.hpp" + +// Uncomment the next three lines to get thorough initialisation of memory. +// #ifndef ZEROFAULT +// #define ZEROFAULT +// #endif + +#ifdef COIN_FAST_CODE +#ifndef COIN_USE_EKK_SORT +#define COIN_USE_EKK_SORT +#endif +#endif + +//############################################################################# + +/** An ordered pair. It's the same as std::pair, just this way it'll have the + same look as the triple sorting. */ +template < class S, class T > +struct CoinPair { +public: + /// First member of pair + S first; + /// Second member of pair + T second; + +public: + /// Construct from ordered pair + CoinPair(const S &s, const T &t) + : first(s) + , second(t) + { + } +}; + +//############################################################################# + +/**@name Comparisons on first element of two ordered pairs */ +//@{ +/** Function operator. + Returns true if t1.first < t2.first (i.e., increasing). */ +template < class S, class T > +class CoinFirstLess_2 { +public: + /// Compare function + inline bool operator()(const CoinPair< S, T > &t1, + const CoinPair< S, T > &t2) const + { + return t1.first < t2.first; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if t1.first > t2.first (i.e, decreasing). */ +template < class S, class T > +class CoinFirstGreater_2 { +public: + /// Compare function + inline bool operator()(const CoinPair< S, T > &t1, + const CoinPair< S, T > &t2) const + { + return t1.first > t2.first; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ +template < class S, class T > +class CoinFirstAbsLess_2 { +public: + /// Compare function + inline bool operator()(const CoinPair< S, T > &t1, + const CoinPair< S, T > &t2) const + { + const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; + return t1Abs < t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ +template < class S, class T > +class CoinFirstAbsGreater_2 { +public: + /// Compare function + inline bool operator()(CoinPair< S, T > t1, CoinPair< S, T > t2) const + { + const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; + return t1Abs > t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class V > +class CoinExternalVectorFirstLess_2 { +private: + CoinExternalVectorFirstLess_2(); + +private: + const V *vec_; + +public: + inline bool operator()(const CoinPair< S, T > &t1, + const CoinPair< S, T > &t2) const + { + return vec_[t1.first] < vec_[t2.first]; + } + CoinExternalVectorFirstLess_2(const V *v) + : vec_(v) + { + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class V > +class CoinExternalVectorFirstGreater_2 { +private: + CoinExternalVectorFirstGreater_2(); + +private: + const V *vec_; + +public: + inline bool operator()(const CoinPair< S, T > &t1, + const CoinPair< S, T > &t2) const + { + return vec_[t1.first] > vec_[t2.first]; + } + CoinExternalVectorFirstGreater_2(const V *v) + : vec_(v) + { + } +}; +//@} + +//############################################################################# + +/** Sort a pair of containers.
+ + Iter_S - iterator for first container
+ Iter_T - iterator for 2nd container
+ CoinCompare2 - class comparing CoinPairs
+*/ + +#ifdef COIN_SORT_ARBITRARY_CONTAINERS +template < class Iter_S, class Iter_T, class CoinCompare2 > +void CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst, const CoinCompare2 &pc) +{ + typedef typename std::iterator_traits< Iter_S >::value_type S; + typedef typename std::iterator_traits< Iter_T >::value_type T; + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinPair< S, T > ST_pair; + ST_pair *x = static_cast< ST_pair * >(::operator new(len * sizeof(ST_pair))); +#ifdef ZEROFAULT + memset(x, 0, (len * sizeof(ST_pair))); +#endif + + int i = 0; + Iter_S scurrent = sfirst; + Iter_T tcurrent = tfirst; + while (scurrent != slast) { + new (x + i++) ST_pair(*scurrent++, *tcurrent++); + } + + std::sort(x.begin(), x.end(), pc); + + scurrent = sfirst; + tcurrent = tfirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template < class Iter_S, class Iter_T > +void CoinSort_2(Iter_S sfirst, Iter_S slast, Iter_T tfirst) +{ + typedef typename std::iterator_traits< Iter_S >::value_type S; + typedef typename std::iterator_traits< Iter_T >::value_type T; + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); +} + +#else //======================================================================= + +template < class S, class T, class CoinCompare2 > +void CoinSort_2(S *sfirst, S *slast, T *tfirst, const CoinCompare2 &pc) +{ + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinPair< S, T > ST_pair; + ST_pair *x = static_cast< ST_pair * >(::operator new(len * sizeof(ST_pair))); +#ifdef ZEROFAULT + // Can show RUI errors on some systems due to copy of ST_pair with gaps. + // E.g., has 4 byte alignment gap on Solaris/SUNWspro. + memset(x, 0, (len * sizeof(ST_pair))); +#endif + + size_t i = 0; + S *scurrent = sfirst; + T *tcurrent = tfirst; + while (scurrent != slast) { + new (x + i++) ST_pair(*scurrent++, *tcurrent++); + } + + std::sort(x, x + len, pc); + + scurrent = sfirst; + tcurrent = tfirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + } + + ::operator delete(x); +} +template < class S, class T > +void +// This Always uses std::sort +CoinSort_2Std(S *sfirst, S *slast, T *tfirst) +{ + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); +} +#ifndef COIN_USE_EKK_SORT +//----------------------------------------------------------------------------- +template < class S, class T > +void CoinSort_2(S *sfirst, S *slast, T *tfirst) +{ + CoinSort_2(sfirst, slast, tfirst, CoinFirstLess_2< S, T >()); +} +#else +//----------------------------------------------------------------------------- +extern int boundary_sort; +extern int boundary_sort2; +extern int boundary_sort3; +/// Sort without new and delete +template < class S, class T > +void CoinSort_2(S *key, S *lastKey, T *array2) +{ + const size_t number = coinDistance(key, lastKey); + if (number <= 1) { + return; + } else if (number > 10000) { + CoinSort_2Std(key, lastKey, array2); + return; + } +#if 0 + if (number==boundary_sort3) { + printf("before sort %d entries\n",number); + for (int j=0;j(number); + int sp; + S *v = key; + S *m, t; + S *ls[32], *rs[32]; + S *l, *r, c; + T it; + int j; + /*check already sorted */ + S last = key[0]; + for (j = 1; j < n; j++) { + if (key[j] >= last) { + last = key[j]; + } else { + break; + } /* endif */ + } /* endfor */ + if (j == n) { + return; + } /* endif */ + sp = 0; + ls[sp] = v; + rs[sp] = v + (n - 1); + while (sp >= 0) { + if (rs[sp] - ls[sp] > minsize) { + l = ls[sp]; + r = rs[sp]; + m = l + (r - l) / 2; + if (*l > *m) { + t = *l; + *l = *m; + *m = t; + it = array2[l - v]; + array2[l - v] = array2[m - v]; + array2[m - v] = it; + } + if (*m > *r) { + t = *m; + *m = *r; + *r = t; + it = array2[m - v]; + array2[m - v] = array2[r - v]; + array2[r - v] = it; + if (*l > *m) { + t = *l; + *l = *m; + *m = t; + it = array2[l - v]; + array2[l - v] = array2[m - v]; + array2[m - v] = it; + } + } + c = *m; + while (r - l > 1) { + while (*(++l) < c) + ; + while (*(--r) > c) + ; + t = *l; + *l = *r; + *r = t; + it = array2[l - v]; + array2[l - v] = array2[r - v]; + array2[r - v] = it; + } + l = r - 1; + if (l < m) { + ls[sp + 1] = ls[sp]; + rs[sp + 1] = l; + ls[sp] = r; + } else { + ls[sp + 1] = r; + rs[sp + 1] = rs[sp]; + rs[sp] = l; + } + sp++; + } else + sp--; + } + for (l = v, m = v + (n - 1); l < m; l++) { + if (*l > *(l + 1)) { + c = *(l + 1); + it = array2[(l - v) + 1]; + for (r = l; r >= v && *r > c; r--) { + *(r + 1) = *r; + array2[(r - v) + 1] = array2[(r - v)]; + } + *(r + 1) = c; + array2[(r - v) + 1] = it; + } + } +#if 0 + if (number==boundary_sort3) { + printf("after sort %d entries\n",number); + for (int j=0;j +void CoinShortSort_2(S *key, S *lastKey, T *array2) +{ + const size_t number = coinDistance(key, lastKey); + if (number <= 2) { + if (number == 2 && key[0] > key[1]) { + S tempS = key[0]; + T tempT = array2[0]; + key[0] = key[1]; + array2[0] = array2[1]; + key[1] = tempS; + array2[1] = tempT; + } + return; + } else if (number > 10000) { + CoinSort_2Std(key, lastKey, array2); + return; + } + int minsize = 10; + size_t n = number; + int sp; + S *v = key; + S *m, t; + S *ls[32], *rs[32]; + S *l, *r, c; + T it; + size_t j; + /*check already sorted */ + S last = key[0]; + for (j = 1; j < n; j++) { + if (key[j] >= last) { + last = key[j]; + } else { + break; + } /* endif */ + } /* endfor */ + if (j == n) { + return; + } /* endif */ + sp = 0; + ls[sp] = v; + rs[sp] = v + (n - 1); + while (sp >= 0) { + if (rs[sp] - ls[sp] > minsize) { + l = ls[sp]; + r = rs[sp]; + m = l + (r - l) / 2; + if (*l > *m) { + t = *l; + *l = *m; + *m = t; + it = array2[l - v]; + array2[l - v] = array2[m - v]; + array2[m - v] = it; + } + if (*m > *r) { + t = *m; + *m = *r; + *r = t; + it = array2[m - v]; + array2[m - v] = array2[r - v]; + array2[r - v] = it; + if (*l > *m) { + t = *l; + *l = *m; + *m = t; + it = array2[l - v]; + array2[l - v] = array2[m - v]; + array2[m - v] = it; + } + } + c = *m; + while (r - l > 1) { + while (*(++l) < c) + ; + while (*(--r) > c) + ; + t = *l; + *l = *r; + *r = t; + it = array2[l - v]; + array2[l - v] = array2[r - v]; + array2[r - v] = it; + } + l = r - 1; + if (l < m) { + ls[sp + 1] = ls[sp]; + rs[sp + 1] = l; + ls[sp] = r; + } else { + ls[sp + 1] = r; + rs[sp + 1] = rs[sp]; + rs[sp] = l; + } + sp++; + } else + sp--; + } + for (l = v, m = v + (n - 1); l < m; l++) { + if (*l > *(l + 1)) { + c = *(l + 1); + it = array2[(l - v) + 1]; + for (r = l; r >= v && *r > c; r--) { + *(r + 1) = *r; + array2[(r - v) + 1] = array2[(r - v)]; + } + *(r + 1) = c; + array2[(r - v) + 1] = it; + } + } +} +//############################################################################# +//############################################################################# + +/**@name Ordered Triple Struct */ +template < class S, class T, class U > +class CoinTriple { +public: + /// First member of triple + S first; + /// Second member of triple + T second; + /// Third member of triple + U third; + +public: + /// Construct from ordered triple + CoinTriple(const S &s, const T &t, const U &u) + : first(s) + , second(t) + , third(u) + { + } +}; + +//############################################################################# +/**@name Comparisons on first element of two ordered triples */ +//@{ +/** Function operator. + Returns true if t1.first < t2.first (i.e., increasing). */ +template < class S, class T, class U > +class CoinFirstLess_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + return t1.first < t2.first; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if t1.first > t2.first (i.e, decreasing). */ +template < class S, class T, class U > +class CoinFirstGreater_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + return t1.first > t2.first; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) < abs(t2.first) (i.e., increasing). */ +template < class S, class T, class U > +class CoinFirstAbsLess_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; + return t1Abs < t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Returns true if abs(t1.first) > abs(t2.first) (i.e., decreasing). */ +template < class S, class T, class U > +class CoinFirstAbsGreater_3 { +public: + /// Compare function + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + const T t1Abs = t1.first < static_cast< T >(0) ? -t1.first : t1.first; + const T t2Abs = t2.first < static_cast< T >(0) ? -t2.first : t2.first; + return t1Abs > t2Abs; + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first < vec[t2.first] (i.e., increasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class U, class V > +class CoinExternalVectorFirstLess_3 { +private: + CoinExternalVectorFirstLess_3(); + +private: + const V *vec_; + +public: + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + return vec_[t1.first] < vec_[t2.first]; + } + CoinExternalVectorFirstLess_3(const V *v) + : vec_(v) + { + } +}; +//----------------------------------------------------------------------------- +/** Function operator. + Compare based on the entries of an external vector, i.e., returns true if + vec[t1.first > vec[t2.first] (i.e., decreasing wrt. vec). Note that to + use this comparison operator .first must be a data type automatically + convertible to int. */ +template < class S, class T, class U, class V > +class CoinExternalVectorFirstGreater_3 { +private: + CoinExternalVectorFirstGreater_3(); + +private: + const V *vec_; + +public: + inline bool operator()(const CoinTriple< S, T, U > &t1, + const CoinTriple< S, T, U > &t2) const + { + return vec_[t1.first] > vec_[t2.first]; + } + CoinExternalVectorFirstGreater_3(const V *v) + : vec_(v) + { + } +}; +//@} + +//############################################################################# + +/**@name Typedefs for sorting the entries of a packed vector based on an + external vector. */ +//@{ +/// Sort packed vector in increasing order of the external vector +typedef CoinExternalVectorFirstLess_3< int, int, double, double > + CoinIncrSolutionOrdered; +/// Sort packed vector in decreasing order of the external vector +typedef CoinExternalVectorFirstGreater_3< int, int, double, double > + CoinDecrSolutionOrdered; +//@} + +//############################################################################# + +/** Sort a triple of containers.
+ + Iter_S - iterator for first container
+ Iter_T - iterator for 2nd container
+ Iter_U - iterator for 3rd container
+ CoinCompare3 - class comparing CoinTriples
+*/ +#ifdef COIN_SORT_ARBITRARY_CONTAINERS +template < class Iter_S, class Iter_T, class Iter_U, class CoinCompare3 > +void CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst, + const CoinCompare3 &tc) +{ + typedef typename std::iterator_traits< Iter_S >::value_type S; + typedef typename std::iterator_traits< Iter_T >::value_type T; + typedef typename std::iterator_traits< Iter_U >::value_type U; + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinTriple< S, T, U > STU_triple; + STU_triple *x = static_cast< STU_triple * >(::operator new(len * sizeof(STU_triple))); + + int i = 0; + Iter_S scurrent = sfirst; + Iter_T tcurrent = tfirst; + Iter_U ucurrent = ufirst; + while (scurrent != slast) { + new (x + i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); + } + + std::sort(x, x + len, tc); + + scurrent = sfirst; + tcurrent = tfirst; + ucurrent = ufirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + *ucurrent++ = x[i].third; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template < class Iter_S, class Iter_T, class Iter_U > +void CoinSort_3(Iter_S sfirst, Iter_S slast, Iter_T tfirst, Iter_U, ufirst) +{ + typedef typename std::iterator_traits< Iter_S >::value_type S; + typedef typename std::iterator_traits< Iter_T >::value_type T; + typedef typename std::iterator_traits< Iter_U >::value_type U; + CoinSort_3(sfirts, slast, tfirst, ufirst, CoinFirstLess_3< S, T, U >()); +} + +#else //======================================================================= + +template < class S, class T, class U, class CoinCompare3 > +void CoinSort_3(S *sfirst, S *slast, T *tfirst, U *ufirst, const CoinCompare3 &tc) +{ + const size_t len = coinDistance(sfirst, slast); + if (len <= 1) + return; + + typedef CoinTriple< S, T, U > STU_triple; + STU_triple *x = static_cast< STU_triple * >(::operator new(len * sizeof(STU_triple))); + + size_t i = 0; + S *scurrent = sfirst; + T *tcurrent = tfirst; + U *ucurrent = ufirst; + while (scurrent != slast) { + new (x + i++) STU_triple(*scurrent++, *tcurrent++, *ucurrent++); + } + + std::sort(x, x + len, tc); + + scurrent = sfirst; + tcurrent = tfirst; + ucurrent = ufirst; + for (i = 0; i < len; ++i) { + *scurrent++ = x[i].first; + *tcurrent++ = x[i].second; + *ucurrent++ = x[i].third; + } + + ::operator delete(x); +} +//----------------------------------------------------------------------------- +template < class S, class T, class U > +void CoinSort_3(S *sfirst, S *slast, T *tfirst, U *ufirst) +{ + CoinSort_3(sfirst, slast, tfirst, ufirst, CoinFirstLess_3< S, T, U >()); +} + +#endif + +//############################################################################# + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinStructuredModel.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinStructuredModel.hpp new file mode 100644 index 000000000..33a8e0293 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinStructuredModel.hpp @@ -0,0 +1,270 @@ +/* $Id$ */ +// Copyright (C) 2008, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinStructuredModel_H +#define CoinStructuredModel_H + +#include "CoinModel.hpp" +#include + +/** + This is a model which is made up of Coin(Structured)Model blocks. +*/ +typedef struct CoinModelInfo2 { + int rowBlock; // Which row block + int columnBlock; // Which column block + char matrix; // nonzero if matrix exists + char rhs; // nonzero if non default rhs exists + char rowName; // nonzero if row names exists + char integer; // nonzero if integer information exists + char bounds; // nonzero if non default bounds/objective exists + char columnName; // nonzero if column names exists + CoinModelInfo2() + : rowBlock(0) + , columnBlock(0) + , matrix(0) + , rhs(0) + , rowName(0) + , integer(0) + , bounds(0) + , columnName(0) + { + } +} CoinModelBlockInfo; + +class CoinStructuredModel : public CoinBaseModel { + +public: + /**@name Useful methods for building model */ + //@{ + /** add a block from a CoinModel using names given as parameters + returns number of errors (e.g. both have objectives but not same) + */ + int addBlock(const std::string &rowBlock, + const std::string &columnBlock, + const CoinBaseModel &block); + /** add a block from a CoinModel with names in model + returns number of errors (e.g. both have objectives but not same) + */ + int addBlock(const CoinBaseModel &block); + /** add a block from a CoinModel using names given as parameters + returns number of errors (e.g. both have objectives but not same) + This passes in block - structured model takes ownership + */ + int addBlock(const std::string &rowBlock, + const std::string &columnBlock, + CoinBaseModel *block); + /** add a block using names + */ + int addBlock(const std::string &rowBlock, + const std::string &columnBlock, + const CoinPackedMatrix &matrix, + const double *rowLower, const double *rowUpper, + const double *columnLower, const double *columnUpper, + const double *objective); + + /** Write the problem in MPS format to a file with the given filename. + + \param compression can be set to three values to indicate what kind + of file should be written +
    +
  • 0: plain text (default) +
  • 1: gzip compressed (.gz is appended to \c filename) +
  • 2: bzip2 compressed (.bz2 is appended to \c filename) (TODO) +
+ If the library was not compiled with the requested compression then + writeMps falls back to writing a plain text file. + + \param formatType specifies the precision to used for values in the + MPS file +
    +
  • 0: normal precision (default) +
  • 1: extra accuracy +
  • 2: IEEE hex +
+ + \param numberAcross specifies whether 1 or 2 (default) values should be + specified on every data line in the MPS file. + + not const as may change model e.g. fill in default bounds + */ + int writeMps(const char *filename, int compression = 0, + int formatType = 0, int numberAcross = 2, bool keepStrings = false); + /// Read SMPS model + int readSmps(const char *filename, + bool keepNames = false, + bool ignoreErrors = false); + + /** Decompose a CoinModel + 1 - try D-W + 2 - try Benders + 3 - try Staircase + Returns number of blocks or zero if no structure + */ + int decompose(const CoinModel &model, int type, + int maxBlocks = 50, const char **starts = NULL); + /** Decompose a model specified as arrays + CoinPackedMatrix + 1 - try D-W + 2 - try Benders + 3 - try Staircase + Returns number of blocks or zero if no structure + */ + int decompose(const CoinPackedMatrix &matrix, + const double *rowLower, const double *rowUpper, + const double *columnLower, const double *columnUpper, + const double *objective, int type, int maxBlocks = 50, + int *starts = NULL, + double objectiveOffset = 0.0); + + //@} + + /**@name For getting information */ + //@{ + /// Return number of row blocks + inline int numberRowBlocks() const + { + return numberRowBlocks_; + } + /// Return number of column blocks + inline int numberColumnBlocks() const + { + return numberColumnBlocks_; + } + /// Return number of elementBlocks + inline int numberElementBlocks() const + { + return numberElementBlocks_; + } + /// Return number of elements + CoinBigIndex numberElements() const; + /// Return the i'th row block name + inline const std::string &getRowBlock(int i) const + { + return rowBlockNames_[i]; + } + /// Set i'th row block name + inline void setRowBlock(int i, const std::string &name) + { + rowBlockNames_[i] = name; + } + /// Add or check a row block name and number of rows + int addRowBlock(int numberRows, const std::string &name); + /// Return a row block index given a row block name + int rowBlock(const std::string &name) const; + /// Return i'th the column block name + inline const std::string &getColumnBlock(int i) const + { + return columnBlockNames_[i]; + } + /// Set i'th column block name + inline void setColumnBlock(int i, const std::string &name) + { + columnBlockNames_[i] = name; + } + /// Add or check a column block name and number of columns + int addColumnBlock(int numberColumns, const std::string &name); + /// Return a column block index given a column block name + int columnBlock(const std::string &name) const; + /// Return i'th block type + inline const CoinModelBlockInfo &blockType(int i) const + { + return blockType_[i]; + } + /// Return i'th block + inline CoinBaseModel *block(int i) const + { + return blocks_[i]; + } + /// Return block corresponding to row and column + const CoinBaseModel *block(int row, int column) const; + /// Return i'th block as CoinModel (or NULL) + CoinModel *coinBlock(int i) const; + /// Return block corresponding to row and column as CoinModel + const CoinBaseModel *coinBlock(int row, int column) const; + /// Return block number corresponding to row and column + int blockIndex(int row, int column) const; + /** Return model as a CoinModel block + and fill in info structure and update counts + */ + CoinModel *coinModelBlock(CoinModelBlockInfo &info); + /// Sets given block into coinModelBlocks_ + void setCoinModel(CoinModel *block, int iBlock); + /// Refresh info in blockType_ + void refresh(int iBlock); + /** Fill pointers corresponding to row and column */ + + CoinModelBlockInfo block(int row, int column, + const double *&rowLower, const double *&rowUpper, + const double *&columnLower, const double *&columnUpper, + const double *&objective) const; + /// Direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline double optimizationDirection() const + { + return optimizationDirection_; + } + /// Set direction of optimization (1 - minimize, -1 - maximize, 0 - ignore + inline void setOptimizationDirection(double value) + { + optimizationDirection_ = value; + } + //@} + + /**@name Constructors, destructor */ + //@{ + /** Default constructor. */ + CoinStructuredModel(); + /** Read a problem in MPS format from the given filename. + May try and decompose + */ + CoinStructuredModel(const char *fileName, int decompose = 0, + int maxBlocks = 50); + /** Destructor */ + virtual ~CoinStructuredModel(); + //@} + + /**@name Copy method */ + //@{ + /** The copy constructor. */ + CoinStructuredModel(const CoinStructuredModel &); + /// = + CoinStructuredModel &operator=(const CoinStructuredModel &); + /// Clone + virtual CoinBaseModel *clone() const; + //@} + +private: + /** Fill in info structure and update counts + Returns number of inconsistencies on border + */ + int fillInfo(CoinModelBlockInfo &info, const CoinModel *block); + /** Fill in info structure and update counts + */ + void fillInfo(CoinModelBlockInfo &info, const CoinStructuredModel *block); + /**@name Data members */ + //@{ + /// Current number of row blocks + int numberRowBlocks_; + /// Current number of column blocks + int numberColumnBlocks_; + /// Current number of element blocks + int numberElementBlocks_; + /// Maximum number of element blocks + int maximumElementBlocks_; + /// Rowblock name + std::vector< std::string > rowBlockNames_; + /// Columnblock name + std::vector< std::string > columnBlockNames_; + /// Blocks + CoinBaseModel **blocks_; + /// CoinModel copies of blocks or NULL if original CoinModel + CoinModel **coinModelBlocks_; + /// Which parts of model are set in block + CoinModelBlockInfo *blockType_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTime.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTime.hpp new file mode 100644 index 000000000..bc54e3560 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTime.hpp @@ -0,0 +1,350 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CoinTime_hpp +#define _CoinTime_hpp + +// Uncomment the next three lines for thorough memory initialisation. +// #ifndef ZEROFAULT +// # define ZEROFAULT +// #endif + +//############################################################################# + +#include +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#else +// MacOS-X and FreeBSD needs sys/time.h +#if defined(__MACH__) || defined(__FreeBSD__) +#include +#endif +#if !defined(__MSVCRT__) +#include +#endif +#endif + +//############################################################################# + +#if defined(_MSC_VER) + +#if 0 // change this to 1 if want to use the win32 API +#include +#ifdef small +/* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a + '#define small char' */ +#undef small +#endif +#define TWO_TO_THE_THIRTYTWO 4294967296.0 +#define DELTA_EPOCH_IN_SECS 11644473600.0 +inline double CoinGetTimeOfDay() +{ + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + double t = ft.dwHighDateTime * TWO_TO_THE_THIRTYTWO + ft.dwLowDateTime; + t = t/10000000.0 - DELTA_EPOCH_IN_SECS; + return t; +} +#else +#include +#include +inline double CoinGetTimeOfDay() +{ + struct _timeb timebuffer; +#pragma warning(disable : 4996) + _ftime(&timebuffer); // C4996 +#pragma warning(default : 4996) + return timebuffer.time + timebuffer.millitm / 1000.0; +} +#endif + +#else + +#include + +inline double CoinGetTimeOfDay() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return static_cast< double >(tv.tv_sec) + static_cast< int >(tv.tv_usec) / 1000000.0; +} + +#endif // _MSC_VER + +/** + Query the elapsed wallclock time since the first call to this function. If + a positive argument is passed to the function then the time of the first + call is set to that value (this kind of argument is allowed only at the + first call!). If a negative argument is passed to the function then it + returns the time when it was set. +*/ + +inline double CoinWallclockTime(double callType = 0) +{ + double callTime = CoinGetTimeOfDay(); + static const double firstCall = callType > 0 ? callType : callTime; + return callType < 0 ? firstCall : callTime - firstCall; +} + +//############################################################################# + +//#define HAVE_SDK // if SDK under Win32 is installed, for CPU instead of elapsed time under Win +#ifdef HAVE_SDK +#include +#ifdef small +/* for some unfathomable reason (to me) rpcndr.h (pulled in by windows.h) does a + '#define small char' */ +#undef small +#endif +#define TWO_TO_THE_THIRTYTWO 4294967296.0 +#endif + +static inline double CoinCpuTime() +{ +#ifdef COIN_DOING_DIFFS + // when trying to see differences between runs it can be helpful + return 0.0; +#endif + double cpu_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) +#ifdef HAVE_SDK + FILETIME creation; + FILETIME exit; + FILETIME kernel; + FILETIME user; + GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user); + double t = user.dwHighDateTime * TWO_TO_THE_THIRTYTWO + user.dwLowDateTime; + return t / 10000000.0; +#else + unsigned int ticksnow; /* clock_t is same as int */ + ticksnow = (unsigned int)clock(); + cpu_temp = (double)((double)ticksnow / CLOCKS_PER_SEC); +#endif + +#else + struct rusage usage; +#ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0; + usage.ru_utime.tv_usec = 0; +#endif + getrusage(RUSAGE_SELF, &usage); + cpu_temp = static_cast< double >(usage.ru_utime.tv_sec); + cpu_temp += 1.0e-6 * (static_cast< double >(usage.ru_utime.tv_usec)); +#endif + return cpu_temp; +} + +//############################################################################# + +static inline double CoinSysTime() +{ + double sys_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) + sys_temp = 0.0; +#else + struct rusage usage; +#ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0; + usage.ru_utime.tv_usec = 0; +#endif + getrusage(RUSAGE_SELF, &usage); + sys_temp = static_cast< double >(usage.ru_stime.tv_sec); + sys_temp += 1.0e-6 * (static_cast< double >(usage.ru_stime.tv_usec)); +#endif + return sys_temp; +} + +//############################################################################# +// On most systems SELF seems to include children threads, This is for when it doesn't +static inline double CoinCpuTimeJustChildren() +{ + double cpu_temp; +#if defined(_MSC_VER) || defined(__MSVCRT__) + cpu_temp = 0.0; +#else + struct rusage usage; +#ifdef ZEROFAULT + usage.ru_utime.tv_sec = 0; + usage.ru_utime.tv_usec = 0; +#endif + getrusage(RUSAGE_CHILDREN, &usage); + cpu_temp = static_cast< double >(usage.ru_utime.tv_sec); + cpu_temp += 1.0e-6 * (static_cast< double >(usage.ru_utime.tv_usec)); +#endif + return cpu_temp; +} +//############################################################################# + +#include + +/** + This class implements a timer that also implements a tracing functionality. + + The timer stores the start time of the timer, for how much time it was set to + and when does it expire (start + limit = end). Queries can be made that tell + whether the timer is expired, is past an absolute time, is past a percentage + of the length of the timer. All times are given in seconds, but as double + numbers, so there can be fractional values. + + The timer can also be initialized with a stream and a specification whether + to write to or read from the stream. In the former case the result of every + query is written into the stream, in the latter case timing is not tested at + all, rather the supposed result is read out from the stream. This makes it + possible to exactly retrace time sensitive program execution. +*/ +class CoinTimer { +private: + /// When the timer was initialized/reset/restarted + double start; + /// + double limit; + double end; +#ifdef COIN_COMPILE_WITH_TRACING + std::fstream *stream; + bool write_stream; +#endif + +private: +#ifdef COIN_COMPILE_WITH_TRACING + inline bool evaluate(bool b_tmp) const + { + int i_tmp = b_tmp; + if (stream) { + if (write_stream) + (*stream) << i_tmp << "\n"; + else + (*stream) >> i_tmp; + } + return i_tmp; + } + inline double evaluate(double d_tmp) const + { + if (stream) { + if (write_stream) + (*stream) << d_tmp << "\n"; + else + (*stream) >> d_tmp; + } + return d_tmp; + } +#else + inline bool evaluate(const bool b_tmp) const + { + return b_tmp; + } + inline double evaluate(const double d_tmp) const + { + return d_tmp; + } +#endif + +public: + /// Default constructor creates a timer with no time limit and no tracing + CoinTimer() + : start(0) + , limit(1e100) + , end(1e100) +#ifdef COIN_COMPILE_WITH_TRACING + , stream(0) + , write_stream(true) +#endif + { + } + + /// Create a timer with the given time limit and with no tracing + CoinTimer(double lim) + : start(CoinCpuTime()) + , limit(lim) + , end(start + lim) +#ifdef COIN_COMPILE_WITH_TRACING + , stream(0) + , write_stream(true) +#endif + { + } + +#ifdef COIN_COMPILE_WITH_TRACING + /** Create a timer with no time limit and with writing/reading the trace + to/from the given stream, depending on the argument \c write. */ + CoinTimer(std::fstream *s, bool write) + : start(0) + , limit(1e100) + , end(1e100) + , stream(s) + , write_stream(write) + { + } + + /** Create a timer with the given time limit and with writing/reading the + trace to/from the given stream, depending on the argument \c write. */ + CoinTimer(double lim, std::fstream *s, bool w) + : start(CoinCpuTime()) + , limit(lim) + , end(start + lim) + , stream(s) + , write_stream(w) + { + } +#endif + + /// Restart the timer (keeping the same time limit) + inline void restart() + { + start = CoinCpuTime(); + end = start + limit; + } + /// An alternate name for \c restart() + inline void reset() { restart(); } + /// Reset (and restart) the timer and change its time limit + inline void reset(double lim) + { + limit = lim; + restart(); + } + + /** Return whether the given percentage of the time limit has elapsed since + the timer was started */ + inline bool isPastPercent(double pct) const + { + return evaluate(start + limit * pct < CoinCpuTime()); + } + /** Return whether the given amount of time has elapsed since the timer was + started */ + inline bool isPast(double lim) const + { + return evaluate(start + lim < CoinCpuTime()); + } + /** Return whether the originally specified time limit has passed since the + timer was started */ + inline bool isExpired() const + { + return evaluate(end < CoinCpuTime()); + } + + /** Return how much time is left on the timer */ + inline double timeLeft() const + { + return evaluate(end - CoinCpuTime()); + } + + /** Return how much time has elapsed */ + inline double timeElapsed() const + { + return evaluate(CoinCpuTime() - start); + } + + inline void setLimit(double l) + { + limit = l; + return; + } +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTypes.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTypes.hpp new file mode 100644 index 000000000..d5006054f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinTypes.hpp @@ -0,0 +1,67 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef _CoinTypes_hpp +#define _CoinTypes_hpp + +#include "CoinUtilsConfig.h" +/* On some systems, we require stdint.h to have the 64bit integer type defined. */ +#ifdef COINUTILS_HAS_STDINT_H +#include +#endif +#ifdef COINUTILS_HAS_CSTDINT +#include +#endif + +#define CoinInt64 COIN_INT64_T +#define CoinUInt64 COIN_UINT64_T +#define CoinIntPtr COIN_INTPTR_T + +//============================================================================= +#ifndef COIN_BIG_INDEX +#define COIN_BIG_INDEX 0 +#endif + +#if COIN_BIG_INDEX == 0 +typedef int CoinBigIndex; +#elif COIN_BIG_INDEX == 1 +typedef long CoinBigIndex; +#else +typedef long long CoinBigIndex; +#endif + +//============================================================================= +#ifndef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 0 +#endif + +// See if we want the ability to have long double work arrays +#if COIN_BIG_DOUBLE == 2 +#undef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 0 +#define COIN_LONG_WORK 1 +typedef long double CoinWorkDouble; +#elif COIN_BIG_DOUBLE == 3 +#undef COIN_BIG_DOUBLE +#define COIN_BIG_DOUBLE 1 +#define COIN_LONG_WORK 1 +typedef long double CoinWorkDouble; +#else +#define COIN_LONG_WORK 0 +typedef double CoinWorkDouble; +#endif + +#if COIN_BIG_DOUBLE == 0 +typedef double CoinFactorizationDouble; +#elif COIN_BIG_DOUBLE == 1 +typedef long double CoinFactorizationDouble; +#else +typedef double CoinFactorizationDouble; +#endif + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtility.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtility.hpp new file mode 100644 index 000000000..19cee3e63 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtility.hpp @@ -0,0 +1,26 @@ +/* $Id$ */ +// Copyright (C) 2004, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinUtility_h_ +#define CoinUtility_h_ + +#include "CoinSort.hpp" + +template < typename S, typename T > +CoinPair< S, T > CoinMakePair(const S &s, const T &t) +{ + return CoinPair< S, T >(s, t); +} + +template < typename S, typename T, typename U > +CoinTriple< S, T, U > CoinMakeTriple(const S &s, const T &t, const U &u) +{ + return CoinTriple< S, T, U >(s, t, u); +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtilsConfig.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtilsConfig.h new file mode 100644 index 000000000..a34a2049a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinUtilsConfig.h @@ -0,0 +1,34 @@ +/* src/config_coinutils.h. Generated by configure. */ +/* inc/config_coinutils.h.in. */ + +#ifndef __CONFIG_COINUTILS_H__ +#define __CONFIG_COINUTILS_H__ + +/* Define to 1 if stdint.h is available for CoinUtils */ +#define COINUTILS_HAS_STDINT_H 1 + +/* Define to 1 if stdint.h is available for CoinUtils */ +#define COINUTILS_HAS_CSTDINT 1 + +/* Version number of project */ +#define COINUTILS_VERSION "2.11" + +/* Major Version number of project */ +#define COINUTILS_VERSION_MAJOR 2 + +/* Minor Version number of project */ +#define COINUTILS_VERSION_MINOR 11 + +/* Release Version number of project */ +#define COINUTILS_VERSION_RELEASE 9999 + +/* Define to 64bit integer type */ +#define COIN_INT64_T int64_t + +/* Define to integer type capturing pointer */ +#define COIN_INTPTR_T intptr_t + +/* Define to 64bit unsigned integer type */ +#define COIN_UINT64_T int64_t + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStart.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStart.hpp new file mode 100644 index 000000000..a250d2b78 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStart.hpp @@ -0,0 +1,56 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStart_H +#define CoinWarmStart_H + +//############################################################################# + +class CoinWarmStartDiff; + +/** Abstract base class for warm start information. + + Really nothing can be generalized for warm start information --- all we + know is that it exists. Hence the abstract base class contains only a + virtual destructor and a virtual clone function (a virtual constructor), + so that derived classes can provide these functions. +*/ + +class CoinWarmStart { +public: + /// Abstract destructor + virtual ~CoinWarmStart() {} + + /// `Virtual constructor' + virtual CoinWarmStart *clone() const = 0; + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const) const { return 0; } + + virtual void + applyDiff(const CoinWarmStartDiff *const) {} +}; + +/*! \class CoinWarmStartDiff + \brief Abstract base class for warm start `diff' objects + + For those types of warm start objects where the notion of a `diff' makes + sense, this virtual base class is provided. As with CoinWarmStart, its sole + reason for existence is to make it possible to write solver-independent code. +*/ + +class CoinWarmStartDiff { +public: + /// Abstract destructor + virtual ~CoinWarmStartDiff() {} + + /// `Virtual constructor' + virtual CoinWarmStartDiff *clone() const = 0; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartBasis.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartBasis.hpp new file mode 100644 index 000000000..765414ee2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartBasis.hpp @@ -0,0 +1,468 @@ +/* $Id$ */ +/*! \legal + Copyright (C) 2000 -- 2003, International Business Machines Corporation + and others. All Rights Reserved. + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ + +/*! \file CoinWarmStart.hpp + \brief Declaration of the generic simplex (basis-oriented) warm start + class. Also contains a basis diff class. +*/ + +#ifndef CoinWarmStartBasis_H +#define CoinWarmStartBasis_H + +#include + +#include "CoinSort.hpp" +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" + +//############################################################################# + +/*! \class CoinWarmStartBasis + \brief The default COIN simplex (basis-oriented) warm start class + + CoinWarmStartBasis provides for a warm start object which contains the + status of each variable (structural and artificial). + + \todo Modify this class so that the number of status entries per byte + and bytes per status vector allocation unit are not hardcoded. + At the least, collect this into a couple of macros. + + \todo Consider separate fields for allocated capacity and actual basis + size. We could avoid some reallocation, at the price of retaining + more space than we need. Perhaps more important, we could do much + better sanity checks. +*/ + +class CoinWarmStartBasis : public virtual CoinWarmStart { +public: + /*! \brief Enum for status of variables + + Matches CoinPrePostsolveMatrix::Status, without superBasic. Most code that + converts between CoinPrePostsolveMatrix::Status and + CoinWarmStartBasis::Status will break if this correspondence is broken. + + The status vectors are currently packed using two bits per status code, + four codes per byte. The location of the status information for + variable \c i is in byte i>>2 and occupies bits 0:1 + if i\%4 == 0, bits 2:3 if i\%4 == 1, etc. + The non-member functions getStatus(const char*,int) and + setStatus(char*,int,CoinWarmStartBasis::Status) are provided to hide + details of the packing. + */ + enum Status { + isFree = 0x00, ///< Nonbasic free variable + basic = 0x01, ///< Basic variable + atUpperBound = 0x02, ///< Nonbasic at upper bound + atLowerBound = 0x03, ///< Nonbasic at lower bound + superBasic = 0x04 ///< Not basic and not at bound + }; + + /** \brief Transfer vector entry for + mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) + */ + typedef CoinTriple< int, int, int > XferEntry; + + /** \brief Transfer vector for + mergeBasis(const CoinWarmStartBasis*,const XferVec*,const XferVec*) + */ + typedef std::vector< XferEntry > XferVec; + +public: + /*! \name Methods to get and set basis information. + + The status of variables is kept in a pair of arrays, one for structural + variables, and one for artificials (aka logicals and slacks). The status + is coded using the values of the Status enum. + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. +*/ + //@{ + /// Return the number of structural variables + inline int getNumStructural() const { return numStructural_; } + + /// Return the number of artificial variables + inline int getNumArtificial() const { return numArtificial_; } + + /** Return the number of basic structurals + + A fast test for an all-slack basis. + */ + int numberBasicStructurals() const; + + /// Return the status of the specified structural variable. + inline Status getStructStatus(int i) const + { + const int st = (structuralStatus_[i >> 2] >> ((i & 3) << 1)) & 3; + return static_cast< CoinWarmStartBasis::Status >(st); + } + + /// Set the status of the specified structural variable. + inline void setStructStatus(int i, Status st) + { + char &st_byte = structuralStatus_[i >> 2]; + st_byte = static_cast< char >(st_byte & ~(3 << ((i & 3) << 1))); + st_byte = static_cast< char >(st_byte | (st << ((i & 3) << 1))); + } + + /** Return the status array for the structural variables + + The status information is stored using the codes defined in the + Status enum, 2 bits per variable, packed 4 variables per byte. + */ + inline char *getStructuralStatus() { return structuralStatus_; } + + /** \c const overload for + \link CoinWarmStartBasis::getStructuralStatus() + getStructuralStatus() + \endlink + */ + inline const char *getStructuralStatus() const { return structuralStatus_; } + + /** As for \link getStructuralStatus() getStructuralStatus \endlink, + but returns the status array for the artificial variables. + */ + inline char *getArtificialStatus() { return artificialStatus_; } + + /// Return the status of the specified artificial variable. + inline Status getArtifStatus(int i) const + { + const int st = (artificialStatus_[i >> 2] >> ((i & 3) << 1)) & 3; + return static_cast< CoinWarmStartBasis::Status >(st); + } + + /// Set the status of the specified artificial variable. + inline void setArtifStatus(int i, Status st) + { + char &st_byte = artificialStatus_[i >> 2]; + st_byte = static_cast< char >(st_byte & ~(3 << ((i & 3) << 1))); + st_byte = static_cast< char >(st_byte | (st << ((i & 3) << 1))); + } + + /** \c const overload for + \link CoinWarmStartBasis::getArtificialStatus() + getArtificialStatus() + \endlink + */ + inline const char *getArtificialStatus() const { return artificialStatus_; } + //@} + + /*! \name Basis `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start basis passed as + a parameter to the warm start basis specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const oldCWS) const; + + /*! \brief Apply \p diff to this basis + + Update this basis by applying \p diff. It's assumed that the allocated + capacity of the basis is sufficiently large. + */ + + virtual void + applyDiff(const CoinWarmStartDiff *const cwsdDiff); + + //@} + + /*! \name Methods to modify the warm start object */ + //@{ + + /*! \brief Set basis capacity; existing basis is discarded. + + After execution of this routine, the warm start object does not describe + a valid basis: all structural and artificial variables have status isFree. + */ + virtual void setSize(int ns, int na); + + /*! \brief Set basis capacity; existing basis is maintained. + + After execution of this routine, the warm start object describes a valid + basis: the status of new structural variables (added columns) is set to + nonbasic at lower bound, and the status of new artificial variables + (added rows) is set to basic. (The basis can be invalid if new structural + variables do not have a finite lower bound.) + */ + virtual void resize(int newNumberRows, int newNumberColumns); + + /** \brief Delete a set of rows from the basis + + \warning + This routine assumes that the set of indices to be deleted is sorted in + ascending order and contains no duplicates. Use deleteRows() if this is + not the case. + + \warning + The resulting basis is guaranteed valid only if all deleted + constraints are slack (hence the associated logicals are basic). + + Removal of a tight constraint with a nonbasic logical implies that + some basic variable must be made nonbasic. This correction is left to + the client. + */ + + virtual void compressRows(int tgtCnt, const int *tgts); + + /** \brief Delete a set of rows from the basis + + \warning + The resulting basis is guaranteed valid only if all deleted + constraints are slack (hence the associated logicals are basic). + + Removal of a tight constraint with a nonbasic logical implies that + some basic variable must be made nonbasic. This correction is left to + the client. + */ + + virtual void deleteRows(int rawTgtCnt, const int *rawTgts); + + /** \brief Delete a set of columns from the basis + + \warning + The resulting basis is guaranteed valid only if all deleted variables + are nonbasic. + + Removal of a basic variable implies that some nonbasic variable must be + made basic. This correction is left to the client. + */ + + virtual void deleteColumns(int number, const int *which); + + /** \brief Merge entries from a source basis into this basis. + + \warning + It's the client's responsibility to ensure validity of the merged basis, + if that's important to the application. + + The vector xferCols (xferRows) specifies runs of entries to be taken from + the source basis and placed in this basis. Each entry is a CoinTriple, + with first specifying the starting source index of a run, second + specifying the starting destination index, and third specifying the run + length. + */ + virtual void mergeBasis(const CoinWarmStartBasis *src, + const XferVec *xferRows, + const XferVec *xferCols); + + //@} + + /*! \name Constructors, destructors, and related functions */ + + //@{ + + /** Default constructor + + Creates a warm start object representing an empty basis + (0 rows, 0 columns). + */ + CoinWarmStartBasis(); + + /** Constructs a warm start object with the specified status vectors. + + The parameters are copied. + Consider assignBasisStatus(int,int,char*&,char*&) if the object should + assume ownership. + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. + */ + CoinWarmStartBasis(int ns, int na, const char *sStat, const char *aStat); + + /** Copy constructor */ + CoinWarmStartBasis(const CoinWarmStartBasis &ws); + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartBasis(*this); + } + + /** Destructor */ + virtual ~CoinWarmStartBasis(); + + /** Assignment */ + + virtual CoinWarmStartBasis &operator=(const CoinWarmStartBasis &rhs); + + /** Assign the status vectors to be the warm start information. + + In this method the CoinWarmStartBasis object assumes ownership of the + pointers and upon return the argument pointers will be NULL. + If copying is desirable, use the + \link CoinWarmStartBasis(int,int,const char*,const char*) + array constructor \endlink + or the + \link operator=(const CoinWarmStartBasis&) + assignment operator \endlink. + + \note + The pointers passed to this method will be + freed using delete[], so they must be created using new[]. + */ + virtual void assignBasisStatus(int ns, int na, char *&sStat, char *&aStat); + //@} + + /*! \name Miscellaneous methods */ + //@{ + + /// Prints in readable format (for debug) + virtual void print() const; + /// Returns true if full basis (for debug) + bool fullBasis() const; + /// Returns true if full basis and fixes up (for debug) + bool fixFullBasis(); + + //@} + +protected: + /** \name Protected data members + + \sa CoinWarmStartBasis::Status for a description of the packing used in + the status arrays. + */ + //@{ + /// The number of structural variables + int numStructural_; + /// The number of artificial variables + int numArtificial_; + /// The maximum sise (in ints - actually 4*char) (so resize does not need to do new) + int maxSize_; + /** The status of the structural variables. */ + char *structuralStatus_; + /** The status of the artificial variables. */ + char *artificialStatus_; + //@} +}; + +/*! \relates CoinWarmStartBasis + \brief Get the status of the specified variable in the given status array. +*/ + +inline CoinWarmStartBasis::Status getStatus(const char *array, int i) +{ + const int st = (array[i >> 2] >> ((i & 3) << 1)) & 3; + return static_cast< CoinWarmStartBasis::Status >(st); +} + +/*! \relates CoinWarmStartBasis + \brief Set the status of the specified variable in the given status array. +*/ + +inline void setStatus(char *array, int i, CoinWarmStartBasis::Status st) +{ + char &st_byte = array[i >> 2]; + st_byte = static_cast< char >(st_byte & ~(3 << ((i & 3) << 1))); + st_byte = static_cast< char >(st_byte | (st << ((i & 3) << 1))); +} + +/*! \relates CoinWarmStartBasis + \brief Generate a print string for a status code +*/ +const char *statusName(CoinWarmStartBasis::Status status); +/** In an example Aleksandr Kazachkov sent to me, I noticed he was + using code as above but with char - it seemed useful + B, F, U, L, S (S - SuperBasic) + */ +/// Convert status to character. +char statusToChar(CoinWarmStartBasis::Status status); +/// Convert character to status +CoinWarmStartBasis::Status charToStatus(char status); + +/*! \class CoinWarmStartBasisDiff + \brief A `diff' between two CoinWarmStartBasis objects + + This class exists in order to hide from the world the details of + calculating and representing a `diff' between two CoinWarmStartBasis + objects. For convenience, assignment, cloning, and deletion are visible to + the world, and default and copy constructors are made available to derived + classes. Knowledge of the rest of this structure, and of generating and + applying diffs, is restricted to the friend functions + CoinWarmStartBasis::generateDiff() and CoinWarmStartBasis::applyDiff(). + + The actual data structure is an unsigned int vector, #difference_ which + starts with indices of changed and then has values starting after #sze_ + + \todo This is a pretty generic structure, and vector diff is a pretty generic + activity. We should be able to convert this to a template. + + \todo Using unsigned int as the data type for the diff vectors might help + to contain the damage when this code is inevitably compiled for 64 bit + architectures. But the notion of int as 4 bytes is hardwired into + CoinWarmStartBasis, so changes are definitely required. +*/ + +class CoinWarmStartBasisDiff : public virtual CoinWarmStartDiff { +public: + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff *clone() const + { + CoinWarmStartBasisDiff *cwsbd = new CoinWarmStartBasisDiff(*this); + return (dynamic_cast< CoinWarmStartDiff * >(cwsbd)); + } + + /*! \brief Assignment */ + virtual CoinWarmStartBasisDiff &operator=(const CoinWarmStartBasisDiff &rhs); + + /*! \brief Destructor */ + virtual ~CoinWarmStartBasisDiff(); + +protected: + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make their default constructor protected or + private. + */ + CoinWarmStartBasisDiff() + : sze_(0) + , difference_(0) + { + } + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartBasisDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + + This is protected (rather than private) so that derived classes can + see it when they make their copy constructor protected or + private. + */ + CoinWarmStartBasisDiff(const CoinWarmStartBasisDiff &cwsbd); + + /*! \brief Standard constructor */ + CoinWarmStartBasisDiff(int sze, const unsigned int *const diffNdxs, + const unsigned int *const diffVals); + + /*! \brief Constructor when full is smaller than diff!*/ + CoinWarmStartBasisDiff(const CoinWarmStartBasis *rhs); + +private: + friend CoinWarmStartDiff * + CoinWarmStartBasis::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartBasis::applyDiff(const CoinWarmStartDiff *const diff); + + /*! \brief Number of entries (and allocated capacity), in units of \c int. */ + int sze_; + + /*! \brief Array of diff indices and diff values */ + + unsigned int *difference_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartDual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartDual.hpp new file mode 100644 index 000000000..97cf9b291 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartDual.hpp @@ -0,0 +1,180 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartDual_H +#define CoinWarmStartDual_H + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" +#include "CoinWarmStartVector.hpp" + +//############################################################################# + +/** WarmStart information that is only a dual vector */ + +class CoinWarmStartDual : public virtual CoinWarmStart { +public: + /// return the size of the dual vector + inline int size() const { return dual_.size(); } + /// return a pointer to the array of duals + inline const double *dual() const { return dual_.values(); } + + /** Assign the dual vector to be the warmstart information. In this method + the object assumes ownership of the pointer and upon return "dual" will + be a NULL pointer. If copying is desirable use the constructor. */ + inline void assignDual(int size, double *&dual) + { + dual_.assignVector(size, dual); + } + + CoinWarmStartDual() {} + + CoinWarmStartDual(int size, const double *dual) + : dual_(size, dual) + { + } + + CoinWarmStartDual(const CoinWarmStartDual &rhs) + : dual_(rhs.dual_) + { + } + + CoinWarmStartDual &operator=(const CoinWarmStartDual &rhs) + { + if (this != &rhs) { + dual_ = rhs.dual_; + } + return *this; + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartDual(*this); + } + + virtual ~CoinWarmStartDual() {} + + /*! \name Dual warm start `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const oldCWS) const; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff(const CoinWarmStartDiff *const cwsdDiff); + +#if 0 +protected: + inline const CoinWarmStartVector& warmStartVector() const { return dual_; } +#endif + + //@} + +private: + ///@name Private data members + CoinWarmStartVector< double > dual_; +}; + +//############################################################################# + +/*! \class CoinWarmStartDualDiff + \brief A `diff' between two CoinWarmStartDual objects + + This class exists in order to hide from the world the details of + calculating and representing a `diff' between two CoinWarmStartDual + objects. For convenience, assignment, cloning, and deletion are visible to + the world, and default and copy constructors are made available to derived + classes. Knowledge of the rest of this structure, and of generating and + applying diffs, is restricted to the friend functions + CoinWarmStartDual::generateDiff() and CoinWarmStartDual::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +class CoinWarmStartDualDiff : public virtual CoinWarmStartDiff { +public: + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartDualDiff(*this); + } + + /*! \brief Assignment */ + virtual CoinWarmStartDualDiff &operator=(const CoinWarmStartDualDiff &rhs) + { + if (this != &rhs) { + diff_ = rhs.diff_; + } + return *this; + } + + /*! \brief Destructor */ + virtual ~CoinWarmStartDualDiff() {} + +protected: + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make their default constructor protected or + private. + */ + CoinWarmStartDualDiff() + : diff_() + { + } + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartDualDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + + This is protected (rather than private) so that derived classes can + see it when the make their copy constructor protected or + private. + */ + CoinWarmStartDualDiff(const CoinWarmStartDualDiff &rhs) + : diff_(rhs.diff_) + { + } + +private: + friend CoinWarmStartDiff * + CoinWarmStartDual::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartDual::applyDiff(const CoinWarmStartDiff *const diff); + + /*! \brief Standard constructor */ + CoinWarmStartDualDiff(int sze, const unsigned int *const diffNdxs, + const double *const diffVals) + : diff_(sze, diffNdxs, diffVals) + { + } + + /*! + \brief The difference in the dual vector is simply the difference in a + vector. + */ + CoinWarmStartVectorDiff< double > diff_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartPrimalDual.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartPrimalDual.hpp new file mode 100644 index 000000000..8f40537c2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartPrimalDual.hpp @@ -0,0 +1,233 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartPrimalDual_H +#define CoinWarmStartPrimalDual_H + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" +#include "CoinWarmStartVector.hpp" + +//############################################################################# + +/** WarmStart information that is only a dual vector */ + +class CoinWarmStartPrimalDual : public virtual CoinWarmStart { +public: + /// return the size of the dual vector + inline int dualSize() const { return dual_.size(); } + /// return a pointer to the array of duals + inline const double *dual() const { return dual_.values(); } + + /// return the size of the primal vector + inline int primalSize() const { return primal_.size(); } + /// return a pointer to the array of primals + inline const double *primal() const { return primal_.values(); } + + /** Assign the primal/dual vectors to be the warmstart information. In this + method the object assumes ownership of the pointers and upon return \c + primal and \c dual will be a NULL pointers. If copying is desirable use + the constructor. + + NOTE: \c primal and \c dual must have been allocated by new double[], + because they will be freed by delete[] upon the desructtion of this + object... + */ + void assign(int primalSize, int dualSize, double *&primal, double *&dual) + { + primal_.assignVector(primalSize, primal); + dual_.assignVector(dualSize, dual); + } + + CoinWarmStartPrimalDual() + : primal_() + , dual_() + { + } + + CoinWarmStartPrimalDual(int primalSize, int dualSize, + const double *primal, const double *dual) + : primal_(primalSize, primal) + , dual_(dualSize, dual) + { + } + + CoinWarmStartPrimalDual(const CoinWarmStartPrimalDual &rhs) + : primal_(rhs.primal_) + , dual_(rhs.dual_) + { + } + + CoinWarmStartPrimalDual &operator=(const CoinWarmStartPrimalDual &rhs) + { + if (this != &rhs) { + primal_ = rhs.primal_; + dual_ = rhs.dual_; + } + return *this; + } + + /*! \brief Clear the data + + Make it appear as if the warmstart was just created using the default + constructor. + */ + inline void clear() + { + primal_.clear(); + dual_.clear(); + } + + inline void swap(CoinWarmStartPrimalDual &rhs) + { + if (this != &rhs) { + primal_.swap(rhs.primal_); + dual_.swap(rhs.dual_); + } + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartPrimalDual(*this); + } + + virtual ~CoinWarmStartPrimalDual() {} + + /*! \name PrimalDual warm start `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const oldCWS) const; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff(const CoinWarmStartDiff *const cwsdDiff); + + //@} + +#if 0 +protected: + inline const CoinWarmStartVector& primalWarmStartVector() const + { return primal_; } + inline const CoinWarmStartVector& dualWarmStartVector() const + { return dual_; } +#endif + +private: + ///@name Private data members + //@{ + CoinWarmStartVector< double > primal_; + CoinWarmStartVector< double > dual_; + //@} +}; + +//############################################################################# + +/*! \class CoinWarmStartPrimalDualDiff + \brief A `diff' between two CoinWarmStartPrimalDual objects + + This class exists in order to hide from the world the details of calculating + and representing a `diff' between two CoinWarmStartPrimalDual objects. For + convenience, assignment, cloning, and deletion are visible to the world, and + default and copy constructors are made available to derived classes. + Knowledge of the rest of this structure, and of generating and applying + diffs, is restricted to the friend functions + CoinWarmStartPrimalDual::generateDiff() and + CoinWarmStartPrimalDual::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +class CoinWarmStartPrimalDualDiff : public virtual CoinWarmStartDiff { + friend CoinWarmStartDiff * + CoinWarmStartPrimalDual::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartPrimalDual::applyDiff(const CoinWarmStartDiff *const diff); + +public: + /*! \brief `Virtual constructor'. To be used when retaining polymorphism is + important */ + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartPrimalDualDiff(*this); + } + + /*! \brief Destructor */ + virtual ~CoinWarmStartPrimalDualDiff() {} + +protected: + /*! \brief Default constructor + + This is protected (rather than private) so that derived classes can + see it when they make their default constructor protected or + private. + */ + CoinWarmStartPrimalDualDiff() + : primalDiff_() + , dualDiff_() + { + } + + /*! \brief Copy constructor + + For convenience when copying objects containing + CoinWarmStartPrimalDualDiff objects. But consider whether you should be + using #clone() to retain polymorphism. + + This is protected (rather than private) so that derived classes can + see it when the make their copy constructor protected or + private. + */ + CoinWarmStartPrimalDualDiff(const CoinWarmStartPrimalDualDiff &rhs) + : primalDiff_(rhs.primalDiff_) + , dualDiff_(rhs.dualDiff_) + { + } + + /*! \brief Clear the data + + Make it appear as if the diff was just created using the default + constructor. + */ + inline void clear() + { + primalDiff_.clear(); + dualDiff_.clear(); + } + + inline void swap(CoinWarmStartPrimalDualDiff &rhs) + { + if (this != &rhs) { + primalDiff_.swap(rhs.primalDiff_); + dualDiff_.swap(rhs.dualDiff_); + } + } + +private: + /*! + \brief These two differences describe the differences in the primal and + in the dual vector. + */ + CoinWarmStartVectorDiff< double > primalDiff_; + CoinWarmStartVectorDiff< double > dualDiff_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartVector.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartVector.hpp new file mode 100644 index 000000000..d78c18b26 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/CoinWarmStartVector.hpp @@ -0,0 +1,523 @@ +/* $Id$ */ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef CoinWarmStartVector_H +#define CoinWarmStartVector_H + +#if defined(_MSC_VER) +// Turn off compiler warning about long names +#pragma warning(disable : 4786) +#endif + +#include +#include + +#include "CoinHelperFunctions.hpp" +#include "CoinWarmStart.hpp" + +//############################################################################# + +/** WarmStart information that is only a vector */ + +template < typename T > +class CoinWarmStartVector : public virtual CoinWarmStart { +protected: + inline void gutsOfDestructor() + { + delete[] values_; + } + inline void gutsOfCopy(const CoinWarmStartVector< T > &rhs) + { + size_ = rhs.size_; + values_ = new T[size_]; + CoinDisjointCopyN(rhs.values_, size_, values_); + } + +public: + /// return the size of the vector + int size() const { return size_; } + /// return a pointer to the array of vectors + const T *values() const { return values_; } + + /** Assign the vector to be the warmstart information. In this method + the object assumes ownership of the pointer and upon return #vector will + be a NULL pointer. If copying is desirable use the constructor. */ + void assignVector(int size, T *&vec) + { + size_ = size; + delete[] values_; + values_ = vec; + vec = NULL; + } + + CoinWarmStartVector() + : size_(0) + , values_(NULL) + { + } + + CoinWarmStartVector(int size, const T *vec) + : size_(size) + , values_(new T[size]) + { + CoinDisjointCopyN(vec, size, values_); + } + + CoinWarmStartVector(const CoinWarmStartVector &rhs) + { + gutsOfCopy(rhs); + } + + CoinWarmStartVector &operator=(const CoinWarmStartVector &rhs) + { + if (this != &rhs) { + gutsOfDestructor(); + gutsOfCopy(rhs); + } + return *this; + } + + inline void swap(CoinWarmStartVector &rhs) + { + if (this != &rhs) { + std::swap(size_, rhs.size_); + std::swap(values_, rhs.values_); + } + } + + /** `Virtual constructor' */ + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartVector(*this); + } + + virtual ~CoinWarmStartVector() + { + gutsOfDestructor(); + } + + /*! \brief Clear the data + + Make it appear as if the warmstart was just created using the default + constructor. + */ + inline void clear() + { + size_ = 0; + delete[] values_; + values_ = NULL; + } + + /*! \name Vector warm start `diff' methods */ + //@{ + + /*! \brief Generate a `diff' that can convert the warm start passed as a + parameter to the warm start specified by \c this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by \c this. + */ + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const oldCWS) const; + + /*! \brief Apply \p diff to this warm start. + + Update this warm start by applying \p diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. + */ + + virtual void applyDiff(const CoinWarmStartDiff *const cwsdDiff); + + //@} + +private: + ///@name Private data members + //@{ + /// the size of the vector + int size_; + /// the vector itself + T *values_; + //@} +}; + +//============================================================================= + +/*! \class CoinWarmStartVectorDiff + \brief A `diff' between two CoinWarmStartVector objects + + This class exists in order to hide from the world the details of calculating + and representing a `diff' between two CoinWarmStartVector objects. For + convenience, assignment, cloning, and deletion are visible to the world, and + default and copy constructors are made available to derived classes. + Knowledge of the rest of this structure, and of generating and applying + diffs, is restricted to the friend functions + CoinWarmStartVector::generateDiff() and CoinWarmStartVector::applyDiff(). + + The actual data structure is a pair of vectors, #diffNdxs_ and #diffVals_. + +*/ + +template < typename T > +class CoinWarmStartVectorDiff : public virtual CoinWarmStartDiff { + friend CoinWarmStartDiff * + CoinWarmStartVector< T >::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartVector< T >::applyDiff(const CoinWarmStartDiff *const diff); + +public: + /*! \brief `Virtual constructor' */ + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartVectorDiff(*this); + } + + /*! \brief Assignment */ + virtual CoinWarmStartVectorDiff & + operator=(const CoinWarmStartVectorDiff< T > &rhs); + + /*! \brief Destructor */ + virtual ~CoinWarmStartVectorDiff() + { + delete[] diffNdxs_; + delete[] diffVals_; + } + + inline void swap(CoinWarmStartVectorDiff &rhs) + { + if (this != &rhs) { + std::swap(sze_, rhs.sze_); + std::swap(diffNdxs_, rhs.diffNdxs_); + std::swap(diffVals_, rhs.diffVals_); + } + } + + /*! \brief Default constructor + */ + CoinWarmStartVectorDiff() + : sze_(0) + , diffNdxs_(0) + , diffVals_(NULL) + { + } + + /*! \brief Copy constructor + + For convenience when copying objects containing CoinWarmStartVectorDiff + objects. But consider whether you should be using #clone() to retain + polymorphism. + */ + CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff< T > &rhs); + + /*! \brief Standard constructor */ + CoinWarmStartVectorDiff(int sze, const unsigned int *const diffNdxs, + const T *const diffVals); + + /*! \brief Clear the data + + Make it appear as if the diff was just created using the default + constructor. + */ + inline void clear() + { + sze_ = 0; + delete[] diffNdxs_; + diffNdxs_ = NULL; + delete[] diffVals_; + diffVals_ = NULL; + } + +private: + /*! + \brief Number of entries (and allocated capacity), in units of \c T. + */ + int sze_; + + /*! \brief Array of diff indices */ + + unsigned int *diffNdxs_; + + /*! \brief Array of diff values */ + + T *diffVals_; +}; + +//############################################################################## + +template < typename T, typename U > +class CoinWarmStartVectorPair : public virtual CoinWarmStart { +private: + CoinWarmStartVector< T > t_; + CoinWarmStartVector< U > u_; + +public: + inline int size0() const { return t_.size(); } + inline int size1() const { return u_.size(); } + inline const T *values0() const { return t_.values(); } + inline const U *values1() const { return u_.values(); } + + inline void assignVector0(int size, T *&vec) { t_.assignVector(size, vec); } + inline void assignVector1(int size, U *&vec) { u_.assignVector(size, vec); } + + CoinWarmStartVectorPair() {} + CoinWarmStartVectorPair(int s0, const T *v0, int s1, const U *v1) + : t_(s0, v0) + , u_(s1, v1) + { + } + + CoinWarmStartVectorPair(const CoinWarmStartVectorPair< T, U > &rhs) + : t_(rhs.t_) + , u_(rhs.u_) + { + } + CoinWarmStartVectorPair &operator=(const CoinWarmStartVectorPair< T, U > &rhs) + { + if (this != &rhs) { + t_ = rhs.t_; + u_ = rhs.u_; + } + return *this; + } + + inline void swap(CoinWarmStartVectorPair< T, U > &rhs) + { + t_.swap(rhs.t_); + u_.swap(rhs.u_); + } + + virtual CoinWarmStart *clone() const + { + return new CoinWarmStartVectorPair(*this); + } + + virtual ~CoinWarmStartVectorPair() {} + + inline void clear() + { + t_.clear(); + u_.clear(); + } + + virtual CoinWarmStartDiff * + generateDiff(const CoinWarmStart *const oldCWS) const; + + virtual void applyDiff(const CoinWarmStartDiff *const cwsdDiff); +}; + +//============================================================================= + +template < typename T, typename U > +class CoinWarmStartVectorPairDiff : public virtual CoinWarmStartDiff { + friend CoinWarmStartDiff * + CoinWarmStartVectorPair< T, U >::generateDiff(const CoinWarmStart *const oldCWS) const; + friend void + CoinWarmStartVectorPair< T, U >::applyDiff(const CoinWarmStartDiff *const diff); + +private: + CoinWarmStartVectorDiff< T > tdiff_; + CoinWarmStartVectorDiff< U > udiff_; + +public: + CoinWarmStartVectorPairDiff() {} + CoinWarmStartVectorPairDiff(const CoinWarmStartVectorPairDiff< T, U > &rhs) + : tdiff_(rhs.tdiff_) + , udiff_(rhs.udiff_) + { + } + virtual ~CoinWarmStartVectorPairDiff() {} + + virtual CoinWarmStartVectorPairDiff & + operator=(const CoinWarmStartVectorPairDiff< T, U > &rhs) + { + if (this != &rhs) { + tdiff_ = rhs.tdiff_; + udiff_ = rhs.udiff_; + } + return *this; + } + + virtual CoinWarmStartDiff *clone() const + { + return new CoinWarmStartVectorPairDiff(*this); + } + + inline void swap(CoinWarmStartVectorPairDiff< T, U > &rhs) + { + tdiff_.swap(rhs.tdiff_); + udiff_.swap(rhs.udiff_); + } + + inline void clear() + { + tdiff_.clear(); + udiff_.clear(); + } +}; + +//############################################################################## +//############################################################################# + +/* + Generate a `diff' that can convert the warm start passed as a parameter to + the warm start specified by this. + + The capabilities are limited: the basis passed as a parameter can be no + larger than the basis pointed to by this. +*/ + +template < typename T > +CoinWarmStartDiff * +CoinWarmStartVector< T >::generateDiff(const CoinWarmStart *const oldCWS) const +{ + /* + Make sure the parameter is CoinWarmStartVector or derived class. +*/ + const CoinWarmStartVector< T > *oldVector = dynamic_cast< const CoinWarmStartVector< T > * >(oldCWS); + if (!oldVector) { + throw CoinError("Old warm start not derived from CoinWarmStartVector.", + "generateDiff", "CoinWarmStartVector"); + } + const CoinWarmStartVector< T > *newVector = this; + /* + Make sure newVector is equal or bigger than oldVector. Calculate the worst + case number of diffs and allocate vectors to hold them. + */ + const int oldCnt = oldVector->size(); + const int newCnt = newVector->size(); + + assert(newCnt >= oldCnt); + + unsigned int *diffNdx = new unsigned int[newCnt]; + T *diffVal = new T[newCnt]; + /* + Scan the vector vectors. For the portion of the vectors which overlap, + create diffs. Then add any additional entries from newVector. + */ + const T *oldVal = oldVector->values(); + const T *newVal = newVector->values(); + int numberChanged = 0; + int i; + for (i = 0; i < oldCnt; i++) { + if (oldVal[i] != newVal[i]) { + diffNdx[numberChanged] = i; + diffVal[numberChanged++] = newVal[i]; + } + } + for (; i < newCnt; i++) { + diffNdx[numberChanged] = i; + diffVal[numberChanged++] = newVal[i]; + } + /* + Create the object of our desire. + */ + CoinWarmStartVectorDiff< T > *diff = new CoinWarmStartVectorDiff< T >(numberChanged, diffNdx, diffVal); + /* + Clean up and return. + */ + delete[] diffNdx; + delete[] diffVal; + + return diff; + // return (dynamic_cast*>(diff)) ; +} + +/* + Apply diff to this warm start. + + Update this warm start by applying diff. It's assumed that the + allocated capacity of the warm start is sufficiently large. +*/ + +template < typename T > +void CoinWarmStartVector< T >::applyDiff(const CoinWarmStartDiff *const cwsdDiff) +{ + /* + Make sure we have a CoinWarmStartVectorDiff + */ + const CoinWarmStartVectorDiff< T > *diff = dynamic_cast< const CoinWarmStartVectorDiff< T > * >(cwsdDiff); + if (!diff) { + throw CoinError("Diff not derived from CoinWarmStartVectorDiff.", + "applyDiff", "CoinWarmStartVector"); + } + /* + Application is by straighforward replacement of words in the vector vector. + */ + const int numberChanges = diff->sze_; + const unsigned int *diffNdxs = diff->diffNdxs_; + const T *diffVals = diff->diffVals_; + T *vals = this->values_; + + for (int i = 0; i < numberChanges; i++) { + unsigned int diffNdx = diffNdxs[i]; + T diffVal = diffVals[i]; + vals[diffNdx] = diffVal; + } +} + +//############################################################################# + +// Assignment + +template < typename T > +CoinWarmStartVectorDiff< T > & +CoinWarmStartVectorDiff< T >::operator=(const CoinWarmStartVectorDiff< T > &rhs) +{ + if (this != &rhs) { + if (sze_ > 0) { + delete[] diffNdxs_; + delete[] diffVals_; + } + sze_ = rhs.sze_; + if (sze_ > 0) { + diffNdxs_ = new unsigned int[sze_]; + memcpy(diffNdxs_, rhs.diffNdxs_, sze_ * sizeof(unsigned int)); + diffVals_ = new T[sze_]; + memcpy(diffVals_, rhs.diffVals_, sze_ * sizeof(T)); + } else { + diffNdxs_ = 0; + diffVals_ = 0; + } + } + + return (*this); +} + +// Copy constructor + +template < typename T > +CoinWarmStartVectorDiff< T >::CoinWarmStartVectorDiff(const CoinWarmStartVectorDiff< T > &rhs) + : sze_(rhs.sze_) + , diffNdxs_(0) + , diffVals_(0) +{ + if (sze_ > 0) { + diffNdxs_ = new unsigned int[sze_]; + memcpy(diffNdxs_, rhs.diffNdxs_, sze_ * sizeof(unsigned int)); + diffVals_ = new T[sze_]; + memcpy(diffVals_, rhs.diffVals_, sze_ * sizeof(T)); + } +} + +/// Standard constructor + +template < typename T > +CoinWarmStartVectorDiff< T >::CoinWarmStartVectorDiff(int sze, const unsigned int *const diffNdxs, const T *const diffVals) + : sze_(sze) + , diffNdxs_(0) + , diffVals_(0) +{ + if (sze > 0) { + diffNdxs_ = new unsigned int[sze]; + memcpy(diffNdxs_, diffNdxs, sze * sizeof(unsigned int)); + diffVals_ = new T[sze]; + memcpy(diffVals_, diffVals, sze * sizeof(T)); + } +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Coin_C_defines.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Coin_C_defines.h new file mode 100644 index 000000000..a271e84c6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Coin_C_defines.h @@ -0,0 +1,149 @@ +/* $Id$ */ +/* + Copyright (C) 2002, 2003 International Business Machines Corporation + and others. All Rights Reserved. + + This code is licensed under the terms of the Eclipse Public License (EPL). +*/ +#ifndef CoinCDefine_H +#define CoinCDefine_H + +/** This has #defines etc for the "C" interface to Coin. + If COIN_EXTERN_C defined then an extra extern C +*/ + +#if defined(CLP_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_SBB +#define COIN_NO_CBC +#endif +#if defined(SBB_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_CLP +#endif +#if defined(CBC_EXTERN_C) +#define COIN_EXTERN_C +#define COIN_NO_CLP +#endif +/* We need to allow for Microsoft */ +#ifndef COINLIBAPI + +#if defined(CBCCINTERFACEDLL_EXPORTS) || defined(CLPMSDLL) +#if defined(COIN_EXTERN_C) +#define COINLIBAPI __declspec(dllexport) +#else +#define COINLIBAPI __declspec(dllexport) +#endif +#define COINLINKAGE __stdcall +#define COINLINKAGE_CB __cdecl +#else +#if defined(COIN_EXTERN_C) +#define COINLIBAPI extern "C" +#else +#define COINLIBAPI +#endif +#define COINLINKAGE +#define COINLINKAGE_CB +#endif + +#endif +/** User does not need to see structure of model but C++ code does */ +#if defined(CLP_EXTERN_C) +/* Real typedef for structure */ +class CMessageHandler; +typedef struct { + ClpSimplex *model_; + CMessageHandler *handler_; +} Clp_Simplex; +#else +typedef void Clp_Simplex; +#endif + +#ifndef COIN_NO_CLP +/** typedef for user call back. + The cvec are constructed so don't need to be const*/ +#if COIN_BIG_INDEX == 0 +typedef void(COINLINKAGE_CB *clp_callback)(Clp_Simplex *model, int msgno, int ndouble, + const double *dvec, int nint, const int *ivec, + int nchar, char **cvec); +#elif COIN_BIG_INDEX == 1 +typedef void(COINLINKAGE_CB *clp_callback)(Clp_Simplex *model, int msgno, int ndouble, + const double *dvec, int nint, const long *ivec, + int nchar, char **cvec); +#else +typedef void(COINLINKAGE_CB *clp_callback)(Clp_Simplex *model, int msgno, int ndouble, + const double *dvec, int nint, const long long *ivec, + int nchar, char **cvec); +#endif +#endif +/** User does not need to see structure of model but C++ code does */ +#if defined(SBB_EXTERN_C) +/* Real typedef for structure */ +class Sbb_MessageHandler; +typedef struct { + OsiClpSolverInterface *solver_; + SbbModel *model_; + Sbb_MessageHandler *handler_; + char *information_; +} Sbb_Model; +#else +typedef void Sbb_Model; +#endif +#if defined(CBC_EXTERN_C) +/* Real typedef for structure */ +class Cbc_MessageHandler; +typedef struct { + OsiClpSolverInterface *solver_; + CbcModel *model_; + CbcSolverUsefulData *cbcData; + Cbc_MessageHandler *handler_; + std::vector< std::string > cmdargs_; + char relax_; + + // cache for columns + int colSpace; + int nCols; + int cNameSpace; + int *cNameStart; + char *cInt; + char *cNames; + double *cLB; + double *cUB; + double *cObj; +} Cbc_Model; +#else +typedef void Cbc_Model; +#endif +#ifndef COIN_NO_SBB +/** typedef for user call back. + The cvec are constructed so don't need to be const*/ +typedef void(COINLINKAGE_CB *sbb_callback)(Sbb_Model *model, int msgno, int ndouble, + const double *dvec, int nint, const int *ivec, + int nchar, char **cvec); + +typedef void(COINLINKAGE_CB *cbc_callback)(Cbc_Model *model, int msgno, int ndouble, + const double *dvec, int nint, const int *ivec, + int nchar, char **cvec); + +/** typedef for cbc cut callback osiSolver needs to be an OsiSolverInterface object, + * osiCuts is an OsiCuts object and appdata is a pointer that will be passed to the cut + * generation, you can use it to point to a data structure with information about the original problem, + * for instance + **/ +typedef void(COINLINKAGE_CB *cbc_cut_callback)(void *osiSolver, void *osiCuts, void *appdata); +#endif +#if COIN_BIG_INDEX == 0 +typedef int CoinBigIndex; +#elif COIN_BIG_INDEX == 1 +typedef long CoinBigIndex; +#else +typedef long long CoinBigIndex; +#endif +/* just in case used somewhere */ +#undef COIN_NO_CLP +#undef COIN_NO_SBB +#undef COIN_NO_CBC +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Idiot.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Idiot.hpp new file mode 100644 index 000000000..10b5c7c8b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/Idiot.hpp @@ -0,0 +1,327 @@ +/* $Id$ */ +// Copyright (C) 2002, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +// "Idiot" as the name of this algorithm is copylefted. If you want to change +// the name then it should be something equally stupid (but not "Stupid") or +// even better something witty. + +#ifndef Idiot_H +#define Idiot_H +#ifndef OSI_IDIOT +#include "ClpSimplex.hpp" +#define OsiSolverInterface ClpSimplex +#else +#include "OsiSolverInterface.hpp" +typedef int CoinBigIndex; +#endif +class CoinMessageHandler; +class CoinMessages; +/// for use internally +typedef struct { + double infeas; + double objval; + double dropThis; + double weighted; + double sumSquared; + double djAtBeginning; + double djAtEnd; + int iteration; +} IdiotResult; +/** This class implements a very silly algorithm. It has no merit + apart from the fact that it gets an approximate solution to + some classes of problems. Better if vaguely homogeneous. + It works on problems where volume algorithm works and often + gets a better primal solution but it has no dual solution. + + It can also be used as a "crash" to get a problem started. This + is probably its most useful function. + + It is based on the idea that algorithms with terrible convergence + properties may be okay at first. Throw in some random dubious tricks + and the resulting code may be worth keeping as long as you don't + look at it. + +*/ + +class Idiot { + +public: + /**@name Constructors and destructor + Just a pointer to model is kept + */ + //@{ + /// Default constructor + Idiot(); + /// Constructor with model + Idiot(OsiSolverInterface &model); + + /// Copy constructor. + Idiot(const Idiot &); + /// Assignment operator. This copies the data + Idiot &operator=(const Idiot &rhs); + /// Destructor + ~Idiot(); + //@} + + /**@name Algorithmic calls + */ + //@{ + /// Get an approximate solution with the idiot code + void solve(); + /// Lightweight "crash" + void crash(int numberPass, CoinMessageHandler *handler, + const CoinMessages *messages, bool doCrossover = true); + /** Use simplex to get an optimal solution + mode is how many steps the simplex crossover should take to + arrive to an extreme point: + 0 - chosen,all ever used, all + 1 - chosen, all + 2 - all + 3 - do not do anything - maybe basis + + 16 do presolves + */ + void crossOver(int mode); + //@} + + /**@name Gets and sets of most useful data + */ + //@{ + /** Starting weight - small emphasizes feasibility, + default 1.0e-4 */ + inline double getStartingWeight() const + { + return mu_; + } + inline void setStartingWeight(double value) + { + mu_ = value; + } + /** Weight factor - weight multiplied by this when changes, + default 0.333 */ + inline double getWeightFactor() const + { + return muFactor_; + } + inline void setWeightFactor(double value) + { + muFactor_ = value; + } + /** Feasibility tolerance - problem essentially feasible if + individual infeasibilities less than this. + default 0.1 */ + inline double getFeasibilityTolerance() const + { + return smallInfeas_; + } + inline void setFeasibilityTolerance(double value) + { + smallInfeas_ = value; + } + /** Reasonably feasible. Dubious method concentrates more on + objective when sum of infeasibilities less than this. + Very dubious default value of (Number of rows)/20 */ + inline double getReasonablyFeasible() const + { + return reasonableInfeas_; + } + inline void setReasonablyFeasible(double value) + { + reasonableInfeas_ = value; + } + /** Exit infeasibility - exit if sum of infeasibilities less than this. + Default -1.0 (i.e. switched off) */ + inline double getExitInfeasibility() const + { + return exitFeasibility_; + } + inline void setExitInfeasibility(double value) + { + exitFeasibility_ = value; + } + /** Major iterations. stop after this number. + Default 30. Use 2-5 for "crash" 50-100 for serious crunching */ + inline int getMajorIterations() const + { + return majorIterations_; + } + inline void setMajorIterations(int value) + { + majorIterations_ = value; + } + /** Minor iterations. Do this number of tiny steps before + deciding whether to change weights etc. + Default - dubious sqrt(Number of Rows). + Good numbers 105 to 405 say (5 is dubious method of making sure + idiot is not trying to be clever which it may do every 10 minor + iterations) */ + inline int getMinorIterations() const + { + return maxIts2_; + } + inline void setMinorIterations(int value) + { + maxIts2_ = value; + } + // minor iterations for first time + inline int getMinorIterations0() const + { + return maxIts_; + } + inline void setMinorIterations0(int value) + { + maxIts_ = value; + } + /** Reduce weight after this many major iterations. It may + get reduced before this but this is a maximum. + Default 3. 3-10 plausible. */ + inline int getReduceIterations() const + { + return maxBigIts_; + } + inline void setReduceIterations(int value) + { + maxBigIts_ = value; + } + /// Amount of information - default of 1 should be okay + inline int getLogLevel() const + { + return logLevel_; + } + inline void setLogLevel(int value) + { + logLevel_ = value; + } + /// How lightweight - 0 not, 1 yes, 2 very lightweight + inline int getLightweight() const + { + return lightWeight_; + } + inline void setLightweight(int value) + { + lightWeight_ = value; + } + /// strategy + inline int getStrategy() const + { + return strategy_; + } + inline void setStrategy(int value) + { + strategy_ = value; + } + /// Fine tuning - okay if feasibility drop this factor + inline double getDropEnoughFeasibility() const + { + return dropEnoughFeasibility_; + } + inline void setDropEnoughFeasibility(double value) + { + dropEnoughFeasibility_ = value; + } + /// Fine tuning - okay if weighted obj drop this factor + inline double getDropEnoughWeighted() const + { + return dropEnoughWeighted_; + } + inline void setDropEnoughWeighted(double value) + { + dropEnoughWeighted_ = value; + } + /// Set model + inline void setModel(OsiSolverInterface *model) + { + model_ = model; + }; + //@} + + /// Stuff for internal use +private: + /// Does actual work + // allow public! +public: + void solve2(CoinMessageHandler *handler, const CoinMessages *messages); + +private: + IdiotResult IdiSolve( + int nrows, int ncols, double *rowsol, double *colsol, + double *pi, double *djs, const double *origcost, + double *rowlower, + double *rowupper, const double *lower, + const double *upper, const double *element, + const int *row, const CoinBigIndex *colcc, + const int *length, double *lambda, + int maxIts, double mu, double drop, + double maxmin, double offset, + int strategy, double djTol, double djExit, double djFlag, + CoinThreadRandom *randomNumberGenerator); + int dropping(IdiotResult result, + double tolerance, + double small, + int *nbad); + IdiotResult objval(int nrows, int ncols, double *rowsol, double *colsol, + double *pi, double *djs, const double *cost, + const double *rowlower, + const double *rowupper, const double *lower, + const double *upper, const double *elemnt, + const int *row, const CoinBigIndex *columnStart, + const int *length, int extraBlock, int *rowExtra, + double *solExtra, double *elemExtra, double *upperExtra, + double *costExtra, double weight); + // Deals with whenUsed and slacks + int cleanIteration(int iteration, int ordinaryStart, int ordinaryEnd, + double *colsol, const double *lower, const double *upper, + const double *rowLower, const double *rowUpper, + const double *cost, const double *element, double fixTolerance, double &objChange, + double &infChange, double &maxInfeasibility); + +private: + /// Underlying model + OsiSolverInterface *model_; + + double djTolerance_; + double mu_; /* starting mu */ + double drop_; /* exit if drop over 5 checks less than this */ + double muFactor_; /* reduce mu by this */ + double stopMu_; /* exit if mu gets smaller than this */ + double smallInfeas_; /* feasibility tolerance */ + double reasonableInfeas_; /* use lambdas if feasibility less than this */ + double exitDrop_; /* candidate for stopping after a major iteration */ + double muAtExit_; /* mu on exit */ + double exitFeasibility_; /* exit if infeasibility less than this */ + double dropEnoughFeasibility_; /* okay if feasibility drop this factor */ + double dropEnoughWeighted_; /* okay if weighted obj drop this factor */ + int *whenUsed_; /* array to say what was used */ + int maxBigIts_; /* always reduce mu after this */ + int maxIts_; /* do this many iterations on first go */ + int majorIterations_; + int logLevel_; + int logFreq_; + int checkFrequency_; /* can exit after 5 * this iterations (on drop) */ + int lambdaIterations_; /* do at least this many lambda iterations */ + int maxIts2_; /* do this many iterations on subsequent goes */ + int strategy_; /* 0 - default strategy + 1 - do accelerator step but be cautious + 2 - do not do accelerator step + 4 - drop, exitDrop and djTolerance all relative + 8 - keep accelerator step to theta=10.0 + + 32 - Scale + 512 - crossover + 2048 - keep lambda across mu change + 4096 - return best solution (not last found) + 8192 - always do a presolve in crossover + 16384 - costed slacks found - so whenUsed_ longer + 32768 - experimental 1 + 65536 - experimental 2 + 131072 - experimental 3 + 262144 - just values pass etc + 524288 - don't treat structural slacks as slacks */ + + int lightWeight_; // 0 - normal, 1 lightweight +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiAuxInfo.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiAuxInfo.hpp new file mode 100644 index 000000000..e5d576eff --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiAuxInfo.hpp @@ -0,0 +1,261 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiAuxInfo_H +#define OsiAuxInfo_H + +class OsiSolverInterface; + +//############################################################################# +/** This class allows for a more structured use of algorithmic tweaking to + an OsiSolverInterface. It is designed to replace the simple use of + appData_ pointer. + + This has been done to make it easier to use NonLinear solvers and other + exotic beasts in a branch and bound mode. After this class definition + there is one for a derived class for just such a purpose. + +*/ + +class OsiAuxInfo { +public: + // Default Constructor + OsiAuxInfo(void *appData = NULL); + + // Copy Constructor + OsiAuxInfo(const OsiAuxInfo &rhs); + // Destructor + virtual ~OsiAuxInfo(); + + /// Clone + virtual OsiAuxInfo *clone() const; + /// Assignment operator + OsiAuxInfo &operator=(const OsiAuxInfo &rhs); + + /// Get application data + inline void *getApplicationData() const + { + return appData_; + } + +protected: + /// Pointer to user-defined data structure + void *appData_; +}; +//############################################################################# +/** This class allows for the use of more exotic solvers e.g. Non-Linear or Volume. + + You can derive from this although at present I can't see the need. +*/ + +class OsiBabSolver : public OsiAuxInfo { +public: + // Default Constructor + OsiBabSolver(int solverType = 0); + + // Copy Constructor + OsiBabSolver(const OsiBabSolver &rhs); + // Destructor + virtual ~OsiBabSolver(); + + /// Clone + virtual OsiAuxInfo *clone() const; + /// Assignment operator + OsiBabSolver &operator=(const OsiBabSolver &rhs); + + /// Update solver + inline void setSolver(const OsiSolverInterface *solver) + { + solver_ = solver; + } + /// Update solver + inline void setSolver(const OsiSolverInterface &solver) + { + solver_ = &solver; + } + + /** returns 0 if no heuristic solution, 1 if valid solution + with better objective value than one passed in + Sets solution values if good, sets objective value + numberColumns is size of newSolution + */ + int solution(double &objectiveValue, + double *newSolution, int numberColumns); + /** Set solution and objective value. + Number of columns and optimization direction taken from current solver. + Size of solution is numberColumns (may be padded or truncated in function) */ + void setSolution(const double *solution, int numberColumns, double objectiveValue); + + /** returns true if the object stores a solution, false otherwise. If there + is a solution then solutionValue and solution will be filled out as well. + In that case the user needs to allocate solution to be a big enough + array. + */ + bool hasSolution(double &solutionValue, double *solution); + + /** Sets solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check solver to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + 4 - normal solver but cuts are needed for integral solution + */ + inline void setSolverType(int value) + { + solverType_ = value; + } + /** gets solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + 4 - normal solver but cuts are needed for integral solution + */ + inline int solverType() const + { + return solverType_; + } + /** Return true if getting solution may add cuts so hot start etc will + be obsolete */ + inline bool solutionAddsCuts() const + { + return solverType_ == 3; + } + /// Return true if we should try cuts at root even if looks satisfied + inline bool alwaysTryCutsAtRootNode() const + { + return solverType_ == 4; + } + /** Returns true if can use solver objective or feasible values, + otherwise use mipBound etc */ + inline bool solverAccurate() const + { + return solverType_ == 0 || solverType_ == 2 || solverType_ == 4; + } + /// Returns true if can use reduced costs for fixing + inline bool reducedCostsAccurate() const + { + return solverType_ == 0 || solverType_ == 4; + } + /// Get objective (well mip bound) + double mipBound() const; + /// Returns true if node feasible + bool mipFeasible() const; + /// Set mip bound (only used for some solvers) + inline void setMipBound(double value) + { + mipBound_ = value; + } + /// Get objective value of saved solution + inline double bestObjectiveValue() const + { + return bestObjectiveValue_; + } + /// Says whether we want to try cuts at all + inline bool tryCuts() const + { + return solverType_ != 2; + } + /// Says whether we have a warm start (so can do strong branching) + inline bool warmStart() const + { + return solverType_ != 2; + } + /** Get bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + inline int extraCharacteristics() const + { + return extraCharacteristics_; + } + /** Set bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + inline void setExtraCharacteristics(int value) + { + extraCharacteristics_ = value; + } + /// Pointer to lower bounds before branch (only if extraCharacteristics set) + inline const double *beforeLower() const + { + return beforeLower_; + } + /// Set pointer to lower bounds before branch (only if extraCharacteristics set) + inline void setBeforeLower(const double *array) + { + beforeLower_ = array; + } + /// Pointer to upper bounds before branch (only if extraCharacteristics set) + inline const double *beforeUpper() const + { + return beforeUpper_; + } + /// Set pointer to upper bounds before branch (only if extraCharacteristics set) + inline void setBeforeUpper(const double *array) + { + beforeUpper_ = array; + } + /// Set pointer to extra stuff + inline void setExtraPointer(void *extraInfo) + { + extraInfo_ = extraInfo; + } + /// get pointer to extra info + inline void *getExtraPointer() const + { + return extraInfo_; + } + +protected: + /// Objective value of best solution (if there is one) (minimization) + double bestObjectiveValue_; + /// Current lower bound on solution ( if > 1.0e50 infeasible) + double mipBound_; + /// Solver to use for getting/setting solutions etc + const OsiSolverInterface *solver_; + /// Best integer feasible solution + double *bestSolution_; + /// Pointer to lower bounds before branch (only if extraCharacteristics set) + const double *beforeLower_; + /// Pointer to upper bounds before branch (only if extraCharacteristics set) + const double *beforeUpper_; + /// Pointer to extra info + void *extraInfo_; + /** Solver type + 0 - normal LP solver + 1 - DW - may also return heuristic solutions + 2 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is + - may also return heuristic solution + 3 - NLP solver or similar - can't compute objective value just from solution + check this (rather than solver) to see if feasible and what objective value is. + Using Outer Approximation so called lp based + - may also return heuristic solution + */ + int solverType_; + /// Size of solution + int sizeSolution_; + /** Bit mask for odd actions of solvers + 1 - solution or bound arrays may move in mysterious ways e.g. cplex + 2 - solver may want bounds before branch + */ + int extraCharacteristics_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiBranchingObject.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiBranchingObject.hpp new file mode 100644 index 000000000..556d16f2b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiBranchingObject.hpp @@ -0,0 +1,1097 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiBranchingObject_H +#define OsiBranchingObject_H + +#include +#include +#include + +#include "CoinError.hpp" +#include "CoinTypes.hpp" + +class OsiSolverInterface; +class OsiSolverBranch; + +class OsiBranchingObject; +class OsiBranchingInformation; + +//############################################################################# +//This contains the abstract base class for an object and for branching. +//It also contains a simple integer class +//############################################################################# + +/** Abstract base class for `objects'. + + The branching model used in Osi is based on the idea of an object. + In the abstract, an object is something that has a feasible region, can be + evaluated for infeasibility, can be branched on (i.e., there's some + constructive action to be taken to move toward feasibility), and allows + comparison of the effect of branching. + + This class (OsiObject) is the base class for an object. To round out the + branching model, the class OsiBranchingObject describes how to perform a + branch, and the class OsiBranchDecision describes how to compare two + OsiBranchingObjects. + + To create a new type of object you need to provide three methods: + #infeasibility(), #feasibleRegion(), and #createBranch(), described below. + + This base class is primarily virtual to allow for any form of structure. + Any form of discontinuity is allowed. + + As there is an overhead in getting information from solvers and because + other useful information is available there is also an OsiBranchingInformation + class which can contain pointers to information. + If used it must at minimum contain pointers to current value of objective, + maximum allowed objective and pointers to arrays for bounds and solution + and direction of optimization. Also integer and primal tolerance. + + Classes which inherit might have other information such as depth, number of + solutions, pseudo-shadow prices etc etc. + May be easier just to throw in here - as I keep doing +*/ +class OsiObject { + +public: + /// Default Constructor + OsiObject(); + + /// Copy constructor + OsiObject(const OsiObject &); + + /// Assignment operator + OsiObject &operator=(const OsiObject &rhs); + + /// Clone + virtual OsiObject *clone() const = 0; + + /// Destructor + virtual ~OsiObject(); + + /** Infeasibility of the object + + This is some measure of the infeasibility of the object. 0.0 + indicates that the object is satisfied. + + The preferred branching direction is returned in whichWay, where for + normal two-way branching 0 is down, 1 is up + + This is used to prepare for strong branching but should also think of + case when no strong branching + + The object may also compute an estimate of cost of going "up" or "down". + This will probably be based on pseudo-cost ideas + + This should also set mutable infeasibility_ and whichWay_ + This is for instant re-use for speed + + Default for this just calls infeasibility with OsiBranchingInformation + NOTE - Convention says that an infeasibility of COIN_DBL_MAX means + object has worked out it can't be satisfied! + */ + double infeasibility(const OsiSolverInterface *solver, int &whichWay) const; + // Faster version when more information available + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const = 0; + // This does NOT set mutable stuff + virtual double checkInfeasibility(const OsiBranchingInformation *info) const; + + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + Returns measure of how much it had to move solution to make feasible + */ + virtual double feasibleRegion(OsiSolverInterface *solver) const; + /** For the variable(s) referenced by the object, + look at the current solution and set bounds to match the solution. + Returns measure of how much it had to move solution to make feasible + Faster version + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const = 0; + + /** Create a branching object and indicate which way to branch first. + + The branching object has to know how to create branches (fix + variables, etc.) + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface * /*solver*/, + const OsiBranchingInformation * /*info*/, + int /*way*/) const + { + throw CoinError("Need code", "createBranch", "OsiBranchingObject"); + return NULL; + } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return true; + } + /** \brief Return true if object can take part in move to nearest heuristic + */ + virtual bool canMoveToNearest() const + { + return false; + } + /** Column number if single column object -1 otherwise, + Used by heuristics + */ + virtual int columnNumber() const; + /// Return Priority - note 1 is highest priority + inline int priority() const + { + return priority_; + } + /// Set priority + inline void setPriority(int priority) + { + priority_ = priority; + } + /** \brief Return true if branch should only bound variables + */ + virtual bool boundBranch() const + { + return true; + } + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { + return false; + } + /// Return maximum number of ways branch may have + inline int numberWays() const + { + return numberWays_; + } + /// Set maximum number of ways branch may have + inline void setNumberWays(int numberWays) + { + numberWays_ = static_cast< short int >(numberWays); + } + /** Return preferred way to branch. If two + then way=0 means down and 1 means up, otherwise + way points to preferred branch + */ + inline void setWhichWay(int way) + { + whichWay_ = static_cast< short int >(way); + } + /** Return current preferred way to branch. If two + then way=0 means down and 1 means up, otherwise + way points to preferred branch + */ + inline int whichWay() const + { + return whichWay_; + } + /// Get pre-emptive preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + virtual int preferredWay() const + { + return -1; + } + /// Return infeasibility + inline double infeasibility() const + { + return infeasibility_; + } + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /** Reset variable bounds to their original values. + Bounds may be tightened, so it may be good to be able to reset them to + their original values. + */ + virtual void resetBounds(const OsiSolverInterface *) {} + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int, const int *) {} + /// Updates stuff like pseudocosts before threads + virtual void updateBefore(const OsiObject *) {} + /// Updates stuff like pseudocosts after threads finished + virtual void updateAfter(const OsiObject *, const OsiObject *) {} + +protected: + /// data + + /// Computed infeasibility + mutable double infeasibility_; + /// Computed preferred way to branch + mutable short whichWay_; + /// Maximum number of ways on branch + short numberWays_; + /// Priority + int priority_; +}; +/// Define a class to add a bit of complexity to OsiObject +/// This assumes 2 way branching + +class OsiObject2 : public OsiObject { + +public: + /// Default Constructor + OsiObject2(); + + /// Copy constructor + OsiObject2(const OsiObject2 &); + + /// Assignment operator + OsiObject2 &operator=(const OsiObject2 &rhs); + + /// Destructor + virtual ~OsiObject2(); + + /// Set preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + inline void setPreferredWay(int value) + { + preferredWay_ = value; + } + + /// Get preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + virtual int preferredWay() const + { + return preferredWay_; + } + +protected: + /// Preferred way of branching - -1 off, 0 down, 1 up (for 2-way) + int preferredWay_; + /// "Infeasibility" on other way + mutable double otherInfeasibility_; +}; + +/** \brief Abstract branching object base class + + In the abstract, an OsiBranchingObject contains instructions for how to + branch. We want an abstract class so that we can describe how to branch on + simple objects (e.g., integers) and more exotic objects + (e.g., cliques or hyperplanes). + + The #branch() method is the crucial routine: it is expected to be able to + step through a set of branch arms, executing the actions required to create + each subproblem in turn. The base class is primarily virtual to allow for + a wide range of problem modifications. + + See OsiObject for an overview of the two classes (OsiObject and + OsiBranchingObject) which make up Osi's branching + model. +*/ + +class OsiBranchingObject { + +public: + /// Default Constructor + OsiBranchingObject(); + + /// Constructor + OsiBranchingObject(OsiSolverInterface *solver, double value); + + /// Copy constructor + OsiBranchingObject(const OsiBranchingObject &); + + /// Assignment operator + OsiBranchingObject &operator=(const OsiBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const = 0; + + /// Destructor + virtual ~OsiBranchingObject(); + + /// The number of branch arms created for this branching object + inline int numberBranches() const + { + return numberBranches_; + } + + /// The number of branch arms left for this branching object + inline int numberBranchesLeft() const + { + return numberBranches_ - branchIndex_; + } + + /// Increment the number of branch arms left for this branching object + inline void incrementNumberBranchesLeft() + { + numberBranches_++; + } + + /** Set the number of branch arms left for this branching object + Just for forcing + */ + inline void setNumberBranchesLeft(int /*value*/) + { /*assert (value==1&&!branchIndex_);*/ + numberBranches_ = 1; + } + + /// Decrement the number of branch arms left for this branching object + inline void decrementNumberBranchesLeft() + { + branchIndex_++; + } + + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface *solver) = 0; + /** \brief Execute the actions required to branch, as specified by the + current state of the branching object, and advance the object's + state. + Returns change in guessed objective on next branch + */ + virtual double branch() { return branch(NULL); } + /** \brief Return true if branch should fix variables + */ + virtual bool boundBranch() const + { + return true; + } + /** Get the state of the branching object + This is just the branch index + */ + inline int branchIndex() const + { + return branchIndex_; + } + + /** Set the state of the branching object. + */ + inline void setBranchingIndex(int branchIndex) + { + branchIndex_ = static_cast< short int >(branchIndex); + } + + /// Current value + inline double value() const + { + return value_; + } + + /// Return pointer back to object which created + inline const OsiObject *originalObject() const + { + return originalObject_; + } + /// Set pointer back to object which created + inline void setOriginalObject(const OsiObject *object) + { + originalObject_ = object; + } + /** Double checks in case node can change its mind! + Returns objective value + Can change objective etc */ + virtual void checkIsCutoff(double) {} + /// For debug + int columnNumber() const; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface * = NULL) const {} + +protected: + /// Current value - has some meaning about branch + double value_; + + /// Pointer back to object which created + const OsiObject *originalObject_; + + /** Number of branches + */ + int numberBranches_; + + /** The state of the branching object. i.e. branch index + This starts at 0 when created + */ + short branchIndex_; +}; +/* This contains information + This could also contain pseudo shadow prices + or information for dealing with computing and trusting pseudo-costs +*/ +class OsiBranchingInformation { + +public: + /// Default Constructor + OsiBranchingInformation(); + + /** Useful Constructor + (normalSolver true if has matrix etc etc) + copySolution true if constructot should make a copy + */ + OsiBranchingInformation(const OsiSolverInterface *solver, bool normalSolver, bool copySolution = false); + + /// Copy constructor + OsiBranchingInformation(const OsiBranchingInformation &); + + /// Assignment operator + OsiBranchingInformation &operator=(const OsiBranchingInformation &rhs); + + /// Clone + virtual OsiBranchingInformation *clone() const; + + /// Destructor + virtual ~OsiBranchingInformation(); + + // Note public +public: + /// data + + /** State of search + 0 - no solution + 1 - only heuristic solutions + 2 - branched to a solution + 3 - no solution but many nodes + */ + int stateOfSearch_; + /// Value of objective function (in minimization sense) + double objectiveValue_; + /// Value of objective cutoff (in minimization sense) + double cutoff_; + /// Direction 1.0 for minimization, -1.0 for maximization + double direction_; + /// Integer tolerance + double integerTolerance_; + /// Primal tolerance + double primalTolerance_; + /// Maximum time remaining before stopping on time + double timeRemaining_; + /// Dual to use if row bound violated (if negative then pseudoShadowPrices off) + double defaultDual_; + /// Pointer to solver + mutable const OsiSolverInterface *solver_; + /// The number of columns + int numberColumns_; + /// Pointer to current lower bounds on columns + mutable const double *lower_; + /// Pointer to current solution + mutable const double *solution_; + /// Pointer to current upper bounds on columns + mutable const double *upper_; + /// Highly optional target (hot start) solution + const double *hotstartSolution_; + /// Pointer to duals + const double *pi_; + /// Pointer to row activity + const double *rowActivity_; + /// Objective + const double *objective_; + /// Pointer to current lower bounds on rows + const double *rowLower_; + /// Pointer to current upper bounds on rows + const double *rowUpper_; + /// Elements in column copy of matrix + const double *elementByColumn_; + /// Column starts + const CoinBigIndex *columnStart_; + /// Column lengths + const int *columnLength_; + /// Row indices + const int *row_; + /** Useful region of length CoinMax(numberColumns,2*numberRows) + This is allocated and deleted before OsiObject::infeasibility + It is zeroed on entry and should be so on exit + It only exists if defaultDual_>=0.0 + */ + double *usefulRegion_; + /// Useful index region to go with usefulRegion_ + int *indexRegion_; + /// Number of solutions found + int numberSolutions_; + /// Number of branching solutions found (i.e. exclude heuristics) + int numberBranchingSolutions_; + /// Depth in tree + int depth_; + /// TEMP + bool owningSolution_; +}; + +/// This just adds two-wayness to a branching object + +class OsiTwoWayBranchingObject : public OsiBranchingObject { + +public: + /// Default constructor + OsiTwoWayBranchingObject(); + + /** Create a standard tw0-way branch object + + Specifies a simple two-way branch. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiTwoWayBranchingObject(OsiSolverInterface *solver, const OsiObject *originalObject, + int way, double value); + + /// Copy constructor + OsiTwoWayBranchingObject(const OsiTwoWayBranchingObject &); + + /// Assignment operator + OsiTwoWayBranchingObject &operator=(const OsiTwoWayBranchingObject &rhs); + + /// Destructor + virtual ~OsiTwoWayBranchingObject(); + + using OsiBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface *solver) = 0; + + inline int firstBranch() const { return firstBranch_; } + /// Way returns -1 on down +1 on up + inline int way() const + { + return !branchIndex_ ? firstBranch_ : -firstBranch_; + } + +protected: + /// Which way was first branch -1 = down, +1 = up + int firstBranch_; +}; +/// Define a single integer class + +class OsiSimpleInteger : public OsiObject2 { + +public: + /// Default Constructor + OsiSimpleInteger(); + + /// Useful constructor - passed solver index + OsiSimpleInteger(const OsiSolverInterface *solver, int iColumn); + + /// Useful constructor - passed solver index and original bounds + OsiSimpleInteger(int iColumn, double lower, double upper); + + /// Copy constructor + OsiSimpleInteger(const OsiSimpleInteger &); + + /// Clone + virtual OsiObject *clone() const; + + /// Assignment operator + OsiSimpleInteger &operator=(const OsiSimpleInteger &rhs); + + /// Destructor + virtual ~OsiSimpleInteger(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + /// Set solver column number + inline void setColumnNumber(int value) + { + columnNumber_ = value; + } + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + + /// Original bounds + inline double originalLowerBound() const + { + return originalLower_; + } + inline void setOriginalLowerBound(double value) + { + originalLower_ = value; + } + inline double originalUpperBound() const + { + return originalUpper_; + } + inline void setOriginalUpperBound(double value) + { + originalUpper_ = value; + } + /** Reset variable bounds to their original values. + Bounds may be tightened, so it may be good to be able to reset them to + their original values. + */ + virtual void resetBounds(const OsiSolverInterface *solver); + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { + return false; + } + +protected: + /// data + /// Original lower bound + double originalLower_; + /// Original upper bound + double originalUpper_; + /// Column number in solver + int columnNumber_; +}; +/** Simple branching object for an integer variable + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. 0 -> down, 1-> up. +*/ + +class OsiIntegerBranchingObject : public OsiTwoWayBranchingObject { + +public: + /// Default constructor + OsiIntegerBranchingObject(); + + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be lb <= x <= floor(x*), the other ceil(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiIntegerBranchingObject(OsiSolverInterface *solver, const OsiSimpleInteger *originalObject, + int way, double value); + /** Create a standard floor/ceiling branch object + + Specifies a simple two-way branch in a more flexible way. One arm of the + branch will be lb <= x <= downUpperBound, the other upLowerBound <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiIntegerBranchingObject(OsiSolverInterface *solver, const OsiSimpleInteger *originalObject, + int way, double value, double downUpperBound, double upLowerBound); + + /// Copy constructor + OsiIntegerBranchingObject(const OsiIntegerBranchingObject &); + + /// Assignment operator + OsiIntegerBranchingObject &operator=(const OsiIntegerBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + /// Destructor + virtual ~OsiIntegerBranchingObject(); + + using OsiBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + +protected: + // Probably could get away with just value which is already stored + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +}; + +/** Define Special Ordered Sets of type 1 and 2. These do not have to be + integer - so do not appear in lists of integers. + + which_ points columns of matrix +*/ + +class OsiSOS : public OsiObject2 { + +public: + // Default Constructor + OsiSOS(); + + /** Useful constructor - which are indices + and weights are also given. If null then 0,1,2.. + type is SOS type + */ + OsiSOS(const OsiSolverInterface *solver, int numberMembers, + const int *which, const double *weights, int type = 1); + + // Copy constructor + OsiSOS(const OsiSOS &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiSOS &operator=(const OsiSOS &rhs); + + // Destructor + virtual ~OsiSOS(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to fix the variable at the current (integer) value. + + Given an integer value, set the lower and upper bounds to fix the + variable. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + + /// Redoes data when sequence numbers change + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + /// Number of members + inline int numberMembers() const + { + return numberMembers_; + } + + /// Members (indices in range 0 ... numberColumns-1) + inline const int *members() const + { + return members_; + } + + /// SOS type + inline int sosType() const + { + return sosType_; + } + + /// SOS type + inline int setType() const + { + return sosType_; + } + + /** Array of weights */ + inline const double *weights() const + { + return weights_; + } + + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return (sosType_ == 1 && integerValued_); + } + /// Set whether set is integer valued or not + inline void setIntegerValued(bool yesNo) + { + integerValued_ = yesNo; + } + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { + return true; + } + /// Set number of members + inline void setNumberMembers(int value) + { + numberMembers_ = value; + } + + /// Members (indices in range 0 ... numberColumns-1) + inline int *mutableMembers() const + { + return members_; + } + + /// Set SOS type + inline void setSosType(int value) + { + sosType_ = value; + } + + /** Array of weights */ + inline double *mutableWeights() const + { + return weights_; + } + +protected: + /// data + + /// Members (indices in range 0 ... numberColumns-1) + int *members_; + /// Weights + double *weights_; + + /// Number of members + int numberMembers_; + /// SOS type + int sosType_; + /// Whether integer valued + bool integerValued_; +}; + +/** Branching object for Special ordered sets + + */ +class OsiSOSBranchingObject : public OsiTwoWayBranchingObject { + +public: + // Default Constructor + OsiSOSBranchingObject(); + + // Useful constructor + OsiSOSBranchingObject(OsiSolverInterface *solver, const OsiSOS *originalObject, + int way, + double separator); + + // Copy constructor + OsiSOSBranchingObject(const OsiSOSBranchingObject &); + + // Assignment operator + OsiSOSBranchingObject &operator=(const OsiSOSBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + // Destructor + virtual ~OsiSOSBranchingObject(); + + using OsiBranchingObject::branch; + /// Does next branch and updates state + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + +private: + /// data +}; +/** Lotsize class */ + +class OsiLotsize : public OsiObject2 { + +public: + // Default Constructor + OsiLotsize(); + + /* Useful constructor - passed model index. + Also passed valid values - if range then pairs + */ + OsiLotsize(const OsiSolverInterface *solver, int iColumn, + int numberPoints, const double *points, bool range = false); + + // Copy constructor + OsiLotsize(const OsiLotsize &); + + /// Clone + virtual OsiObject *clone() const; + + // Assignment operator + OsiLotsize &operator=(const OsiLotsize &rhs); + + // Destructor + virtual ~OsiLotsize(); + + using OsiObject::infeasibility; + /// Infeasibility - large is 0.5 + virtual double infeasibility(const OsiBranchingInformation *info, int &whichWay) const; + + using OsiObject::feasibleRegion; + /** Set bounds to contain the current solution. + + More precisely, for the variable associated with this object, take the + value given in the current solution, force it within the current bounds + if required, then set the bounds to fix the variable at the integer + nearest the solution value. Returns amount it had to move variable. + */ + virtual double feasibleRegion(OsiSolverInterface *solver, const OsiBranchingInformation *info) const; + + /** Creates a branching object + + The preferred direction is set by \p way, 0 for down, 1 for up. + */ + virtual OsiBranchingObject *createBranch(OsiSolverInterface *solver, const OsiBranchingInformation *info, int way) const; + + /// Set solver column number + inline void setColumnNumber(int value) + { + columnNumber_ = value; + } + + /** Column number if single column object -1 otherwise, + so returns >= 0 + Used by heuristics + */ + virtual int columnNumber() const; + /** Reset original upper and lower bound values from the solver. + + Handy for updating bounds held in this object after bounds held in the + solver have been tightened. + */ + virtual void resetBounds(const OsiSolverInterface *solver); + + /** Finds range of interest so value is feasible in range range_ or infeasible + between hi[range_] and lo[range_+1]. Returns true if feasible. + */ + bool findRange(double value, double integerTolerance) const; + + /** Returns floor and ceiling + */ + virtual void floorCeiling(double &floorLotsize, double &ceilingLotsize, double value, + double tolerance) const; + + /// Original bounds + inline double originalLowerBound() const + { + return bound_[0]; + } + inline double originalUpperBound() const + { + return bound_[rangeType_ * numberRanges_ - 1]; + } + /// Type - 1 points, 2 ranges + inline int rangeType() const + { + return rangeType_; + } + /// Number of points + inline int numberRanges() const + { + return numberRanges_; + } + /// Ranges + inline double *bound() const + { + return bound_; + } + /** Change column numbers after preprocessing + */ + virtual void resetSequenceEtc(int numberColumns, const int *originalColumns); + + /// Return "up" estimate (default 1.0e-5) + virtual double upEstimate() const; + /// Return "down" estimate (default 1.0e-5) + virtual double downEstimate() const; + /// Return true if knows how to deal with Pseudo Shadow Prices + virtual bool canHandleShadowPrices() const + { + return true; + } + /** \brief Return true if object can take part in normal heuristics + */ + virtual bool canDoHeuristics() const + { + return false; + } + +private: + /// data + + /// Column number in model + int columnNumber_; + /// Type - 1 points, 2 ranges + int rangeType_; + /// Number of points + int numberRanges_; + // largest gap + double largestGap_; + /// Ranges + double *bound_; + /// Current range + mutable int range_; +}; + +/** Lotsize branching object + + This object can specify a two-way branch on an integer variable. For each + arm of the branch, the upper and lower bounds on the variable can be + independently specified. + + Variable_ holds the index of the integer variable in the integerVariable_ + array of the model. +*/ + +class OsiLotsizeBranchingObject : public OsiTwoWayBranchingObject { + +public: + /// Default constructor + OsiLotsizeBranchingObject(); + + /** Create a lotsize floor/ceiling branch object + + Specifies a simple two-way branch. Let \p value = x*. One arm of the + branch will be is lb <= x <= valid range below(x*), the other valid range above(x*) <= x <= ub. + Specify way = -1 to set the object state to perform the down arm first, + way = 1 for the up arm. + */ + OsiLotsizeBranchingObject(OsiSolverInterface *solver, const OsiLotsize *originalObject, + int way, double value); + + /// Copy constructor + OsiLotsizeBranchingObject(const OsiLotsizeBranchingObject &); + + /// Assignment operator + OsiLotsizeBranchingObject &operator=(const OsiLotsizeBranchingObject &rhs); + + /// Clone + virtual OsiBranchingObject *clone() const; + + /// Destructor + virtual ~OsiLotsizeBranchingObject(); + + using OsiBranchingObject::branch; + /** \brief Sets the bounds for the variable according to the current arm + of the branch and advances the object state to the next arm. + state. + Returns change in guessed objective on next branch + */ + virtual double branch(OsiSolverInterface *solver); + + using OsiBranchingObject::print; + /** \brief Print something about branch - only if log level high + */ + virtual void print(const OsiSolverInterface *solver = NULL); + +protected: + /// Lower [0] and upper [1] bounds for the down arm (way_ = -1) + double down_[2]; + /// Lower [0] and upper [1] bounds for the up arm (way_ = 1) + double up_[2]; +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCbcSolverInterface.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCbcSolverInterface.hpp new file mode 100644 index 000000000..eebba5ccb --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCbcSolverInterface.hpp @@ -0,0 +1,791 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCbcSolverInterface_H +#define OsiCbcSolverInterface_H + +#include +#include +#include +#include "CbcModel.hpp" +#include "CoinPackedMatrix.hpp" +#include "OsiSolverInterface.hpp" +#include "CbcStrategy.hpp" +#include "CoinWarmStartBasis.hpp" + +class OsiRowCut; +class OsiClpSolverInterface; +static const double OsiCbcInfinity = COIN_DBL_MAX; + +//############################################################################# + +/** Cbc Solver Interface + +Instantiation of OsiCbcSolverInterface for the Model Algorithm. + +*/ + +class OsiCbcSolverInterface : virtual public OsiSolverInterface { + friend void OsiCbcSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir); + +public: + //--------------------------------------------------------------------------- + /**@name Solve methods */ + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + + /// Resolve an LP relaxation after problem modification + virtual void resolve(); + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound(); + //@} + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the cbc algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + */ + //@{ + // Set an integer parameter + bool setIntParam(OsiIntParam key, int value); + // Set an double parameter + bool setDblParam(OsiDblParam key, double value); + // Set a string parameter + bool setStrParam(OsiStrParam key, const std::string &value); + // Get an integer parameter + bool getIntParam(OsiIntParam key, int &value) const; + // Get an double parameter + bool getDblParam(OsiDblParam key, double &value) const; + // Get a string parameter + bool getStrParam(OsiStrParam key, std::string &value) const; + // Set a hint parameter - overrides OsiSolverInterface + virtual bool setHintParam(OsiHintParam key, bool yesNo = true, + OsiHintStrength strength = OsiHintTry, + void *otherInformation = NULL); + /// Get a hint parameter + virtual bool getHintParam(OsiHintParam key, bool &yesNo, + OsiHintStrength &strength, + void *&otherInformation) const; + + using OsiSolverInterface::getHintParam; + /// Get a hint parameter + virtual bool getHintParam(OsiHintParam key, bool &yesNo, + OsiHintStrength &strength) const; + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there a numerical difficulties? + virtual bool isAbandoned() const; + /// Is optimality proven? + virtual bool isProvenOptimal() const; + /// Is primal infeasiblity proven? + virtual bool isProvenPrimalInfeasible() const; + /// Is dual infeasiblity proven? + virtual bool isProvenDualInfeasible() const; + /// Is the given primal objective limit reached? + virtual bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + virtual bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + virtual bool isIterationLimitReached() const; + //@} + + //--------------------------------------------------------------------------- + /**@name WarmStart related methods */ + //@{ + + /*! \brief Get an empty warm start object + + This routine returns an empty CoinWarmStartBasis object. Its purpose is + to provide a way to give a client a warm start basis object of the + appropriate type, which can resized and modified as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart() const; + + /// Get warmstarting information + virtual CoinWarmStart *getWarmStart() const; + /** Set warmstarting information. Return true/false depending on whether + the warmstart information was accepted or not. */ + virtual bool setWarmStart(const CoinWarmStart *warmstart); + //@} + + //--------------------------------------------------------------------------- + /**@name Hotstart related methods (primarily used in strong branching).
+ The user can create a hotstart (a snapshot) of the optimization process + then reoptimize over and over again always starting from there.
+ NOTE: between hotstarted optimizations only + bound changes are allowed. */ + //@{ + /// Create a hotstart point of the optimization process + virtual void markHotStart(); + /// Optimize starting from the hotstart + virtual void solveFromHotStart(); + /// Delete the snapshot + virtual void unmarkHotStart(); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem information methods + + These methods call the solver's query routines to return + information about the problem referred to by the current object. + Querying a problem that has no data associated with it result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. + + Const pointers returned from any data-query method are valid as + long as the data is unchanged and the solver is not called. + */ + //@{ + /**@name Methods related to querying the input data */ + //@{ + /// Get number of columns + virtual int getNumCols() const; + + /// Get number of rows + virtual int getNumRows() const; + + /// Get number of nonzero elements + virtual CoinBigIndex getNumElements() const; + + /// Get pointer to array[getNumCols()] of column lower bounds + virtual const double *getColLower() const; + + /// Get pointer to array[getNumCols()] of column upper bounds + virtual const double *getColUpper() const; + + /** Get pointer to array[getNumRows()] of row constraint senses. +
    +
  • 'L' <= constraint +
  • 'E' = constraint +
  • 'G' >= constraint +
  • 'R' ranged constraint +
  • 'N' free constraint +
+ */ + virtual const char *getRowSense() const; + + /** Get pointer to array[getNumRows()] of rows right-hand sides +
    +
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] +
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0 +
+ */ + virtual const double *getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. +
    +
  • if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] +
  • if rowsense()[i] != 'R' then + rowrange()[i] is undefined +
+ */ + virtual const double *getRowRange() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + virtual const double *getRowLower() const; + + /// Get pointer to array[getNumRows()] of row upper bounds + virtual const double *getRowUpper() const; + + /// Get pointer to array[getNumCols()] of objective function coefficients + virtual const double *getObjCoefficients() const; + + /// Get objective function sense (1 for min (default), -1 for max) + virtual double getObjSense() const; + + /// Return true if column is continuous + virtual bool isContinuous(int colNumber) const; + + /// Get pointer to row-wise copy of matrix + virtual const CoinPackedMatrix *getMatrixByRow() const; + + /// Get pointer to column-wise copy of matrix + virtual const CoinPackedMatrix *getMatrixByCol() const; + + /// Get solver's value for infinity + virtual double getInfinity() const; + //@} + + /**@name Methods related to querying the solution */ + //@{ + /// Get pointer to array[getNumCols()] of primal solution vector + virtual const double *getColSolution() const; + + /// Get pointer to array[getNumRows()] of dual prices + virtual const double *getRowPrice() const; + + /// Get a pointer to array[getNumCols()] of reduced costs + virtual const double *getReducedCost() const; + + /** Get pointer to array[getNumRows()] of row activity levels (constraint + matrix times the solution vector */ + virtual const double *getRowActivity() const; + + /// Get objective function value + virtual double getObjValue() const; + + /** Get how many iterations it took to solve the problem (whatever + "iteration" mean to the solver. */ + virtual int getIterationCount() const; + + /** Get as many dual rays as the solver can provide. (In case of proven + primal infeasibility there should be at least one.) + + The first getNumRows() ray components will always be associated with + the row duals (as returned by getRowPrice()). If \c fullRay is true, + the final getNumCols() entries will correspond to the ray components + associated with the nonbasic variables. If the full ray is requested + and the method cannot provide it, it will throw an exception. + + NOTE for implementers of solver interfaces:
+ The double pointers in the vector should point to arrays of length + getNumRows() and they should be allocated via new[].
+ + NOTE for users of solver interfaces:
+ It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector< double * > getDualRays(int maxNumRays, + bool fullRay = false) const; + /** Get as many primal rays as the solver can provide. (In case of proven + dual infeasibility there should be at least one.) + + NOTE for implementers of solver interfaces:
+ The double pointers in the vector should point to arrays of length + getNumCols() and they should be allocated via new[].
+ + NOTE for users of solver interfaces:
+ It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector< double * > getPrimalRays(int maxNumRays) const; + + //@} + + /*! \name Methods for row and column names. + + Because OsiCbc is a pass-through class, it's necessary to override any + virtual method in order to be sure we catch an override by the underlying + solver. See the OsiSolverInterface class documentation for detailed + descriptions. + */ + //@{ + + /*! \brief Generate a standard name of the form Rnnnnnnn or Cnnnnnnn */ + + virtual std::string dfltRowColName(char rc, + int ndx, unsigned digits = 7) const; + + /*! \brief Return the name of the objective function */ + + virtual std::string getObjName(std::string::size_type maxLen = std::string::npos) const; + + /*! \brief Set the name of the objective function */ + + virtual void setObjName(std::string name); + + /*! \brief Return the name of the row. */ + + virtual std::string getRowName(int rowIndex, + std::string::size_type maxLen = std::string::npos) const; + + /*! \brief Return a pointer to a vector of row names */ + + virtual const OsiNameVec &getRowNames(); + + /*! \brief Set a row name */ + + virtual void setRowName(int ndx, std::string name); + + /*! \brief Set multiple row names */ + + virtual void setRowNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart); + + /*! \brief Delete len row names starting at index tgtStart */ + + virtual void deleteRowNames(int tgtStart, int len); + + /*! \brief Return the name of the column */ + + virtual std::string getColName(int colIndex, + std::string::size_type maxLen = std::string::npos) const; + + /*! \brief Return a pointer to a vector of column names */ + + virtual const OsiNameVec &getColNames(); + + /*! \brief Set a column name */ + + virtual void setColName(int ndx, std::string name); + + /*! \brief Set multiple column names */ + + virtual void setColNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart); + + /*! \brief Delete len column names starting at index tgtStart */ + virtual void deleteColNames(int tgtStart, int len); + + //@} + + //@} + + //--------------------------------------------------------------------------- + + /**@name Problem modifying methods */ + //@{ + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff(int elementIndex, double elementValue); + + using OsiSolverInterface::setColLower; + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + virtual void setColLower(int elementIndex, double elementValue); + + using OsiSolverInterface::setColUpper; + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + virtual void setColUpper(int elementIndex, double elementValue); + + /** Set a single column lower and upper bound */ + virtual void setColBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of columns simultaneously
+ The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + virtual void setColSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set a single row lower bound
+ Use -DBL_MAX for -infinity. */ + virtual void setRowLower(int elementIndex, double elementValue); + + /** Set a single row upper bound
+ Use DBL_MAX for infinity. */ + virtual void setRowUpper(int elementIndex, double elementValue); + + /** Set a single row lower and upper bound */ + virtual void setRowBounds(int elementIndex, + double lower, double upper); + + /** Set the type of a single row
*/ + virtual void setRowType(int index, char sense, double rightHandSide, + double range); + + /** Set the bounds on a number of rows simultaneously
+ The default implementation just invokes setRowLower() and + setRowUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + either bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + virtual void setRowSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set the type of a number of rows simultaneously
+ The default implementation just invokes setRowType() + over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + any characteristics changes + @param senseList the new senses + @param rhsList the new right hand sides + @param rangeList the new ranges + */ + virtual void setRowSetTypes(const int *indexFirst, + const int *indexLast, + const char *senseList, + const double *rhsList, + const double *rangeList); + //@} + + //------------------------------------------------------------------------- + /**@name Integrality related changing methods */ + //@{ + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index); + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index); + /** Set the variables listed in indices (which is of length len) to be + continuous variables */ + virtual void setContinuous(const int *indices, int len); + /** Set the variables listed in indices (which is of length len) to be + integer variables */ + virtual void setInteger(const int *indices, int len); + //@} + + //------------------------------------------------------------------------- + /// Set objective function sense (1 for min (default), -1 for max,) + virtual void setObjSense(double s); + + /** Set the primal solution column values + + colsol[numcols()] is an array of values of the problem column + variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of colsol() until changed by another call to + setColsol() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setColSolution(const double *colsol); + + /** Set dual solution vector + + rowprice[numrows()] is an array of values of the problem row + dual variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of rowprice() until changed by another call to + setRowprice() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setRowPrice(const double *rowprice); + + //------------------------------------------------------------------------- + /**@name Methods to expand a problem.
+ Note that if a column is added then by default it will correspond to a + continuous variable. */ + //@{ + using OsiSolverInterface::addCol; + /** */ + virtual void addCol(const CoinPackedVectorBase &vec, + const double collb, const double colub, + const double obj); + /** Add a column (primal variable) to the problem. */ + virtual void addCol(int numberElements, const int *rows, const double *elements, + const double collb, const double colub, + const double obj); + + using OsiSolverInterface::addCols; + /** */ + virtual void addCols(const int numcols, + const CoinPackedVectorBase *const *cols, + const double *collb, const double *colub, + const double *obj); + /** */ + virtual void deleteCols(const int num, const int *colIndices); + + using OsiSolverInterface::addRow; + /** */ + virtual void addRow(const CoinPackedVectorBase &vec, + const double rowlb, const double rowub); + /** */ + virtual void addRow(const CoinPackedVectorBase &vec, + const char rowsen, const double rowrhs, + const double rowrng); + + using OsiSolverInterface::addRows; + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const double *rowlb, const double *rowub); + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const char *rowsen, const double *rowrhs, + const double *rowrng); + /** */ + virtual void deleteRows(const int num, const int *rowIndices); + + //----------------------------------------------------------------------- + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut *cuts); + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + This uses array of pointers + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut **cuts); + //@} + //@} + + //--------------------------------------------------------------------------- + +public: + /**@name Methods to input a problem */ + //@{ + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is 0 then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by lower and upper bounds). For + default values see the previous method.
+ WARNING: The arguments passed to this method will be + freed using the C++ delete and delete[] + functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + double *&rowlb, double *&rowub); + + /** Load in an problem by copying the arguments (the constraints on the + rows are given by sense/rhs/range triplets). If a pointer is 0 then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • obj: all variables have 0 objective coefficient +
  • rowsen: all rows are >= +
  • rowrhs: all right hand sides are 0 +
  • rowrng: 0 for the ranged rows +
+ */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by sense/rhs/range triplets). For + default values see the previous method.
+ WARNING: The arguments passed to this method will be + freed using the C++ delete and delete[] + functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + char *&rowsen, double *&rowrhs, + double *&rowrng); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + using OsiSolverInterface::readMps; + /** Read an mps file from the given filename (defaults to Osi reader) - returns + number of errors (see OsiMpsReader class) */ + virtual int readMps(const char *filename, + const char *extension = "mps"); + + /** Write the problem into an mps file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants */ + virtual void writeMps(const char *filename, + const char *extension = "mps", + double objSense = 0.0) const; + /** Write the problem into an mps file of the given filename, + names may be null. formatType is + 0 - normal + 1 - extra accuracy + 2 - IEEE hex (later) + + Returns non-zero on I/O error + */ + virtual int writeMpsNative(const char *filename, + const char **rowNames, const char **columnNames, + int formatType = 0, int numberAcross = 2, + double objSense = 0.0) const; + //@} + + /**@name Message handling (extra for Cbc messages). + Normally I presume you would want the same language. + If not then you could use underlying model pointer */ + //@{ + /// Set language + void newLanguage(CoinMessages::Language language); + void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + //@} + //--------------------------------------------------------------------------- + + /**@name Cbc specific public interfaces */ + //@{ + /// Get pointer to Cbc model + inline CbcModel *getModelPtr() const + { + return modelPtr_; + } + /// Get pointer to underlying solver + inline OsiSolverInterface *getRealSolverPtr() const + { + return modelPtr_->solver(); + } + /// Set cutoff bound on the objective function. + inline void setCutoff(double value) + { + modelPtr_->setCutoff(value); + } + /// Get the cutoff bound on the objective function - always as minimize + inline double getCutoff() const + { + return modelPtr_->getCutoff(); + } + /// Set the CbcModel::CbcMaxNumNode maximum node limit + inline void setMaximumNodes(int value) + { + modelPtr_->setMaximumNodes(value); + } + /// Get the CbcModel::CbcMaxNumNode maximum node limit + inline int getMaximumNodes() const + { + return modelPtr_->getMaximumNodes(); + } + /// Set the CbcModel::CbcMaxNumSol maximum number of solutions + inline void setMaximumSolutions(int value) + { + modelPtr_->setMaximumSolutions(value); + } + /// Get the CbcModel::CbcMaxNumSol maximum number of solutions + inline int getMaximumSolutions() const + { + return modelPtr_->getMaximumSolutions(); + } + /// Set the CbcModel::CbcMaximumSeconds maximum number of seconds + inline void setMaximumSeconds(double value) + { + modelPtr_->setMaximumSeconds(value); + } + /// Get the CbcModel::CbcMaximumSeconds maximum number of seconds + inline double getMaximumSeconds() const + { + return modelPtr_->getMaximumSeconds(); + } + /// Node limit reached? + inline bool isNodeLimitReached() const + { + return modelPtr_->isNodeLimitReached(); + } + /// Solution limit reached? + inline bool isSolutionLimitReached() const + { + return modelPtr_->isSolutionLimitReached(); + } + /// Get how many Nodes it took to solve the problem. + inline int getNodeCount() const + { + return modelPtr_->getNodeCount(); + } + /// Final status of problem - 0 finished, 1 stopped, 2 difficulties + inline int status() const + { + return modelPtr_->status(); + } + /** Pass in a message handler + + It is the client's responsibility to destroy a message handler installed + by this routine; it will not be destroyed when the solver interface is + destroyed. + */ + virtual void passInMessageHandler(CoinMessageHandler *handler); + //@} + + //--------------------------------------------------------------------------- + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiCbcSolverInterface(OsiSolverInterface *solver = NULL, + CbcStrategy *strategy = NULL); + + /// Clone + virtual OsiSolverInterface *clone(bool copyData = true) const; + + /// Copy constructor + OsiCbcSolverInterface(const OsiCbcSolverInterface &); +#if 0 + /// Borrow constructor - only delete one copy + OsiCbcSolverInterface (CbcModel * rhs, bool reallyOwn=false); + + /// Releases so won't error + void releaseCbc(); +#endif + /// Assignment operator + OsiCbcSolverInterface &operator=(const OsiCbcSolverInterface &rhs); + + /// Destructor + virtual ~OsiCbcSolverInterface(); + + //@} + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to constraint matrix). */ + virtual void applyRowCut(const OsiRowCut &rc); + + /** Apply a column cut (adjust one or more bounds). */ + virtual void applyColCut(const OsiColCut &cc); + //@} + /**@name Protected member data */ + //@{ + /// Cbc model represented by this class instance + mutable CbcModel *modelPtr_; + //@} +}; +// So unit test can find out if NDEBUG set +bool OsiCbcHasNDEBUG(); + +//############################################################################# +/** A function that tests the methods in the OsiCbcSolverInterface class. */ +void OsiCbcSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir); + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiChooseVariable.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiChooseVariable.hpp new file mode 100644 index 000000000..ca8d137f9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiChooseVariable.hpp @@ -0,0 +1,645 @@ +// Copyright (C) 2006, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiChooseVariable_H +#define OsiChooseVariable_H + +#include +#include + +#include "CoinWarmStartBasis.hpp" +#include "OsiBranchingObject.hpp" + +class OsiSolverInterface; +class OsiHotInfo; + +/** This class chooses a variable to branch on + + The base class just chooses the variable and direction without strong branching but it + has information which would normally be used by strong branching e.g. to re-enter + having fixed a variable but using same candidates for strong branching. + + The flow is : + a) initialize the process. This decides on strong branching list + and stores indices of all infeasible objects + b) do strong branching on list. If list is empty then just + choose one candidate and return without strong branching. If not empty then + go through list and return best. However we may find that the node is infeasible + or that we can fix a variable. If so we return and it is up to user to call + again (after fixing a variable). +*/ + +class OsiChooseVariable { + +public: + /// Default Constructor + OsiChooseVariable(); + + /// Constructor from solver (so we can set up arrays etc) + OsiChooseVariable(const OsiSolverInterface *solver); + + /// Copy constructor + OsiChooseVariable(const OsiChooseVariable &); + + /// Assignment operator + OsiChooseVariable &operator=(const OsiChooseVariable &rhs); + + /// Clone + virtual OsiChooseVariable *clone() const; + + /// Destructor + virtual ~OsiChooseVariable(); + + /** Sets up strong list and clears all if initialize is true. + Returns number of infeasibilities. + If returns -1 then has worked out node is infeasible! + */ + virtual int setupList(OsiBranchingInformation *info, bool initialize); + /** Choose a variable + Returns - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + If fixVariables is true then 2,3,4 are all really same as problem changed + */ + virtual int chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables); + /// Returns true if solution looks feasible against given objects + virtual bool feasibleSolution(const OsiBranchingInformation *info, + const double *solution, + int numberObjects, + const OsiObject **objects); + /// Saves a good solution + void saveSolution(const OsiSolverInterface *solver); + /// Clears out good solution after use + void clearGoodSolution(); + /// Given a candidate fill in useful information e.g. estimates + virtual void updateInformation(const OsiBranchingInformation *info, + int branch, OsiHotInfo *hotInfo); +#if 1 + /// Given a branch fill in useful information e.g. estimates + virtual void updateInformation(int whichObject, int branch, + double changeInObjective, double changeInValue, + int status); +#endif + /// Objective value for feasible solution + inline double goodObjectiveValue() const + { + return goodObjectiveValue_; + } + /// Estimate of up change or change on chosen if n-way + inline double upChange() const + { + return upChange_; + } + /// Estimate of down change or max change on other possibilities if n-way + inline double downChange() const + { + return downChange_; + } + /// Good solution - deleted by finalize + inline const double *goodSolution() const + { + return goodSolution_; + } + /// Index of chosen object + inline int bestObjectIndex() const + { + return bestObjectIndex_; + } + /// Set index of chosen object + inline void setBestObjectIndex(int value) + { + bestObjectIndex_ = value; + } + /// Preferred way of chosen object + inline int bestWhichWay() const + { + return bestWhichWay_; + } + /// Set preferred way of chosen object + inline void setBestWhichWay(int value) + { + bestWhichWay_ = value; + } + /// Index of forced object + inline int firstForcedObjectIndex() const + { + return firstForcedObjectIndex_; + } + /// Set index of forced object + inline void setFirstForcedObjectIndex(int value) + { + firstForcedObjectIndex_ = value; + } + /// Preferred way of forced object + inline int firstForcedWhichWay() const + { + return firstForcedWhichWay_; + } + /// Set preferred way of forced object + inline void setFirstForcedWhichWay(int value) + { + firstForcedWhichWay_ = value; + } + /// Get the number of objects unsatisfied at this node - accurate on first pass + inline int numberUnsatisfied() const + { + return numberUnsatisfied_; + } + /// Number of objects to choose for strong branching + inline int numberStrong() const + { + return numberStrong_; + } + /// Set number of objects to choose for strong branching + inline void setNumberStrong(int value) + { + numberStrong_ = value; + } + /// Number left on strong list + inline int numberOnList() const + { + return numberOnList_; + } + /// Number of strong branches actually done + inline int numberStrongDone() const + { + return numberStrongDone_; + } + /// Number of strong iterations actually done + inline int numberStrongIterations() const + { + return numberStrongIterations_; + } + /// Number of strong branches which changed bounds + inline int numberStrongFixed() const + { + return numberStrongFixed_; + } + /// List of candidates + inline const int *candidates() const + { + return list_; + } + /// Trust results from strong branching for changing bounds + inline bool trustStrongForBound() const + { + return trustStrongForBound_; + } + /// Set trust results from strong branching for changing bounds + inline void setTrustStrongForBound(bool yesNo) + { + trustStrongForBound_ = yesNo; + } + /// Trust results from strong branching for valid solution + inline bool trustStrongForSolution() const + { + return trustStrongForSolution_; + } + /// Set trust results from strong branching for valid solution + inline void setTrustStrongForSolution(bool yesNo) + { + trustStrongForSolution_ = yesNo; + } + /// Set solver and redo arrays + void setSolver(const OsiSolverInterface *solver); + /** Return status - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + */ + inline int status() const + { + return status_; + } + inline void setStatus(int value) + { + status_ = value; + } + +protected: + // Data + /// Objective value for feasible solution + double goodObjectiveValue_; + /// Estimate of up change or change on chosen if n-way + double upChange_; + /// Estimate of down change or max change on other possibilities if n-way + double downChange_; + /// Good solution - deleted by finalize + double *goodSolution_; + /// List of candidates + int *list_; + /// Useful array (for sorting etc) + double *useful_; + /// Pointer to solver + const OsiSolverInterface *solver_; + /* Status - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + */ + int status_; + /// Index of chosen object + int bestObjectIndex_; + /// Preferred way of chosen object + int bestWhichWay_; + /// Index of forced object + int firstForcedObjectIndex_; + /// Preferred way of forced object + int firstForcedWhichWay_; + /// The number of objects unsatisfied at this node. + int numberUnsatisfied_; + /// Number of objects to choose for strong branching + int numberStrong_; + /// Number left on strong list + int numberOnList_; + /// Number of strong branches actually done + int numberStrongDone_; + /// Number of strong iterations actually done + int numberStrongIterations_; + /// Number of bound changes due to strong branching + int numberStrongFixed_; + /// List of unsatisfied objects - first numberOnList_ for strong branching + /// Trust results from strong branching for changing bounds + bool trustStrongForBound_; + /// Trust results from strong branching for valid solution + bool trustStrongForSolution_; +}; + +/** This class is the placeholder for the pseudocosts used by OsiChooseStrong. + It can also be used by any other pseudocost based strong branching + algorithm. +*/ + +class OsiPseudoCosts { +protected: + // Data + /// Total of all changes up + double *upTotalChange_; + /// Total of all changes down + double *downTotalChange_; + /// Number of times up + int *upNumber_; + /// Number of times down + int *downNumber_; + /// Number of objects (could be found from solver) + int numberObjects_; + /// Number before we trust + int numberBeforeTrusted_; + +private: + void gutsOfDelete(); + void gutsOfCopy(const OsiPseudoCosts &rhs); + +public: + OsiPseudoCosts(); + virtual ~OsiPseudoCosts(); + OsiPseudoCosts(const OsiPseudoCosts &rhs); + OsiPseudoCosts &operator=(const OsiPseudoCosts &rhs); + + /// Number of times before trusted + inline int numberBeforeTrusted() const + { + return numberBeforeTrusted_; + } + /// Set number of times before trusted + inline void setNumberBeforeTrusted(int value) + { + numberBeforeTrusted_ = value; + } + /// Initialize the pseudocosts with n entries + void initialize(int n); + /// Give the number of objects for which pseudo costs are stored + inline int numberObjects() const + { + return numberObjects_; + } + + /** @name Accessor methods to pseudo costs data */ + //@{ + inline double *upTotalChange() { return upTotalChange_; } + inline const double *upTotalChange() const { return upTotalChange_; } + + inline double *downTotalChange() { return downTotalChange_; } + inline const double *downTotalChange() const { return downTotalChange_; } + + inline int *upNumber() { return upNumber_; } + inline const int *upNumber() const { return upNumber_; } + + inline int *downNumber() { return downNumber_; } + inline const int *downNumber() const { return downNumber_; } + //@} + + /// Given a candidate fill in useful information e.g. estimates + virtual void updateInformation(const OsiBranchingInformation *info, + int branch, OsiHotInfo *hotInfo); +#if 1 + /// Given a branch fill in useful information e.g. estimates + virtual void updateInformation(int whichObject, int branch, + double changeInObjective, double changeInValue, + int status); +#endif +}; + +/** This class chooses a variable to branch on + + This chooses the variable and direction with reliability strong branching. + + The flow is : + a) initialize the process. This decides on strong branching list + and stores indices of all infeasible objects + b) do strong branching on list. If list is empty then just + choose one candidate and return without strong branching. If not empty then + go through list and return best. However we may find that the node is infeasible + or that we can fix a variable. If so we return and it is up to user to call + again (after fixing a variable). +*/ + +class OsiChooseStrong : public OsiChooseVariable { + +public: + /// Default Constructor + OsiChooseStrong(); + + /// Constructor from solver (so we can set up arrays etc) + OsiChooseStrong(const OsiSolverInterface *solver); + + /// Copy constructor + OsiChooseStrong(const OsiChooseStrong &); + + /// Assignment operator + OsiChooseStrong &operator=(const OsiChooseStrong &rhs); + + /// Clone + virtual OsiChooseVariable *clone() const; + + /// Destructor + virtual ~OsiChooseStrong(); + + /** Sets up strong list and clears all if initialize is true. + Returns number of infeasibilities. + If returns -1 then has worked out node is infeasible! + */ + virtual int setupList(OsiBranchingInformation *info, bool initialize); + /** Choose a variable + Returns - + -1 Node is infeasible + 0 Normal termination - we have a candidate + 1 All looks satisfied - no candidate + 2 We can change the bound on a variable - but we also have a strong branching candidate + 3 We can change the bound on a variable - but we have a non-strong branching candidate + 4 We can change the bound on a variable - no other candidates + We can pick up branch from bestObjectIndex() and bestWhichWay() + We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay() + If we have a solution then we can pick up from goodObjectiveValue() and goodSolution() + If fixVariables is true then 2,3,4 are all really same as problem changed + */ + virtual int chooseVariable(OsiSolverInterface *solver, OsiBranchingInformation *info, bool fixVariables); + + /** Pseudo Shadow Price mode + 0 - off + 1 - use if no strong info + 2 - use if strong not trusted + 3 - use even if trusted + */ + inline int shadowPriceMode() const + { + return shadowPriceMode_; + } + /// Set Shadow price mode + inline void setShadowPriceMode(int value) + { + shadowPriceMode_ = value; + } + + /** Accessor method to pseudo cost object*/ + const OsiPseudoCosts &pseudoCosts() const + { + return pseudoCosts_; + } + + /** Accessor method to pseudo cost object*/ + OsiPseudoCosts &pseudoCosts() + { + return pseudoCosts_; + } + + /** A feww pass-through methods to access members of pseudoCosts_ as if they + were members of OsiChooseStrong object */ + inline int numberBeforeTrusted() const + { + return pseudoCosts_.numberBeforeTrusted(); + } + inline void setNumberBeforeTrusted(int value) + { + pseudoCosts_.setNumberBeforeTrusted(value); + } + inline int numberObjects() const + { + return pseudoCosts_.numberObjects(); + } + +protected: + /** This is a utility function which does strong branching on + a list of objects and stores the results in OsiHotInfo.objects. + On entry the object sequence is stored in the OsiHotInfo object + and maybe more. + It returns - + -1 - one branch was infeasible both ways + 0 - all inspected - nothing can be fixed + 1 - all inspected - some can be fixed (returnCriterion==0) + 2 - may be returning early - one can be fixed (last one done) (returnCriterion==1) + 3 - returning because max time + + */ + int doStrongBranching(OsiSolverInterface *solver, + OsiBranchingInformation *info, + int numberToDo, int returnCriterion); + + /** Clear out the results array */ + void resetResults(int num); + +protected: + /** Pseudo Shadow Price mode + 0 - off + 1 - use and multiply by strong info + 2 - use + */ + int shadowPriceMode_; + + /** The pseudo costs for the chooser */ + OsiPseudoCosts pseudoCosts_; + + /** The results of the strong branching done on the candidates where the + pseudocosts were not sufficient */ + OsiHotInfo *results_; + /** The number of OsiHotInfo objetcs that contain information */ + int numResults_; +}; + +/** This class contains the result of strong branching on a variable + When created it stores enough information for strong branching +*/ + +class OsiHotInfo { + +public: + /// Default Constructor + OsiHotInfo(); + + /// Constructor from useful information + OsiHotInfo(OsiSolverInterface *solver, + const OsiBranchingInformation *info, + const OsiObject *const *objects, + int whichObject); + + /// Copy constructor + OsiHotInfo(const OsiHotInfo &); + + /// Assignment operator + OsiHotInfo &operator=(const OsiHotInfo &rhs); + + /// Clone + virtual OsiHotInfo *clone() const; + + /// Destructor + virtual ~OsiHotInfo(); + + /** Fill in useful information after strong branch. + Return status + */ + int updateInformation(const OsiSolverInterface *solver, const OsiBranchingInformation *info, + OsiChooseVariable *choose); + /// Original objective value + inline double originalObjectiveValue() const + { + return originalObjectiveValue_; + } + /// Up change - invalid if n-way + inline double upChange() const + { + assert(branchingObject_->numberBranches() == 2); + return changes_[1]; + } + /// Down change - invalid if n-way + inline double downChange() const + { + assert(branchingObject_->numberBranches() == 2); + return changes_[0]; + } + /// Set up change - invalid if n-way + inline void setUpChange(double value) + { + assert(branchingObject_->numberBranches() == 2); + changes_[1] = value; + } + /// Set down change - invalid if n-way + inline void setDownChange(double value) + { + assert(branchingObject_->numberBranches() == 2); + changes_[0] = value; + } + /// Change on way k + inline double change(int k) const + { + return changes_[k]; + } + + /// Up iteration count - invalid if n-way + inline int upIterationCount() const + { + assert(branchingObject_->numberBranches() == 2); + return iterationCounts_[1]; + } + /// Down iteration count - invalid if n-way + inline int downIterationCount() const + { + assert(branchingObject_->numberBranches() == 2); + return iterationCounts_[0]; + } + /// Iteration count on way k + inline int iterationCount(int k) const + { + return iterationCounts_[k]; + } + + /// Up status - invalid if n-way + inline int upStatus() const + { + assert(branchingObject_->numberBranches() == 2); + return statuses_[1]; + } + /// Down status - invalid if n-way + inline int downStatus() const + { + assert(branchingObject_->numberBranches() == 2); + return statuses_[0]; + } + /// Set up status - invalid if n-way + inline void setUpStatus(int value) + { + assert(branchingObject_->numberBranches() == 2); + statuses_[1] = value; + } + /// Set down status - invalid if n-way + inline void setDownStatus(int value) + { + assert(branchingObject_->numberBranches() == 2); + statuses_[0] = value; + } + /// Status on way k + inline int status(int k) const + { + return statuses_[k]; + } + /// Branching object + inline OsiBranchingObject *branchingObject() const + { + return branchingObject_; + } + inline int whichObject() const + { + return whichObject_; + } + +protected: + // Data + /// Original objective value + double originalObjectiveValue_; + /// Objective changes + double *changes_; + /// Iteration counts + int *iterationCounts_; + /** Status + -1 - not done + 0 - feasible and finished + 1 - infeasible + 2 - not finished + */ + int *statuses_; + /// Branching object + OsiBranchingObject *branchingObject_; + /// Which object on list + int whichObject_; +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiClpSolverInterface.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiClpSolverInterface.hpp new file mode 100644 index 000000000..9b945741f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiClpSolverInterface.hpp @@ -0,0 +1,1604 @@ +// $Id$ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiClpSolverInterface_H +#define OsiClpSolverInterface_H + +#include +#include +#include + +#include "ClpSimplex.hpp" +#include "ClpLinearObjective.hpp" +#include "CoinPackedMatrix.hpp" +#include "OsiSolverInterface.hpp" +#include "CoinWarmStartBasis.hpp" +#include "ClpEventHandler.hpp" +#include "ClpNode.hpp" +#include "CoinIndexedVector.hpp" +#include "CoinFinite.hpp" + +class OsiRowCut; +class OsiClpUserSolver; +class OsiClpDisasterHandler; +class CoinSet; +static const double OsiClpInfinity = COIN_DBL_MAX; + +//############################################################################# + +/** Clp Solver Interface + +Instantiation of OsiClpSolverInterface for the Model Algorithm. + +*/ + +class OsiClpSolverInterface : virtual public OsiSolverInterface { + friend void OsiClpSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir); + +public: + //--------------------------------------------------------------------------- + /**@name Solve methods */ + //@{ + /// Solve initial LP relaxation + virtual void initialSolve(); + + /// Resolve an LP relaxation after problem modification + virtual void resolve(); + + /// Resolve an LP relaxation after problem modification (try GUB) + virtual void resolveGub(int needed); + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound(); + + /** Solve when primal column and dual row solutions are near-optimal + options - 0 no presolve (use primal and dual) + 1 presolve (just use primal) + 2 no presolve (just use primal) + basis - 0 use all slack basis + 1 try and put some in basis + */ + void crossover(int options, int basis); + //@} + + /*! @name OsiSimplexInterface methods + \brief Methods for the Osi Simplex API. + + The current implementation should work for both minimisation and + maximisation in mode 1 (tableau access). In mode 2 (single pivot), only + minimisation is supported as of 100907. + */ + //@{ + /** \brief Simplex API capability. + + Returns + - 0 if no simplex API + - 1 if can just do getBInv etc + - 2 if has all OsiSimplex methods + */ + virtual int canDoSimplexInterface() const; + + /*! \brief Enables simplex mode 1 (tableau access) + + Tells solver that calls to getBInv etc are about to take place. + Underlying code may need mutable as this may be called from + CglCut::generateCuts which is const. If that is too horrific then + each solver e.g. BCP or CBC will have to do something outside + main loop. + */ + virtual void enableFactorization() const; + + /*! \brief Undo any setting changes made by #enableFactorization */ + virtual void disableFactorization() const; + + /** Returns true if a basis is available + AND problem is optimal. This should be used to see if + the BInvARow type operations are possible and meaningful. + */ + virtual bool basisIsAvailable() const; + + /** The following two methods may be replaced by the + methods of OsiSolverInterface using OsiWarmStartBasis if: + 1. OsiWarmStartBasis resize operation is implemented + more efficiently and + 2. It is ensured that effects on the solver are the same + + Returns a basis status of the structural/artificial variables + At present as warm start i.e 0 free, 1 basic, 2 upper, 3 lower + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + virtual void getBasisStatus(int *cstat, int *rstat) const; + + /** Set the status of structural/artificial variables and + factorize, update solution etc + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + Returns 0 if OK, 1 if problem is bad e.g. duplicate elements, too large ... + */ + virtual int setBasisStatus(const int *cstat, const int *rstat); + + ///Get the reduced gradient for the cost vector c + virtual void getReducedGradient(double *columnReducedCosts, + double *duals, + const double *c) const; + + ///Get a row of the tableau (slack part in slack if not NULL) + virtual void getBInvARow(int row, double *z, double *slack = NULL) const; + + /** Get a row of the tableau (slack part in slack if not NULL) + If keepScaled is true then scale factors not applied after so + user has to use coding similar to what is in this method + */ + virtual void getBInvARow(int row, CoinIndexedVector *z, CoinIndexedVector *slack = NULL, + bool keepScaled = false) const; + + ///Get a row of the basis inverse + virtual void getBInvRow(int row, double *z) const; + + ///Get a column of the tableau + virtual void getBInvACol(int col, double *vec) const; + + ///Get a column of the tableau + virtual void getBInvACol(int col, CoinIndexedVector *vec) const; + + /** Update (i.e. ftran) the vector passed in. + Unscaling is applied after - can't be applied before + */ + + virtual void getBInvACol(CoinIndexedVector *vec) const; + + ///Get a column of the basis inverse + virtual void getBInvCol(int col, double *vec) const; + + /** Get basic indices (order of indices corresponds to the + order of elements in a vector retured by getBInvACol() and + getBInvCol()). + */ + virtual void getBasics(int *index) const; + + /*! \brief Enables simplex mode 2 (individual pivot control) + + This method is supposed to ensure that all typical things (like + reduced costs, etc.) are updated when individual pivots are executed + and can be queried by other methods. + */ + virtual void enableSimplexInterface(bool doingPrimal); + + /*! \brief Undo setting changes made by #enableSimplexInterface */ + virtual void disableSimplexInterface(); + + /** Perform a pivot by substituting a colIn for colOut in the basis. + The status of the leaving variable is given in statOut. Where + 1 is to upper bound, -1 to lower bound + Return code is 0 for okay, + 1 if inaccuracy forced re-factorization (should be okay) and + -1 for singular factorization + */ + virtual int pivot(int colIn, int colOut, int outStatus); + + /** Obtain a result of the primal pivot + Outputs: colOut -- leaving column, outStatus -- its status, + t -- step size, and, if dx!=NULL, *dx -- primal ray direction. + Inputs: colIn -- entering column, sign -- direction of its change (+/-1). + Both for colIn and colOut, artificial variables are index by + the negative of the row index minus 1. + Return code (for now): 0 -- leaving variable found, + -1 -- everything else? + Clearly, more informative set of return values is required + Primal and dual solutions are updated + */ + virtual int primalPivotResult(int colIn, int sign, + int &colOut, int &outStatus, + double &t, CoinPackedVector *dx); + + /** Obtain a result of the dual pivot (similar to the previous method) + Differences: entering variable and a sign of its change are now + the outputs, the leaving variable and its statuts -- the inputs + If dx!=NULL, then *dx contains dual ray + Return code: same + */ + virtual int dualPivotResult(int &colIn, int &sign, + int colOut, int outStatus, + double &t, CoinPackedVector *dx); + + //@} + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. There can be various reasons for failure: the given + parameter is not applicable for the solver (e.g., refactorization + frequency for the clp algorithm), the parameter is not yet implemented + for the solver or simply the value of the parameter is out of the range + the solver accepts. If a parameter setting call returns false check the + details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + */ + //@{ + // Set an integer parameter + bool setIntParam(OsiIntParam key, int value); + // Set an double parameter + bool setDblParam(OsiDblParam key, double value); + // Set a string parameter + bool setStrParam(OsiStrParam key, const std::string &value); + // Get an integer parameter + bool getIntParam(OsiIntParam key, int &value) const; + // Get an double parameter + bool getDblParam(OsiDblParam key, double &value) const; + // Get a string parameter + bool getStrParam(OsiStrParam key, std::string &value) const; + // Set a hint parameter - overrides OsiSolverInterface + virtual bool setHintParam(OsiHintParam key, bool yesNo = true, + OsiHintStrength strength = OsiHintTry, + void *otherInformation = NULL); + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there a numerical difficulties? + virtual bool isAbandoned() const; + /// Is optimality proven? + virtual bool isProvenOptimal() const; + /// Is primal infeasiblity proven? + virtual bool isProvenPrimalInfeasible() const; + /// Is dual infeasiblity proven? + virtual bool isProvenDualInfeasible() const; + /// Is the given primal objective limit reached? + virtual bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + virtual bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + virtual bool isIterationLimitReached() const; + //@} + + //--------------------------------------------------------------------------- + /**@name WarmStart related methods */ + //@{ + + /*! \brief Get an empty warm start object + + This routine returns an empty CoinWarmStartBasis object. Its purpose is + to provide a way to give a client a warm start basis object of the + appropriate type, which can resized and modified as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart() const; + + /// Get warmstarting information + virtual CoinWarmStart *getWarmStart() const; + /// Get warmstarting information + inline CoinWarmStartBasis *getPointerToWarmStart() + { + return &basis_; + } + /// Get warmstarting information + inline const CoinWarmStartBasis *getConstPointerToWarmStart() const + { + return &basis_; + } + /** Set warmstarting information. Return true/false depending on whether + the warmstart information was accepted or not. */ + virtual bool setWarmStart(const CoinWarmStart *warmstart); + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. This does not necessarily create an + object - may just point to one. must Delete set true if user + should delete returned object. + OsiClp version always returns pointer and false. + */ + virtual CoinWarmStart *getPointerToWarmStart(bool &mustDelete); + + /// Set column status in ClpSimplex and warmStart + void setColumnStatus(int iColumn, ClpSimplex::Status status); + + //@} + + //--------------------------------------------------------------------------- + /**@name Hotstart related methods (primarily used in strong branching). + The user can create a hotstart (a snapshot) of the optimization process + then reoptimize over and over again always starting from there.
+ NOTE: between hotstarted optimizations only + bound changes are allowed. */ + //@{ + /// Create a hotstart point of the optimization process + virtual void markHotStart(); + /// Optimize starting from the hotstart + virtual void solveFromHotStart(); + /// Delete the snapshot + virtual void unmarkHotStart(); + /** Start faster dual - returns negative if problems 1 if infeasible, + Options to pass to solver + 1 - create external reduced costs for columns + 2 - create external reduced costs for rows + 4 - create external row activity (columns always done) + Above only done if feasible + When set resolve does less work + */ + int startFastDual(int options); + /// Stop fast dual + void stopFastDual(); + /// Sets integer tolerance and increment + void setStuff(double tolerance, double increment); + /// Return a conflict analysis cut from small model + OsiRowCut *smallModelCut(const double *originalLower, const double *originalUpper, + int numberRowsAtContinuous, const int *whichGenerator, + int typeCut = 0); + /** Return a conflict analysis cut from model + If type is 0 then genuine cut, if 1 then only partially processed + */ + OsiRowCut *modelCut(const double *originalLower, const double *originalUpper, + int numberRowsAtContinuous, const int *whichGenerator, + int typeCut = 0); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem information methods + + These methods call the solver's query routines to return + information about the problem referred to by the current object. + Querying a problem that has no data associated with it result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. + + Const pointers returned from any data-query method are valid as + long as the data is unchanged and the solver is not called. + */ + //@{ + /**@name Methods related to querying the input data */ + //@{ + /// Get number of columns + virtual int getNumCols() const + { + return modelPtr_->numberColumns(); + } + + /// Get number of rows + virtual int getNumRows() const + { + return modelPtr_->numberRows(); + } + + /// Get number of nonzero elements + virtual CoinBigIndex getNumElements() const + { + CoinBigIndex retVal = 0; + const CoinPackedMatrix *matrix = modelPtr_->matrix(); + if (matrix != NULL) + retVal = matrix->getNumElements(); + return retVal; + } + + /// Return name of row if one exists or Rnnnnnnn + /// maxLen is currently ignored and only there to match the signature from the base class! + virtual std::string getRowName(int rowIndex, + unsigned maxLen = static_cast< unsigned >(std::string::npos)) const; + + /// Return name of column if one exists or Cnnnnnnn + /// maxLen is currently ignored and only there to match the signature from the base class! + virtual std::string getColName(int colIndex, + unsigned maxLen = static_cast< unsigned >(std::string::npos)) const; + + /// Get pointer to array[getNumCols()] of column lower bounds + virtual const double *getColLower() const { return modelPtr_->columnLower(); } + + /// Get pointer to array[getNumCols()] of column upper bounds + virtual const double *getColUpper() const { return modelPtr_->columnUpper(); } + + /** Get pointer to array[getNumRows()] of row constraint senses. +
    +
  • 'L' <= constraint +
  • 'E' = constraint +
  • 'G' >= constraint +
  • 'R' ranged constraint +
  • 'N' free constraint +
+ */ + virtual const char *getRowSense() const; + + /** Get pointer to array[getNumRows()] of rows right-hand sides +
    +
  • if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] +
  • if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] +
  • if rowsense()[i] == 'N' then rhs()[i] == 0.0 +
+ */ + virtual const double *getRightHandSide() const; + + /** Get pointer to array[getNumRows()] of row ranges. +
    +
  • if rowsense()[i] == 'R' then + rowrange()[i] == rowupper()[i] - rowlower()[i] +
  • if rowsense()[i] != 'R' then + rowrange()[i] is undefined +
+ */ + virtual const double *getRowRange() const; + + /// Get pointer to array[getNumRows()] of row lower bounds + virtual const double *getRowLower() const { return modelPtr_->rowLower(); } + + /// Get pointer to array[getNumRows()] of row upper bounds + virtual const double *getRowUpper() const { return modelPtr_->rowUpper(); } + + /// Get pointer to array[getNumCols()] of objective function coefficients + virtual const double *getObjCoefficients() const + { + if (fakeMinInSimplex_) + return linearObjective_; + else + return modelPtr_->objective(); + } + + /// Get objective function sense (1 for min (default), -1 for max) + virtual double getObjSense() const + { + return ((fakeMinInSimplex_) ? -modelPtr_->optimizationDirection() : modelPtr_->optimizationDirection()); + } + + /// Return true if column is continuous + virtual bool isContinuous(int colNumber) const; + /// Return true if variable is binary + virtual bool isBinary(int colIndex) const; + + /** Return true if column is integer. + Note: This function returns true if the the column + is binary or a general integer. + */ + virtual bool isInteger(int colIndex) const; + + /// Return true if variable is general integer + virtual bool isIntegerNonBinary(int colIndex) const; + + /// Return true if variable is binary and not fixed at either bound + virtual bool isFreeBinary(int colIndex) const; + /** Return array of column length + 0 - continuous + 1 - binary (may get fixed later) + 2 - general integer (may get fixed later) + */ + virtual const char *getColType(bool refresh = false) const; + + /** Return true if column is integer but does not have to + be declared as such. + Note: This function returns true if the the column + is binary or a general integer. + */ + bool isOptionalInteger(int colIndex) const; + /** Set the index-th variable to be an optional integer variable */ + void setOptionalInteger(int index); + /// Return true only if integer and not optional + inline bool isHeuristicInteger(int colIndex) const + { + return (integerInformation_ && integerInformation_[colIndex] == 1); + } + /// Return integer type (0,1,2=optional,3=sc,4=scint) + inline int integerType(int colIndex) const + { + return integerInformation_ ? integerInformation_[colIndex] : 0; + } + /// Set integer type (0,1,2=optional,3=sc,4=scint) + inline void setIntegerType(int colIndex, int value) + { + integerInformation_[colIndex] = static_cast< char >(value); + } + /// Get pointer to row-wise copy of matrix + virtual const CoinPackedMatrix *getMatrixByRow() const; + + /// Get pointer to column-wise copy of matrix + virtual const CoinPackedMatrix *getMatrixByCol() const; + + /// Get pointer to mutable column-wise copy of matrix + virtual CoinPackedMatrix *getMutableMatrixByCol() const; + + /// Get solver's value for infinity + virtual double getInfinity() const { return OsiClpInfinity; } + //@} + + /**@name Methods related to querying the solution */ + //@{ + /// Get pointer to array[getNumCols()] of primal solution vector + virtual const double *getColSolution() const; + + /// Get pointer to array[getNumRows()] of dual prices + virtual const double *getRowPrice() const; + + /// Get a pointer to array[getNumCols()] of reduced costs + virtual const double *getReducedCost() const; + + /** Get pointer to array[getNumRows()] of row activity levels (constraint + matrix times the solution vector */ + virtual const double *getRowActivity() const; + + /// Get objective function value + virtual double getObjValue() const; + + /** Get how many iterations it took to solve the problem (whatever + "iteration" mean to the solver. */ + virtual int getIterationCount() const + { + return modelPtr_->numberIterations(); + } + + /** Get as many dual rays as the solver can provide. (In case of proven + primal infeasibility there should be at least one.) + + The first getNumRows() ray components will always be associated with + the row duals (as returned by getRowPrice()). If \c fullRay is true, + the final getNumCols() entries will correspond to the ray components + associated with the nonbasic variables. If the full ray is requested + and the method cannot provide it, it will throw an exception. + + NOTE for implementers of solver interfaces:
+ The double pointers in the vector should point to arrays of length + getNumRows() and they should be allocated via new[].
+ + NOTE for users of solver interfaces:
+ It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector< double * > getDualRays(int maxNumRays, + bool fullRay = false) const; + /** Get as many primal rays as the solver can provide. (In case of proven + dual infeasibility there should be at least one.) + + NOTE for implementers of solver interfaces:
+ The double pointers in the vector should point to arrays of length + getNumCols() and they should be allocated via new[].
+ + NOTE for users of solver interfaces:
+ It is the user's responsibility to free the double pointers in the + vector using delete[]. + */ + virtual std::vector< double * > getPrimalRays(int maxNumRays) const; + + //@} + //@} + + //--------------------------------------------------------------------------- + + /**@name Problem modifying methods */ + //@{ + //------------------------------------------------------------------------- + /**@name Changing bounds on variables and constraints */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff(int elementIndex, double elementValue); + + /** Set a single column lower bound
+ Use -DBL_MAX for -infinity. */ + virtual void setColLower(int elementIndex, double elementValue); + + /** Set a single column upper bound
+ Use DBL_MAX for infinity. */ + virtual void setColUpper(int elementIndex, double elementValue); + + /** Set a single column lower and upper bound */ + virtual void setColBounds(int elementIndex, + double lower, double upper); + + /** Set the bounds on a number of columns simultaneously
+ The default implementation just invokes setColLower() and + setColUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the variables whose + either bound changes + @param boundList the new lower/upper bound pairs for the variables + */ + virtual void setColSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set a single row lower bound
+ Use -DBL_MAX for -infinity. */ + virtual void setRowLower(int elementIndex, double elementValue); + + /** Set a single row upper bound
+ Use DBL_MAX for infinity. */ + virtual void setRowUpper(int elementIndex, double elementValue); + + /** Set a single row lower and upper bound */ + virtual void setRowBounds(int elementIndex, + double lower, double upper); + + /** Set the type of a single row
*/ + virtual void setRowType(int index, char sense, double rightHandSide, + double range); + + /** Set the bounds on a number of rows simultaneously
+ The default implementation just invokes setRowLower() and + setRowUpper() over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + either bound changes + @param boundList the new lower/upper bound pairs for the constraints + */ + virtual void setRowSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set the type of a number of rows simultaneously
+ The default implementation just invokes setRowType() + over and over again. + @param indexFirst,indexLast pointers to the beginning and after the + end of the array of the indices of the constraints whose + any characteristics changes + @param senseList the new senses + @param rhsList the new right hand sides + @param rangeList the new ranges + */ + virtual void setRowSetTypes(const int *indexFirst, + const int *indexLast, + const char *senseList, + const double *rhsList, + const double *rangeList); + /** Set the objective coefficients for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setObjective(const double *array); + + /** Set the lower bounds for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColLower(const double *array); + + /** Set the upper bounds for all columns + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColUpper(const double *array); + + // using OsiSolverInterface::setRowName ; + /// Set name of row + // virtual void setRowName(int rowIndex, std::string & name) ; + virtual void setRowName(int rowIndex, std::string name); + + // using OsiSolverInterface::setColName ; + /// Set name of column + // virtual void setColName(int colIndex, std::string & name) ; + virtual void setColName(int colIndex, std::string name); + + //@} + + //------------------------------------------------------------------------- + /**@name Integrality related changing methods */ + //@{ + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index); + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index); + /** Set the variables listed in indices (which is of length len) to be + continuous variables */ + virtual void setContinuous(const int *indices, int len); + /** Set the variables listed in indices (which is of length len) to be + integer variables */ + virtual void setInteger(const int *indices, int len); + /// Number of SOS sets + inline int numberSOS() const + { + return numberSOS_; + } + /// SOS set info + inline const CoinSet *setInfo() const + { + return setInfo_; + } + /// Replace setInfo (takes over ownership) + void replaceSetInfo(int numberSOS, CoinSet *setInfo); + /** \brief Identify integer variables and SOS and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If the solver supports SOS then do the same for SOS. + If justCount then no objects created and we just store numberIntegers_ + Returns number of SOS + */ + + virtual int findIntegersAndSOS(bool justCount); + //@} + + //------------------------------------------------------------------------- + /// Set objective function sense (1 for min (default), -1 for max,) + virtual void setObjSense(double s) + { + modelPtr_->setOptimizationDirection(s < 0 ? -1 : 1); + } + + /** Set the primal solution column values + + colsol[numcols()] is an array of values of the problem column + variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of colsol() until changed by another call to + setColsol() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setColSolution(const double *colsol); + + /** Set dual solution vector + + rowprice[numrows()] is an array of values of the problem row + dual variables. These values are copied to memory owned by the + solver object or the solver. They will be returned as the + result of rowprice() until changed by another call to + setRowprice() or by a call to any solver routine. Whether the + solver makes use of the solution in any way is + solver-dependent. + */ + virtual void setRowPrice(const double *rowprice); + + //------------------------------------------------------------------------- + /**@name Methods to expand a problem.
+ Note that if a column is added then by default it will correspond to a + continuous variable. */ + //@{ + + //using OsiSolverInterface::addCol ; + /** */ + virtual void addCol(const CoinPackedVectorBase &vec, + const double collb, const double colub, + const double obj); + /*! \brief Add a named column (primal variable) to the problem. + */ + virtual void addCol(const CoinPackedVectorBase &vec, + const double collb, const double colub, + const double obj, std::string name); + /** Add a column (primal variable) to the problem. */ + virtual void addCol(int numberElements, const int *rows, const double *elements, + const double collb, const double colub, + const double obj); + /*! \brief Add a named column (primal variable) to the problem. + */ + virtual void addCol(int numberElements, + const int *rows, const double *elements, + const double collb, const double colub, + const double obj, std::string name); + /** */ + virtual void addCols(const int numcols, + const CoinPackedVectorBase *const *cols, + const double *collb, const double *colub, + const double *obj); + /** */ + virtual void addCols(const int numcols, + const CoinBigIndex *columnStarts, const int *rows, const double *elements, + const double *collb, const double *colub, + const double *obj); + /** */ + virtual void deleteCols(const int num, const int *colIndices); + + /** */ + virtual void addRow(const CoinPackedVectorBase &vec, + const double rowlb, const double rowub); + /** */ + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase &vec, + const double rowlb, const double rowub, + std::string name); + virtual void addRow(const CoinPackedVectorBase &vec, + const char rowsen, const double rowrhs, + const double rowrng); + /** Add a row (constraint) to the problem. */ + virtual void addRow(int numberElements, const int *columns, const double *element, + const double rowlb, const double rowub); + /*! \brief Add a named row (constraint) to the problem. + */ + virtual void addRow(const CoinPackedVectorBase &vec, + const char rowsen, const double rowrhs, + const double rowrng, std::string name); + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const double *rowlb, const double *rowub); + /** */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + /** */ + virtual void addRows(const int numrows, + const CoinBigIndex *rowStarts, const int *columns, const double *element, + const double *rowlb, const double *rowub); + /// + void modifyCoefficient(int row, int column, double newElement, + bool keepZero = false) + { + modelPtr_->modifyCoefficient(row, column, newElement, keepZero); + } + + /** */ + virtual void deleteRows(const int num, const int *rowIndices); + /** If solver wants it can save a copy of "base" (continuous) model here + */ + virtual void saveBaseModel(); + /** Strip off rows to get to this number of rows. + If solver wants it can restore a copy of "base" (continuous) model here + */ + virtual void restoreBaseModel(int numberRows); + + //----------------------------------------------------------------------- + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut *cuts); + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + This uses array of pointers + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut **cuts); + /** Apply a collection of cuts. + + Only cuts which have an effectiveness >= effectivenessLb + are applied. +
    +
  • ReturnCode.getNumineffective() -- number of cuts which were + not applied because they had an + effectiveness < effectivenessLb +
  • ReturnCode.getNuminconsistent() -- number of invalid cuts +
  • ReturnCode.getNuminconsistentWrtIntegerModel() -- number of + cuts that are invalid with respect to this integer model +
  • ReturnCode.getNuminfeasible() -- number of cuts that would + make this integer model infeasible +
  • ReturnCode.getNumApplied() -- number of integer cuts which + were applied to the integer model +
  • cs.size() == getNumineffective() + + getNuminconsistent() + + getNuminconsistentWrtIntegerModel() + + getNuminfeasible() + + getNumApplied() +
+ */ + virtual ApplyCutsReturnCode applyCuts(const OsiCuts &cs, + double effectivenessLb = 0.0); + + //@} + //@} + + //--------------------------------------------------------------------------- + +public: + /**@name Methods to input a problem */ + //@{ + /** Load in an problem by copying the arguments (the constraints on the + rows are given by lower and upper bounds). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by lower and upper bounds). For + default values see the previous method.
+ WARNING: The arguments passed to this method will be + freed using the C++ delete and delete[] + functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + double *&rowlb, double *&rowub); + + /** Load in an problem by copying the arguments (the constraints on the + rows are given by sense/rhs/range triplets). If a pointer is NULL then the + following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • obj: all variables have 0 objective coefficient +
  • rowsen: all rows are >= +
  • rowrhs: all right hand sides are 0 +
  • rowrng: 0 for the ranged rows +
+ */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + /** Load in an problem by assuming ownership of the arguments (the + constraints on the rows are given by sense/rhs/range triplets). For + default values see the previous method.
+ WARNING: The arguments passed to this method will be + freed using the C++ delete and delete[] + functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + char *&rowsen, double *&rowrhs, + double *&rowrng); + + /** Just like the other loadProblem() methods except that the matrix is + given as a ClpMatrixBase. */ + virtual void loadProblem(const ClpMatrixBase &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub); + + /** Just like the other loadProblem() methods except that the matrix is + given in a standard column major ordered format (without gaps). */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng); + /// This loads a model from a coinModel object - returns number of errors + virtual int loadFromCoinModel(CoinModel &modelObject, bool keepSolution = false); + + /** Read an mps file from the given filename (defaults to Osi reader) - returns + number of errors (see OsiMpsReader class) */ + virtual int readMps(const char *filename, + const char *extension = "mps"); + /** Read an mps file from the given filename returns + number of errors (see OsiMpsReader class) */ + int readMps(const char *filename, bool keepNames, bool allowErrors); + /// Read an mps file + virtual int readMps(const char *filename, const char *extension, + int &numberSets, CoinSet **&sets); + + /** Write the problem into an mps file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants */ + virtual void writeMps(const char *filename, + const char *extension = "mps", + double objSense = 0.0) const; + /** Write the problem into an mps file of the given filename, + names may be null. formatType is + 0 - normal + 1 - extra accuracy + 2 - IEEE hex (later) + + Returns non-zero on I/O error + */ + virtual int writeMpsNative(const char *filename, + const char **rowNames, const char **columnNames, + int formatType = 0, int numberAcross = 2, + double objSense = 0.0) const; + /// Read file in LP format (with names) + virtual int readLp(const char *filename, const double epsilon = 1e-5); + /** Write the problem into an Lp file of the given filename. + If objSense is non zero then -1.0 forces the code to write a + maximization objective and +1.0 to write a minimization one. + If 0.0 then solver can do what it wants. + This version calls writeLpNative with names */ + virtual void writeLp(const char *filename, + const char *extension = "lp", + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLp() with first parameter filename. + */ + virtual void writeLp(FILE *fp, + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + /** + I (JJF) am getting annoyed because I can't just replace a matrix. + The default behavior of this is do nothing so only use where that would not matter + e.g. strengthening a matrix for MIP + */ + virtual void replaceMatrixOptional(const CoinPackedMatrix &matrix); + /// And if it does matter (not used at present) + virtual void replaceMatrix(const CoinPackedMatrix &matrix); + //@} + + /**@name Message handling (extra for Clp messages). + Normally I presume you would want the same language. + If not then you could use underlying model pointer */ + //@{ + /** Pass in a message handler + + It is the client's responsibility to destroy a message handler installed + by this routine; it will not be destroyed when the solver interface is + destroyed. + */ + virtual void passInMessageHandler(CoinMessageHandler *handler); + /// Set language + void newLanguage(CoinMessages::Language language); + void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + /// Set log level (will also set underlying solver's log level) + void setLogLevel(int value); + /// Create C++ lines to get to current state + void generateCpp(FILE *fp); + //@} + //--------------------------------------------------------------------------- + + /**@name Clp specific public interfaces */ + //@{ + /// Get pointer to Clp model + ClpSimplex *getModelPtr() const; + /// Set pointer to Clp model and return old + inline ClpSimplex *swapModelPtr(ClpSimplex *newModel) + { + ClpSimplex *model = modelPtr_; + modelPtr_ = newModel; + return model; + } + /// Get special options + inline unsigned int specialOptions() const + { + return specialOptions_; + } + void setSpecialOptions(unsigned int value); + /// Last algorithm used , 1 = primal, 2 = dual other unknown + inline int lastAlgorithm() const + { + return lastAlgorithm_; + } + /// Set last algorithm used , 1 = primal, 2 = dual other unknown + inline void setLastAlgorithm(int value) + { + lastAlgorithm_ = value; + } + /// Get scaling action option + inline int cleanupScaling() const + { + return cleanupScaling_; + } + /** Set Scaling option + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + */ + inline void setCleanupScaling(int value) + { + cleanupScaling_ = value; + } + /** Get smallest allowed element in cut. + If smaller than this then ignored */ + inline double smallestElementInCut() const + { + return smallestElementInCut_; + } + /** Set smallest allowed element in cut. + If smaller than this then ignored */ + inline void setSmallestElementInCut(double value) + { + smallestElementInCut_ = value; + } + /** Get smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. + (upper-lower) is taken to be at least 1.0 and + this is assumed >= smallestElementInCut_ + */ + inline double smallestChangeInCut() const + { + return smallestChangeInCut_; + } + /** Set smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. + (upper-lower) is taken to be at least 1.0 and + this is assumed >= smallestElementInCut_ + */ + inline void setSmallestChangeInCut(double value) + { + smallestChangeInCut_ = value; + } + /// Pass in initial solve options + inline void setSolveOptions(const ClpSolve &options) + { + solveOptions_ = options; + } + /** Tighten bounds - lightweight or very lightweight + 0 - normal, 1 lightweight but just integers, 2 lightweight and all + */ + virtual int tightenBounds(int lightweight = 0); + /// See if any integer variables make infeasible other way + int infeasibleOtherWay(char *whichWay); + /// Return number of entries in L part of current factorization + virtual CoinBigIndex getSizeL() const; + /// Return number of entries in U part of current factorization + virtual CoinBigIndex getSizeU() const; + /// Get disaster handler + const OsiClpDisasterHandler *disasterHandler() const + { + return disasterHandler_; + } + /// Pass in disaster handler + void passInDisasterHandler(OsiClpDisasterHandler *handler); + /// Get fake objective + ClpLinearObjective *fakeObjective() const + { + return fakeObjective_; + } + /// Set fake objective (and take ownership) + void setFakeObjective(ClpLinearObjective *fakeObjective); + /// Set fake objective + void setFakeObjective(double *fakeObjective); + /*! \brief Set up solver for repeated use by Osi interface. + + The normal usage does things like keeping factorization around so can be + used. Will also do things like keep scaling and row copy of matrix if + matrix does not change. + + \p senseOfAdventure: + - 0 - safe stuff as above + - 1 - will take more risks - if it does not work then bug which will be + fixed + - 2 - don't bother doing most extreme termination checks e.g. don't bother + re-factorizing if less than 20 iterations. + - 3 - Actually safer than 1 (mainly just keeps factorization) + + \p printOut + - -1 always skip round common messages instead of doing some work + - 0 skip if normal defaults + - 1 leaves + */ + void setupForRepeatedUse(int senseOfAdventure = 0, int printOut = 0); + /// Synchronize model (really if no cuts in tree) + virtual void synchronizeModel(); + /*! \brief Set special options in underlying clp solver. + + Safe as const because #modelPtr_ is mutable. + */ + void setSpecialOptionsMutable(unsigned int value) const; + + //@} + + //--------------------------------------------------------------------------- + + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiClpSolverInterface(); + + /// Clone + virtual OsiSolverInterface *clone(bool copyData = true) const; + + /// Copy constructor + OsiClpSolverInterface(const OsiClpSolverInterface &); + + /// Borrow constructor - only delete one copy + OsiClpSolverInterface(ClpSimplex *rhs, bool reallyOwn = false); + + /// Releases so won't error + void releaseClp(); + + /// Assignment operator + OsiClpSolverInterface &operator=(const OsiClpSolverInterface &rhs); + + /// Destructor + virtual ~OsiClpSolverInterface(); + + /// Resets as if default constructor + virtual void reset(); + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to constraint matrix). */ + virtual void applyRowCut(const OsiRowCut &rc); + + /** Apply a column cut (adjust one or more bounds). */ + virtual void applyColCut(const OsiColCut &cc); + //@} + + //--------------------------------------------------------------------------- + +protected: + /**@name Protected methods */ + //@{ + /// The real work of a copy constructor (used by copy and assignment) + void gutsOfDestructor(); + + /// Deletes all mutable stuff + void freeCachedResults() const; + + /// Deletes all mutable stuff for row ranges etc + void freeCachedResults0() const; + + /// Deletes all mutable stuff for matrix etc + void freeCachedResults1() const; + + /// A method that fills up the rowsense_, rhs_ and rowrange_ arrays + void extractSenseRhsRange() const; + + /// + void fillParamMaps(); + /** Warm start + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + CoinWarmStartBasis getBasis(ClpSimplex *model) const; + /** Sets up working basis as a copy of input + + NOTE artificials are treated as +1 elements so for <= rhs + artificial will be at lower bound if constraint is tight + + This means that Clpsimplex flips artificials as it works + in terms of row activities + */ + void setBasis(const CoinWarmStartBasis &basis, ClpSimplex *model); + /// Crunch down problem a bit + void crunch(); + /// Extend scale factors + void redoScaleFactors(int numberRows, const CoinBigIndex *starts, + const int *indices, const double *elements); + +public: + /** Sets up working basis as a copy of input and puts in as basis + */ + void setBasis(const CoinWarmStartBasis &basis); + /// Just puts current basis_ into ClpSimplex model + inline void setBasis() + { + setBasis(basis_, modelPtr_); + } + /// Warm start difference from basis_ to statusArray + CoinWarmStartDiff *getBasisDiff(const unsigned char *statusArray) const; + /// Warm start from statusArray + CoinWarmStartBasis *getBasis(const unsigned char *statusArray) const; + /// Delete all scale factor stuff and reset option + void deleteScaleFactors(); + /// If doing fast hot start then ranges are computed + inline const double *upRange() const + { + return rowActivity_; + } + inline const double *downRange() const + { + return columnActivity_; + } + /// Pass in range array + inline void passInRanges(int *array) + { + whichRange_ = array; + } + /// Pass in sos stuff from AMPl + void setSOSData(int numberSOS, const char *type, + const int *start, const int *indices, const double *weights = NULL); + /// Compute largest amount any at continuous away from bound + void computeLargestAway(); + /// Get largest amount continuous away from bound + inline double largestAway() const + { + return largestAway_; + } + /// Set largest amount continuous away from bound + inline void setLargestAway(double value) + { + largestAway_ = value; + } + /// Sort of lexicographic resolve + void lexSolve(); + /// Get continuous model + inline ClpSimplex *getContinuousModel() const + { + return continuousModel_; + } + /// Set continuous model + inline void setContinuousModel(ClpSimplex *model) + { + continuousModel_ = model; + } + //@} + +protected: + /**@name Protected member data */ + //@{ + /// Clp model represented by this class instance + mutable ClpSimplex *modelPtr_; + //@} + /**@name Cached information derived from the OSL model */ + //@{ + /// Pointer to dense vector of row sense indicators + mutable char *rowsense_; + + /// Pointer to dense vector of row right-hand side values + mutable double *rhs_; + + /** Pointer to dense vector of slack upper bounds for range + constraints (undefined for non-range rows) + */ + mutable double *rowrange_; + + /** A pointer to the warmstart information to be used in the hotstarts. + This is NOT efficient and more thought should be given to it... */ + mutable CoinWarmStartBasis *ws_; + /** also save row and column information for hot starts + only used in hotstarts so can be casual */ + mutable double *rowActivity_; + mutable double *columnActivity_; + /// Stuff for fast dual + ClpNodeStuff stuff_; + /// Number of SOS sets + int numberSOS_; + /// SOS set info + CoinSet *setInfo_; + /// Alternate model (hot starts) - but also could be permanent and used for crunch + ClpSimplex *smallModel_; + /// factorization for hot starts + ClpFactorization *factorization_; + /** Smallest allowed element in cut. + If smaller than this then ignored */ + double smallestElementInCut_; + /** Smallest change in cut. + If (upper-lower)*element < this then element is + taken out and cut relaxed. */ + double smallestChangeInCut_; + /// Largest amount continuous away from bound + double largestAway_; + /// Arrays for hot starts + char *spareArrays_; + /** Warmstart information to be used in resolves. */ + CoinWarmStartBasis basis_; + /** The original iteration limit before hotstarts started. */ + int itlimOrig_; + + /*! \brief Last algorithm used + + Coded as + - 0 invalid + - 1 primal + - 2 dual + - -911 disaster in the algorithm that was attempted + - 999 current solution no longer optimal due to change in problem or + basis + */ + mutable int lastAlgorithm_; + + /// To say if destructor should delete underlying model + bool notOwned_; + + /// Pointer to row-wise copy of problem matrix coefficients. + mutable CoinPackedMatrix *matrixByRow_; + + /// Pointer to row-wise copy of continuous problem matrix coefficients. + CoinPackedMatrix *matrixByRowAtContinuous_; + + /// Pointer to integer information + char *integerInformation_; + + /** Pointer to variables for which we want range information + The number is in [0] + memory is not owned by OsiClp + */ + int *whichRange_; + + //std::map intParamMap_; + //std::map dblParamMap_; + //std::map strParamMap_; + + /*! \brief Faking min to get proper dual solution signs in simplex API */ + mutable bool fakeMinInSimplex_; + /*! \brief Linear objective + + Normally a pointer to the linear coefficient array in the clp objective. + An independent copy when #fakeMinInSimplex_ is true, because we need + something permanent to point to when #getObjCoefficients is called. + */ + mutable double *linearObjective_; + + /// To save data in OsiSimplex stuff + mutable ClpDataSave saveData_; + /// Options for initialSolve + ClpSolve solveOptions_; + /** Scaling option + When scaling is on it is possible that the scaled problem + is feasible but the unscaled is not. Clp returns a secondary + status code to that effect. This option allows for a cleanup. + If you use it I would suggest 1. + This only affects actions when scaled optimal + 0 - no action + 1 - clean up using dual if primal infeasibility + 2 - clean up using dual if dual infeasibility + 3 - clean up using dual if primal or dual infeasibility + 11,12,13 - as 1,2,3 but use primal + */ + int cleanupScaling_; + /** Special options + 0x80000000 off + 0 simple stuff for branch and bound + 1 try and keep work regions as much as possible + 2 do not use any perturbation + 4 allow exit before re-factorization + 8 try and re-use factorization if no cuts + 16 use standard strong branching rather than clp's + 32 Just go to first factorization in fast dual + 64 try and tighten bounds in crunch + 128 Model will only change in column bounds + 256 Clean up model before hot start + 512 Give user direct access to Clp regions in getBInvARow etc (i.e., + do not unscale, and do not return result in getBInv parameters; + you have to know where to look for the answer) + 1024 Don't "borrow" model in initialSolve + 2048 Don't crunch + 4096 quick check for optimality + Bits above 8192 give where called from in Cbc + At present 0 is normal, 1 doing fast hotstarts, 2 is can do quick check + 65536 Keep simple i.e. no crunch etc + 131072 Try and keep scaling factors around + 262144 Don't try and tighten bounds (funny global cuts) + 524288 Fake objective and 0-1 + 1048576 Don't recompute ray after crunch + 2097152 + 8388608 Odd integers e.g. semi-continuous + */ + mutable unsigned int specialOptions_; + /// Copy of model when option 131072 set + ClpSimplex *baseModel_; + /// Number of rows when last "scaled" + int lastNumberRows_; + /// Continuous model + ClpSimplex *continuousModel_; + /// Possible disaster handler + OsiClpDisasterHandler *disasterHandler_; + /// Fake objective + ClpLinearObjective *fakeObjective_; + /// Row scale factors (has inverse at end) + CoinDoubleArrayWithLength rowScale_; + /// Column scale factors (has inverse at end) + CoinDoubleArrayWithLength columnScale_; + //@} +}; + +class OsiClpDisasterHandler : public ClpDisasterHandler { +public: + /**@name Virtual methods that the derived classe should provide. + */ + //@{ + /// Into simplex + virtual void intoSimplex(); + /// Checks if disaster + virtual bool check() const; + /// saves information for next attempt + virtual void saveInfo(); + /// Type of disaster 0 can fix, 1 abort + virtual int typeOfDisaster(); + //@} + + /**@name Constructors, destructor */ + + //@{ + /** Default constructor. */ + OsiClpDisasterHandler(OsiClpSolverInterface *model = NULL); + /** Destructor */ + virtual ~OsiClpDisasterHandler(); + // Copy + OsiClpDisasterHandler(const OsiClpDisasterHandler &); + // Assignment + OsiClpDisasterHandler &operator=(const OsiClpDisasterHandler &); + /// Clone + virtual ClpDisasterHandler *clone() const; + + //@} + + /**@name Sets/gets */ + + //@{ + /** set model. */ + void setOsiModel(OsiClpSolverInterface *model); + /// Get model + inline OsiClpSolverInterface *osiModel() const + { + return osiModel_; + } + /// Set where from + inline void setWhereFrom(int value) + { + whereFrom_ = value; + } + /// Get where from + inline int whereFrom() const + { + return whereFrom_; + } + /// Set phase + inline void setPhase(int value) + { + phase_ = value; + } + /// Get phase + inline int phase() const + { + return phase_; + } + /// are we in trouble + bool inTrouble() const; + + //@} + +protected: + /**@name Data members + The data members are protected to allow access for derived classes. */ + //@{ + /// Pointer to model + OsiClpSolverInterface *osiModel_; + /** Where from + 0 dual (resolve) + 1 crunch + 2 primal (resolve) + 4 dual (initialSolve) + 6 primal (initialSolve) + */ + int whereFrom_; + /** phase + 0 initial + 1 trying continuing with back in and maybe different perturb + 2 trying continuing with back in and different scaling + 3 trying dual from all slack + 4 trying primal from previous stored basis + */ + int phase_; + /// Are we in trouble + bool inTrouble_; + //@} +}; +// So unit test can find out if NDEBUG set +bool OsiClpHasNDEBUG(); +//############################################################################# +/** A function that tests the methods in the OsiClpSolverInterface class. */ +void OsiClpSolverInterfaceUnitTest(const std::string &mpsDir, const std::string &netlibDir); +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiColCut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiColCut.hpp new file mode 100644 index 000000000..46c7c2b36 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiColCut.hpp @@ -0,0 +1,322 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiColCut_H +#define OsiColCut_H + +#include + +#include "CoinPackedVector.hpp" + +#include "OsiCollections.hpp" +#include "OsiCut.hpp" + +/** Column Cut Class + +Column Cut Class has: +
    +
  • a sparse vector of column lower bounds +
  • a sparse vector of column upper bounds +
+*/ +class OsiColCut : public OsiCut { + friend void OsiColCutUnitTest(const OsiSolverInterface *baseSiP, + const std::string &mpsDir); + +public: + //---------------------------------------------------------------- + + /**@name Setting column bounds */ + //@{ + /// Set column lower bounds + inline void setLbs( + int nElements, + const int *colIndices, + const double *lbElements); + + /// Set column lower bounds from a packed vector + inline void setLbs(const CoinPackedVector &lbs); + + /// Set column upper bounds + inline void setUbs( + int nElements, + const int *colIndices, + const double *ubElements); + + /// Set column upper bounds from a packed vector + inline void setUbs(const CoinPackedVector &ubs); + //@} + + //---------------------------------------------------------------- + + /**@name Getting column bounds */ + //@{ + /// Get column lower bounds + inline const CoinPackedVector &lbs() const; + /// Get column upper bounds + inline const CoinPackedVector &ubs() const; + //@} + + /**@name Comparison operators */ + //@{ +#if __GNUC__ != 2 + using OsiCut::operator==; +#endif + /** equal - true if lower bounds, upper bounds, + and OsiCut are equal. + */ + inline virtual bool operator==(const OsiColCut &rhs) const; + +#if __GNUC__ != 2 + using OsiCut::operator!=; +#endif + /// not equal + inline virtual bool operator!=(const OsiColCut &rhs) const; + //@} + + //---------------------------------------------------------------- + + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent with respect to itself. + This checks to ensure that: +
    +
  • The bound vectors do not have duplicate indices, +
  • The bound vectors indices are >=0 +
+ */ + inline virtual bool consistent() const; + + /** Returns true if cut is consistent with respect to the solver + interface's model. This checks to ensure that + the lower & upperbound packed vectors: +
    +
  • do not have an index >= the number of column is the model. +
+ */ + inline virtual bool consistent(const OsiSolverInterface &im) const; + + /** Returns true if the cut is infeasible with respect to its bounds and the + column bounds in the solver interface's models. + This checks whether: +
    +
  • the maximum of the new and existing lower bounds is strictly + greater than the minimum of the new and existing upper bounds. +
+ */ + inline virtual bool infeasible(const OsiSolverInterface &im) const; + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double *solution) const; + //@} + + //---------------------------------------------------------------- + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiColCut &operator=(const OsiColCut &rhs); + + /// Copy constructor + OsiColCut(const OsiColCut &); + + /// Default Constructor + OsiColCut(); + + /// Clone + virtual OsiColCut *clone() const; + + /// Destructor + virtual ~OsiColCut(); + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const; + //@} + +private: + /**@name Private member data */ + //@{ + /// Lower bounds + CoinPackedVector lbs_; + /// Upper bounds + CoinPackedVector ubs_; + //@} +}; + +//------------------------------------------------------------------- +// Set lower & upper bound vectors +//------------------------------------------------------------------- +void OsiColCut::setLbs( + int size, + const int *colIndices, + const double *lbElements) +{ + lbs_.setVector(size, colIndices, lbElements); +} +// +void OsiColCut::setUbs( + int size, + const int *colIndices, + const double *ubElements) +{ + ubs_.setVector(size, colIndices, ubElements); +} +// +void OsiColCut::setLbs(const CoinPackedVector &lbs) +{ + lbs_ = lbs; +} +// +void OsiColCut::setUbs(const CoinPackedVector &ubs) +{ + ubs_ = ubs; +} + +//------------------------------------------------------------------- +// Get Column Lower Bounds and Column Upper Bounds +//------------------------------------------------------------------- +const CoinPackedVector &OsiColCut::lbs() const +{ + return lbs_; +} +// +const CoinPackedVector &OsiColCut::ubs() const +{ + return ubs_; +} + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool OsiColCut::operator==( + const OsiColCut &rhs) const +{ + if (this->OsiCut::operator!=(rhs)) + return false; + if (lbs() != rhs.lbs()) + return false; + if (ubs() != rhs.ubs()) + return false; + return true; +} +// +bool OsiColCut::operator!=( + const OsiColCut &rhs) const +{ + return !((*this) == rhs); +} + +//---------------------------------------------------------------- +// consistent & infeasible +//------------------------------------------------------------------- +bool OsiColCut::consistent() const +{ + const CoinPackedVector &lb = lbs(); + const CoinPackedVector &ub = ubs(); + // Test for consistent cut. + // Are packed vectors consistent? + lb.duplicateIndex("consistent", "OsiColCut"); + ub.duplicateIndex("consistent", "OsiColCut"); + if (lb.getMinIndex() < 0) + return false; + if (ub.getMinIndex() < 0) + return false; + return true; +} +// +bool OsiColCut::consistent(const OsiSolverInterface &im) const +{ + const CoinPackedVector &lb = lbs(); + const CoinPackedVector &ub = ubs(); + + // Test for consistent cut. + if (lb.getMaxIndex() >= im.getNumCols()) + return false; + if (ub.getMaxIndex() >= im.getNumCols()) + return false; + + return true; +} + +#if 0 +bool OsiColCut::feasible(const OsiSolverInterface &im) const +{ + const double * oldColLb = im.getColLower(); + const double * oldColUb = im.getColUpper(); + const CoinPackedVector & cutLbs = lbs(); + const CoinPackedVector & cutUbs = ubs(); + int i; + + for ( i=0; i oldColLb[colIndx] ) + newLb = cutLbs.elements()[i]; + else + newLb = oldColLb[colIndx]; + + double newUb = oldColUb[colIndx]; + if ( cutUbs.indexExists(colIndx) ) + if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx]; + if ( newLb > newUb ) + return false; + } + + for ( i=0; i newLb ) newLb = cutLbs[colIndx]; + if ( newUb < newLb ) + return false; + } + + return true; +} +#endif + +bool OsiColCut::infeasible(const OsiSolverInterface &im) const +{ + const double *oldColLb = im.getColLower(); + const double *oldColUb = im.getColUpper(); + const CoinPackedVector &cutLbs = lbs(); + const CoinPackedVector &cutUbs = ubs(); + int i; + + for (i = 0; i < cutLbs.getNumElements(); i++) { + int colIndx = cutLbs.getIndices()[i]; + double newLb = cutLbs.getElements()[i] > oldColLb[colIndx] ? cutLbs.getElements()[i] : oldColLb[colIndx]; + + double newUb = oldColUb[colIndx]; + if (cutUbs.isExistingIndex(colIndx)) + if (cutUbs[colIndx] < newUb) + newUb = cutUbs[colIndx]; + if (newLb > newUb) + return true; + } + + for (i = 0; i < cutUbs.getNumElements(); i++) { + int colIndx = cutUbs.getIndices()[i]; + double newUb = cutUbs.getElements()[i] < oldColUb[colIndx] ? cutUbs.getElements()[i] : oldColUb[colIndx]; + double newLb = oldColLb[colIndx]; + if (cutLbs.isExistingIndex(colIndx)) + if (cutLbs[colIndx] > newLb) + newLb = cutLbs[colIndx]; + if (newUb < newLb) + return true; + } + + return false; +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCollections.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCollections.hpp new file mode 100644 index 000000000..60c908794 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCollections.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCollections_H +#define OsiCollections_H + +#include + +//Forward declarations +class OsiColCut; +class OsiRowCut; +class OsiCut; + +/* Collection Classes */ + +/**@name Typedefs for Standard Template Library collections of Osi Objects. */ +//@{ +/// Vector of int +typedef std::vector< int > OsiVectorInt; +/// Vector of double +typedef std::vector< double > OsiVectorDouble; +/// Vector of OsiColCut pointers +typedef std::vector< OsiColCut * > OsiVectorColCutPtr; +/// Vector of OsiRowCut pointers +typedef std::vector< OsiRowCut * > OsiVectorRowCutPtr; +/// Vector of OsiCut pointers +typedef std::vector< OsiCut * > OsiVectorCutPtr; +//@} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiConfig.h b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiConfig.h new file mode 100644 index 000000000..7877451dc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiConfig.h @@ -0,0 +1,19 @@ +/* src/Osi/config_osi.h. Generated by configure. */ +/* src/Osi/config_osi.h.in. */ + +#ifndef __CONFIG_OSI_H__ +#define __CONFIG_OSI_H__ + +/* Version number of project */ +#define OSI_VERSION "0.108" + +/* Major Version number of project */ +#define OSI_VERSION_MAJOR 0 + +/* Minor Version number of project */ +#define OSI_VERSION_MINOR 108 + +/* Release Version number of project */ +#define OSI_VERSION_RELEASE 9999 + +#endif diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCut.hpp new file mode 100644 index 000000000..535f11296 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCut.hpp @@ -0,0 +1,251 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCut_H +#define OsiCut_H + +#include "OsiCollections.hpp" +#include "OsiSolverInterface.hpp" + +/** Base Class for cut. + +The Base cut class contains: +
    +
  • a measure of the cut's effectivness +
+*/ + +/* + COIN_NOTEST_DUPLICATE is rooted in CoinUtils. Check there before you + meddle here. +*/ +#ifdef COIN_FAST_CODE +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_NOTEST_DUPLICATE +#endif +#endif + +#ifndef COIN_NOTEST_DUPLICATE +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE true +#else +#define COIN_DEFAULT_VALUE_FOR_DUPLICATE false +#endif + +class OsiCut { + +public: + //------------------------------------------------------------------- + /**@name Effectiveness */ + //@{ + /// Set effectiveness + inline void setEffectiveness(double e); + /// Get effectiveness + inline double effectiveness() const; + //@} + + /**@name GloballyValid */ + //@{ + /// Set globallyValid (nonzero true) + inline void setGloballyValid(bool trueFalse) + { + globallyValid_ = trueFalse ? 1 : 0; + } + inline void setGloballyValid() + { + globallyValid_ = 1; + } + inline void setNotGloballyValid() + { + globallyValid_ = 0; + } + /// Get globallyValid + inline bool globallyValid() const + { + return globallyValid_ != 0; + } + /// Set globallyValid as integer (nonzero true) + inline void setGloballyValidAsInteger(int trueFalse) + { + globallyValid_ = trueFalse; + } + /// Get globallyValid + inline int globallyValidAsInteger() const + { + return globallyValid_; + } + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const {} + //@} + +#if 0 + / **@name Times used */ + / /@{ + / // Set times used + inline void setTimesUsed( int t ); + / // Increment times used + inline void incrementTimesUsed(); + / // Get times used + inline int timesUsed() const; + / /@} + + / **@name Times tested */ + / /@{ + / // Set times tested + inline void setTimesTested( int t ); + / // Increment times tested + inline void incrementTimesTested(); + / // Get times tested + inline int timesTested() const; + / /@} +#endif + + //---------------------------------------------------------------- + + /**@name Comparison operators */ + //@{ + ///equal. 2 cuts are equal if there effectiveness are equal + inline virtual bool operator==(const OsiCut &rhs) const; + /// not equal + inline virtual bool operator!=(const OsiCut &rhs) const; + /// less than. True if this.effectiveness < rhs.effectiveness + inline virtual bool operator<(const OsiCut &rhs) const; + /// less than. True if this.effectiveness > rhs.effectiveness + inline virtual bool operator>(const OsiCut &rhs) const; + //@} + + //---------------------------------------------------------------- + // consistent() - returns true if the cut is consistent with repect to itself. + // This might include checks to ensure that a packed vector + // itself does not have a negative index. + // consistent(const OsiSolverInterface& si) - returns true if cut is consistent with + // respect to the solver interface's model. This might include a check to + // make sure a column index is not greater than the number + // of columns in the problem. + // infeasible(const OsiSolverInterface& si) - returns true if the cut is infeasible + // "with respect to itself". This might include a check to ensure + // the lower bound is greater than the upper bound, or if the + // cut simply replaces bounds that the new bounds are feasible with + // respect to the old bounds. + //----------------------------------------------------------------- + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent with respect to itself, + without considering any + data in the model. For example, it might check to ensure + that a column index is not negative. + */ + inline virtual bool consistent() const = 0; + + /** Returns true if cut is consistent when considering the solver + interface's model. For example, it might check to ensure + that a column index is not greater than the number of columns + in the model. Assumes consistent() is true. + */ + inline virtual bool consistent(const OsiSolverInterface &si) const = 0; + + /** Returns true if the cut is infeasible "with respect to itself" and + cannot be satisfied. This method does NOT check whether adding the + cut to the solver interface's model will make the -model- infeasble. + A cut which returns !infeasible(si) may very well make the model + infeasible. (Of course, adding a cut with returns infeasible(si) + will make the model infeasible.) + + The "with respect to itself" is in quotes becaues + in the case where the cut + simply replaces existing bounds, it may make + sense to test infeasibility with respect to the current bounds + held in the solver interface's model. For example, if the cut + has a single variable in it, it might check that the maximum + of new and existing lower bounds is greater than the minium of + the new and existing upper bounds. + + Assumes that consistent(si) is true.
+ Infeasible cuts can be a useful mechanism for a cut generator to + inform the solver interface that its detected infeasibility of the + problem. + */ + inline virtual bool infeasible(const OsiSolverInterface &si) const = 0; + + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double *solution) const = 0; + //@} + +protected: + /**@name Constructors and destructors */ + //@{ + /// Default Constructor + OsiCut(); + + /// Copy constructor + OsiCut(const OsiCut &); + + /// Assignment operator + OsiCut &operator=(const OsiCut &rhs); + + /// Destructor + virtual ~OsiCut(); + //@} + +private: + /**@name Private member data */ + //@{ + /// Effectiveness + double effectiveness_; + /// If cut has global validity i.e. can be used anywhere in tree + int globallyValid_; +#if 0 + /// Times used + int timesUsed_; + /// Times tested + int timesTested_; +#endif + //@} +}; + +//------------------------------------------------------------------- +// Set/Get member data +//------------------------------------------------------------------- +void OsiCut::setEffectiveness(double e) { effectiveness_ = e; } +double OsiCut::effectiveness() const { return effectiveness_; } + +#if 0 +void OsiCut::setTimesUsed( int t ) { timesUsed_=t; } +void OsiCut::incrementTimesUsed() { timesUsed_++; } +int OsiCut::timesUsed() const { return timesUsed_; } + +void OsiCut::setTimesTested( int t ) { timesTested_=t; } +void OsiCut::incrementTimesTested() { timesTested_++; } +int OsiCut::timesTested() const{ return timesTested_; } +#endif + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool OsiCut::operator==(const OsiCut &rhs) const +{ + return effectiveness() == rhs.effectiveness(); +} +bool OsiCut::operator!=(const OsiCut &rhs) const +{ + return !((*this) == rhs); +} +bool OsiCut::operator<(const OsiCut &rhs) const +{ + return effectiveness() < rhs.effectiveness(); +} +bool OsiCut::operator>(const OsiCut &rhs) const +{ + return effectiveness() > rhs.effectiveness(); +} +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCuts.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCuts.hpp new file mode 100644 index 000000000..19ee925ad --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiCuts.hpp @@ -0,0 +1,505 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiCuts_H +#define OsiCuts_H + +#include "CoinPragma.hpp" + +#include +#include +#include "OsiCollections.hpp" +#include "OsiRowCut.hpp" +#include "OsiColCut.hpp" +#include "CoinFloatEqual.hpp" + +/** Collections of row cuts and column cuts +*/ +class OsiCuts { + friend void OsiCutsUnitTest(); + +public: + /**@name Iterator classes + */ + //@{ + /** Iterator + + This is a class for iterating over the collection of cuts. + */ + class iterator { + friend class OsiCuts; + + public: + iterator(OsiCuts &cuts); + iterator(const iterator &src); + iterator &operator=(const iterator &rhs); + ~iterator(); + OsiCut *operator*() const { return cutP_; } + iterator operator++(); + + iterator operator++(int) + { + iterator temp = *this; + ++*this; + return temp; + } + + bool operator==(const iterator &it) const + { + return (colCutIndex_ + rowCutIndex_) == (it.colCutIndex_ + it.rowCutIndex_); + } + + bool operator!=(const iterator &it) const + { + return !((*this) == it); + } + + bool operator<(const iterator &it) const + { + return (colCutIndex_ + rowCutIndex_) < (it.colCutIndex_ + it.rowCutIndex_); + } + + private: + iterator(); + // *THINK* : how to inline these without sticking the code here (ugly...) + iterator begin(); + iterator end(); + OsiCuts &cuts_; + int rowCutIndex_; + int colCutIndex_; + OsiCut *cutP_; + }; + + /** Const Iterator + + This is a class for iterating over the collection of cuts. + */ + class const_iterator { + friend class OsiCuts; + + public: + typedef std::forward_iterator_tag iterator_category; + typedef OsiCut *value_type; + typedef size_t difference_type; + typedef OsiCut **pointer; + typedef OsiCut *&reference; + + public: + const_iterator(const OsiCuts &cuts); + const_iterator(const const_iterator &src); + const_iterator &operator=(const const_iterator &rhs); + ~const_iterator(); + const OsiCut *operator*() const { return cutP_; } + + const_iterator operator++(); + + const_iterator operator++(int) + { + const_iterator temp = *this; + ++*this; + return temp; + } + + bool operator==(const const_iterator &it) const + { + return (colCutIndex_ + rowCutIndex_) == (it.colCutIndex_ + it.rowCutIndex_); + } + + bool operator!=(const const_iterator &it) const + { + return !((*this) == it); + } + + bool operator<(const const_iterator &it) const + { + return (colCutIndex_ + rowCutIndex_) < (it.colCutIndex_ + it.rowCutIndex_); + } + + private: + inline const_iterator(); + // *THINK* : how to inline these without sticking the code here (ugly...) + const_iterator begin(); + const_iterator end(); + const OsiCuts *cutsPtr_; + int rowCutIndex_; + int colCutIndex_; + const OsiCut *cutP_; + }; + //@} + + //------------------------------------------------------------------- + // + // Cuts class definition begins here: + // + //------------------------------------------------------------------- + + /** \name Inserting a cut into collection */ + //@{ + /** \brief Insert a row cut */ + inline void insert(const OsiRowCut &rc); + /** \brief Insert a row cut unless it is a duplicate - cut may get sorted. + Duplicate is defined as CoinAbsFltEq says same*/ + void insertIfNotDuplicate(OsiRowCut &rc, CoinAbsFltEq treatAsSame = CoinAbsFltEq(1.0e-12)); + /** \brief Insert a row cut unless it is a duplicate - cut may get sorted. + Duplicate is defined as CoinRelFltEq says same*/ + void insertIfNotDuplicate(OsiRowCut &rc, CoinRelFltEq treatAsSame); + /** \brief Insert a column cut */ + inline void insert(const OsiColCut &cc); + + /** \brief Insert a row cut. + + The OsiCuts object takes control of the cut object. + On return, \c rcPtr is NULL. + */ + inline void insert(OsiRowCut *&rcPtr); + /** \brief Insert a column cut. + + The OsiCuts object takes control of the cut object. + On return \c ccPtr is NULL. + */ + inline void insert(OsiColCut *&ccPtr); +#if 0 + inline void insert( OsiCut * & cPtr ); +#endif + + /** \brief Insert a set of cuts */ + inline void insert(const OsiCuts &cs); + + //@} + + /**@name Number of cuts in collection */ + //@{ + /// Number of row cuts in collection + inline int sizeRowCuts() const; + /// Number of column cuts in collection + inline int sizeColCuts() const; + /// Number of cuts in collection + inline int sizeCuts() const; + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + inline void printCuts() const; + //@} + + /**@name Get a cut from collection */ + //@{ + /// Get pointer to i'th row cut + inline OsiRowCut *rowCutPtr(int i); + /// Get const pointer to i'th row cut + inline const OsiRowCut *rowCutPtr(int i) const; + /// Get pointer to i'th column cut + inline OsiColCut *colCutPtr(int i); + /// Get const pointer to i'th column cut + inline const OsiColCut *colCutPtr(int i) const; + + /// Get reference to i'th row cut + inline OsiRowCut &rowCut(int i); + /// Get const reference to i'th row cut + inline const OsiRowCut &rowCut(int i) const; + /// Get reference to i'th column cut + inline OsiColCut &colCut(int i); + /// Get const reference to i'th column cut + inline const OsiColCut &colCut(int i) const; + + /// Get const pointer to the most effective cut + inline const OsiCut *mostEffectiveCutPtr() const; + /// Get pointer to the most effective cut + inline OsiCut *mostEffectiveCutPtr(); + //@} + + /**@name Deleting cut from collection */ + //@{ + /// Remove i'th row cut from collection + inline void eraseRowCut(int i); + /// Remove i'th column cut from collection + inline void eraseColCut(int i); + /// Get pointer to i'th row cut and remove ptr from collection + inline OsiRowCut *rowCutPtrAndZap(int i); + /*! \brief Clear all row cuts without deleting them + + Handy in case one wants to use CGL without managing cuts in one of + the OSI containers. Client is ultimately responsible for deleting the + data structures holding the row cuts. + */ + inline void dumpCuts(); + /*! \brief Selective delete and clear for row cuts. + + Deletes the cuts specified in \p to_erase then clears remaining cuts + without deleting them. A hybrid of eraseRowCut(int) and dumpCuts(). + Client is ultimately responsible for deleting the data structures + for row cuts not specified in \p to_erase. + */ + inline void eraseAndDumpCuts(const std::vector< int > to_erase); + //@} + + /**@name Sorting collection */ + //@{ + /// Cuts with greatest effectiveness are first. + inline void sort(); + //@} + + /**@name Iterators + Example of using an iterator to sum effectiveness + of all cuts in the collection. +
+     double sumEff=0.0;
+     for ( OsiCuts::iterator it=cuts.begin(); it!=cuts.end(); ++it )
+           sumEff+= (*it)->effectiveness();
+     
+ */ + //@{ + /// Get iterator to beginning of collection + inline iterator begin() + { + iterator it(*this); + it.begin(); + return it; + } + /// Get const iterator to beginning of collection + inline const_iterator begin() const + { + const_iterator it(*this); + it.begin(); + return it; + } + /// Get iterator to end of collection + inline iterator end() + { + iterator it(*this); + it.end(); + return it; + } + /// Get const iterator to end of collection + inline const_iterator end() const + { + const_iterator it(*this); + it.end(); + return it; + } + //@} + + /**@name Constructors and destructors */ + //@{ + /// Default constructor + OsiCuts(); + + /// Copy constructor + OsiCuts(const OsiCuts &); + + /// Assignment operator + OsiCuts &operator=(const OsiCuts &rhs); + + /// Destructor + virtual ~OsiCuts(); + //@} + +private: + //*@name Function operator for sorting cuts by efectiveness */ + //@{ + class OsiCutCompare { + public: + /// Function for sorting cuts by effectiveness + inline bool operator()(const OsiCut *c1P, const OsiCut *c2P) + { + return c1P->effectiveness() > c2P->effectiveness(); + } + }; + //@} + + /**@name Private methods */ + //@{ + /// Copy internal data + void gutsOfCopy(const OsiCuts &source); + /// Delete internal data + void gutsOfDestructor(); + //@} + + /**@name Private member data */ + //@{ + /// Vector of row cuts pointers + OsiVectorRowCutPtr rowCutPtrs_; + /// Vector of column cuts pointers + OsiVectorColCutPtr colCutPtrs_; + //@} +}; + +//------------------------------------------------------------------- +// insert cuts into collection +//------------------------------------------------------------------- +void OsiCuts::insert(const OsiRowCut &rc) +{ + OsiRowCut *newCutPtr = rc.clone(); + //assert(dynamic_cast(newCutPtr) != NULL ); + rowCutPtrs_.push_back(static_cast< OsiRowCut * >(newCutPtr)); +} +void OsiCuts::insert(const OsiColCut &cc) +{ + OsiColCut *newCutPtr = cc.clone(); + //assert(dynamic_cast(newCutPtr) != NULL ); + colCutPtrs_.push_back(static_cast< OsiColCut * >(newCutPtr)); +} + +void OsiCuts::insert(OsiRowCut *&rcPtr) +{ + rowCutPtrs_.push_back(rcPtr); + rcPtr = NULL; +} +void OsiCuts::insert(OsiColCut *&ccPtr) +{ + colCutPtrs_.push_back(ccPtr); + ccPtr = NULL; +} +#if 0 +void OsiCuts::insert( OsiCut* & cPtr ) +{ + OsiRowCut * rcPtr = dynamic_cast(cPtr); + if ( rcPtr != NULL ) { + insert( rcPtr ); + cPtr = rcPtr; + } + else { + OsiColCut * ccPtr = dynamic_cast(cPtr); + assert( ccPtr != NULL ); + insert( ccPtr ); + cPtr = ccPtr; + } +} +#endif + +// LANNEZ SEBASTIEN added Thu May 25 01:22:51 EDT 2006 +void OsiCuts::insert(const OsiCuts &cs) +{ + for (OsiCuts::const_iterator it = cs.begin(); it != cs.end(); it++) { + const OsiRowCut *rCut = dynamic_cast< const OsiRowCut * >(*it); + const OsiColCut *cCut = dynamic_cast< const OsiColCut * >(*it); + assert(rCut || cCut); + if (rCut) + insert(*rCut); + else + insert(*cCut); + } +} + +//------------------------------------------------------------------- +// sort +//------------------------------------------------------------------- +void OsiCuts::sort() +{ + std::sort(colCutPtrs_.begin(), colCutPtrs_.end(), OsiCutCompare()); + std::sort(rowCutPtrs_.begin(), rowCutPtrs_.end(), OsiCutCompare()); +} + +//------------------------------------------------------------------- +// Get number of in collections +//------------------------------------------------------------------- +int OsiCuts::sizeRowCuts() const +{ + return static_cast< int >(rowCutPtrs_.size()); +} +int OsiCuts::sizeColCuts() const +{ + return static_cast< int >(colCutPtrs_.size()); +} +int OsiCuts::sizeCuts() const +{ + return static_cast< int >(sizeRowCuts() + sizeColCuts()); +} + +//---------------------------------------------------------------- +// Get i'th cut from the collection +//---------------------------------------------------------------- +const OsiRowCut *OsiCuts::rowCutPtr(int i) const { return rowCutPtrs_[i]; } +const OsiColCut *OsiCuts::colCutPtr(int i) const { return colCutPtrs_[i]; } +OsiRowCut *OsiCuts::rowCutPtr(int i) { return rowCutPtrs_[i]; } +OsiColCut *OsiCuts::colCutPtr(int i) { return colCutPtrs_[i]; } + +const OsiRowCut &OsiCuts::rowCut(int i) const { return *rowCutPtr(i); } +const OsiColCut &OsiCuts::colCut(int i) const { return *colCutPtr(i); } +OsiRowCut &OsiCuts::rowCut(int i) { return *rowCutPtr(i); } +OsiColCut &OsiCuts::colCut(int i) { return *colCutPtr(i); } + +//---------------------------------------------------------------- +// Get most effective cut from collection +//---------------------------------------------------------------- +const OsiCut *OsiCuts::mostEffectiveCutPtr() const +{ + const_iterator b = begin(); + const_iterator e = end(); + return *(std::min_element(b, e, OsiCutCompare())); +} +OsiCut *OsiCuts::mostEffectiveCutPtr() +{ + iterator b = begin(); + iterator e = end(); + //return *(std::min_element(b,e,OsiCutCompare())); + OsiCut *retVal = NULL; + double maxEff = COIN_DBL_MIN; + for (OsiCuts::iterator it = b; it != e; ++it) { + if (maxEff < (*it)->effectiveness()) { + maxEff = (*it)->effectiveness(); + retVal = *it; + } + } + return retVal; +} + +//---------------------------------------------------------------- +// Print all cuts +//---------------------------------------------------------------- +void OsiCuts::printCuts() const +{ + // do all column cuts first + int i; + int numberColCuts = sizeColCuts(); + for (i = 0; i < numberColCuts; i++) { + const OsiColCut *cut = colCutPtr(i); + cut->print(); + } + int numberRowCuts = sizeRowCuts(); + for (i = 0; i < numberRowCuts; i++) { + const OsiRowCut *cut = rowCutPtr(i); + cut->print(); + } +} + +//---------------------------------------------------------------- +// Erase i'th cut from the collection +//---------------------------------------------------------------- +void OsiCuts::eraseRowCut(int i) +{ + delete rowCutPtrs_[i]; + rowCutPtrs_.erase(rowCutPtrs_.begin() + i); +} +void OsiCuts::eraseColCut(int i) +{ + delete colCutPtrs_[i]; + colCutPtrs_.erase(colCutPtrs_.begin() + i); +} +/// Get pointer to i'th row cut and remove ptr from collection +OsiRowCut * +OsiCuts::rowCutPtrAndZap(int i) +{ + OsiRowCut *cut = rowCutPtrs_[i]; + rowCutPtrs_[i] = NULL; + rowCutPtrs_.erase(rowCutPtrs_.begin() + i); + return cut; +} +void OsiCuts::dumpCuts() +{ + rowCutPtrs_.clear(); +} +void OsiCuts::eraseAndDumpCuts(const std::vector< int > to_erase) +{ + for (unsigned i = 0; i < to_erase.size(); i++) { + delete rowCutPtrs_[to_erase[i]]; + } + rowCutPtrs_.clear(); +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiPresolve.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiPresolve.hpp new file mode 100644 index 000000000..aee71016f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiPresolve.hpp @@ -0,0 +1,272 @@ +// Copyright (C) 2003, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiPresolve_H +#define OsiPresolve_H +#include "OsiSolverInterface.hpp" + +class CoinPresolveAction; +#include "CoinPresolveMatrix.hpp" + +/*! \class OsiPresolve + \brief OSI interface to COIN problem simplification capabilities + + COIN provides a number of classes which implement problem simplification + algorithms (CoinPresolveAction, CoinPrePostsolveMatrix, and derived + classes). The model of operation is as follows: +
    +
  • + Create a copy of the original problem. +
  • +
  • + Subject the copy to a series of transformations (the presolve + methods) to produce a presolved model. Each transformation is also + expected to provide a method to reverse the transformation (the + postsolve method). The postsolve methods are collected in a + linked list; the postsolve method for the final presolve transformation + is at the head of the list. +
  • +
  • + Hand the presolved problem to the solver for optimization. +
  • +
  • + Apply the collected postsolve methods to the presolved problem + and solution, restating the solution in terms of the original problem. +
  • +
+ + The COIN presolve algorithms are unaware of OSI. The OsiPresolve class takes + care of the interface. Given an OsiSolverInterface \c origModel, it will take + care of creating a clone properly loaded with the presolved problem and ready + for optimization. After optimization, it will apply postsolve + transformations and load the result back into \c origModel. + + Assuming a problem has been loaded into an + \c OsiSolverInterface \c origModel, a bare-bones application looks like this: + \code + OsiPresolve pinfo ; + OsiSolverInterface *presolvedModel ; + // Return an OsiSolverInterface loaded with the presolved problem. + presolvedModel = pinfo.presolvedModel(*origModel,1.0e-8,false,numberPasses) ; + presolvedModel->initialSolve() ; + // Restate the solution and load it back into origModel. + pinfo.postsolve(true) ; + delete presolvedModel ; + \endcode +*/ + +class OsiPresolve { +public: + /// Default constructor (empty object) + OsiPresolve(); + + /// Virtual destructor + virtual ~OsiPresolve(); + + /*! \brief Create a new OsiSolverInterface loaded with the presolved problem. + + This method implements the first two steps described in the class + documentation. It clones \c origModel and applies presolve + transformations, storing the resulting list of postsolve + transformations. It returns a pointer to a new OsiSolverInterface loaded + with the presolved problem, or NULL if the problem is infeasible or + unbounded. If \c keepIntegers is true then bounds may be tightened in + the original. Bounds will be moved by up to \c feasibilityTolerance to + try and stay feasible. When \c doStatus is true, the current solution will + be transformed to match the presolved model. + + This should be paired with postsolve(). It is up to the client to + destroy the returned OsiSolverInterface, after calling postsolve(). + + This method is virtual. Override this method if you need to customize + the steps of creating a model to apply presolve transformations. + + In some sense, a wrapper for presolve(CoinPresolveMatrix*). + */ + virtual OsiSolverInterface *presolvedModel(OsiSolverInterface &origModel, + double feasibilityTolerance = 0.0, + bool keepIntegers = true, + int numberPasses = 5, + const char *prohibited = NULL, + bool doStatus = true, + const char *rowProhibited = NULL); + + /*! \brief Restate the solution to the presolved problem in terms of the + original problem and load it into the original model. + + postsolve() restates the solution in terms of the original problem and + updates the original OsiSolverInterface supplied to presolvedModel(). If + the problem has not been solved to optimality, there are no guarantees. + If you are using an algorithm like simplex that has a concept of a basic + solution, then set updateStatus + + The advantage of going back to the original problem is that it + will be exactly as it was, i.e., 0.0 will not become 1.0e-19. + + Note that if you modified the original problem after presolving, then you + must ``undo'' these modifications before calling postsolve(). + + In some sense, a wrapper for postsolve(CoinPostsolveMatrix&). + */ + virtual void postsolve(bool updateStatus = true); + + /*! \brief Return a pointer to the presolved model. */ + OsiSolverInterface *model() const; + + /// Return a pointer to the original model + OsiSolverInterface *originalModel() const; + + /// Set the pointer to the original model + void setOriginalModel(OsiSolverInterface *model); + + /// Return a pointer to the original columns + const int *originalColumns() const; + + /// Return a pointer to the original rows + const int *originalRows() const; + + /// Return number of rows in original model + inline int getNumRows() const + { + return nrows_; + } + + /// Return number of columns in original model + inline int getNumCols() const + { + return ncols_; + } + + /** "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + */ + inline void setNonLinearValue(double value) + { + nonLinearValue_ = value; + } + inline double nonLinearValue() const + { + return nonLinearValue_; + } + /*! \brief Fine control over presolve actions + + Set/clear the following bits to allow or suppress actions: + - 0x01 allow duplicate column processing on integer columns + and dual stuff on integers + - 0x02 switch off actions which can change +1 to something else + (doubleton, tripleton, implied free) + - 0x04 allow transfer of costs from singletons and between integer + variables (when advantageous) + - 0x08 do not allow x+y+z=1 transform + - 0x10 allow actions that don't easily unroll + - 0x20 allow dubious gub element reduction + + GUB element reduction is only partially implemented in CoinPresolve (see + gubrow_action) and willl cause an abort at postsolve. It's not clear + what's meant by `dual stuff on integers'. + -- lh, 110605 -- + */ + inline void setPresolveActions(int action) + { + presolveActions_ = (presolveActions_ & 0xffff0000) | (action & 0xffff); + } + /// Get presolved model + inline OsiSolverInterface *presolvedModel() const + { + return presolvedModel_; + } + /// Set presolved model + inline void setPresolvedModel(OsiSolverInterface *presolvedModel) + { + presolvedModel_ = presolvedModel; + } + +private: + /*! Original model (solver interface loaded with the original problem). + + Must not be destroyed until after postsolve(). + */ + OsiSolverInterface *originalModel_; + + /*! Presolved model (solver interface loaded with the presolved problem) + + Must be destroyed by the client (using delete) after postsolve(). + */ + OsiSolverInterface *presolvedModel_; + + /*! "Magic" number. If this is non-zero then any elements with this value + may change and so presolve is very limited in what can be done + to the row and column. This is for non-linear problems. + One could also allow for cases where sign of coefficient is known. + */ + double nonLinearValue_; + + /// Original column numbers + int *originalColumn_; + + /// Original row numbers + int *originalRow_; + + /// The list of transformations applied. + const CoinPresolveAction *paction_; + + /*! \brief Number of columns in original model. + + The problem will expand back to its former size as postsolve + transformations are applied. It is efficient to allocate data structures + for the final size of the problem rather than expand them as needed. + */ + int ncols_; + + /*! \brief Number of rows in original model. */ + int nrows_; + + /*! \brief Number of nonzero matrix coefficients in the original model. */ + CoinBigIndex nelems_; + + /** Whether we want to skip dual part of presolve etc. + 1 bit allows duplicate column processing on integer columns + and dual stuff on integers + 4 transfers costs to integer variables + */ + int presolveActions_; + /// Number of major passes + int numberPasses_; + +protected: + /*! \brief Apply presolve transformations to the problem. + + Handles the core activity of applying presolve transformations. + + If you want to apply the individual presolve routines differently, or + perhaps add your own to the mix, define a derived class and override + this method + */ + virtual const CoinPresolveAction *presolve(CoinPresolveMatrix *prob); + + /*! \brief Reverse presolve transformations to recover the solution + to the original problem. + + Handles the core activity of applying postsolve transformations. + + Postsolving is pretty generic; just apply the transformations in reverse + order. You will probably only be interested in overriding this method if + you want to add code to test for consistency while debugging new presolve + techniques. + */ + virtual void postsolve(CoinPostsolveMatrix &prob); + + /*! \brief Destroys queued postsolve actions. + + E.g., when presolve() determines the problem is infeasible, so that + it will not be necessary to actually solve the presolved problem and + convert the result back to the original problem. + */ + void gutsOfDestroy(); +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCut.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCut.hpp new file mode 100644 index 000000000..1f2c6c3ca --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCut.hpp @@ -0,0 +1,345 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiRowCut_H +#define OsiRowCut_H + +#include "CoinPackedVector.hpp" + +#include "OsiCollections.hpp" +#include "OsiCut.hpp" + +//#define OSI_INLINE_ROWCUT_METHODS +#ifdef OSI_INLINE_ROWCUT_METHODS +#define OsiRowCut_inline inline +#else +#define OsiRowCut_inline +#endif + +/** Row Cut Class + +A row cut has: +
    +
  • a lower bound
    +
  • an upper bound
    +
  • a vector of row elements +
+*/ +class OsiRowCut : public OsiCut { + friend void OsiRowCutUnitTest(const OsiSolverInterface *baseSiP, + const std::string &mpsDir); + +public: + /**@name Row bounds */ + //@{ + /// Get lower bound + OsiRowCut_inline double lb() const; + /// Set lower bound + OsiRowCut_inline void setLb(double lb); + /// Get upper bound + OsiRowCut_inline double ub() const; + /// Set upper bound + OsiRowCut_inline void setUb(double ub); + //@} + + /**@name Row rhs, sense, range */ + //@{ + /// Get sense ('E', 'G', 'L', 'N', 'R') + char sense() const; + /// Get right-hand side + double rhs() const; + /// Get range (ub - lb for 'R' rows, 0 otherwise) + double range() const; + //@} + + //------------------------------------------------------------------- + /**@name Row elements */ + //@{ + /// Set row elements + OsiRowCut_inline void setRow( + int size, + const int *colIndices, + const double *elements, + bool testForDuplicateIndex = COIN_DEFAULT_VALUE_FOR_DUPLICATE); + /// Set row elements from a packed vector + OsiRowCut_inline void setRow(const CoinPackedVector &v); + /// Get row elements + OsiRowCut_inline const CoinPackedVector &row() const; + /// Get row elements for changing + OsiRowCut_inline CoinPackedVector &mutableRow(); + //@} + + /**@name Comparison operators */ + //@{ +#if __GNUC__ != 2 + using OsiCut::operator==; +#endif + /** equal - true if lower bound, upper bound, row elements, + and OsiCut are equal. + */ + OsiRowCut_inline bool operator==(const OsiRowCut &rhs) const; + +#if __GNUC__ != 2 + using OsiCut::operator!=; +#endif + /// not equal + OsiRowCut_inline bool operator!=(const OsiRowCut &rhs) const; + //@} + + //---------------------------------------------------------------- + /**@name Sanity checks on cut */ + //@{ + /** Returns true if the cut is consistent. + This checks to ensure that: +
    +
  • The row element vector does not have duplicate indices +
  • The row element vector indices are >= 0 +
+ */ + OsiRowCut_inline bool consistent() const; + + /** Returns true if cut is consistent with respect to the solver + interface's model. + This checks to ensure that +
    +
  • The row element vector indices are < the number of columns + in the model +
+ */ + OsiRowCut_inline bool consistent(const OsiSolverInterface &im) const; + + /** Returns true if the row cut itself is infeasible and cannot be satisfied. + This checks whether +
    +
  • the lower bound is strictly greater than the + upper bound. +
+ */ + OsiRowCut_inline bool infeasible(const OsiSolverInterface &im) const; + /** Returns infeasibility of the cut with respect to solution + passed in i.e. is positive if cuts off that solution. + solution is getNumCols() long.. + */ + virtual double violated(const double *solution) const; + //@} + + /**@name Arithmetic operators. Apply CoinPackedVector methods to the vector */ + //@{ + /// add value to every vector entry + void operator+=(double value) + { + row_ += value; + } + + /// subtract value from every vector entry + void operator-=(double value) + { + row_ -= value; + } + + /// multiply every vector entry by value + void operator*=(double value) + { + row_ *= value; + } + + /// divide every vector entry by value + void operator/=(double value) + { + row_ /= value; + } + //@} + + /// Allow access row sorting function + void sortIncrIndex() + { + row_.sortIncrIndex(); + } + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiRowCut &operator=(const OsiRowCut &rhs); + + /// Copy constructor + OsiRowCut(const OsiRowCut &); + + /// Clone + virtual OsiRowCut *clone() const; + + /// Default Constructor + OsiRowCut(); + + /** \brief Ownership Constructor + + This constructor assumes ownership of the vectors passed as parameters + for indices and elements. \p colIndices and \p elements will be NULL + on return. + */ + OsiRowCut(double cutlb, double cutub, + int capacity, int size, + int *&colIndices, double *&elements); + + /// Destructor + virtual ~OsiRowCut(); + //@} + + /**@name Debug stuff */ + //@{ + /// Print cuts in collection + virtual void print() const; + //@} + +private: + /**@name Private member data */ + //@{ + /// Row elements + CoinPackedVector row_; + /// Row lower bound + double lb_; + /// Row upper bound + double ub_; + //@} +}; + +#ifdef OSI_INLINE_ROWCUT_METHODS + +//------------------------------------------------------------------- +// Set/Get lower & upper bounds +//------------------------------------------------------------------- +double OsiRowCut::lb() const { return lb_; } +void OsiRowCut::setLb(double lb) { lb_ = lb; } +double OsiRowCut::ub() const { return ub_; } +void OsiRowCut::setUb(double ub) { ub_ = ub; } + +//------------------------------------------------------------------- +// Set row elements +//------------------------------------------------------------------- +void OsiRowCut::setRow(int size, + const int *colIndices, const double *elements) +{ + row_.setVector(size, colIndices, elements); +} +void OsiRowCut::setRow(const CoinPackedVector &v) +{ + row_ = v; +} + +//------------------------------------------------------------------- +// Get the row +//------------------------------------------------------------------- +const CoinPackedVector &OsiRowCut::row() const +{ + return row_; +} + +//------------------------------------------------------------------- +// Get the row so we can change +//------------------------------------------------------------------- +CoinPackedVector &OsiRowCut::mutableRow() +{ + return row_; +} + +//---------------------------------------------------------------- +// == operator +//------------------------------------------------------------------- +bool OsiRowCut::operator==(const OsiRowCut &rhs) const +{ + if (this->OsiCut::operator!=(rhs)) + return false; + if (row() != rhs.row()) + return false; + if (lb() != rhs.lb()) + return false; + if (ub() != rhs.ub()) + return false; + return true; +} +bool OsiRowCut::operator!=(const OsiRowCut &rhs) const +{ + return !((*this) == rhs); +} + +//---------------------------------------------------------------- +// consistent & infeasible +//------------------------------------------------------------------- +bool OsiRowCut::consistent() const +{ + const CoinPackedVector &r = row(); + r.duplicateIndex("consistent", "OsiRowCut"); + if (r.getMinIndex() < 0) + return false; + return true; +} +bool OsiRowCut::consistent(const OsiSolverInterface &im) const +{ + const CoinPackedVector &r = row(); + if (r.getMaxIndex() >= im.getNumCols()) + return false; + + return true; +} +bool OsiRowCut::infeasible(const OsiSolverInterface &im) const +{ + if (lb() > ub()) + return true; + + return false; +} + +#endif + +/** Row Cut Class which refers back to row which created it. + It may be useful to strengthen a row rather than add a cut. To do this + we need to know which row is strengthened. This trivial extension + to OsiRowCut does that. + +*/ +class OsiRowCut2 : public OsiRowCut { + +public: + /**@name Which row */ + //@{ + /// Get row + inline int whichRow() const + { + return whichRow_; + } + /// Set row + inline void setWhichRow(int row) + { + whichRow_ = row; + } + //@} + + /**@name Constructors and destructors */ + //@{ + /// Assignment operator + OsiRowCut2 &operator=(const OsiRowCut2 &rhs); + + /// Copy constructor + OsiRowCut2(const OsiRowCut2 &); + + /// Clone + virtual OsiRowCut *clone() const; + + /// Default Constructor + OsiRowCut2(int row = -1); + + /// Destructor + virtual ~OsiRowCut2(); + //@} + +private: + /**@name Private member data */ + //@{ + /// Which row + int whichRow_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCutDebugger.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCutDebugger.hpp new file mode 100644 index 000000000..bb2aa25b4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiRowCutDebugger.hpp @@ -0,0 +1,190 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiRowCutDebugger_H +#define OsiRowCutDebugger_H + +/*! \file OsiRowCutDebugger.hpp + + \brief Provides a facility to validate cut constraints to ensure that they + do not cut off a given solution. +*/ + +#include + +#include "OsiCuts.hpp" +#include "OsiSolverInterface.hpp" + +/*! \brief Validate cuts against a known solution + + OsiRowCutDebugger provides a facility for validating cuts against a known + solution for a problem. The debugger knows an optimal solution for many of + the miplib3 problems. Check the source for + #activate(const OsiSolverInterface&,const char*) + in OsiRowCutDebugger.cpp for the full set of known problems. + + A full solution vector can be supplied as a parameter with + (#activate(const OsiSolverInterface&,const double*,bool)). + Only the integer values need to be valid. + The default behaviour is to solve an lp relaxation with the integer + variables fixed to the specified values and use the optimal solution to fill + in the continuous variables in the solution. + The debugger can be instructed to preserve the continuous variables (useful + when debugging solvers where the linear relaxation doesn't capture all the + constraints). + + Note that the solution must match the problem held in the solver interface. + If you want to use the row cut debugger on a problem after applying presolve + transformations, your solution must match the presolved problem. (But see + #redoSolution().) +*/ +class OsiRowCutDebugger { + friend void OsiRowCutDebuggerUnitTest(const OsiSolverInterface *siP, + const std::string &mpsDir); + +public: + /*! @name Validate Row Cuts + + Check that the specified cuts do not cut off the known solution. + */ + //@{ + /*! \brief Check that the set of cuts does not cut off the solution known + to the debugger. + + Check if any generated cuts cut off the solution known to the debugger! + If so then print offending cuts. Return the number of invalid cuts. + */ + virtual int validateCuts(const OsiCuts &cs, int first, int last) const; + + /*! \brief Check that the cut does not cut off the solution known to the + debugger. + + Return true if cut is invalid + */ + virtual bool invalidCut(const OsiRowCut &rowcut) const; + + /*! \brief Returns true if the solution held in the solver is compatible + with the known solution. + + More specifically, returns true if the known solution satisfies the column + bounds held in the solver. + */ + bool onOptimalPath(const OsiSolverInterface &si) const; + //@} + + /*! @name Activate the Debugger + + The debugger is considered to be active when it holds a known solution. + */ + //@{ + /*! \brief Activate a debugger using the name of a problem. + + The debugger knows an optimal solution for most of miplib3. Check the + source code for the full list. Returns true if the debugger is + successfully activated. + */ + bool activate(const OsiSolverInterface &si, const char *model); + + /*! \brief Activate a debugger using a full solution array. + + The solution must have one entry for every variable, but only the entries + for integer values are used. By default the debugger will solve an lp + relaxation with the integer variables fixed and fill in values for the + continuous variables from this solution. If the debugger should preserve + the given values for the continuous variables, set \p keepContinuous to + \c true. + + Returns true if debugger activates successfully. + */ + bool activate(const OsiSolverInterface &si, const double *solution, + bool keepContinuous = false); + + /// Returns true if the debugger is active + bool active() const; + //@} + + /*! @name Query or Manipulate the Known Solution */ + //@{ + /// Return the known solution + inline const double *optimalSolution() const + { + return knownSolution_; + } + + /// Return the number of columns in the known solution + inline int numberColumns() const { return (numberColumns_); } + + /// Return the value of the objective for the known solution + inline double optimalValue() const { return knownValue_; } + + /*! \brief Edit the known solution to reflect column changes + + Given a translation array \p originalColumns[numberColumns] which can + translate current column indices to original column indices, this method + will edit the solution held in the debugger so that it matches the current + set of columns. + + Useful when the original problem is preprocessed prior to cut generation. + The debugger does keep a record of the changes. + */ + void redoSolution(int numberColumns, const int *originalColumns); + + /// Print optimal solution (returns -1 bad debug, 0 on optimal, 1 not) + int printOptimalSolution(const OsiSolverInterface &si) const; + //@} + + /**@name Constructors and Destructors */ + //@{ + /// Default constructor - no checking + OsiRowCutDebugger(); + + /*! \brief Constructor with name of model. + + See #activate(const OsiSolverInterface&,const char*). + */ + OsiRowCutDebugger(const OsiSolverInterface &si, const char *model); + + /*! \brief Constructor with full solution. + + See #activate(const OsiSolverInterface&,const double*,bool). + */ + OsiRowCutDebugger(const OsiSolverInterface &si, const double *solution, + bool enforceOptimality = false); + + /// Copy constructor + OsiRowCutDebugger(const OsiRowCutDebugger &); + + /// Assignment operator + OsiRowCutDebugger &operator=(const OsiRowCutDebugger &rhs); + + /// Destructor + virtual ~OsiRowCutDebugger(); + //@} + +private: + // Private member data + + /**@name Private member data */ + //@{ + /// Value of known solution + double knownValue_; + + /*! \brief Number of columns in known solution + + This must match the number of columns reported by the solver. + */ + int numberColumns_; + + /// array specifying integer variables + bool *integerVariable_; + + /// array specifying known solution + double *knownSolution_; + //@} +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverBranch.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverBranch.hpp new file mode 100644 index 000000000..aae9ace7a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverBranch.hpp @@ -0,0 +1,169 @@ +// Copyright (C) 2005, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverBranch_H +#define OsiSolverBranch_H + +class OsiSolverInterface; +#include "CoinWarmStartBasis.hpp" + +//############################################################################# + +/** Solver Branch Class + + This provides information on a branch as a set of tighter bounds on both ways +*/ + +class OsiSolverBranch { + +public: + ///@name Add and Get methods + //@{ + /// Add a simple branch (i.e. first sets ub of floor(value), second lb of ceil(value)) + void addBranch(int iColumn, double value); + + /// Add bounds - way =-1 is first , +1 is second + void addBranch(int way, int numberTighterLower, const int *whichLower, const double *newLower, + int numberTighterUpper, const int *whichUpper, const double *newUpper); + /// Add bounds - way =-1 is first , +1 is second + void addBranch(int way, int numberColumns, const double *oldLower, const double *newLower, + const double *oldUpper, const double *newUpper); + + /// Apply bounds + void applyBounds(OsiSolverInterface &solver, int way) const; + /// Returns true if current solution satsifies one side of branch + bool feasibleOneWay(const OsiSolverInterface &solver) const; + /// Starts + inline const int *starts() const + { + return start_; + } + /// Which variables + inline const int *which() const + { + return indices_; + } + /// Bounds + inline const double *bounds() const + { + return bound_; + } + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverBranch(); + + /// Copy constructor + OsiSolverBranch(const OsiSolverBranch &rhs); + + /// Assignment operator + OsiSolverBranch &operator=(const OsiSolverBranch &rhs); + + /// Destructor + ~OsiSolverBranch(); + + //@} + +private: + ///@name Private member data + //@{ + /// Start of lower first, upper first, lower second, upper second + int start_[5]; + /// Column numbers (if >= numberColumns treat as rows) + int *indices_; + /// New bounds + double *bound_; + //@} +}; +//############################################################################# + +/** Solver Result Class + + This provides information on a result as a set of tighter bounds on both ways +*/ + +class OsiSolverResult { + +public: + ///@name Add and Get methods + //@{ + /// Create result + void createResult(const OsiSolverInterface &solver, const double *lowerBefore, + const double *upperBefore); + + /// Restore result + void restoreResult(OsiSolverInterface &solver) const; + + /// Get basis + inline const CoinWarmStartBasis &basis() const + { + return basis_; + } + + /// Objective value (as minimization) + inline double objectiveValue() const + { + return objectiveValue_; + } + + /// Primal solution + inline const double *primalSolution() const + { + return primalSolution_; + } + + /// Dual solution + inline const double *dualSolution() const + { + return dualSolution_; + } + + /// Extra fixed + inline const OsiSolverBranch &fixed() const + { + return fixed_; + } + //@} + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverResult(); + + /// Constructor from solver + OsiSolverResult(const OsiSolverInterface &solver, const double *lowerBefore, + const double *upperBefore); + + /// Copy constructor + OsiSolverResult(const OsiSolverResult &rhs); + + /// Assignment operator + OsiSolverResult &operator=(const OsiSolverResult &rhs); + + /// Destructor + ~OsiSolverResult(); + + //@} + +private: + ///@name Private member data + //@{ + /// Value of objective (if >= OsiSolverInterface::getInfinity() then infeasible) + double objectiveValue_; + /// Warm start information + CoinWarmStartBasis basis_; + /// Primal solution (numberColumns) + double *primalSolution_; + /// Dual solution (numberRows) + double *dualSolution_; + /// Which extra variables have been fixed (only way==-1 counts) + OsiSolverBranch fixed_; + //@} +}; +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverInterface.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverInterface.hpp new file mode 100644 index 000000000..8ebdb854f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverInterface.hpp @@ -0,0 +1,2221 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverInterface_H +#define OsiSolverInterface_H + +#include +#include +#include + +#include "CoinTypes.hpp" +#include "CoinMessageHandler.hpp" +#include "CoinPackedVectorBase.hpp" +#include "CoinPackedMatrix.hpp" +#include "CoinWarmStart.hpp" +#include "CoinFinite.hpp" +#include "CoinError.hpp" + +#include "OsiCollections.hpp" +#include "OsiSolverParameters.hpp" + +class CoinSnapshot; +class CoinLpIO; +class CoinMpsIO; + +class OsiCuts; +class OsiAuxInfo; +class OsiRowCut; +class OsiRowCutDebugger; +class CoinSet; +class CoinBuild; +class CoinModel; +class OsiSolverBranch; +class OsiSolverResult; +class OsiObject; + +//############################################################################# + +/*! \brief Abstract Base Class for describing an interface to a solver. + + Many OsiSolverInterface query methods return a const pointer to the + requested read-only data. If the model data is changed or the solver + is called, these pointers may no longer be valid and should be + refreshed by invoking the member function to obtain an updated copy + of the pointer. + For example: + \code + OsiSolverInterface solverInterfacePtr ; + const double * ruBnds = solverInterfacePtr->getRowUpper(); + solverInterfacePtr->applyCuts(someSetOfCuts); + // ruBnds is no longer a valid pointer and must be refreshed + ruBnds = solverInterfacePtr->getRowUpper(); + \endcode + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from + the methods that return vectors. +*/ + +class OsiSolverInterface { + friend void OsiSolverInterfaceCommonUnitTest( + const OsiSolverInterface *emptySi, + const std::string &mpsDir, + const std::string &netlibDir); + friend void OsiSolverInterfaceMpsUnitTest( + const std::vector< OsiSolverInterface * > &vecSiP, + const std::string &mpsDir); + +public: + /// Internal class for obtaining status from the applyCuts method + class ApplyCutsReturnCode { + friend class OsiSolverInterface; + friend class OsiClpSolverInterface; + friend class OsiGrbSolverInterface; + + public: + ///@name Constructors and desctructors + //@{ + /// Default constructor + ApplyCutsReturnCode() + : intInconsistent_(0) + , extInconsistent_(0) + , infeasible_(0) + , ineffective_(0) + , applied_(0) + { + } + /// Copy constructor + ApplyCutsReturnCode(const ApplyCutsReturnCode &rhs) + : intInconsistent_(rhs.intInconsistent_) + , extInconsistent_(rhs.extInconsistent_) + , infeasible_(rhs.infeasible_) + , ineffective_(rhs.ineffective_) + , applied_(rhs.applied_) + { + } + /// Assignment operator + ApplyCutsReturnCode &operator=(const ApplyCutsReturnCode &rhs) + { + if (this != &rhs) { + intInconsistent_ = rhs.intInconsistent_; + extInconsistent_ = rhs.extInconsistent_; + infeasible_ = rhs.infeasible_; + ineffective_ = rhs.ineffective_; + applied_ = rhs.applied_; + } + return *this; + } + /// Destructor + ~ApplyCutsReturnCode() {} + //@} + + /**@name Accessing return code attributes */ + //@{ + /// Number of logically inconsistent cuts + inline int getNumInconsistent() const + { + return intInconsistent_; + } + /// Number of cuts inconsistent with the current model + inline int getNumInconsistentWrtIntegerModel() const + { + return extInconsistent_; + } + /// Number of cuts that cause obvious infeasibility + inline int getNumInfeasible() const + { + return infeasible_; + } + /// Number of redundant or ineffective cuts + inline int getNumIneffective() const + { + return ineffective_; + } + /// Number of cuts applied + inline int getNumApplied() const + { + return applied_; + } + //@} + + private: + /**@name Private methods */ + //@{ + /// Increment logically inconsistent cut counter + inline void incrementInternallyInconsistent() { intInconsistent_++; } + /// Increment model-inconsistent counter + inline void incrementExternallyInconsistent() { extInconsistent_++; } + /// Increment infeasible cut counter + inline void incrementInfeasible() { infeasible_++; } + /// Increment ineffective cut counter + inline void incrementIneffective() { ineffective_++; } + /// Increment applied cut counter + inline void incrementApplied() { applied_++; } + //@} + + ///@name Private member data + //@{ + /// Counter for logically inconsistent cuts + int intInconsistent_; + /// Counter for model-inconsistent cuts + int extInconsistent_; + /// Counter for infeasible cuts + int infeasible_; + /// Counter for ineffective cuts + int ineffective_; + /// Counter for applied cuts + int applied_; + //@} + }; + + //--------------------------------------------------------------------------- + + ///@name Solve methods + //@{ + /// Solve initial LP relaxation + virtual void initialSolve() = 0; + + /*! \brief Resolve an LP relaxation after problem modification + + Note the `re-' in `resolve'. initialSolve() should be used to solve the + problem for the first time. + */ + virtual void resolve() = 0; + + /// Invoke solver's built-in enumeration algorithm + virtual void branchAndBound() = 0; + +#ifdef CBC_NEXT_VERSION + /* + Would it make sense to collect all of these routines in a `MIP Helper' + section? It'd make it easier for users and implementors to find them. + */ + /** + Solve 2**N (N==depth) problems and return solutions and bases. + There are N branches each of which changes bounds on both sides + as given by branch. The user should provide an array of (empty) + results which will be filled in. See OsiSolveResult for more details + (in OsiSolveBranch.?pp) but it will include a basis and primal solution. + + The order of results is left to right at feasible leaf nodes so first one + is down, down, ..... + + Returns number of feasible leaves. Also sets number of solves done and number + of iterations. + + This is provided so a solver can do faster. + + If forceBranch true then branch done even if satisfied + */ + virtual int solveBranches(int depth, const OsiSolverBranch *branch, + OsiSolverResult *result, + int &numberSolves, int &numberIterations, + bool forceBranch = false); +#endif + //@} + + //--------------------------------------------------------------------------- + /**@name Parameter set/get methods + + The set methods return true if the parameter was set to the given value, + false otherwise. When a set method returns false, the original value (if + any) should be unchanged. There can be various reasons for failure: the + given parameter is not applicable for the solver (e.g., refactorization + frequency for the volume algorithm), the parameter is not yet + implemented for the solver or simply the value of the parameter is out + of the range the solver accepts. If a parameter setting call returns + false check the details of your solver. + + The get methods return true if the given parameter is applicable for the + solver and is implemented. In this case the value of the parameter is + returned in the second argument. Otherwise they return false. + + \note + There is a default implementation of the set/get + methods, namely to store/retrieve the given value using an array in the + base class. A specific solver implementation can use this feature, for + example, to store parameters that should be used later on. Implementors + of a solver interface should overload these functions to provide the + proper interface to and accurately reflect the capabilities of a + specific solver. + + The format for hints is slightly different in that a boolean specifies + the sense of the hint and an enum specifies the strength of the hint. + Hints should be initialised when a solver is instantiated. + (See OsiSolverParameters.hpp for defined hint parameters and strength.) + When specifying the sense of the hint, a value of true means to work with + the hint, false to work against it. For example, +
    +
  • \code setHintParam(OsiDoScale,true,OsiHintTry) \endcode + is a mild suggestion to the solver to scale the constraint + system. +
  • \code setHintParam(OsiDoScale,false,OsiForceDo) \endcode + tells the solver to disable scaling, or throw an exception if + it cannot comply. +
+ As another example, a solver interface could use the value and strength + of the \c OsiDoReducePrint hint to adjust the amount of information + printed by the interface and/or solver. The extent to which a solver + obeys hints is left to the solver. The value and strength returned by + \c getHintParam will match the most recent call to \c setHintParam, + and will not necessarily reflect the solver's ability to comply with the + hint. If the hint strength is \c OsiForceDo, the solver is required to + throw an exception if it cannot perform the specified action. + + \note + As with the other set/get methods, there is a default implementation + which maintains arrays in the base class for hint sense and strength. + The default implementation does not store the \c otherInformation + pointer, and always throws an exception for strength \c OsiForceDo. + Implementors of a solver interface should override these functions to + provide the proper interface to and accurately reflect the capabilities + of a specific solver. + */ + //@{ + //! Set an integer parameter + virtual bool setIntParam(OsiIntParam key, int value) + { + if (key == OsiLastIntParam) + return (false); + intParam_[key] = value; + return true; + } + //! Set a double parameter + virtual bool setDblParam(OsiDblParam key, double value) + { + if (key == OsiLastDblParam) + return (false); + dblParam_[key] = value; + return true; + } + //! Set a string parameter + virtual bool setStrParam(OsiStrParam key, const std::string &value) + { + if (key == OsiLastStrParam) + return (false); + strParam_[key] = value; + return true; + } + /*! \brief Set a hint parameter + + The \c otherInformation parameter can be used to pass in an arbitrary + block of information which is interpreted by the OSI and the underlying + solver. Users are cautioned that this hook is solver-specific. + + Implementors: + The default implementation completely ignores \c otherInformation and + always throws an exception for OsiForceDo. This is almost certainly not + the behaviour you want; you really should override this method. + */ + virtual bool setHintParam(OsiHintParam key, bool yesNo = true, + OsiHintStrength strength = OsiHintTry, + void * /*otherInformation*/ = NULL) + { + if (key == OsiLastHintParam) + return false; + hintParam_[key] = yesNo; + hintStrength_[key] = strength; + if (strength == OsiForceDo) + throw CoinError("OsiForceDo illegal", + "setHintParam", "OsiSolverInterface"); + return true; + } + //! Get an integer parameter + virtual bool getIntParam(OsiIntParam key, int &value) const + { + if (key == OsiLastIntParam) + return (false); + value = intParam_[key]; + return true; + } + //! Get a double parameter + virtual bool getDblParam(OsiDblParam key, double &value) const + { + if (key == OsiLastDblParam) + return (false); + value = dblParam_[key]; + return true; + } + //! Get a string parameter + virtual bool getStrParam(OsiStrParam key, std::string &value) const + { + if (key == OsiLastStrParam) + return (false); + value = strParam_[key]; + return true; + } + /*! \brief Get a hint parameter (all information) + + Return all available information for the hint: sense, strength, + and any extra information associated with the hint. + + Implementors: The default implementation will always set + \c otherInformation to NULL. This is almost certainly not the + behaviour you want; you really should override this method. + */ + virtual bool getHintParam(OsiHintParam key, bool &yesNo, + OsiHintStrength &strength, + void *&otherInformation) const + { + if (key == OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + strength = hintStrength_[key]; + otherInformation = NULL; + return true; + } + /*! \brief Get a hint parameter (sense and strength only) + + Return only the sense and strength of the hint. + */ + virtual bool getHintParam(OsiHintParam key, bool &yesNo, + OsiHintStrength &strength) const + { + if (key == OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + strength = hintStrength_[key]; + return true; + } + /*! \brief Get a hint parameter (sense only) + + Return only the sense (true/false) of the hint. + */ + virtual bool getHintParam(OsiHintParam key, bool &yesNo) const + { + if (key == OsiLastHintParam) + return false; + yesNo = hintParam_[key]; + return true; + } + /*! \brief Copy all parameters in this section from one solver to another + + Note that the current implementation also copies the appData block, + message handler, and rowCutDebugger. Arguably these should have + independent copy methods. + */ + void copyParameters(OsiSolverInterface &rhs); + + /** \brief Return the integrality tolerance of the underlying solver. + + We should be able to get an integrality tolerance, but + until that time just use the primal tolerance + + \todo + This method should be replaced; it's architecturally wrong. This + should be an honest dblParam with a keyword. Underlying solvers + that do not support integer variables should return false for set and + get on this parameter. Underlying solvers that support integrality + should add this to the parameters they support, using whatever + tolerance is appropriate. -lh, 091021- + */ + inline double getIntegerTolerance() const + { + return dblParam_[OsiPrimalTolerance]; + } + //@} + + //--------------------------------------------------------------------------- + ///@name Methods returning info on how the solution process terminated + //@{ + /// Are there numerical difficulties? + virtual bool isAbandoned() const = 0; + /// Is optimality proven? + virtual bool isProvenOptimal() const = 0; + /// Is primal infeasibility proven? + virtual bool isProvenPrimalInfeasible() const = 0; + /// Is dual infeasibility proven? + virtual bool isProvenDualInfeasible() const = 0; + /// Is the given primal objective limit reached? + virtual bool isPrimalObjectiveLimitReached() const; + /// Is the given dual objective limit reached? + virtual bool isDualObjectiveLimitReached() const; + /// Iteration limit reached? + virtual bool isIterationLimitReached() const = 0; + //@} + + //--------------------------------------------------------------------------- + /** \name Warm start methods + + Note that the warm start methods return a generic CoinWarmStart object. + The precise characteristics of this object are solver-dependent. Clients + who wish to maintain a maximum degree of solver independence should take + care to avoid unnecessary assumptions about the properties of a warm start + object. + */ + //@{ + /*! \brief Get an empty warm start object + + This routine returns an empty warm start object. Its purpose is + to provide a way for a client to acquire a warm start object of the + appropriate type for the solver, which can then be resized and modified + as desired. + */ + + virtual CoinWarmStart *getEmptyWarmStart() const = 0; + + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. + */ + virtual CoinWarmStart *getWarmStart() const = 0; + /** \brief Get warm start information. + + Return warm start information for the current state of the solver + interface. If there is no valid warm start information, an empty warm + start object wil be returned. This does not necessarily create an + object - may just point to one. must Delete set true if user + should delete returned object. + */ + virtual CoinWarmStart *getPointerToWarmStart(bool &mustDelete); + + /** \brief Set warm start information. + + Return true or false depending on whether the warm start information was + accepted or not. + By definition, a call to setWarmStart with a null parameter should + cause the solver interface to refresh its warm start information + from the underlying solver. + */ + virtual bool setWarmStart(const CoinWarmStart *warmstart) = 0; + //@} + + //--------------------------------------------------------------------------- + /**@name Hot start methods + + Primarily used in strong branching. The user can create a hot start + object --- a snapshot of the optimization process --- then reoptimize + over and over again, starting from the same point. + + \note +
    +
  • Between hot started optimizations only bound changes are allowed. +
  • The copy constructor and assignment operator should NOT copy any + hot start information. +
  • The default implementation simply extracts a warm start object in + \c markHotStart, resets to the warm start object in + \c solveFromHotStart, and deletes the warm start object in + \c unmarkHotStart. + Actual solver implementations are encouraged to do better. +
+ + */ + //@{ + /// Create a hot start snapshot of the optimization process. + virtual void markHotStart(); + /// Optimize starting from the hot start snapshot. + virtual void solveFromHotStart(); + /// Delete the hot start snapshot. + virtual void unmarkHotStart(); + //@} + + //--------------------------------------------------------------------------- + /**@name Problem query methods + + Querying a problem that has no data associated with it will result in + zeros for the number of rows and columns, and NULL pointers from the + methods that return vectors. + + Const pointers returned from any data-query method are valid as long as + the data is unchanged and the solver is not called. + */ + //@{ + /// Get the number of columns + virtual int getNumCols() const = 0; + + /// Get the number of rows + virtual int getNumRows() const = 0; + + /// Get the number of nonzero elements + virtual CoinBigIndex getNumElements() const = 0; + + /// Get the number of integer variables + virtual int getNumIntegers() const; + + /// Get a pointer to an array[getNumCols()] of column lower bounds + virtual const double *getColLower() const = 0; + + /// Get a pointer to an array[getNumCols()] of column upper bounds + virtual const double *getColUpper() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row constraint senses. + +
    +
  • 'L': <= constraint +
  • 'E': = constraint +
  • 'G': >= constraint +
  • 'R': ranged constraint +
  • 'N': free constraint +
+ */ + virtual const char *getRowSense() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row right-hand sides + +
    +
  • if getRowSense()[i] == 'L' then + getRightHandSide()[i] == getRowUpper()[i] +
  • if getRowSense()[i] == 'G' then + getRightHandSide()[i] == getRowLower()[i] +
  • if getRowSense()[i] == 'R' then + getRightHandSide()[i] == getRowUpper()[i] +
  • if getRowSense()[i] == 'N' then + getRightHandSide()[i] == 0.0 +
+ */ + virtual const double *getRightHandSide() const = 0; + + /*! \brief Get a pointer to an array[getNumRows()] of row ranges. + +
    +
  • if getRowSense()[i] == 'R' then + getRowRange()[i] == getRowUpper()[i] - getRowLower()[i] +
  • if getRowSense()[i] != 'R' then + getRowRange()[i] is 0.0 +
+ */ + virtual const double *getRowRange() const = 0; + + /// Get a pointer to an array[getNumRows()] of row lower bounds + virtual const double *getRowLower() const = 0; + + /// Get a pointer to an array[getNumRows()] of row upper bounds + virtual const double *getRowUpper() const = 0; + + /*! \brief Get a pointer to an array[getNumCols()] of objective + function coefficients. + */ + virtual const double *getObjCoefficients() const = 0; + + /*! \brief Get the objective function sense + + - 1 for minimisation (default) + - -1 for maximisation + */ + virtual double getObjSense() const = 0; + + /// Return true if the variable is continuous + virtual bool isContinuous(int colIndex) const = 0; + + /// Return true if the variable is binary + virtual bool isBinary(int colIndex) const; + + /*! \brief Return true if the variable is integer. + + This method returns true if the variable is binary or general integer. + */ + virtual bool isInteger(int colIndex) const; + + /// Return true if the variable is general integer + virtual bool isIntegerNonBinary(int colIndex) const; + + /// Return true if the variable is binary and not fixed + virtual bool isFreeBinary(int colIndex) const; + + /*! \brief Return an array[getNumCols()] of column types + + \deprecated See #getColType + */ + inline const char *columnType(bool refresh = false) const + { + return getColType(refresh); + } + + /// Set column type + inline void setColumnType(int iColumn, char type) + { + if (!columnType_) + getColType(true); + columnType_[iColumn] = type; + } + + /*! \brief Return an array[getNumCols()] of column types + + - 0 - continuous + - 1 - binary + - 2 - general integer + - 3 - if supported - semi-continuous + - 4 - if supported - semi-continuous integer + + If \p refresh is true, the classification of integer variables as + binary or general integer will be reevaluated. If the current bounds + are [0,1], or if the variable is fixed at 0 or 1, it will be classified + as binary, otherwise it will be classified as general integer. + */ + virtual const char *getColType(bool refresh = false) const; + + /// Get a pointer to a row-wise copy of the matrix + virtual const CoinPackedMatrix *getMatrixByRow() const = 0; + + /// Get a pointer to a column-wise copy of the matrix + virtual const CoinPackedMatrix *getMatrixByCol() const = 0; + + /*! \brief Get a pointer to a mutable row-wise copy of the matrix. + + Returns NULL if the request is not meaningful (i.e., the OSI will not + recognise any modifications to the matrix). + */ + virtual CoinPackedMatrix *getMutableMatrixByRow() const { return NULL; } + + /*! \brief Get a pointer to a mutable column-wise copy of the matrix + + Returns NULL if the request is not meaningful (i.e., the OSI will not + recognise any modifications to the matrix). + */ + virtual CoinPackedMatrix *getMutableMatrixByCol() const { return NULL; } + + /// Get the solver's value for infinity + virtual double getInfinity() const = 0; + //@} + + /**@name Solution query methods */ + //@{ + /// Get a pointer to an array[getNumCols()] of primal variable values + virtual const double *getColSolution() const = 0; + + /** Get a pointer to an array[getNumCols()] of primal variable values + guaranteed to be between the column lower and upper bounds. + */ + virtual const double *getStrictColSolution(); + + /// Get pointer to array[getNumRows()] of dual variable values + virtual const double *getRowPrice() const = 0; + + /// Get a pointer to an array[getNumCols()] of reduced costs + virtual const double *getReducedCost() const = 0; + + /** Get a pointer to array[getNumRows()] of row activity levels. + + The row activity for a row is the left-hand side evaluated at the + current solution. + */ + virtual const double *getRowActivity() const = 0; + + /// Get the objective function value. + virtual double getObjValue() const = 0; + + /** Get the number of iterations it took to solve the problem (whatever + `iteration' means to the solver). + */ + virtual int getIterationCount() const = 0; + + /** Get as many dual rays as the solver can provide. In case of proven + primal infeasibility there should (with high probability) be at least + one. + + The first getNumRows() ray components will always be associated with + the row duals (as returned by getRowPrice()). If \c fullRay is true, + the final getNumCols() entries will correspond to the ray components + associated with the nonbasic variables. If the full ray is requested + and the method cannot provide it, it will throw an exception. + + \note + Implementors of solver interfaces note that the double pointers in + the vector should point to arrays of length getNumRows() (fullRay = + false) or (getNumRows()+getNumCols()) (fullRay = true) and they should + be allocated with new[]. + + \note + Clients of solver interfaces note that it is the client's + responsibility to free the double pointers in the vector using + delete[]. Clients are reminded that a problem can be dual and primal + infeasible. + */ + virtual std::vector< double * > getDualRays(int maxNumRays, + bool fullRay = false) const = 0; + + /** Get as many primal rays as the solver can provide. In case of proven + dual infeasibility there should (with high probability) be at least + one. + + \note + Implementors of solver interfaces note that the double pointers in + the vector should point to arrays of length getNumCols() and they + should be allocated with new[]. + + \note + Clients of solver interfaces note that it is the client's + responsibility to free the double pointers in the vector using + delete[]. Clients are reminded that a problem can be dual and primal + infeasible. + */ + virtual std::vector< double * > getPrimalRays(int maxNumRays) const = 0; + + /** Get vector of indices of primal variables which are integer variables + but have fractional values in the current solution. */ + virtual OsiVectorInt getFractionalIndices(const double etol = 1.e-05) + const; + //@} + + //------------------------------------------------------------------------- + /**@name Methods to modify the objective, bounds, and solution + + For functions which take a set of indices as parameters + (\c setObjCoeffSet(), \c setColSetBounds(), \c setRowSetBounds(), + \c setRowSetTypes()), the parameters follow the C++ STL iterator + convention: \c indexFirst points to the first index in the + set, and \c indexLast points to a position one past the last index + in the set. + + */ + //@{ + /** Set an objective function coefficient */ + virtual void setObjCoeff(int elementIndex, double elementValue) = 0; + + /** Set a set of objective function coefficients */ + virtual void setObjCoeffSet(const int *indexFirst, + const int *indexLast, + const double *coeffList); + + /** Set the objective coefficients for all columns. + + array [getNumCols()] is an array of values for the objective. + This defaults to a series of set operations and is here for speed. + */ + virtual void setObjective(const double *array); + + /** Set the objective function sense. + + Use 1 for minimisation (default), -1 for maximisation. + + \note + Implementors note that objective function sense is a parameter of + the OSI, not a property of the problem. Objective sense can be + set prior to problem load and should not be affected by loading a + new problem. + */ + virtual void setObjSense(double s) = 0; + + /** Set a single column lower bound. + Use -getInfinity() for -infinity. */ + virtual void setColLower(int elementIndex, double elementValue) = 0; + + /** Set the lower bounds for all columns. + + array [getNumCols()] is an array of values for the lower bounds. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColLower(const double *array); + + /** Set a single column upper bound. + Use getInfinity() for infinity. */ + virtual void setColUpper(int elementIndex, double elementValue) = 0; + + /** Set the upper bounds for all columns. + + array [getNumCols()] is an array of values for the upper bounds. + This defaults to a series of set operations and is here for speed. + */ + virtual void setColUpper(const double *array); + + /** Set a single column lower and upper bound. + The default implementation just invokes setColLower() and + setColUpper() */ + virtual void setColBounds(int elementIndex, + double lower, double upper) + { + setColLower(elementIndex, lower); + setColUpper(elementIndex, upper); + } + + /** Set the upper and lower bounds of a set of columns. + + The default implementation just invokes setColBounds() over and over + again. For each column, boundList must contain both a lower and + upper bound, in that order. + */ + virtual void setColSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set a single row lower bound. + Use -getInfinity() for -infinity. */ + virtual void setRowLower(int elementIndex, double elementValue) = 0; + + /** Set a single row upper bound. + Use getInfinity() for infinity. */ + virtual void setRowUpper(int elementIndex, double elementValue) = 0; + + /** Set a single row lower and upper bound. + The default implementation just invokes setRowLower() and + setRowUpper() */ + virtual void setRowBounds(int elementIndex, + double lower, double upper) + { + setRowLower(elementIndex, lower); + setRowUpper(elementIndex, upper); + } + + /** Set the bounds on a set of rows. + + The default implementation just invokes setRowBounds() over and over + again. For each row, boundList must contain both a lower and + upper bound, in that order. + */ + virtual void setRowSetBounds(const int *indexFirst, + const int *indexLast, + const double *boundList); + + /** Set the type of a single row */ + virtual void setRowType(int index, char sense, double rightHandSide, + double range) + = 0; + + /** Set the type of a set of rows. + The default implementation just invokes setRowType() + over and over again. + */ + virtual void setRowSetTypes(const int *indexFirst, + const int *indexLast, + const char *senseList, + const double *rhsList, + const double *rangeList); + + /** Set the primal solution variable values + + colsol[getNumCols()] is an array of values for the primal variables. + These values are copied to memory owned by the solver interface + object or the solver. They will be returned as the result of + getColSolution() until changed by another call to setColSolution() or + by a call to any solver routine. Whether the solver makes use of the + solution in any way is solver-dependent. + */ + virtual void setColSolution(const double *colsol) = 0; + + /** Set dual solution variable values + + rowprice[getNumRows()] is an array of values for the dual variables. + These values are copied to memory owned by the solver interface + object or the solver. They will be returned as the result of + getRowPrice() until changed by another call to setRowPrice() or by a + call to any solver routine. Whether the solver makes use of the + solution in any way is solver-dependent. + */ + virtual void setRowPrice(const double *rowprice) = 0; + + /** Fix variables at bound based on reduced cost + + For variables currently at bound, fix the variable at bound if the + reduced cost exceeds the gap. Return the number of variables fixed. + + If justInteger is set to false, the routine will also fix continuous + variables, but the test still assumes a delta of 1.0. + */ + virtual int reducedCostFix(double gap, bool justInteger = true); + //@} + + //------------------------------------------------------------------------- + /**@name Methods to set variable type */ + //@{ + /** Set the index-th variable to be a continuous variable */ + virtual void setContinuous(int index) = 0; + /** Set the index-th variable to be an integer variable */ + virtual void setInteger(int index) = 0; + /** Set the variables listed in indices (which is of length len) to be + continuous variables */ + virtual void setContinuous(const int *indices, int len); + /** Set the variables listed in indices (which is of length len) to be + integer variables */ + virtual void setInteger(const int *indices, int len); + //@} + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + + /*! \brief Data type for name vectors. */ + typedef std::vector< std::string > OsiNameVec; + + /*! \name Methods for row and column names + + Osi defines three name management disciplines: `auto names' (0), `lazy + names' (1), and `full names' (2). See the description of + #OsiNameDiscipline for details. Changing the name discipline (via + setIntParam()) will not automatically add or remove name information, + but setting the discipline to auto will make existing information + inaccessible until the discipline is reset to lazy or full. + + By definition, a row index of getNumRows() (i.e., one larger than + the largest valid row index) refers to the objective function. + + OSI users and implementors: While the OSI base class can define an + interface and provide rudimentary support, use of names really depends + on support by the OsiXXX class to ensure that names are managed + correctly. If an OsiXXX class does not support names, it should return + false for calls to getIntParam() or setIntParam() that reference + OsiNameDiscipline. + */ + //@{ + + /*! \brief Generate a standard name of the form Rnnnnnnn or Cnnnnnnn + + Set \p rc to 'r' for a row name, 'c' for a column name. + The `nnnnnnn' part is generated from ndx and will contain 7 digits + by default, padded with zeros if necessary. As a special case, + ndx = getNumRows() is interpreted as a request for the name of the + objective function. OBJECTIVE is returned, truncated to digits+1 + characters to match the row and column names. + */ + virtual std::string dfltRowColName(char rc, + int ndx, unsigned digits = 7) const; + + /*! \brief Return the name of the objective function */ + + virtual std::string getObjName(unsigned maxLen = static_cast< unsigned >(std::string::npos)) const; + + /*! \brief Set the name of the objective function */ + + virtual inline void setObjName(std::string name) + { + objName_ = name; + } + + /*! \brief Return the name of the row. + + The routine will always return some name, regardless of the name + discipline or the level of support by an OsiXXX derived class. Use + maxLen to limit the length. + */ + virtual std::string getRowName(int rowIndex, + unsigned maxLen = static_cast< unsigned >(std::string::npos)) const; + + /*! \brief Return a pointer to a vector of row names + + If the name discipline (#OsiNameDiscipline) is auto, the return value + will be a vector of length zero. If the name discipline is lazy, the + vector will contain only names supplied by the client and will be no + larger than needed to hold those names; entries not supplied will be + null strings. In particular, the objective name is not + included in the vector for lazy names. If the name discipline is + full, the vector will have getNumRows() names, either supplied or + generated, plus one additional entry for the objective name. + */ + virtual const OsiNameVec &getRowNames(); + + /*! \brief Set a row name + + Quietly does nothing if the name discipline (#OsiNameDiscipline) is + auto. Quietly fails if the row index is invalid. + */ + virtual void setRowName(int ndx, std::string name); + + /*! \brief Set multiple row names + + The run of len entries starting at srcNames[srcStart] are installed as + row names starting at row index tgtStart. The base class implementation + makes repeated calls to setRowName. + */ + virtual void setRowNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart); + + /*! \brief Delete len row names starting at index tgtStart + + The specified row names are removed and the remaining row names are + copied down to close the gap. + */ + virtual void deleteRowNames(int tgtStart, int len); + + /*! \brief Return the name of the column + + The routine will always return some name, regardless of the name + discipline or the level of support by an OsiXXX derived class. Use + maxLen to limit the length. + */ + virtual std::string getColName(int colIndex, + unsigned maxLen = static_cast< unsigned >(std::string::npos)) const; + + /*! \brief Return a pointer to a vector of column names + + If the name discipline (#OsiNameDiscipline) is auto, the return value + will be a vector of length zero. If the name discipline is lazy, the + vector will contain only names supplied by the client and will be no + larger than needed to hold those names; entries not supplied will be + null strings. If the name discipline is full, the vector will have + getNumCols() names, either supplied or generated. + */ + virtual const OsiNameVec &getColNames(); + + /*! \brief Set a column name + + Quietly does nothing if the name discipline (#OsiNameDiscipline) is + auto. Quietly fails if the column index is invalid. + */ + virtual void setColName(int ndx, std::string name); + + /*! \brief Set multiple column names + + The run of len entries starting at srcNames[srcStart] are installed as + column names starting at column index tgtStart. The base class + implementation makes repeated calls to setColName. + */ + virtual void setColNames(OsiNameVec &srcNames, + int srcStart, int len, int tgtStart); + + /*! \brief Delete len column names starting at index tgtStart + + The specified column names are removed and the remaining column names + are copied down to close the gap. + */ + virtual void deleteColNames(int tgtStart, int len); + + /*! \brief Set row and column names from a CoinMpsIO object. + + Also sets the name of the objective function. If the name discipline + is auto, you get what you asked for. This routine does not use + setRowName or setColName. + */ + void setRowColNames(const CoinMpsIO &mps); + + /*! \brief Set row and column names from a CoinModel object. + + If the name discipline is auto, you get what you asked for. + This routine does not use setRowName or setColName. + */ + void setRowColNames(CoinModel &mod); + + /*! \brief Set row and column names from a CoinLpIO object. + + Also sets the name of the objective function. If the name discipline is + auto, you get what you asked for. This routine does not use setRowName + or setColName. + */ + void setRowColNames(CoinLpIO &mod); + + //@} + //------------------------------------------------------------------------- + + //------------------------------------------------------------------------- + /**@name Methods to modify the constraint system. + + Note that new columns are added as continuous variables. + */ + //@{ + + /** Add a column (primal variable) to the problem. */ + virtual void addCol(const CoinPackedVectorBase &vec, + const double collb, const double colub, + const double obj) + = 0; + + /*! \brief Add a named column (primal variable) to the problem. + + The default implementation adds the column, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addCol(const CoinPackedVectorBase &vec, + const double collb, const double colub, + const double obj, std::string name); + + /** Add a column (primal variable) to the problem. */ + virtual void addCol(int numberElements, + const int *rows, const double *elements, + const double collb, const double colub, + const double obj); + + /*! \brief Add a named column (primal variable) to the problem. + + The default implementation adds the column, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addCol(int numberElements, + const int *rows, const double *elements, + const double collb, const double colub, + const double obj, std::string name); + + /** Add a set of columns (primal variables) to the problem. + + The default implementation simply makes repeated calls to + addCol(). + */ + virtual void addCols(const int numcols, + const CoinPackedVectorBase *const *cols, + const double *collb, const double *colub, + const double *obj); + + /** Add a set of columns (primal variables) to the problem. + + The default implementation simply makes repeated calls to + addCol(). + */ + virtual void addCols(const int numcols, const CoinBigIndex *columnStarts, + const int *rows, const double *elements, + const double *collb, const double *colub, + const double *obj); + + /// Add columns using a CoinBuild object + void addCols(const CoinBuild &buildObject); + + /** Add columns from a model object. returns + -1 if object in bad state (i.e. has row information) + otherwise number of errors + modelObject non const as can be regularized as part of build + */ + int addCols(CoinModel &modelObject); + +#if 0 + /** */ + virtual void addCols(const CoinPackedMatrix& matrix, + const double* collb, const double* colub, + const double* obj); +#endif + + /** \brief Remove a set of columns (primal variables) from the + problem. + + The solver interface for a basis-oriented solver will maintain valid + warm start information if all deleted variables are nonbasic. + */ + virtual void deleteCols(const int num, const int *colIndices) = 0; + + /*! \brief Add a row (constraint) to the problem. */ + virtual void addRow(const CoinPackedVectorBase &vec, + const double rowlb, const double rowub) + = 0; + + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase &vec, + const double rowlb, const double rowub, + std::string name); + + /*! \brief Add a row (constraint) to the problem. */ + virtual void addRow(const CoinPackedVectorBase &vec, + const char rowsen, const double rowrhs, + const double rowrng) + = 0; + + /*! \brief Add a named row (constraint) to the problem. + + The default implementation adds the row, then changes the name. This + can surely be made more efficient within an OsiXXX class. + */ + virtual void addRow(const CoinPackedVectorBase &vec, + const char rowsen, const double rowrhs, + const double rowrng, std::string name); + + /*! Add a row (constraint) to the problem. + + Converts to addRow(CoinPackedVectorBase&,const double,const double). + */ + virtual void addRow(int numberElements, + const int *columns, const double *element, + const double rowlb, const double rowub); + + /*! Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const double *rowlb, const double *rowub); + + /** Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, + const CoinPackedVectorBase *const *rows, + const char *rowsen, const double *rowrhs, + const double *rowrng); + + /** Add a set of rows (constraints) to the problem. + + The default implementation simply makes repeated calls to + addRow(). + */ + virtual void addRows(const int numrows, const CoinBigIndex *rowStarts, + const int *columns, const double *element, + const double *rowlb, const double *rowub); + + /// Add rows using a CoinBuild object + void addRows(const CoinBuild &buildObject); + + /*! Add rows from a CoinModel object. + + Returns -1 if the object is in the wrong state (i.e., has + column-major information), otherwise the number of errors. + + The modelObject is not const as it can be regularized as part of + the build. + */ + int addRows(CoinModel &modelObject); + +#if 0 + /** */ + virtual void addRows(const CoinPackedMatrix& matrix, + const double* rowlb, const double* rowub); + /** */ + virtual void addRows(const CoinPackedMatrix& matrix, + const char* rowsen, const double* rowrhs, + const double* rowrng); +#endif + + /** \brief Delete a set of rows (constraints) from the problem. + + The solver interface for a basis-oriented solver will maintain valid + warm start information if all deleted rows are loose. + */ + virtual void deleteRows(const int num, const int *rowIndices) = 0; + + /** \brief Replace the constraint matrix + + I (JJF) am getting annoyed because I can't just replace a matrix. + The default behavior of this is do nothing so only use where that would + not matter, e.g. strengthening a matrix for MIP. + */ + virtual void replaceMatrixOptional(const CoinPackedMatrix &) {} + + /** \brief Replace the constraint matrix + + And if it does matter (not used at present) + */ + virtual void replaceMatrix(const CoinPackedMatrix &) { abort(); } + + /** \brief Save a copy of the base model + + If solver wants it can save a copy of "base" (continuous) model here. + */ + virtual void saveBaseModel() {} + + /** \brief Reduce the constraint system to the specified number of + constraints. + + If solver wants it can restore a copy of "base" (continuous) model + here. + + \note + The name is somewhat misleading. Implementors should consider + the opportunity to optimise behaviour in the common case where + \p numberRows is exactly the number of original constraints. Do not, + however, neglect the possibility that \p numberRows does not equal + the number of original constraints. + */ + virtual void restoreBaseModel(int numberRows); + //----------------------------------------------------------------------- + /** Apply a collection of cuts. + + Only cuts which have an effectiveness >= effectivenessLb + are applied. +
    +
  • ReturnCode.getNumineffective() -- number of cuts which were + not applied because they had an + effectiveness < effectivenessLb +
  • ReturnCode.getNuminconsistent() -- number of invalid cuts +
  • ReturnCode.getNuminconsistentWrtIntegerModel() -- number of + cuts that are invalid with respect to this integer model +
  • ReturnCode.getNuminfeasible() -- number of cuts that would + make this integer model infeasible +
  • ReturnCode.getNumApplied() -- number of integer cuts which + were applied to the integer model +
  • cs.size() == getNumineffective() + + getNuminconsistent() + + getNuminconsistentWrtIntegerModel() + + getNuminfeasible() + + getNumApplied() +
+ */ + virtual ApplyCutsReturnCode applyCuts(const OsiCuts &cs, + double effectivenessLb = 0.0); + + /** Apply a collection of row cuts which are all effective. + applyCuts seems to do one at a time which seems inefficient. + Would be even more efficient to pass an array of pointers. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut *cuts); + + /** Apply a collection of row cuts which are all effective. + This is passed in as an array of pointers. + */ + virtual void applyRowCuts(int numberCuts, const OsiRowCut **cuts); + + /// Deletes branching information before columns deleted + void deleteBranchingInfo(int numberDeleted, const int *which); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Methods for problem input and output */ + //@{ + /*! \brief Load in a problem by copying the arguments. The constraints on + the rows are given by lower and upper bounds. + + If a pointer is 0 then the following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • rowub: all rows have upper bound infinity +
  • rowlb: all rows have lower bound -infinity +
  • obj: all variables have 0 objective coefficient +
+ + Note that the default values for rowub and rowlb produce the + constraint -infty <= ax <= infty. This is probably not what you want. + */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub) + = 0; + + /*! \brief Load in a problem by assuming ownership of the arguments. + The constraints on the rows are given by lower and upper bounds. + + For default argument values see the matching loadProblem method. + + \warning + The arguments passed to this method will be freed using the + C++ delete and delete[] functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + double *&rowlb, double *&rowub) + = 0; + + /*! \brief Load in a problem by copying the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + If a pointer is 0 then the following values are the default: +
    +
  • colub: all columns have upper bound infinity +
  • collb: all columns have lower bound 0 +
  • obj: all variables have 0 objective coefficient +
  • rowsen: all rows are >= +
  • rowrhs: all right hand sides are 0 +
  • rowrng: 0 for the ranged rows +
+ + Note that the default values for rowsen, rowrhs, and rowrng produce the + constraint ax >= 0. + */ + virtual void loadProblem(const CoinPackedMatrix &matrix, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng) + = 0; + + /*! \brief Load in a problem by assuming ownership of the arguments. + The constraints on the rows are given by sense/rhs/range triplets. + + For default argument values see the matching loadProblem method. + + \warning + The arguments passed to this method will be freed using the + C++ delete and delete[] functions. + */ + virtual void assignProblem(CoinPackedMatrix *&matrix, + double *&collb, double *&colub, double *&obj, + char *&rowsen, double *&rowrhs, + double *&rowrng) + = 0; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by lower and upper bounds. + + The matrix vectors must be gap-free. Note that start must + have numcols+1 entries so that the length of the last column + can be calculated as start[numcols]-start[numcols-1]. + + See the previous loadProblem method using rowlb and rowub for default + argument values. + */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const double *rowlb, const double *rowub) + = 0; + + /*! \brief Load in a problem by copying the arguments. The constraint + matrix is is specified with standard column-major + column starts / row indices / coefficients vectors. + The constraints on the rows are given by sense/rhs/range triplets. + + The matrix vectors must be gap-free. Note that start must + have numcols+1 entries so that the length of the last column + can be calculated as start[numcols]-start[numcols-1]. + + See the previous loadProblem method using sense/rhs/range for default + argument values. + */ + virtual void loadProblem(const int numcols, const int numrows, + const CoinBigIndex *start, const int *index, + const double *value, + const double *collb, const double *colub, + const double *obj, + const char *rowsen, const double *rowrhs, + const double *rowrng) + = 0; + + /*! \brief Load a model from a CoinModel object. Return the number of + errors encountered. + + The modelObject parameter cannot be const as it may be changed as part + of process. If keepSolution is true will try and keep warmStart. + */ + virtual int loadFromCoinModel(CoinModel &modelObject, + bool keepSolution = false); + + /*! \brief Read a problem in MPS format from the given filename. + + The default implementation uses CoinMpsIO::readMps() to read + the MPS file and returns the number of errors encountered. + */ + virtual int readMps(const char *filename, + const char *extension = "mps"); + + /*! \brief Read a problem in MPS format from the given full filename. + + This uses CoinMpsIO::readMps() to read the MPS file and returns the + number of errors encountered. It also may return an array of set + information + */ + virtual int readMps(const char *filename, const char *extension, + int &numberSets, CoinSet **&sets); + + /*! \brief Read a problem in GMPL format from the given filenames. + + The default implementation uses CoinMpsIO::readGMPL(). This capability + is available only if the third-party package Glpk is installed. + */ + virtual int readGMPL(const char *filename, const char *dataname = NULL); + + /*! \brief Write the problem in MPS format to the specified file. + + If objSense is non-zero, a value of -1.0 causes the problem to be + written with a maximization objective; +1.0 forces a minimization + objective. If objSense is zero, the choice is left to the implementation. + */ + virtual void writeMps(const char *filename, + const char *extension = "mps", + double objSense = 0.0) const = 0; + + /*! \brief Write the problem in MPS format to the specified file with + more control over the output. + + Row and column names may be null. + formatType is +
    +
  • 0 - normal +
  • 1 - extra accuracy +
  • 2 - IEEE hex +
+ + Returns non-zero on I/O error + */ + int writeMpsNative(const char *filename, + const char **rowNames, const char **columnNames, + int formatType = 0, int numberAcross = 2, + double objSense = 0.0, int numberSOS = 0, + const CoinSet *setInfo = NULL) const; + + /***********************************************************************/ + // Lp files + + /** Write the problem into an Lp file of the given filename with the + specified extension. + Coefficients with value less than epsilon away from an integer value + are written as integers. + Write at most numberAcross monomials on a line. + Write non integer numbers with decimals digits after the decimal point. + + The written problem is always a minimization problem. + If the current problem is a maximization problem, the + intended objective function for the written problem is the current + objective function multiplied by -1. If the current problem is a + minimization problem, the intended objective function for the + written problem is the current objective function. + If objSense < 0, the intended objective function is multiplied by -1 + before writing the problem. It is left unchanged otherwise. + + Write objective function name and constraint names if useRowNames is + true. This version calls writeLpNative(). + */ + virtual void writeLp(const char *filename, + const char *extension = "lp", + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 9, + double objSense = 0.0, + bool useRowNames = true) const; + + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLp() with first parameter filename. + */ + virtual void writeLp(FILE *fp, + double epsilon = 1e-5, + int numberAcross = 10, + int decimals = 5, + double objSense = 0.0, + bool useRowNames = true) const; + + /** Write the problem into an Lp file. Parameters are similar to + those of writeLp(), but in addition row names and column names + may be given. + + Parameter rowNames may be NULL, in which case default row names + are used. If rowNames is not NULL, it must have exactly one entry + per row in the problem and one additional + entry (rowNames[getNumRows()] with the objective function name. + These getNumRows()+1 entries must be distinct. If this is not the + case, default row names + are used. In addition, format restrictions are imposed on names + (see CoinLpIO::is_invalid_name() for details). + + Similar remarks can be made for the parameter columnNames which + must either be NULL or have exactly getNumCols() distinct entries. + + Write objective function name and constraint names if + useRowNames is true. */ + int writeLpNative(const char *filename, + char const *const *const rowNames, + char const *const *const columnNames, + const double epsilon = 1.0e-5, + const int numberAcross = 10, + const int decimals = 5, + const double objSense = 0.0, + const bool useRowNames = true) const; + + /** Write the problem into the file pointed to by the parameter fp. + Other parameters are similar to + those of writeLpNative() with first parameter filename. + */ + int writeLpNative(FILE *fp, + char const *const *const rowNames, + char const *const *const columnNames, + const double epsilon = 1.0e-5, + const int numberAcross = 10, + const int decimals = 5, + const double objSense = 0.0, + const bool useRowNames = true) const; + + /// Read file in LP format from file with name filename. + /// See class CoinLpIO for description of this format. + virtual int readLp(const char *filename, const double epsilon = 1e-5); + + /// Read file in LP format from the file pointed to by fp. + /// See class CoinLpIO for description of this format. + int readLp(FILE *fp, const double epsilon = 1e-5); + + //@} + + //--------------------------------------------------------------------------- + + /**@name Miscellaneous */ + //@{ + /** Check two models against each other. Return nonzero if different. + Ignore names if that set. + (Note initial version does not check names) + May modify both models by cleaning up + */ + int differentModel(OsiSolverInterface &other, + bool ignoreNames = true); + /** Get some statistics about model - min/max always computed + type 0->4 , larger gives more information + 0 - Just set min and max values of coefficients + */ + void statistics(double &minimumNegative, double &maximumNegative, + double &minimumPositive, double &maximumPositive, + int type = 3) const; +#ifdef COIN_SNAPSHOT + /// Return a CoinSnapshot + virtual CoinSnapshot *snapshot(bool createArrays = true) const; +#endif +#ifdef COIN_FACTORIZATION_INFO + /// Return number of entries in L part of current factorization + virtual CoinBigIndex getSizeL() const; + /// Return number of entries in U part of current factorization + virtual CoinBigIndex getSizeU() const; +#endif + //@} + + //--------------------------------------------------------------------------- + + /**@name Setting/Accessing application data */ + //@{ + /** Set application data. + + This is a pointer that the application can store into and + retrieve from the solver interface. + This field is available for the application to optionally + define and use. + */ + void setApplicationData(void *appData); + /** Create a clone of an Auxiliary Information object. + The base class just stores an application data pointer + but can be more general. Application data pointer is + designed for one user while this can be extended to cope + with more general extensions. + */ + void setAuxiliaryInfo(OsiAuxInfo *auxiliaryInfo); + + /// Get application data + void *getApplicationData() const; + /// Get pointer to auxiliary info object + OsiAuxInfo *getAuxiliaryInfo() const; + //@} + //--------------------------------------------------------------------------- + + /**@name Message handling + + See the COIN library documentation for additional information about + COIN message facilities. + + */ + //@{ + /** Pass in a message handler + + It is the client's responsibility to destroy a message handler installed + by this routine; it will not be destroyed when the solver interface is + destroyed. + */ + virtual void passInMessageHandler(CoinMessageHandler *handler); + /// Set language + void newLanguage(CoinMessages::Language language); + inline void setLanguage(CoinMessages::Language language) + { + newLanguage(language); + } + /// Return a pointer to the current message handler + inline CoinMessageHandler *messageHandler() const + { + return handler_; + } + /// Return the current set of messages + inline CoinMessages messages() + { + return messages_; + } + /// Return a pointer to the current set of messages + inline CoinMessages *messagesPointer() + { + return &messages_; + } + /// Return true if default handler + inline bool defaultHandler() const + { + return defaultHandler_; + } + //@} + //--------------------------------------------------------------------------- + /**@name Methods for dealing with discontinuities other than integers. + + Osi should be able to know about SOS and other types. This is an optional + section where such information can be stored. + + */ + //@{ + /** \brief Identify integer variables and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If justCount then no objects created and we just store numberIntegers_ + */ + + void findIntegers(bool justCount); + /** \brief Identify integer variables and SOS and create corresponding objects. + + Record integer variables and create an OsiSimpleInteger object for each + one. All existing OsiSimpleInteger objects will be destroyed. + If the solver supports SOS then do the same for SOS. + + If justCount then no objects created and we just store numberIntegers_ + Returns number of SOS + */ + + virtual int findIntegersAndSOS(bool justCount); + /// Get the number of objects + inline int numberObjects() const { return numberObjects_; } + /// Set the number of objects + inline void setNumberObjects(int number) + { + numberObjects_ = number; + } + + /// Get the array of objects + inline OsiObject **objects() const { return object_; } + + /// Get the specified object + const inline OsiObject *object(int which) const { return object_[which]; } + /// Get the specified object + inline OsiObject *modifiableObject(int which) const { return object_[which]; } + + /// Delete all object information + void deleteObjects(); + + /** Add in object information. + + Objects are cloned; the owner can delete the originals. + */ + void addObjects(int numberObjects, OsiObject **objects); + /** Use current solution to set bounds so current integer feasible solution will stay feasible. + Only feasible bounds will be used, even if current solution outside bounds. The amount of + such violation will be returned (and if small can be ignored) + */ + double forceFeasible(); + //@} + //--------------------------------------------------------------------------- + + /*! @name Methods related to testing generated cuts + + See the documentation for OsiRowCutDebugger for additional details. + */ + //@{ + /*! \brief Activate the row cut debugger. + + If \p modelName is in the set of known models then all cuts are + checked to see that they do NOT cut off the optimal solution known + to the debugger. + */ + virtual void activateRowCutDebugger(const char *modelName); + + /*! \brief Activate the row cut debugger using a full solution array. + + + Activate the debugger for a model not included in the debugger's + internal database. Cuts will be checked to see that they do NOT + cut off the given solution. + + \p solution must be a full solution vector, but only the integer + variables need to be correct. The debugger will fill in the continuous + variables by solving an lp relaxation with the integer variables + fixed as specified. If the given values for the continuous variables + should be preserved, set \p keepContinuous to true. + */ + virtual void activateRowCutDebugger(const double *solution, + bool enforceOptimality = true); + + /*! \brief Get the row cut debugger provided the solution known to the + debugger is within the feasible region held in the solver. + + If there is a row cut debugger object associated with model AND if + the solution known to the debugger is within the solver's current + feasible region (i.e., the column bounds held in the solver are + compatible with the known solution) then a pointer to the debugger + is returned which may be used to test validity of cuts. + + Otherwise NULL is returned + */ + const OsiRowCutDebugger *getRowCutDebugger() const; + + /*! \brief Get the row cut debugger object + + Return the row cut debugger object if it exists. One common usage of + this method is to obtain a debugger object in order to execute + OsiRowCutDebugger::redoSolution (so that the stored solution is again + compatible with the problem held in the solver). + */ + OsiRowCutDebugger *getRowCutDebuggerAlways() const; + //@} + + /*! \name OsiSimplexInterface + \brief Simplex Interface + + Methods for an advanced interface to a simplex solver. The interface + comprises two groups of methods. Group 1 contains methods for tableau + access. Group 2 contains methods for dictating individual simplex pivots. + */ + //@{ + + /*! \brief Return the simplex implementation level. + + The return codes are: + - 0: the simplex interface is not implemented. + - 1: the Group 1 (tableau access) methods are implemented. + - 2: the Group 2 (pivoting) methods are implemented + + The codes are cumulative - a solver which implements Group 2 also + implements Group 1. + */ + virtual int canDoSimplexInterface() const; + //@} + + /*! \name OsiSimplex Group 1 + \brief Tableau access methods. + + This group of methods provides access to rows and columns of the basis + inverse and to rows and columns of the tableau. + */ + //@{ + + /*! \brief Prepare the solver for the use of tableau access methods. + + Prepares the solver for the use of the tableau access methods, if + any such preparation is required. + + The \c const attribute is required due to the places this method + may be called (e.g., within CglCutGenerator::generateCuts()). + */ + virtual void enableFactorization() const; + + /*! \brief Undo the effects of #enableFactorization. */ + virtual void disableFactorization() const; + + /*! \brief Check if an optimal basis is available. + + Returns true if the problem has been solved to optimality and a + basis is available. This should be used to see if the tableau access + operations are possible and meaningful. + + \note + Implementors please note that this method may be called + before #enableFactorization. + */ + virtual bool basisIsAvailable() const; + + /// Synonym for #basisIsAvailable + inline bool optimalBasisIsAvailable() const { return basisIsAvailable(); } + + /*! \brief Retrieve status information for column and row variables. + + This method returns status as integer codes: +
    +
  • 0: free +
  • 1: basic +
  • 2: nonbasic at upper bound +
  • 3: nonbasic at lower bound +
+ + The #getWarmStart method provides essentially the same functionality + for a simplex-oriented solver, but the implementation details are very + different. + + \note + Logical variables associated with rows are all assumed to have +1 + coefficients, so for a <= constraint the logical will be at lower + bound if the constraint is tight. + + \note + Implementors may choose to implement this method as a wrapper which + converts a CoinWarmStartBasis to the requested representation. + */ + virtual void getBasisStatus(int *cstat, int *rstat) const; + + /*! \brief Set the status of column and row variables and update + the basis factorization and solution. + + Status information should be coded as documented for #getBasisStatus. + Returns 0 if all goes well, 1 if something goes wrong. + + This method differs from #setWarmStart in the format of the input + and in its immediate effect. Think of it as #setWarmStart immediately + followed by #resolve, but no pivots are allowed. + + \note + Implementors may choose to implement this method as a wrapper that calls + #setWarmStart and #resolve if the no pivot requirement can be satisfied. + */ + virtual int setBasisStatus(const int *cstat, const int *rstat); + + /*! \brief Calculate duals and reduced costs for the given objective + coefficients. + + The solver's objective coefficient vector is not changed. + */ + virtual void getReducedGradient(double *columnReducedCosts, + double *duals, const double *c) const; + + /*! \brief Get a row of the tableau + + If \p slack is not null, it will be loaded with the coefficients for + the artificial (logical) variables (i.e., the row of the basis inverse). + */ + virtual void getBInvARow(int row, double *z, double *slack = NULL) const; + + /*! \brief Get a row of the basis inverse */ + virtual void getBInvRow(int row, double *z) const; + + /*! \brief Get a column of the tableau */ + virtual void getBInvACol(int col, double *vec) const; + + /*! \brief Get a column of the basis inverse */ + virtual void getBInvCol(int col, double *vec) const; + + /*! \brief Get indices of basic variables + + If the logical (artificial) for row i is basic, the index should be coded + as (#getNumCols + i). + The order of indices must match the order of elements in the vectors + returned by #getBInvACol and #getBInvCol. + */ + virtual void getBasics(int *index) const; + + //@} + + /*! \name OsiSimplex Group 2 + \brief Pivoting methods + + This group of methods provides for control of individual pivots by a + simplex solver. + */ + //@{ + + /**Enables normal operation of subsequent functions. + This method is supposed to ensure that all typical things (like + reduced costs, etc.) are updated when individual pivots are executed + and can be queried by other methods. says whether will be + doing primal or dual + */ + virtual void enableSimplexInterface(bool doingPrimal); + + ///Undo whatever setting changes the above method had to make + virtual void disableSimplexInterface(); + /** Perform a pivot by substituting a colIn for colOut in the basis. + The status of the leaving variable is given in outStatus. Where + 1 is to upper bound, -1 to lower bound + Return code was undefined - now for OsiClp is 0 for okay, + 1 if inaccuracy forced re-factorization (should be okay) and + -1 for singular factorization + */ + virtual int pivot(int colIn, int colOut, int outStatus); + + /** Obtain a result of the primal pivot + Outputs: colOut -- leaving column, outStatus -- its status, + t -- step size, and, if dx!=NULL, *dx -- primal ray direction. + Inputs: colIn -- entering column, sign -- direction of its change (+/-1). + Both for colIn and colOut, artificial variables are index by + the negative of the row index minus 1. + Return code (for now): 0 -- leaving variable found, + -1 -- everything else? + Clearly, more informative set of return values is required + Primal and dual solutions are updated + */ + virtual int primalPivotResult(int colIn, int sign, + int &colOut, int &outStatus, + double &t, CoinPackedVector *dx); + + /** Obtain a result of the dual pivot (similar to the previous method) + Differences: entering variable and a sign of its change are now + the outputs, the leaving variable and its statuts -- the inputs + If dx!=NULL, then *dx contains dual ray + Return code: same + */ + virtual int dualPivotResult(int &colIn, int &sign, + int colOut, int outStatus, + double &t, CoinPackedVector *dx); + //@} + + //--------------------------------------------------------------------------- + + ///@name Constructors and destructors + //@{ + /// Default Constructor + OsiSolverInterface(); + + /** Clone + + The result of calling clone(false) is defined to be equivalent to + calling the default constructor OsiSolverInterface(). + */ + virtual OsiSolverInterface *clone(bool copyData = true) const = 0; + + /// Copy constructor + OsiSolverInterface(const OsiSolverInterface &); + + /// Assignment operator + OsiSolverInterface &operator=(const OsiSolverInterface &rhs); + + /// Destructor + virtual ~OsiSolverInterface(); + + /** Reset the solver interface. + + A call to reset() returns the solver interface to the same state as + it would have if it had just been constructed by calling the default + constructor OsiSolverInterface(). + */ + virtual void reset(); + //@} + + //--------------------------------------------------------------------------- + +protected: + ///@name Protected methods + //@{ + /** Apply a row cut (append to the constraint matrix). */ + virtual void applyRowCut(const OsiRowCut &rc) = 0; + + /** Apply a column cut (adjust the bounds of one or more variables). */ + virtual void applyColCut(const OsiColCut &cc) = 0; + + /** A quick inlined function to convert from the lb/ub style of + constraint definition to the sense/rhs/range style */ + inline void + convertBoundToSense(const double lower, const double upper, + char &sense, double &right, double &range) const; + /** A quick inlined function to convert from the sense/rhs/range style + of constraint definition to the lb/ub style */ + inline void + convertSenseToBound(const char sense, const double right, + const double range, + double &lower, double &upper) const; + /** A quick inlined function to force a value to be between a minimum and + a maximum value */ + template < class T > + inline T + forceIntoRange(const T value, const T lower, const T upper) const + { + return value < lower ? lower : (value > upper ? upper : value); + } + /** Set OsiSolverInterface object state for default constructor + + This routine establishes the initial values of data fields in the + OsiSolverInterface object when the object is created using the + default constructor. + */ + void setInitialData(); + //@} + + ///@name Protected member data + //@{ + /*! \brief Pointer to row cut debugger object + + Mutable so that we can update the solution held in the debugger while + maintaining const'ness for the Osi object. + */ + mutable OsiRowCutDebugger *rowCutDebugger_; + // Why not just make useful stuff protected? + /// Message handler + CoinMessageHandler *handler_; + /** Flag to say if the currrent handler is the default handler. + Indicates if the solver interface object is responsible + for destruction of the handler (true) or if the client is + responsible (false). + */ + bool defaultHandler_; + /// Messages + CoinMessages messages_; + /// Number of integers + int numberIntegers_; + /// Total number of objects + int numberObjects_; + + /// Integer and ... information (integer info normally at beginning) + OsiObject **object_; + /** Column type + 0 - continuous + 1 - binary (may get fixed later) + 2 - general integer (may get fixed later) + 3 - if supported - semi-continuous + 4 - if supported - semi-continuous integer + */ + mutable char *columnType_; + + //@} + + //--------------------------------------------------------------------------- + +private: + ///@name Private member data + //@{ + /// Pointer to user-defined data structure - and more if user wants + OsiAuxInfo *appDataEtc_; + /// Array of integer parameters + int intParam_[OsiLastIntParam]; + /// Array of double parameters + double dblParam_[OsiLastDblParam]; + /// Array of string parameters + std::string strParam_[OsiLastStrParam]; + /// Array of hint parameters + bool hintParam_[OsiLastHintParam]; + /// Array of hint strengths + OsiHintStrength hintStrength_[OsiLastHintParam]; + /** Warm start information used for hot starts when the default + hot start implementation is used. */ + CoinWarmStart *ws_; + /// Column solution satisfying lower and upper column bounds + std::vector< double > strictColSolution_; + + /// Row names + OsiNameVec rowNames_; + /// Column names + OsiNameVec colNames_; + /// Objective name + std::string objName_; + + //@} +}; + +//############################################################################# +/** A quick inlined function to convert from the lb/ub style of constraint + definition to the sense/rhs/range style */ +inline void +OsiSolverInterface::convertBoundToSense(const double lower, const double upper, + char &sense, double &right, + double &range) const +{ + double inf = getInfinity(); + range = 0.0; + if (lower > -inf) { + if (upper < inf) { + right = upper; + if (upper == lower) { + sense = 'E'; + } else { + sense = 'R'; + range = upper - lower; + } + } else { + sense = 'G'; + right = lower; + } + } else { + if (upper < inf) { + sense = 'L'; + right = upper; + } else { + sense = 'N'; + right = 0.0; + } + } +} + +//----------------------------------------------------------------------------- +/** A quick inlined function to convert from the sense/rhs/range style of + constraint definition to the lb/ub style */ +inline void +OsiSolverInterface::convertSenseToBound(const char sense, const double right, + const double range, + double &lower, double &upper) const +{ + double inf = getInfinity(); + switch (sense) { + case 'E': + lower = upper = right; + break; + case 'L': + lower = -inf; + upper = right; + break; + case 'G': + lower = right; + upper = inf; + break; + case 'R': + lower = right - range; + upper = right; + break; + case 'N': + lower = -inf; + upper = inf; + break; + } +} + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverParameters.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverParameters.hpp new file mode 100644 index 000000000..03209a8dd --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiSolverParameters.hpp @@ -0,0 +1,144 @@ +// Copyright (C) 2000, International Business Machines +// Corporation and others. All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +#ifndef OsiSolverParameters_H +#define OsiSolverParameters_H + +enum OsiIntParam { + /*! \brief Iteration limit for initial solve and resolve. + + The maximum number of iterations (whatever that means for the given + solver) the solver can execute in the OsiSolverinterface::initialSolve() + and OsiSolverinterface::resolve() methods before terminating. + */ + OsiMaxNumIteration = 0, + /*! \brief Iteration limit for hot start + + The maximum number of iterations (whatever that means for the given + solver) the solver can execute in the + OsiSolverinterface::solveFromHotStart() method before terminating. + */ + OsiMaxNumIterationHotStart, + /*! \brief Handling of row and column names. + + The name discipline specifies how the solver will handle row and column + names: + - 0: Auto names: Names cannot be set by the client. Names of the form + Rnnnnnnn or Cnnnnnnn are generated on demand when a name for a + specific row or column is requested; nnnnnnn is derived from the row + or column index. Requests for a vector of names return a vector with + zero entries. + - 1: Lazy names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to the largest index of a name supplied by the client; + some entries in the vector may be null strings. + - 2: Full names: Names supplied by the client are retained. Names of the + form Rnnnnnnn or Cnnnnnnn are generated on demand if no name has been + supplied by the client. Requests for a vector of names return a + vector sized to match the constraint system, and all entries will + contain either the name specified by the client or a generated name. + */ + OsiNameDiscipline, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + integer parameters. + */ + OsiLastIntParam +}; + +enum OsiDblParam { + /*! \brief Dual objective limit. + + This is to be used as a termination criteria in algorithms where the dual + objective changes monotonically (e.g., dual simplex, volume algorithm). + */ + OsiDualObjectiveLimit = 0, + /*! \brief Primal objective limit. + + This is to be used as a termination criteria in algorithms where the + primal objective changes monotonically (e.g., primal simplex) + */ + OsiPrimalObjectiveLimit, + /*! \brief Dual feasibility tolerance. + + The maximum amount a dual constraint can be violated and still be + considered feasible. + */ + OsiDualTolerance, + /*! \brief Primal feasibility tolerance. + + The maximum amount a primal constraint can be violated and still be + considered feasible. + */ + OsiPrimalTolerance, + /** The value of any constant term in the objective function. */ + OsiObjOffset, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + double parameters. + */ + OsiLastDblParam +}; + +enum OsiStrParam { + /*! \brief The name of the loaded problem. + + This is the string specified on the Name card of an mps file. + */ + OsiProbName = 0, + /*! \brief The name of the solver. + + This parameter is read-only. + */ + OsiSolverName, + /*! \brief End marker. + + Used by OsiSolverInterface to allocate a fixed-sized array to store + string parameters. + */ + OsiLastStrParam +}; + +enum OsiHintParam { + /** Whether to do a presolve in initialSolve */ + OsiDoPresolveInInitial = 0, + /** Whether to use a dual algorithm in initialSolve. + The reverse is to use a primal algorithm */ + OsiDoDualInInitial, + /** Whether to do a presolve in resolve */ + OsiDoPresolveInResolve, + /** Whether to use a dual algorithm in resolve. + The reverse is to use a primal algorithm */ + OsiDoDualInResolve, + /** Whether to scale problem */ + OsiDoScale, + /** Whether to create a non-slack basis (only in initialSolve) */ + OsiDoCrash, + /** Whether to reduce amount of printout, e.g., for branch and cut */ + OsiDoReducePrint, + /** Whether we are in branch and cut - so can modify behavior */ + OsiDoInBranchAndCut, + /** Just a marker, so that OsiSolverInterface can allocate a static sized + array to store parameters. */ + OsiLastHintParam +}; + +enum OsiHintStrength { + /** Ignore hint (default) */ + OsiHintIgnore = 0, + /** This means it is only a hint */ + OsiHintTry, + /** This means do hint if at all possible */ + OsiHintDo, + /** And this means throw an exception if not possible */ + OsiForceDo +}; + +#endif + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiUnitTests.hpp b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiUnitTests.hpp new file mode 100644 index 000000000..ac3366ccf --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/include/coin/OsiUnitTests.hpp @@ -0,0 +1,390 @@ +// Copyright (C) 2010 +// All Rights Reserved. +// This code is licensed under the terms of the Eclipse Public License (EPL). + +/*! \file OsiUnitTests.hpp + + Utility methods for OSI unit tests. +*/ + +#ifndef OSISOLVERINTERFACETEST_HPP_ +#define OSISOLVERINTERFACETEST_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include + +class OsiSolverInterface; +class CoinPackedVectorBase; + +/** A function that tests that a lot of problems given in MPS files (mostly the NETLIB problems) solve properly with all the specified solvers. + * + * The routine creates a vector of NetLib problems (problem name, objective, + * various other characteristics), and a vector of solvers to be tested. + * + * Each solver is run on each problem. The run is deemed successful if the + * solver reports the correct problem size after loading and returns the + * correct objective value after optimization. + + * If multiple solvers are available, the results are compared pairwise against + * the results reported by adjacent solvers in the solver vector. Due to + * limitations of the volume solver, it must be the last solver in vecEmptySiP. + */ +void OsiSolverInterfaceMpsUnitTest(const std::vector< OsiSolverInterface * > &vecEmptySiP, + const std::string &mpsDir); + +/** A function that tests the methods in the OsiSolverInterface class. + * Some time ago, if this method is compiled with optimization, + * the compilation took 10-15 minutes and the machine pages (has 256M core memory!)... + */ +void OsiSolverInterfaceCommonUnitTest(const OsiSolverInterface *emptySi, + const std::string &mpsDir, + const std::string &netlibDir); + +/** A function that tests the methods in the OsiColCut class. */ +void OsiColCutUnitTest(const OsiSolverInterface *baseSiP, + const std::string &mpsDir); + +/** A function that tests the methods in the OsiRowCut class. */ +void OsiRowCutUnitTest(const OsiSolverInterface *baseSiP, + const std::string &mpsDir); + +/** A function that tests the methods in the OsiRowCutDebugger class. */ +void OsiRowCutDebuggerUnitTest(const OsiSolverInterface *siP, + const std::string &mpsDir); + +/** A function that tests the methods in the OsiCuts class. */ +void OsiCutsUnitTest(); + +/// A namespace so we can define a few `global' variables to use during tests. +namespace OsiUnitTest { + +class TestOutcomes; + +/*! \brief Verbosity level of unit tests + + 0 (default) for minimal output; larger numbers produce more output +*/ +extern unsigned int verbosity; + +/*! \brief Behaviour on failing a test + + - 0 (= default) continue + - 1 press any key to continue + - 2 stop with abort() +*/ +extern unsigned int haltonerror; + +/*! \brief Test outcomes + + A global TestOutcomes object to store test outcomes during the run of the unit test + for an OSI. + */ +extern TestOutcomes outcomes; + +/*! \brief Print an error message + + Formatted as "XxxSolverInterface testing issue: message" where Xxx is the string + provided as \p solverName. + + Flushes std::cout before printing to std::cerr. +*/ +void failureMessage(const std::string &solverName, + const std::string &message); +/// \overload +void failureMessage(const OsiSolverInterface &si, + const std::string &message); + +/*! \brief Print an error message, specifying the test name and condition + + Formatted as "XxxSolverInterface testing issue: testname failed: testcond" where + Xxx is the OsiStrParam::OsiSolverName parameter of the \p si. + Flushes std::cout before printing to std::cerr. +*/ +void failureMessage(const std::string &solverName, + const std::string &testname, const std::string &testcond); + +/// \overload +void failureMessage(const OsiSolverInterface &si, + const std::string &testname, const std::string &testcond); + +/*! \brief Print a message. + + Prints the message as given. Flushes std::cout before printing to std::cerr. +*/ +void testingMessage(const char *const msg); + +/*! \brief Utility method to check equality + + Tests for equality using CoinRelFltEq with tolerance \p tol. Understands the + notion of solver infinity and obtains the value for infinity from the solver + interfaces supplied as parameters. +*/ +bool equivalentVectors(const OsiSolverInterface *si1, + const OsiSolverInterface *si2, + double tol, const double *v1, const double *v2, int size); + +/*! \brief Compare two problems for equality + + Compares the problems held in the two solvers: constraint matrix, row and column + bounds, column type, and objective. Rows are checked using upper and lower bounds + and using sense, bound, and range. +*/ +bool compareProblems(OsiSolverInterface *osi1, OsiSolverInterface *osi2); + +/*! \brief Compare a packed vector with an expanded vector + + Checks that all values present in the packed vector are present in the full vector + and checks that there are no extra entries in the full vector. Uses CoinRelFltEq + with the default tolerance. +*/ +bool isEquivalent(const CoinPackedVectorBase &pv, int n, const double *fv); + +/*! \brief Process command line parameters. + + An unrecognised keyword which is not in the \p ignorekeywords map will trigger the + help message and a return value of false. For each keyword in \p ignorekeywords, you + can specify the number of following parameters that should be ignored. + + This should be replaced with the one of the standard CoinUtils parameter mechanisms. + */ +bool processParameters(int argc, const char **argv, + std::map< std::string, std::string > &parms, + const std::map< std::string, int > &ignorekeywords = std::map< std::string, int >()); + +/// A single test outcome record. +class TestOutcome { +public: + /// Test result + typedef enum { + NOTE = 0, + PASSED = 1, + WARNING = 2, + ERROR = 3, + LAST = 4 + } SeverityLevel; + /// Print strings for SeverityLevel + static std::string SeverityLevelName[LAST]; + /// Name of component under test + std::string component; + /// Name of test + std::string testname; + /// Condition being tested + std::string testcond; + /// Test result + SeverityLevel severity; + /// Set to true if problem is expected + bool expected; + /// Name of code file where test executed + std::string filename; + /// Line number in code file where test executed + int linenumber; + /// Standard constructor + TestOutcome(const std::string &comp, const std::string &tst, + const char *cond, SeverityLevel sev, + const char *file, int line, bool exp = false) + : component(comp) + , testname(tst) + , testcond(cond) + , severity(sev) + , expected(exp) + , filename(file) + , linenumber(line) + { + } + /// Print the test outcome + void print() const; +}; + +/// Utility class to maintain a list of test outcomes. +class TestOutcomes : public std::list< TestOutcome > { +public: + /// Add an outcome to the list + void add(std::string comp, std::string tst, const char *cond, + TestOutcome::SeverityLevel sev, const char *file, int line, + bool exp = false) + { + push_back(TestOutcome(comp, tst, cond, sev, file, line, exp)); + } + + /*! \brief Add an outcome to the list + + Get the component name from the solver interface. + */ + void add(const OsiSolverInterface &si, std::string tst, const char *cond, + TestOutcome::SeverityLevel sev, const char *file, int line, + bool exp = false); + /// Print the list of outcomes + void print() const; + /*! \brief Count total and expected outcomes at given severity level + + Given a severity level, walk the list of outcomes and count the total number + of outcomes at this severity level and the number expected. + */ + void getCountBySeverity(TestOutcome::SeverityLevel sev, + int &total, int &expected) const; +}; + +/// Convert parameter to a string (stringification) +#define OSIUNITTEST_QUOTEME_(x) #x +/// Convert to string with one level of expansion of the parameter +#define OSIUNITTEST_QUOTEME(x) OSIUNITTEST_QUOTEME_(x) + +template < typename Component > +bool OsiUnitTestAssertSeverityExpected( + bool condition, const char *condition_str, const char *filename, + int line, const Component &component, const std::string &testname, + TestOutcome::SeverityLevel severity, bool expected) +{ + if (condition) { + OsiUnitTest::outcomes.add(component, testname, condition_str, + OsiUnitTest::TestOutcome::PASSED, filename, line, false); + if (OsiUnitTest::verbosity >= 2) { + std::ostringstream successmsg; + successmsg << __FILE__ << ":" << __LINE__ << ": " << testname + << " (condition \'" << condition_str << "\') passed.\n"; + OsiUnitTest::testingMessage(successmsg.str().c_str()); + } + return true; + } + OsiUnitTest::outcomes.add(component, testname, condition_str, + severity, filename, line, expected); + OsiUnitTest::failureMessage(component, testname, condition_str); + switch (OsiUnitTest::haltonerror) { + case 2: { + if (severity >= OsiUnitTest::TestOutcome::ERROR) + std::abort(); + break; + } + case 1: { + std::cout << std::endl + << "press any key to continue..." << std::endl; + std::getchar(); + break; + } + default:; + } + return false; +} + +/// Add a test outcome to the list held in OsiUnitTest::outcomes +#define OSIUNITTEST_ADD_OUTCOME(component, testname, testcondition, severity, expected) \ + OsiUnitTest::outcomes.add(component, testname, testcondition, severity, \ + __FILE__, __LINE__, expected) +/*! \brief Test for a condition and record the result + + Test \p condition and record the result in OsiUnitTest::outcomes. + If it succeeds, record the result as OsiUnitTest::TestOutcome::PASSED and print + a message for OsiUnitTest::verbosity >= 2. + If it fails, record the test as failed with \p severity and \p expected and + react as specified by OsiUnitTest::haltonerror. + + \p failurecode is executed when failure is not fatal. +*/ +#define OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition, failurecode, component, \ + testname, severity, expected) \ + { \ + if (!OsiUnitTestAssertSeverityExpected(condition, #condition, \ + __FILE__, __LINE__, component, testname, severity, expected)) { \ + failurecode; \ + } \ + } + +/*! \brief Perform a test with severity OsiUnitTest::TestOutcome::ERROR, failure not + expected. +*/ +#define OSIUNITTEST_ASSERT_ERROR(condition, failurecode, component, testname) \ + OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition, failurecode, component, testname, \ + OsiUnitTest::TestOutcome::ERROR, false) + +/*! \brief Perform a test with severity OsiUnitTest::TestOutcome::WARNING, failure + not expected. +*/ +#define OSIUNITTEST_ASSERT_WARNING(condition, failurecode, component, testname) \ + OSIUNITTEST_ASSERT_SEVERITY_EXPECTED(condition, failurecode, component, testname, \ + OsiUnitTest::TestOutcome::WARNING, false) + +/*! \brief Perform a test surrounded by a try/catch block + + \p trycode is executed in a try/catch block; if there's no throw the test is deemed + to have succeeded and is recorded in OsiUnitTest::outcomes with status + OsiUnitTest::TestOutcome::PASSED. If the \p trycode throws a CoinError, the failure + is recorded with status \p severity and \p expected and the value of + OsiUnitTest::haltonerror is consulted. If the failure is not fatal, \p catchcode is + executed. If any other error is thrown, the failure is recorded as for a CoinError + and \p catchcode is executed (haltonerror is not consulted). +*/ +#define OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, \ + severity, expected) \ + { \ + try { \ + trycode; \ + OSIUNITTEST_ADD_OUTCOME(component, testname, #trycode " did not throw exception", \ + OsiUnitTest::TestOutcome::PASSED, false); \ + if (OsiUnitTest::verbosity >= 2) { \ + std::string successmsg(__FILE__ ":" OSIUNITTEST_QUOTEME(__LINE__) ": "); \ + successmsg = successmsg + testname; \ + successmsg = successmsg + " (code \'" #trycode "\') did not throw exception"; \ + successmsg = successmsg + ".\n"; \ + OsiUnitTest::testingMessage(successmsg.c_str()); \ + } \ + } catch (CoinError & e) { \ + std::stringstream errmsg; \ + errmsg << #trycode " threw CoinError: " << e.message(); \ + if (e.className().length() > 0) \ + errmsg << " in " << e.className(); \ + if (e.methodName().length() > 0) \ + errmsg << " in " << e.methodName(); \ + if (e.lineNumber() >= 0) \ + errmsg << " at " << e.fileName() << ":" << e.lineNumber(); \ + OSIUNITTEST_ADD_OUTCOME(component, testname, errmsg.str().c_str(), \ + severity, expected); \ + OsiUnitTest::failureMessage(component, testname, errmsg.str().c_str()); \ + switch (OsiUnitTest::haltonerror) { \ + case 2: { \ + if (severity >= OsiUnitTest::TestOutcome::ERROR) \ + abort(); \ + break; \ + } \ + case 1: { \ + std::cout << std::endl \ + << "press any key to continue..." << std::endl; \ + getchar(); \ + break; \ + } \ + default:; \ + } \ + catchcode; \ + } catch (...) { \ + std::string errmsg; \ + errmsg = #trycode; \ + errmsg = errmsg + " threw unknown exception"; \ + OSIUNITTEST_ADD_OUTCOME(component, testname, errmsg.c_str(), severity, false); \ + OsiUnitTest::failureMessage(component, testname, errmsg.c_str()); \ + catchcode; \ + } \ + } + +/*! \brief Perform a try/catch test with severity OsiUnitTest::TestOutcome::ERROR, + failure not expected. +*/ +#define OSIUNITTEST_CATCH_ERROR(trycode, catchcode, component, testname) \ + OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::ERROR, false) + +/*! \brief Perform a try/catch test with severity OsiUnitTest::TestOutcome::WARNING, + failure not expected. +*/ +#define OSIUNITTEST_CATCH_WARNING(trycode, catchcode, component, testname) \ + OSIUNITTEST_CATCH_SEVERITY_EXPECTED(trycode, catchcode, component, testname, OsiUnitTest::TestOutcome::WARNING, false) + +} // end namespace OsiUnitTest + +#endif /*OSISOLVERINTERFACETEST_HPP_*/ + +/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 +*/ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.a new file mode 100644 index 000000000..5ecba8a48 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.la new file mode 100755 index 000000000..ac65d50ab --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbc.la @@ -0,0 +1,35 @@ +# libCbc.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libCbc.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/usr/lib/ -lnauty -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libCgl.la /home/runner/work/Cbc/Cbc/dist/lib/libOsiClp.la /home/runner/work/Cbc/Cbc/dist/lib/libClpSolver.la /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libCbc. +current=13 +age=10 +revision=12 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.a new file mode 100644 index 000000000..8d7355600 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.la new file mode 100755 index 000000000..a3bf4bc41 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCbcSolver.la @@ -0,0 +1,35 @@ +# libCbcSolver.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libCbcSolver.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/usr/lib/ -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libCbc.la -lnauty /home/runner/work/Cbc/Cbc/dist/lib/libCgl.la /home/runner/work/Cbc/Cbc/dist/lib/libOsiClp.la /home/runner/work/Cbc/Cbc/dist/lib/libClpSolver.la /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libCbcSolver. +current=13 +age=10 +revision=12 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.a new file mode 100644 index 000000000..57a81f0bc Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.la new file mode 100755 index 000000000..cf9997fe9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCgl.la @@ -0,0 +1,35 @@ +# libCgl.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libCgl.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libOsiClp.la /home/runner/work/Cbc/Cbc/dist/lib/libClpSolver.la /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libCgl. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.a new file mode 100644 index 000000000..593eb36c1 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.la new file mode 100755 index 000000000..10b3b0c92 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClp.la @@ -0,0 +1,35 @@ +# libClp.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libClp.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libClp. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.a new file mode 100644 index 000000000..50f4f6c6c Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.la new file mode 100755 index 000000000..e3c68602c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libClpSolver.la @@ -0,0 +1,35 @@ +# libClpSolver.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libClpSolver.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libClpSolver. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.a new file mode 100644 index 000000000..d8b36fe74 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.la new file mode 100755 index 000000000..7e2bba4cc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libCoinUtils.la @@ -0,0 +1,35 @@ +# libCoinUtils.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libCoinUtils.a' + +# Libraries that this one depends upon. +dependency_libs=' -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libCoinUtils. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.a new file mode 100644 index 000000000..58cce0f51 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.la new file mode 100755 index 000000000..f62332521 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsi.la @@ -0,0 +1,35 @@ +# libOsi.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libOsi.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libOsi. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.a new file mode 100644 index 000000000..19bcd154e Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.la new file mode 100755 index 000000000..00e72fc27 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCbc.la @@ -0,0 +1,35 @@ +# libOsiCbc.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libOsiCbc.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/usr/lib/ -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libCbc.la -lnauty /home/runner/work/Cbc/Cbc/dist/lib/libCgl.la /home/runner/work/Cbc/Cbc/dist/lib/libOsiClp.la /home/runner/work/Cbc/Cbc/dist/lib/libClpSolver.la /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libOsiCbc. +current=13 +age=10 +revision=12 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.a new file mode 100644 index 000000000..b7b3c2944 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.la new file mode 100755 index 000000000..ce3b454ae --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiClp.la @@ -0,0 +1,35 @@ +# libOsiClp.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libOsiClp.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libClp.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libOsiClp. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.a b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.a new file mode 100644 index 000000000..f6969796f Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.a differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.la b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.la new file mode 100755 index 000000000..5fe96e4fb --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/libOsiCommonTests.la @@ -0,0 +1,35 @@ +# libOsiCommonTests.la - a libtool library file +# Generated by ltmain.sh - GNU libtool 1.5.22 (1.1220.2.365 2005/12/18 22:14:06) +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='' + +# Names of this library. +library_names='' + +# The name of the static archive. +old_library='libOsiCommonTests.a' + +# Libraries that this one depends upon. +dependency_libs=' -L/home/runner/work/Cbc/Cbc/dist/lib /home/runner/work/Cbc/Cbc/dist/lib/libOsi.la /home/runner/work/Cbc/Cbc/dist/lib/libCoinUtils.la -lbz2 -lz -llapack -lgfortran -lquadmath -lblas' + +# Version information for libOsiCommonTests. +current=0 +age=0 +revision=0 + +# Is this an already installed library? +installed=yes + +# Should we warn about portability when linking against -modules? +shouldnotlink=no + +# Files to dlopen/dlpreopen +dlopen='' +dlpreopen='' + +# Directory that this library needs to be installed in: +libdir='/home/runner/work/Cbc/Cbc/dist/lib' diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cbc.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cbc.pc new file mode 100644 index 000000000..e750ebaf1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cbc.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: CBC +Description: COIN-OR Branch and Cut +URL: https://projects.coin-or.org/Cbc +Version: 2.10.12 +Libs: -L${libdir} -lCbcSolver -lCbc -L/usr/lib/ -lnauty +Cflags: -I${includedir} +Requires: clp osi-clp cgl osi coinutils diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cgl.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cgl.pc new file mode 100644 index 000000000..ec06d9a86 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/cgl.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: CGL +Description: COIN-OR Cut Generation Library +URL: https://projects.coin-or.org/Cgl +Version: 0.60 +Libs: -L${libdir} -lCgl +Cflags: -I${includedir} +Requires: osi-clp clp osi coinutils diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/clp.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/clp.pc new file mode 100644 index 000000000..e151795e8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/clp.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: CLP +Description: COIN-OR Linear Programming Solver +URL: https://projects.coin-or.org/Clp +Version: 1.17 +Libs: -L${libdir} -lClpSolver -lClp +Cflags: -I${includedir} +Requires: coinutils diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatamiplib3.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatamiplib3.pc new file mode 100644 index 000000000..ad47475f4 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatamiplib3.pc @@ -0,0 +1,9 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +datadir=${prefix}/share/coin/Data/miplib3 + +Name: Miplib3 +Description: MIPLIB3 models +URL: https://projects.coin-or.org/svn/Data/miplib3 +Version: 1.2 +Libs: +Cflags: diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatasample.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatasample.pc new file mode 100644 index 000000000..5bccce69e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coindatasample.pc @@ -0,0 +1,9 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +datadir=${prefix}/share/coin/Data/Sample + +Name: Sample +Description: Sample models +URL: https://projects.coin-or.org/svn/Data/Sample +Version: 1.2 +Libs: +Cflags: diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coinutils.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coinutils.pc new file mode 100644 index 000000000..e236dd0af --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/coinutils.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: CoinUtils +Description: COIN-OR Utilities +URL: https://projects.coin-or.org/CoinUtils +Version: 2.11 +Libs: -L${libdir} -lCoinUtils -lbz2 -lz -llapack -lblas -lgfortran -lquadmath -lm -lblas -lblas -lm +Cflags: -I${includedir} +Requires: diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-cbc.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-cbc.pc new file mode 100644 index 000000000..cd02854a6 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-cbc.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: OsiCbc +Description: COIN-OR Open Solver Interface for CBC +URL: https://projects.coin-or.org/Osi +Version: 2.10.12 +Libs: -L${libdir} -lOsiCbc +Cflags: -I${includedir} +Requires: cbc diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-clp.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-clp.pc new file mode 100644 index 000000000..118499f66 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-clp.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: OsiClp +Description: COIN-OR Open Solver Interface for CLP +URL: https://projects.coin-or.org/Osi +Version: 1.17 +Libs: -L${libdir} -lOsiClp +Cflags: -I${includedir} +Requires: clp osi diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-unittests.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-unittests.pc new file mode 100644 index 000000000..d93123e2b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi-unittests.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: OsiUnitTests +Description: COIN-OR Open Solver Interface Common Unit Tests +URL: https://projects.coin-or.org/Osi +Version: 0.108 +Libs: -L${libdir} -lOsiCommonTests +Cflags: -I${includedir} +Requires: osi diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi.pc b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi.pc new file mode 100644 index 000000000..024bac746 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/lib/pkgconfig/osi.pc @@ -0,0 +1,12 @@ +prefix=/home/runner/work/Cbc/Cbc/dist +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include/coin + +Name: Osi +Description: COIN-OR Open Solver Interface +URL: https://projects.coin-or.org/Osi +Version: 0.108 +Libs: -L${libdir} -lOsi +Cflags: -I${includedir} +Requires: coinutils diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/afiro.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/afiro.mps new file mode 100644 index 000000000..26002a3ce --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/afiro.mps @@ -0,0 +1,83 @@ +NAME AFIRO +ROWS + E R09 + E R10 + L X05 + L X21 + E R12 + E R13 + L X17 + L X18 + L X19 + L X20 + E R19 + E R20 + L X27 + L X44 + E R22 + E R23 + L X40 + L X41 + L X42 + L X43 + L X45 + L X46 + L X47 + L X48 + L X49 + L X50 + L X51 + N COST +COLUMNS + X01 X48 .301 R09 -1. + X01 R10 -1.06 X05 1. + X02 X21 -1. R09 1. + X02 COST -.4 + X03 X46 -1. R09 1. + X04 X50 1. R10 1. + X06 X49 .301 R12 -1. + X06 R13 -1.06 X17 1. + X07 X49 .313 R12 -1. + X07 R13 -1.06 X18 1. + X08 X49 .313 R12 -1. + X08 R13 -.96 X19 1. + X09 X49 .326 R12 -1. + X09 R13 -.86 X20 1. + X10 X45 2.364 X17 -1. + X11 X45 2.386 X18 -1. + X12 X45 2.408 X19 -1. + X13 X45 2.429 X20 -1. + X14 X21 1.4 R12 1. + X14 COST -.32 + X15 X47 -1. R12 1. + X16 X51 1. R13 1. + X22 X46 .109 R19 -1. + X22 R20 -.43 X27 1. + X23 X44 -1. R19 1. + X23 COST -.6 + X24 X48 -1. R19 1. + X25 X45 -1. R19 1. + X26 X50 1. R20 1. + X28 X47 .109 R22 -.43 + X28 R23 1. X40 1. + X29 X47 .108 R22 -.43 + X29 R23 1. X41 1. + X30 X47 .108 R22 -.39 + X30 R23 1. X42 1. + X31 X47 .107 R22 -.37 + X31 R23 1. X43 1. + X32 X45 2.191 X40 -1. + X33 X45 2.219 X41 -1. + X34 X45 2.249 X42 -1. + X35 X45 2.279 X43 -1. + X36 X44 1.4 R23 -1. + X36 COST -.48 + X37 X49 -1. R23 1. + X38 X51 1. R22 1. + X39 R23 1. COST 10. +RHS + B X50 310. X51 300. + B X05 80. X17 80. + B X27 500. R23 44. + B X40 500. +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.cor b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.cor new file mode 100644 index 000000000..c0e0b9ebf --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.cor @@ -0,0 +1,139 @@ +NAME APP +ROWS + N COST + L K01 + L K02 + L K03 + L K04 + L K05 + E D00101 + E D00201 + E D00301 + E D00401 + E D00102 + E D00202 + E D00302 + E D00402 + E D00103 + E D00203 + E D00303 + E D00403 + E D00104 + E D00204 + E D00304 + E D00404 + E D00105 + E D00205 + E D00305 + E D00405 +COLUMNS + X00101 K01 1 D00101 1. + X00201 K01 1 D00201 1. + X00301 K01 1 D00301 1. + X00401 K01 1 D00401 1. + X00102 K02 1 D00102 1. + X00202 K02 1 D00202 1. + X00302 K02 1 D00302 1. + X00402 K02 1 D00402 1. + X00103 K03 1 D00103 1. + X00203 K03 1 D00203 1. + X00303 K03 1 D00303 1. + X00403 K03 1 D00403 1. + X00104 K04 1 D00104 1. + X00204 K04 1 D00204 1. + X00304 K04 1 D00304 1. + X00404 K04 1 D00404 1. + X00105 K05 1 D00105 1. + X00205 K05 1 D00205 1. + X00305 K05 1 D00305 1. + X00405 K05 1 D00405 1. + I00101 COST 1 D00101 -1. + I00101 D00102 1. + Y00101 COST 2 D00101 1. + I00201 COST 2 D00201 -1. + I00201 D00202 1. + Y00201 COST 3 D00201 1. + I00301 COST 3 D00301 -1. + I00301 D00302 1. + Y00301 COST 2 D00301 1. + I00401 COST 4 D00401 -1. + I00401 D00402 1. + Y00401 COST 5 D00401 1. + INT1 'MARKER' 'INTORG' + I00102 COST 1 D00102 -1. + I00102 D00103 1. + Y00102 COST 2 D00102 1. + I00202 COST 2 D00202 -1. + I00202 D00203 1. + Y00202 COST 3 D00202 1. + INT1END 'MARKER' 'INTEND' + I00302 COST 3 D00302 -1. + I00302 D00303 1. + Y00302 COST 2 D00302 1. + I00402 COST 4 D00402 -1. + I00402 D00403 1. + Y00402 COST 5 D00402 1. + I00103 COST 1 D00103 -1. + I00103 D00104 1. + Y00103 COST 2 D00103 1. + I00203 COST 2 D00203 -1. + I00203 D00204 1. + Y00203 COST 3 D00203 1. + I00303 COST 3 D00303 -1. + I00303 D00304 1. + Y00303 COST 2 D00303 1. + I00403 COST 4 D00403 -1. + I00403 D00404 1. + Y00403 COST 5 D00403 1. + I00104 COST 1 D00104 -1. + I00104 D00105 1. + Y00104 COST 2 D00104 1. + I00204 COST 2 D00204 -1. + I00204 D00205 1. + Y00204 COST 3 D00204 1. + I00304 COST 3 D00304 -1. + I00304 D00305 1. + Y00304 COST 2 D00304 1. + I00404 COST 4 D00404 -1. + I00404 D00405 1. + Y00404 COST 5 D00404 1. + I00105 COST 1 D00105 -1. + Y00105 COST 2 D00105 1. + I00205 COST 2 D00205 -1. + Y00205 COST 3 D00205 1. + I00305 COST 3 D00305 -1. + Y00305 COST 2 D00305 1. + I00405 COST 4 D00405 -1. + Y00405 COST 5 D00405 1. +RHS + RHS K01 3 + RHS K02 6 + RHS K03 10 + RHS K04 2000 + RHS K05 18 + RHS D00101 1.000 + RHS D00201 1.000 + RHS D00301 1.000 + RHS D00401 1.000 + RHS D00102 2.667 + RHS D00202 1.667 + RHS D00302 2.667 + RHS D00402 3.333 + RHS D00103 2.667 + RHS D00203 2.000 + RHS D00303 3.000 + RHS D00403 3.000 + RHS D00104 2.667 + RHS D00204 2.667 + RHS D00304 2.667 + RHS D00404 2.667 + RHS D00105 2.667 + RHS D00205 2.333 + RHS D00305 2.333 + RHS D00405 2.333 +BOUNDS + UP BOUND1 I00102 51.000000 + UP BOUND1 Y00102 51.000000 + UP BOUND1 Y00202 51.000000 + UP BOUND1 I00202 51.000000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.stoch b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.stoch new file mode 100644 index 000000000..3d98234e9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.stoch @@ -0,0 +1,132 @@ +NAME APP +SCENARIOS DISCRETE ADD + SC SCEN01 ROOT 0.111 STAGE-2 + RHS D00102 -0.667 + RHS D00202 -0.667 + RHS D00302 -0.667 + RHS D00402 -1.333 + RHS D00103 0.333 + RHS D00203 -1.000 + RHS D00303 0.000 + RHS D00403 -1.000 + RHS D00104 1.333 + RHS D00204 -1.667 + RHS D00304 1.333 + RHS D00404 -0.667 + RHS D00105 2.333 + RHS D00205 -1.333 + RHS D00305 2.667 + RHS D00405 -0.333 + SC SCEN02 SCEN01 0.111 STAGE-3 + RHS D00103 -0.667 + RHS D00203 1.000 + RHS D00303 0.000 + RHS D00403 0.000 + RHS D00104 -0.667 + RHS D00204 -0.667 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -0.667 + RHS D00205 -1.333 + RHS D00305 -1.333 + RHS D00405 0.667 + SC SCEN03 SCEN01 0.111 STAGE-3 + RHS D00103 0.333 + RHS D00203 0.000 + RHS D00303 0.000 + RHS D00403 1.000 + RHS D00104 -0.667 + RHS D00204 2.333 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -1.667 + RHS D00205 2.667 + RHS D00305 -1.333 + RHS D00405 -0.333 + SC SCEN04 ROOT 0.111 STAGE-2 + RHS D00102 -0.667 + RHS D00202 0.333 + RHS D00302 -0.667 + RHS D00402 -0.333 + RHS D00103 0.333 + RHS D00203 -1.000 + RHS D00303 0.000 + RHS D00403 -1.000 + RHS D00104 1.333 + RHS D00204 -1.667 + RHS D00304 1.333 + RHS D00404 -0.667 + RHS D00105 2.333 + RHS D00205 -1.333 + RHS D00305 2.667 + RHS D00405 -0.333 + SC SCEN05 SCEN04 0.111 STAGE-3 + RHS D00103 -0.667 + RHS D00203 1.000 + RHS D00303 0.000 + RHS D00403 0.000 + RHS D00104 -0.667 + RHS D00204 -0.667 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -0.667 + RHS D00205 -1.333 + RHS D00305 -1.333 + RHS D00405 0.667 + SC SCEN06 SCEN04 0.111 STAGE-3 + RHS D00103 0.333 + RHS D00203 0.000 + RHS D00303 0.000 + RHS D00403 1.000 + RHS D00104 -0.667 + RHS D00204 2.333 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -1.667 + RHS D00205 2.667 + RHS D00305 -1.333 + RHS D00405 -0.333 + SC SCEN07 ROOT 0.111 STAGE-2 + RHS D00102 1.333 + RHS D00202 0.333 + RHS D00302 1.333 + RHS D00402 1.667 + RHS D00103 0.333 + RHS D00203 -1.000 + RHS D00303 0.000 + RHS D00403 -1.000 + RHS D00104 1.333 + RHS D00204 -1.667 + RHS D00304 1.333 + RHS D00404 -0.667 + RHS D00105 2.333 + RHS D00205 -1.333 + RHS D00305 2.667 + RHS D00405 -0.333 + SC SCEN08 SCEN07 0.111 STAGE-3 + RHS D00103 -0.667 + RHS D00203 1.000 + RHS D00303 0.000 + RHS D00403 0.000 + RHS D00104 -0.667 + RHS D00204 -0.667 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -0.667 + RHS D00205 -1.333 + RHS D00305 -1.333 + RHS D00405 0.667 + SC SCEN09 SCEN07 0.111 STAGE-3 + RHS D00103 0.333 + RHS D00203 0.000 + RHS D00303 0.000 + RHS D00403 1.000 + RHS D00104 -0.667 + RHS D00204 2.333 + RHS D00304 -0.667 + RHS D00404 0.333 + RHS D00105 -1.667 + RHS D00205 2.667 + RHS D00305 -1.333 + RHS D00405 -0.333 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.time b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.time new file mode 100644 index 000000000..dfb2f2fe1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110.time @@ -0,0 +1,6 @@ +TIME APP +PERIODS LP + X00101 K01 ROOT + I00102 D00102 STAGE-2 + I00103 D00103 STAGE-3 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.cor b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.cor new file mode 100644 index 000000000..49daacd52 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.cor @@ -0,0 +1,125 @@ +NAME MYSMPS +ROWS + N OBJECTRW + L R0000001 + L R0000002 + L R0000003 + L R0000004 + L R0000005 + E R0000006 + E R0000007 + E R0000008 + E R0000009 + E R0000010 + E R0000011 + E R0000012 + E R0000013 + E R0000014 + E R0000015 + E R0000016 + E R0000017 + E R0000018 + E R0000019 + E R0000020 + E R0000021 + E R0000022 + E R0000023 + E R0000024 + E R0000025 +COLUMNS + C0000001 R0000001 1. R0000006 1. + C0000002 R0000001 1. R0000007 1. + C0000003 R0000001 1. R0000008 1. + C0000004 R0000001 1. R0000009 1. + C0000005 R0000002 1. R0000010 1. + C0000006 R0000002 1. R0000011 1. + C0000007 R0000002 1. R0000012 1. + C0000008 R0000002 1. R0000013 1. + C0000009 R0000003 1. R0000014 1. + C0000010 R0000003 1. R0000015 1. + C0000011 R0000003 1. R0000016 1. + C0000012 R0000003 1. R0000017 1. + C0000013 R0000004 1. R0000018 1. + C0000014 R0000004 1. R0000019 1. + C0000015 R0000004 1. R0000020 1. + C0000016 R0000004 1. R0000021 1. + C0000017 R0000005 1. R0000022 1. + C0000018 R0000005 1. R0000023 1. + C0000019 R0000005 1. R0000024 1. + C0000020 R0000005 1. R0000025 1. + C0000021 OBJECTRW 1. R0000006 -1. + C0000021 R0000010 1. + C0000022 OBJECTRW 2. R0000006 1. + C0000023 OBJECTRW 2. R0000007 -1. + C0000023 R0000011 1. + C0000024 OBJECTRW 3. R0000007 1. + C0000025 OBJECTRW 3. R0000008 -1. + C0000025 R0000012 1. + C0000026 OBJECTRW 2. R0000008 1. + C0000027 OBJECTRW 4. R0000009 -1. + C0000027 R0000013 1. + C0000028 OBJECTRW 5. R0000009 1. + C0000029 OBJECTRW 1. R0000010 -1. + C0000029 R0000014 1. + C0000030 OBJECTRW 2. R0000010 1. + C0000031 OBJECTRW 2. R0000011 -1. + C0000031 R0000015 1. + C0000032 OBJECTRW 3. R0000011 1. + C0000033 OBJECTRW 3. R0000012 -1. + C0000033 R0000016 1. + C0000034 OBJECTRW 2. R0000012 1. + C0000035 OBJECTRW 4. R0000013 -1. + C0000035 R0000017 1. + C0000036 OBJECTRW 5. R0000013 1. + C0000037 OBJECTRW 1. R0000014 -1. + C0000037 R0000018 1. + C0000038 OBJECTRW 2. R0000014 1. + C0000039 OBJECTRW 2. R0000015 -1. + C0000039 R0000019 1. + C0000040 OBJECTRW 3. R0000015 1. + C0000041 OBJECTRW 3. R0000016 -1. + C0000041 R0000020 1. + C0000042 OBJECTRW 2. R0000016 1. + C0000043 OBJECTRW 4. R0000017 -1. + C0000043 R0000021 1. + C0000044 OBJECTRW 5. R0000017 1. + C0000045 OBJECTRW 1. R0000018 -1. + C0000045 R0000022 1. + C0000046 OBJECTRW 2. R0000018 1. + C0000047 OBJECTRW 2. R0000019 -1. + C0000047 R0000023 1. + C0000048 OBJECTRW 3. R0000019 1. + C0000049 OBJECTRW 3. R0000020 -1. + C0000049 R0000024 1. + C0000050 OBJECTRW 2. R0000020 1. + C0000051 OBJECTRW 4. R0000021 -1. + C0000051 R0000025 1. + C0000052 OBJECTRW 5. R0000021 1. + C0000053 OBJECTRW 1. R0000022 -1. + C0000054 OBJECTRW 2. R0000022 1. + C0000055 OBJECTRW 2. R0000023 -1. + C0000056 OBJECTRW 3. R0000023 1. + C0000057 OBJECTRW 3. R0000024 -1. + C0000058 OBJECTRW 2. R0000024 1. + C0000059 OBJECTRW 4. R0000025 -1. + C0000060 OBJECTRW 5. R0000025 1. +RHS + RHS R0000001 3. R0000002 6. + RHS R0000003 10. R0000004 2000. + RHS R0000005 18. R0000006 1. + RHS R0000007 1. R0000008 1. + RHS R0000009 1. R0000010 2.667 + RHS R0000011 1.667 R0000012 2.667 + RHS R0000013 3.333 R0000014 2.667 + RHS R0000015 2. R0000016 3. + RHS R0000017 3. R0000018 2.667 + RHS R0000019 2.667 R0000020 2.667 + RHS R0000021 2.667 R0000022 2.667 + RHS R0000023 2.333 R0000024 2.333 + RHS R0000025 2.333 +BOUNDS + UP BOUND C0000029 51. + UP BOUND C0000030 51. + UP BOUND C0000031 51. + UP BOUND C0000032 51. +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.stoch b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.stoch new file mode 100644 index 000000000..7e41688a0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.stoch @@ -0,0 +1,117 @@ +NAME MYSMPS +SCENARIOS DISCRETE REPLACE + SC SCEN0001 ROOT 0.111 STG00002 + RHS R0000010 2 + RHS R0000011 1 + RHS R0000012 2 + RHS R0000013 2 + RHS R0000014 3 + RHS R0000015 1 + RHS R0000017 2 + RHS R0000018 4 + RHS R0000019 1 + RHS R0000020 4 + RHS R0000021 2 + RHS R0000022 5 + RHS R0000023 1 + RHS R0000024 5 + RHS R0000025 2 + SC SCEN0002 SCEN0001 0.111 STG00003 + RHS R0000014 2 + RHS R0000015 3 + RHS R0000018 2 + RHS R0000019 2 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 2 + RHS R0000023 1 + RHS R0000024 1 + RHS R0000025 3 + SC SCEN0003 SCEN0001 0.111 STG00003 + RHS R0000014 3 + RHS R0000017 4 + RHS R0000018 2 + RHS R0000019 5 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 1 + RHS R0000023 5 + RHS R0000024 1 + RHS R0000025 2 + SC SCEN0004 ROOT 0.111 STG00002 + RHS R0000010 2 + RHS R0000011 2 + RHS R0000012 2 + RHS R0000013 3 + RHS R0000014 3 + RHS R0000015 1 + RHS R0000017 2 + RHS R0000018 4 + RHS R0000019 1 + RHS R0000020 4 + RHS R0000021 2 + RHS R0000022 5 + RHS R0000023 1 + RHS R0000024 5 + RHS R0000025 2 + SC SCEN0005 SCEN0004 0.111 STG00003 + RHS R0000014 2 + RHS R0000015 3 + RHS R0000018 2 + RHS R0000019 2 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 2 + RHS R0000023 1 + RHS R0000024 1 + RHS R0000025 3 + SC SCEN0006 SCEN0004 0.111 STG00003 + RHS R0000014 3 + RHS R0000017 4 + RHS R0000018 2 + RHS R0000019 5 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 1 + RHS R0000023 5 + RHS R0000024 1 + RHS R0000025 2 + SC SCEN0007 ROOT 0.111 STG00002 + RHS R0000010 4 + RHS R0000011 2 + RHS R0000012 4 + RHS R0000013 5 + RHS R0000014 3 + RHS R0000015 1 + RHS R0000017 2 + RHS R0000018 4 + RHS R0000019 1 + RHS R0000020 4 + RHS R0000021 2 + RHS R0000022 5 + RHS R0000023 1 + RHS R0000024 5 + RHS R0000025 2 + SC SCEN0008 SCEN0007 0.111 STG00003 + RHS R0000014 2 + RHS R0000015 3 + RHS R0000018 2 + RHS R0000019 2 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 2 + RHS R0000023 1 + RHS R0000024 1 + RHS R0000025 3 + SC SCEN0009 SCEN0007 0.111 STG00003 + RHS R0000014 3 + RHS R0000017 4 + RHS R0000018 2 + RHS R0000019 5 + RHS R0000020 2 + RHS R0000021 3 + RHS R0000022 1 + RHS R0000023 5 + RHS R0000024 1 + RHS R0000025 2 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.time b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.time new file mode 100644 index 000000000..680027297 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/app0110R.time @@ -0,0 +1,6 @@ +NAME MYSMPS +PERIODS LP + C0000001 R0000001 STG00001 + C0000029 R0000010 STG00002 + C0000037 R0000014 STG00003 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.block b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.block new file mode 100644 index 000000000..c92f13ffc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.block @@ -0,0 +1,10 @@ +0 52 +10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 +1 52 +62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 +2 52 +114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 +3 52 +166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 +4 52 +218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.mps new file mode 100644 index 000000000..9a66acbbb --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/atm_5_10_1.mps @@ -0,0 +1,1597 @@ +NAME BLANK FREE +ROWS + N OBJROW + L budget(d_DATE0) + L budget(d_DATE1) + L budget(d_DATE2) + L budget(d_DATE3) + L budget(d_DATE4) + L budget(d_DATE5) + L budget(d_DATE6) + L budget(d_DATE7) + L budget(d_DATE8) + L budget(d_DATE9) + E demand_def(a_ATM0,d_DATE0) + L linkv(a_ATM0,d_DATE0) + E demand_def(a_ATM0,d_DATE1) + L linkv(a_ATM0,d_DATE1) + E demand_def(a_ATM0,d_DATE2) + L linkv(a_ATM0,d_DATE2) + E demand_def(a_ATM0,d_DATE3) + L linkv(a_ATM0,d_DATE3) + E demand_def(a_ATM0,d_DATE4) + L linkv(a_ATM0,d_DATE4) + E demand_def(a_ATM0,d_DATE5) + L linkv(a_ATM0,d_DATE5) + E demand_def(a_ATM0,d_DATE6) + L linkv(a_ATM0,d_DATE6) + E demand_def(a_ATM0,d_DATE7) + L linkv(a_ATM0,d_DATE7) + E demand_def(a_ATM0,d_DATE8) + L linkv(a_ATM0,d_DATE8) + E demand_def(a_ATM0,d_DATE9) + L linkv(a_ATM0,d_DATE9) + L pickone_x1(a_ATM0) + L count(a_ATM0) + L ztox1(a_ATM0,t_1) + L ztox2(a_ATM0,t_1) + G ztox3(a_ATM0,t_1) + L ztox1(a_ATM0,t_2) + L ztox2(a_ATM0,t_2) + G ztox3(a_ATM0,t_2) + L ztox1(a_ATM0,t_3) + L ztox2(a_ATM0,t_3) + G ztox3(a_ATM0,t_3) + L ztox1(a_ATM0,t_4) + L ztox2(a_ATM0,t_4) + G ztox3(a_ATM0,t_4) + L ztox1(a_ATM0,t_5) + L ztox2(a_ATM0,t_5) + G ztox3(a_ATM0,t_5) + L ztox1(a_ATM0,t_6) + L ztox2(a_ATM0,t_6) + G ztox3(a_ATM0,t_6) + L ztox1(a_ATM0,t_7) + L ztox2(a_ATM0,t_7) + G ztox3(a_ATM0,t_7) + L ztox1(a_ATM0,t_8) + L ztox2(a_ATM0,t_8) + G ztox3(a_ATM0,t_8) + L ztox1(a_ATM0,t_9) + L ztox2(a_ATM0,t_9) + G ztox3(a_ATM0,t_9) + L ztox1(a_ATM0,t_10) + L ztox2(a_ATM0,t_10) + G ztox3(a_ATM0,t_10) + E demand_def(a_ATM1,d_DATE0) + L linkv(a_ATM1,d_DATE0) + E demand_def(a_ATM1,d_DATE1) + L linkv(a_ATM1,d_DATE1) + E demand_def(a_ATM1,d_DATE2) + L linkv(a_ATM1,d_DATE2) + E demand_def(a_ATM1,d_DATE3) + L linkv(a_ATM1,d_DATE3) + E demand_def(a_ATM1,d_DATE4) + L linkv(a_ATM1,d_DATE4) + E demand_def(a_ATM1,d_DATE5) + L linkv(a_ATM1,d_DATE5) + E demand_def(a_ATM1,d_DATE6) + L linkv(a_ATM1,d_DATE6) + E demand_def(a_ATM1,d_DATE7) + L linkv(a_ATM1,d_DATE7) + E demand_def(a_ATM1,d_DATE8) + L linkv(a_ATM1,d_DATE8) + E demand_def(a_ATM1,d_DATE9) + L linkv(a_ATM1,d_DATE9) + L pickone_x1(a_ATM1) + L count(a_ATM1) + L ztox1(a_ATM1,t_1) + L ztox2(a_ATM1,t_1) + G ztox3(a_ATM1,t_1) + L ztox1(a_ATM1,t_2) + L ztox2(a_ATM1,t_2) + G ztox3(a_ATM1,t_2) + L ztox1(a_ATM1,t_3) + L ztox2(a_ATM1,t_3) + G ztox3(a_ATM1,t_3) + L ztox1(a_ATM1,t_4) + L ztox2(a_ATM1,t_4) + G ztox3(a_ATM1,t_4) + L ztox1(a_ATM1,t_5) + L ztox2(a_ATM1,t_5) + G ztox3(a_ATM1,t_5) + L ztox1(a_ATM1,t_6) + L ztox2(a_ATM1,t_6) + G ztox3(a_ATM1,t_6) + L ztox1(a_ATM1,t_7) + L ztox2(a_ATM1,t_7) + G ztox3(a_ATM1,t_7) + L ztox1(a_ATM1,t_8) + L ztox2(a_ATM1,t_8) + G ztox3(a_ATM1,t_8) + L ztox1(a_ATM1,t_9) + L ztox2(a_ATM1,t_9) + G ztox3(a_ATM1,t_9) + L ztox1(a_ATM1,t_10) + L ztox2(a_ATM1,t_10) + G ztox3(a_ATM1,t_10) + E demand_def(a_ATM2,d_DATE0) + L linkv(a_ATM2,d_DATE0) + E demand_def(a_ATM2,d_DATE1) + L linkv(a_ATM2,d_DATE1) + E demand_def(a_ATM2,d_DATE2) + L linkv(a_ATM2,d_DATE2) + E demand_def(a_ATM2,d_DATE3) + L linkv(a_ATM2,d_DATE3) + E demand_def(a_ATM2,d_DATE4) + L linkv(a_ATM2,d_DATE4) + E demand_def(a_ATM2,d_DATE5) + L linkv(a_ATM2,d_DATE5) + E demand_def(a_ATM2,d_DATE6) + L linkv(a_ATM2,d_DATE6) + E demand_def(a_ATM2,d_DATE7) + L linkv(a_ATM2,d_DATE7) + E demand_def(a_ATM2,d_DATE8) + L linkv(a_ATM2,d_DATE8) + E demand_def(a_ATM2,d_DATE9) + L linkv(a_ATM2,d_DATE9) + L pickone_x1(a_ATM2) + L count(a_ATM2) + L ztox1(a_ATM2,t_1) + L ztox2(a_ATM2,t_1) + G ztox3(a_ATM2,t_1) + L ztox1(a_ATM2,t_2) + L ztox2(a_ATM2,t_2) + G ztox3(a_ATM2,t_2) + L ztox1(a_ATM2,t_3) + L ztox2(a_ATM2,t_3) + G ztox3(a_ATM2,t_3) + L ztox1(a_ATM2,t_4) + L ztox2(a_ATM2,t_4) + G ztox3(a_ATM2,t_4) + L ztox1(a_ATM2,t_5) + L ztox2(a_ATM2,t_5) + G ztox3(a_ATM2,t_5) + L ztox1(a_ATM2,t_6) + L ztox2(a_ATM2,t_6) + G ztox3(a_ATM2,t_6) + L ztox1(a_ATM2,t_7) + L ztox2(a_ATM2,t_7) + G ztox3(a_ATM2,t_7) + L ztox1(a_ATM2,t_8) + L ztox2(a_ATM2,t_8) + G ztox3(a_ATM2,t_8) + L ztox1(a_ATM2,t_9) + L ztox2(a_ATM2,t_9) + G ztox3(a_ATM2,t_9) + L ztox1(a_ATM2,t_10) + L ztox2(a_ATM2,t_10) + G ztox3(a_ATM2,t_10) + E demand_def(a_ATM3,d_DATE0) + L linkv(a_ATM3,d_DATE0) + E demand_def(a_ATM3,d_DATE1) + L linkv(a_ATM3,d_DATE1) + E demand_def(a_ATM3,d_DATE2) + L linkv(a_ATM3,d_DATE2) + E demand_def(a_ATM3,d_DATE3) + L linkv(a_ATM3,d_DATE3) + E demand_def(a_ATM3,d_DATE4) + L linkv(a_ATM3,d_DATE4) + E demand_def(a_ATM3,d_DATE5) + L linkv(a_ATM3,d_DATE5) + E demand_def(a_ATM3,d_DATE6) + L linkv(a_ATM3,d_DATE6) + E demand_def(a_ATM3,d_DATE7) + L linkv(a_ATM3,d_DATE7) + E demand_def(a_ATM3,d_DATE8) + L linkv(a_ATM3,d_DATE8) + E demand_def(a_ATM3,d_DATE9) + L linkv(a_ATM3,d_DATE9) + L pickone_x1(a_ATM3) + L count(a_ATM3) + L ztox1(a_ATM3,t_1) + L ztox2(a_ATM3,t_1) + G ztox3(a_ATM3,t_1) + L ztox1(a_ATM3,t_2) + L ztox2(a_ATM3,t_2) + G ztox3(a_ATM3,t_2) + L ztox1(a_ATM3,t_3) + L ztox2(a_ATM3,t_3) + G ztox3(a_ATM3,t_3) + L ztox1(a_ATM3,t_4) + L ztox2(a_ATM3,t_4) + G ztox3(a_ATM3,t_4) + L ztox1(a_ATM3,t_5) + L ztox2(a_ATM3,t_5) + G ztox3(a_ATM3,t_5) + L ztox1(a_ATM3,t_6) + L ztox2(a_ATM3,t_6) + G ztox3(a_ATM3,t_6) + L ztox1(a_ATM3,t_7) + L ztox2(a_ATM3,t_7) + G ztox3(a_ATM3,t_7) + L ztox1(a_ATM3,t_8) + L ztox2(a_ATM3,t_8) + G ztox3(a_ATM3,t_8) + L ztox1(a_ATM3,t_9) + L ztox2(a_ATM3,t_9) + G ztox3(a_ATM3,t_9) + L ztox1(a_ATM3,t_10) + L ztox2(a_ATM3,t_10) + G ztox3(a_ATM3,t_10) + E demand_def(a_ATM4,d_DATE0) + L linkv(a_ATM4,d_DATE0) + E demand_def(a_ATM4,d_DATE1) + L linkv(a_ATM4,d_DATE1) + E demand_def(a_ATM4,d_DATE2) + L linkv(a_ATM4,d_DATE2) + E demand_def(a_ATM4,d_DATE3) + L linkv(a_ATM4,d_DATE3) + E demand_def(a_ATM4,d_DATE4) + L linkv(a_ATM4,d_DATE4) + E demand_def(a_ATM4,d_DATE5) + L linkv(a_ATM4,d_DATE5) + E demand_def(a_ATM4,d_DATE6) + L linkv(a_ATM4,d_DATE6) + E demand_def(a_ATM4,d_DATE7) + L linkv(a_ATM4,d_DATE7) + E demand_def(a_ATM4,d_DATE8) + L linkv(a_ATM4,d_DATE8) + E demand_def(a_ATM4,d_DATE9) + L linkv(a_ATM4,d_DATE9) + L pickone_x1(a_ATM4) + L count(a_ATM4) + L ztox1(a_ATM4,t_1) + L ztox2(a_ATM4,t_1) + G ztox3(a_ATM4,t_1) + L ztox1(a_ATM4,t_2) + L ztox2(a_ATM4,t_2) + G ztox3(a_ATM4,t_2) + L ztox1(a_ATM4,t_3) + L ztox2(a_ATM4,t_3) + G ztox3(a_ATM4,t_3) + L ztox1(a_ATM4,t_4) + L ztox2(a_ATM4,t_4) + G ztox3(a_ATM4,t_4) + L ztox1(a_ATM4,t_5) + L ztox2(a_ATM4,t_5) + G ztox3(a_ATM4,t_5) + L ztox1(a_ATM4,t_6) + L ztox2(a_ATM4,t_6) + G ztox3(a_ATM4,t_6) + L ztox1(a_ATM4,t_7) + L ztox2(a_ATM4,t_7) + G ztox3(a_ATM4,t_7) + L ztox1(a_ATM4,t_8) + L ztox2(a_ATM4,t_8) + G ztox3(a_ATM4,t_8) + L ztox1(a_ATM4,t_9) + L ztox2(a_ATM4,t_9) + G ztox3(a_ATM4,t_9) + L ztox1(a_ATM4,t_10) + L ztox2(a_ATM4,t_10) + G ztox3(a_ATM4,t_10) +COLUMNS + x1(0_ATM0,1) demand_def(a_ATM0,d_DATE0) -282.2 demand_def(a_ATM0,d_DATE1) -133.7 + x1(0_ATM0,1) demand_def(a_ATM0,d_DATE2) -268.5 demand_def(a_ATM0,d_DATE3) 59.5 + x1(0_ATM0,1) demand_def(a_ATM0,d_DATE4) -304.1 demand_def(a_ATM0,d_DATE5) -72.1 + x1(0_ATM0,1) demand_def(a_ATM0,d_DATE6) -357.3 demand_def(a_ATM0,d_DATE7) -39.9 + x1(0_ATM0,1) demand_def(a_ATM0,d_DATE8) -164.4 demand_def(a_ATM0,d_DATE9) 116.1 + x1(0_ATM0,1) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_1) -1. + x1(0_ATM0,1) ztox3(a_ATM0,t_1) -1. + x1(1_ATM0,2) demand_def(a_ATM0,d_DATE0) -564.4 demand_def(a_ATM0,d_DATE1) -267.4 + x1(1_ATM0,2) demand_def(a_ATM0,d_DATE2) -537. demand_def(a_ATM0,d_DATE3) 119. + x1(1_ATM0,2) demand_def(a_ATM0,d_DATE4) -608.2 demand_def(a_ATM0,d_DATE5) -144.2 + x1(1_ATM0,2) demand_def(a_ATM0,d_DATE6) -714.6 demand_def(a_ATM0,d_DATE7) -79.8 + x1(1_ATM0,2) demand_def(a_ATM0,d_DATE8) -328.8 demand_def(a_ATM0,d_DATE9) 232.2 + x1(1_ATM0,2) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_2) -1. + x1(1_ATM0,2) ztox3(a_ATM0,t_2) -1. + x1(2_ATM0,3) demand_def(a_ATM0,d_DATE0) -846.6 demand_def(a_ATM0,d_DATE1) -401.1 + x1(2_ATM0,3) demand_def(a_ATM0,d_DATE2) -805.5 demand_def(a_ATM0,d_DATE3) 178.5 + x1(2_ATM0,3) demand_def(a_ATM0,d_DATE4) -912.3 demand_def(a_ATM0,d_DATE5) -216.3 + x1(2_ATM0,3) demand_def(a_ATM0,d_DATE6) -1071.9 demand_def(a_ATM0,d_DATE7) -119.7 + x1(2_ATM0,3) demand_def(a_ATM0,d_DATE8) -493.2 demand_def(a_ATM0,d_DATE9) 348.3 + x1(2_ATM0,3) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_3) -1. + x1(2_ATM0,3) ztox3(a_ATM0,t_3) -1. + x1(3_ATM0,4) demand_def(a_ATM0,d_DATE0) -1128.8 demand_def(a_ATM0,d_DATE1) -534.8 + x1(3_ATM0,4) demand_def(a_ATM0,d_DATE2) -1074. demand_def(a_ATM0,d_DATE3) 238. + x1(3_ATM0,4) demand_def(a_ATM0,d_DATE4) -1216.4 demand_def(a_ATM0,d_DATE5) -288.4 + x1(3_ATM0,4) demand_def(a_ATM0,d_DATE6) -1429.2 demand_def(a_ATM0,d_DATE7) -159.6 + x1(3_ATM0,4) demand_def(a_ATM0,d_DATE8) -657.6 demand_def(a_ATM0,d_DATE9) 464.4 + x1(3_ATM0,4) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_4) -1. + x1(3_ATM0,4) ztox3(a_ATM0,t_4) -1. + x1(4_ATM0,5) demand_def(a_ATM0,d_DATE0) -1411. demand_def(a_ATM0,d_DATE1) -668.5 + x1(4_ATM0,5) demand_def(a_ATM0,d_DATE2) -1342.5 demand_def(a_ATM0,d_DATE3) 297.5 + x1(4_ATM0,5) demand_def(a_ATM0,d_DATE4) -1520.5 demand_def(a_ATM0,d_DATE5) -360.5 + x1(4_ATM0,5) demand_def(a_ATM0,d_DATE6) -1786.5 demand_def(a_ATM0,d_DATE7) -199.5 + x1(4_ATM0,5) demand_def(a_ATM0,d_DATE8) -822. demand_def(a_ATM0,d_DATE9) 580.5 + x1(4_ATM0,5) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_5) -1. + x1(4_ATM0,5) ztox3(a_ATM0,t_5) -1. + x1(5_ATM0,6) demand_def(a_ATM0,d_DATE0) -1693.2 demand_def(a_ATM0,d_DATE1) -802.2 + x1(5_ATM0,6) demand_def(a_ATM0,d_DATE2) -1611. demand_def(a_ATM0,d_DATE3) 357. + x1(5_ATM0,6) demand_def(a_ATM0,d_DATE4) -1824.6 demand_def(a_ATM0,d_DATE5) -432.6 + x1(5_ATM0,6) demand_def(a_ATM0,d_DATE6) -2143.8 demand_def(a_ATM0,d_DATE7) -239.4 + x1(5_ATM0,6) demand_def(a_ATM0,d_DATE8) -986.4 demand_def(a_ATM0,d_DATE9) 696.6 + x1(5_ATM0,6) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_6) -1. + x1(5_ATM0,6) ztox3(a_ATM0,t_6) -1. + x1(6_ATM0,7) demand_def(a_ATM0,d_DATE0) -1975.4 demand_def(a_ATM0,d_DATE1) -935.9 + x1(6_ATM0,7) demand_def(a_ATM0,d_DATE2) -1879.5 demand_def(a_ATM0,d_DATE3) 416.5 + x1(6_ATM0,7) demand_def(a_ATM0,d_DATE4) -2128.7 demand_def(a_ATM0,d_DATE5) -504.7 + x1(6_ATM0,7) demand_def(a_ATM0,d_DATE6) -2501.1 demand_def(a_ATM0,d_DATE7) -279.3 + x1(6_ATM0,7) demand_def(a_ATM0,d_DATE8) -1150.8 demand_def(a_ATM0,d_DATE9) 812.7 + x1(6_ATM0,7) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_7) -1. + x1(6_ATM0,7) ztox3(a_ATM0,t_7) -1. + x1(7_ATM0,8) demand_def(a_ATM0,d_DATE0) -2257.6 demand_def(a_ATM0,d_DATE1) -1069.6 + x1(7_ATM0,8) demand_def(a_ATM0,d_DATE2) -2148. demand_def(a_ATM0,d_DATE3) 476. + x1(7_ATM0,8) demand_def(a_ATM0,d_DATE4) -2432.8 demand_def(a_ATM0,d_DATE5) -576.8 + x1(7_ATM0,8) demand_def(a_ATM0,d_DATE6) -2858.4 demand_def(a_ATM0,d_DATE7) -319.2 + x1(7_ATM0,8) demand_def(a_ATM0,d_DATE8) -1315.2 demand_def(a_ATM0,d_DATE9) 928.8 + x1(7_ATM0,8) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_8) -1. + x1(7_ATM0,8) ztox3(a_ATM0,t_8) -1. + x1(8_ATM0,9) demand_def(a_ATM0,d_DATE0) -2539.8 demand_def(a_ATM0,d_DATE1) -1203.3 + x1(8_ATM0,9) demand_def(a_ATM0,d_DATE2) -2416.5 demand_def(a_ATM0,d_DATE3) 535.5 + x1(8_ATM0,9) demand_def(a_ATM0,d_DATE4) -2736.9 demand_def(a_ATM0,d_DATE5) -648.9 + x1(8_ATM0,9) demand_def(a_ATM0,d_DATE6) -3215.7 demand_def(a_ATM0,d_DATE7) -359.1 + x1(8_ATM0,9) demand_def(a_ATM0,d_DATE8) -1479.6 demand_def(a_ATM0,d_DATE9) 1044.9 + x1(8_ATM0,9) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_9) -1. + x1(8_ATM0,9) ztox3(a_ATM0,t_9) -1. + x1(9_ATM0,10) demand_def(a_ATM0,d_DATE0) -2822. demand_def(a_ATM0,d_DATE1) -1337. + x1(9_ATM0,10) demand_def(a_ATM0,d_DATE2) -2685. demand_def(a_ATM0,d_DATE3) 595. + x1(9_ATM0,10) demand_def(a_ATM0,d_DATE4) -3041. demand_def(a_ATM0,d_DATE5) -721. + x1(9_ATM0,10) demand_def(a_ATM0,d_DATE6) -3573. demand_def(a_ATM0,d_DATE7) -399. + x1(9_ATM0,10) demand_def(a_ATM0,d_DATE8) -1644. demand_def(a_ATM0,d_DATE9) 1161. + x1(9_ATM0,10) pickone_x1(a_ATM0) 1. ztox1(a_ATM0,t_10) -1. + x1(9_ATM0,10) ztox3(a_ATM0,t_10) -1. + x1(10_ATM1,1) demand_def(a_ATM1,d_DATE0) 167.1 demand_def(a_ATM1,d_DATE1) -293.3 + x1(10_ATM1,1) demand_def(a_ATM1,d_DATE2) 285. demand_def(a_ATM1,d_DATE3) 247. + x1(10_ATM1,1) demand_def(a_ATM1,d_DATE4) 124.8 demand_def(a_ATM1,d_DATE5) -203.1 + x1(10_ATM1,1) demand_def(a_ATM1,d_DATE6) -500.2 demand_def(a_ATM1,d_DATE7) -632.8 + x1(10_ATM1,1) demand_def(a_ATM1,d_DATE8) -144.3 demand_def(a_ATM1,d_DATE9) 156.1 + x1(10_ATM1,1) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_1) -1. + x1(10_ATM1,1) ztox3(a_ATM1,t_1) -1. + x1(11_ATM1,2) demand_def(a_ATM1,d_DATE0) 334.2 demand_def(a_ATM1,d_DATE1) -586.6 + x1(11_ATM1,2) demand_def(a_ATM1,d_DATE2) 570. demand_def(a_ATM1,d_DATE3) 494. + x1(11_ATM1,2) demand_def(a_ATM1,d_DATE4) 249.6 demand_def(a_ATM1,d_DATE5) -406.2 + x1(11_ATM1,2) demand_def(a_ATM1,d_DATE6) -1000.4 demand_def(a_ATM1,d_DATE7) -1265.6 + x1(11_ATM1,2) demand_def(a_ATM1,d_DATE8) -288.6 demand_def(a_ATM1,d_DATE9) 312.2 + x1(11_ATM1,2) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_2) -1. + x1(11_ATM1,2) ztox3(a_ATM1,t_2) -1. + x1(12_ATM1,3) demand_def(a_ATM1,d_DATE0) 501.3 demand_def(a_ATM1,d_DATE1) -879.9 + x1(12_ATM1,3) demand_def(a_ATM1,d_DATE2) 855. demand_def(a_ATM1,d_DATE3) 741. + x1(12_ATM1,3) demand_def(a_ATM1,d_DATE4) 374.4 demand_def(a_ATM1,d_DATE5) -609.3 + x1(12_ATM1,3) demand_def(a_ATM1,d_DATE6) -1500.6 demand_def(a_ATM1,d_DATE7) -1898.4 + x1(12_ATM1,3) demand_def(a_ATM1,d_DATE8) -432.9 demand_def(a_ATM1,d_DATE9) 468.3 + x1(12_ATM1,3) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_3) -1. + x1(12_ATM1,3) ztox3(a_ATM1,t_3) -1. + x1(13_ATM1,4) demand_def(a_ATM1,d_DATE0) 668.4 demand_def(a_ATM1,d_DATE1) -1173.2 + x1(13_ATM1,4) demand_def(a_ATM1,d_DATE2) 1140. demand_def(a_ATM1,d_DATE3) 988. + x1(13_ATM1,4) demand_def(a_ATM1,d_DATE4) 499.2 demand_def(a_ATM1,d_DATE5) -812.4 + x1(13_ATM1,4) demand_def(a_ATM1,d_DATE6) -2000.8 demand_def(a_ATM1,d_DATE7) -2531.2 + x1(13_ATM1,4) demand_def(a_ATM1,d_DATE8) -577.2 demand_def(a_ATM1,d_DATE9) 624.4 + x1(13_ATM1,4) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_4) -1. + x1(13_ATM1,4) ztox3(a_ATM1,t_4) -1. + x1(14_ATM1,5) demand_def(a_ATM1,d_DATE0) 835.5 demand_def(a_ATM1,d_DATE1) -1466.5 + x1(14_ATM1,5) demand_def(a_ATM1,d_DATE2) 1425. demand_def(a_ATM1,d_DATE3) 1235. + x1(14_ATM1,5) demand_def(a_ATM1,d_DATE4) 624. demand_def(a_ATM1,d_DATE5) -1015.5 + x1(14_ATM1,5) demand_def(a_ATM1,d_DATE6) -2501. demand_def(a_ATM1,d_DATE7) -3164. + x1(14_ATM1,5) demand_def(a_ATM1,d_DATE8) -721.5 demand_def(a_ATM1,d_DATE9) 780.5 + x1(14_ATM1,5) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_5) -1. + x1(14_ATM1,5) ztox3(a_ATM1,t_5) -1. + x1(15_ATM1,6) demand_def(a_ATM1,d_DATE0) 1002.6 demand_def(a_ATM1,d_DATE1) -1759.8 + x1(15_ATM1,6) demand_def(a_ATM1,d_DATE2) 1710. demand_def(a_ATM1,d_DATE3) 1482. + x1(15_ATM1,6) demand_def(a_ATM1,d_DATE4) 748.8 demand_def(a_ATM1,d_DATE5) -1218.6 + x1(15_ATM1,6) demand_def(a_ATM1,d_DATE6) -3001.2 demand_def(a_ATM1,d_DATE7) -3796.8 + x1(15_ATM1,6) demand_def(a_ATM1,d_DATE8) -865.8 demand_def(a_ATM1,d_DATE9) 936.6 + x1(15_ATM1,6) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_6) -1. + x1(15_ATM1,6) ztox3(a_ATM1,t_6) -1. + x1(16_ATM1,7) demand_def(a_ATM1,d_DATE0) 1169.7 demand_def(a_ATM1,d_DATE1) -2053.1 + x1(16_ATM1,7) demand_def(a_ATM1,d_DATE2) 1995. demand_def(a_ATM1,d_DATE3) 1729. + x1(16_ATM1,7) demand_def(a_ATM1,d_DATE4) 873.6 demand_def(a_ATM1,d_DATE5) -1421.7 + x1(16_ATM1,7) demand_def(a_ATM1,d_DATE6) -3501.4 demand_def(a_ATM1,d_DATE7) -4429.6 + x1(16_ATM1,7) demand_def(a_ATM1,d_DATE8) -1010.1 demand_def(a_ATM1,d_DATE9) 1092.7 + x1(16_ATM1,7) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_7) -1. + x1(16_ATM1,7) ztox3(a_ATM1,t_7) -1. + x1(17_ATM1,8) demand_def(a_ATM1,d_DATE0) 1336.8 demand_def(a_ATM1,d_DATE1) -2346.4 + x1(17_ATM1,8) demand_def(a_ATM1,d_DATE2) 2280. demand_def(a_ATM1,d_DATE3) 1976. + x1(17_ATM1,8) demand_def(a_ATM1,d_DATE4) 998.4 demand_def(a_ATM1,d_DATE5) -1624.8 + x1(17_ATM1,8) demand_def(a_ATM1,d_DATE6) -4001.6 demand_def(a_ATM1,d_DATE7) -5062.4 + x1(17_ATM1,8) demand_def(a_ATM1,d_DATE8) -1154.4 demand_def(a_ATM1,d_DATE9) 1248.8 + x1(17_ATM1,8) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_8) -1. + x1(17_ATM1,8) ztox3(a_ATM1,t_8) -1. + x1(18_ATM1,9) demand_def(a_ATM1,d_DATE0) 1503.9 demand_def(a_ATM1,d_DATE1) -2639.7 + x1(18_ATM1,9) demand_def(a_ATM1,d_DATE2) 2565. demand_def(a_ATM1,d_DATE3) 2223. + x1(18_ATM1,9) demand_def(a_ATM1,d_DATE4) 1123.2 demand_def(a_ATM1,d_DATE5) -1827.9 + x1(18_ATM1,9) demand_def(a_ATM1,d_DATE6) -4501.8 demand_def(a_ATM1,d_DATE7) -5695.2 + x1(18_ATM1,9) demand_def(a_ATM1,d_DATE8) -1298.7 demand_def(a_ATM1,d_DATE9) 1404.9 + x1(18_ATM1,9) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_9) -1. + x1(18_ATM1,9) ztox3(a_ATM1,t_9) -1. + x1(19_ATM1,10) demand_def(a_ATM1,d_DATE0) 1671. demand_def(a_ATM1,d_DATE1) -2933. + x1(19_ATM1,10) demand_def(a_ATM1,d_DATE2) 2850. demand_def(a_ATM1,d_DATE3) 2470. + x1(19_ATM1,10) demand_def(a_ATM1,d_DATE4) 1248. demand_def(a_ATM1,d_DATE5) -2031. + x1(19_ATM1,10) demand_def(a_ATM1,d_DATE6) -5002. demand_def(a_ATM1,d_DATE7) -6328. + x1(19_ATM1,10) demand_def(a_ATM1,d_DATE8) -1443. demand_def(a_ATM1,d_DATE9) 1561. + x1(19_ATM1,10) pickone_x1(a_ATM1) 1. ztox1(a_ATM1,t_10) -1. + x1(19_ATM1,10) ztox3(a_ATM1,t_10) -1. + x1(20_ATM2,1) demand_def(a_ATM2,d_DATE0) -58.9 demand_def(a_ATM2,d_DATE1) 106.8 + x1(20_ATM2,1) demand_def(a_ATM2,d_DATE2) 18.5 demand_def(a_ATM2,d_DATE3) -41.3 + x1(20_ATM2,1) demand_def(a_ATM2,d_DATE4) -117.4 demand_def(a_ATM2,d_DATE5) -156.4 + x1(20_ATM2,1) demand_def(a_ATM2,d_DATE6) -22.5 demand_def(a_ATM2,d_DATE7) 134. + x1(20_ATM2,1) demand_def(a_ATM2,d_DATE8) -209.7 demand_def(a_ATM2,d_DATE9) -99.6 + x1(20_ATM2,1) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_1) -1. + x1(20_ATM2,1) ztox3(a_ATM2,t_1) -1. + x1(21_ATM2,2) demand_def(a_ATM2,d_DATE0) -117.8 demand_def(a_ATM2,d_DATE1) 213.6 + x1(21_ATM2,2) demand_def(a_ATM2,d_DATE2) 37. demand_def(a_ATM2,d_DATE3) -82.6 + x1(21_ATM2,2) demand_def(a_ATM2,d_DATE4) -234.8 demand_def(a_ATM2,d_DATE5) -312.8 + x1(21_ATM2,2) demand_def(a_ATM2,d_DATE6) -45. demand_def(a_ATM2,d_DATE7) 268. + x1(21_ATM2,2) demand_def(a_ATM2,d_DATE8) -419.4 demand_def(a_ATM2,d_DATE9) -199.2 + x1(21_ATM2,2) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_2) -1. + x1(21_ATM2,2) ztox3(a_ATM2,t_2) -1. + x1(22_ATM2,3) demand_def(a_ATM2,d_DATE0) -176.7 demand_def(a_ATM2,d_DATE1) 320.4 + x1(22_ATM2,3) demand_def(a_ATM2,d_DATE2) 55.5 demand_def(a_ATM2,d_DATE3) -123.9 + x1(22_ATM2,3) demand_def(a_ATM2,d_DATE4) -352.2 demand_def(a_ATM2,d_DATE5) -469.2 + x1(22_ATM2,3) demand_def(a_ATM2,d_DATE6) -67.5 demand_def(a_ATM2,d_DATE7) 402. + x1(22_ATM2,3) demand_def(a_ATM2,d_DATE8) -629.1 demand_def(a_ATM2,d_DATE9) -298.8 + x1(22_ATM2,3) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_3) -1. + x1(22_ATM2,3) ztox3(a_ATM2,t_3) -1. + x1(23_ATM2,4) demand_def(a_ATM2,d_DATE0) -235.6 demand_def(a_ATM2,d_DATE1) 427.2 + x1(23_ATM2,4) demand_def(a_ATM2,d_DATE2) 74. demand_def(a_ATM2,d_DATE3) -165.2 + x1(23_ATM2,4) demand_def(a_ATM2,d_DATE4) -469.6 demand_def(a_ATM2,d_DATE5) -625.6 + x1(23_ATM2,4) demand_def(a_ATM2,d_DATE6) -90. demand_def(a_ATM2,d_DATE7) 536. + x1(23_ATM2,4) demand_def(a_ATM2,d_DATE8) -838.8 demand_def(a_ATM2,d_DATE9) -398.4 + x1(23_ATM2,4) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_4) -1. + x1(23_ATM2,4) ztox3(a_ATM2,t_4) -1. + x1(24_ATM2,5) demand_def(a_ATM2,d_DATE0) -294.5 demand_def(a_ATM2,d_DATE1) 534. + x1(24_ATM2,5) demand_def(a_ATM2,d_DATE2) 92.5 demand_def(a_ATM2,d_DATE3) -206.5 + x1(24_ATM2,5) demand_def(a_ATM2,d_DATE4) -587. demand_def(a_ATM2,d_DATE5) -782. + x1(24_ATM2,5) demand_def(a_ATM2,d_DATE6) -112.5 demand_def(a_ATM2,d_DATE7) 670. + x1(24_ATM2,5) demand_def(a_ATM2,d_DATE8) -1048.5 demand_def(a_ATM2,d_DATE9) -498. + x1(24_ATM2,5) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_5) -1. + x1(24_ATM2,5) ztox3(a_ATM2,t_5) -1. + x1(25_ATM2,6) demand_def(a_ATM2,d_DATE0) -353.4 demand_def(a_ATM2,d_DATE1) 640.8 + x1(25_ATM2,6) demand_def(a_ATM2,d_DATE2) 111. demand_def(a_ATM2,d_DATE3) -247.8 + x1(25_ATM2,6) demand_def(a_ATM2,d_DATE4) -704.4 demand_def(a_ATM2,d_DATE5) -938.4 + x1(25_ATM2,6) demand_def(a_ATM2,d_DATE6) -135. demand_def(a_ATM2,d_DATE7) 804. + x1(25_ATM2,6) demand_def(a_ATM2,d_DATE8) -1258.2 demand_def(a_ATM2,d_DATE9) -597.6 + x1(25_ATM2,6) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_6) -1. + x1(25_ATM2,6) ztox3(a_ATM2,t_6) -1. + x1(26_ATM2,7) demand_def(a_ATM2,d_DATE0) -412.3 demand_def(a_ATM2,d_DATE1) 747.6 + x1(26_ATM2,7) demand_def(a_ATM2,d_DATE2) 129.5 demand_def(a_ATM2,d_DATE3) -289.1 + x1(26_ATM2,7) demand_def(a_ATM2,d_DATE4) -821.8 demand_def(a_ATM2,d_DATE5) -1094.8 + x1(26_ATM2,7) demand_def(a_ATM2,d_DATE6) -157.5 demand_def(a_ATM2,d_DATE7) 938. + x1(26_ATM2,7) demand_def(a_ATM2,d_DATE8) -1467.9 demand_def(a_ATM2,d_DATE9) -697.2 + x1(26_ATM2,7) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_7) -1. + x1(26_ATM2,7) ztox3(a_ATM2,t_7) -1. + x1(27_ATM2,8) demand_def(a_ATM2,d_DATE0) -471.2 demand_def(a_ATM2,d_DATE1) 854.4 + x1(27_ATM2,8) demand_def(a_ATM2,d_DATE2) 148. demand_def(a_ATM2,d_DATE3) -330.4 + x1(27_ATM2,8) demand_def(a_ATM2,d_DATE4) -939.2 demand_def(a_ATM2,d_DATE5) -1251.2 + x1(27_ATM2,8) demand_def(a_ATM2,d_DATE6) -180. demand_def(a_ATM2,d_DATE7) 1072. + x1(27_ATM2,8) demand_def(a_ATM2,d_DATE8) -1677.6 demand_def(a_ATM2,d_DATE9) -796.8 + x1(27_ATM2,8) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_8) -1. + x1(27_ATM2,8) ztox3(a_ATM2,t_8) -1. + x1(28_ATM2,9) demand_def(a_ATM2,d_DATE0) -530.1 demand_def(a_ATM2,d_DATE1) 961.2 + x1(28_ATM2,9) demand_def(a_ATM2,d_DATE2) 166.5 demand_def(a_ATM2,d_DATE3) -371.7 + x1(28_ATM2,9) demand_def(a_ATM2,d_DATE4) -1056.6 demand_def(a_ATM2,d_DATE5) -1407.6 + x1(28_ATM2,9) demand_def(a_ATM2,d_DATE6) -202.5 demand_def(a_ATM2,d_DATE7) 1206. + x1(28_ATM2,9) demand_def(a_ATM2,d_DATE8) -1887.3 demand_def(a_ATM2,d_DATE9) -896.4 + x1(28_ATM2,9) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_9) -1. + x1(28_ATM2,9) ztox3(a_ATM2,t_9) -1. + x1(29_ATM2,10) demand_def(a_ATM2,d_DATE0) -589. demand_def(a_ATM2,d_DATE1) 1068. + x1(29_ATM2,10) demand_def(a_ATM2,d_DATE2) 185. demand_def(a_ATM2,d_DATE3) -413. + x1(29_ATM2,10) demand_def(a_ATM2,d_DATE4) -1174. demand_def(a_ATM2,d_DATE5) -1564. + x1(29_ATM2,10) demand_def(a_ATM2,d_DATE6) -225. demand_def(a_ATM2,d_DATE7) 1340. + x1(29_ATM2,10) demand_def(a_ATM2,d_DATE8) -2097. demand_def(a_ATM2,d_DATE9) -996. + x1(29_ATM2,10) pickone_x1(a_ATM2) 1. ztox1(a_ATM2,t_10) -1. + x1(29_ATM2,10) ztox3(a_ATM2,t_10) -1. + x1(30_ATM3,1) demand_def(a_ATM3,d_DATE0) 48.2 demand_def(a_ATM3,d_DATE1) -403.6 + x1(30_ATM3,1) demand_def(a_ATM3,d_DATE2) 116.8 demand_def(a_ATM3,d_DATE3) 95.5 + x1(30_ATM3,1) demand_def(a_ATM3,d_DATE4) 112.3 demand_def(a_ATM3,d_DATE5) -62.1 + x1(30_ATM3,1) demand_def(a_ATM3,d_DATE6) 95.9 demand_def(a_ATM3,d_DATE7) -503.2 + x1(30_ATM3,1) demand_def(a_ATM3,d_DATE8) 35. demand_def(a_ATM3,d_DATE9) 357.9 + x1(30_ATM3,1) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_1) -1. + x1(30_ATM3,1) ztox3(a_ATM3,t_1) -1. + x1(31_ATM3,2) demand_def(a_ATM3,d_DATE0) 96.4 demand_def(a_ATM3,d_DATE1) -807.2 + x1(31_ATM3,2) demand_def(a_ATM3,d_DATE2) 233.6 demand_def(a_ATM3,d_DATE3) 191. + x1(31_ATM3,2) demand_def(a_ATM3,d_DATE4) 224.6 demand_def(a_ATM3,d_DATE5) -124.2 + x1(31_ATM3,2) demand_def(a_ATM3,d_DATE6) 191.8 demand_def(a_ATM3,d_DATE7) -1006.4 + x1(31_ATM3,2) demand_def(a_ATM3,d_DATE8) 70. demand_def(a_ATM3,d_DATE9) 715.8 + x1(31_ATM3,2) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_2) -1. + x1(31_ATM3,2) ztox3(a_ATM3,t_2) -1. + x1(32_ATM3,3) demand_def(a_ATM3,d_DATE0) 144.6 demand_def(a_ATM3,d_DATE1) -1210.8 + x1(32_ATM3,3) demand_def(a_ATM3,d_DATE2) 350.4 demand_def(a_ATM3,d_DATE3) 286.5 + x1(32_ATM3,3) demand_def(a_ATM3,d_DATE4) 336.9 demand_def(a_ATM3,d_DATE5) -186.3 + x1(32_ATM3,3) demand_def(a_ATM3,d_DATE6) 287.7 demand_def(a_ATM3,d_DATE7) -1509.6 + x1(32_ATM3,3) demand_def(a_ATM3,d_DATE8) 105. demand_def(a_ATM3,d_DATE9) 1073.7 + x1(32_ATM3,3) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_3) -1. + x1(32_ATM3,3) ztox3(a_ATM3,t_3) -1. + x1(33_ATM3,4) demand_def(a_ATM3,d_DATE0) 192.8 demand_def(a_ATM3,d_DATE1) -1614.4 + x1(33_ATM3,4) demand_def(a_ATM3,d_DATE2) 467.2 demand_def(a_ATM3,d_DATE3) 382. + x1(33_ATM3,4) demand_def(a_ATM3,d_DATE4) 449.2 demand_def(a_ATM3,d_DATE5) -248.4 + x1(33_ATM3,4) demand_def(a_ATM3,d_DATE6) 383.6 demand_def(a_ATM3,d_DATE7) -2012.8 + x1(33_ATM3,4) demand_def(a_ATM3,d_DATE8) 140. demand_def(a_ATM3,d_DATE9) 1431.6 + x1(33_ATM3,4) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_4) -1. + x1(33_ATM3,4) ztox3(a_ATM3,t_4) -1. + x1(34_ATM3,5) demand_def(a_ATM3,d_DATE0) 241. demand_def(a_ATM3,d_DATE1) -2018. + x1(34_ATM3,5) demand_def(a_ATM3,d_DATE2) 584. demand_def(a_ATM3,d_DATE3) 477.5 + x1(34_ATM3,5) demand_def(a_ATM3,d_DATE4) 561.5 demand_def(a_ATM3,d_DATE5) -310.5 + x1(34_ATM3,5) demand_def(a_ATM3,d_DATE6) 479.5 demand_def(a_ATM3,d_DATE7) -2516. + x1(34_ATM3,5) demand_def(a_ATM3,d_DATE8) 175. demand_def(a_ATM3,d_DATE9) 1789.5 + x1(34_ATM3,5) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_5) -1. + x1(34_ATM3,5) ztox3(a_ATM3,t_5) -1. + x1(35_ATM3,6) demand_def(a_ATM3,d_DATE0) 289.2 demand_def(a_ATM3,d_DATE1) -2421.6 + x1(35_ATM3,6) demand_def(a_ATM3,d_DATE2) 700.8 demand_def(a_ATM3,d_DATE3) 573. + x1(35_ATM3,6) demand_def(a_ATM3,d_DATE4) 673.8 demand_def(a_ATM3,d_DATE5) -372.6 + x1(35_ATM3,6) demand_def(a_ATM3,d_DATE6) 575.4 demand_def(a_ATM3,d_DATE7) -3019.2 + x1(35_ATM3,6) demand_def(a_ATM3,d_DATE8) 210. demand_def(a_ATM3,d_DATE9) 2147.4 + x1(35_ATM3,6) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_6) -1. + x1(35_ATM3,6) ztox3(a_ATM3,t_6) -1. + x1(36_ATM3,7) demand_def(a_ATM3,d_DATE0) 337.4 demand_def(a_ATM3,d_DATE1) -2825.2 + x1(36_ATM3,7) demand_def(a_ATM3,d_DATE2) 817.6 demand_def(a_ATM3,d_DATE3) 668.5 + x1(36_ATM3,7) demand_def(a_ATM3,d_DATE4) 786.1 demand_def(a_ATM3,d_DATE5) -434.7 + x1(36_ATM3,7) demand_def(a_ATM3,d_DATE6) 671.3 demand_def(a_ATM3,d_DATE7) -3522.4 + x1(36_ATM3,7) demand_def(a_ATM3,d_DATE8) 245. demand_def(a_ATM3,d_DATE9) 2505.3 + x1(36_ATM3,7) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_7) -1. + x1(36_ATM3,7) ztox3(a_ATM3,t_7) -1. + x1(37_ATM3,8) demand_def(a_ATM3,d_DATE0) 385.6 demand_def(a_ATM3,d_DATE1) -3228.8 + x1(37_ATM3,8) demand_def(a_ATM3,d_DATE2) 934.4 demand_def(a_ATM3,d_DATE3) 764. + x1(37_ATM3,8) demand_def(a_ATM3,d_DATE4) 898.4 demand_def(a_ATM3,d_DATE5) -496.8 + x1(37_ATM3,8) demand_def(a_ATM3,d_DATE6) 767.2 demand_def(a_ATM3,d_DATE7) -4025.6 + x1(37_ATM3,8) demand_def(a_ATM3,d_DATE8) 280. demand_def(a_ATM3,d_DATE9) 2863.2 + x1(37_ATM3,8) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_8) -1. + x1(37_ATM3,8) ztox3(a_ATM3,t_8) -1. + x1(38_ATM3,9) demand_def(a_ATM3,d_DATE0) 433.8 demand_def(a_ATM3,d_DATE1) -3632.4 + x1(38_ATM3,9) demand_def(a_ATM3,d_DATE2) 1051.2 demand_def(a_ATM3,d_DATE3) 859.5 + x1(38_ATM3,9) demand_def(a_ATM3,d_DATE4) 1010.7 demand_def(a_ATM3,d_DATE5) -558.9 + x1(38_ATM3,9) demand_def(a_ATM3,d_DATE6) 863.1 demand_def(a_ATM3,d_DATE7) -4528.8 + x1(38_ATM3,9) demand_def(a_ATM3,d_DATE8) 315. demand_def(a_ATM3,d_DATE9) 3221.1 + x1(38_ATM3,9) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_9) -1. + x1(38_ATM3,9) ztox3(a_ATM3,t_9) -1. + x1(39_ATM3,10) demand_def(a_ATM3,d_DATE0) 482. demand_def(a_ATM3,d_DATE1) -4036. + x1(39_ATM3,10) demand_def(a_ATM3,d_DATE2) 1168. demand_def(a_ATM3,d_DATE3) 955. + x1(39_ATM3,10) demand_def(a_ATM3,d_DATE4) 1123. demand_def(a_ATM3,d_DATE5) -621. + x1(39_ATM3,10) demand_def(a_ATM3,d_DATE6) 959. demand_def(a_ATM3,d_DATE7) -5032. + x1(39_ATM3,10) demand_def(a_ATM3,d_DATE8) 350. demand_def(a_ATM3,d_DATE9) 3579. + x1(39_ATM3,10) pickone_x1(a_ATM3) 1. ztox1(a_ATM3,t_10) -1. + x1(39_ATM3,10) ztox3(a_ATM3,t_10) -1. + x1(40_ATM4,1) demand_def(a_ATM4,d_DATE0) -233.4 demand_def(a_ATM4,d_DATE1) -149.2 + x1(40_ATM4,1) demand_def(a_ATM4,d_DATE2) 335.2 demand_def(a_ATM4,d_DATE3) -94.2 + x1(40_ATM4,1) demand_def(a_ATM4,d_DATE4) 135.3 demand_def(a_ATM4,d_DATE5) 16.7 + x1(40_ATM4,1) demand_def(a_ATM4,d_DATE6) -90. demand_def(a_ATM4,d_DATE7) -237.8 + x1(40_ATM4,1) demand_def(a_ATM4,d_DATE8) -316.7 demand_def(a_ATM4,d_DATE9) 232.4 + x1(40_ATM4,1) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_1) -1. + x1(40_ATM4,1) ztox3(a_ATM4,t_1) -1. + x1(41_ATM4,2) demand_def(a_ATM4,d_DATE0) -466.8 demand_def(a_ATM4,d_DATE1) -298.4 + x1(41_ATM4,2) demand_def(a_ATM4,d_DATE2) 670.4 demand_def(a_ATM4,d_DATE3) -188.4 + x1(41_ATM4,2) demand_def(a_ATM4,d_DATE4) 270.6 demand_def(a_ATM4,d_DATE5) 33.4 + x1(41_ATM4,2) demand_def(a_ATM4,d_DATE6) -180. demand_def(a_ATM4,d_DATE7) -475.6 + x1(41_ATM4,2) demand_def(a_ATM4,d_DATE8) -633.4 demand_def(a_ATM4,d_DATE9) 464.8 + x1(41_ATM4,2) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_2) -1. + x1(41_ATM4,2) ztox3(a_ATM4,t_2) -1. + x1(42_ATM4,3) demand_def(a_ATM4,d_DATE0) -700.2 demand_def(a_ATM4,d_DATE1) -447.6 + x1(42_ATM4,3) demand_def(a_ATM4,d_DATE2) 1005.6 demand_def(a_ATM4,d_DATE3) -282.6 + x1(42_ATM4,3) demand_def(a_ATM4,d_DATE4) 405.9 demand_def(a_ATM4,d_DATE5) 50.1 + x1(42_ATM4,3) demand_def(a_ATM4,d_DATE6) -270. demand_def(a_ATM4,d_DATE7) -713.4 + x1(42_ATM4,3) demand_def(a_ATM4,d_DATE8) -950.1 demand_def(a_ATM4,d_DATE9) 697.2 + x1(42_ATM4,3) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_3) -1. + x1(42_ATM4,3) ztox3(a_ATM4,t_3) -1. + x1(43_ATM4,4) demand_def(a_ATM4,d_DATE0) -933.6 demand_def(a_ATM4,d_DATE1) -596.8 + x1(43_ATM4,4) demand_def(a_ATM4,d_DATE2) 1340.8 demand_def(a_ATM4,d_DATE3) -376.8 + x1(43_ATM4,4) demand_def(a_ATM4,d_DATE4) 541.2 demand_def(a_ATM4,d_DATE5) 66.8 + x1(43_ATM4,4) demand_def(a_ATM4,d_DATE6) -360. demand_def(a_ATM4,d_DATE7) -951.2 + x1(43_ATM4,4) demand_def(a_ATM4,d_DATE8) -1266.8 demand_def(a_ATM4,d_DATE9) 929.6 + x1(43_ATM4,4) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_4) -1. + x1(43_ATM4,4) ztox3(a_ATM4,t_4) -1. + x1(44_ATM4,5) demand_def(a_ATM4,d_DATE0) -1167. demand_def(a_ATM4,d_DATE1) -746. + x1(44_ATM4,5) demand_def(a_ATM4,d_DATE2) 1676. demand_def(a_ATM4,d_DATE3) -471. + x1(44_ATM4,5) demand_def(a_ATM4,d_DATE4) 676.5 demand_def(a_ATM4,d_DATE5) 83.5 + x1(44_ATM4,5) demand_def(a_ATM4,d_DATE6) -450. demand_def(a_ATM4,d_DATE7) -1189. + x1(44_ATM4,5) demand_def(a_ATM4,d_DATE8) -1583.5 demand_def(a_ATM4,d_DATE9) 1162. + x1(44_ATM4,5) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_5) -1. + x1(44_ATM4,5) ztox3(a_ATM4,t_5) -1. + x1(45_ATM4,6) demand_def(a_ATM4,d_DATE0) -1400.4 demand_def(a_ATM4,d_DATE1) -895.2 + x1(45_ATM4,6) demand_def(a_ATM4,d_DATE2) 2011.2 demand_def(a_ATM4,d_DATE3) -565.2 + x1(45_ATM4,6) demand_def(a_ATM4,d_DATE4) 811.8 demand_def(a_ATM4,d_DATE5) 100.2 + x1(45_ATM4,6) demand_def(a_ATM4,d_DATE6) -540. demand_def(a_ATM4,d_DATE7) -1426.8 + x1(45_ATM4,6) demand_def(a_ATM4,d_DATE8) -1900.2 demand_def(a_ATM4,d_DATE9) 1394.4 + x1(45_ATM4,6) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_6) -1. + x1(45_ATM4,6) ztox3(a_ATM4,t_6) -1. + x1(46_ATM4,7) demand_def(a_ATM4,d_DATE0) -1633.8 demand_def(a_ATM4,d_DATE1) -1044.4 + x1(46_ATM4,7) demand_def(a_ATM4,d_DATE2) 2346.4 demand_def(a_ATM4,d_DATE3) -659.4 + x1(46_ATM4,7) demand_def(a_ATM4,d_DATE4) 947.1 demand_def(a_ATM4,d_DATE5) 116.9 + x1(46_ATM4,7) demand_def(a_ATM4,d_DATE6) -630. demand_def(a_ATM4,d_DATE7) -1664.6 + x1(46_ATM4,7) demand_def(a_ATM4,d_DATE8) -2216.9 demand_def(a_ATM4,d_DATE9) 1626.8 + x1(46_ATM4,7) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_7) -1. + x1(46_ATM4,7) ztox3(a_ATM4,t_7) -1. + x1(47_ATM4,8) demand_def(a_ATM4,d_DATE0) -1867.2 demand_def(a_ATM4,d_DATE1) -1193.6 + x1(47_ATM4,8) demand_def(a_ATM4,d_DATE2) 2681.6 demand_def(a_ATM4,d_DATE3) -753.6 + x1(47_ATM4,8) demand_def(a_ATM4,d_DATE4) 1082.4 demand_def(a_ATM4,d_DATE5) 133.6 + x1(47_ATM4,8) demand_def(a_ATM4,d_DATE6) -720. demand_def(a_ATM4,d_DATE7) -1902.4 + x1(47_ATM4,8) demand_def(a_ATM4,d_DATE8) -2533.6 demand_def(a_ATM4,d_DATE9) 1859.2 + x1(47_ATM4,8) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_8) -1. + x1(47_ATM4,8) ztox3(a_ATM4,t_8) -1. + x1(48_ATM4,9) demand_def(a_ATM4,d_DATE0) -2100.6 demand_def(a_ATM4,d_DATE1) -1342.8 + x1(48_ATM4,9) demand_def(a_ATM4,d_DATE2) 3016.8 demand_def(a_ATM4,d_DATE3) -847.8 + x1(48_ATM4,9) demand_def(a_ATM4,d_DATE4) 1217.7 demand_def(a_ATM4,d_DATE5) 150.3 + x1(48_ATM4,9) demand_def(a_ATM4,d_DATE6) -810. demand_def(a_ATM4,d_DATE7) -2140.2 + x1(48_ATM4,9) demand_def(a_ATM4,d_DATE8) -2850.3 demand_def(a_ATM4,d_DATE9) 2091.6 + x1(48_ATM4,9) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_9) -1. + x1(48_ATM4,9) ztox3(a_ATM4,t_9) -1. + x1(49_ATM4,10) demand_def(a_ATM4,d_DATE0) -2334. demand_def(a_ATM4,d_DATE1) -1492. + x1(49_ATM4,10) demand_def(a_ATM4,d_DATE2) 3352. demand_def(a_ATM4,d_DATE3) -942. + x1(49_ATM4,10) demand_def(a_ATM4,d_DATE4) 1353. demand_def(a_ATM4,d_DATE5) 167. + x1(49_ATM4,10) demand_def(a_ATM4,d_DATE6) -900. demand_def(a_ATM4,d_DATE7) -2378. + x1(49_ATM4,10) demand_def(a_ATM4,d_DATE8) -3167. demand_def(a_ATM4,d_DATE9) 2324. + x1(49_ATM4,10) pickone_x1(a_ATM4) 1. ztox1(a_ATM4,t_10) -1. + x1(49_ATM4,10) ztox3(a_ATM4,t_10) -1. + z(50_ATM0,1) demand_def(a_ATM0,d_DATE0) 198.4 demand_def(a_ATM0,d_DATE1) 253. + z(50_ATM0,1) demand_def(a_ATM0,d_DATE2) -6.7 demand_def(a_ATM0,d_DATE3) -313.5 + z(50_ATM0,1) demand_def(a_ATM0,d_DATE4) -95.1 demand_def(a_ATM0,d_DATE5) 47.9 + z(50_ATM0,1) demand_def(a_ATM0,d_DATE6) 318.6 demand_def(a_ATM0,d_DATE7) 34.1 + z(50_ATM0,1) demand_def(a_ATM0,d_DATE8) -64.3 demand_def(a_ATM0,d_DATE9) -93.1 + z(50_ATM0,1) ztox1(a_ATM0,t_1) 1. ztox2(a_ATM0,t_1) 1. + z(50_ATM0,1) ztox3(a_ATM0,t_1) 1. + z(51_ATM0,2) demand_def(a_ATM0,d_DATE0) 396.8 demand_def(a_ATM0,d_DATE1) 506. + z(51_ATM0,2) demand_def(a_ATM0,d_DATE2) -13.4 demand_def(a_ATM0,d_DATE3) -627. + z(51_ATM0,2) demand_def(a_ATM0,d_DATE4) -190.2 demand_def(a_ATM0,d_DATE5) 95.8 + z(51_ATM0,2) demand_def(a_ATM0,d_DATE6) 637.2 demand_def(a_ATM0,d_DATE7) 68.2 + z(51_ATM0,2) demand_def(a_ATM0,d_DATE8) -128.6 demand_def(a_ATM0,d_DATE9) -186.2 + z(51_ATM0,2) ztox1(a_ATM0,t_2) 1. ztox2(a_ATM0,t_2) 1. + z(51_ATM0,2) ztox3(a_ATM0,t_2) 1. + z(52_ATM0,3) demand_def(a_ATM0,d_DATE0) 595.2 demand_def(a_ATM0,d_DATE1) 759. + z(52_ATM0,3) demand_def(a_ATM0,d_DATE2) -20.1 demand_def(a_ATM0,d_DATE3) -940.5 + z(52_ATM0,3) demand_def(a_ATM0,d_DATE4) -285.3 demand_def(a_ATM0,d_DATE5) 143.7 + z(52_ATM0,3) demand_def(a_ATM0,d_DATE6) 955.8 demand_def(a_ATM0,d_DATE7) 102.3 + z(52_ATM0,3) demand_def(a_ATM0,d_DATE8) -192.9 demand_def(a_ATM0,d_DATE9) -279.3 + z(52_ATM0,3) ztox1(a_ATM0,t_3) 1. ztox2(a_ATM0,t_3) 1. + z(52_ATM0,3) ztox3(a_ATM0,t_3) 1. + z(53_ATM0,4) demand_def(a_ATM0,d_DATE0) 793.6 demand_def(a_ATM0,d_DATE1) 1012. + z(53_ATM0,4) demand_def(a_ATM0,d_DATE2) -26.8 demand_def(a_ATM0,d_DATE3) -1254. + z(53_ATM0,4) demand_def(a_ATM0,d_DATE4) -380.4 demand_def(a_ATM0,d_DATE5) 191.6 + z(53_ATM0,4) demand_def(a_ATM0,d_DATE6) 1274.4 demand_def(a_ATM0,d_DATE7) 136.4 + z(53_ATM0,4) demand_def(a_ATM0,d_DATE8) -257.2 demand_def(a_ATM0,d_DATE9) -372.4 + z(53_ATM0,4) ztox1(a_ATM0,t_4) 1. ztox2(a_ATM0,t_4) 1. + z(53_ATM0,4) ztox3(a_ATM0,t_4) 1. + z(54_ATM0,5) demand_def(a_ATM0,d_DATE0) 992. demand_def(a_ATM0,d_DATE1) 1265. + z(54_ATM0,5) demand_def(a_ATM0,d_DATE2) -33.5 demand_def(a_ATM0,d_DATE3) -1567.5 + z(54_ATM0,5) demand_def(a_ATM0,d_DATE4) -475.5 demand_def(a_ATM0,d_DATE5) 239.5 + z(54_ATM0,5) demand_def(a_ATM0,d_DATE6) 1593. demand_def(a_ATM0,d_DATE7) 170.5 + z(54_ATM0,5) demand_def(a_ATM0,d_DATE8) -321.5 demand_def(a_ATM0,d_DATE9) -465.5 + z(54_ATM0,5) ztox1(a_ATM0,t_5) 1. ztox2(a_ATM0,t_5) 1. + z(54_ATM0,5) ztox3(a_ATM0,t_5) 1. + z(55_ATM0,6) demand_def(a_ATM0,d_DATE0) 1190.4 demand_def(a_ATM0,d_DATE1) 1518. + z(55_ATM0,6) demand_def(a_ATM0,d_DATE2) -40.2 demand_def(a_ATM0,d_DATE3) -1881. + z(55_ATM0,6) demand_def(a_ATM0,d_DATE4) -570.6 demand_def(a_ATM0,d_DATE5) 287.4 + z(55_ATM0,6) demand_def(a_ATM0,d_DATE6) 1911.6 demand_def(a_ATM0,d_DATE7) 204.6 + z(55_ATM0,6) demand_def(a_ATM0,d_DATE8) -385.8 demand_def(a_ATM0,d_DATE9) -558.6 + z(55_ATM0,6) ztox1(a_ATM0,t_6) 1. ztox2(a_ATM0,t_6) 1. + z(55_ATM0,6) ztox3(a_ATM0,t_6) 1. + z(56_ATM0,7) demand_def(a_ATM0,d_DATE0) 1388.8 demand_def(a_ATM0,d_DATE1) 1771. + z(56_ATM0,7) demand_def(a_ATM0,d_DATE2) -46.9 demand_def(a_ATM0,d_DATE3) -2194.5 + z(56_ATM0,7) demand_def(a_ATM0,d_DATE4) -665.7 demand_def(a_ATM0,d_DATE5) 335.3 + z(56_ATM0,7) demand_def(a_ATM0,d_DATE6) 2230.2 demand_def(a_ATM0,d_DATE7) 238.7 + z(56_ATM0,7) demand_def(a_ATM0,d_DATE8) -450.1 demand_def(a_ATM0,d_DATE9) -651.7 + z(56_ATM0,7) ztox1(a_ATM0,t_7) 1. ztox2(a_ATM0,t_7) 1. + z(56_ATM0,7) ztox3(a_ATM0,t_7) 1. + z(57_ATM0,8) demand_def(a_ATM0,d_DATE0) 1587.2 demand_def(a_ATM0,d_DATE1) 2024. + z(57_ATM0,8) demand_def(a_ATM0,d_DATE2) -53.6 demand_def(a_ATM0,d_DATE3) -2508. + z(57_ATM0,8) demand_def(a_ATM0,d_DATE4) -760.8 demand_def(a_ATM0,d_DATE5) 383.2 + z(57_ATM0,8) demand_def(a_ATM0,d_DATE6) 2548.8 demand_def(a_ATM0,d_DATE7) 272.8 + z(57_ATM0,8) demand_def(a_ATM0,d_DATE8) -514.4 demand_def(a_ATM0,d_DATE9) -744.8 + z(57_ATM0,8) ztox1(a_ATM0,t_8) 1. ztox2(a_ATM0,t_8) 1. + z(57_ATM0,8) ztox3(a_ATM0,t_8) 1. + z(58_ATM0,9) demand_def(a_ATM0,d_DATE0) 1785.6 demand_def(a_ATM0,d_DATE1) 2277. + z(58_ATM0,9) demand_def(a_ATM0,d_DATE2) -60.3 demand_def(a_ATM0,d_DATE3) -2821.5 + z(58_ATM0,9) demand_def(a_ATM0,d_DATE4) -855.9 demand_def(a_ATM0,d_DATE5) 431.1 + z(58_ATM0,9) demand_def(a_ATM0,d_DATE6) 2867.4 demand_def(a_ATM0,d_DATE7) 306.9 + z(58_ATM0,9) demand_def(a_ATM0,d_DATE8) -578.7 demand_def(a_ATM0,d_DATE9) -837.9 + z(58_ATM0,9) ztox1(a_ATM0,t_9) 1. ztox2(a_ATM0,t_9) 1. + z(58_ATM0,9) ztox3(a_ATM0,t_9) 1. + z(59_ATM0,10) demand_def(a_ATM0,d_DATE0) 1984. demand_def(a_ATM0,d_DATE1) 2530. + z(59_ATM0,10) demand_def(a_ATM0,d_DATE2) -67. demand_def(a_ATM0,d_DATE3) -3135. + z(59_ATM0,10) demand_def(a_ATM0,d_DATE4) -951. demand_def(a_ATM0,d_DATE5) 479. + z(59_ATM0,10) demand_def(a_ATM0,d_DATE6) 3186. demand_def(a_ATM0,d_DATE7) 341. + z(59_ATM0,10) demand_def(a_ATM0,d_DATE8) -643. demand_def(a_ATM0,d_DATE9) -931. + z(59_ATM0,10) ztox1(a_ATM0,t_10) 1. ztox2(a_ATM0,t_10) 1. + z(59_ATM0,10) ztox3(a_ATM0,t_10) 1. + z(60_ATM1,1) demand_def(a_ATM1,d_DATE0) 60.1 demand_def(a_ATM1,d_DATE1) 61.8 + z(60_ATM1,1) demand_def(a_ATM1,d_DATE2) -61. demand_def(a_ATM1,d_DATE3) -197.7 + z(60_ATM1,1) demand_def(a_ATM1,d_DATE4) 156.6 demand_def(a_ATM1,d_DATE5) -148. + z(60_ATM1,1) demand_def(a_ATM1,d_DATE6) 67.9 demand_def(a_ATM1,d_DATE7) 137.5 + z(60_ATM1,1) demand_def(a_ATM1,d_DATE8) 53.4 demand_def(a_ATM1,d_DATE9) 15.7 + z(60_ATM1,1) ztox1(a_ATM1,t_1) 1. ztox2(a_ATM1,t_1) 1. + z(60_ATM1,1) ztox3(a_ATM1,t_1) 1. + z(61_ATM1,2) demand_def(a_ATM1,d_DATE0) 120.2 demand_def(a_ATM1,d_DATE1) 123.6 + z(61_ATM1,2) demand_def(a_ATM1,d_DATE2) -122. demand_def(a_ATM1,d_DATE3) -395.4 + z(61_ATM1,2) demand_def(a_ATM1,d_DATE4) 313.2 demand_def(a_ATM1,d_DATE5) -296. + z(61_ATM1,2) demand_def(a_ATM1,d_DATE6) 135.8 demand_def(a_ATM1,d_DATE7) 275. + z(61_ATM1,2) demand_def(a_ATM1,d_DATE8) 106.8 demand_def(a_ATM1,d_DATE9) 31.4 + z(61_ATM1,2) ztox1(a_ATM1,t_2) 1. ztox2(a_ATM1,t_2) 1. + z(61_ATM1,2) ztox3(a_ATM1,t_2) 1. + z(62_ATM1,3) demand_def(a_ATM1,d_DATE0) 180.3 demand_def(a_ATM1,d_DATE1) 185.4 + z(62_ATM1,3) demand_def(a_ATM1,d_DATE2) -183. demand_def(a_ATM1,d_DATE3) -593.1 + z(62_ATM1,3) demand_def(a_ATM1,d_DATE4) 469.8 demand_def(a_ATM1,d_DATE5) -444. + z(62_ATM1,3) demand_def(a_ATM1,d_DATE6) 203.7 demand_def(a_ATM1,d_DATE7) 412.5 + z(62_ATM1,3) demand_def(a_ATM1,d_DATE8) 160.2 demand_def(a_ATM1,d_DATE9) 47.1 + z(62_ATM1,3) ztox1(a_ATM1,t_3) 1. ztox2(a_ATM1,t_3) 1. + z(62_ATM1,3) ztox3(a_ATM1,t_3) 1. + z(63_ATM1,4) demand_def(a_ATM1,d_DATE0) 240.4 demand_def(a_ATM1,d_DATE1) 247.2 + z(63_ATM1,4) demand_def(a_ATM1,d_DATE2) -244. demand_def(a_ATM1,d_DATE3) -790.8 + z(63_ATM1,4) demand_def(a_ATM1,d_DATE4) 626.4 demand_def(a_ATM1,d_DATE5) -592. + z(63_ATM1,4) demand_def(a_ATM1,d_DATE6) 271.6 demand_def(a_ATM1,d_DATE7) 550. + z(63_ATM1,4) demand_def(a_ATM1,d_DATE8) 213.6 demand_def(a_ATM1,d_DATE9) 62.8 + z(63_ATM1,4) ztox1(a_ATM1,t_4) 1. ztox2(a_ATM1,t_4) 1. + z(63_ATM1,4) ztox3(a_ATM1,t_4) 1. + z(64_ATM1,5) demand_def(a_ATM1,d_DATE0) 300.5 demand_def(a_ATM1,d_DATE1) 309. + z(64_ATM1,5) demand_def(a_ATM1,d_DATE2) -305. demand_def(a_ATM1,d_DATE3) -988.5 + z(64_ATM1,5) demand_def(a_ATM1,d_DATE4) 783. demand_def(a_ATM1,d_DATE5) -740. + z(64_ATM1,5) demand_def(a_ATM1,d_DATE6) 339.5 demand_def(a_ATM1,d_DATE7) 687.5 + z(64_ATM1,5) demand_def(a_ATM1,d_DATE8) 267. demand_def(a_ATM1,d_DATE9) 78.5 + z(64_ATM1,5) ztox1(a_ATM1,t_5) 1. ztox2(a_ATM1,t_5) 1. + z(64_ATM1,5) ztox3(a_ATM1,t_5) 1. + z(65_ATM1,6) demand_def(a_ATM1,d_DATE0) 360.6 demand_def(a_ATM1,d_DATE1) 370.8 + z(65_ATM1,6) demand_def(a_ATM1,d_DATE2) -366. demand_def(a_ATM1,d_DATE3) -1186.2 + z(65_ATM1,6) demand_def(a_ATM1,d_DATE4) 939.6 demand_def(a_ATM1,d_DATE5) -888. + z(65_ATM1,6) demand_def(a_ATM1,d_DATE6) 407.4 demand_def(a_ATM1,d_DATE7) 825. + z(65_ATM1,6) demand_def(a_ATM1,d_DATE8) 320.4 demand_def(a_ATM1,d_DATE9) 94.2 + z(65_ATM1,6) ztox1(a_ATM1,t_6) 1. ztox2(a_ATM1,t_6) 1. + z(65_ATM1,6) ztox3(a_ATM1,t_6) 1. + z(66_ATM1,7) demand_def(a_ATM1,d_DATE0) 420.7 demand_def(a_ATM1,d_DATE1) 432.6 + z(66_ATM1,7) demand_def(a_ATM1,d_DATE2) -427. demand_def(a_ATM1,d_DATE3) -1383.9 + z(66_ATM1,7) demand_def(a_ATM1,d_DATE4) 1096.2 demand_def(a_ATM1,d_DATE5) -1036. + z(66_ATM1,7) demand_def(a_ATM1,d_DATE6) 475.3 demand_def(a_ATM1,d_DATE7) 962.5 + z(66_ATM1,7) demand_def(a_ATM1,d_DATE8) 373.8 demand_def(a_ATM1,d_DATE9) 109.9 + z(66_ATM1,7) ztox1(a_ATM1,t_7) 1. ztox2(a_ATM1,t_7) 1. + z(66_ATM1,7) ztox3(a_ATM1,t_7) 1. + z(67_ATM1,8) demand_def(a_ATM1,d_DATE0) 480.8 demand_def(a_ATM1,d_DATE1) 494.4 + z(67_ATM1,8) demand_def(a_ATM1,d_DATE2) -488. demand_def(a_ATM1,d_DATE3) -1581.6 + z(67_ATM1,8) demand_def(a_ATM1,d_DATE4) 1252.8 demand_def(a_ATM1,d_DATE5) -1184. + z(67_ATM1,8) demand_def(a_ATM1,d_DATE6) 543.2 demand_def(a_ATM1,d_DATE7) 1100. + z(67_ATM1,8) demand_def(a_ATM1,d_DATE8) 427.2 demand_def(a_ATM1,d_DATE9) 125.6 + z(67_ATM1,8) ztox1(a_ATM1,t_8) 1. ztox2(a_ATM1,t_8) 1. + z(67_ATM1,8) ztox3(a_ATM1,t_8) 1. + z(68_ATM1,9) demand_def(a_ATM1,d_DATE0) 540.9 demand_def(a_ATM1,d_DATE1) 556.2 + z(68_ATM1,9) demand_def(a_ATM1,d_DATE2) -549. demand_def(a_ATM1,d_DATE3) -1779.3 + z(68_ATM1,9) demand_def(a_ATM1,d_DATE4) 1409.4 demand_def(a_ATM1,d_DATE5) -1332. + z(68_ATM1,9) demand_def(a_ATM1,d_DATE6) 611.1 demand_def(a_ATM1,d_DATE7) 1237.5 + z(68_ATM1,9) demand_def(a_ATM1,d_DATE8) 480.6 demand_def(a_ATM1,d_DATE9) 141.3 + z(68_ATM1,9) ztox1(a_ATM1,t_9) 1. ztox2(a_ATM1,t_9) 1. + z(68_ATM1,9) ztox3(a_ATM1,t_9) 1. + z(69_ATM1,10) demand_def(a_ATM1,d_DATE0) 601. demand_def(a_ATM1,d_DATE1) 618. + z(69_ATM1,10) demand_def(a_ATM1,d_DATE2) -610. demand_def(a_ATM1,d_DATE3) -1977. + z(69_ATM1,10) demand_def(a_ATM1,d_DATE4) 1566. demand_def(a_ATM1,d_DATE5) -1480. + z(69_ATM1,10) demand_def(a_ATM1,d_DATE6) 679. demand_def(a_ATM1,d_DATE7) 1375. + z(69_ATM1,10) demand_def(a_ATM1,d_DATE8) 534. demand_def(a_ATM1,d_DATE9) 157. + z(69_ATM1,10) ztox1(a_ATM1,t_10) 1. ztox2(a_ATM1,t_10) 1. + z(69_ATM1,10) ztox3(a_ATM1,t_10) 1. + z(70_ATM2,1) demand_def(a_ATM2,d_DATE0) -69.1 demand_def(a_ATM2,d_DATE1) -200.1 + z(70_ATM2,1) demand_def(a_ATM2,d_DATE2) 262.6 demand_def(a_ATM2,d_DATE3) 364.9 + z(70_ATM2,1) demand_def(a_ATM2,d_DATE4) -95.1 demand_def(a_ATM2,d_DATE5) -137.6 + z(70_ATM2,1) demand_def(a_ATM2,d_DATE6) 206.7 demand_def(a_ATM2,d_DATE7) 104.6 + z(70_ATM2,1) demand_def(a_ATM2,d_DATE8) -57.4 demand_def(a_ATM2,d_DATE9) -137.7 + z(70_ATM2,1) ztox1(a_ATM2,t_1) 1. ztox2(a_ATM2,t_1) 1. + z(70_ATM2,1) ztox3(a_ATM2,t_1) 1. + z(71_ATM2,2) demand_def(a_ATM2,d_DATE0) -138.2 demand_def(a_ATM2,d_DATE1) -400.2 + z(71_ATM2,2) demand_def(a_ATM2,d_DATE2) 525.2 demand_def(a_ATM2,d_DATE3) 729.8 + z(71_ATM2,2) demand_def(a_ATM2,d_DATE4) -190.2 demand_def(a_ATM2,d_DATE5) -275.2 + z(71_ATM2,2) demand_def(a_ATM2,d_DATE6) 413.4 demand_def(a_ATM2,d_DATE7) 209.2 + z(71_ATM2,2) demand_def(a_ATM2,d_DATE8) -114.8 demand_def(a_ATM2,d_DATE9) -275.4 + z(71_ATM2,2) ztox1(a_ATM2,t_2) 1. ztox2(a_ATM2,t_2) 1. + z(71_ATM2,2) ztox3(a_ATM2,t_2) 1. + z(72_ATM2,3) demand_def(a_ATM2,d_DATE0) -207.3 demand_def(a_ATM2,d_DATE1) -600.3 + z(72_ATM2,3) demand_def(a_ATM2,d_DATE2) 787.8 demand_def(a_ATM2,d_DATE3) 1094.7 + z(72_ATM2,3) demand_def(a_ATM2,d_DATE4) -285.3 demand_def(a_ATM2,d_DATE5) -412.8 + z(72_ATM2,3) demand_def(a_ATM2,d_DATE6) 620.1 demand_def(a_ATM2,d_DATE7) 313.8 + z(72_ATM2,3) demand_def(a_ATM2,d_DATE8) -172.2 demand_def(a_ATM2,d_DATE9) -413.1 + z(72_ATM2,3) ztox1(a_ATM2,t_3) 1. ztox2(a_ATM2,t_3) 1. + z(72_ATM2,3) ztox3(a_ATM2,t_3) 1. + z(73_ATM2,4) demand_def(a_ATM2,d_DATE0) -276.4 demand_def(a_ATM2,d_DATE1) -800.4 + z(73_ATM2,4) demand_def(a_ATM2,d_DATE2) 1050.4 demand_def(a_ATM2,d_DATE3) 1459.6 + z(73_ATM2,4) demand_def(a_ATM2,d_DATE4) -380.4 demand_def(a_ATM2,d_DATE5) -550.4 + z(73_ATM2,4) demand_def(a_ATM2,d_DATE6) 826.8 demand_def(a_ATM2,d_DATE7) 418.4 + z(73_ATM2,4) demand_def(a_ATM2,d_DATE8) -229.6 demand_def(a_ATM2,d_DATE9) -550.8 + z(73_ATM2,4) ztox1(a_ATM2,t_4) 1. ztox2(a_ATM2,t_4) 1. + z(73_ATM2,4) ztox3(a_ATM2,t_4) 1. + z(74_ATM2,5) demand_def(a_ATM2,d_DATE0) -345.5 demand_def(a_ATM2,d_DATE1) -1000.5 + z(74_ATM2,5) demand_def(a_ATM2,d_DATE2) 1313. demand_def(a_ATM2,d_DATE3) 1824.5 + z(74_ATM2,5) demand_def(a_ATM2,d_DATE4) -475.5 demand_def(a_ATM2,d_DATE5) -688. + z(74_ATM2,5) demand_def(a_ATM2,d_DATE6) 1033.5 demand_def(a_ATM2,d_DATE7) 523. + z(74_ATM2,5) demand_def(a_ATM2,d_DATE8) -287. demand_def(a_ATM2,d_DATE9) -688.5 + z(74_ATM2,5) ztox1(a_ATM2,t_5) 1. ztox2(a_ATM2,t_5) 1. + z(74_ATM2,5) ztox3(a_ATM2,t_5) 1. + z(75_ATM2,6) demand_def(a_ATM2,d_DATE0) -414.6 demand_def(a_ATM2,d_DATE1) -1200.6 + z(75_ATM2,6) demand_def(a_ATM2,d_DATE2) 1575.6 demand_def(a_ATM2,d_DATE3) 2189.4 + z(75_ATM2,6) demand_def(a_ATM2,d_DATE4) -570.6 demand_def(a_ATM2,d_DATE5) -825.6 + z(75_ATM2,6) demand_def(a_ATM2,d_DATE6) 1240.2 demand_def(a_ATM2,d_DATE7) 627.6 + z(75_ATM2,6) demand_def(a_ATM2,d_DATE8) -344.4 demand_def(a_ATM2,d_DATE9) -826.2 + z(75_ATM2,6) ztox1(a_ATM2,t_6) 1. ztox2(a_ATM2,t_6) 1. + z(75_ATM2,6) ztox3(a_ATM2,t_6) 1. + z(76_ATM2,7) demand_def(a_ATM2,d_DATE0) -483.7 demand_def(a_ATM2,d_DATE1) -1400.7 + z(76_ATM2,7) demand_def(a_ATM2,d_DATE2) 1838.2 demand_def(a_ATM2,d_DATE3) 2554.3 + z(76_ATM2,7) demand_def(a_ATM2,d_DATE4) -665.7 demand_def(a_ATM2,d_DATE5) -963.2 + z(76_ATM2,7) demand_def(a_ATM2,d_DATE6) 1446.9 demand_def(a_ATM2,d_DATE7) 732.2 + z(76_ATM2,7) demand_def(a_ATM2,d_DATE8) -401.8 demand_def(a_ATM2,d_DATE9) -963.9 + z(76_ATM2,7) ztox1(a_ATM2,t_7) 1. ztox2(a_ATM2,t_7) 1. + z(76_ATM2,7) ztox3(a_ATM2,t_7) 1. + z(77_ATM2,8) demand_def(a_ATM2,d_DATE0) -552.8 demand_def(a_ATM2,d_DATE1) -1600.8 + z(77_ATM2,8) demand_def(a_ATM2,d_DATE2) 2100.8 demand_def(a_ATM2,d_DATE3) 2919.2 + z(77_ATM2,8) demand_def(a_ATM2,d_DATE4) -760.8 demand_def(a_ATM2,d_DATE5) -1100.8 + z(77_ATM2,8) demand_def(a_ATM2,d_DATE6) 1653.6 demand_def(a_ATM2,d_DATE7) 836.8 + z(77_ATM2,8) demand_def(a_ATM2,d_DATE8) -459.2 demand_def(a_ATM2,d_DATE9) -1101.6 + z(77_ATM2,8) ztox1(a_ATM2,t_8) 1. ztox2(a_ATM2,t_8) 1. + z(77_ATM2,8) ztox3(a_ATM2,t_8) 1. + z(78_ATM2,9) demand_def(a_ATM2,d_DATE0) -621.9 demand_def(a_ATM2,d_DATE1) -1800.9 + z(78_ATM2,9) demand_def(a_ATM2,d_DATE2) 2363.4 demand_def(a_ATM2,d_DATE3) 3284.1 + z(78_ATM2,9) demand_def(a_ATM2,d_DATE4) -855.9 demand_def(a_ATM2,d_DATE5) -1238.4 + z(78_ATM2,9) demand_def(a_ATM2,d_DATE6) 1860.3 demand_def(a_ATM2,d_DATE7) 941.4 + z(78_ATM2,9) demand_def(a_ATM2,d_DATE8) -516.6 demand_def(a_ATM2,d_DATE9) -1239.3 + z(78_ATM2,9) ztox1(a_ATM2,t_9) 1. ztox2(a_ATM2,t_9) 1. + z(78_ATM2,9) ztox3(a_ATM2,t_9) 1. + z(79_ATM2,10) demand_def(a_ATM2,d_DATE0) -691. demand_def(a_ATM2,d_DATE1) -2001. + z(79_ATM2,10) demand_def(a_ATM2,d_DATE2) 2626. demand_def(a_ATM2,d_DATE3) 3649. + z(79_ATM2,10) demand_def(a_ATM2,d_DATE4) -951. demand_def(a_ATM2,d_DATE5) -1376. + z(79_ATM2,10) demand_def(a_ATM2,d_DATE6) 2067. demand_def(a_ATM2,d_DATE7) 1046. + z(79_ATM2,10) demand_def(a_ATM2,d_DATE8) -574. demand_def(a_ATM2,d_DATE9) -1377. + z(79_ATM2,10) ztox1(a_ATM2,t_10) 1. ztox2(a_ATM2,t_10) 1. + z(79_ATM2,10) ztox3(a_ATM2,t_10) 1. + z(80_ATM3,1) demand_def(a_ATM3,d_DATE0) 294.3 demand_def(a_ATM3,d_DATE1) 9.3 + z(80_ATM3,1) demand_def(a_ATM3,d_DATE2) -45.1 demand_def(a_ATM3,d_DATE3) -128.2 + z(80_ATM3,1) demand_def(a_ATM3,d_DATE4) 125.1 demand_def(a_ATM3,d_DATE5) -114.1 + z(80_ATM3,1) demand_def(a_ATM3,d_DATE6) -321.4 demand_def(a_ATM3,d_DATE7) -97.6 + z(80_ATM3,1) demand_def(a_ATM3,d_DATE8) -48. demand_def(a_ATM3,d_DATE9) -236.9 + z(80_ATM3,1) ztox1(a_ATM3,t_1) 1. ztox2(a_ATM3,t_1) 1. + z(80_ATM3,1) ztox3(a_ATM3,t_1) 1. + z(81_ATM3,2) demand_def(a_ATM3,d_DATE0) 588.6 demand_def(a_ATM3,d_DATE1) 18.6 + z(81_ATM3,2) demand_def(a_ATM3,d_DATE2) -90.2 demand_def(a_ATM3,d_DATE3) -256.4 + z(81_ATM3,2) demand_def(a_ATM3,d_DATE4) 250.2 demand_def(a_ATM3,d_DATE5) -228.2 + z(81_ATM3,2) demand_def(a_ATM3,d_DATE6) -642.8 demand_def(a_ATM3,d_DATE7) -195.2 + z(81_ATM3,2) demand_def(a_ATM3,d_DATE8) -96. demand_def(a_ATM3,d_DATE9) -473.8 + z(81_ATM3,2) ztox1(a_ATM3,t_2) 1. ztox2(a_ATM3,t_2) 1. + z(81_ATM3,2) ztox3(a_ATM3,t_2) 1. + z(82_ATM3,3) demand_def(a_ATM3,d_DATE0) 882.9 demand_def(a_ATM3,d_DATE1) 27.9 + z(82_ATM3,3) demand_def(a_ATM3,d_DATE2) -135.3 demand_def(a_ATM3,d_DATE3) -384.6 + z(82_ATM3,3) demand_def(a_ATM3,d_DATE4) 375.3 demand_def(a_ATM3,d_DATE5) -342.3 + z(82_ATM3,3) demand_def(a_ATM3,d_DATE6) -964.2 demand_def(a_ATM3,d_DATE7) -292.8 + z(82_ATM3,3) demand_def(a_ATM3,d_DATE8) -144. demand_def(a_ATM3,d_DATE9) -710.7 + z(82_ATM3,3) ztox1(a_ATM3,t_3) 1. ztox2(a_ATM3,t_3) 1. + z(82_ATM3,3) ztox3(a_ATM3,t_3) 1. + z(83_ATM3,4) demand_def(a_ATM3,d_DATE0) 1177.2 demand_def(a_ATM3,d_DATE1) 37.2 + z(83_ATM3,4) demand_def(a_ATM3,d_DATE2) -180.4 demand_def(a_ATM3,d_DATE3) -512.8 + z(83_ATM3,4) demand_def(a_ATM3,d_DATE4) 500.4 demand_def(a_ATM3,d_DATE5) -456.4 + z(83_ATM3,4) demand_def(a_ATM3,d_DATE6) -1285.6 demand_def(a_ATM3,d_DATE7) -390.4 + z(83_ATM3,4) demand_def(a_ATM3,d_DATE8) -192. demand_def(a_ATM3,d_DATE9) -947.6 + z(83_ATM3,4) ztox1(a_ATM3,t_4) 1. ztox2(a_ATM3,t_4) 1. + z(83_ATM3,4) ztox3(a_ATM3,t_4) 1. + z(84_ATM3,5) demand_def(a_ATM3,d_DATE0) 1471.5 demand_def(a_ATM3,d_DATE1) 46.5 + z(84_ATM3,5) demand_def(a_ATM3,d_DATE2) -225.5 demand_def(a_ATM3,d_DATE3) -641. + z(84_ATM3,5) demand_def(a_ATM3,d_DATE4) 625.5 demand_def(a_ATM3,d_DATE5) -570.5 + z(84_ATM3,5) demand_def(a_ATM3,d_DATE6) -1607. demand_def(a_ATM3,d_DATE7) -488. + z(84_ATM3,5) demand_def(a_ATM3,d_DATE8) -240. demand_def(a_ATM3,d_DATE9) -1184.5 + z(84_ATM3,5) ztox1(a_ATM3,t_5) 1. ztox2(a_ATM3,t_5) 1. + z(84_ATM3,5) ztox3(a_ATM3,t_5) 1. + z(85_ATM3,6) demand_def(a_ATM3,d_DATE0) 1765.8 demand_def(a_ATM3,d_DATE1) 55.8 + z(85_ATM3,6) demand_def(a_ATM3,d_DATE2) -270.6 demand_def(a_ATM3,d_DATE3) -769.2 + z(85_ATM3,6) demand_def(a_ATM3,d_DATE4) 750.6 demand_def(a_ATM3,d_DATE5) -684.6 + z(85_ATM3,6) demand_def(a_ATM3,d_DATE6) -1928.4 demand_def(a_ATM3,d_DATE7) -585.6 + z(85_ATM3,6) demand_def(a_ATM3,d_DATE8) -288. demand_def(a_ATM3,d_DATE9) -1421.4 + z(85_ATM3,6) ztox1(a_ATM3,t_6) 1. ztox2(a_ATM3,t_6) 1. + z(85_ATM3,6) ztox3(a_ATM3,t_6) 1. + z(86_ATM3,7) demand_def(a_ATM3,d_DATE0) 2060.1 demand_def(a_ATM3,d_DATE1) 65.1 + z(86_ATM3,7) demand_def(a_ATM3,d_DATE2) -315.7 demand_def(a_ATM3,d_DATE3) -897.4 + z(86_ATM3,7) demand_def(a_ATM3,d_DATE4) 875.7 demand_def(a_ATM3,d_DATE5) -798.7 + z(86_ATM3,7) demand_def(a_ATM3,d_DATE6) -2249.8 demand_def(a_ATM3,d_DATE7) -683.2 + z(86_ATM3,7) demand_def(a_ATM3,d_DATE8) -336. demand_def(a_ATM3,d_DATE9) -1658.3 + z(86_ATM3,7) ztox1(a_ATM3,t_7) 1. ztox2(a_ATM3,t_7) 1. + z(86_ATM3,7) ztox3(a_ATM3,t_7) 1. + z(87_ATM3,8) demand_def(a_ATM3,d_DATE0) 2354.4 demand_def(a_ATM3,d_DATE1) 74.4 + z(87_ATM3,8) demand_def(a_ATM3,d_DATE2) -360.8 demand_def(a_ATM3,d_DATE3) -1025.6 + z(87_ATM3,8) demand_def(a_ATM3,d_DATE4) 1000.8 demand_def(a_ATM3,d_DATE5) -912.8 + z(87_ATM3,8) demand_def(a_ATM3,d_DATE6) -2571.2 demand_def(a_ATM3,d_DATE7) -780.8 + z(87_ATM3,8) demand_def(a_ATM3,d_DATE8) -384. demand_def(a_ATM3,d_DATE9) -1895.2 + z(87_ATM3,8) ztox1(a_ATM3,t_8) 1. ztox2(a_ATM3,t_8) 1. + z(87_ATM3,8) ztox3(a_ATM3,t_8) 1. + z(88_ATM3,9) demand_def(a_ATM3,d_DATE0) 2648.7 demand_def(a_ATM3,d_DATE1) 83.7 + z(88_ATM3,9) demand_def(a_ATM3,d_DATE2) -405.9 demand_def(a_ATM3,d_DATE3) -1153.8 + z(88_ATM3,9) demand_def(a_ATM3,d_DATE4) 1125.9 demand_def(a_ATM3,d_DATE5) -1026.9 + z(88_ATM3,9) demand_def(a_ATM3,d_DATE6) -2892.6 demand_def(a_ATM3,d_DATE7) -878.4 + z(88_ATM3,9) demand_def(a_ATM3,d_DATE8) -432. demand_def(a_ATM3,d_DATE9) -2132.1 + z(88_ATM3,9) ztox1(a_ATM3,t_9) 1. ztox2(a_ATM3,t_9) 1. + z(88_ATM3,9) ztox3(a_ATM3,t_9) 1. + z(89_ATM3,10) demand_def(a_ATM3,d_DATE0) 2943. demand_def(a_ATM3,d_DATE1) 93. + z(89_ATM3,10) demand_def(a_ATM3,d_DATE2) -451. demand_def(a_ATM3,d_DATE3) -1282. + z(89_ATM3,10) demand_def(a_ATM3,d_DATE4) 1251. demand_def(a_ATM3,d_DATE5) -1141. + z(89_ATM3,10) demand_def(a_ATM3,d_DATE6) -3214. demand_def(a_ATM3,d_DATE7) -976. + z(89_ATM3,10) demand_def(a_ATM3,d_DATE8) -480. demand_def(a_ATM3,d_DATE9) -2369. + z(89_ATM3,10) ztox1(a_ATM3,t_10) 1. ztox2(a_ATM3,t_10) 1. + z(89_ATM3,10) ztox3(a_ATM3,t_10) 1. + z(90_ATM4,1) demand_def(a_ATM4,d_DATE0) 15.1 demand_def(a_ATM4,d_DATE1) 81.1 + z(90_ATM4,1) demand_def(a_ATM4,d_DATE2) -331. demand_def(a_ATM4,d_DATE3) -104.3 + z(90_ATM4,1) demand_def(a_ATM4,d_DATE4) -178.9 demand_def(a_ATM4,d_DATE5) -34.6 + z(90_ATM4,1) demand_def(a_ATM4,d_DATE6) -13.6 demand_def(a_ATM4,d_DATE7) -184.9 + z(90_ATM4,1) demand_def(a_ATM4,d_DATE8) -44.3 demand_def(a_ATM4,d_DATE9) -95.1 + z(90_ATM4,1) ztox1(a_ATM4,t_1) 1. ztox2(a_ATM4,t_1) 1. + z(90_ATM4,1) ztox3(a_ATM4,t_1) 1. + z(91_ATM4,2) demand_def(a_ATM4,d_DATE0) 30.2 demand_def(a_ATM4,d_DATE1) 162.2 + z(91_ATM4,2) demand_def(a_ATM4,d_DATE2) -662. demand_def(a_ATM4,d_DATE3) -208.6 + z(91_ATM4,2) demand_def(a_ATM4,d_DATE4) -357.8 demand_def(a_ATM4,d_DATE5) -69.2 + z(91_ATM4,2) demand_def(a_ATM4,d_DATE6) -27.2 demand_def(a_ATM4,d_DATE7) -369.8 + z(91_ATM4,2) demand_def(a_ATM4,d_DATE8) -88.6 demand_def(a_ATM4,d_DATE9) -190.2 + z(91_ATM4,2) ztox1(a_ATM4,t_2) 1. ztox2(a_ATM4,t_2) 1. + z(91_ATM4,2) ztox3(a_ATM4,t_2) 1. + z(92_ATM4,3) demand_def(a_ATM4,d_DATE0) 45.3 demand_def(a_ATM4,d_DATE1) 243.3 + z(92_ATM4,3) demand_def(a_ATM4,d_DATE2) -993. demand_def(a_ATM4,d_DATE3) -312.9 + z(92_ATM4,3) demand_def(a_ATM4,d_DATE4) -536.7 demand_def(a_ATM4,d_DATE5) -103.8 + z(92_ATM4,3) demand_def(a_ATM4,d_DATE6) -40.8 demand_def(a_ATM4,d_DATE7) -554.7 + z(92_ATM4,3) demand_def(a_ATM4,d_DATE8) -132.9 demand_def(a_ATM4,d_DATE9) -285.3 + z(92_ATM4,3) ztox1(a_ATM4,t_3) 1. ztox2(a_ATM4,t_3) 1. + z(92_ATM4,3) ztox3(a_ATM4,t_3) 1. + z(93_ATM4,4) demand_def(a_ATM4,d_DATE0) 60.4 demand_def(a_ATM4,d_DATE1) 324.4 + z(93_ATM4,4) demand_def(a_ATM4,d_DATE2) -1324. demand_def(a_ATM4,d_DATE3) -417.2 + z(93_ATM4,4) demand_def(a_ATM4,d_DATE4) -715.6 demand_def(a_ATM4,d_DATE5) -138.4 + z(93_ATM4,4) demand_def(a_ATM4,d_DATE6) -54.4 demand_def(a_ATM4,d_DATE7) -739.6 + z(93_ATM4,4) demand_def(a_ATM4,d_DATE8) -177.2 demand_def(a_ATM4,d_DATE9) -380.4 + z(93_ATM4,4) ztox1(a_ATM4,t_4) 1. ztox2(a_ATM4,t_4) 1. + z(93_ATM4,4) ztox3(a_ATM4,t_4) 1. + z(94_ATM4,5) demand_def(a_ATM4,d_DATE0) 75.5 demand_def(a_ATM4,d_DATE1) 405.5 + z(94_ATM4,5) demand_def(a_ATM4,d_DATE2) -1655. demand_def(a_ATM4,d_DATE3) -521.5 + z(94_ATM4,5) demand_def(a_ATM4,d_DATE4) -894.5 demand_def(a_ATM4,d_DATE5) -173. + z(94_ATM4,5) demand_def(a_ATM4,d_DATE6) -68. demand_def(a_ATM4,d_DATE7) -924.5 + z(94_ATM4,5) demand_def(a_ATM4,d_DATE8) -221.5 demand_def(a_ATM4,d_DATE9) -475.5 + z(94_ATM4,5) ztox1(a_ATM4,t_5) 1. ztox2(a_ATM4,t_5) 1. + z(94_ATM4,5) ztox3(a_ATM4,t_5) 1. + z(95_ATM4,6) demand_def(a_ATM4,d_DATE0) 90.6 demand_def(a_ATM4,d_DATE1) 486.6 + z(95_ATM4,6) demand_def(a_ATM4,d_DATE2) -1986. demand_def(a_ATM4,d_DATE3) -625.8 + z(95_ATM4,6) demand_def(a_ATM4,d_DATE4) -1073.4 demand_def(a_ATM4,d_DATE5) -207.6 + z(95_ATM4,6) demand_def(a_ATM4,d_DATE6) -81.6 demand_def(a_ATM4,d_DATE7) -1109.4 + z(95_ATM4,6) demand_def(a_ATM4,d_DATE8) -265.8 demand_def(a_ATM4,d_DATE9) -570.6 + z(95_ATM4,6) ztox1(a_ATM4,t_6) 1. ztox2(a_ATM4,t_6) 1. + z(95_ATM4,6) ztox3(a_ATM4,t_6) 1. + z(96_ATM4,7) demand_def(a_ATM4,d_DATE0) 105.7 demand_def(a_ATM4,d_DATE1) 567.7 + z(96_ATM4,7) demand_def(a_ATM4,d_DATE2) -2317. demand_def(a_ATM4,d_DATE3) -730.1 + z(96_ATM4,7) demand_def(a_ATM4,d_DATE4) -1252.3 demand_def(a_ATM4,d_DATE5) -242.2 + z(96_ATM4,7) demand_def(a_ATM4,d_DATE6) -95.2 demand_def(a_ATM4,d_DATE7) -1294.3 + z(96_ATM4,7) demand_def(a_ATM4,d_DATE8) -310.1 demand_def(a_ATM4,d_DATE9) -665.7 + z(96_ATM4,7) ztox1(a_ATM4,t_7) 1. ztox2(a_ATM4,t_7) 1. + z(96_ATM4,7) ztox3(a_ATM4,t_7) 1. + z(97_ATM4,8) demand_def(a_ATM4,d_DATE0) 120.8 demand_def(a_ATM4,d_DATE1) 648.8 + z(97_ATM4,8) demand_def(a_ATM4,d_DATE2) -2648. demand_def(a_ATM4,d_DATE3) -834.4 + z(97_ATM4,8) demand_def(a_ATM4,d_DATE4) -1431.2 demand_def(a_ATM4,d_DATE5) -276.8 + z(97_ATM4,8) demand_def(a_ATM4,d_DATE6) -108.8 demand_def(a_ATM4,d_DATE7) -1479.2 + z(97_ATM4,8) demand_def(a_ATM4,d_DATE8) -354.4 demand_def(a_ATM4,d_DATE9) -760.8 + z(97_ATM4,8) ztox1(a_ATM4,t_8) 1. ztox2(a_ATM4,t_8) 1. + z(97_ATM4,8) ztox3(a_ATM4,t_8) 1. + z(98_ATM4,9) demand_def(a_ATM4,d_DATE0) 135.9 demand_def(a_ATM4,d_DATE1) 729.9 + z(98_ATM4,9) demand_def(a_ATM4,d_DATE2) -2979. demand_def(a_ATM4,d_DATE3) -938.7 + z(98_ATM4,9) demand_def(a_ATM4,d_DATE4) -1610.1 demand_def(a_ATM4,d_DATE5) -311.4 + z(98_ATM4,9) demand_def(a_ATM4,d_DATE6) -122.4 demand_def(a_ATM4,d_DATE7) -1664.1 + z(98_ATM4,9) demand_def(a_ATM4,d_DATE8) -398.7 demand_def(a_ATM4,d_DATE9) -855.9 + z(98_ATM4,9) ztox1(a_ATM4,t_9) 1. ztox2(a_ATM4,t_9) 1. + z(98_ATM4,9) ztox3(a_ATM4,t_9) 1. + z(99_ATM4,10) demand_def(a_ATM4,d_DATE0) 151. demand_def(a_ATM4,d_DATE1) 811. + z(99_ATM4,10) demand_def(a_ATM4,d_DATE2) -3310. demand_def(a_ATM4,d_DATE3) -1043. + z(99_ATM4,10) demand_def(a_ATM4,d_DATE4) -1789. demand_def(a_ATM4,d_DATE5) -346. + z(99_ATM4,10) demand_def(a_ATM4,d_DATE6) -136. demand_def(a_ATM4,d_DATE7) -1849. + z(99_ATM4,10) demand_def(a_ATM4,d_DATE8) -443. demand_def(a_ATM4,d_DATE9) -951. + z(99_ATM4,10) ztox1(a_ATM4,t_10) 1. ztox2(a_ATM4,t_10) 1. + z(99_ATM4,10) ztox3(a_ATM4,t_10) 1. + fp(100_ATM0,DATE0) OBJROW 1. budget(d_DATE0) 1. + fp(100_ATM0,DATE0) demand_def(a_ATM0,d_DATE0) 1. + fp(101_ATM0,DATE1) OBJROW 1. budget(d_DATE1) 1. + fp(101_ATM0,DATE1) demand_def(a_ATM0,d_DATE1) 1. + fp(102_ATM0,DATE2) OBJROW 1. budget(d_DATE2) 1. + fp(102_ATM0,DATE2) demand_def(a_ATM0,d_DATE2) 1. + fp(103_ATM0,DATE3) OBJROW 1. budget(d_DATE3) 1. + fp(103_ATM0,DATE3) demand_def(a_ATM0,d_DATE3) 1. + fp(104_ATM0,DATE4) OBJROW 1. budget(d_DATE4) 1. + fp(104_ATM0,DATE4) demand_def(a_ATM0,d_DATE4) 1. + fp(105_ATM0,DATE5) OBJROW 1. budget(d_DATE5) 1. + fp(105_ATM0,DATE5) demand_def(a_ATM0,d_DATE5) 1. + fp(106_ATM0,DATE6) OBJROW 1. budget(d_DATE6) 1. + fp(106_ATM0,DATE6) demand_def(a_ATM0,d_DATE6) 1. + fp(107_ATM0,DATE7) OBJROW 1. budget(d_DATE7) 1. + fp(107_ATM0,DATE7) demand_def(a_ATM0,d_DATE7) 1. + fp(108_ATM0,DATE8) OBJROW 1. budget(d_DATE8) 1. + fp(108_ATM0,DATE8) demand_def(a_ATM0,d_DATE8) 1. + fp(109_ATM0,DATE9) OBJROW 1. budget(d_DATE9) 1. + fp(109_ATM0,DATE9) demand_def(a_ATM0,d_DATE9) 1. + fp(110_ATM1,DATE0) OBJROW 1. budget(d_DATE0) 1. + fp(110_ATM1,DATE0) demand_def(a_ATM1,d_DATE0) 1. + fp(111_ATM1,DATE1) OBJROW 1. budget(d_DATE1) 1. + fp(111_ATM1,DATE1) demand_def(a_ATM1,d_DATE1) 1. + fp(112_ATM1,DATE2) OBJROW 1. budget(d_DATE2) 1. + fp(112_ATM1,DATE2) demand_def(a_ATM1,d_DATE2) 1. + fp(113_ATM1,DATE3) OBJROW 1. budget(d_DATE3) 1. + fp(113_ATM1,DATE3) demand_def(a_ATM1,d_DATE3) 1. + fp(114_ATM1,DATE4) OBJROW 1. budget(d_DATE4) 1. + fp(114_ATM1,DATE4) demand_def(a_ATM1,d_DATE4) 1. + fp(115_ATM1,DATE5) OBJROW 1. budget(d_DATE5) 1. + fp(115_ATM1,DATE5) demand_def(a_ATM1,d_DATE5) 1. + fp(116_ATM1,DATE6) OBJROW 1. budget(d_DATE6) 1. + fp(116_ATM1,DATE6) demand_def(a_ATM1,d_DATE6) 1. + fp(117_ATM1,DATE7) OBJROW 1. budget(d_DATE7) 1. + fp(117_ATM1,DATE7) demand_def(a_ATM1,d_DATE7) 1. + fp(118_ATM1,DATE8) OBJROW 1. budget(d_DATE8) 1. + fp(118_ATM1,DATE8) demand_def(a_ATM1,d_DATE8) 1. + fp(119_ATM1,DATE9) OBJROW 1. budget(d_DATE9) 1. + fp(119_ATM1,DATE9) demand_def(a_ATM1,d_DATE9) 1. + fp(120_ATM2,DATE0) OBJROW 1. budget(d_DATE0) 1. + fp(120_ATM2,DATE0) demand_def(a_ATM2,d_DATE0) 1. + fp(121_ATM2,DATE1) OBJROW 1. budget(d_DATE1) 1. + fp(121_ATM2,DATE1) demand_def(a_ATM2,d_DATE1) 1. + fp(122_ATM2,DATE2) OBJROW 1. budget(d_DATE2) 1. + fp(122_ATM2,DATE2) demand_def(a_ATM2,d_DATE2) 1. + fp(123_ATM2,DATE3) OBJROW 1. budget(d_DATE3) 1. + fp(123_ATM2,DATE3) demand_def(a_ATM2,d_DATE3) 1. + fp(124_ATM2,DATE4) OBJROW 1. budget(d_DATE4) 1. + fp(124_ATM2,DATE4) demand_def(a_ATM2,d_DATE4) 1. + fp(125_ATM2,DATE5) OBJROW 1. budget(d_DATE5) 1. + fp(125_ATM2,DATE5) demand_def(a_ATM2,d_DATE5) 1. + fp(126_ATM2,DATE6) OBJROW 1. budget(d_DATE6) 1. + fp(126_ATM2,DATE6) demand_def(a_ATM2,d_DATE6) 1. + fp(127_ATM2,DATE7) OBJROW 1. budget(d_DATE7) 1. + fp(127_ATM2,DATE7) demand_def(a_ATM2,d_DATE7) 1. + fp(128_ATM2,DATE8) OBJROW 1. budget(d_DATE8) 1. + fp(128_ATM2,DATE8) demand_def(a_ATM2,d_DATE8) 1. + fp(129_ATM2,DATE9) OBJROW 1. budget(d_DATE9) 1. + fp(129_ATM2,DATE9) demand_def(a_ATM2,d_DATE9) 1. + fp(130_ATM3,DATE0) OBJROW 1. budget(d_DATE0) 1. + fp(130_ATM3,DATE0) demand_def(a_ATM3,d_DATE0) 1. + fp(131_ATM3,DATE1) OBJROW 1. budget(d_DATE1) 1. + fp(131_ATM3,DATE1) demand_def(a_ATM3,d_DATE1) 1. + fp(132_ATM3,DATE2) OBJROW 1. budget(d_DATE2) 1. + fp(132_ATM3,DATE2) demand_def(a_ATM3,d_DATE2) 1. + fp(133_ATM3,DATE3) OBJROW 1. budget(d_DATE3) 1. + fp(133_ATM3,DATE3) demand_def(a_ATM3,d_DATE3) 1. + fp(134_ATM3,DATE4) OBJROW 1. budget(d_DATE4) 1. + fp(134_ATM3,DATE4) demand_def(a_ATM3,d_DATE4) 1. + fp(135_ATM3,DATE5) OBJROW 1. budget(d_DATE5) 1. + fp(135_ATM3,DATE5) demand_def(a_ATM3,d_DATE5) 1. + fp(136_ATM3,DATE6) OBJROW 1. budget(d_DATE6) 1. + fp(136_ATM3,DATE6) demand_def(a_ATM3,d_DATE6) 1. + fp(137_ATM3,DATE7) OBJROW 1. budget(d_DATE7) 1. + fp(137_ATM3,DATE7) demand_def(a_ATM3,d_DATE7) 1. + fp(138_ATM3,DATE8) OBJROW 1. budget(d_DATE8) 1. + fp(138_ATM3,DATE8) demand_def(a_ATM3,d_DATE8) 1. + fp(139_ATM3,DATE9) OBJROW 1. budget(d_DATE9) 1. + fp(139_ATM3,DATE9) demand_def(a_ATM3,d_DATE9) 1. + fp(140_ATM4,DATE0) OBJROW 1. budget(d_DATE0) 1. + fp(140_ATM4,DATE0) demand_def(a_ATM4,d_DATE0) 1. + fp(141_ATM4,DATE1) OBJROW 1. budget(d_DATE1) 1. + fp(141_ATM4,DATE1) demand_def(a_ATM4,d_DATE1) 1. + fp(142_ATM4,DATE2) OBJROW 1. budget(d_DATE2) 1. + fp(142_ATM4,DATE2) demand_def(a_ATM4,d_DATE2) 1. + fp(143_ATM4,DATE3) OBJROW 1. budget(d_DATE3) 1. + fp(143_ATM4,DATE3) demand_def(a_ATM4,d_DATE3) 1. + fp(144_ATM4,DATE4) OBJROW 1. budget(d_DATE4) 1. + fp(144_ATM4,DATE4) demand_def(a_ATM4,d_DATE4) 1. + fp(145_ATM4,DATE5) OBJROW 1. budget(d_DATE5) 1. + fp(145_ATM4,DATE5) demand_def(a_ATM4,d_DATE5) 1. + fp(146_ATM4,DATE6) OBJROW 1. budget(d_DATE6) 1. + fp(146_ATM4,DATE6) demand_def(a_ATM4,d_DATE6) 1. + fp(147_ATM4,DATE7) OBJROW 1. budget(d_DATE7) 1. + fp(147_ATM4,DATE7) demand_def(a_ATM4,d_DATE7) 1. + fp(148_ATM4,DATE8) OBJROW 1. budget(d_DATE8) 1. + fp(148_ATM4,DATE8) demand_def(a_ATM4,d_DATE8) 1. + fp(149_ATM4,DATE9) OBJROW 1. budget(d_DATE9) 1. + fp(149_ATM4,DATE9) demand_def(a_ATM4,d_DATE9) 1. + fm(150_ATM0,DATE0) OBJROW 1. budget(d_DATE0) -1. + fm(150_ATM0,DATE0) demand_def(a_ATM0,d_DATE0) -1. linkv(a_ATM0,d_DATE0) 1. + fm(151_ATM0,DATE1) OBJROW 1. budget(d_DATE1) -1. + fm(151_ATM0,DATE1) demand_def(a_ATM0,d_DATE1) -1. linkv(a_ATM0,d_DATE1) 1. + fm(152_ATM0,DATE2) OBJROW 1. budget(d_DATE2) -1. + fm(152_ATM0,DATE2) demand_def(a_ATM0,d_DATE2) -1. linkv(a_ATM0,d_DATE2) 1. + fm(153_ATM0,DATE3) OBJROW 1. budget(d_DATE3) -1. + fm(153_ATM0,DATE3) demand_def(a_ATM0,d_DATE3) -1. linkv(a_ATM0,d_DATE3) 1. + fm(154_ATM0,DATE4) OBJROW 1. budget(d_DATE4) -1. + fm(154_ATM0,DATE4) demand_def(a_ATM0,d_DATE4) -1. linkv(a_ATM0,d_DATE4) 1. + fm(155_ATM0,DATE5) OBJROW 1. budget(d_DATE5) -1. + fm(155_ATM0,DATE5) demand_def(a_ATM0,d_DATE5) -1. linkv(a_ATM0,d_DATE5) 1. + fm(156_ATM0,DATE6) OBJROW 1. budget(d_DATE6) -1. + fm(156_ATM0,DATE6) demand_def(a_ATM0,d_DATE6) -1. linkv(a_ATM0,d_DATE6) 1. + fm(157_ATM0,DATE7) OBJROW 1. budget(d_DATE7) -1. + fm(157_ATM0,DATE7) demand_def(a_ATM0,d_DATE7) -1. linkv(a_ATM0,d_DATE7) 1. + fm(158_ATM0,DATE8) OBJROW 1. budget(d_DATE8) -1. + fm(158_ATM0,DATE8) demand_def(a_ATM0,d_DATE8) -1. linkv(a_ATM0,d_DATE8) 1. + fm(159_ATM0,DATE9) OBJROW 1. budget(d_DATE9) -1. + fm(159_ATM0,DATE9) demand_def(a_ATM0,d_DATE9) -1. linkv(a_ATM0,d_DATE9) 1. + fm(160_ATM1,DATE0) OBJROW 1. budget(d_DATE0) -1. + fm(160_ATM1,DATE0) demand_def(a_ATM1,d_DATE0) -1. linkv(a_ATM1,d_DATE0) 1. + fm(161_ATM1,DATE1) OBJROW 1. budget(d_DATE1) -1. + fm(161_ATM1,DATE1) demand_def(a_ATM1,d_DATE1) -1. linkv(a_ATM1,d_DATE1) 1. + fm(162_ATM1,DATE2) OBJROW 1. budget(d_DATE2) -1. + fm(162_ATM1,DATE2) demand_def(a_ATM1,d_DATE2) -1. linkv(a_ATM1,d_DATE2) 1. + fm(163_ATM1,DATE3) OBJROW 1. budget(d_DATE3) -1. + fm(163_ATM1,DATE3) demand_def(a_ATM1,d_DATE3) -1. linkv(a_ATM1,d_DATE3) 1. + fm(164_ATM1,DATE4) OBJROW 1. budget(d_DATE4) -1. + fm(164_ATM1,DATE4) demand_def(a_ATM1,d_DATE4) -1. linkv(a_ATM1,d_DATE4) 1. + fm(165_ATM1,DATE5) OBJROW 1. budget(d_DATE5) -1. + fm(165_ATM1,DATE5) demand_def(a_ATM1,d_DATE5) -1. linkv(a_ATM1,d_DATE5) 1. + fm(166_ATM1,DATE6) OBJROW 1. budget(d_DATE6) -1. + fm(166_ATM1,DATE6) demand_def(a_ATM1,d_DATE6) -1. linkv(a_ATM1,d_DATE6) 1. + fm(167_ATM1,DATE7) OBJROW 1. budget(d_DATE7) -1. + fm(167_ATM1,DATE7) demand_def(a_ATM1,d_DATE7) -1. linkv(a_ATM1,d_DATE7) 1. + fm(168_ATM1,DATE8) OBJROW 1. budget(d_DATE8) -1. + fm(168_ATM1,DATE8) demand_def(a_ATM1,d_DATE8) -1. linkv(a_ATM1,d_DATE8) 1. + fm(169_ATM1,DATE9) OBJROW 1. budget(d_DATE9) -1. + fm(169_ATM1,DATE9) demand_def(a_ATM1,d_DATE9) -1. linkv(a_ATM1,d_DATE9) 1. + fm(170_ATM2,DATE0) OBJROW 1. budget(d_DATE0) -1. + fm(170_ATM2,DATE0) demand_def(a_ATM2,d_DATE0) -1. linkv(a_ATM2,d_DATE0) 1. + fm(171_ATM2,DATE1) OBJROW 1. budget(d_DATE1) -1. + fm(171_ATM2,DATE1) demand_def(a_ATM2,d_DATE1) -1. linkv(a_ATM2,d_DATE1) 1. + fm(172_ATM2,DATE2) OBJROW 1. budget(d_DATE2) -1. + fm(172_ATM2,DATE2) demand_def(a_ATM2,d_DATE2) -1. linkv(a_ATM2,d_DATE2) 1. + fm(173_ATM2,DATE3) OBJROW 1. budget(d_DATE3) -1. + fm(173_ATM2,DATE3) demand_def(a_ATM2,d_DATE3) -1. linkv(a_ATM2,d_DATE3) 1. + fm(174_ATM2,DATE4) OBJROW 1. budget(d_DATE4) -1. + fm(174_ATM2,DATE4) demand_def(a_ATM2,d_DATE4) -1. linkv(a_ATM2,d_DATE4) 1. + fm(175_ATM2,DATE5) OBJROW 1. budget(d_DATE5) -1. + fm(175_ATM2,DATE5) demand_def(a_ATM2,d_DATE5) -1. linkv(a_ATM2,d_DATE5) 1. + fm(176_ATM2,DATE6) OBJROW 1. budget(d_DATE6) -1. + fm(176_ATM2,DATE6) demand_def(a_ATM2,d_DATE6) -1. linkv(a_ATM2,d_DATE6) 1. + fm(177_ATM2,DATE7) OBJROW 1. budget(d_DATE7) -1. + fm(177_ATM2,DATE7) demand_def(a_ATM2,d_DATE7) -1. linkv(a_ATM2,d_DATE7) 1. + fm(178_ATM2,DATE8) OBJROW 1. budget(d_DATE8) -1. + fm(178_ATM2,DATE8) demand_def(a_ATM2,d_DATE8) -1. linkv(a_ATM2,d_DATE8) 1. + fm(179_ATM2,DATE9) OBJROW 1. budget(d_DATE9) -1. + fm(179_ATM2,DATE9) demand_def(a_ATM2,d_DATE9) -1. linkv(a_ATM2,d_DATE9) 1. + fm(180_ATM3,DATE0) OBJROW 1. budget(d_DATE0) -1. + fm(180_ATM3,DATE0) demand_def(a_ATM3,d_DATE0) -1. linkv(a_ATM3,d_DATE0) 1. + fm(181_ATM3,DATE1) OBJROW 1. budget(d_DATE1) -1. + fm(181_ATM3,DATE1) demand_def(a_ATM3,d_DATE1) -1. linkv(a_ATM3,d_DATE1) 1. + fm(182_ATM3,DATE2) OBJROW 1. budget(d_DATE2) -1. + fm(182_ATM3,DATE2) demand_def(a_ATM3,d_DATE2) -1. linkv(a_ATM3,d_DATE2) 1. + fm(183_ATM3,DATE3) OBJROW 1. budget(d_DATE3) -1. + fm(183_ATM3,DATE3) demand_def(a_ATM3,d_DATE3) -1. linkv(a_ATM3,d_DATE3) 1. + fm(184_ATM3,DATE4) OBJROW 1. budget(d_DATE4) -1. + fm(184_ATM3,DATE4) demand_def(a_ATM3,d_DATE4) -1. linkv(a_ATM3,d_DATE4) 1. + fm(185_ATM3,DATE5) OBJROW 1. budget(d_DATE5) -1. + fm(185_ATM3,DATE5) demand_def(a_ATM3,d_DATE5) -1. linkv(a_ATM3,d_DATE5) 1. + fm(186_ATM3,DATE6) OBJROW 1. budget(d_DATE6) -1. + fm(186_ATM3,DATE6) demand_def(a_ATM3,d_DATE6) -1. linkv(a_ATM3,d_DATE6) 1. + fm(187_ATM3,DATE7) OBJROW 1. budget(d_DATE7) -1. + fm(187_ATM3,DATE7) demand_def(a_ATM3,d_DATE7) -1. linkv(a_ATM3,d_DATE7) 1. + fm(188_ATM3,DATE8) OBJROW 1. budget(d_DATE8) -1. + fm(188_ATM3,DATE8) demand_def(a_ATM3,d_DATE8) -1. linkv(a_ATM3,d_DATE8) 1. + fm(189_ATM3,DATE9) OBJROW 1. budget(d_DATE9) -1. + fm(189_ATM3,DATE9) demand_def(a_ATM3,d_DATE9) -1. linkv(a_ATM3,d_DATE9) 1. + fm(190_ATM4,DATE0) OBJROW 1. budget(d_DATE0) -1. + fm(190_ATM4,DATE0) demand_def(a_ATM4,d_DATE0) -1. linkv(a_ATM4,d_DATE0) 1. + fm(191_ATM4,DATE1) OBJROW 1. budget(d_DATE1) -1. + fm(191_ATM4,DATE1) demand_def(a_ATM4,d_DATE1) -1. linkv(a_ATM4,d_DATE1) 1. + fm(192_ATM4,DATE2) OBJROW 1. budget(d_DATE2) -1. + fm(192_ATM4,DATE2) demand_def(a_ATM4,d_DATE2) -1. linkv(a_ATM4,d_DATE2) 1. + fm(193_ATM4,DATE3) OBJROW 1. budget(d_DATE3) -1. + fm(193_ATM4,DATE3) demand_def(a_ATM4,d_DATE3) -1. linkv(a_ATM4,d_DATE3) 1. + fm(194_ATM4,DATE4) OBJROW 1. budget(d_DATE4) -1. + fm(194_ATM4,DATE4) demand_def(a_ATM4,d_DATE4) -1. linkv(a_ATM4,d_DATE4) 1. + fm(195_ATM4,DATE5) OBJROW 1. budget(d_DATE5) -1. + fm(195_ATM4,DATE5) demand_def(a_ATM4,d_DATE5) -1. linkv(a_ATM4,d_DATE5) 1. + fm(196_ATM4,DATE6) OBJROW 1. budget(d_DATE6) -1. + fm(196_ATM4,DATE6) demand_def(a_ATM4,d_DATE6) -1. linkv(a_ATM4,d_DATE6) 1. + fm(197_ATM4,DATE7) OBJROW 1. budget(d_DATE7) -1. + fm(197_ATM4,DATE7) demand_def(a_ATM4,d_DATE7) -1. linkv(a_ATM4,d_DATE7) 1. + fm(198_ATM4,DATE8) OBJROW 1. budget(d_DATE8) -1. + fm(198_ATM4,DATE8) demand_def(a_ATM4,d_DATE8) -1. linkv(a_ATM4,d_DATE8) 1. + fm(199_ATM4,DATE9) OBJROW 1. budget(d_DATE9) -1. + fm(199_ATM4,DATE9) demand_def(a_ATM4,d_DATE9) -1. linkv(a_ATM4,d_DATE9) 1. + x2(200_ATM0) demand_def(a_ATM0,d_DATE0) -1984. demand_def(a_ATM0,d_DATE1) -2530. + x2(200_ATM0) demand_def(a_ATM0,d_DATE2) 67. demand_def(a_ATM0,d_DATE3) 3135. + x2(200_ATM0) demand_def(a_ATM0,d_DATE4) 951. demand_def(a_ATM0,d_DATE5) -479. + x2(200_ATM0) demand_def(a_ATM0,d_DATE6) -3186. demand_def(a_ATM0,d_DATE7) -341. + x2(200_ATM0) demand_def(a_ATM0,d_DATE8) 643. demand_def(a_ATM0,d_DATE9) 931. + x2(200_ATM0) ztox2(a_ATM0,t_1) -1. ztox3(a_ATM0,t_1) -1. + x2(200_ATM0) ztox2(a_ATM0,t_2) -1. ztox3(a_ATM0,t_2) -1. + x2(200_ATM0) ztox2(a_ATM0,t_3) -1. ztox3(a_ATM0,t_3) -1. + x2(200_ATM0) ztox2(a_ATM0,t_4) -1. ztox3(a_ATM0,t_4) -1. + x2(200_ATM0) ztox2(a_ATM0,t_5) -1. ztox3(a_ATM0,t_5) -1. + x2(200_ATM0) ztox2(a_ATM0,t_6) -1. ztox3(a_ATM0,t_6) -1. + x2(200_ATM0) ztox2(a_ATM0,t_7) -1. ztox3(a_ATM0,t_7) -1. + x2(200_ATM0) ztox2(a_ATM0,t_8) -1. ztox3(a_ATM0,t_8) -1. + x2(200_ATM0) ztox2(a_ATM0,t_9) -1. ztox3(a_ATM0,t_9) -1. + x2(200_ATM0) ztox2(a_ATM0,t_10) -1. ztox3(a_ATM0,t_10) -1. + x2(201_ATM1) demand_def(a_ATM1,d_DATE0) -601. demand_def(a_ATM1,d_DATE1) -618. + x2(201_ATM1) demand_def(a_ATM1,d_DATE2) 610. demand_def(a_ATM1,d_DATE3) 1977. + x2(201_ATM1) demand_def(a_ATM1,d_DATE4) -1566. demand_def(a_ATM1,d_DATE5) 1480. + x2(201_ATM1) demand_def(a_ATM1,d_DATE6) -679. demand_def(a_ATM1,d_DATE7) -1375. + x2(201_ATM1) demand_def(a_ATM1,d_DATE8) -534. demand_def(a_ATM1,d_DATE9) -157. + x2(201_ATM1) ztox2(a_ATM1,t_1) -1. ztox3(a_ATM1,t_1) -1. + x2(201_ATM1) ztox2(a_ATM1,t_2) -1. ztox3(a_ATM1,t_2) -1. + x2(201_ATM1) ztox2(a_ATM1,t_3) -1. ztox3(a_ATM1,t_3) -1. + x2(201_ATM1) ztox2(a_ATM1,t_4) -1. ztox3(a_ATM1,t_4) -1. + x2(201_ATM1) ztox2(a_ATM1,t_5) -1. ztox3(a_ATM1,t_5) -1. + x2(201_ATM1) ztox2(a_ATM1,t_6) -1. ztox3(a_ATM1,t_6) -1. + x2(201_ATM1) ztox2(a_ATM1,t_7) -1. ztox3(a_ATM1,t_7) -1. + x2(201_ATM1) ztox2(a_ATM1,t_8) -1. ztox3(a_ATM1,t_8) -1. + x2(201_ATM1) ztox2(a_ATM1,t_9) -1. ztox3(a_ATM1,t_9) -1. + x2(201_ATM1) ztox2(a_ATM1,t_10) -1. ztox3(a_ATM1,t_10) -1. + x2(202_ATM2) demand_def(a_ATM2,d_DATE0) 691. demand_def(a_ATM2,d_DATE1) 2001. + x2(202_ATM2) demand_def(a_ATM2,d_DATE2) -2626. demand_def(a_ATM2,d_DATE3) -3649. + x2(202_ATM2) demand_def(a_ATM2,d_DATE4) 951. demand_def(a_ATM2,d_DATE5) 1376. + x2(202_ATM2) demand_def(a_ATM2,d_DATE6) -2067. demand_def(a_ATM2,d_DATE7) -1046. + x2(202_ATM2) demand_def(a_ATM2,d_DATE8) 574. demand_def(a_ATM2,d_DATE9) 1377. + x2(202_ATM2) ztox2(a_ATM2,t_1) -1. ztox3(a_ATM2,t_1) -1. + x2(202_ATM2) ztox2(a_ATM2,t_2) -1. ztox3(a_ATM2,t_2) -1. + x2(202_ATM2) ztox2(a_ATM2,t_3) -1. ztox3(a_ATM2,t_3) -1. + x2(202_ATM2) ztox2(a_ATM2,t_4) -1. ztox3(a_ATM2,t_4) -1. + x2(202_ATM2) ztox2(a_ATM2,t_5) -1. ztox3(a_ATM2,t_5) -1. + x2(202_ATM2) ztox2(a_ATM2,t_6) -1. ztox3(a_ATM2,t_6) -1. + x2(202_ATM2) ztox2(a_ATM2,t_7) -1. ztox3(a_ATM2,t_7) -1. + x2(202_ATM2) ztox2(a_ATM2,t_8) -1. ztox3(a_ATM2,t_8) -1. + x2(202_ATM2) ztox2(a_ATM2,t_9) -1. ztox3(a_ATM2,t_9) -1. + x2(202_ATM2) ztox2(a_ATM2,t_10) -1. ztox3(a_ATM2,t_10) -1. + x2(203_ATM3) demand_def(a_ATM3,d_DATE0) -2943. demand_def(a_ATM3,d_DATE1) -93. + x2(203_ATM3) demand_def(a_ATM3,d_DATE2) 451. demand_def(a_ATM3,d_DATE3) 1282. + x2(203_ATM3) demand_def(a_ATM3,d_DATE4) -1251. demand_def(a_ATM3,d_DATE5) 1141. + x2(203_ATM3) demand_def(a_ATM3,d_DATE6) 3214. demand_def(a_ATM3,d_DATE7) 976. + x2(203_ATM3) demand_def(a_ATM3,d_DATE8) 480. demand_def(a_ATM3,d_DATE9) 2369. + x2(203_ATM3) ztox2(a_ATM3,t_1) -1. ztox3(a_ATM3,t_1) -1. + x2(203_ATM3) ztox2(a_ATM3,t_2) -1. ztox3(a_ATM3,t_2) -1. + x2(203_ATM3) ztox2(a_ATM3,t_3) -1. ztox3(a_ATM3,t_3) -1. + x2(203_ATM3) ztox2(a_ATM3,t_4) -1. ztox3(a_ATM3,t_4) -1. + x2(203_ATM3) ztox2(a_ATM3,t_5) -1. ztox3(a_ATM3,t_5) -1. + x2(203_ATM3) ztox2(a_ATM3,t_6) -1. ztox3(a_ATM3,t_6) -1. + x2(203_ATM3) ztox2(a_ATM3,t_7) -1. ztox3(a_ATM3,t_7) -1. + x2(203_ATM3) ztox2(a_ATM3,t_8) -1. ztox3(a_ATM3,t_8) -1. + x2(203_ATM3) ztox2(a_ATM3,t_9) -1. ztox3(a_ATM3,t_9) -1. + x2(203_ATM3) ztox2(a_ATM3,t_10) -1. ztox3(a_ATM3,t_10) -1. + x2(204_ATM4) demand_def(a_ATM4,d_DATE0) -151. demand_def(a_ATM4,d_DATE1) -811. + x2(204_ATM4) demand_def(a_ATM4,d_DATE2) 3310. demand_def(a_ATM4,d_DATE3) 1043. + x2(204_ATM4) demand_def(a_ATM4,d_DATE4) 1789. demand_def(a_ATM4,d_DATE5) 346. + x2(204_ATM4) demand_def(a_ATM4,d_DATE6) 136. demand_def(a_ATM4,d_DATE7) 1849. + x2(204_ATM4) demand_def(a_ATM4,d_DATE8) 443. demand_def(a_ATM4,d_DATE9) 951. + x2(204_ATM4) ztox2(a_ATM4,t_1) -1. ztox3(a_ATM4,t_1) -1. + x2(204_ATM4) ztox2(a_ATM4,t_2) -1. ztox3(a_ATM4,t_2) -1. + x2(204_ATM4) ztox2(a_ATM4,t_3) -1. ztox3(a_ATM4,t_3) -1. + x2(204_ATM4) ztox2(a_ATM4,t_4) -1. ztox3(a_ATM4,t_4) -1. + x2(204_ATM4) ztox2(a_ATM4,t_5) -1. ztox3(a_ATM4,t_5) -1. + x2(204_ATM4) ztox2(a_ATM4,t_6) -1. ztox3(a_ATM4,t_6) -1. + x2(204_ATM4) ztox2(a_ATM4,t_7) -1. ztox3(a_ATM4,t_7) -1. + x2(204_ATM4) ztox2(a_ATM4,t_8) -1. ztox3(a_ATM4,t_8) -1. + x2(204_ATM4) ztox2(a_ATM4,t_9) -1. ztox3(a_ATM4,t_9) -1. + x2(204_ATM4) ztox2(a_ATM4,t_10) -1. ztox3(a_ATM4,t_10) -1. + x3(205_ATM0) demand_def(a_ATM0,d_DATE0) -1045. demand_def(a_ATM0,d_DATE1) -1510. + x3(205_ATM0) demand_def(a_ATM0,d_DATE2) -145. demand_def(a_ATM0,d_DATE3) -581. + x3(205_ATM0) demand_def(a_ATM0,d_DATE4) -74. demand_def(a_ATM0,d_DATE5) -1121. + x3(205_ATM0) demand_def(a_ATM0,d_DATE6) -757. demand_def(a_ATM0,d_DATE7) -843. + x3(205_ATM0) demand_def(a_ATM0,d_DATE8) -915. demand_def(a_ATM0,d_DATE9) -43. + x3(206_ATM1) demand_def(a_ATM1,d_DATE0) -1772. demand_def(a_ATM1,d_DATE1) -636. + x3(206_ATM1) demand_def(a_ATM1,d_DATE2) -825. demand_def(a_ATM1,d_DATE3) -20. + x3(206_ATM1) demand_def(a_ATM1,d_DATE4) -1262. demand_def(a_ATM1,d_DATE5) -976. + x3(206_ATM1) demand_def(a_ATM1,d_DATE6) -632. demand_def(a_ATM1,d_DATE7) -586. + x3(206_ATM1) demand_def(a_ATM1,d_DATE8) -655. demand_def(a_ATM1,d_DATE9) -859. + x3(207_ATM2) demand_def(a_ATM2,d_DATE0) -1229. demand_def(a_ATM2,d_DATE1) -410. + x3(207_ATM2) demand_def(a_ATM2,d_DATE2) -454. demand_def(a_ATM2,d_DATE3) -26. + x3(207_ATM2) demand_def(a_ATM2,d_DATE4) -958. demand_def(a_ATM2,d_DATE5) -443. + x3(207_ATM2) demand_def(a_ATM2,d_DATE6) -800. demand_def(a_ATM2,d_DATE7) -123. + x3(207_ATM2) demand_def(a_ATM2,d_DATE8) -396. demand_def(a_ATM2,d_DATE9) -82. + x3(208_ATM3) demand_def(a_ATM3,d_DATE0) -1593. demand_def(a_ATM3,d_DATE1) -1387. + x3(208_ATM3) demand_def(a_ATM3,d_DATE2) -1785. demand_def(a_ATM3,d_DATE3) -3317. + x3(208_ATM3) demand_def(a_ATM3,d_DATE4) -80. demand_def(a_ATM3,d_DATE5) -1642. + x3(208_ATM3) demand_def(a_ATM3,d_DATE6) -815. demand_def(a_ATM3,d_DATE7) -99. + x3(208_ATM3) demand_def(a_ATM3,d_DATE8) -242. demand_def(a_ATM3,d_DATE9) -1546. + x3(209_ATM4) demand_def(a_ATM4,d_DATE0) -92. demand_def(a_ATM4,d_DATE1) -2282. + x3(209_ATM4) demand_def(a_ATM4,d_DATE2) -404. demand_def(a_ATM4,d_DATE3) -504. + x3(209_ATM4) demand_def(a_ATM4,d_DATE4) -549. demand_def(a_ATM4,d_DATE5) -185. + x3(209_ATM4) demand_def(a_ATM4,d_DATE6) -624. demand_def(a_ATM4,d_DATE7) -2004. + x3(209_ATM4) demand_def(a_ATM4,d_DATE8) -1659. demand_def(a_ATM4,d_DATE9) -1204. + v(210_ATM0,DATE0) linkv(a_ATM0,d_DATE0) -780. count(a_ATM0) 1. + v(211_ATM0,DATE1) linkv(a_ATM0,d_DATE1) -2351. count(a_ATM0) 1. + v(212_ATM0,DATE2) linkv(a_ATM0,d_DATE2) -2288. count(a_ATM0) 1. + v(213_ATM0,DATE3) linkv(a_ATM0,d_DATE3) -1357. count(a_ATM0) 1. + v(214_ATM0,DATE4) linkv(a_ATM0,d_DATE4) -3637. count(a_ATM0) 1. + v(215_ATM0,DATE5) linkv(a_ATM0,d_DATE5) -1371. count(a_ATM0) 1. + v(216_ATM0,DATE6) linkv(a_ATM0,d_DATE6) -2225. count(a_ATM0) 1. + v(217_ATM0,DATE7) linkv(a_ATM0,d_DATE7) -1721. count(a_ATM0) 1. + v(218_ATM0,DATE8) linkv(a_ATM0,d_DATE8) -2110. count(a_ATM0) 1. + v(219_ATM0,DATE9) linkv(a_ATM0,d_DATE9) -3118. count(a_ATM0) 1. + v(220_ATM1,DATE0) linkv(a_ATM1,d_DATE0) -2830. count(a_ATM1) 1. + v(221_ATM1,DATE1) linkv(a_ATM1,d_DATE1) -184. count(a_ATM1) 1. + v(222_ATM1,DATE2) linkv(a_ATM1,d_DATE2) -282. count(a_ATM1) 1. + v(223_ATM1,DATE3) linkv(a_ATM1,d_DATE3) -998. count(a_ATM1) 1. + v(224_ATM1,DATE4) linkv(a_ATM1,d_DATE4) -3198. count(a_ATM1) 1. + v(225_ATM1,DATE5) linkv(a_ATM1,d_DATE5) -3170. count(a_ATM1) 1. + v(226_ATM1,DATE6) linkv(a_ATM1,d_DATE6) -2301. count(a_ATM1) 1. + v(227_ATM1,DATE7) linkv(a_ATM1,d_DATE7) -719. count(a_ATM1) 1. + v(228_ATM1,DATE8) linkv(a_ATM1,d_DATE8) -818. count(a_ATM1) 1. + v(229_ATM1,DATE9) linkv(a_ATM1,d_DATE9) -1426. count(a_ATM1) 1. + v(230_ATM2,DATE0) linkv(a_ATM2,d_DATE0) -2803. count(a_ATM2) 1. + v(231_ATM2,DATE1) linkv(a_ATM2,d_DATE1) -1031. count(a_ATM2) 1. + v(232_ATM2,DATE2) linkv(a_ATM2,d_DATE2) -23. count(a_ATM2) 1. + v(233_ATM2,DATE3) linkv(a_ATM2,d_DATE3) -376. count(a_ATM2) 1. + v(234_ATM2,DATE4) linkv(a_ATM2,d_DATE4) -541. count(a_ATM2) 1. + v(235_ATM2,DATE5) linkv(a_ATM2,d_DATE5) -2195. count(a_ATM2) 1. + v(236_ATM2,DATE6) linkv(a_ATM2,d_DATE6) -3676. count(a_ATM2) 1. + v(237_ATM2,DATE7) linkv(a_ATM2,d_DATE7) -2475. count(a_ATM2) 1. + v(238_ATM2,DATE8) linkv(a_ATM2,d_DATE8) -1232. count(a_ATM2) 1. + v(239_ATM2,DATE9) linkv(a_ATM2,d_DATE9) -352. count(a_ATM2) 1. + v(240_ATM3,DATE0) linkv(a_ATM3,d_DATE0) -853. count(a_ATM3) 1. + v(241_ATM3,DATE1) linkv(a_ATM3,d_DATE1) -2310. count(a_ATM3) 1. + v(242_ATM3,DATE2) linkv(a_ATM3,d_DATE2) -3542. count(a_ATM3) 1. + v(243_ATM3,DATE3) linkv(a_ATM3,d_DATE3) -739. count(a_ATM3) 1. + v(244_ATM3,DATE4) linkv(a_ATM3,d_DATE4) -1315. count(a_ATM3) 1. + v(245_ATM3,DATE5) linkv(a_ATM3,d_DATE5) -2929. count(a_ATM3) 1. + v(246_ATM3,DATE6) linkv(a_ATM3,d_DATE6) -2928. count(a_ATM3) 1. + v(247_ATM3,DATE7) linkv(a_ATM3,d_DATE7) -2101. count(a_ATM3) 1. + v(248_ATM3,DATE8) linkv(a_ATM3,d_DATE8) -3522. count(a_ATM3) 1. + v(249_ATM3,DATE9) linkv(a_ATM3,d_DATE9) -319. count(a_ATM3) 1. + v(250_ATM4,DATE0) linkv(a_ATM4,d_DATE0) -1184. count(a_ATM4) 1. + v(251_ATM4,DATE1) linkv(a_ATM4,d_DATE1) -181. count(a_ATM4) 1. + v(252_ATM4,DATE2) linkv(a_ATM4,d_DATE2) -1096. count(a_ATM4) 1. + v(253_ATM4,DATE3) linkv(a_ATM4,d_DATE3) -1568. count(a_ATM4) 1. + v(254_ATM4,DATE4) linkv(a_ATM4,d_DATE4) -2710. count(a_ATM4) 1. + v(255_ATM4,DATE5) linkv(a_ATM4,d_DATE5) -1096. count(a_ATM4) 1. + v(256_ATM4,DATE6) linkv(a_ATM4,d_DATE6) -3834. count(a_ATM4) 1. + v(257_ATM4,DATE7) linkv(a_ATM4,d_DATE7) -4214. count(a_ATM4) 1. + v(258_ATM4,DATE8) linkv(a_ATM4,d_DATE8) -1902. count(a_ATM4) 1. + v(259_ATM4,DATE9) linkv(a_ATM4,d_DATE9) -3280. count(a_ATM4) 1. +RHS + RHS budget(d_DATE0) 5829. budget(d_DATE1) 9829. + RHS budget(d_DATE2) 70. budget(d_DATE3) 841. + RHS budget(d_DATE4) 4915. budget(d_DATE5) 1100. + RHS budget(d_DATE6) 4915. budget(d_DATE7) 5622. + RHS budget(d_DATE8) 6264. budget(d_DATE9) 243. + RHS demand_def(a_ATM0,d_DATE0) 593. demand_def(a_ATM0,d_DATE1) -2177. + RHS demand_def(a_ATM0,d_DATE2) 532. demand_def(a_ATM0,d_DATE3) 1962. + RHS demand_def(a_ATM0,d_DATE4) -1590. demand_def(a_ATM0,d_DATE5) 799. + RHS demand_def(a_ATM0,d_DATE6) -324. demand_def(a_ATM0,d_DATE7) -368. + RHS demand_def(a_ATM0,d_DATE8) -532. demand_def(a_ATM0,d_DATE9) -1334. + RHS pickone_x1(a_ATM0) 1. count(a_ATM0) 4. + RHS ztox3(a_ATM0,t_1) -1. ztox3(a_ATM0,t_2) -1. + RHS ztox3(a_ATM0,t_3) -1. ztox3(a_ATM0,t_4) -1. + RHS ztox3(a_ATM0,t_5) -1. ztox3(a_ATM0,t_6) -1. + RHS ztox3(a_ATM0,t_7) -1. ztox3(a_ATM0,t_8) -1. + RHS ztox3(a_ATM0,t_9) -1. ztox3(a_ATM0,t_10) -1. + RHS demand_def(a_ATM1,d_DATE0) -568. demand_def(a_ATM1,d_DATE1) 891. + RHS demand_def(a_ATM1,d_DATE2) 2781. demand_def(a_ATM1,d_DATE3) 1922. + RHS demand_def(a_ATM1,d_DATE4) -1703. demand_def(a_ATM1,d_DATE5) -517. + RHS demand_def(a_ATM1,d_DATE6) -1402. demand_def(a_ATM1,d_DATE7) 438. + RHS demand_def(a_ATM1,d_DATE8) 635. demand_def(a_ATM1,d_DATE9) 355. + RHS pickone_x1(a_ATM1) 1. count(a_ATM1) 3. + RHS ztox3(a_ATM1,t_1) -1. ztox3(a_ATM1,t_2) -1. + RHS ztox3(a_ATM1,t_3) -1. ztox3(a_ATM1,t_4) -1. + RHS ztox3(a_ATM1,t_5) -1. ztox3(a_ATM1,t_6) -1. + RHS ztox3(a_ATM1,t_7) -1. ztox3(a_ATM1,t_8) -1. + RHS ztox3(a_ATM1,t_9) -1. ztox3(a_ATM1,t_10) -1. + RHS demand_def(a_ATM2,d_DATE0) -1935. demand_def(a_ATM2,d_DATE1) 1043. + RHS demand_def(a_ATM2,d_DATE2) 771. demand_def(a_ATM2,d_DATE3) 480. + RHS demand_def(a_ATM2,d_DATE4) 1669. demand_def(a_ATM2,d_DATE5) 29. + RHS demand_def(a_ATM2,d_DATE6) -2933. demand_def(a_ATM2,d_DATE7) -627. + RHS demand_def(a_ATM2,d_DATE8) 1009. demand_def(a_ATM2,d_DATE9) 2157. + RHS pickone_x1(a_ATM2) 1. count(a_ATM2) 3. + RHS ztox3(a_ATM2,t_1) -1. ztox3(a_ATM2,t_2) -1. + RHS ztox3(a_ATM2,t_3) -1. ztox3(a_ATM2,t_4) -1. + RHS ztox3(a_ATM2,t_5) -1. ztox3(a_ATM2,t_6) -1. + RHS ztox3(a_ATM2,t_7) -1. ztox3(a_ATM2,t_8) -1. + RHS ztox3(a_ATM2,t_9) -1. ztox3(a_ATM2,t_10) -1. + RHS demand_def(a_ATM3,d_DATE0) -178. demand_def(a_ATM3,d_DATE1) 286. + RHS demand_def(a_ATM3,d_DATE2) -2323. demand_def(a_ATM3,d_DATE3) 940. + RHS demand_def(a_ATM3,d_DATE4) -130. demand_def(a_ATM3,d_DATE5) -1206. + RHS demand_def(a_ATM3,d_DATE6) 469. demand_def(a_ATM3,d_DATE7) -969. + RHS demand_def(a_ATM3,d_DATE8) -2804. demand_def(a_ATM3,d_DATE9) 3330. + RHS pickone_x1(a_ATM3) 1. count(a_ATM3) 7. + RHS ztox3(a_ATM3,t_1) -1. ztox3(a_ATM3,t_2) -1. + RHS ztox3(a_ATM3,t_3) -1. ztox3(a_ATM3,t_4) -1. + RHS ztox3(a_ATM3,t_5) -1. ztox3(a_ATM3,t_6) -1. + RHS ztox3(a_ATM3,t_7) -1. ztox3(a_ATM3,t_8) -1. + RHS ztox3(a_ATM3,t_9) -1. ztox3(a_ATM3,t_10) -1. + RHS demand_def(a_ATM4,d_DATE0) -144. demand_def(a_ATM4,d_DATE1) 359. + RHS demand_def(a_ATM4,d_DATE2) 2349. demand_def(a_ATM4,d_DATE3) -184. + RHS demand_def(a_ATM4,d_DATE4) -55. demand_def(a_ATM4,d_DATE5) -698. + RHS demand_def(a_ATM4,d_DATE6) -3187. demand_def(a_ATM4,d_DATE7) -1890. + RHS demand_def(a_ATM4,d_DATE8) 1647. demand_def(a_ATM4,d_DATE9) 233. + RHS pickone_x1(a_ATM4) 1. count(a_ATM4) 5. + RHS ztox3(a_ATM4,t_1) -1. ztox3(a_ATM4,t_2) -1. + RHS ztox3(a_ATM4,t_3) -1. ztox3(a_ATM4,t_4) -1. + RHS ztox3(a_ATM4,t_5) -1. ztox3(a_ATM4,t_6) -1. + RHS ztox3(a_ATM4,t_7) -1. ztox3(a_ATM4,t_8) -1. + RHS ztox3(a_ATM4,t_9) -1. ztox3(a_ATM4,t_10) -1. +BOUNDS + BV BOUND x1(0_ATM0,1) 1. + BV BOUND x1(1_ATM0,2) 1. + BV BOUND x1(2_ATM0,3) 1. + BV BOUND x1(3_ATM0,4) 1. + BV BOUND x1(4_ATM0,5) 1. + BV BOUND x1(5_ATM0,6) 1. + BV BOUND x1(6_ATM0,7) 1. + BV BOUND x1(7_ATM0,8) 1. + BV BOUND x1(8_ATM0,9) 1. + BV BOUND x1(9_ATM0,10) 1. + BV BOUND x1(10_ATM1,1) 1. + BV BOUND x1(11_ATM1,2) 1. + BV BOUND x1(12_ATM1,3) 1. + BV BOUND x1(13_ATM1,4) 1. + BV BOUND x1(14_ATM1,5) 1. + BV BOUND x1(15_ATM1,6) 1. + BV BOUND x1(16_ATM1,7) 1. + BV BOUND x1(17_ATM1,8) 1. + BV BOUND x1(18_ATM1,9) 1. + BV BOUND x1(19_ATM1,10) 1. + BV BOUND x1(20_ATM2,1) 1. + BV BOUND x1(21_ATM2,2) 1. + BV BOUND x1(22_ATM2,3) 1. + BV BOUND x1(23_ATM2,4) 1. + BV BOUND x1(24_ATM2,5) 1. + BV BOUND x1(25_ATM2,6) 1. + BV BOUND x1(26_ATM2,7) 1. + BV BOUND x1(27_ATM2,8) 1. + BV BOUND x1(28_ATM2,9) 1. + BV BOUND x1(29_ATM2,10) 1. + BV BOUND x1(30_ATM3,1) 1. + BV BOUND x1(31_ATM3,2) 1. + BV BOUND x1(32_ATM3,3) 1. + BV BOUND x1(33_ATM3,4) 1. + BV BOUND x1(34_ATM3,5) 1. + BV BOUND x1(35_ATM3,6) 1. + BV BOUND x1(36_ATM3,7) 1. + BV BOUND x1(37_ATM3,8) 1. + BV BOUND x1(38_ATM3,9) 1. + BV BOUND x1(39_ATM3,10) 1. + BV BOUND x1(40_ATM4,1) 1. + BV BOUND x1(41_ATM4,2) 1. + BV BOUND x1(42_ATM4,3) 1. + BV BOUND x1(43_ATM4,4) 1. + BV BOUND x1(44_ATM4,5) 1. + BV BOUND x1(45_ATM4,6) 1. + BV BOUND x1(46_ATM4,7) 1. + BV BOUND x1(47_ATM4,8) 1. + BV BOUND x1(48_ATM4,9) 1. + BV BOUND x1(49_ATM4,10) 1. + UP BOUND z(50_ATM0,1) 1. + UP BOUND z(51_ATM0,2) 1. + UP BOUND z(52_ATM0,3) 1. + UP BOUND z(53_ATM0,4) 1. + UP BOUND z(54_ATM0,5) 1. + UP BOUND z(55_ATM0,6) 1. + UP BOUND z(56_ATM0,7) 1. + UP BOUND z(57_ATM0,8) 1. + UP BOUND z(58_ATM0,9) 1. + UP BOUND z(59_ATM0,10) 1. + UP BOUND z(60_ATM1,1) 1. + UP BOUND z(61_ATM1,2) 1. + UP BOUND z(62_ATM1,3) 1. + UP BOUND z(63_ATM1,4) 1. + UP BOUND z(64_ATM1,5) 1. + UP BOUND z(65_ATM1,6) 1. + UP BOUND z(66_ATM1,7) 1. + UP BOUND z(67_ATM1,8) 1. + UP BOUND z(68_ATM1,9) 1. + UP BOUND z(69_ATM1,10) 1. + UP BOUND z(70_ATM2,1) 1. + UP BOUND z(71_ATM2,2) 1. + UP BOUND z(72_ATM2,3) 1. + UP BOUND z(73_ATM2,4) 1. + UP BOUND z(74_ATM2,5) 1. + UP BOUND z(75_ATM2,6) 1. + UP BOUND z(76_ATM2,7) 1. + UP BOUND z(77_ATM2,8) 1. + UP BOUND z(78_ATM2,9) 1. + UP BOUND z(79_ATM2,10) 1. + UP BOUND z(80_ATM3,1) 1. + UP BOUND z(81_ATM3,2) 1. + UP BOUND z(82_ATM3,3) 1. + UP BOUND z(83_ATM3,4) 1. + UP BOUND z(84_ATM3,5) 1. + UP BOUND z(85_ATM3,6) 1. + UP BOUND z(86_ATM3,7) 1. + UP BOUND z(87_ATM3,8) 1. + UP BOUND z(88_ATM3,9) 1. + UP BOUND z(89_ATM3,10) 1. + UP BOUND z(90_ATM4,1) 1. + UP BOUND z(91_ATM4,2) 1. + UP BOUND z(92_ATM4,3) 1. + UP BOUND z(93_ATM4,4) 1. + UP BOUND z(94_ATM4,5) 1. + UP BOUND z(95_ATM4,6) 1. + UP BOUND z(96_ATM4,7) 1. + UP BOUND z(97_ATM4,8) 1. + UP BOUND z(98_ATM4,9) 1. + UP BOUND z(99_ATM4,10) 1. + UP BOUND fm(150_ATM0,DATE0) 780. + UP BOUND fm(151_ATM0,DATE1) 2351. + UP BOUND fm(152_ATM0,DATE2) 2288. + UP BOUND fm(153_ATM0,DATE3) 1357. + UP BOUND fm(154_ATM0,DATE4) 3637. + UP BOUND fm(155_ATM0,DATE5) 1371. + UP BOUND fm(156_ATM0,DATE6) 2225. + UP BOUND fm(157_ATM0,DATE7) 1721. + UP BOUND fm(158_ATM0,DATE8) 2110. + UP BOUND fm(159_ATM0,DATE9) 3118. + UP BOUND fm(160_ATM1,DATE0) 2830. + UP BOUND fm(161_ATM1,DATE1) 184. + UP BOUND fm(162_ATM1,DATE2) 282. + UP BOUND fm(163_ATM1,DATE3) 998. + UP BOUND fm(164_ATM1,DATE4) 3198. + UP BOUND fm(165_ATM1,DATE5) 3170. + UP BOUND fm(166_ATM1,DATE6) 2301. + UP BOUND fm(167_ATM1,DATE7) 719. + UP BOUND fm(168_ATM1,DATE8) 818. + UP BOUND fm(169_ATM1,DATE9) 1426. + UP BOUND fm(170_ATM2,DATE0) 2803. + UP BOUND fm(171_ATM2,DATE1) 1031. + UP BOUND fm(172_ATM2,DATE2) 23. + UP BOUND fm(173_ATM2,DATE3) 376. + UP BOUND fm(174_ATM2,DATE4) 541. + UP BOUND fm(175_ATM2,DATE5) 2195. + UP BOUND fm(176_ATM2,DATE6) 3676. + UP BOUND fm(177_ATM2,DATE7) 2475. + UP BOUND fm(178_ATM2,DATE8) 1232. + UP BOUND fm(179_ATM2,DATE9) 352. + UP BOUND fm(180_ATM3,DATE0) 853. + UP BOUND fm(181_ATM3,DATE1) 2310. + UP BOUND fm(182_ATM3,DATE2) 3542. + UP BOUND fm(183_ATM3,DATE3) 739. + UP BOUND fm(184_ATM3,DATE4) 1315. + UP BOUND fm(185_ATM3,DATE5) 2929. + UP BOUND fm(186_ATM3,DATE6) 2928. + UP BOUND fm(187_ATM3,DATE7) 2101. + UP BOUND fm(188_ATM3,DATE8) 3522. + UP BOUND fm(189_ATM3,DATE9) 319. + UP BOUND fm(190_ATM4,DATE0) 1184. + UP BOUND fm(191_ATM4,DATE1) 181. + UP BOUND fm(192_ATM4,DATE2) 1096. + UP BOUND fm(193_ATM4,DATE3) 1568. + UP BOUND fm(194_ATM4,DATE4) 2710. + UP BOUND fm(195_ATM4,DATE5) 1096. + UP BOUND fm(196_ATM4,DATE6) 3834. + UP BOUND fm(197_ATM4,DATE7) 4214. + UP BOUND fm(198_ATM4,DATE8) 1902. + UP BOUND fm(199_ATM4,DATE9) 3280. + UP BOUND x2(200_ATM0) 1. + UP BOUND x2(201_ATM1) 1. + UP BOUND x2(202_ATM2) 1. + UP BOUND x2(203_ATM3) 1. + UP BOUND x2(204_ATM4) 1. + UP BOUND x3(205_ATM0) 1000. + UP BOUND x3(206_ATM1) 1000. + UP BOUND x3(207_ATM2) 1000. + UP BOUND x3(208_ATM3) 1000. + UP BOUND x3(209_ATM4) 1000. + BV BOUND v(210_ATM0,DATE0) 1. + BV BOUND v(211_ATM0,DATE1) 1. + BV BOUND v(212_ATM0,DATE2) 1. + BV BOUND v(213_ATM0,DATE3) 1. + BV BOUND v(214_ATM0,DATE4) 1. + BV BOUND v(215_ATM0,DATE5) 1. + BV BOUND v(216_ATM0,DATE6) 1. + BV BOUND v(217_ATM0,DATE7) 1. + BV BOUND v(218_ATM0,DATE8) 1. + BV BOUND v(219_ATM0,DATE9) 1. + BV BOUND v(220_ATM1,DATE0) 1. + BV BOUND v(221_ATM1,DATE1) 1. + BV BOUND v(222_ATM1,DATE2) 1. + BV BOUND v(223_ATM1,DATE3) 1. + BV BOUND v(224_ATM1,DATE4) 1. + BV BOUND v(225_ATM1,DATE5) 1. + BV BOUND v(226_ATM1,DATE6) 1. + BV BOUND v(227_ATM1,DATE7) 1. + BV BOUND v(228_ATM1,DATE8) 1. + BV BOUND v(229_ATM1,DATE9) 1. + BV BOUND v(230_ATM2,DATE0) 1. + BV BOUND v(231_ATM2,DATE1) 1. + BV BOUND v(232_ATM2,DATE2) 1. + BV BOUND v(233_ATM2,DATE3) 1. + BV BOUND v(234_ATM2,DATE4) 1. + BV BOUND v(235_ATM2,DATE5) 1. + BV BOUND v(236_ATM2,DATE6) 1. + BV BOUND v(237_ATM2,DATE7) 1. + BV BOUND v(238_ATM2,DATE8) 1. + BV BOUND v(239_ATM2,DATE9) 1. + BV BOUND v(240_ATM3,DATE0) 1. + BV BOUND v(241_ATM3,DATE1) 1. + BV BOUND v(242_ATM3,DATE2) 1. + BV BOUND v(243_ATM3,DATE3) 1. + BV BOUND v(244_ATM3,DATE4) 1. + BV BOUND v(245_ATM3,DATE5) 1. + BV BOUND v(246_ATM3,DATE6) 1. + BV BOUND v(247_ATM3,DATE7) 1. + BV BOUND v(248_ATM3,DATE8) 1. + BV BOUND v(249_ATM3,DATE9) 1. + BV BOUND v(250_ATM4,DATE0) 1. + BV BOUND v(251_ATM4,DATE1) 1. + BV BOUND v(252_ATM4,DATE2) 1. + BV BOUND v(253_ATM4,DATE3) 1. + BV BOUND v(254_ATM4,DATE4) 1. + BV BOUND v(255_ATM4,DATE5) 1. + BV BOUND v(256_ATM4,DATE6) 1. + BV BOUND v(257_ATM4,DATE7) 1. + BV BOUND v(258_ATM4,DATE8) 1. + BV BOUND v(259_ATM4,DATE9) 1. +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.dec b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.dec new file mode 100644 index 000000000..ec2e7826f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.dec @@ -0,0 +1,22 @@ +NBLOCKS +4 +BLOCK 1 +C_5.0_1.0 +C_6.0_1.0 +C_7.0_1.0 +BLOCK 2 +C_8.0_2.0 +C_9.0_2.0 +C_10.0_2.0 +C_11.0_2.0 +C_12.0_2.0 +BLOCK 3 +C_13.0_3.0 +C_14.0_3.0 +C_15.0_3.0 +C_16.0_3.0 +BLOCK 4 +C_17.0_4.0 +C_18.0_4.0 +C_19.0_4.0 +C_20.0_4.0 diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.lp b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.lp new file mode 100644 index 000000000..906bed2c7 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/block_milp.lp @@ -0,0 +1,73 @@ +\* MILP *\ +Minimize +Objective: - 20 x_1.0 - 7 x_10.0 - 4 x_11.0 - 9 x_12.0 - 8 x_13.0 - 2 x_14.0 + - 3 x_15.0 - 8 x_16.0 - 8 x_17.0 - 7 x_18.0 - 2 x_19.0 - 4 x_2.0 - 10 x_20.0 + - x_21.0 - 10 x_22.0 - 8 x_23.0 - 6 x_24.0 - 9 x_25.0 - 5 x_26.0 - 3 x_27.0 + - 8 x_28.0 - 5 x_29.0 - 3 x_3.0 - 9 x_30.0 - 7 x_31.0 - 2 x_32.0 - 2 x_33.0 + - 6 x_34.0 - 10 x_35.0 - 5 x_36.0 - 6 x_37.0 - 3 x_38.0 - 7 x_39.0 - x_4.0 + - 6 x_40.0 - 4 x_5.0 - 8 x_6.0 - 2 x_7.0 - 10 x_8.0 - 5 x_9.0 +Subject To +C_1.0: 2 x_11.0 + 8 x_13.0 + 10 x_20.0 + x_22.0 + 2 x_32.0 + 2 x_33.0 + 2 x_34.0 + + 5 x_37.0 + 5 x_7.0 + 7 x_8.0 + 6 x_9.0 <= 10 +C_2.0: x_13.0 + 8 x_2.0 + x_28.0 + 10 x_3.0 + 10 x_30.0 + 4 x_36.0 + 3 x_38.0 + + 9 x_7.0 <= 9 +C_3.0: 7 x_1.0 + 6 x_17.0 + 7 x_19.0 + 3 x_23.0 + 6 x_4.0 <= 7 +C_4.0: 3 x_16.0 + 4 x_29.0 + 8 x_3.0 + 10 x_34.0 + 3 x_37.0 + 8 x_40.0 <= 11 +C_5.0_1.0: 5 x_32.0 + 2 x_34.0 + 2 x_37.0 <= 4 +C_6.0_1.0: 4 x_33.0 + 4 x_38.0 + 3 x_39.0 <= 5 +C_7.0_1.0: 4 x_31.0 + 5 x_35.0 + 2 x_36.0 + 3 x_40.0 <= 6 +C_8.0_2.0: 5 x_24.0 + 7 x_30.0 <= 5 +C_9.0_2.0: 6 x_22.0 + 3 x_23.0 + 6 x_28.0 <= 5 +C_10.0_2.0: 10 x_22.0 + 6 x_24.0 + 4 x_26.0 <= 5 +C_11.0_2.0: 9 x_23.0 + 4 x_25.0 + 7 x_27.0 <= 4 +C_12.0_2.0: 4 x_22.0 + 8 x_24.0 + 2 x_30.0 <= 5 +C_13.0_3.0: 3 x_15.0 + x_21.0 <= 5 +C_14.0_3.0: 5 x_16.0 + 5 x_19.0 <= 4 +C_15.0_3.0: 3 x_17.0 + 4 x_20.0 <= 4 +C_16.0_3.0: 7 x_16.0 + 10 x_18.0 <= 5 +C_17.0_4.0: 3 x_11.0 + 6 x_14.0 + 2 x_6.0 + 3 x_9.0 <= 5 +C_18.0_4.0: 5 x_3.0 + 7 x_5.0 + x_9.0 <= 5 +C_19.0_4.0: 5 x_11.0 + 7 x_12.0 + 10 x_14.0 + 7 x_2.0 + 10 x_4.0 + x_8.0 <= 5 +C_20.0_4.0: 2 x_10.0 + 5 x_11.0 + 5 x_13.0 + 2 x_7.0 <= 4 +Binaries +x_1.0 +x_10.0 +x_11.0 +x_12.0 +x_13.0 +x_14.0 +x_15.0 +x_16.0 +x_17.0 +x_18.0 +x_19.0 +x_2.0 +x_20.0 +x_21.0 +x_22.0 +x_23.0 +x_24.0 +x_25.0 +x_26.0 +x_27.0 +x_28.0 +x_29.0 +x_3.0 +x_30.0 +x_31.0 +x_32.0 +x_33.0 +x_34.0 +x_35.0 +x_36.0 +x_37.0 +x_38.0 +x_39.0 +x_4.0 +x_40.0 +x_5.0 +x_6.0 +x_7.0 +x_8.0 +x_9.0 +End diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/brandy.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/brandy.mps new file mode 100644 index 000000000..50cf3c84b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/brandy.mps @@ -0,0 +1,1388 @@ +NAME BRANDY +ROWS + N 10000A + E 10001A + E 10002A + E 10003A + E 10004A + L 10006A + L 10007A + E 10008A + L 10009A + L 10010A + L 10011A + L 10012A + L 10013A + E 10014A + L 10015A + L 10016A + L 10017A + L 10018A + L 10019A + L 10020A + L 10021A + L 10022A + L 10023A + L 10024A + E 10025A + E 10026A + E 10027A + E 10028A + E 10029A + E 10030A + E 10031A + E 10032A + E 10033A + E 10034A + E 10035A + E 10036A + E 10037A + E 10038A + E 10039A + L 10040A + E 10041A + E 10042A + E 10043A + E 10044A + E 10045A + E 10046A + E 10047A + E 10048A + E 10049A + E 10050A + E 10051A + E 10052A + E 10053A + E 10054A + E 10055A + E 10056A + E 10057A + E 10058A + L 10059A + L 10060A + E 10061A + E 10062A + E 10063A + E 10064A + E 10065A + E 10066A + E 10067A + E 10068A + E 10069A + E 10070A + E 10071A + E 10072A + E 10073A + E 10074A + E 10075A + E 10076A + E 10077A + E 10078A + E 10079A + E 10080A + E 10081A + E 10082A + E 10083A + E 10084A + E 10085A + E 10086A + E 10087A + E 10088A + L 10089A + E 10090A + E 10091A + E 10092A + E 10093A + E 10094A + E 10095A + E 10096A + E 10097A + E 10098A + E 10099A + E 10100A + E 10101A + E 10102A + E 10103A + E 10104A + E 10105A + E 10106A + E 10107A + E 10108A + E 10109A + E 10110A + E 10111A + E 10112A + E 10113A + E 10114A + E 10115A + E 10116A + E 10117A + E 10118A + E 10119A + E 10120A + E 10121A + L 10122A + E 10123A + E 10124A + L 10125A + E 10126A + L 10127A + E 10128A + E 10129A + L 10130A + L 10131A + L 10132A + E 10133A + E 10134A + E 10135A + L 10136A + L 10137A + E 10138A + L 10139A + E 10140A + E 10141A + E 10142A + E 10143A + E 10144A + E 10145A + E 10146A + E 10147A + E 10148A + E 10149A + E 10150A + E 10151A + E 10152A + E 10153A + E 10154A + E 10155A + E 10156A + E 10157A + E 10158A + E 10159A + L 10160A + E 10161A + L 10162A + L 10163A + L 10164A + E 10165A + E 10166A + L 10167A + L 10168A + L 10169A + E 10170A + E 10171A + E 10172A + E 10173A + E 10174A + E 10175A + E 10176A + E 10177A + L 10178A + L 10179A + L 10180A + L 10181A + L 10182A + L 10183A + L 10184A + L 10185A + L 10186A + L 10187A + L 10188A + L 10189A + L 10190A + L 10191A + L 10192A + L 10193A + E 10194A + L 10195A + E 10196A + E 10197A + E 10198A + E 10199A + E 10200A + E 10201A + E 10202A + E 10203A + E 10204A + E 10205A + E 10206A + E 10207A + E 10208A + E 10209A + E 10210A + E 10211A + E 10212A + E 10213A + E 10214A + E 10215A + E 10216A + E 10217A + E 10218A + E 10219A + E 10220A + E 10221A +COLUMNS + 100001 10000A 1. 10056A -1. + 100002 10000A 1. 10025A -1. + 100100 10006A 1. 10008A 1. + 100100 10025A 7. 10043A .003 + 100100 10044A .067 10045A .022 + 100100 10056A .01 10063A .22 + 100100 10064A .1 10065A .112 + 100100 10066A .349 10068A .125 + 100100 10144A .02 + 100101 10006A 1. 10014A 1. + 100101 10025A 7.05 10043A .002 + 100101 10044A .012 10045A .003 + 100101 10047A .041 10048A .043 + 100101 10049A .017 10050A .09 + 100101 10051A .037 10056A .01 + 100101 10061A .006 10062A .12 + 100101 10065A .101 10066A .221 + 100101 10068A .161 10144A .02 + 100101 10154A .149 + 100103 10006A 1. 10014A 1. + 100103 10025A 7.05 10043A .002 + 100103 10044A .012 10045A .003 + 100103 10047A .041 10048A .043 + 100103 10049A .017 10050A .09 + 100103 10051A .062 10056A .01 + 100103 10061A .007 10063A .173 + 100103 10064A .063 10065A .107 + 100103 10066A .221 10068A .161 + 100103 10144A .02 + 100109 10094A 1. 10107A 1. + 100110 10006A 1. 10025A 7.6 + 100110 10043A .005 10044A .022 + 100110 10045A .005 10047A .061 + 100110 10048A .06 10049A .023 + 100110 10050A .117 10051A .074 + 100110 10056A .01 10061A .009 + 100110 10063A .17 10064A .062 + 100110 10065A .107 10066A .205 + 100110 10068A .08 10144A .02 + 100110 10160A 1. + 100112 10006A 1. 10025A 7.24 + 100112 10043A .003 10044A .015 + 100112 10045A .005 10047A .037 + 100112 10048A .048 10049A .045 + 100112 10050A .127 10051A .052 + 100112 10056A .01 10061A .005 + 100112 10063A .164 10064A .081 + 100112 10065A .102 10066A .252 + 100112 10068A .062 10144A .02 + 100112 10162A 1. + 100113 10006A 1. 10025A 7.17 + 100113 10043A .002 10044A .007 + 100113 10045A .002 10047A .036 + 100113 10048A .041 10049A .019 + 100113 10050A .098 10051A .058 + 100113 10056A .01 10061A .006 + 100113 10063A .179 10064A .068 + 100113 10065A .118 10066A .25 + 100113 10068A .117 10144A .02 + 100113 10163A 1. + 100114 10014A -1. 10164A 1. + 100120 10007A 1. 10010A 1. + 100120 10025A 6.64 10043A .002 + 100120 10044A .01 10045A .003 + 100120 10047A .05 10048A .053 + 100120 10049A .022 10050A .108 + 100120 10051A .065 10053A .133 + 100120 10054A .099 10055A .263 + 100120 10056A .02 10057A .181 + 100120 10061A .012 10144A .022 + 100121 10007A 1. 10009A 1. + 100121 10025A 5.9 10043A .001 + 100121 10044A .003 10045A .001 + 100121 10047A .021 10048A .022 + 100121 10049A .01 10050A .052 + 100121 10051A .042 10053A .122 + 100121 10054A .115 10055A .33 + 100121 10056A .02 10057A .276 + 100121 10061A .008 10144A .022 + 100122 10007A 1. 10025A 6.5 + 100122 10043A .001 10044A .004 + 100122 10045A .001 10047A .026 + 100122 10048A .028 10049A .013 + 100122 10050A .072 10051A .054 + 100122 10053A .158 10054A .155 + 100122 10055A .326 10056A .02 + 100122 10057A .154 10061A .011 + 100122 10144A .022 10167A 1. + 100125 10007A 1. 10010A 1. + 100125 10025A 6.64 10043A .002 + 100125 10044A .01 10045A .003 + 100125 10047A .05 10048A .053 + 100125 10049A .022 10050A .108 + 100125 10051A .065 10054A .032 + 100125 10055A .263 10056A .02 + 100125 10057A .181 10058A .2 + 100125 10061A .012 10144A .022 + 100125 10149A -2.23 10150A -.067 + 100126 10007A 1. 10009A 1. + 100126 10025A 5.9 10043A .001 + 100126 10044A .003 10045A .001 + 100126 10047A .021 10048A .022 + 100126 10049A .01 10050A .052 + 100126 10051A .042 10054A .04 + 100126 10055A .33 10056A .02 + 100126 10057A .276 10058A .197 + 100126 10061A .008 10144A .022 + 100126 10149A -2.52 10150A -.112 + 100130 10007A .67 10012A 1. + 100130 10025A 5.5 10044A .75 + 100130 10045A .25 10056A .03 + 100130 10144A .027 + 100131 10007A .67 10025A 7. + 100131 10044A .05 10045A .95 + 100131 10056A .03 10122A 1. + 100131 10144A .027 + 100132 10007A .67 10011A 1. + 100132 10025A 7.5 10047A .7 + 100132 10048A .2 10049A .1 + 100132 10056A .01 10144A .021 + 100133 10006A 1. 10025A 4. + 100133 10044A .75 10045A .25 + 100133 10056A .03 10144A .027 + 100133 10159A 1. + 100134 10025A 8.5 10044A .05 + 100134 10045A .95 + 100140 10048A -.71 10049A -.29 + 100140 10151A 1. + 100150 10043A -.13 10044A -.06 + 100150 10045A -.05 10046A -.04 + 100150 10047A -.04 10048A -.04 + 100150 10049A -.04 10050A -.14 + 100150 10051A -.05 10070A -.08 + 100150 10073A -.03 10080A -.07 + 100150 10081A -.03 10096A -.02 + 100150 10097A -.01 10098A -.01 + 100150 10100A 1. 10104A -.0012 + 100150 10105A -.0012 10107A -.08 + 100150 10120A -.06 + 100200 10017A 1. 10018A .565 + 100200 10041A .032 10043A .047 + 100200 10044A .007 10045A .027 + 100200 10046A .049 10056A .03 + 100200 10069A 1. 10070A .12 + 100200 10076A .134 10081A .052 + 100200 10086A .18 10087A .152 + 100200 10091A .219 10092A .032 + 100200 10093A .043 10144A .055 + 100200 10145A -1. 10146A -29. + 100200 10147A -.75 + 100201 10017A 1.25 10018A .539 + 100201 10041A .032 10043A .041 + 100201 10044A .005 10045A .024 + 100201 10046A .044 10056A .03 + 100201 10069A 1. 10070A .12 + 100201 10076A .149 10081A .056 + 100201 10086A .193 10087A .163 + 100201 10091A .193 10092A .032 + 100201 10093A .041 10124A .81 + 100201 10125A .06 10126A .72 + 100201 10127A -.0015 10144A .058 + 100201 10145A -1. 10146A -29. + 100201 10147A -.75 10207A .82 + 100203 10017A 1.5 10018A .526 + 100203 10041A .032 10043A .037 + 100203 10044A .005 10045A .02 + 100203 10046A .041 10056A .04 + 100203 10069A 1. 10070A .12 + 100203 10076A .16 10081A .058 + 100203 10086A .203 10087A .17 + 100203 10091A .175 10092A .032 + 100203 10093A .04 10124A 1.88 + 100203 10125A .11 10126A 1.25 + 100203 10127A -.0025 10144A .061 + 100203 10145A -1. 10146A -29. + 100203 10147A -.75 10207A 1.88 + 100204 10017A 1. 10018A .758 + 100204 10041A .032 10043A .065 + 100204 10044A .014 10045A .045 + 100204 10046A .061 10056A .03 + 100204 10069A 1. 10070A .13 + 100204 10078A .164 10081A .058 + 100204 10086A .157 10087A .127 + 100204 10091A .165 10092A .032 + 100204 10093A .058 10144A .066 + 100204 10145A -1. 10146A -29. + 100204 10147A -.75 + 100205 10017A 1.25 10018A .719 + 100205 10041A .032 10043A .06 + 100205 10044A .012 10045A .04 + 100205 10046A .054 10056A .03 + 100205 10069A 1. 10070A .13 + 100205 10078A .183 10081A .063 + 100205 10086A .169 10087A .136 + 100205 10091A .142 10092A .032 + 100205 10093A .055 10124A 1.34 + 100205 10125A .06 10126A .7 + 100205 10127A -.0008 10144A .068 + 100205 10145A -1. 10146A -29. + 100205 10147A -.75 10207A 1.3 + 100207 10017A 1.5 10018A .707 + 100207 10041A .032 10043A .053 + 100207 10044A .011 10045A .037 + 100207 10046A .051 10056A .04 + 100207 10069A 1. 10070A .13 + 100207 10078A .196 10081A .066 + 100207 10086A .179 10087A .145 + 100207 10091A .122 10092A .032 + 100207 10093A .054 10124A 3.32 + 100207 10125A .09 10126A .76 + 100207 10127A -.0017 10144A .072 + 100207 10145A -1. 10146A -29. + 100207 10147A -.75 10207A 3.27 + 100208 10017A 1. 10018A 1.015 + 100208 10041A .032 10043A .094 + 100208 10044A .023 10045A .066 + 100208 10046A .072 10056A .03 + 100208 10069A 1. 10070A .14 + 100208 10080A .177 10081A .06 + 100208 10086A .134 10087A .102 + 100208 10091A .112 10092A .032 + 100208 10093A .078 10144A .078 + 100208 10145A -1. 10146A -29. + 100208 10147A -.75 + 100209 10017A 1.25 10018A .962 + 100209 10041A .032 10043A .082 + 100209 10044A .02 10045A .061 + 100209 10046A .064 10056A .04 + 100209 10069A 1. 10070A .14 + 100209 10080A .204 10081A .066 + 100209 10086A .146 10087A .112 + 100209 10091A .088 10092A .032 + 100209 10093A .074 10124A 1.63 + 100209 10125A .04 10126A .89 + 100209 10127A -.0009 10144A .081 + 100209 10145A -1. 10146A -29. + 100209 10147A -.75 10207A 1.7 + 100212 10017A 1. 10018A .668 + 100212 10041A .01 10043A .07 + 100212 10044A .015 10045A .058 + 100212 10046A .058 10056A .03 + 100212 10064A -1. 10069A 1. + 100212 10070A .094 10072A 6.1 + 100212 10074A -6.52 10081A .046 + 100212 10082A .165 10086A .159 + 100212 10087A .318 10091A .017 + 100212 10092A .01 10093A .051 + 100212 10136A -.215 10137A -3.18 + 100212 10144A .061 10208A 3.13 + 100213 10017A 1. 10018A .468 + 100213 10043A .057 10044A .01 + 100213 10045A .042 10046A .037 + 100213 10053A -1. 10056A .03 + 100213 10069A 1. 10070A .081 + 100213 10072A 3.9 10074A -12.04 + 100213 10081A .234 10083A .138 + 100213 10086A .391 10093A .036 + 100213 10136A -.02 10137A -5.86 + 100213 10144A .054 10208A 3.44 + 100214 10017A 1.5 10018A 1.195 + 100214 10041A .031 10043A .11 + 100214 10044A .029 10045A .079 + 100214 10046A .07 10056A .04 + 100214 10069A 1. 10070A .15 + 100214 10081A .065 10086A .135 + 100214 10087A .095 10091A .018 + 100214 10092A .031 10093A .091 + 100214 10124A 5.7 10125A -.02 + 100214 10126A 2. 10127A -.0012 + 100214 10144A .096 10145A -1. + 100214 10146A -29. 10147A -.75 + 100214 10158A .231 10207A 5.45 + 100215 10017A 1.5 10018A .924 + 100215 10041A .032 10043A .073 + 100215 10044A .02 10045A .057 + 100215 10046A .061 10056A .04 + 100215 10069A 1. 10070A .14 + 100215 10080A .221 10081A .069 + 100215 10086A .156 10087A .12 + 100215 10091A .069 10092A .032 + 100215 10093A .071 10124A 4.46 + 100215 10125A .06 10126A 1.45 + 100215 10127A -.0014 10144A .083 + 100215 10145A -1. 10146A -29. + 100215 10147A -.75 10207A 4.24 + 100216 10017A 1. 10018A 1.323 + 100216 10041A .031 10043A .137 + 100216 10044A .033 10045A .089 + 100216 10046A .083 10056A .04 + 100216 10069A 1. 10070A .15 + 100216 10081A .054 10086A .11 + 100216 10087A .075 10091A .066 + 100216 10092A .031 10093A .101 + 100216 10144A .093 10145A -1. + 100216 10146A -29. 10147A -.75 + 100216 10158A .174 + 100217 10017A 1.25 10018A 1.234 + 100217 10041A .031 10043A .122 + 100217 10044A .03 10045A .083 + 100217 10046A .074 10056A .04 + 100217 10069A 1. 10070A .15 + 100217 10081A .061 10086A .124 + 100217 10087A .086 10091A .039 + 100217 10092A .031 10093A .094 + 100217 10124A 2.44 10125A -.02 + 100217 10126A 1.3 10127A -.0009 + 100217 10144A .094 10145A -1. + 100217 10146A -29. 10147A -.75 + 100217 10158A .211 10207A 2.39 + 100218 10017A 1. 10018A .588 + 100218 10041A .006 10043A .064 + 100218 10044A .012 10045A .051 + 100218 10046A .051 10056A .03 + 100218 10069A 1. 10070A .081 + 100218 10072A 8. 10074A -8.03 + 100218 10081A .08 10082A .147 + 100218 10086A .385 10087A .119 + 100218 10091A .01 10092A .006 + 100218 10093A .045 10124A -.01 + 100218 10125A .06 10126A .26 + 100218 10127A -.0022 10136A -.247 + 100218 10137A -.27 10144A .056 + 100218 10154A -1. 10208A 4.27 + 100220 10015A 1. 10016A .64 + 100220 10043A .051 10044A .007 + 100220 10045A .021 10046A .044 + 100220 10056A .03 10070A .12 + 100220 10071A .137 10084A .18 + 100220 10085A .152 10090A .219 + 100220 10092A .032 10093A .032 + 100220 10098A .052 10144A .058 + 100220 10148A -1. 10149A -26. + 100220 10150A -2.1 + 100221 10015A 1.25 10016A .628 + 100221 10043A .044 10044A .005 + 100221 10045A .018 10046A .039 + 100221 10056A .03 10070A .12 + 100221 10071A .152 10084A .193 + 100221 10085A .163 10090A .193 + 100221 10092A .032 10093A .031 + 100221 10098A .056 10124A .82 + 100221 10125A .07 10126A .68 + 100221 10127A -.0044 10144A .062 + 100221 10148A -1. 10149A -26. + 100221 10150A -2.1 10207A .68 + 100223 10015A 1.5 10016A 1.099 + 100223 10043A .087 10044A .018 + 100223 10045A .046 10046A .052 + 100223 10056A .04 10070A .14 + 100223 10075A .21 10084A .156 + 100223 10085A .12 10090A .069 + 100223 10092A .032 10093A .054 + 100223 10098A .069 10124A 4.43 + 100223 10125A .1 10126A 1.48 + 100223 10127A -.0055 10144A .09 + 100223 10148A -1. 10149A -26. + 100223 10150A -2.1 10207A 4.39 + 100224 10015A 1. 10016A .864 + 100224 10043A .074 10044A .014 + 100224 10045A .035 10046A .053 + 100224 10056A .03 10070A .13 + 100224 10073A .164 10084A .157 + 100224 10085A .127 10090A .165 + 100224 10092A .032 10093A .043 + 100224 10098A .058 10144A .07 + 100224 10148A -1. 10149A -26. + 100224 10150A -2.1 + 100225 10015A 1.25 10016A .85 + 100225 10043A .065 10044A .012 + 100225 10045A .032 10046A .048 + 100225 10056A .04 10070A .13 + 100225 10073A .185 10084A .169 + 100225 10085A .136 10090A .142 + 100225 10092A .032 10093A .042 + 100225 10098A .063 10124A 1.24 + 100225 10125A .07 10126A .75 + 100225 10127A -.0037 10144A .074 + 100225 10148A -1. 10149A -26. + 100225 10150A -2.1 10207A 1.31 + 100228 10015A 1. 10016A 1.192 + 100228 10043A .112 10044A .021 + 100228 10045A .054 10046A .063 + 100228 10056A .03 10070A .14 + 100228 10075A .168 10084A .134 + 100228 10085A .102 10090A .112 + 100228 10092A .032 10093A .059 + 100228 10098A .06 10144A .085 + 100228 10148A -1. 10149A -26. + 100228 10150A -2.1 + 100229 10015A 1.25 10016A 1.113 + 100229 10043A .096 10044A .018 + 100229 10045A .049 10046A .055 + 100229 10056A .04 10070A .14 + 100229 10075A .195 10084A .146 + 100229 10085A .112 10090A .088 + 100229 10092A .032 10093A .055 + 100229 10098A .066 10124A 1.62 + 100229 10125A .07 10126A .95 + 100229 10127A -.0036 10144A .087 + 100229 10148A -1. 10149A -26. + 100229 10150A -2.1 10207A 1.57 + 100232 10015A 1. 10016A 1.545 + 100232 10043A .166 10044A .031 + 100232 10045A .074 10046A .071 + 100232 10056A .03 10070A .15 + 100232 10084A .11 10085A .075 + 100232 10090A .066 10092A .031 + 100232 10093A .076 10098A .054 + 100232 10144A .102 10148A -1. + 100232 10149A -26. 10150A -2.1 + 100232 10156A .151 + 100233 10015A 1.25 10016A 1.44 + 100233 10043A .14 10044A .028 + 100233 10045A .069 10046A .063 + 100233 10056A .04 10070A .15 + 100233 10084A .124 10085A .086 + 100233 10090A .039 10092A .031 + 100233 10093A .071 10098A .061 + 100233 10124A 2.53 10125A .04 + 100233 10126A 1.7 10127A -.0039 + 100233 10144A .102 10148A -1. + 100233 10149A -26. 10150A -2.1 + 100233 10156A .192 10207A 2.44 + 100234 10015A 1.5 10016A .616 + 100234 10043A .039 10044A .005 + 100234 10045A .015 10046A .036 + 100234 10056A .04 10070A .12 + 100234 10071A .162 10084A .203 + 100234 10085A .17 10090A .175 + 100234 10092A .032 10093A .03 + 100234 10098A .058 10124A 2.22 + 100234 10125A .12 10126A 1.13 + 100234 10127A -.0069 10144A .065 + 100234 10148A -1. 10149A -26. + 100234 10150A -2.1 10207A 1.98 + 100235 10015A 1.5 10016A .838 + 100235 10043A .059 10044A .011 + 100235 10045A .028 10046A .043 + 100235 10056A .04 10070A .13 + 100235 10073A .196 10084A .179 + 100235 10085A .145 10090A .122 + 100235 10092A .032 10093A .041 + 100235 10098A .065 10124A 3.55 + 100235 10125A .1 10126A 1.14 + 100235 10127A -.0058 10144A .077 + 100235 10148A -1. 10149A -26. + 100235 10150A -2.1 10207A 3.58 + 100236 10015A 1.5 10016A 1.4 + 100236 10043A .131 10044A .027 + 100236 10045A .065 10046A .058 + 100236 10056A .04 10070A .15 + 100236 10084A .135 10085A .095 + 100236 10090A .018 10092A .031 + 100236 10093A .069 10098A .065 + 100236 10124A 5.94 10125A .06 + 100236 10126A 2.49 10127A -.0059 + 100236 10144A .104 10148A -1. + 100236 10149A -26. 10150A -2.1 + 100236 10156A .211 10207A 5.8 + 100240 10017A .15 10065A -1.15 + 100240 10081A .15 10145A 1. + 100240 10146A 32.3 10147A .357 + 100241 10066A -1. 10145A 1. + 100241 10146A 27. 10147A .512 + 100242 10101A -1. 10145A 1. + 100242 10146A 30.6 10147A .78 + 100243 10054A -1. 10145A 1. + 100243 10146A 31.4 10147A 1.57 + 100245 10102A -1. 10145A 1. + 100245 10146A 25.6 10147A 2.6 + 100250 10054A -1. 10148A 1. + 100250 10149A 31.6 10150A 1.54 + 100251 10015A .05 10055A -1.05 + 100251 10098A .05 10148A 1. + 100251 10149A 22.7 10150A 2.51 + 100252 10102A -1. 10148A 1. + 100252 10149A 25.6 10150A 2.6 + 100254 10101A -1. 10148A 1. + 100254 10149A 30.6 10150A .78 + 100270 10069A -1. + 100280 10018A -.004 10041A -.004 + 100280 10044A -.003 10045A -.006 + 100280 10046A -.005 10056A -.001 + 100280 10070A -.004 10072A -.13 + 100280 10074A 1.33 10080A -.006 + 100280 10086A .006 10087A .019 + 100280 10091A -.003 10092A -.004 + 100280 10124A -.15 10125A -.07 + 100280 10126A -.12 10127A .0142 + 100280 10136A .088 10137A -.23 + 100280 10139A .025 10140A -.27 + 100280 10144A -.001 10147A -.32 + 100280 10207A -.15 10208A -.05 + 100281 10018A .004 10041A .004 + 100281 10044A .003 10045A .006 + 100281 10046A .005 10056A .001 + 100281 10070A .004 10072A .13 + 100281 10074A -1.33 10080A .006 + 100281 10086A -.006 10087A -.019 + 100281 10091A .003 10092A .004 + 100281 10124A .15 10125A .07 + 100281 10126A .12 10127A -.0142 + 100281 10136A -.088 10137A .23 + 100281 10139A -.025 10140A .27 + 100281 10144A .001 10147A .32 + 100281 10207A .15 10208A .05 + 100282 10018A -.336 10041A -.021 + 100282 10043A -.036 10044A -.009 + 100282 10045A -.007 10046A -.017 + 100282 10056A -.003 10070A -.03 + 100282 10072A 2.47 10074A 3.35 + 100282 10080A -.045 10081A .005 + 100282 10086A .018 10087A .112 + 100282 10091A .017 10092A -.021 + 100282 10093A -.026 10124A -.34 + 100282 10125A -.1 10126A .15 + 100282 10127A .0027 10136A .016 + 100282 10137A -4.65 10139A -.013 + 100282 10140A -1.18 10144A -.018 + 100282 10146A -5. 10207A -.34 + 100282 10208A 1.15 + 100283 10018A .336 10041A .021 + 100283 10043A .036 10044A .009 + 100283 10045A .007 10046A .017 + 100283 10056A .003 10070A .03 + 100283 10072A -2.47 10074A -3.35 + 100283 10080A .045 10081A -.005 + 100283 10086A -.018 10087A -.112 + 100283 10091A -.017 10092A .021 + 100283 10093A .026 10124A .34 + 100283 10125A .1 10126A -.15 + 100283 10127A -.0027 10136A -.016 + 100283 10137A 4.65 10139A .013 + 100283 10140A 1.18 10144A .018 + 100283 10146A 5. 10207A .34 + 100283 10208A -1.15 + 100290 10016A -.026 10043A -.002 + 100290 10044A -.003 10045A -.006 + 100290 10046A -.006 10056A -.001 + 100290 10070A -.008 10072A -.14 + 100290 10073A -.011 10074A -2.08 + 100290 10084A .003 10085A .029 + 100290 10090A .003 10092A -.006 + 100290 10093A -.001 10124A -.09 + 100290 10125A -.05 10126A -.04 + 100290 10127A .0247 10136A .121 + 100290 10137A -1.47 10139A .067 + 100290 10140A -.74 10144A -.002 + 100290 10150A -.5 10207A -.09 + 100290 10208A -.08 + 100291 10016A -.245 10043A -.008 + 100291 10044A -.008 10045A -.008 + 100291 10046A -.015 10056A -.003 + 100291 10070A -.032 10072A 4.52 + 100291 10073A -.048 10074A -7.83 + 100291 10084A .019 10085A .17 + 100291 10090A -.059 10092A -.025 + 100291 10093A -.012 10098A .001 + 100291 10124A -.08 10125A -.07 + 100291 10126A .13 10127A .0128 + 100291 10136A -.107 10137A -2.77 + 100291 10139A .015 10140A -1.54 + 100291 10144A -.014 10149A -5. + 100291 10207A -.08 10208A 2.29 + 100292 10016A .245 10043A .008 + 100292 10044A .008 10045A .008 + 100292 10046A .015 10056A .003 + 100292 10070A .032 10072A -4.52 + 100292 10073A .048 10074A 7.83 + 100292 10084A -.019 10085A -.17 + 100292 10090A .059 10092A .025 + 100292 10093A .012 10098A -.001 + 100292 10124A .08 10125A .07 + 100292 10126A -.13 10127A -.0128 + 100292 10136A .107 10137A 2.77 + 100292 10139A -.015 10140A 1.54 + 100292 10144A .014 10149A 5. + 100292 10207A .08 10208A -2.29 + 100293 10016A .026 10043A .002 + 100293 10044A .003 10045A .006 + 100293 10046A .006 10056A .001 + 100293 10070A .008 10072A .14 + 100293 10073A .011 10074A 2.08 + 100293 10084A -.003 10085A -.029 + 100293 10090A -.003 10092A .006 + 100293 10093A .001 10124A .09 + 100293 10125A .05 10126A .04 + 100293 10127A -.0247 10136A -.121 + 100293 10137A 1.47 10139A -.067 + 100293 10140A .74 10144A .002 + 100293 10150A .5 10207A .09 + 100293 10208A .08 + 100400 10043A .098 10044A .033 + 100400 10045A .022 10052A -1. + 100400 10056A .44 10106A .838 + 100400 10144A .078 10168A 1. + 100401 10043A .105 10044A .037 + 100401 10045A .024 10052A -1. + 100401 10056A .44 10107A .821 + 100401 10144A .08 10168A 1. + 100402 10043A .044 10044A -.33 + 100402 10045A .294 10056A .49 + 100402 10089A 1. 10144A .031 + 100402 10168A 2.5 + 100403 10023A 1. 10043A .098 + 100403 10044A .033 10045A .022 + 100403 10052A -1. 10056A .4 + 100403 10106A .838 10144A .062 + 100404 10023A 1. 10043A .105 + 100404 10044A .037 10045A .024 + 100404 10052A -1. 10056A .4 + 100404 10107A .821 10144A .063 + 100405 10023A 1. 10043A .116 + 100405 10044A .043 10045A .029 + 100405 10052A -1. 10056A .4 + 100405 10108A .798 10144A .065 + 100410 10024A 1. 10043A .098 + 100410 10044A .033 10045A .022 + 100410 10052A -1. 10056A .11 + 100410 10106A .838 10144A .067 + 100411 10024A 1. 10043A .105 + 100411 10044A .037 10045A .024 + 100411 10052A -1. 10056A .11 + 100411 10107A .821 10144A .068 + 100412 10024A 1. 10043A .116 + 100412 10044A .043 10045A .029 + 100412 10052A -1. 10056A .11 + 100412 10108A .798 10144A .07 + 100413 10024A 1. 10043A .1 + 100413 10044A .033 10045A .022 + 100413 10049A -.33 10052A -.67 + 100413 10056A .11 10106A .832 + 100413 10125A .33 10126A 1.16 + 100413 10144A .067 + 100414 10024A 1. 10043A .107 + 100414 10044A .037 10045A .025 + 100414 10049A -.33 10052A -.67 + 100414 10056A .11 10107A .815 + 100414 10125A .33 10126A 1.06 + 100414 10144A .068 + 100415 10024A 1. 10043A .119 + 100415 10044A .043 10045A .03 + 100415 10049A -.33 10052A -.67 + 100415 10056A .11 10108A .793 + 100415 10125A .24 10126A .63 + 100415 10144A .07 + 100440 10050A -1. 10052A 1. + 100441 10051A -1. 10052A 1. + 100500 10019A 1. 10022A .067 + 100500 10043A .053 10044A .009 + 100500 10045A .002 10046A .007 + 100500 10056A .25 10057A -1. + 100500 10095A .039 10097A .148 + 100500 10102A .523 10105A .067 + 100500 10144A .058 + 100502 10019A 1. 10022A .06 + 100502 10043A .056 10044A .011 + 100502 10045A .002 10046A .009 + 100502 10056A .24 10068A -1. + 100502 10095A .052 10096A .19 + 100502 10101A .515 10104A .06 + 100502 10144A .06 + 100503 10020A 1. 10021A .06 + 100503 10043A .056 10044A .011 + 100503 10045A .002 10046A .009 + 100503 10056A .19 10068A -1. + 100503 10095A .052 10096A .19 + 100503 10101A .515 10104A .06 + 100503 10144A .061 + 100505 10020A 1. 10021A .067 + 100505 10043A .053 10044A .009 + 100505 10045A .002 10046A .007 + 100505 10056A .2 10057A -1. + 100505 10095A .039 10097A .148 + 100505 10102A .523 10105A .067 + 100505 10144A .059 + 100506 10019A 1. 10022A .009 + 100506 10042A 1. 10043A .008 + 100506 10044A .001 10046A .001 + 100506 10051A -.053 10053A -.096 + 100506 10054A -.078 10055A -.061 + 100506 10056A .07 10057A -.041 + 100506 10063A -.143 10065A -.164 + 100506 10066A -.054 10068A -.1 + 100506 10080A -.21 10095A .007 + 100506 10096A .195 10097A .093 + 100506 10101A .648 10102A .021 + 100506 10104A .006 10105A .003 + 100506 10144A .047 + 100600 10045A -1. 10116A 1. + 100601 10046A -1. 10117A 1. + 100602 10043A .625 10044A -.368 + 100602 10045A -.562 10046A -.241 + 100602 10118A .018 10119A .153 + 100602 10204A 1. + 100700 10056A .76 10116A -.663 + 100700 10117A -.571 10120A 1. + 100700 10144A .02 + 100702 10056A 1.56 10060A 1. + 100702 10070A -.606 10116A -.606 + 100702 10120A 1. 10124A 1.6 + 100702 10125A -3.6 10126A -12.1 + 100702 10127A .024 10130A 13.7 + 100702 10131A 16.1 10132A -.3 + 100702 10133A -9.9 10144A .02 + 100702 10207A 1.2 + 100796 10056A .04 10076A -1. + 100796 10123A 1. 10124A 12.9 + 100796 10125A 3.4 10126A -.5 + 100796 10127A .185 10128A 1. + 100796 10207A 2. + 100797 10056A .04 10123A 1. + 100797 10124A 8.1 10125A 5.3 + 100797 10126A 5.4 10127A .019 + 100797 10128A 1. 10158A -1. + 100797 10207A -3.4 + 100798 10056A .04 10071A -1. + 100798 10123A 1. 10124A 20.4 + 100798 10125A 3.4 10126A -1. + 100798 10127A .416 10128A 1. + 100798 10207A 6.4 + 100799 10056A .04 10123A 1. + 100799 10124A 10.4 10125A 5.4 + 100799 10126A 5.3 10127A .057 + 100799 10128A 1. 10156A -1. + 100799 10207A -3.3 + 100800 10044A -1. 10123A 1. + 100800 10124A -4.5 10125A 65. + 100800 10126A 125. 10127A .01 + 100800 10128A 1. 10207A -1.4 + 100801 10116A -1. 10123A 1. + 100801 10124A -22.2 10125A 87. + 100801 10126A 125. 10127A .01 + 100801 10128A 1. 10207A -20.2 + 100802 10117A -1. 10123A 1. + 100802 10124A -6.6 10125A 70. + 100802 10126A 125. 10127A .01 + 100802 10128A 1. 10207A -16.5 + 100803 10118A -1. 10123A 1. + 100803 10124A -22.2 10125A 87. + 100803 10126A 125. 10127A .01 + 100803 10128A 1. 10207A -20.2 + 100804 10119A -1. 10123A 1. + 100804 10124A -6.6 10125A 70. + 100804 10126A 125. 10127A .01 + 100804 10128A 1. 10207A -16.5 + 100805 10047A -1. 10056A .02 + 100805 10123A 1. 10124A 49.3 + 100805 10125A 9.7 10126A 58.3 + 100805 10127A .051 10128A 1. + 100805 10207A 58.6 + 100806 10056A .03 10070A -1. + 100806 10123A 1. 10124A 9. + 100806 10125A 12.5 10126A 70. + 100806 10127A .05 10128A 1. + 100806 10207A -6.5 + 100807 10056A .03 10095A -1. + 100807 10123A 1. 10124A 55.5 + 100807 10125A 12.5 10126A 70. + 100807 10127A .08 10128A 1. + 100807 10207A 47.3 + 100810 10056A .04 10078A -1. + 100810 10123A 1. 10124A 12.4 + 100810 10125A 4. 10126A 1.5 + 100810 10127A .094 10128A 1. + 100810 10207A .7 + 100812 10056A .04 10080A -1. + 100812 10123A 1. 10124A 10.4 + 100812 10125A 4.7 10126A 3.5 + 100812 10127A .047 10128A 1. + 100812 10207A -1.6 + 100813 10056A .04 10081A -1. + 100813 10123A 1. 10124A 76. + 100813 10125A .5 10126A -3.6 + 100813 10127A .16 10128A 1. + 100813 10207A 50.5 + 100814 10056A .04 10082A -1. + 100814 10123A 1. 10124A -9.8 + 100814 10125A 9.4 10126A 9. + 100814 10127A -.008 10128A 1. + 100814 10207A -33.4 + 100815 10056A .04 10083A -1. + 100815 10123A 1. 10124A 203.7 + 100815 10125A 6.8 10126A 26. + 100815 10127A .564 10128A 1. + 100815 10207A 176. + 100818 10056A .04 10073A -1. + 100818 10123A 1. 10124A 18.5 + 100818 10125A 4. 10126A 1.1 + 100818 10127A .212 10128A 1. + 100818 10207A 4.1 + 100820 10056A .04 10075A -1. + 100820 10123A 1. 10124A 14.9 + 100820 10125A 4.7 10126A 3.1 + 100820 10127A .111 10128A 1. + 100820 10207A .4 + 100821 10056A .04 10096A -1. + 100821 10123A 1. 10124A 129. + 100821 10125A 6. 10126A -7.5 + 100821 10127A .2 10128A 1. + 100821 10207A 125. + 100822 10056A .04 10097A -1. + 100822 10123A 1. 10124A 143. + 100822 10125A 6. 10126A -7.5 + 100822 10127A .9 10128A 1. + 100822 10207A 139. + 100823 10056A .04 10098A -1. + 100823 10123A 1. 10124A 81. + 100823 10125A .5 10126A -2.7 + 100823 10127A .6 10128A 1. + 100823 10207A 53. + 100825 10106A -1. 10123A 1. + 100825 10124A 7.2 10125A 3.1 + 100825 10126A 3.6 10128A 1. + 100826 10107A -1. 10123A 1. + 100826 10124A .5 10125A 3.4 + 100826 10126A 4.8 10128A 1. + 100826 10207A -8.5 + 100827 10108A -1. 10123A 1. + 100827 10124A -5.8 10125A 3.8 + 100827 10126A 6.8 10128A 1. + 100827 10207A -18.3 + 100835 10120A -1. 10123A 1. + 100835 10124A -11.1 10125A 2.7 + 100835 10126A 1.2 10127A .01 + 100835 10128A 1. 10207A -6.5 + 100836 10121A -1. 10123A 1. + 100836 10124A 26.1 10125A .5 + 100836 10126A -6. 10127A .02 + 100836 10128A 1. 10207A 31.5 + 100838 10048A -1. 10056A .02 + 100838 10123A 1. 10124A 62.4 + 100838 10125A 6.4 10126A 36.1 + 100838 10127A .044 10128A 1. + 100838 10207A 70.8 + 100839 10049A -1. 10056A .02 + 100839 10123A 1. 10124A 91.2 + 100839 10125A 1.8 10126A -5.1 + 100839 10127A .039 10128A 1. + 100839 10207A 97.1 + 100840 10027A 1. 10056A .295 + 100840 10123A -1. 10124A -20.6 + 100840 10127A -.115 + 100841 10027A 1. 10056A .395 + 100841 10123A -1. 10124A -25.6 + 100841 10127A -.115 + 100842 10027A 1. 10056A .495 + 100842 10123A -1. 10124A -29.8 + 100842 10127A -.115 + 100843 10027A 1. 10056A .595 + 100843 10123A -1. 10124A -33.5 + 100843 10127A -.115 + 100845 10125A -11.3 10126A -33.2 + 100845 10128A -1. + 100846 10125A -11.5 10126A -31.2 + 100846 10128A -1. + 100847 10125A -11.7 10126A -27.2 + 100847 10128A -1. + 100848 10025A 50. 10125A -12.85 + 100848 10126A -35.75 10128A -1. + 100849 10025A 50. 10125A -12.85 + 100849 10126A -22. 10128A -1. + 100850 10044A -1. 10129A 1. + 100850 10130A 8.6 10131A 13.2 + 100850 10132A 65. 10133A 125. + 100855 10047A -1. 10056A .02 + 100855 10129A 1. 10130A 78.7 + 100855 10131A 92.2 10132A 10.2 + 100855 10133A 54.7 + 100856 10056A .03 10070A -1. + 100856 10129A 1. 10130A 43. + 100856 10131A 24. 10132A 12.5 + 100856 10133A 70. + 100857 10056A .02 10129A 1. + 100857 10130A 92. 10131A 105.4 + 100857 10132A 5.1 10133A 24.2 + 100857 10151A -1. + 100875 10106A -1. 10129A 1. + 100875 10130A 34. 10131A 31.3 + 100875 10132A 3.1 10133A 3.6 + 100876 10107A -1. 10129A 1. + 100876 10130A 26.5 10131A 21.5 + 100876 10132A 3.4 10133A 4.8 + 100877 10108A -1. 10129A 1. + 100877 10130A 18.5 10131A 11.2 + 100877 10132A 3.8 10133A 6.8 + 100885 10120A -1. 10129A 1. + 100885 10130A .5 10131A 9.2 + 100885 10132A 2.7 10133A 1.2 + 100886 10121A -1. 10129A 1. + 100886 10130A 39.8 10131A 45.5 + 100886 10132A .5 10133A -6. + 100890 10026A 1. 10056A .323 + 100890 10129A -1. 10130A -18.6 + 100890 10131A -21.1 10134A -1. + 100891 10026A 1. 10056A .423 + 100891 10129A -1. 10130A -23.6 + 100891 10131A -26.1 10134A -1. + 100892 10026A 1. 10056A .523 + 100892 10129A -1. 10130A -27.8 + 100892 10131A -30.3 10134A -1. + 100893 10026A 1. 10056A .623 + 100893 10129A -1. 10130A -31.5 + 100893 10131A -34. 10134A -1. + 100895 10132A -11.3 10133A -33.2 + 100895 10134A 1. + 100896 10132A -11.5 10133A -31.2 + 100896 10134A 1. + 100897 10132A -11.7 10133A -27.2 + 100897 10134A 1. + 100898 10025A 50. 10132A -12.85 + 100898 10133A -35.2 10134A 1. + 100899 10025A 50. 10132A -12.85 + 100899 10133A -22. 10134A 1. + 100900 10028A 1. 10044A -.05 + 100900 10056A .89 10110A -.05 + 100900 10120A -.889 10121A .089 + 100900 10144A .02 10151A -.1 + 101000 10056A .03 10062A -.5 + 101000 10063A -.5 10152A 1. + 101012 10029A 1. 10051A -.4 + 101012 10056A .27 10062A -.25 + 101012 10151A -.35 + 101013 10029A 1. 10056A .27 + 101013 10061A -.4 10062A -.25 + 101013 10151A -.35 + 101021 10030A 1. 10051A -.45 + 101021 10056A .05 10062A -.55 + 101099 10031A 1. 10051A -1. + 101099 10056A .03 + 101100 10031A 1. 10056A .03 + 101100 10063A -1. + 101101 10031A 1. 10053A -.15 + 101101 10056A .03 10063A -.85 + 101102 10032A 1. 10056A .04 + 101102 10063A -.8 10064A -.2 + 101103 10032A 1. 10053A -.12 + 101103 10056A .04 10063A -.68 + 101103 10064A -.2 + 101107 10034A 1. 10056A .03 + 101107 10084A -.67 10086A -.13 + 101107 10087A -.2 + 101108 10034A 1. 10056A .03 + 101108 10084A -.38 10085A -.29 + 101108 10086A -.17 10087A -.03 + 101108 10098A -.13 + 101109 10034A 1. 10056A .03 + 101109 10086A -.85 10087A -.15 + 101110 10063A -1. 10072A 54.1 + 101110 10074A -23.6 10135A 1. + 101110 10136A .072 10137A -18. + 101110 10208A 42.1 + 101111 10064A -1. 10072A 60.7 + 101111 10074A .7 10135A 1. + 101111 10136A .217 10137A 61. + 101111 10208A 35.7 + 101112 10053A -1. 10072A 48.9 + 101112 10074A -31. 10135A 1. + 101112 10136A .61 10137A -29. + 101112 10208A 40.3 + 101113 10072A 28.5 10074A -4.2 + 101113 10084A -1. 10135A 1. + 101113 10136A 1.9 10137A -21. + 101113 10208A 26.6 + 101114 10072A 36. 10074A 4.3 + 101114 10085A -1. 10135A 1. + 101114 10136A 1.95 10137A 32. + 101114 10208A 22.9 + 101115 10072A 30. 10074A 4.5 + 101115 10086A -1. 10135A 1. + 101115 10136A .67 10137A -16. + 101115 10208A 27.8 + 101116 10072A 41. 10074A 11. + 101116 10087A -1. 10135A 1. + 101116 10136A .71 10137A 54. + 101116 10208A 25.4 + 101117 10058A -1. 10072A 50.3 + 101117 10074A -20.2 10135A 1. + 101117 10136A .893 10137A -16. + 101117 10208A 37.3 + 101118 10072A 58.9 10074A -6.2 + 101118 10135A 1. 10136A .185 + 101118 10137A 26. 10154A -1. + 101118 10208A 37.3 + 101119 10061A -1. 10072A 50. + 101119 10074A -30. 10135A 1. + 101119 10136A .11 10137A -39. + 101119 10208A 48.2 + 101120 10072A 31. 10074A -18.2 + 101120 10081A -1. 10135A 1. + 101120 10136A .16 10137A -38. + 101120 10208A 36.3 + 101121 10051A -1. 10072A 50. + 101121 10074A -30. 10135A 1. + 101121 10136A .11 10137A -40. + 101121 10208A 48.7 + 101122 10072A 28. 10074A -8.7 + 101122 10084A -.728 10098A -.272 + 101122 10135A 1. 10136A 1.55 + 101122 10137A -26. 10208A 28.5 + 101123 10056A .02 10137A -5. + 101123 10211A 1. + 101124 10056A .04 10137A -10. + 101124 10211A 1. + 101125 10033A 1. 10056A .04 + 101125 10135A -1. 10136A -.65 + 101125 10137A 10. 10211A -1. + 101126 10025A 50. 10033A 1. + 101126 10056A .04 10135A -1. + 101126 10136A -.65 10137A 13. + 101126 10211A -1. + 101API 10208A -1. + 101201 10035A 1. 10084A -.245 + 101201 10086A -.272 10141A -.483 + 101202 10035A 1. 10084A -.154 + 101202 10085A -.124 10086A -.149 + 101202 10087A -.114 10141A -.459 + 101203 10036A 1. 10090A -.13 + 101203 10091A -.13 10141A -.74 + 101204 10037A 1. 10194A -1. + 101204 10195A -1.05 10196A -60. + 101206 10038A 1. 10141A -1. + 101207 10035A 1. 10086A -.327 + 101207 10087A -.25 10141A -.423 + 101210 10057A -1. 10138A 1. + 101210 10139A 4.14 10140A 96.9 + 101211 10068A -1. 10138A 1. + 101211 10139A .939 10140A 89.2 + 101213 10090A -1. 10138A 1. + 101213 10139A 2.3 10140A 8. + 101214 10091A -1. 10138A 1. + 101214 10139A .82 10140A 8. + 101215 10085A -1. 10138A 1. + 101215 10139A 1.95 10140A -2.1 + 101216 10086A -1. 10138A 1. + 101216 10139A .71 10140A 4.6 + 101217 10084A -1. 10138A 1. + 101217 10139A 1.9 10140A -10.6 + 101219 10138A -1. 10139A -2.8 + 101219 10140A -60. 10141A 1. + 101220 10092A -1. 10142A .977 + 101220 10143A .977 + 101221 10040A 1. 10068A -1. + 101221 10142A .972 10143A .972 + 101222 10025A 50. 10057A -.7 + 101222 10090A -.3 10142A .947 + 101222 10143A .947 + 101224 10090A -1. 10142A .918 + 101224 10143A .918 + 101225 10043A -1. 10142A 1. + 101226 10093A -1. 10142A 1. + 101227 10025A 6.21 10142A 1. + 101227 10169A 1. + 101228 10013A 1. 10025A 4.97 + 101228 10142A 1. + 101229 10044A -1. 10142A .636 + 101230 10141A -1. 10142A .943 + 101230 10143A .943 + 101231 10142A .931 10143A .931 + 101231 10153A -1. + 101232 10085A -.5 10090A -.5 + 101232 10142A .915 10143A .915 + 101234 10143A -1. + 101235 10142A -1. 10144A -1. + 101236 10068A -1. 10194A 1. + 101236 10195A .939 10196A 89.2 + 101237 10091A -1. 10194A 1. + 101237 10195A .82 10196A 8. + 101238 10064A -1. 10194A 1. + 101238 10195A .22 10196A -4.9 + 101239 10041A -1. 10092A -1. + 101239 10194A 1. 10195A 1.26 + 101239 10196A 61.5 + 101300 10039A 1. 10051A -.016 + 101300 10056A .18 10062A -.005 + 101300 10065A -.325 10066A -.755 + 101300 10084A -.065 10085A -.054 + 101300 10144A .042 10147A .31 + 101300 10153A .22 + 101CET 10072A -1. + 101400 10057A .75 10197A 1. + 101400 10203A .25 + 101401 10066A .075 10068A .525 + 101401 10198A 1. 10203A .4 + 101402 10057A 1. 10199A 1. + 101403 10066A .17 10068A .83 + 101403 10200A 1. + 101404 10057A -.75 10203A -.25 + 101404 10209A 1. + 101405 10066A -.075 10068A -.525 + 101405 10203A -.4 10210A 1. + 101406 10057A -1. 10201A 1. + 101407 10066A -.17 10068A -.83 + 101407 10202A 1. + 101408 10051A -.47 10084A -.36 + 101408 10090A -.17 10203A 1. + 101VIS 10074A 1. + 101600 10025A -17.86 10105A -1. + 101601 10025A -23.21 10104A -1. + 101I93 10207A -1. + 102000 10001A -1. 10025A 10.5 + 102000 10027A 1. + 102001 10025A 15. 10026A 1. + 102002 10025A 50. 10031A 1. + 102003 10025A 50. 10033A 1. + 102004 10025A 50. 10038A 1. + 102006 10025A 20. 10110A 1. + 102500 10027A -1. + 102502 10031A -1. + 102503 10033A -1. + 102504 10038A -1. + 102I93 10207A 1. + 103000 10031A 1. 10170A 1. + 103001 10033A 1. 10171A 1. + 103002 10038A 1. 10172A 1. + 103003 10037A 1. 10173A 1. + 103005 10145A 1. 10146A 29. + 103005 10147A .75 10175A 1. + 103006 10148A 1. 10149A 26. + 103006 10150A 2.1 10176A 1. + 103007 10044A .25 10116A .3 + 103007 10117A .45 10177A 1. + 104003 10215A 100. + 104004 10038A -1. 10183A 1. + 104004 10219A 100. + 104030 10059A 1. 10090A -1. + 104030 10183A 1. 10216A 100. + 104120 10084A -1. 10190A 1. + 104120 10193A 1. 10217A 100. + 104171 10148A -1. 10149A -26. + 104171 10150A -2.1 10191A 1. + 104171 10192A 1. 10218A 100. + 104191 10084A -.6 10085A -.4 + 104191 10191A 1. 10193A 1. + 104191 10220A 100. +RHS + ZZZZ0001 10006A 132.5 10007A 87.5 + ZZZZ0001 10008A 8.1 10009A 55. + ZZZZ0001 10010A 45. 10011A 3. + ZZZZ0001 10012A 2.6 10013A 2.6 + ZZZZ0001 10014A 80. 10015A 52. + ZZZZ0001 10016A 30. 10017A 65.6 + ZZZZ0001 10018A 45. 10019A 12.5 + ZZZZ0001 10020A 15. 10021A .834 + ZZZZ0001 10022A .536 10024A 20.2 + ZZZZ0001 10026A 21.4 10027A 65.6 + ZZZZ0001 10028A 2. 10029A 5.7 + ZZZZ0001 10030A 3.3 10031A 10.3 + ZZZZ0001 10032A 9. 10033A 33. + ZZZZ0001 10034A 3. 10035A 4.35 + ZZZZ0001 10036A .65 10037A 4. + ZZZZ0001 10038A 13.4 10039A 7.2 + ZZZZ0001 10040A 1.5 10042A 4. + ZZZZ0001 10043A 3.5 10060A .8 + ZZZZ0001 10089A 5. 10094A .2 + ZZZZ0001 10100A 2. 10143A 3.5 + ZZZZ0001 10144A -6.8 10152A 1.7 + ZZZZ0001 10159A .6 10160A 40. + ZZZZ0001 10163A 8. 10164A 14. + ZZZZ0001 10167A 5. 10168A 10.6 + ZZZZ0001 10169A .9 10201A 2.9 + ZZZZ0001 10202A 2.5 10204A 1.06 + ZZZZ0001 10209A 2.1 10210A .5 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.cor b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.cor new file mode 100644 index 000000000..6d285ac6e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.cor @@ -0,0 +1,35 @@ +NAME BUG +ROWS + N obj + G C0 + G C1 + G C2 + G C3 +COLUMNS + x01 obj 1 + x01 C3 1 + x01 C1 1 + x01 C0 1 + x02 obj 1 + x02 C2 1 + x02 C1 1 + x02 C0 1 + x03 obj 1 + x03 C3 1 + x03 C2 1 + x03 C0 1 + x04 obj 0.5 + x04 C3 1 + x04 C1 1 + x05 obj 0.5 + x05 C2 1 + x05 C1 1 + x06 obj 0.5 + x06 C3 1 + x06 C2 1 +RHS + RHS C0 0 + RHS C1 1 + RHS C2 1 + RHS C3 1 +ENDATA \ No newline at end of file diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.stoch b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.stoch new file mode 100644 index 000000000..198880225 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.stoch @@ -0,0 +1,11 @@ +NAME BUG +SCENARIOS DISCRETE REPLACE + SC SCEN01 ROOT 0.500 STG02 + RHS C1 1.000 + RHS C2 1.000 + RHS C3 0.000 + SC SCEN02 ROOT 0.500 STG02 + RHS C1 0.000 + RHS C2 1.000 + RHS C3 0.000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.time b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.time new file mode 100644 index 000000000..7849cc132 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/bug.time @@ -0,0 +1,5 @@ +TIME BUG +PERIODS LP + x01 C0 STG01 + x04 C1 STG02 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/conic.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/conic.mps new file mode 100644 index 000000000..3f1e6fd1d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/conic.mps @@ -0,0 +1,52 @@ +NAME +ROWS + N obj + L c1 +COLUMNS + x0 obj 1 c1 1 + INT 'MARKER' 'INTORG' + x1 obj -1 c1 10 + INT 'MARKER' 'INTEND' +* S1 NAME1 'MARKER' 'SOSORG' + x2 obj -9 c1 5 + x3 obj -6 c1 8 +* NAME1 'MARKER' 'SOSEND' + x4 obj 1 c1 1 + x5 obj -6 c1 8 + x6 obj 1 c1 1 + x7 obj 1 c1 1 + x8 obj -6 c1 8 + x9 obj -2 c1 1 + x10 obj -3 c1 1 + x11 obj -1 c1 -1 + x12 obj -2 c1 1 + x13 obj -3 c1 1 + x14 obj -9 c1 5 +RHS + rhs c1 10000 +RANGES + range c1 2000 +BOUNDS + LI BOUND x1 2 + UI BOUND x1 3 +SOS + S1 set1 + x2 + x3 + S2 set2 + x4 20 + x5 40 +QUADOBJ + x6 x6 1 + x6 x7 2 + x7 x7 7 +CSECTION cone1 0.0 QUAD + x8 + x9 + x10 +CSECTION cone2 0.0 RQUAD + x11 + x12 + x13 + x14 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/e226.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/e226.mps new file mode 100644 index 000000000..46c25e6f9 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/e226.mps @@ -0,0 +1,1733 @@ +NAME E226 +ROWS + N ...000 + L ...010 + E ...011 + L ...012 + E ...013 + E ...014 + E ...015 + E ...016 + L ...017 + L ...018 + L ...019 + L ...020 + L ...021 + L ...022 + L ...023 + L ...024 + L ...025 + E ...026 + L ...027 + E ...028 + L ...029 + L ...030 + L ...031 + E ...032 + L ...033 + L ...034 + L ...035 + L ...036 + L ...037 + L ...038 + L ...039 + L ...040 + L ...041 + L ...042 + L ...043 + L ...044 + L ...045 + E ...046 + L ...047 + L ...048 + L ...049 + L ...050 + L ...051 + L ...052 + L ...053 + L ...054 + L ...055 + L ...056 + L ...057 + L ...058 + L ...059 + L ...060 + L ...120 + L ...133 + L ...134 + L ...135 + L ...136 + L ...137 + L ...138 + L ...139 + L ...140 + L ...141 + L ...142 + L ...143 + L ...144 + L ...145 + L ...146 + E ...147 + L ...148 + L ...149 + L ...150 + L ...151 + L ...152 + L ...153 + L ...154 + L ...155 + E ...156 + E ...157 + L ...158 + L ...159 + L ...160 + L ...161 + L ...162 + L ...163 + E ...164 + E ...165 + E ...166 + L ...167 + L ...168 + L ...169 + L ...170 + L ...171 + L ...172 + L ...173 + L ...174 + L ...175 + E ...176 + E ...177 + E ...178 + L ...179 + L ...180 + E ...181 + L ...182 + L ...183 + E ...184 + L ...185 + L ...186 + E ...187 + E ...188 + L ...189 + L ...190 + G ...191 + L ...192 + L ...193 + L ...194 + L ...195 + L ...196 + L ...197 + L ...198 + L ...199 + L ...200 + G ...201 + L ...202 + G ...203 + L ...204 + L ...205 + L ...206 + L ...207 + L ...208 + L ...209 + L ...210 + L ...211 + L ...212 + L ...213 + L ...214 + L ...215 + L ...216 + L ...217 + L ...218 + L ...219 + L ...220 + L ...221 + L ...222 + L ...223 + L ...224 + L ...225 + L ...226 + L ...227 + L ...228 + L ...229 + L ...230 + L ...231 + L ...232 + L ...233 + L ...234 + L ...235 + L ...236 + L ...237 + L ...238 + L ...239 + L ...240 + L ...241 + L ...242 + L ...243 + L ...244 + L ...245 + L ...246 + L ...247 + L ...248 + L ...249 + L ...250 + E ...251 + L ...252 + L ...253 + L ...254 + L ...255 + L ...256 + L ...257 + L ...258 + L ...259 + L ...260 + L ...261 + E ...262 + L ...263 + E ...264 + L ...265 + L ...267 + L ...266 + L ...268 + E ...269 + L ...270 + L ...271 + L ...272 + L ...273 + L ...274 + L ...275 + E ...276 + E ...277 + E ...278 + E ...279 + L ...280 + L ...281 + L ...282 + L ...283 + L ...284 + L ...285 + L ...286 + L ...287 + L ...288 + E ...289 + L ...290 + L ...291 + G ...292 + L ...293 + E ...294 + L ...295 + L ...296 + G ...297 + L ...298 + E ...299 + L ...300 + L ...301 + L ...302 + L ...303 +COLUMNS + .ETHSD ...269 1. ...270 1. + .ETHSD ...000 -10.1974 + .BUDSD ...271 1. ...293 1. + .BUDSD ...000 -29.1163 + .HEPTS ...267 1. ...268 1. + .HEPTS ...000 -12.8462 + .M28IS ...032 1. ...055 1. + .TF0SD ...300 1. ...301 .63 + .TF0SD ...302 .37 ...000 -4.7113 + .RKDIS ...028 1. ...055 1. + .ADHD1 ...056 2.857 ...133 .984 + .ADHD1 ...140 1. ...000 -3.9824 + .PREHT ...289 1. ...290 1. + .C4LPG ...169 1. ...173 1. + .C4LPG ...174 1. ...000 -2.7214 + .M28SL ...033 1. ...049 1. + .M28SL ...045 -.4286 ...000 -6.5884 + .HEPP0 ...267 1. ...274 -1. + .RKSLD ...029 1. ...031 1. + .RKSLD ...045 -.2195 ...000 -4.158 + .UN010 ...010 -1. + .XCAPY ...182 1. + .REDBA ...294 .1 ...013 -.04 + .TFVIS ...051 .362 ...052 1. + .TFVIS ...053 .362 ...054 .829 + .TFVIS ...056 2.127 ...000 -4.3557 + .T0TMX ...168 1. ...170 -.25 + .T0TMX ...171 .12 ...173 1. + .T0TMX ...174 1. ...000 -3.103 + .EGV0L ...000 -5.9898 ...211 1. + .EGV0L ...212 1. + .VNNF2 ...193 -.272 ...192 -.272 + .VNNF2 ...194 -.272 ...195 -.272 + .C5FDP ...181 1. ...183 -1. + .C5FDP ...184 -.1614 ...185 1.1614 + .C5FDP ...186 1.1614 + .TFNS1 ...050 1. ...051 -1. + .TFNS1 ...000 .0087 + .CFMSU ...261 -2.9155 ...278 1. + .VN4PH ...179 1. ...198 -1. + .CFMSG ...279 1. ...285 .6526 + .ERV0L ...233 1. ...234 1. + .ERV0L ...000 -4.4497 + .PKDIS ...026 1. ...055 1. + .EEV0L ...000 -5.348 ...222 1. + .EEV0L ...223 1. + .CS1TP ...189 -1. ...191 1. + .CS1TP ...190 1. ...000 .0078 + .JP5DS ...046 1. ...047 -.5 + .JP5DS ...048 1. ...050 1. + .JP5DS ...000 -4.0337 + .DMD0S ...144 1. ...145 1. + .DMD0S ...000 -3.8202 + .PKSLD ...027 1.25 ...030 1. + .PKSLD ...045 -.25 ...000 -4.3425 + .VNSW2 ...051 1. ...189 -1. + .VNSW2 ...000 .015 + .TGAS1 ...134 1. ...135 1. + .TGAS1 ...137 -1.667 + .TGAS2 ...137 -1.367 ...134 1. + .TGAS2 ...136 1. + .LD1EG ...219 5.2638 ...244 7.593 + .LD1EG ...000 -1. + .LD2EG ...219 15.7829 ...245 18.5185 + .LD2EG ...000 -1. + .JP1TF ...034 1. ...050 1. + .JP1TF ...301 -1. + .JP1DS ...034 1. ...035 1. + .JP1DS ...036 -.2 ...050 1. + .JP1DS ...000 -4.5066 + .JP4DS ...038 1. ...041 1. + .JP4DS ...050 1. ...000 -2.7704 + .VN4DB ...051 1. ...179 1. + .VN4DB ...204 2. ...281 1. + .VN4DB ...000 -4.3739 + .T5JP5 ...037 1. ...046 -1. + .T5JP5 ...047 1. ...050 -1. + .T5JP5 ...000 -.0087 + .J4210 ...041 1. ...042 1.062 + .J4210 ...044 .0638 ...050 1. + .J4210 ...000 -3.0626 + .T5JP1 ...034 -1. ...036 1. + .T5JP1 ...037 1. ...050 -1. + .T5JP1 ...000 -.0087 + .TFCAT ...054 -11.055 ...156 24.476 + .TFCAT ...157 1. ...281 -2.5386 + .TFCAT ...282 10.0375 + .VNSW1 ...050 1. ...189 -1. + .VNSW1 ...000 .0087 + .ETHRF ...264 -.42 ...269 1. + .ETHRF ...000 1.35 + .LD1ER ...241 75.9202 ...248 19.7239 + .LD1ER ...000 -1. + .LD2ER ...000 -1. ...241 151.8405 + .LD2ER ...249 12.3305 + .LD1EE ...000 -1. ...230 14.5377 + .LD1EE ...246 14.1044 + .LD2EE ...000 -1. ...230 25.3995 + .LD2EE ...247 12.3305 + .PC4TF ...264 -.66 ...265 .66 + .PC4TF ...273 1. + .C5TRF ...183 1. ...264 -.7 + .C5TRF ...265 .7 + .CCSRF ...156 17.372 ...157 1. + .CCSRF ...264 -.9 ...266 1. + .CCSRF ...000 -.2 + .DGHDS ...137 8.33 ...138 1. + .DGHDS ...139 1.483 ...262 -9.648 + .DGHDS ...264 -.014 ...265 .014 + .DGHDS ...000 -5.9218 + .ADHDS ...133 .982 ...137 10. + .ADHDS ...140 1. ...262 -9.648 + .ADHDS ...000 -3.9942 ...264 -.0126 + .ADHDS ...265 .0126 + .VN4RF ...179 1. ...264 -.78 + .VN4RF ...265 .78 + .GWG0S ...142 1. ...143 1. + .GWG0S ...000 -4.0195 + .DGFDG ...139 -1. ...141 1. + .DGFDG ...142 1. + .ADFHD ...140 -1. ...142 .7763 + .ADFHD ...156 4.401 ...157 .2237 + .C4VIS ...173 -1. ...200 1. + .CATFI ...147 -1. ...276 -6. + .CATFI ...277 -3.3 ...278 -1.6 + .CATFI ...279 -.916 ...000 3.2253 + .C3LPG ...167 1. ...172 1. + .C3LPG ...174 1. ...202 1. + .C3LPG ...000 -2.7904 + .PETCF ...147 -1. ...148 1. + .PETCF ...276 -18.4 ...277 .462 + .PETCF ...278 -4.2 ...279 -.966 + .C3MIX ...170 1. ...171 -1. + .C3MIX ...172 1. ...173 -1. + .C3MIX ...202 1. + .CB1H1 ...147 -1. ...158 1. + .CB1H1 ...276 -5.4 ...277 -3.96 + .CB1H1 ...278 -1.68 ...279 -.927 + .CB1H3 ...147 -1. ...159 1. + .CB1H3 ...276 -7.1 ...277 9.9 + .CB1H3 ...278 -1.97 ...279 -.946 + .PS1LF ...147 -1. ...149 1. + .PS1LF ...276 -2.5 ...277 -20.46 + .PS1LF ...278 -1.6 ...279 -.861 + .PS1H1 ...147 -1. ...150 1. + .PS1H1 ...276 -2.8 ...277 -14.685 + .PS1H1 ...278 -2.6 ...279 -.892 + .PS1H2 ...147 -1. ...151 1. + .PS1H2 ...276 -3.7 ...277 3.135 + .PS1H2 ...278 -2.8 ...279 -.915 + .PS1H3 ...147 -1. ...152 1. + .PS1H3 ...276 -3.4 ...277 9.735 + .PS1H3 ...278 -3.1 ...279 -.942 + .PS2LF ...147 -1. ...153 1. + .PS2LF ...276 -1.1 ...277 -16.5 + .PS2LF ...278 -1.74 ...279 -.862 + .PS2HF ...147 -1. ...154 1. + .PS2HF ...276 -3.9 ...277 -1.65 + .PS2HF ...278 -2.71 ...279 -.894 + .GTSGB ...175 1. ...260 1. + .GTSGB ...000 -2.9662 + .MD0CF ...145 1. ...147 -1. + .MD0CF ...276 .3 ...277 -23.1 + .MD0CF ...278 -1.25 ...279 -.845 + .SPSU1 ...260 .00026 ...261 1. + .SPSU1 ...263 1. ...000 -.00176 + .SPSU2 ...260 .00026 ...262 1. + .SPSU2 ...263 1. ...000 -.00176 + .C3VRF ...202 1. ...264 -.56 + .PS3HF ...147 -1. ...155 1. + .PS3HF ...276 -1.1 ...277 -9.9 + .PS3HF ...278 -2.15 ...279 -.878 + .BF0SD ...164 1. ...165 1. + .BF0SD ...000 -2.6143 + .C4VRF ...200 1. ...264 -.66 + .C4VRF ...265 .66 + .CCSF6 ...157 1. ...164 -1. + .CCSVF ...156 1. ...166 -1. + .FCTEM ...260 -.0029 ...283 -.0007 + .FCTEM ...284 .44 ...285 -.0459 + .FCTEM ...286 1. ...289 -.78 + .FCTEM ...000 -.00049 + .VN0ER ...188 1. ...241 -1.125 + .GASRF ...260 1. ...264 -1. + .G0TCF ...142 1. ...147 -1. + .G0TCF ...276 1.2 ...277 -23.1 + .G0TCF ...278 -1. ...279 -.832 + .PC4TG ...213 64. ...214 -66. + .PC4TG ...215 73. ...216 -92. + .PC4TG ...217 40. ...218 -50. + .PC4TG ...220 317.5 ...221 -613.2 + .PC4TG ...219 .24 ...211 -1. + .PC4TG ...244 -1. ...245 -1. + .PC4TG ...273 1. + .P0LYG ...213 1. ...214 -3. + .P0LYG ...215 -17. ...216 -2. + .P0LYG ...217 -24. ...218 14. + .P0LYG ...220 -5.1 ...221 -19.2 + .P0LYG ...219 1.29 ...211 -1. + .P0LYG ...244 -1. ...245 -1. + .P0LYG ...274 1. + .P90BG ...256 1. ...213 -9. + .P90BG ...214 7. ...215 -52. + .P90BG ...216 33. ...217 -70. + .P90BG ...218 60. ...220 -81. + .P90BG ...221 95.8 ...219 -.7 + .P90BG ...211 -1. ...244 -1. + .P90BG ...245 -1. ...000 .0023 + .P93BG ...213 -9. ...214 7. + .P93BG ...215 -52. ...216 33. + .P93BG ...217 -69. ...218 59. + .P93BG ...220 -80.6 ...221 95.8 + .P93BG ...219 -3.23 ...211 -1. + .P93BG ...244 -1. ...245 -1. + .P93BG ...257 1. ...000 .0023 + .P96BG ...213 -9. ...214 7. + .P96BG ...215 -52. ...216 33. + .P96BG ...217 -68. ...218 58. + .P96BG ...220 -80.2 ...221 95.8 + .P96BG ...219 -4.94 ...211 -1. + .P96BG ...244 -1. ...245 -1. + .P96BG ...258 1. ...000 .0023 + .P990G ...213 1.1 ...214 -3.1 + .P990G ...215 22. ...216 -41. + .P990G ...217 49. ...218 -59. + .P990G ...220 44. ...221 -59. + .P990G ...219 7.48 ...211 -1. + .P990G ...244 -1. ...245 -1. + .P990G ...255 1. ...000 .0023 + .P99BG ...213 -9. ...214 7. + .P99BG ...215 -52. ...216 33. + .P99BG ...217 -67. ...218 57. + .P99BG ...220 -79.8 ...221 95.8 + .P99BG ...219 -6.21 ...211 -1. + .P99BG ...244 -1. ...245 -1. + .P99BG ...259 1. ...000 .0023 + .C5TEG ...213 4. ...214 -6. + .C5TEG ...215 58. ...216 -77. + .C5TEG ...217 40. ...218 -50. + .C5TEG ...220 70. ...221 -118.2 + .C5TEG ...219 10.99 ...211 -1. + .C5TEG ...244 -1. ...245 -1. + .C5TEG ...183 1. ...250 1. + .C5TEG ...251 -1. + .LCN0G ...213 1.5 ...214 -3.5 + .LCN0G ...215 40. ...216 -59. + .LCN0G ...217 38. ...218 -48. + .LCN0G ...220 50.2 ...221 -80.2 + .LCN0G ...219 2.98 ...211 -1. + .LCN0G ...244 -1. ...245 -1. + .LCN0G ...250 1. ...280 1. + .LCN0G ...000 .0089 + .FCREC ...156 -.7977 ...260 -.0071 + .FCREC ...280 -.0059 ...281 -.0039 + .FCREC ...282 -.0033 ...283 .0065 + .FCREC ...284 -.09 ...285 -.0564 + .FCREC ...287 1. ...289 -.925 + .FCREC ...000 -.00123 + .FCMAR ...260 -.0017 ...276 1. + .FCMAR ...280 .0036 ...281 .0024 + .FCMAR ...282 .002 ...283 .0011 + .FCMAR ...284 .32 ...285 .0696 + .FCMBR ...156 .152 ...277 1. + .FCMBR ...283 -.0023 ...280 .0006 + .FCMBR ...281 .0004 ...282 .00035 + .FCMBR ...260 -.0005 ...284 .042 + .FCC0N ...260 .0006 ...280 -.00112 + .FCC0N ...281 -.00075 ...282 -.00063 + .FCC0N ...283 -.039 ...284 1. + .FCC0N ...285 .1969 ...288 1. + .FCC0N ...289 2.375 ...156 .6075 + .FCC0N ...157 .05 ...000 .00058 + .VN1ER ...187 1. ...239 1. + .VN1ER ...240 -1. ...242 .4 + .FCTPT ...147 1. ...156 -7.383 + .FCTPT ...157 -.4 ...260 -.04495 + .FCTPT ...280 -.19654 ...281 -.13103 + .FCTPT ...282 -.10919 ...283 -.22573 + .FCTPT ...284 4.569 ...286 -6. + .FCTPT ...287 -2. ...288 -2. + .FCTPT ...289 1.49 ...290 -1.3 + .FCTPT ...291 1. ...292 1. + .FCTPT ...000 .0186 + .VNRER ...235 1. ...236 -1. + .VNRER ...242 4. ...243 -8. + .VNRER ...177 1. + .VN7ER ...237 1. ...238 -1. + .VN7ER ...242 .5 ...243 -1. + .VN7ER ...178 1. + .C4VEG ...213 53. ...214 -55. + .C4VEG ...215 73. ...216 -92. + .C4VEG ...217 40. ...218 -50. + .C4VEG ...220 273.5 ...221 -525.2 + .C4VEG ...219 7.34 ...211 -1. + .C4VEG ...244 -1. ...245 -1. + .C4VEG ...200 1. + .C3VEG ...213 169. ...214 -171. + .C3VEG ...215 98. ...216 -117. + .C3VEG ...217 70. ...218 -80. + .C3VEG ...220 762. ...221 -1478.2 + .C3VEG ...219 -2.56 ...211 -1. + .C3VEG ...244 -1. ...245 -1. + .C3VEG ...202 1. + .G0IF6 ...164 -1. ...166 -20.051 + .G0IF6 ...000 4.0021 + .MD0IF ...164 -1. ...166 -15.911 + .MD0IF ...000 3.7167 + .CFIF6 ...164 -1. ...166 -5.395 + .CFIF6 ...000 3.2253 + .F1V0L ...160 1. ...164 1. + .F1V0L ...166 7.925 ...000 -3.1011 + .F2V0L ...161 1. ...164 1. + .F2V0L ...166 3.117 ...000 -2.8049 + .F3V0L ...162 1. ...164 1. + .F3V0L ...166 1.954 ...000 -2.7235 + .F4V0L ...163 1. ...164 1. + .F4V0L ...166 -1.117 ...000 -2.8146 + .PETF6 ...164 -1. ...148 1. + .PETF6 ...166 -6.192 + .KEBF6 ...044 1. ...164 -1. + .KEBF6 ...166 -27.4598 + .WKEF6 ...045 1. ...164 -1. + .WKEF6 ...166 -28.869 + .CB161 ...158 1. ...164 -1. + .CB161 ...166 -6.248 + .CB163 ...159 1. ...164 -1. + .CB163 ...166 -2.346 + .PS1L6 ...149 1. ...164 -1. + .PS1L6 ...166 -15.619 + .PS161 ...150 1. ...164 -1. + .PS161 ...166 -9.972 + .PS162 ...151 1. ...164 -1. + .PS162 ...166 -5.883 + .PS163 ...152 1. ...164 -1. + .PS163 ...166 -.923 + .PS2L6 ...153 1. ...164 -1. + .PS2L6 ...166 -15.292 + .PS2H6 ...154 1. ...164 -1. + .PS2H6 ...166 -9.503 + .MD0F6 ...145 1. ...164 -1. + .MD0F6 ...166 -15.911 + .PTF0E ...224 -2.5 ...225 .5 + .PTF0E ...226 -14.32 ...227 -5.7 + .PTF0E ...228 9. ...229 -19. + .PTF0E ...231 -4.56 ...232 16.1 + .PTF0E ...230 2.01 ...222 -1. + .PTF0E ...246 -1. ...247 -1. + .PTF0E ...303 1. + .SCNTE ...224 -.2 ...225 -1.8 + .SCNTE ...226 1.64 ...227 -21.6 + .SCNTE ...228 30. ...229 -40. + .SCNTE ...231 21.02 ...232 -18.2 + .SCNTE ...230 6.61 ...222 -1. + .SCNTE ...246 -1. ...247 -1. + .SCNTE ...275 1. ...000 .0005 + .SCNTR ...235 -.2 ...236 -1.8 + .SCNTR ...237 9. ...238 -29. + .SCNTR ...239 30. ...240 -40. + .SCNTR ...242 24.7 ...243 -25.6 + .SCNTR ...241 -2.38 ...233 -1. + .SCNTR ...248 -1. ...249 -1. + .SCNTR ...275 1. ...000 .0005 + .PTF0R ...235 -2.5 ...236 .5 + .PTF0R ...237 -12. ...238 -8. + .PTF0R ...239 9. ...240 -19. + .PTF0R ...242 -3.4 ...243 13.8 + .PTF0R ...241 -6.93 ...233 -1. + .PTF0R ...248 -1. ...249 -1. + .PTF0R ...303 1. + .PC4TE ...224 66. ...225 -68. + .PC4TE ...226 51.8 ...227 -71.8 + .PC4TE ...228 40. ...229 -50. + .PC4TE ...231 314.9 ...232 -598. + .PC4TE ...230 -3.78 ...222 -1. + .PC4TE ...246 -1. ...247 -1. + .PC4TE ...273 1. + .P0LYE ...224 3. ...225 -5. + .P0LYE ...226 -16.6 ...227 -3.4 + .P0LYE ...228 -24. ...229 14. + .P0LYE ...231 3.1 ...232 -25.6 + .P0LYE ...230 -2.69 ...222 -1. + .P0LYE ...246 -1. ...247 -1. + .P0LYE ...274 1. + .PC4TR ...273 1. ...235 66. + .PC4TR ...236 -68. ...237 75. + .PC4TR ...238 -95. ...239 40. + .PC4TR ...240 -50. ...242 326.5 + .PC4TR ...243 -621.2 ...241 -12.74 + .PC4TR ...233 -1. ...248 -1. + .PC4TR ...249 -1. + .P0LYR ...235 3. ...236 -5. + .P0LYR ...237 -15. ...238 -5. + .P0LYR ...239 -24. ...240 14. + .P0LYR ...242 3.9 ...243 -27.2 + .P0LYR ...241 -6.68 ...233 -1. + .P0LYR ...248 -1. ...249 -1. + .P0LYR ...274 1. + .P900E ...225 -2. ...226 -.64 + .P900E ...227 -19.4 ...228 45. + .P900E ...229 -55. ...231 26.68 + .P900E ...232 -17.6 ...230 5.74 + .P900E ...222 -1. ...246 -1. + .P900E ...247 -1. ...252 1. + .P900E ...000 .0023 + .P930E ...224 1. ...225 -3. + .P930E ...226 3.16 ...227 -23.2 + .P930E ...228 46. ...229 -56. + .P930E ...231 32.98 ...232 -29.4 + .P930E ...230 5.55 ...222 -1. + .P930E ...246 -1. ...247 -1. + .P930E ...253 1. ...000 .0023 + .P960E ...224 2. ...225 -4. + .P960E ...226 6.96 ...227 -27. + .P960E ...228 47. ...229 -57. + .P960E ...231 39.28 ...232 -41.2 + .P960E ...230 5.15 ...222 -1. + .P960E ...246 -1. ...247 -1. + .P960E ...254 1. ...000 .0023 + .P900R ...236 -2. ...237 6. + .P900R ...238 -26. ...239 45. + .P900R ...240 -55. ...242 30. + .P900R ...243 -24.2 ...241 -1.05 + .P900R ...233 -1. ...248 -1. + .P900R ...249 -1. ...252 1. + .P900R ...000 .0023 + .P930R ...235 1. ...236 -3. + .P930R ...237 11. ...238 -31. + .P930R ...239 46. ...240 -56. + .P930R ...242 36.9 ...243 -37.2 + .P930R ...241 -1.27 ...233 -1. + .P930R ...248 -1. ...249 -1. + .P930R ...253 1. ...000 .0023 + .P960R ...235 2. ...236 -4. + .P960R ...237 16. ...238 -36. + .P960R ...239 47. ...240 -57. + .P960R ...242 43.8 ...243 -50.2 + .P960R ...241 -1.71 ...233 -1. + .P960R ...248 -1. ...249 -1. + .P960R ...254 1. ...000 .0023 + .F0RFF ...164 1. ...264 -1. + .F0RFF ...000 .3 + .P90BE ...224 -7. ...225 5. + .P90BE ...226 -43.2 ...227 23.2 + .P90BE ...228 -70. ...229 60. + .P90BE ...231 -68.6 ...232 81. + .P90BE ...230 -3.65 ...222 -1. + .P90BE ...246 -1. ...247 -1. + .P90BE ...256 1. ...000 .0023 + .P93BE ...224 -7. ...225 5. + .P93BE ...226 -43.2 ...227 23.2 + .P93BE ...228 -69. ...229 59. + .P93BE ...231 -68.2 ...232 81. + .P93BE ...230 -5.85 ...222 -1. + .P93BE ...246 -1. ...247 -1. + .P93BE ...257 1. ...000 .0023 + .P96BE ...224 -7. ...225 5. + .P96BE ...226 -43.2 ...227 23.2 + .P96BE ...228 -68. ...229 58. + .P96BE ...231 -67.8 ...232 81. + .P96BE ...230 -7.63 ...222 -1. + .P96BE ...246 -1. ...247 -1. + .P96BE ...258 1. ...000 .0023 + .P990E ...224 3.5 ...225 -5.5 + .P990E ...226 13.04 ...227 -33. + .P990E ...228 49. ...229 -59. + .P990E ...231 49.12 ...232 -59.2 + .P990E ...230 4.43 ...222 -1. + .P990E ...246 -1. ...247 -1. + .P990E ...255 1. ...000 .0023 + .P99BE ...224 -7. ...225 5. + .P99BE ...226 -43.2 ...227 23.2 + .P99BE ...228 -67. ...229 57. + .P99BE ...231 -67.4 ...232 81. + .P99BE ...230 -8.38 ...222 -1. + .P99BE ...246 -1. ...247 -1. + .P99BE ...259 1. ...000 .0023 + .P90BR ...235 -7. ...236 5. + .P90BR ...237 -50. ...238 30. + .P90BR ...239 -70. ...240 60. + .P90BR ...242 -72. ...243 87.8 + .P90BR ...241 -10.34 ...233 -1. + .P90BR ...248 -1. ...249 -1. + .P90BR ...256 1. ...000 .0023 + .P93BR ...235 -7. ...236 5. + .P93BR ...237 -50. ...238 30. + .P93BR ...239 -69. ...240 59. + .P93BR ...242 -71.6 ...243 87.8 + .P93BR ...241 -12.38 ...233 -1. + .P93BR ...248 -1. ...249 -1. + .P93BR ...257 1. ...000 .0023 + .P96BR ...235 -7. ...236 5. + .P96BR ...237 -50. ...238 30. + .P96BR ...239 -68. ...240 58. + .P96BR ...242 -71.2 ...243 87.8 + .P96BR ...241 -14.06 ...233 -1. + .P96BR ...248 -1. ...249 -1. + .P96BR ...258 1. ...000 .0023 + .P990R ...235 3.5 ...236 -5.5 + .P990R ...237 24. ...238 -44. + .P990R ...239 49. ...240 -59. + .P990R ...242 54.6 ...243 -70.2 + .P990R ...241 -2.38 ...233 -1. + .P990R ...248 -1. ...249 -1. + .P990R ...255 1. ...000 .0023 + .P99BR ...235 -7. ...236 5. + .P99BR ...237 -50. ...238 30. + .P99BR ...239 -67. ...240 57. + .P99BR ...242 -70.8 ...243 87.8 + .P99BR ...241 -14.97 ...233 -1. + .P99BR ...248 -1. ...249 -1. + .P99BR ...259 1. ...000 .0023 + .PS3H6 ...155 1. ...164 -1. + .PS3H6 ...166 -13.855 + .HCNTE ...224 -6.5 ...225 4.5 + .HCNTE ...226 -34.08 ...227 14.1 + .HCNTE ...228 -50. ...229 40. + .HCNTE ...231 -54.04 ...222 -1. + .HCNTE ...246 -1. ...232 67.9 + .HCNTE ...230 2.44 ...247 -1. + .HCNTE ...282 1. + .HCNTR ...235 -6.5 ...236 4.5 + .HCNTR ...237 -38. ...240 40. + .HCNTR ...242 -56. ...243 71.8 + .HCNTR ...241 -6.68 ...233 -1. + .HCNTR ...248 -1. ...238 18. + .HCNTR ...239 -50. ...249 -1. + .HCNTR ...282 1. + .LCNBE ...224 -8. ...225 6. + .LCNBE ...226 -29.52 ...227 21.7 + .LCNBE ...228 -56. ...229 46. + .LCNBE ...231 -60.16 ...232 87.5 + .LCNBE ...230 1.92 ...222 -1. + .LCNBE ...246 -1. ...247 -1. + .LCNBE ...281 1. ...000 .0103 + .LCNBR ...235 -8. ...236 6. + .LCNBR ...237 -48. ...238 28. + .LCNBR ...239 -56. ...240 46. + .LCNBR ...242 -69.4 ...243 93.8 + .LCNBR ...241 -7.02 ...233 -1. + .LCNBR ...248 -1. ...249 -1. + .LCNBR ...281 1. ...000 .0103 + .C5TEE ...224 6. ...225 -8. + .C5TEE ...226 40.4 ...227 -60.4 + .C5TEE ...228 40. ...229 -50. + .C5TEE ...231 69.2 ...232 -106.6 + .C5TEE ...230 6.96 ...222 -1. + .C5TEE ...246 -1. ...247 -1. + .C5TEE ...183 1. ...250 1. + .C5TEE ...251 .20083 + .LCN0E ...224 3.5 ...225 -5.5 + .LCN0E ...226 26.72 ...227 -46.7 + .LCN0E ...228 38. ...229 -48. + .LCN0E ...231 51.56 ...232 -72.9 + .LCN0E ...230 -1.19 ...222 -1. + .LCN0E ...246 -1. ...247 -1. + .LCN0E ...250 1. ...280 1. + .LCN0E ...000 .0089 + .LCN0R ...235 3.5 ...236 -5.5 + .LCN0R ...237 42. ...238 -62. + .LCN0R ...239 38. ...240 -48. + .LCN0R ...242 59.2 ...243 -88.2 + .LCN0R ...241 -10.17 ...233 -1. + .LCN0R ...248 -1. ...249 -1. + .LCN0R ...250 1. ...280 1. + .LCN0R ...000 .0089 + .G0TF6 ...142 1. ...146 -1. + .G0TF6 ...164 -1. ...166 -20.051 + .DACFP ...120 2.63 ...147 -.33 + .DACFP ...164 .33 ...166 .49 + .DACFP ...276 -2.013 ...277 3.267 + .DACFP ...278 -1.0164 ...279 -.3102 + .DACFP ...000 .0311 + .C4VEE ...200 1. ...224 55. + .C4VEE ...225 -57. ...226 51.8 + .C4VEE ...227 -71.8 ...228 40. + .C4VEE ...229 -50. ...231 270.9 + .C4VEE ...232 -510. ...230 3.25 + .C4VEE ...222 -1. ...246 -1. + .C4VEE ...247 -1. + .C3VEE ...202 1. ...224 171. + .C3VEE ...225 -173. ...226 70.8 + .C3VEE ...227 -90.8 ...228 70. + .C3VEE ...229 -80. ...231 756.4 + .C3VEE ...232 -1457. ...230 -6.36 + .C3VEE ...222 -1. ...246 -1. + .C3VEE ...247 -1. + .C4VER ...200 1. ...201 1. + .C4VER ...235 55. ...236 -57. + .C4VER ...237 75. ...238 -95. + .C4VER ...239 40. ...240 -50. + .C4VER ...242 282.5 ...243 -533.2 + .C4VER ...241 -5.81 ...233 -1. + .C4VER ...248 -1. ...249 -1. + .C3VER ...202 1. ...203 1. + .C3VER ...235 171. ...236 -173. + .C3VER ...237 100. ...238 -120. + .C3VER ...239 70. ...240 -80. + .C3VER ...242 771. ...243 -1486.2 + .C3VER ...241 -15.15 ...233 -1. + .C3VER ...248 -1. ...249 -1. + .SCSRT ...164 -.033 ...166 -.007 + .SCSRT ...180 1. ...182 1. + .SCSRT ...186 1. ...260 -.079 + .SCSRT ...269 -.3351 ...271 -.0347 + .SCSRT ...275 -.3769 + .P0LYF ...164 -.0059 ...166 -.114 + .P0LYF ...260 -.0802 ...267 -.0427 + .P0LYF ...271 -.0586 ...273 -.1917 + .P0LYF ...274 -.4058 ...283 1. + .P0LYF ...000 .1273 + .VNVER ...176 1. ...189 1. + .VNVER ...235 -9. ...236 7. + .VNVER ...237 -40. ...238 20. + .VNVER ...239 -60. ...240 50. + .VNVER ...242 -71. ...243 93.8 + .VNVER ...241 65.12 ...233 -1. + .VNVER ...248 -1. ...249 -1. + .VN2PT ...134 -5.7 ...164 -.01 + .VN2PT ...166 -.151 ...196 1. + .VN2PT ...199 .4762 ...264 .085 + .VN2PT ...260 -.315 ...302 -.198 + .VN2PT ...303 -.462 + .IMPP0 ...134 -5.05 ...164 -.005 + .IMPP0 ...166 -.076 ...199 .4673 + .IMPP0 ...252 -.34 ...256 -.413 + .IMPP0 ...264 .085 ...260 -.219 + .IMPP0 ...000 3.3169 + .IMPP3 ...134 -5.38 ...164 -.005 + .IMPP3 ...166 -.076 ...199 .4673 + .IMPP3 ...253 -.316 ...260 -.259 + .IMPP3 ...000 3.3201 ...257 -.401 + .IMPP3 ...264 .085 + .IMPP6 ...134 -5.7 ...164 -.01 + .IMPP6 ...166 -.151 ...199 .657 + .IMPP6 ...254 -.288 ...258 -.372 + .IMPP6 ...264 .085 ...260 -.315 + .IMPP6 ...000 3.3233 + .IMPP9 ...134 -5.7 ...164 -.01 + .IMPP9 ...166 -.151 ...199 1.2129 + .IMPP9 ...255 -.235 ...259 -.349 + .IMPP9 ...264 .085 ...260 -.395 + .IMPP9 ...000 3.3305 + .VN3P0 ...134 -5.47 ...164 -.005 + .VN3P0 ...166 -.076 ...197 1. + .VN3P0 ...199 .4673 ...252 -.209 + .VN3P0 ...256 -.561 ...264 .085 + .VN3P0 ...260 -.2 ...000 .0481 + .VN3P3 ...134 -6.13 ...164 -.01 + .VN3P3 ...166 -.151 ...197 1. + .VN3P3 ...199 .4673 ...253 -.212 + .VN3P3 ...257 -.521 ...264 .085 + .VN3P3 ...260 -.235 ...000 .0513 + .VN3P6 ...134 -6.79 ...164 -.01 + .VN3P6 ...166 -.151 ...197 1. + .VN3P6 ...199 .4932 ...254 -.222 + .VN3P6 ...258 -.471 ...264 .085 + .VN3P6 ...260 -.282 ...000 .0545 + .VN4P0 ...134 -5.8 ...164 -.052 + .VN4P0 ...166 -.786 ...198 1. + .VN4P0 ...199 .4673 ...252 -.218 + .VN4P0 ...256 -.538 ...264 .085 + .VN4P0 ...260 -.167 ...000 .0481 + .VN4P3 ...134 -6.51 ...164 -.057 + .VN4P3 ...166 -.861 ...198 1. + .VN4P3 ...199 .4673 ...253 -.231 + .VN4P3 ...257 -.502 ...264 .085 + .VN4P3 ...260 -.188 ...000 .0513 + .VN4P6 ...134 -7.21 ...164 -.081 + .VN4P6 ...166 -1.224 ...198 1. + .VN4P6 ...199 .5055 ...254 -.231 + .VN4P6 ...258 -.442 ...264 .085 + .VN4P6 ...260 -.225 ...000 .0545 + .VN2P0 ...134 -5.05 ...164 -.005 + .VN2P0 ...166 -.076 ...196 1. + .VN2P0 ...199 .4673 ...252 -.34 + .VN2P0 ...256 -.413 ...264 .085 + .VN2P0 ...260 -.219 ...000 .0481 + .VN2P3 ...134 -5.38 ...164 -.005 + .VN2P3 ...166 -.076 ...196 1. + .VN2P3 ...199 .4673 ...253 -.316 + .VN2P3 ...257 -.401 ...264 .085 + .VN2P3 ...260 -.259 ...000 .0513 + .VN2P6 ...134 -5.7 ...164 -.01 + .VN2P6 ...166 -.151 ...196 1. + .VN2P6 ...199 .657 ...254 -.288 + .VN2P6 ...258 -.372 ...264 .085 + .VN2P6 ...260 -.315 ...000 .0545 + .VN3P9 ...134 -7.45 ...164 -.015 + .VN3P9 ...166 -.227 ...197 1. + .VN3P9 ...199 1.1306 ...255 -.216 + .VN3P9 ...259 -.427 ...264 .085 + .VN3P9 ...260 -.331 ...000 .0577 + .VN4P9 ...134 -7.92 ...164 -.086 + .VN4P9 ...166 -1.299 ...198 1. + .VN4P9 ...199 .8789 ...255 -.23 + .VN4P9 ...259 -.394 ...264 .085 + .VN4P9 ...260 -.279 ...000 .0577 + .VN2P9 ...134 -5.7 ...164 -.01 + .VN2P9 ...166 -.151 ...196 1. + .VN2P9 ...199 1.2129 ...255 -.235 + .VN2P9 ...259 -.349 ...264 .085 + .VN2P9 ...260 -.395 ...000 .0577 + .NIMP1 ...176 -1. ...177 -8.5 + .NIMP1 ...178 -62.5 ...187 -100. + .NIMP1 ...188 -55.95 ...000 3.4736 + .NIMP2 ...000 3.1736 ...176 -1. + .NIMP2 ...177 -.9 ...178 16. + .NIMP2 ...187 20. ...188 -46.04 + .C4FVN ...176 1. ...177 64. + .C4FVN ...178 115. ...184 1. + .C4FVN ...187 100. ...188 64. + .WSDIS ...023 .92 ...024 1. + .WSDIS ...025 1. ...176 -.08 + .WSDIS ...177 -.856 ...178 -3.72 + .WSDIS ...187 -4.656 ...188 -4.4312 + .WSDIS ...000 -4.663 + .C5TVN ...176 -1. ...177 -15. + .C5TVN ...178 -100. ...183 1. + .C5TVN ...184 .1614 ...187 -100. + .C5TVN ...188 -60.28 + .ST13T ...043 1. ...044 -.7 + .ST13T ...045 1. ...176 -.3 + .ST13T ...178 6.3 ...187 6. + .ST13T ...188 -19.314 ...000 .0177 + .VN0SC ...176 1. ...177 8.5 + .VN0SC ...178 62.5 ...180 -.62 + .VN0SC ...181 -.38 ...187 100. + .VN0SC ...188 55.95 ...193 .652 + .VN0SC ...194 .652 ...000 .0005 + .VN4VN ...176 -1. ...177 -.9 + .VN4VN ...178 16. ...179 1. + .VN4VN ...187 20. ...188 -46.04 + .VN2PH ...176 1. ...177 2.2 + .VN2PH ...178 -16. ...187 22.4 + .VN2PH ...188 49.12 ...194 .43 + .VN2PH ...195 .43 ...196 -1. + .VN3PH ...176 1. ...177 1.1 + .VN3PH ...178 -30. ...187 -7.4 + .VN3PH ...188 48.08 ...192 .534 + .VN3PH ...195 .534 ...197 -1. + .VN1SC ...176 1. ...177 11. + .VN1SC ...178 94. ...180 -.419 + .VN1SC ...181 -.581 ...187 100. + .VN1SC ...188 59. ...192 .742 + .VN1SC ...193 .742 ...000 .0005 + .C4TS2 ...176 1. ...177 64. + .C4TS2 ...178 115. ...187 100. + .C4TS2 ...188 64. ...189 1. + .C4TS2 ...210 1. ...000 -2.8721 + .C5TS2 ...176 1. ...177 15. + .C5TS2 ...178 100. ...187 100. + .C5TS2 ...188 60.28 ...189 1. + .C5TS2 ...210 1. ...000 -2.8721 + .VN2S2 ...176 1. ...177 2.2 + .VN2S2 ...178 -16. ...187 22.4 + .VN2S2 ...188 49.12 ...189 1. + .VN2S2 ...210 1. ...000 -2.8721 + .VN3S2 ...176 1. ...177 1.1 + .VN3S2 ...178 -30. ...187 -7.4 + .VN3S2 ...188 48.08 ...189 1. + .VN3S2 ...210 1. ...000 -2.8721 + .VN4S2 ...176 1. ...177 .9 + .VN4S2 ...178 -16. ...187 -20. + .VN4S2 ...188 46.04 ...189 1. + .VN4S2 ...210 1. ...000 -2.8721 + .VN0S2 ...176 1. ...177 8.5 + .VN0S2 ...178 62.5 ...187 100. + .VN0S2 ...188 55.95 ...189 1. + .VN0S2 ...210 1. ...000 -2.8721 + .VN1RF ...176 1. ...177 11. + .VN1RF ...178 94. ...187 100. + .VN1RF ...188 59. ...264 -.71 + .VN1RF ...265 .71 + .VN2RF ...176 1. ...177 2.2 + .VN2RF ...178 -16. ...188 49.12 + .VN2RF ...187 22.4 ...264 -.74 + .VN2RF ...265 .74 + .VN3RF ...176 1. ...177 1.1 + .VN3RF ...178 -30. ...187 -7.4 + .VN3RF ...188 48.08 ...264 -.75 + .VN3RF ...265 .75 + .VN0RF ...176 1. ...177 8.5 + .VN0RF ...178 62.5 ...187 100. + .VN0RF ...188 55.95 ...264 -.72 + .VN0RF ...265 .72 + .C4TS1 ...176 1. ...272 50.5 + .C4TS1 ...177 64. ...178 115. + .C4TS1 ...187 100. ...188 64. + .C4TS1 ...189 1. ...205 1. + .C4TS1 ...206 .096 ...207 -.126 + .C4TS1 ...208 55. ...209 -50. + .C4TS1 ...000 -2.8721 + .C5TS1 ...176 1. ...177 15. + .C5TS1 ...272 1.5 ...178 100. + .C5TS1 ...187 100. ...188 60.28 + .C5TS1 ...189 1. ...205 1. + .C5TS1 ...206 .05 ...207 -.08 + .C5TS1 ...208 50. ...209 -50. + .C5TS1 ...000 -2.8721 + .VN1S1 ...176 1. ...177 11. + .VN1S1 ...178 94. ...187 100. + .VN1S1 ...188 59. ...189 1. + .VN1S1 ...205 1. ...206 .03 + .VN1S1 ...207 -.06 ...208 47. + .VN1S1 ...209 -50. ...272 -2.5 + .VN1S1 ...000 -2.8721 + .VN2S1 ...176 1. ...177 2.2 + .VN2S1 ...178 -16. ...187 22.4 + .VN2S1 ...188 49.12 ...189 1. + .VN2S1 ...205 1. ...206 -.06 + .VN2S1 ...207 .03 ...208 -50. + .VN2S1 ...209 14. ...272 -11.3 + .VN2S1 ...000 -2.8721 + .VN3S1 ...176 1. ...177 1.1 + .VN3S1 ...178 -30. ...187 -7.4 + .VN3S1 ...188 48.08 ...189 1. + .VN3S1 ...205 1. ...206 -.069 + .VN3S1 ...207 .039 ...208 -73. + .VN3S1 ...209 45. ...272 -12.4 + .VN3S1 ...000 -2.8721 + .VN4S1 ...176 1. ...177 .9 + .VN4S1 ...178 -16. ...187 -20. + .VN4S1 ...188 46.04 ...189 1. + .VN4S1 ...205 1. ...206 -.083 + .VN4S1 ...207 .053 ...208 -68. + .VN4S1 ...209 60. ...272 -12.6 + .VN4S1 ...000 -2.8721 + .VN0S1 ...176 1. ...177 8.5 + .VN0S1 ...178 62.5 ...187 100. + .VN0S1 ...188 55.95 ...189 1. + .VN0S1 ...205 1. ...206 .006 + .VN0S1 ...207 -.036 ...208 15. + .VN0S1 ...209 -50. ...272 -5. + .VN0S1 ...000 -2.8721 + .NJP46 ...039 3.6 ...040 -4.4 + .NJP46 ...041 -1. ...050 -1. + .NJP46 ...176 1. ...177 6. + .NJP46 ...178 26. ...187 54. + .NJP46 ...188 53.08 ...189 1. + .NJP46 ...000 -.0087 + .NJP47 ...039 4.6 ...040 -5.4 + .NJP47 ...041 -1. ...050 -1. + .NJP47 ...176 1. ...177 7. + .NJP47 ...178 27.5 ...187 54.8 + .NJP47 ...188 53.27 ...189 1. + .NJP47 ...000 -.0087 + .NJP48 ...039 5.6 ...040 -6.4 + .NJP48 ...041 -1. ...050 -1. + .NJP48 ...176 1. ...177 8. + .NJP48 ...178 29. ...187 55.6 + .NJP48 ...188 53.46 ...189 1. + .NJP48 ...000 -.0087 + .VNFEE ...224 1.7 ...225 -3.7 + .VNFEE ...226 -.26 ...227 -19.7 + .VNFEE ...228 -1.8 ...229 -8.2 + .VNFEE ...231 14.95 ...232 -31.5 + .VNFEE ...230 12.86 ...222 -1. + .VNFEE ...246 -1. ...247 -1. + .VNFEE ...176 1. ...177 10.7 + .VNFEE ...178 46.5 ...187 58.2 + .VNFEE ...188 55.39 ...189 1. + .HNGWR ...014 1. ...021 1. + .HNGWR ...142 -.34 ...164 -.366 + .HNGWR ...166 -.091 ...176 -.2857 + .HNGWR ...177 -1.9999 ...178 -5.3997 + .HNGWR ...187 -11.5709 ...188 -15.105 + .HNGWR ...200 -.0043 ...202 -.002 + .HNGWR ...260 -.00112 ...000 2.8145 + .INGNR ...013 1. ...021 1. + .INGNR ...142 -.34 ...164 -.366 + .INGNR ...166 -.9088 ...176 -.2856 + .INGNR ...177 -1.9992 ...178 -5.3978 + .INGNR ...187 -11.5382 ...188 -15.105 + .INGNR ...200 -.0044 ...202 -.002 + .INGNR ...260 -.00112 ...000 2.8317 + .B1MW2 ...011 1. ...019 1. + .B1MW2 ...034 -.135 ...145 -.266 + .B1MW2 ...154 -.152 ...164 -.21 + .B1MW2 ...166 1.4839 ...176 -.2018 + .B1MW2 ...177 -1.4126 ...178 -3.814 + .B1MW2 ...187 -11.7448 ...188 -10.7963 + .B1MW2 ...200 -.0172 ...202 -.008 + .B1MW2 ...260 -.00504 ...000 2.9089 + .TNTWT ...017 .746 ...058 -.29 + .TNTWT ...142 -.238 ...145 -.035 + .TNTWT ...158 -.242 ...159 -.048 + .TNTWT ...164 -.29 ...166 3.69 + .TNTWT ...176 -.1292 ...177 -.9044 + .TNTWT ...178 -2.1189 ...187 -5.5427 + .TNTWT ...188 -7.2107 ...200 -.0058 + .TNTWT ...202 -.006 ...260 -.00336 + .TNTWT ...000 3.215 + .TNBWT ...017 1.111 ...057 -.205 + .TNBWT ...142 -.238 ...145 -.035 + .TNBWT ...158 -.237 ...159 -.138 + .TNBWT ...164 -.205 ...166 2.714 + .TNBWT ...176 -.1292 ...177 -.9044 + .TNBWT ...178 -2.1189 ...187 -5.5427 + .TNBWT ...188 -7.2107 ...200 -.0058 + .TNBWT ...202 -.006 ...260 -.00336 + .TNBWT ...000 3.215 + .KNGWR ...299 1. ...012 -1. + .KNGWR ...021 1. ...142 -.28 + .KNGWR ...164 -.467 ...166 .601 + .KNGWR ...176 -.2321 ...177 -1.6247 + .KNGWR ...178 -4.4099 ...187 -8.9823 + .KNGWR ...188 -12.0181 ...200 -.0069 + .KNGWR ...202 -.005 ...260 -.00504 + .KNGWR ...000 2.6929 + .KNGWC ...012 -1. ...299 1. + .KNGWC ...022 1. ...142 -.28 + .KNGWC ...146 .28 ...164 -.467 + .KNGWC ...166 .601 ...176 -.2321 + .KNGWC ...177 -1.6247 ...178 -4.4099 + .KNGWC ...187 -8.9823 ...188 -12.0181 + .KNGWC ...200 -.0069 ...202 -.005 + .KNGWC ...260 -.00504 ...000 2.6957 + .TNLWT ...017 .746 ...059 -.29 + .TNLWT ...060 -.03 ...142 -.238 + .TNLWT ...145 -.035 ...158 -.26 + .TNLWT ...159 -.03 ...164 -.29 + .TNLWT ...166 3.69 ...176 -.1292 + .TNLWT ...177 -.9044 ...178 -2.1189 + .TNLWT ...187 -5.5427 ...188 -7.2107 + .TNLWT ...200 -.0058 ...202 -.006 + .TNLWT ...260 -.00336 ...000 3.215 + .A5MW3 ...010 1. ...020 .111 + .A5MW3 ...046 -.126 ...145 -.222 + .A5MW3 ...155 -.019 ...164 -.36 + .A5MW3 ...166 .3341 ...176 -.2729 + .A5MW3 ...177 -1.9103 ...178 -3.8479 + .A5MW3 ...187 -8.9328 ...188 -13.9793 + .A5MW3 ...200 .0039 ...202 -.001 + .A5MW3 ...260 -.0017 ...000 2.8771 + .B5MW3 ...011 1. ...020 .111 + .B5MW3 ...046 -.116 ...145 -.16 + .B5MW3 ...155 -.025 ...164 -.39 + .B5MW3 ...166 .0148 ...176 -.2847 + .B5MW3 ...177 -1.9929 ...178 -3.8435 + .B5MW3 ...187 -10.9325 ...188 -14.8044 + .B5MW3 ...200 -.0083 ...202 -.008 + .B5MW3 ...260 -.00504 ...000 2.9066 + .T5TWT ...017 .746 ...037 -.15 + .T5TWT ...058 -.29 ...142 -.088 + .T5TWT ...145 -.035 ...158 -.242 + .T5TWT ...159 -.048 ...164 -.29 + .T5TWT ...166 3.69 ...176 -.1292 + .T5TWT ...177 -.9044 ...178 -2.1189 + .T5TWT ...187 -5.5427 ...188 -7.2107 + .T5TWT ...200 -.0058 ...202 -.006 + .T5TWT ...260 -.00336 ...000 3.215 + .T5BWT ...017 1.111 ...037 -.15 + .T5BWT ...057 -.205 ...142 -.088 + .T5BWT ...145 -.035 ...158 -.237 + .T5BWT ...159 -.138 ...164 -.205 + .T5BWT ...166 2.724 ...176 -.1292 + .T5BWT ...177 -.9044 ...178 -2.1189 + .T5BWT ...187 -5.5427 ...188 -7.2107 + .T5BWT ...200 -.0058 ...202 -.006 + .T5BWT ...260 -.00336 ...000 3.215 + .T5LWT ...017 .746 ...037 -.15 + .T5LWT ...059 -.29 ...060 -.03 + .T5LWT ...142 -.088 ...145 -.035 + .T5LWT ...158 -.26 ...159 -.03 + .T5LWT ...164 -.29 ...166 3.69 + .T5LWT ...176 -.1292 ...177 -.9044 + .T5LWT ...178 -2.1189 ...187 -5.5427 + .T5LWT ...188 -7.2107 ...200 -.0058 + .T5LWT ...202 -.006 ...260 -.00336 + .T5LWT ...000 3.215 + .B1MN3 ...011 1. ...020 .111 + .B1MN3 ...034 -.116 ...145 -.306 + .B1MN3 ...164 -.342 ...166 .5595 + .B1MN3 ...176 -.2018 ...177 -1.4126 + .B1MN3 ...178 -3.814 ...187 -11.7448 + .B1MN3 ...188 -10.7963 ...200 -.0172 + .B1MN3 ...202 -.008 ...260 -.00504 + .B1MN3 ...000 2.9061 + .QKMW2 ...026 -.1343 ...016 1. + .QKMW2 ...019 1. ...027 -.235 + .QKMW2 ...145 -.115 ...153 -.062 + .QKMW2 ...154 -.146 ...164 -.14 + .QKMW2 ...166 .5247 ...176 -.2755 + .QKMW2 ...177 -1.9285 ...178 -5.2345 + .QKMW2 ...187 -6.9977 ...188 -14.5023 + .QKMW2 ...200 -.0125 ...202 -.009 + .QKMW2 ...260 -.0028 ...000 2.9969 + .IKMW2 ...026 -.1293 ...013 1. + .IKMW2 ...019 1. ...027 -.19 + .IKMW2 ...145 -.19 ...153 -.037 + .IKMW2 ...154 -.193 ...164 -.16 + .IKMW2 ...166 1.589 ...176 -.2165 + .IKMW2 ...177 -1.5155 ...178 -6.5167 + .IKMW2 ...187 -13.8127 ...188 -11.6585 + .IKMW2 ...200 -.0095 ...202 -.002 + .IKMW2 ...260 -.00112 ...000 2.8409 + .JNGW2 ...015 1. ...019 1. + .JNGW2 ...142 -.299 ...153 -.05 + .JNGW2 ...154 -.175 ...164 -.18 + .JNGW2 ...166 1.787 ...176 -.1965 + .JNGW2 ...177 -1.3755 ...178 -5.8164 + .JNGW2 ...179 -.085 ...187 -12.3599 + .JNGW2 ...188 -10.5776 ...200 -.0065 + .JNGW2 ...202 -.004 ...260 -.00224 + .JNGW2 ...000 2.8236 + .AKMW2 ...026 -.1143 ...010 1. + .AKMW2 ...019 1. ...027 -.2 + .AKMW2 ...145 -.16 ...153 -.052 + .AKMW2 ...154 -.2 ...164 -.16 + .AKMW2 ...166 1.5197 ...176 -.2232 + .AKMW2 ...177 -1.5624 ...178 -6.071 + .AKMW2 ...187 -9.7315 ...188 -11.3765 + .AKMW2 ...200 -.0008 ...202 -.001 + .AKMW2 ...260 -.00168 ...000 2.8796 + .KN8W3 ...012 -1. ...020 .132 + .KN8W3 ...299 1. ...032 -.7 + .KN8W3 ...033 -.196 ...155 -.06 + .KN8W3 ...164 -.437 ...166 1.0927 + .KN8W3 ...176 -.1429 ...177 -1.0003 + .KN8W3 ...178 -4.2156 ...179 -.08 + .KN8W3 ...187 -9.7029 ...188 -7.638 + .KN8W3 ...200 -.0161 ...202 -.005 + .KN8W3 ...260 -.00504 ...000 2.6992 + .BKMW2 ...026 -.1086 ...011 1. + .BKMW2 ...019 1. ...027 -.19 + .BKMW2 ...145 -.14 ...153 -.042 + .BKMW2 ...154 -.187 ...164 -.21 + .BKMW2 ...166 1.484 ...176 -.1963 + .BKMW2 ...177 -1.3741 ...178 -4.829 + .BKMW2 ...187 -11.7976 ...188 -10.5256 + .BKMW2 ...200 -.0177 ...202 -.008 + .BKMW2 ...260 -.00504 ...000 2.9089 + .KRMN2 ...299 1. ...028 -.0777 + .KRMN2 ...012 -1. ...019 1. + .KRMN2 ...029 -.11152 ...145 -.12 + .KRMN2 ...153 -.08 ...154 -.182 + .KRMN2 ...164 -.255 ...166 2.274 + .KRMN2 ...176 -.2015 ...177 -1.4105 + .KRMN2 ...178 -3.9091 ...187 -9.1481 + .KRMN2 ...188 -10.4982 ...200 -.0115 + .KRMN2 ...202 -.005 ...260 -.00504 + .KRMN2 ...000 2.7023 + .QKMN3 ...016 1. ...020 .118 + .QKMN3 ...026 -.1229 ...027 -.215 + .QKMN3 ...145 -.155 ...155 -.075 + .QKMN3 ...164 -.253 ...166 -.3722 + .QKMN3 ...176 -.2755 ...177 -1.9285 + .QKMN3 ...178 -5.2345 ...187 -6.9977 + .QKMN3 ...188 -14.5023 ...200 -.0125 + .QKMN3 ...202 -.009 ...260 -.0028 + .QKMN3 ...000 2.9941 + .A1GW2 ...010 1. ...019 1. + .A1GW2 ...034 -.141 ...142 -.212 + .A1GW2 ...153 -.054 ...154 -.2 + .A1GW2 ...164 -.16 ...166 1.5197 + .A1GW2 ...176 -.2286 ...177 -1.6002 + .A1GW2 ...178 -3.7033 ...187 -9.5326 + .A1GW2 ...188 -11.8026 ...200 -.0004 + .A1GW2 ...202 -.001 ...260 -.00168 + .A1GW2 ...000 2.8797 + .B1GW2 ...011 1. ...019 1. + .B1GW2 ...034 -.135 ...142 -.216 + .B1GW2 ...153 -.015 ...154 -.187 + .B1GW2 ...164 -.21 ...166 1.4839 + .B1GW2 ...176 -.2018 ...177 -1.4126 + .B1GW2 ...178 -3.814 ...187 -11.7448 + .B1GW2 ...188 -10.7963 ...200 -.0172 + .B1GW2 ...202 -.008 ...260 -.00504 + .B1GW2 ...000 2.9089 + .IRGW3 ...028 -.1086 ...013 1. + .IRGW3 ...020 .111 ...029 -.1558 + .IRGW3 ...142 -.15 ...155 -.075 + .IRGW3 ...164 -.355 ...166 .5765 + .IRGW3 ...176 -.2165 ...177 -1.5155 + .IRGW3 ...178 -6.6249 ...187 -13.8127 + .IRGW3 ...188 -11.6585 ...200 -.0095 + .IRGW3 ...202 -.002 ...260 -.00112 + .IRGW3 ...000 2.8381 + .IKMN3 ...013 1. ...020 .118 + .IKMN3 ...026 -.0983 ...027 -.172 + .IKMN3 ...145 -.216 ...155 -.035 + .IKMN3 ...164 -.323 ...166 .435 + .IKMN3 ...176 -.2424 ...177 -1.6968 + .IKMN3 ...178 -6.3266 ...187 -13.2108 + .IKMN3 ...188 -12.9563 ...200 -.0076 + .IKMN3 ...202 -.002 ...260 -.00112 + .IKMN3 ...000 2.8383 + .IKMN4 ...013 1. ...020 .139 + .IKMN4 ...026 -.0983 ...027 -.172 + .IKMN4 ...145 -.216 ...155 -.118 + .IKMN4 ...164 -.24 ...166 1.6186 + .IKMN4 ...176 -.2421 ...177 -1.6947 + .IKMN4 ...178 -6.3914 ...187 -13.1702 + .IKMN4 ...188 -12.9378 ...200 -.0079 + .IKMN4 ...202 -.002 ...260 -.00112 + .IKMN4 ...000 2.8383 + .AKMW3 ...010 1. ...020 .111 + .AKMW3 ...026 -.1143 ...027 -.2 + .AKMW3 ...145 -.16 ...155 -.052 + .AKMW3 ...164 -.36 ...166 .3341 + .AKMW3 ...176 -.2232 ...177 -1.5624 + .AKMW3 ...178 -6.071 ...187 -9.7315 + .AKMW3 ...188 -11.3765 ...200 -.0008 + .AKMW3 ...202 -.001 ...260 -.00168 + .AKMW3 ...000 2.8768 + .CNGW3 ...294 1. ...020 .114 + .CNGW3 ...142 -.252 ...155 -.081 + .CNGW3 ...000 2.38 ...164 -.493 + .CNGW3 ...166 3.436 ...176 -.1409 + .CNGW3 ...177 -.9863 ...178 -2.8462 + .CNGW3 ...179 -.026 ...187 -7.045 + .CNGW3 ...188 -7.7143 ...200 -.0031 + .CNGW3 ...202 -.003 ...260 -.00056 + .A5GW3 ...010 1. ...020 .111 + .A5GW3 ...046 -.126 ...142 -.164 + .A5GW3 ...155 -.077 ...164 -.36 + .A5GW3 ...166 .3341 ...176 -.2729 + .A5GW3 ...177 -1.9103 ...178 -3.8479 + .A5GW3 ...187 -8.9238 ...188 -13.9397 + .A5GW3 ...200 .0039 ...202 -.001 + .A5GW3 ...260 -.0017 ...000 2.8771 + .B5GW3 ...011 1. ...020 .111 + .B5GW3 ...046 -.116 ...142 -.11 + .B5GW3 ...155 -.075 ...164 -.39 + .B5GW3 ...166 .0148 ...176 -.2847 + .B5GW3 ...177 -1.9929 ...178 -3.8435 + .B5GW3 ...187 -10.9325 ...188 -14.8044 + .B5GW3 ...200 -.0083 ...202 -.008 + .B5GW3 ...260 -.00504 ...000 2.9066 + .INGW3 ...013 1. ...020 .115 + .INGW3 ...142 -.306 ...155 -.066 + .INGW3 ...164 -.334 ...166 .346 + .INGW3 ...176 -.1882 ...177 -1.3174 + .INGW3 ...178 -6.7376 ...179 -.09 + .INGW3 ...187 -14.2279 ...188 -10.2381 + .INGW3 ...200 -.0118 ...202 -.002 + .INGW3 ...260 -.00112 ...000 2.8379 + .A1GW3 ...010 1. ...020 .111 + .A1GW3 ...034 -.141 ...142 -.212 + .A1GW3 ...155 -.054 ...164 -.36 + .A1GW3 ...166 .3341 ...176 -.2286 + .A1GW3 ...177 -1.6002 ...178 -3.7033 + .A1GW3 ...187 -9.5326 ...188 -11.8026 + .A1GW3 ...200 -.0004 ...202 -.001 + .A1GW3 ...260 -.00168 ...000 2.8769 + .B1GW3 ...011 1. ...020 .111 + .B1GW3 ...034 -.135 ...142 -.216 + .B1GW3 ...155 -.022 ...164 -.39 + .B1GW3 ...166 .0148 ...176 -.2018 + .B1GW3 ...177 -1.4126 ...178 -3.814 + .B1GW3 ...187 -11.7448 ...188 -10.7963 + .B1GW3 ...200 -.0172 ...202 -.008 + .B1GW3 ...260 -.00504 ...000 2.9061 + .KTGW1 ...299 1. ...012 -1. + .KTGW1 ...018 1. ...053 -.152 + .KTGW1 ...142 -.143 ...149 -.046 + .KTGW1 ...150 -.105 ...151 -.065 + .KTGW1 ...152 -.065 ...164 -.255 + .KTGW1 ...166 2.274 ...176 -.1388 + .KTGW1 ...177 -.9716 ...178 -4.2334 + .KTGW1 ...187 -9.6882 ...188 -7.423 + .KTGW1 ...200 -.0162 ...202 -.005 + .KTGW1 ...260 -.00504 ...000 2.6988 + .KWGW1 ...012 -1. ...299 1. + .KWGW1 ...018 1. ...141 -.245 + .KWGW1 ...142 -.245 ...150 -.1 + .KWGW1 ...151 -.065 ...152 -.065 + .KWGW1 ...164 -.255 ...166 2.274 + .KWGW1 ...176 -.1938 ...177 -1.3566 + .KWGW1 ...178 -3.9148 ...187 -9.1474 + .KWGW1 ...188 -10.144 ...200 -.0122 + .KWGW1 ...202 -.005 ...025 -.05 + .KWGW1 ...260 -.00504 ...000 2.6992 + .KKMN1 ...299 1. ...026 -.0777 + .KKMN1 ...012 -1. ...018 1. + .KKMN1 ...027 -.136 ...145 -.12 + .KKMN1 ...149 -.027 ...150 -.105 + .KKMN1 ...151 -.065 ...152 -.065 + .KKMN1 ...164 -.255 ...166 2.274 + .KKMN1 ...176 -.2015 ...177 -1.4105 + .KKMN1 ...178 -3.9091 ...187 -9.1481 + .KKMN1 ...188 -10.4982 ...200 -.0115 + .KKMN1 ...202 -.005 ...260 -.00504 + .KKMN1 ...000 2.6992 + .K5GW1 ...299 1. ...012 -1. + .K5GW1 ...018 1. ...046 -.1 + .K5GW1 ...142 -.07 ...149 -.082 + .K5GW1 ...150 -.105 ...151 -.065 + .K5GW1 ...152 -.065 ...164 -.255 + .K5GW1 ...166 2.274 ...176 -.2377 + .K5GW1 ...177 -1.6639 ...178 -4.5638 + .K5GW1 ...187 -8.9851 ...188 -12.2986 + .K5GW1 ...200 -.0063 ...202 -.005 + .K5GW1 ...260 -.00504 ...000 2.6994 + .QKGW2 ...026 -.1343 ...016 1. + .QKGW2 ...019 1. ...027 -.235 + .QKGW2 ...142 -.09 ...153 -.087 + .QKGW2 ...154 -.146 ...164 -.14 + .QKGW2 ...166 .5247 ...176 -.2755 + .QKGW2 ...177 -1.9285 ...178 -5.2345 + .QKGW2 ...187 -6.9977 ...188 -14.5023 + .QKGW2 ...200 -.0125 ...202 -.009 + .QKGW2 ...260 -.0028 ...000 2.9969 + .K1GW1 ...299 1. ...012 -1. + .K1GW1 ...018 1. ...034 -.11 + .K1GW1 ...142 -.129 ...149 -.052 + .K1GW1 ...150 -.105 ...151 -.065 + .K1GW1 ...152 -.065 ...164 -.255 + .K1GW1 ...166 2.274 ...176 -.1928 + .K1GW1 ...177 -1.3494 ...178 -3.8946 + .K1GW1 ...187 -9.1474 ...188 -10.0719 + .K1GW1 ...200 -.0122 ...202 -.005 + .K1GW1 ...260 -.00504 ...000 2.6992 + .IKGW2 ...026 -.1293 ...013 1. + .IKGW2 ...019 1. ...027 -.19 + .IKGW2 ...142 -.15 ...153 -.077 + .IKGW2 ...154 -.193 ...164 -.16 + .IKGW2 ...166 1.589 ...176 -.2165 + .IKGW2 ...177 -1.5155 ...178 -6.5167 + .IKGW2 ...187 -13.8127 ...188 -11.6585 + .IKGW2 ...200 -.0095 ...202 -.002 + .IKGW2 ...260 -.00112 ...000 2.8409 + .KNGW1 ...299 1. ...012 -1. + .KNGW1 ...018 1. ...142 -.28 + .KNGW1 ...150 -.082 ...151 -.065 + .KNGW1 ...152 -.065 ...164 -.255 + .KNGW1 ...166 2.274 ...176 -.1429 + .KNGW1 ...177 -1.0003 ...178 -4.2156 + .KNGW1 ...179 -.08 ...187 -9.7029 + .KNGW1 ...188 -7.638 ...200 -.0161 + .KNGW1 ...202 -.005 ...260 -.00504 + .KNGW1 ...000 2.6989 + .A4GW2 ...010 1. ...019 1. + .A4GW2 ...039 -.4248 ...040 .2832 + .A4GW2 ...041 -.177 ...154 -.2 + .A4GW2 ...164 -.16 ...166 1.5197 + .A4GW2 ...176 -.1792 ...177 -1.2544 + .A4GW2 ...178 -3.7811 ...187 -10.4474 + .A4GW2 ...188 -9.3901 ...200 -.0048 + .A4GW2 ...202 -.001 ...260 -.00168 + .A4GW2 ...000 2.8794 + .AKGW2 ...026 -.1143 ...010 1. + .AKGW2 ...019 1. ...027 -.2 + .AKGW2 ...142 -.104 ...153 -.108 + .AKGW2 ...154 -.2 ...164 -.16 + .AKGW2 ...166 1.52 ...176 -.2232 + .AKGW2 ...177 -1.5624 ...178 -4.955 + .AKGW2 ...187 -9.7315 ...188 -11.5484 + .AKGW2 ...200 -.0008 ...202 -.001 + .AKGW2 ...260 -.00168 ...000 2.8796 + .BKGW2 ...026 -.1086 ...011 1. + .BKGW2 ...019 1. ...027 -.19 + .BKGW2 ...142 -.09 ...153 -.092 + .BKGW2 ...154 -.187 ...164 -.21 + .BKGW2 ...166 1.4839 ...176 -.1964 + .BKGW2 ...177 -1.3748 ...178 -4.8511 + .BKGW2 ...187 -11.8036 ...188 -10.531 + .BKGW2 ...200 -.0176 ...202 -.008 + .BKGW2 ...260 -.00504 ...000 2.9089 + .B4GW2 ...011 1. ...019 1. + .B4GW2 ...039 -.3984 ...040 .2656 + .B4GW2 ...041 -.166 ...142 -.094 + .B4GW2 ...153 -.045 ...154 -.283 + .B4GW2 ...164 -.21 ...166 1.4839 + .B4GW2 ...176 -.146 ...177 -1.022 + .B4GW2 ...178 -6.5846 ...187 -12.2932 + .B4GW2 ...188 -7.976 ...200 -.021 + .B4GW2 ...202 -.008 ...260 -.00504 + .B4GW2 ...000 2.9086 + .C4GW3 ...294 1. ...020 .114 + .C4GW3 ...000 2.38 ...039 -.3504 + .C4GW3 ...040 .2336 ...041 -.146 + .C4GW3 ...142 -.124 ...155 -.118 + .C4GW3 ...164 -.493 ...166 3.436 + .C4GW3 ...176 -.1089 ...177 -.7623 + .C4GW3 ...178 -2.5918 ...187 -7.2527 + .C4GW3 ...188 -6.0178 ...200 -.0061 + .C4GW3 ...202 -.003 ...260 -.00056 + .QKGW3 ...016 1. ...020 .118 + .QKGW3 ...026 -.1343 ...027 -.235 + .QKGW3 ...142 -.09 ...155 -.12 + .QKGW3 ...164 -.253 ...166 -.28 + .QKGW3 ...176 -.2756 ...177 -1.9292 + .QKGW3 ...178 -5.264 ...187 -7.0278 + .QKGW3 ...188 -14.5076 ...200 -.0124 + .QKGW3 ...202 -.009 ...260 -.0028 + .QKGW3 ...000 2.9941 + .QKGW4 ...016 1. ...020 .139 + .QKGW4 ...026 -.1343 ...027 -.235 + .QKGW4 ...142 -.09 ...155 -.203 + .QKGW4 ...164 -.17 ...166 .3468 + .QKGW4 ...176 -.2755 ...177 -1.9285 + .QKGW4 ...178 -4.408 ...187 -6.9977 + .QKGW4 ...188 -14.5023 ...200 -.0125 + .QKGW4 ...202 -.009 ...260 -.0028 + .QKGW4 ...000 2.9941 + .A4GW3 ...010 1. ...020 .111 + .A4GW3 ...039 -.4248 ...040 .2832 + .A4GW3 ...041 -.177 ...142 -.23 + .A4GW3 ...155 -.045 ...164 -.36 + .A4GW3 ...166 .3341 ...176 -.1792 + .A4GW3 ...177 -1.2544 ...178 -3.7811 + .A4GW3 ...187 -10.4474 ...188 -9.3901 + .A4GW3 ...200 -.0048 ...202 -.001 + .A4GW3 ...260 -.00168 ...000 2.8766 + .BKGW3 ...011 1. ...020 .111 + .BKGW3 ...026 -.1086 ...027 -.19 + .BKGW3 ...142 -.09 ...155 -.099 + .BKGW3 ...164 -.39 ...166 1.5031 + .BKGW3 ...176 -.1964 ...177 -1.3748 + .BKGW3 ...178 -4.8511 ...187 -11.8036 + .BKGW3 ...188 -10.531 ...200 -.0176 + .BKGW3 ...202 -.008 ...260 -.00504 + .BKGW3 ...000 2.9061 + .B4GW3 ...011 1. ...020 .111 + .B4GW3 ...039 -.3984 ...040 .2656 + .B4GW3 ...041 -.166 ...142 -.094 + .B4GW3 ...155 -.148 ...164 -.39 + .B4GW3 ...166 1.5031 ...176 -.146 + .B4GW3 ...177 -1.022 ...178 -6.5846 + .B4GW3 ...187 -12.2932 ...188 -7.976 + .B4GW3 ...200 -.021 ...202 -.008 + .B4GW3 ...260 -.00504 ...000 2.9058 + .KNGW2 ...299 1. ...012 -1. + .KNGW2 ...019 1. ...142 -.28 + .KNGW2 ...154 -.212 ...164 -.255 + .KNGW2 ...166 .2274 ...176 -.1429 + .KNGW2 ...177 -1.0003 ...178 -4.2156 + .KNGW2 ...179 -.08 ...187 -9.7029 + .KNGW2 ...188 -7.638 ...200 -.0161 + .KNGW2 ...202 -.005 ...260 -.00504 + .KNGW2 ...000 2.702 + .K5GW3 ...012 -1. ...020 .114 + .K5GW3 ...299 1. ...046 -.1 + .K5GW3 ...142 -.07 ...155 -.12 + .K5GW3 ...164 -.452 ...166 .786 + .K5GW3 ...176 -.2377 ...177 -1.6639 + .K5GW3 ...178 -4.5638 ...187 -8.9851 + .K5GW3 ...188 -12.2986 ...200 -.0063 + .K5GW3 ...202 -.005 ...260 -.00504 + .K5GW3 ...000 2.6997 + .K5GW4 ...012 -1. ...020 .139 + .K5GW4 ...299 1. ...046 -.1 + .K5GW4 ...142 -.07 ...155 -.242 + .K5GW4 ...164 -.33 ...166 2.897 + .K5GW4 ...176 -.2377 ...177 -1.6639 + .K5GW4 ...178 -4.5638 ...187 -8.9851 + .K5GW4 ...188 -12.2986 ...200 -.0063 + .K5GW4 ...202 -.005 ...260 -.00504 + .K5GW4 ...000 2.6997 + .K1GW3 ...012 -1. ...020 .116 + .K1GW3 ...034 -.11 ...142 -.129 + .K1GW3 ...155 -.142 ...164 -.4 + .K1GW3 ...166 1.249 ...176 -.1928 + .K1GW3 ...177 -1.3496 ...178 -3.8946 + .K1GW3 ...187 -9.1474 ...188 -10.0719 + .K1GW3 ...200 -.0122 ...202 -.005 + .K1GW3 ...260 -.00504 ...000 2.6995 + .K1GW3 ...299 1. + .K1GW4 ...012 -1. ...020 .139 + .K1GW4 ...299 1. ...034 -.11 + .K1GW4 ...142 -.129 ...155 -.212 + .K1GW4 ...164 -.33 ...166 2.897 + .K1GW4 ...176 -.1928 ...177 -1.3496 + .K1GW4 ...178 -3.8946 ...187 -9.1002 + .K1GW4 ...188 -10.0719 ...200 -.0122 + .K1GW4 ...202 -.005 ...260 -.00504 + .K1GW4 ...000 2.6995 + .KNGW3 ...012 -1. ...020 .118 + .KNGW3 ...299 1. ...142 -.25 + .KNGW3 ...155 -.06 ...164 -.437 + .KNGW3 ...166 .955 ...176 -.1429 + .KNGW3 ...177 -1.0003 ...178 -4.2156 + .KNGW3 ...179 -.08 ...187 -9.7029 + .KNGW3 ...188 -7.638 ...200 -.0161 + .KNGW3 ...202 -.005 ...260 -.00504 + .KNGW3 ...000 2.6992 + .KNGW4 ...012 -1. ...020 .139 + .KNGW4 ...299 1. ...142 -.25 + .KNGW4 ...155 -.167 ...164 -.33 + .KNGW4 ...166 2.897 ...176 -.1429 + .KNGW4 ...177 -1.0003 ...178 -4.2156 + .KNGW4 ...179 -.08 ...187 -9.7029 + .KNGW4 ...188 -7.638 ...200 -.0161 + .KNGW4 ...202 -.005 ...260 -.00504 + .KNGW4 ...000 2.6992 + .K4GW1 ...299 1. ...012 -1. + .K4GW1 ...018 1. ...039 -.3648 + .K4GW1 ...040 .2432 ...041 -.152 + .K4GW1 ...142 -.143 ...149 -.046 + .K4GW1 ...150 -.105 ...151 -.065 + .K4GW1 ...152 -.065 ...164 -.255 + .K4GW1 ...166 2.274 ...176 -.1388 + .K4GW1 ...177 -.9716 ...178 -4.2334 + .K4GW1 ...187 -9.6882 ...188 -7.43 + .K4GW1 ...200 -.0162 ...202 -.005 + .K4GW1 ...260 -.00504 ...000 2.6988 + .K4GW2 ...299 1. ...012 -1. + .K4GW2 ...019 1. ...039 -.3648 + .K4GW2 ...040 .2432 ...041 -.152 + .K4GW2 ...142 -.143 ...153 -.096 + .K4GW2 ...154 -.185 ...164 -.255 + .K4GW2 ...166 2.274 ...176 -.1388 + .K4GW2 ...177 -.9716 ...178 -4.2334 + .K4GW2 ...187 -9.6882 ...188 -7.43 + .K4GW2 ...200 -.0162 ...202 -.005 + .K4GW2 ...260 -.00504 ...000 2.7019 + .K4GW3 ...012 -1. ...020 .114 + .K4GW3 ...299 1. ...039 -.3648 + .K4GW3 ...040 .2432 ...041 -.152 + .K4GW3 ...142 -.143 ...155 -.12 + .K4GW3 ...164 -.416 ...166 1.192 + .K4GW3 ...176 -.1388 ...177 -.9716 + .K4GW3 ...178 -4.2334 ...187 -9.6882 + .K4GW3 ...188 -7.43 ...200 -.0162 + .K4GW3 ...202 -.005 ...260 -.00504 + .K4GW3 ...000 2.6991 + .KKGN3 ...012 -1. ...020 .118 + .KKGN3 ...299 1. ...026 -.0777 + .KKGN3 ...027 -.136 ...142 -.117 + .KKGN3 ...155 -.11 ...164 -.41 + .KKGN3 ...166 1.216 ...176 -.2015 + .KKGN3 ...177 -1.4105 ...178 -3.9091 + .KKGN3 ...187 -9.1481 ...188 -10.4982 + .KKGN3 ...202 -.005 ...200 -.0115 + .KKGN3 ...260 -.00504 ...000 2.6995 + .K4GW4 ...012 -1. ...020 .139 + .K4GW4 ...299 1. ...039 -.3648 + .K4GW4 ...040 .2432 ...041 -.152 + .K4GW4 ...142 -.143 ...155 -.206 + .K4GW4 ...164 -.33 ...166 2.897 + .K4GW4 ...176 -.1388 ...177 -.9716 + .K4GW4 ...178 -4.2334 ...187 -9.6882 + .K4GW4 ...188 -7.43 ...200 -.0162 + .K4GW4 ...202 -.005 ...260 -.00504 + .K4GW4 ...000 2.6991 + .KKGN4 ...012 -1. ...020 .139 + .KKGN4 ...299 1. ...026 -.0777 + .KKGN4 ...027 -.136 ...142 -.117 + .KKGN4 ...155 -.19 ...164 -.33 + .KKGN4 ...166 2.897 ...176 -.2015 + .KKGN4 ...177 -1.4105 ...178 -3.9091 + .KKGN4 ...187 -9.1481 ...188 -10.4982 + .KKGN4 ...200 -.0115 ...202 -.005 + .KKGN4 ...260 -.00504 ...000 2.6995 + .VN3HF ...176 1. ...295 -1. + .VN3HF ...177 1.1 ...178 -30. + .VN3HF ...187 -7.4 ...188 48.08 + .VN3HF ...192 .534 ...195 .534 + .VNFHF ...000 .123 ...134 -1.25 + .VNFHF ...164 -.03 ...166 -.4092 + .VNFHF ...260 -.246 ...295 1. + .VNFHF ...296 1. ...297 1. + .VNFHF ...298 -.62 +RHS + ZZZZZZ01 ...000 -7.113 ...010 2.284 + ZZZZZZ01 ...011 1.59 ...013 3.99 + ZZZZZZ01 ...014 .109 ...015 .69 + ZZZZZZ01 ...017 1. ...018 5.216 + ZZZZZZ01 ...019 7.233 ...020 1. + ZZZZZZ01 ...021 .65 ...023 .1395 + ZZZZZZ01 ...024 .1805 ...030 1.3453 + ZZZZZZ01 ...035 .4207 ...038 .6665 + ZZZZZZ01 ...043 .5 ...048 .1019 + ZZZZZZ01 ...050 .935 ...055 .96 + ZZZZZZ01 ...057 -.0098 ...059 -.2662 + ZZZZZZ01 ...060 -.0104 ...120 .099 + ZZZZZZ01 ...133 1.6342 ...134 1.8 + ZZZZZZ01 ...135 16.5 ...136 1.5 + ZZZZZZ01 ...138 .1938 ...142 -.0637 + ZZZZZZ01 ...143 .6344 ...144 .6045 + ZZZZZZ01 ...147 .5789 ...148 .347 + ZZZZZZ01 ...150 -.0459 ...151 -.1422 + ZZZZZZ01 ...152 -.2448 ...156 -12.1938 + ZZZZZZ01 ...157 -.6231 ...158 -.2857 + ZZZZZZ01 ...159 -.033 ...160 .2314 + ZZZZZZ01 ...161 .0675 ...163 4.3845 + ZZZZZZ01 ...164 -.3658 ...165 3.8254 + ZZZZZZ01 ...166 3.3851 ...167 .0327 + ZZZZZZ01 ...168 .0487 ...169 .0775 + ZZZZZZ01 ...172 .05 ...174 .205 + ZZZZZZ01 ...175 .1375 ...176 .1692 + ZZZZZZ01 ...177 1.8446 ...178 9.1385 + ZZZZZZ01 ...179 .0495 ...182 .631 + ZZZZZZ01 ...185 .5 ...186 1.05 + ZZZZZZ01 ...187 10.8308 ...188 9.5531 + ZZZZZZ01 ...189 .1692 ...190 2.952 + ZZZZZZ01 ...191 1.302 ...192 1. + ZZZZZZ01 ...193 1. ...194 1. + ZZZZZZ01 ...195 1. ...196 .1181 + ZZZZZZ01 ...197 .1181 ...199 1. + ZZZZZZ01 ...202 -.0095 ...204 .1107 + ZZZZZZ01 ...205 .3953 ...212 .3987 + ZZZZZZ01 ...223 2.908 ...234 1.9642 + ZZZZZZ01 ...250 1.7 ...261 2.799 + ZZZZZZ01 ...263 56.92 ...264 -1.1958 + ZZZZZZ01 ...265 .44 ...266 .5 + ZZZZZZ01 ...268 .0425 ...270 .1984 + ZZZZZZ01 ...276 1.5231 ...277 3.9475 + ZZZZZZ01 ...278 1.2884 ...279 .5186 + ZZZZZZ01 ...280 -.1901 ...281 .1275 + ZZZZZZ01 ...284 42. ...285 3.8 + ZZZZZZ01 ...291 4.68 ...292 2.4 + ZZZZZZ01 ...293 .1114 ...294 2.264 + ZZZZZZ01 ...299 10.57 ...300 .2137 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.5.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.5.mps new file mode 100644 index 000000000..5e4957487 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.5.mps @@ -0,0 +1,77 @@ +************************************************************************ +* +* The data in this file represents the following problem: +* +* Minimize or maximize Z = x1 + 2x5 - x8 +* +* Subject to: +* +* 2.5 <= 3x1 + x2 - 2x4 - x5 - x8 +* 2x2 + 1.1x3 <= 2.1 +* x3 + x6 = 4.0 +* 1.8 <= 2.8x4 -1.2x7 <= 5.0 +* 3.0 <= 5.6x1 + x5 + 1.9x8 <= 15.0 +* 15x3 + 12x4 + x5 <= 6.8 +* +* where: +* +* 2.5 <= x1 +* 0 <= x2 <= 4.1 +* 0 <= x3 +* 0 <= x4 +* 0.5 <= x5 <= 4.0 +* 0 <= x6 +* 0 <= x7 <= 2.0 +* 0 <= x8 <= 4.3 +* +* x3, x4 are 0,1 variables. +* +************************************************************************ +NAME EXAMPLE +ROWS + N OBJ + G ROW01 + L ROW02 + E ROW03 + G ROW04 + L ROW05 + L ROW06 +COLUMNS + COL01 OBJ 1.0 + COL01 ROW01 3.0 ROW05 5.6 + COL02 ROW01 1.0 ROW02 2.0 +* +* Mark COL03 and COL04 as integer variables. +* + INT1 'MARKER' 'INTORG' + COL03 ROW02 1.1 ROW03 1.0 + COL03 ROW06 15.0 + COL04 ROW01 -2.0 ROW04 2.8 + COL04 ROW06 12.0 + INT1END 'MARKER' 'INTEND' +* + COL05 OBJ 2.0 + COL05 ROW01 -1.0 ROW05 1.0 + COL05 ROW06 1.0 + COL06 ROW03 1.0 + COL07 ROW04 -1.2 + COL08 OBJ -1.0 + COL08 ROW01 -1.0 ROW05 1.9 +RHS + RHS1 ROW01 2.5 + RHS1 ROW02 2.1 + RHS1 ROW03 4.0 + RHS1 ROW04 1.8 + RHS1 ROW05 15.0 + RHS1 ROW06 6.8 +RANGES + RNG1 ROW04 3.2 + RNG1 ROW05 12.0 +BOUNDS + LO BND1 COL01 2.5 + UP BND1 COL02 4.1 + LO BND1 COL05 0.5 + UP BND1 COL05 4.0 + UP BND1 COL07 2.0 + UP BND1 COL08 4.3 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.lp b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.lp new file mode 100644 index 000000000..36dd8d4dc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.lp @@ -0,0 +1,23 @@ +\ENCODING=ISO-8859-1 +\Problem name: exmip1.mps + +Minimize + OBJ: COL01 + 2 COL05 - COL08 +Subject To + ROW01: 3 COL01 + COL02 - 2 COL04 - COL05 - COL08 >= 2.5 + ROW02: 2 COL02 + 1.1 COL03 <= 2.1 + ROW03: COL03 + COL06 = 4 + ROW04: 2.8 COL04 - 1.2 COL07 - RgROW04 = 1.8 + ROW05: 5.6 COL01 + COL05 + 1.9 COL08 - RgROW05 = 15 +Bounds + COL01 >= 2.5 + 0 <= COL02 <= 4.1 + 0 <= COL03 <= 1 + 0 <= COL04 <= 1 + 0.5 <= COL05 <= 4 + 0 <= COL08 <= 4.3 + 0 <= RgROW04 <= 3.2 +-12 <= RgROW05 <= 0 +Binaries + COL03 COL04 +End diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.mps new file mode 100644 index 000000000..4f73ac511 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/exmip1.mps @@ -0,0 +1,70 @@ +************************************************************************ +* +* The data in this file represents the following problem: +* +* Minimize or maximize Z = x1 + 2x5 - x8 +* +* Subject to: +* +* 2.5 <= 3x1 + x2 - 2x4 - x5 - x8 +* 2x2 + 1.1x3 <= 2.1 +* x3 + x6 = 4.0 +* 1.8 <= 2.8x4 -1.2x7 <= 5.0 +* 3.0 <= 5.6x1 + x5 + 1.9x8 <= 15.0 +* +* where: +* +* 2.5 <= x1 +* 0 <= x2 <= 4.1 +* 0 <= x3 +* 0 <= x4 +* 0.5 <= x5 <= 4.0 +* 0 <= x6 +* 0 <= x7 +* 0 <= x8 <= 4.3 +* +* x3, x4 are 0,1 variables. +* +************************************************************************ +NAME EXAMPLE +ROWS + N OBJ + G ROW01 + L ROW02 + E ROW03 + G ROW04 + L ROW05 +COLUMNS + COL01 OBJ 1.0 + COL01 ROW01 3.0 ROW05 5.6 + COL02 ROW01 1.0 ROW02 2.0 +* +* Mark COL03 and COL04 as integer variables. +* + INT1 'MARKER' 'INTORG' + COL03 ROW02 1.1 ROW03 1.0 + COL04 ROW01 -2.0 ROW04 2.8 + INT1END 'MARKER' 'INTEND' +* + COL05 OBJ 2.0 + COL05 ROW01 -1.0 ROW05 1.0 + COL06 ROW03 1.0 + COL07 ROW04 -1.2 + COL08 OBJ -1.0 + COL08 ROW01 -1.0 ROW05 1.9 +RHS + RHS1 ROW01 2.5 + RHS1 ROW02 2.1 + RHS1 ROW03 4.0 + RHS1 ROW04 1.8 + RHS1 ROW05 15.0 +RANGES + RNG1 ROW04 3.2 + RNG1 ROW05 12.0 +BOUNDS + LO BND1 COL01 2.5 + UP BND1 COL02 4.1 + LO BND1 COL05 0.5 + UP BND1 COL05 4.0 + UP BND1 COL08 4.3 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/finnis.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/finnis.mps new file mode 100644 index 000000000..394db61df --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/finnis.mps @@ -0,0 +1,2180 @@ +NAME FINNIS (PTABLES3) +ROWS + N PRICER + G 1BALHCO + G 1BALCOK + G 1BALOIK + G 1BALOIL + G 1BALGSL + G 1BALDSL + G 1BALDSH + G 1BALDSR + G 1BALGAK + G 1BALGAS + G 1BALALC + G 1BALHYD + G 1BALURN + G 1BALUDP + G 1BALPLU + G 1BALMAG + G 1BALAGR + G 1BALAGS + G 1BALLMF + G 1BALLMS + G 2BALHCO + G 2BALCOK + G 2BALOIK + G 2BALOIL + G 2BALGSL + G 2BALDSL + G 2BALDSH + G 2BALDSR + G 2BALGAK + G 2BALGAS + G 2BALALC + G 2BALHYD + G 2BALURN + G 2BALUDP + G 2BALPLU + G 2BALMAG + G 2BALAGR + G 2BALAGS + G 2BALLMF + G 2BALLMS + G 3BALHCO + G 3BALCOK + G 3BALOIK + G 3BALOIL + G 3BALGSL + G 3BALDSL + G 3BALDSH + G 3BALDSR + G 3BALGAK + G 3BALGAS + G 3BALALC + G 3BALHYD + G 3BALURN + G 3BALUDP + G 3BALPLU + G 3BALMAG + G 3BALAGR + G 3BALAGS + G 3BALLMF + G 3BALLMS + E 1CPTEC3 + E 1CPTEP1 + E 1CPTE14 + E 1CPTE22 + E 1CPTE23 + E 1CPTE31 + E 1CPTE51 + E 1CPTS06 + E 1CPTS08 + E 1CPTS09 + E 1CPTS21 + E 1CPTS23 + E 1CPTS28 + E 2CPTEC3 + E 2CPTEP1 + E 2CPTE14 + E 2CPTE22 + E 2CPTE23 + E 2CPTE31 + E 2CPTE35 + E 2CPTE51 + E 2CPTS06 + E 2CPTS08 + E 2CPTS09 + E 2CPTS21 + E 2CPTS23 + E 2CPTS28 + E 3CPTEC3 + E 3CPTEP1 + E 3CPTE14 + E 3CPTE22 + E 3CPTE23 + E 3CPTE31 + E 3CPTE35 + E 3CPTE94 + E 3CPTE60 + E 3CPTE51 + E 3CPTS01 + E 3CPTS04 + E 3CPTS06 + E 3CPTS08 + E 3CPTS09 + E 3CPTS21 + E 3CPTS23 + E 3CPTS28 + E 3CPTS29 + E 3CPTS80 + L 1CPTIJ6 + L 1CPTIJ7 + L 1CPTIJ8 + L 1CPTR20 + L 1CPTR21 + L 1CPTR23 + L 1CPTR27 + L 1CPTR28 + L 1CPTR2D + L 1CPTR2L + L 1CPTRT0 + L 1CPTRT1 + L 1CPTRT3 + L 1CPTRT7 + L 1CPTRT8 + L 1CPTR50 + L 1CPTR51 + L 1CPTR53 + L 1CPTR57 + L 1CPTR58 + L 1CPTR5H + L 1CPTR5L + L 1CPTR5M + L 2CPTIJ6 + L 2CPTIJ7 + L 2CPTIJ8 + L 2CPTR20 + L 2CPTR21 + L 2CPTR23 + L 2CPTR27 + L 2CPTR28 + L 2CPTR2A + L 2CPTR2B + L 2CPTR2C + L 2CPTR2D + L 2CPTR2L + L 2CPTRT0 + L 2CPTRT1 + L 2CPTRT3 + L 2CPTRT7 + L 2CPTRT8 + L 2CPTRTB + L 2CPTRTC + L 2CPTR50 + L 2CPTR51 + L 2CPTR53 + L 2CPTR57 + L 2CPTR58 + L 2CPTR5A + L 2CPTR5H + L 2CPTR5L + L 2CPTR5M + L 3CPTIJ6 + L 3CPTIJ7 + L 3CPTIJ8 + L 3CPTR20 + L 3CPTR21 + L 3CPTR23 + L 3CPTR27 + L 3CPTR28 + L 3CPTR2A + L 3CPTR2B + L 3CPTR2C + L 3CPTR2D + L 3CPTR2L + L 3CPTRT0 + L 3CPTRT1 + L 3CPTRT3 + L 3CPTRT7 + L 3CPTRT8 + L 3CPTRTB + L 3CPTRTC + L 3CPTR50 + L 3CPTR51 + L 3CPTR53 + L 3CPTR57 + L 3CPTR58 + L 3CPTR5A + L 3CPTR5C + L 3CPTR5H + L 3CPTR5L + L 3CPTR5M + L 3GRCE35 + L 2GRCT80 + L 3GRCT80 + G 1DEMI1 + G 1DEMII + G 1DEMIJ + G 1DEMNY + G 1DEMR2 + G 1DEMRT + G 1DEMR5 + G 1DEMRD + G 1DEMT8 + G 1DEMTX + G 2DEMI1 + G 2DEMII + G 2DEMIJ + G 2DEMNY + G 2DEMR2 + G 2DEMRT + G 2DEMR5 + G 2DEMRD + G 2DEMT8 + G 2DEMTX + G 3DEMI1 + G 3DEMII + G 3DEMIJ + G 3DEMNY + G 3DEMR2 + G 3DEMRT + G 3DEMR5 + G 3DEMRD + G 3DEMT8 + G 3DEMTX + L 1UTLS06 + L 1UTLS08 + L 1UTLS09 + L 1UTLS21 + L 1UTLS23 + L 1UTLS28 + L 2UTLS06 + L 2UTLS08 + L 2UTLS09 + L 2UTLS21 + L 2UTLS23 + L 2UTLS28 + L 3UTLS01 + L 3UTLS04 + L 3UTLS06 + L 3UTLS08 + L 3UTLS09 + L 3UTLS21 + L 3UTLS23 + L 3UTLS28 + L 3UTLS29 + L 3UTLS80 + G 1UTLEC1 + G 1UTLEC2 + G 1UTLEP1 + G 1UTLE22 + G 1UTLE23 + G 2UTLEC1 + G 2UTLEC2 + G 2UTLEP1 + G 2UTLE22 + G 2UTLE23 + G 3UTLEC1 + G 3UTLEC2 + G 3UTLEP1 + G 3UTLE22 + G 3UTLE23 + G 1BNDEP1L + G 2BNDEP1L + G 1BALEWD + G 1BALEWN + G 1BALEID + G 1BALEIN + G 1BALESD + G 1BALESN + G 2BALEWD + G 2BALEWN + G 2BALEID + G 2BALEIN + G 2BALESD + G 2BALESN + G 3BALEWD + G 3BALEWN + G 3BALEID + G 3BALEIN + G 3BALESD + G 3BALESN + G 1EPKWD + G 1EPKSD + G 2EPKWD + G 2EPKSD + G 3EPKWD + G 3EPKSD + L 1EWDEC1 + L 1EWDEC2 + L 1EWDEC3 + L 1EWDEP1 + L 1EWDE14 + L 1EWDE22 + L 1EWDE23 + L 1EWDE31 + L 1EWDE51 + L 1EIDEC1 + L 1EIDEC2 + L 1EIDEC3 + L 1EIDEP1 + L 1EIDE14 + L 1EIDE22 + L 1EIDE23 + L 1EIDE31 + L 1EIDE51 + L 1ESDEC1 + L 1ESDEC2 + L 1ESDEC3 + L 1ESDEP1 + L 1ESDE14 + L 1ESDE22 + L 1ESDE23 + L 1ESDE31 + L 1ESDE51 + L 2EWDEC1 + L 2EWDEC2 + L 2EWDEC3 + L 2EWDEP1 + L 2EWDE14 + L 2EWDE22 + L 2EWDE23 + L 2EWDE31 + L 2EWDE35 + L 2EWDE51 + L 2EIDEC1 + L 2EIDEC2 + L 2EIDEC3 + L 2EIDEP1 + L 2EIDE14 + L 2EIDE22 + L 2EIDE23 + L 2EIDE31 + L 2EIDE35 + L 2EIDE51 + L 2ESDEC1 + L 2ESDEC2 + L 2ESDEC3 + L 2ESDEP1 + L 2ESDE14 + L 2ESDE22 + L 2ESDE23 + L 2ESDE31 + L 2ESDE35 + L 2ESDE51 + L 3EWDEC1 + L 3EWDEC2 + L 3EWDEC3 + L 3EWDEP1 + L 3EWDE14 + L 3EWDE22 + L 3EWDE23 + L 3EWDE31 + L 3EWDE35 + L 3EWDE94 + L 3EWDE60 + L 3EWDE51 + L 3EIDEC1 + L 3EIDEC2 + L 3EIDEC3 + L 3EIDEP1 + L 3EIDE14 + L 3EIDE22 + L 3EIDE23 + L 3EIDE31 + L 3EIDE35 + L 3EIDE94 + L 3EIDE60 + L 3EIDE51 + L 3ESDEC1 + L 3ESDEC2 + L 3ESDEC3 + L 3ESDEP1 + L 3ESDE14 + L 3ESDE22 + L 3ESDE23 + L 3ESDE31 + L 3ESDE35 + L 3ESDE94 + L 3ESDE60 + L 3ESDE51 + L 1EWNEC1 + L 1EWNEC2 + L 1EWNEC3 + L 1EWNEP1 + L 1EWNE14 + L 1EWNE31 + L 1EINEC1 + L 1EINEC2 + L 1EINEC3 + L 1EINEP1 + L 1EINE14 + L 1EINE31 + L 1ESNEC1 + L 1ESNEC2 + L 1ESNEC3 + L 1ESNEP1 + L 1ESNE14 + L 1ESNE31 + L 2EWNEC1 + L 2EWNEC2 + L 2EWNEC3 + L 2EWNEP1 + L 2EWNE14 + L 2EWNE31 + L 2EWNE35 + L 2EINEC1 + L 2EINEC2 + L 2EINEC3 + L 2EINEP1 + L 2EINE14 + L 2EINE31 + L 2EINE35 + L 2ESNEC1 + L 2ESNEC2 + L 2ESNEC3 + L 2ESNEP1 + L 2ESNE14 + L 2ESNE31 + L 2ESNE35 + L 3EWNEC1 + L 3EWNEC2 + L 3EWNEC3 + L 3EWNEP1 + L 3EWNE14 + L 3EWNE31 + L 3EWNE35 + L 3EWNE94 + L 3EWNE60 + L 3EINEC1 + L 3EINEC2 + L 3EINEC3 + L 3EINEP1 + L 3EINE14 + L 3EINE31 + L 3EINE35 + L 3EINE94 + L 3EINE60 + L 3ESNEC1 + L 3ESNEC2 + L 3ESNEC3 + L 3ESNEP1 + L 3ESNE14 + L 3ESNE31 + L 3ESNE35 + L 3ESNE94 + L 3ESNE60 + L 1BASW + L 1BASI + L 1BASS + L 2BASW + L 2BASI + L 2BASS + L 3BASW + L 3BASI + L 3BASS + G 2BALDHW + G 2BALDHI + G 2BALDHS + G 3BALDHW + G 3BALDHI + G 3BALDHS + G 2HPKW + G 3HPKW + G 1RAT001 + G 2RAT001 + G 3RAT001 + G 1RAT002 + G 2RAT002 + G 3RAT002 + G 1RAT003 + G 2RAT003 + G 3RAT003 + L 1RAT004 + L 2RAT004 + L 3RAT004 + L 1RAT005 + L 2RAT005 + L 3RAT005 + L 1RAT006 + L 2RAT006 + L 3RAT006 + L 1RAT007 + L 2RAT007 + L 3RAT007 + L 2RAT008 + L 3RAT008 + L 2RAT009 + L 3RAT009 + L 1RAT010 + L 2RAT010 + L 3RAT010 + L 1RAT011 + L 2RAT011 + L 3RAT011 + L 2RAT012 + L 3RAT012 + L 1RAT013 + L 2RAT013 + L 3RAT013 +COLUMNS + 1MINHCO1 PRICER 10.330608 1BALHCO 1. + 1MINHCO1 1BALEWD -.000659 1BALEWN -.000659 + 1MINHCO1 1BALEID -.000857 1BALEIN -.000461 + 1MINHCO1 1BALESD -.002834 1BALESN -.00112 + 1MINHCO1 1EPKWD -.00659 1EPKSD -.00659 + 2MINHCO1 PRICER 9.170958 2BALHCO 1. + 2MINHCO1 2BALEWD -.000659 2BALEWN -.000659 + 2MINHCO1 2BALEID -.000857 2BALEIN -.000461 + 2MINHCO1 2BALESD -.002834 2BALESN -.00112 + 2MINHCO1 2EPKWD -.00659 2EPKSD -.00659 + 3MINHCO1 PRICER 7.93182 3BALHCO 1. + 3MINHCO1 3BALEWD -.000659 3BALEWN -.000659 + 3MINHCO1 3BALEID -.000857 3BALEIN -.000461 + 3MINHCO1 3BALESD -.002834 3BALESN -.00112 + 3MINHCO1 3EPKWD -.00659 3EPKSD -.00659 + 1IMPHCO1 PRICER 16.167389 1BALHCO 1. + 2IMPHCO1 PRICER 13.355014 2BALHCO 1. + 3IMPHCO1 PRICER 10.93149 3BALHCO 1. + 1EXPHCO1 PRICER -16.167389 1BALHCO -1. + 2EXPHCO1 PRICER -13.355014 2BALHCO -1. + 3EXPHCO1 PRICER -10.93149 3BALHCO -1. + 1IMPOIL1 PRICER 27.995941 1BALOIL 1. + 2IMPOIL1 PRICER 22.001038 2BALOIL 1. + 3IMPOIL1 PRICER 17.248093 3BALOIL 1. + 1EXPOIL1 PRICER -27.995941 1BALOIL -1. + 2EXPOIL1 PRICER -22.001038 2BALOIL -1. + 3EXPOIL1 PRICER -17.248093 3BALOIL -1. + 1STKOIK1 1BALOIK 1. 1RAT011 -1. + 2STKOIK1 2BALOIK 1. 1BALOIK -1. + 2STKOIK1 2RAT011 -1. + 3STKOIK1 3BALOIK 1. 2BALOIK -1. + 3STKOIK1 3RAT011 -1. + ZSTKOIK1 3BALOIK -1. + 1EXPDSH1 1BALDSH -1. + 2EXPDSH1 2BALDSH -1. + 3EXPDSH1 3BALDSH -1. + 1EXPDSL1 1BALDSL -1. + 2EXPDSL1 2BALDSL -1. + 3EXPDSL1 3BALDSL -1. + 1IMPGAS1 PRICER 19.886414 1BALGAS .95 + 2IMPGAS1 PRICER 18.295593 2BALGAS .95 + 3IMPGAS1 PRICER 16.238586 3BALGAS .95 + 1EXPGAS1 PRICER -19.886414 1BALGAS -1. + 2EXPGAS1 PRICER -18.295593 2BALGAS -1. + 3EXPGAS1 PRICER -16.238586 3BALGAS -1. + 1STKGAK1 1BALGAK 1. 1RAT010 -1. + 2STKGAK1 2BALGAK 1. 1BALGAK -1. + 2STKGAK1 2RAT010 -1. + 3STKGAK1 3BALGAK 1. 2BALGAK -1. + 3STKGAK1 3RAT010 -1. + ZSTKGAK1 3BALGAK -1. + 1IMPURN1 PRICER .537191 1BALURN 1. + 2IMPURN1 PRICER .401422 2BALURN 1. + 3IMPURN1 PRICER .299967 3BALURN 1. + 1STKURN1 1BALURN 1. + 2STKURN1 2BALURN 1. 1BALURN -1. + 3STKURN1 3BALURN 1. 2BALURN -1. + ZSTKURN1 3BALURN -1. + 1STKUDP1 1BALUDP 1. + 2STKUDP1 2BALUDP 1. 1BALUDP -1. + 3STKUDP1 3BALUDP 1. 2BALUDP -1. + ZSTKUDP1 3BALUDP -1. + 1STKPLU1 1BALPLU 1. + 2STKPLU1 2BALPLU 1. 1BALPLU -1. + 3STKPLU1 3BALPLU 1. 2BALPLU -1. + ZSTKPLU1 3BALPLU -1. + 1STKAGS1 1BALAGS 1. + 2STKAGS1 2BALAGS 1. 1BALAGS -1. + 3STKAGS1 3BALAGS 1. 2BALAGS -1. + ZSTKAGS1 3BALAGS -1. + 1STKLMS1 1BALLMS 1. + 2STKLMS1 2BALLMS 1. 1BALLMS -1. + 3STKLMS1 3BALLMS 1. 2BALLMS -1. + ZSTKLMS1 3BALLMS -1. + 1EC3INV PRICER 2240.95752 1CPTEC3 -1. + 1EC3INV 2CPTEC3 -1. 3CPTEC3 -1. + 2EC3INV PRICER 1269.021484 2CPTEC3 -1. + 2EC3INV 3CPTEC3 -1. + 3EC3INV PRICER 542.729248 3CPTEC3 -1. + 1EP1INV PRICER 2188.71875 1CPTEP1 -1. + 1EP1INV 2CPTEP1 -1. 3CPTEP1 -1. + 2EP1INV PRICER 1239.439453 2CPTEP1 -1. + 2EP1INV 3CPTEP1 -1. + 3EP1INV PRICER 530.077637 3CPTEP1 -1. + 1E14INV PRICER 1783.052734 1CPTE14 -1. + 1E14INV 2CPTE14 -1. 3CPTE14 -1. + 2E14INV PRICER 1009.716797 2CPTE14 -1. + 2E14INV 3CPTE14 -1. + 3E14INV PRICER 431.830811 3CPTE14 -1. + 1E22INV PRICER 1260.778809 1CPTE22 -1. + 1E22INV 2CPTE22 -1. 3CPTE22 -1. + 2E22INV PRICER 713.960449 2CPTE22 -1. + 2E22INV 3CPTE22 -1. + 3E22INV PRICER 305.343506 3CPTE22 -1. + 1E23INV PRICER 4029.3042 1CPTE23 -1. + 1E23INV 2CPTE23 -1. 3CPTE23 -1. + 2E23INV PRICER 2281.73584 1BALAGR -11.662 + 2E23INV 2CPTE23 -1. 3CPTE23 -1. + 3E23INV PRICER 975.842285 2BALAGR -11.662 + 3E23INV 3CPTE23 -1. + 1E31INV PRICER .00001 1CPTE31 -1. + 1E31INV 2CPTE31 -1. 3CPTE31 -1. + 2E31INV PRICER .00001 2CPTE31 -1. + 2E31INV 3CPTE31 -1. + 3E31INV PRICER .00001 3CPTE31 -1. + 2E35INV PRICER .00001 2CPTE35 -1. + 2E35INV 3CPTE35 -1. + 3E35INV PRICER .00001 3CPTE35 -1. + 3E94INV PRICER 369.621338 3CPTE94 -1. + 3E60INV PRICER 721.590332 3CPTE60 -1. + 1E51INV PRICER 814.03125 1CPTE51 -1. + 1E51INV 2CPTE51 -1. 3CPTE51 -1. + 2E51INV PRICER 460.973877 2CPTE51 -1. + 2E51INV 3CPTE51 -1. + 3E51INV PRICER 197.147232 3CPTE51 -1. + 3S01INV PRICER 2.182532 3CPTS01 -1. + 3S04INV PRICER 2.932184 3CPTS04 -1. + 1S06INV 1CPTS06 -1. 2CPTS06 -1. + 1S06INV 3CPTS06 -1. + 2S06INV 2CPTS06 -1. 3CPTS06 -1. + 3S06INV 3CPTS06 -1. + 1S08INV PRICER 2.611933 1CPTS08 -1. + 1S08INV 2CPTS08 -1. 3CPTS08 -1. + 2S08INV PRICER 1.4791 2CPTS08 -1. + 2S08INV 3CPTS08 -1. + 3S08INV PRICER .632575 3CPTS08 -1. + 1S09INV PRICER 6.203342 1CPTS09 -1. + 1S09INV 2CPTS09 -1. 3CPTS09 -1. + 2S09INV PRICER 3.512862 2CPTS09 -1. + 2S09INV 3CPTS09 -1. + 3S09INV PRICER 1.502365 3CPTS09 -1. + 1S21INV PRICER 5.800726 1CPTS21 -1. + 1S21INV 2CPTS21 -1. 3CPTS21 -1. + 2S21INV PRICER 3.284866 2CPTS21 -1. + 2S21INV 3CPTS21 -1. + 3S21INV PRICER 1.404856 3CPTS21 -1. + 1S23INV PRICER 5.273388 1CPTS23 -1. + 1S23INV 2CPTS23 -1. 3CPTS23 -1. + 2S23INV PRICER 2.986242 2CPTS23 -1. + 2S23INV 3CPTS23 -1. + 3S23INV PRICER 1.277142 3CPTS23 -1. + 1S28INV PRICER 2.109354 1CPTS28 -1. + 1S28INV 2CPTS28 -1. 3CPTS28 -1. + 2S28INV PRICER 1.194496 2CPTS28 -1. + 2S28INV 3CPTS28 -1. + 3S28INV PRICER .510857 3CPTS28 -1. + 3S29INV PRICER 1.532571 3CPTS29 -1. + 3S80INV PRICER 1.870049 3CPTS80 -1. + 1IJ6INV PRICER 1.43445 1CPTIJ6 -1. + 1IJ6INV 2CPTIJ6 -1. 3CPTIJ6 -1. + 2IJ6INV PRICER .812309 2CPTIJ6 -1. + 2IJ6INV 3CPTIJ6 -1. + 3IJ6INV PRICER .347404 3CPTIJ6 -1. + 1IJ7INV PRICER 1.43445 1CPTIJ7 -1. + 1IJ7INV 2CPTIJ7 -1. 3CPTIJ7 -1. + 2IJ7INV PRICER .812309 2CPTIJ7 -1. + 2IJ7INV 3CPTIJ7 -1. + 3IJ7INV PRICER .347404 3CPTIJ7 -1. + 1IJ8INV PRICER 4.944228 1CPTIJ8 -1. + 1IJ8INV 2CPTIJ8 -1. 3CPTIJ8 -1. + 2IJ8INV PRICER 2.799844 2CPTIJ8 -1. + 2IJ8INV 3CPTIJ8 -1. + 3IJ8INV PRICER 1.197424 3CPTIJ8 -1. + 1R20INV PRICER 19.863083 1CPTR20 -1. + 1R20INV 2CPTR20 -1. 3CPTR20 -1. + 2R20INV PRICER 11.248174 2CPTR20 -1. + 2R20INV 3CPTR20 -1. + 3R20INV PRICER 4.810567 3CPTR20 -1. + 1R21INV PRICER 11.053495 1CPTR21 -1. + 1R21INV 2CPTR21 -1. 3CPTR21 -1. + 2R21INV PRICER 6.259433 2CPTR21 -1. + 2R21INV 3CPTR21 -1. + 3R21INV PRICER 2.677005 3CPTR21 -1. + 1R23INV PRICER 53.349091 1CPTR23 -1. + 1R23INV 2CPTR23 -1. 3CPTR23 -1. + 2R23INV PRICER 30.210815 2CPTR23 -1. + 2R23INV 3CPTR23 -1. + 3R23INV PRICER 12.920424 3CPTR23 -1. + 1R27INV PRICER 39.374603 1CPTR27 -1. + 1R27INV 2CPTR27 -1. 3CPTR27 -1. + 2R27INV PRICER 22.297272 2CPTR27 -1. + 2R27INV 3CPTR27 -1. + 3R27INV PRICER 9.536002 3CPTR27 -1. + 1R28INV PRICER 54.491653 1CPTR28 -1. + 1R28INV 2CPTR28 -1. 3CPTR28 -1. + 2R28INV PRICER 30.857819 2CPTR28 -1. + 2R28INV 3CPTR28 -1. + 3R28INV PRICER 13.197139 3CPTR28 -1. + 2R2AINV PRICER .00001 2CPTR2A -1. + 2R2AINV 3CPTR2A -1. + 3R2AINV PRICER .00001 3CPTR2A -1. + 2R2BINV PRICER .00001 2CPTR2B -1. + 2R2BINV 3CPTR2B -1. + 3R2BINV PRICER .00001 3CPTR2B -1. + 2R2CINV PRICER 20.4711 2CPTR2C -1. + 2R2CINV 3CPTR2C -1. + 3R2CINV PRICER 8.755 3CPTR2C -1. + 1R2DINV PRICER .00001 1CPTR2D -1. + 1R2DINV 2CPTR2D -1. 3CPTR2D -1. + 2R2DINV PRICER .00001 2CPTR2D -1. + 2R2DINV 3CPTR2D -1. + 3R2DINV PRICER .00001 3CPTR2D -1. + 1R2LINV PRICER 55.615082 1CPTR2L -1. + 1R2LINV 2CPTR2L -1. 3CPTR2L -1. + 2R2LINV PRICER 31.494003 2CPTR2L -1. + 2R2LINV 3CPTR2L -1. + 3R2LINV PRICER 13.469211 3CPTR2L -1. + 1RT0INV PRICER 19.863083 1CPTRT0 -1. + 1RT0INV 2CPTRT0 -1. 3CPTRT0 -1. + 2RT0INV PRICER 11.248174 2CPTRT0 -1. + 2RT0INV 3CPTRT0 -1. + 3RT0INV PRICER 4.810567 3CPTRT0 -1. + 1RT1INV PRICER 11.053495 1CPTRT1 -1. + 1RT1INV 2CPTRT1 -1. 3CPTRT1 -1. + 2RT1INV PRICER 6.259433 2CPTRT1 -1. + 2RT1INV 3CPTRT1 -1. + 3RT1INV PRICER 2.677005 3CPTRT1 -1. + 1RT3INV PRICER 53.349091 1CPTRT3 -1. + 1RT3INV 2CPTRT3 -1. 3CPTRT3 -1. + 2RT3INV PRICER 30.210815 2CPTRT3 -1. + 2RT3INV 3CPTRT3 -1. + 3RT3INV PRICER 12.920424 3CPTRT3 -1. + 1RT7INV PRICER 39.374603 1CPTRT7 -1. + 1RT7INV 2CPTRT7 -1. 3CPTRT7 -1. + 2RT7INV PRICER 22.297272 2CPTRT7 -1. + 2RT7INV 3CPTRT7 -1. + 3RT7INV PRICER 9.536002 3CPTRT7 -1. + 1RT8INV PRICER 54.491653 1CPTRT8 -1. + 1RT8INV 2CPTRT8 -1. 3CPTRT8 -1. + 2RT8INV PRICER 30.857819 2CPTRT8 -1. + 2RT8INV 3CPTRT8 -1. + 3RT8INV PRICER 13.197139 3CPTRT8 -1. + 2RTBINV PRICER .00001 2CPTRTB -1. + 2RTBINV 3CPTRTB -1. + 3RTBINV PRICER .00001 3CPTRTB -1. + 2RTCINV PRICER 20.4711 2CPTRTC -1. + 2RTCINV 3CPTRTC -1. + 3RTCINV PRICER 8.755 3CPTRTC -1. + 1R50INV PRICER 17.226379 1CPTR50 -1. + 1R50INV 2CPTR50 -1. 3CPTR50 -1. + 2R50INV PRICER 9.755052 2CPTR50 -1. + 2R50INV 3CPTR50 -1. + 3R50INV PRICER 4.172 3CPTR50 -1. + 1R51INV PRICER 8.560434 1CPTR51 -1. + 1R51INV 2CPTR51 -1. 3CPTR51 -1. + 2R51INV PRICER 4.847649 2CPTR51 -1. + 2R51INV 3CPTR51 -1. + 3R51INV PRICER 2.073219 3CPTR51 -1. + 1R53INV PRICER 53.349091 1CPTR53 -1. + 1R53INV 2CPTR53 -1. 3CPTR53 -1. + 2R53INV PRICER 30.210815 2CPTR53 -1. + 2R53INV 3CPTR53 -1. + 3R53INV PRICER 12.920424 3CPTR53 -1. + 1R57INV PRICER 39.374603 1CPTR57 -1. + 1R57INV 2CPTR57 -1. 3CPTR57 -1. + 2R57INV PRICER 22.297272 2CPTR57 -1. + 2R57INV 3CPTR57 -1. + 3R57INV PRICER 9.536002 3CPTR57 -1. + 1R58INV PRICER 54.491653 1CPTR58 -1. + 1R58INV 2CPTR58 -1. 3CPTR58 -1. + 2R58INV PRICER 30.857819 2CPTR58 -1. + 2R58INV 3CPTR58 -1. + 3R58INV PRICER 13.197139 3CPTR58 -1. + 2R5AINV PRICER .00001 2CPTR5A -1. + 2R5AINV 3CPTR5A -1. + 3R5AINV PRICER .00001 3CPTR5A -1. + 3R5CINV PRICER 8.755 3CPTR5C -1. + 1R5HINV PRICER 101.799759 1CPTR5H -1. + 1R5HINV 2CPTR5H -1. 3CPTR5H -1. + 2R5HINV PRICER 57.647705 2CPTR5H -1. + 2R5HINV 3CPTR5H -1. + 3R5HINV PRICER 24.654495 3CPTR5H -1. + 1R5LINV PRICER 17.120865 1CPTR5L -1. + 1R5LINV 2CPTR5L -1. 3CPTR5L -1. + 2R5LINV PRICER 9.695297 2CPTR5L -1. + 2R5LINV 3CPTR5L -1. + 3R5LINV PRICER 4.146439 3CPTR5L -1. + 1R5MINV PRICER 17.120865 1CPTR5M -1. + 1R5MINV 2CPTR5M -1. 3CPTR5M -1. + 2R5MINV PRICER 9.695297 2CPTR5M -1. + 2R5MINV 3CPTR5M -1. + 3R5MINV PRICER 4.146439 3CPTR5M -1. + 1I1YCAP 1BALHCO -.0135 1BALCOK -.4268 + 1I1YCAP 1BALDSL -.0323 1BALDSH -.1983 + 1I1YCAP 1BALGAS -.2186 1DEMI1 1. + 1I1YCAP 1BALEWD -.014242 1BALEWN -.01104 + 1I1YCAP 1BALEID -.016781 1BALEIN -.006182 + 1I1YCAP 1BALESD -.048907 1BALESN -.013248 + 1I1YCAP 1EPKWD -.142416 1EPKSD -.113738 + 2I1YCAP 2BALHCO -.0165 2BALCOK -.5198 + 2I1YCAP 2BALDSL -.0212 2BALDSH -.1305 + 2I1YCAP 2BALGAS -.1977 2DEMI1 1. + 2I1YCAP 2BALEWD -.014758 2BALEWN -.01144 + 2I1YCAP 2BALEID -.017389 2BALEIN -.006406 + 2I1YCAP 2BALESD -.050679 2BALESN -.013728 + 2I1YCAP 2EPKWD -.147576 2EPKSD -.117859 + 3I1YCAP 3BALHCO -.0194 3BALCOK -.6166 + 3I1YCAP 3BALDSL -.0102 3BALDSH -.0628 + 3I1YCAP 3BALGAS -.1777 3DEMI1 1. + 3I1YCAP 3BALEWD -.015261 3BALEWN -.01183 + 3I1YCAP 3BALEID -.017982 3BALEIN -.006625 + 3I1YCAP 3BALESD -.052407 3BALESN -.014196 + 3I1YCAP 3EPKWD -.152607 3EPKSD -.121876 + 1IIYCAP 1BALHCO -.1313 1BALCOK -.027 + 1IIYCAP 1BALDSL -.2811 1BALGAS -.2555 + 1IIYCAP 1DEMII 1. 1BALEWD -.039358 + 1IIYCAP 1BALEWN -.03051 1BALEID -.046375 + 1IIYCAP 1BALEIN -.017086 1BALESD -.135159 + 1IIYCAP 1BALESN -.036612 1EPKWD -.393579 + 1IIYCAP 1EPKSD -.314324 + 2IIYCAP 2BALHCO -.1549 2BALCOK -.0318 + 2IIYCAP 2BALDSL -.2619 2BALGAS -.2453 + 2IIYCAP 2DEMII 1. 2BALEWD -.039487 + 2IIYCAP 2BALEWN -.03061 2BALEID -.046527 + 2IIYCAP 2BALEIN -.017142 2BALESD -.135602 + 2IIYCAP 2BALESN -.036732 2EPKWD -.394869 + 2IIYCAP 2EPKSD -.315354 + 3IIYCAP 3BALHCO -.1852 3BALCOK -.038 + 3IIYCAP 3BALDSL -.2695 3BALGAS -.2048 + 3IIYCAP 3DEMII 1. 3BALEWD -.03901 + 3IIYCAP 3BALEWN -.03024 3BALEID -.045965 + 3IIYCAP 3BALEIN -.016934 3BALESD -.133963 + 3IIYCAP 3BALESN -.036288 3EPKWD -.390096 + 3IIYCAP 3EPKSD -.311542 + 1IJ6CAP PRICER 15.909122 1BALDSH -1.818181 + 1IJ6CAP 1CPTIJ6 1. 1DEMIJ 1. + 2IJ6CAP PRICER 11.88827 2BALDSH -1.818181 + 2IJ6CAP 2CPTIJ6 1. 2DEMIJ 1. + 3IJ6CAP PRICER 8.88363 3BALDSH -1.818181 + 3IJ6CAP 3CPTIJ6 1. 3DEMIJ 1. + 1IJ7CAP PRICER 39.002 1BALGAS -1.538461 + 1IJ7CAP 1CPTIJ7 1. 1DEMIJ 1. + 2IJ7CAP PRICER 29.144684 2BALGAS -1.538461 + 2IJ7CAP 2CPTIJ7 1. 2DEMIJ 1. + 3IJ7CAP PRICER 21.778656 3BALGAS -1.538461 + 3IJ7CAP 3CPTIJ7 1. 3DEMIJ 1. + 1IJ8CAP PRICER 11.053747 1BALHCO -2. + 1IJ8CAP 1CPTIJ8 1. 1DEMIJ 1. + 2IJ8CAP PRICER 8.260037 2BALHCO -2. + 2IJ8CAP 2CPTIJ8 1. 2DEMIJ 1. + 3IJ8CAP PRICER 6.172396 3BALHCO -2. + 3IJ8CAP 3CPTIJ8 1. 3DEMIJ 1. + 1NYYCAP 1BALGSL -.2795 1BALDSH -.4192 + 1NYYCAP 1BALGAS -.3013 1DEMNY 1. + 2NYYCAP 2BALGSL -.285 2BALDSH -.4275 + 2NYYCAP 2BALGAS -.2875 2DEMNY 1. + 3NYYCAP 3BALGSL -.2915 3BALDSH -.4373 + 3NYYCAP 3BALGAS -.2712 3DEMNY 1. + 1R20CAP PRICER 7.231423 1CPTR20 1. + 1R20CAP 1DEMR2 1. 1BALEWN -.482222 + 1R20CAP 1BALEIN -.345555 1BALESN -.283333 + 2R20CAP PRICER 5.403763 2CPTR20 1. + 2R20CAP 2DEMR2 1. 2BALEWN -.482222 + 2R20CAP 2BALEIN -.345555 2BALESN -.283333 + 3R20CAP PRICER 4.038016 3CPTR20 1. + 3R20CAP 3DEMR2 1. 3BALEWN -.482222 + 3R20CAP 3BALEIN -.345555 3BALESN -.283333 + 1R21CAP PRICER 6.869854 1CPTR21 1. + 1R21CAP 1DEMR2 1. 1BALEWD -.385555 + 1R21CAP 1BALEWN -.096667 1BALEID -.276667 + 1R21CAP 1BALEIN -.068889 1BALESD -.226667 + 1R21CAP 1BALESN -.056667 1EPKWD -3.855558 + 1R21CAP 1EPKSD -.527132 1RAT004 .311 + 2R21CAP PRICER 5.133575 2CPTR21 1. + 2R21CAP 2DEMR2 1. 2BALEWD -.385555 + 2R21CAP 2BALEWN -.096667 2BALEID -.276667 + 2R21CAP 2BALEIN -.068889 2BALESD -.226667 + 2R21CAP 2BALESN -.056667 2EPKWD -3.855558 + 2R21CAP 2EPKSD -.527132 2RAT004 .314 + 3R21CAP PRICER 3.836116 3CPTR21 1. + 3R21CAP 3DEMR2 1. 3BALEWD -.385555 + 3R21CAP 3BALEWN -.096667 3BALEID -.276667 + 3R21CAP 3BALEIN -.068889 3BALESD -.226667 + 3R21CAP 3BALESN -.056667 3EPKWD -3.855558 + 3R21CAP 3EPKSD -.527132 3RAT004 .317 + 1R23CAP PRICER 15.416441 1BALDSL -1.538461 + 1R23CAP 1CPTR23 1. 1DEMR2 1. + 1R23CAP 1RAT005 .311 + 2R23CAP PRICER 11.520109 2BALDSL -1.538461 + 2R23CAP 2CPTR23 1. 2DEMR2 1. + 2R23CAP 2RAT005 .314 + 3R23CAP PRICER 8.608518 3BALDSL -1.538461 + 3R23CAP 3CPTR23 1. 3DEMR2 1. + 3R23CAP 3RAT005 .317 + 1R27CAP PRICER 19.469208 1BALGAS -1.538461 + 1R27CAP 1CPTR27 1. 1DEMR2 1. + 1R27CAP 1RAT006 .311 + 2R27CAP PRICER 14.548593 2BALGAS -1.538461 + 2R27CAP 2CPTR27 1. 2DEMR2 1. + 2R27CAP 2RAT006 .314 + 3R27CAP PRICER 10.871583 3BALGAS -1.538461 + 3R27CAP 3CPTR27 1. 3DEMR2 1. + 3R27CAP 3RAT006 .317 + 1R28CAP PRICER 31.92157 1BALHCO -2. + 1R28CAP 1CPTR28 1. 1DEMR2 1. + 1R28CAP 1RAT007 .311 + 2R28CAP PRICER 23.853745 2BALHCO -2. + 2R28CAP 2CPTR28 1. 2DEMR2 1. + 2R28CAP 2RAT007 .314 + 3R28CAP PRICER 17.824951 3BALHCO -2. + 3R28CAP 3CPTR28 1. 3DEMR2 1. + 3R28CAP 3RAT007 .317 + 2R2ACAP PRICER 6.947694 2CPTR2A 1. + 2R2ACAP 2DEMR2 1. 2BALEWD -.144583 + 2R2ACAP 2BALEWN -.03625 2BALEID -.10375 + 2R2ACAP 2BALEIN -.025833 2BALESD -.085 + 2R2ACAP 2BALESN -.02125 2EPKWD -1.445833 + 2R2ACAP 2EPKSD -.197674 2RAT008 .314 + 3R2ACAP PRICER 5.191734 3CPTR2A 1. + 3R2ACAP 3DEMR2 1. 3BALEWD -.144583 + 3R2ACAP 3BALEWN -.03625 3BALEID -.10375 + 3R2ACAP 3BALEIN -.025833 3BALESD -.085 + 3R2ACAP 3BALESN -.02125 3EPKWD -1.445833 + 3R2ACAP 3EPKSD -.197674 3RAT008 .317 + 2R2BCAP PRICER 11.901143 2BALGAS -.833333 + 2R2BCAP 2CPTR2B 1. 2DEMR2 1. + 2R2BCAP 2RAT009 .314 + 3R2BCAP PRICER 8.862661 3BALGAS -.826447 + 3R2BCAP 3CPTR2B 1. 3DEMR2 1. + 3R2BCAP 3RAT009 .317 + 2R2CCAP PRICER 9.263595 2CPTR2C 1. + 2R2CCAP 2DEMR2 1. 2BALDHW -.563636 + 2R2CCAP 2BALDHI -.403896 2BALDHS -.331169 + 2R2CCAP 2HPKW -2.818182 2RAT012 .314 + 3R2CCAP PRICER 6.922315 3CPTR2C 1. + 3R2CCAP 3DEMR2 1. 3BALDHW -.563636 + 3R2CCAP 3BALDHI -.403896 3BALDHS -.331169 + 3R2CCAP 3HPKW -2.818182 3RAT012 .317 + 1R2DCAP 1CPTR2D 1. 1DEMR2 1. + 1R2DCAP 1RAT002 -1.8 + 2R2DCAP 2CPTR2D 1. 2DEMR2 1. + 2R2DCAP 2RAT002 -1.8 + 3R2DCAP 3CPTR2D 1. 3DEMR2 1. + 3R2DCAP 3RAT002 -1.8 + 1R2LCAP PRICER 14.772768 1CPTR2L 1. + 1R2LCAP 1DEMR2 1. 1BALEWD -.347 + 1R2LCAP 1BALEWN -.087 1BALEID -.249 + 1R2LCAP 1BALEIN -.062 1BALESD -.204 + 1R2LCAP 1BALESN -.051 1EPKWD -3.47 + 1R2LCAP 1EPKSD -.474419 1RAT002 1. + 2R2LCAP PRICER 11.039117 2CPTR2L 1. + 2R2LCAP 2DEMR2 1. 2BALEWD -.347 + 2R2LCAP 2BALEWN -.087 2BALEID -.249 + 2R2LCAP 2BALEIN -.062 2BALESD -.204 + 2R2LCAP 2BALESN -.051 2EPKWD -3.47 + 2R2LCAP 2EPKSD -.474419 2RAT002 1. + 3R2LCAP PRICER 8.249092 3CPTR2L 1. + 3R2LCAP 3DEMR2 1. 3BALEWD -.347 + 3R2LCAP 3BALEWN -.087 3BALEID -.249 + 3R2LCAP 3BALEIN -.062 3BALESD -.204 + 3R2LCAP 3BALESN -.051 3EPKWD -3.47 + 3R2LCAP 3EPKSD -.474419 3RAT002 1. + 1R2YCAP 1BALHCO -.923936 1BALDSL -.114623 + 1R2YCAP 1BALGAS -1.068479 1DEMR2 1. + 2R2YCAP 2BALHCO -.54554 2BALDSL -.072151 + 2R2YCAP 2BALGAS -1.256371 2DEMR2 1. + 3R2YCAP 3BALHCO -.418028 3BALDSL -.058718 + 3R2YCAP 3BALGAS -1.318908 3DEMR2 1. + 1RT0CAP PRICER 7.231423 1CPTRT0 1. + 1RT0CAP 1DEMRT 1. 1BALEWN -.482222 + 1RT0CAP 1BALEIN -.345555 1BALESN -.283333 + 2RT0CAP PRICER 5.403763 2CPTRT0 1. + 2RT0CAP 2DEMRT 1. 2BALEWN -.482222 + 2RT0CAP 2BALEIN -.345555 2BALESN -.283333 + 3RT0CAP PRICER 4.038016 3CPTRT0 1. + 3RT0CAP 3DEMRT 1. 3BALEWN -.482222 + 3RT0CAP 3BALEIN -.345555 3BALESN -.283333 + 1RT1CAP PRICER 6.869854 1CPTRT1 1. + 1RT1CAP 1DEMRT 1. 1BALEWD -.385555 + 1RT1CAP 1BALEWN -.096667 1BALEID -.276667 + 1RT1CAP 1BALEIN -.068889 1BALESD -.226667 + 1RT1CAP 1BALESN -.056667 1EPKWD -3.855558 + 1RT1CAP 1EPKSD -.527132 + 2RT1CAP PRICER 5.133575 2CPTRT1 1. + 2RT1CAP 2DEMRT 1. 2BALEWD -.385555 + 2RT1CAP 2BALEWN -.096667 2BALEID -.276667 + 2RT1CAP 2BALEIN -.068889 2BALESD -.226667 + 2RT1CAP 2BALESN -.056667 2EPKWD -3.855558 + 2RT1CAP 2EPKSD -.527132 + 3RT1CAP PRICER 3.836116 3CPTRT1 1. + 3RT1CAP 3DEMRT 1. 3BALEWD -.385555 + 3RT1CAP 3BALEWN -.096667 3BALEID -.276667 + 3RT1CAP 3BALEIN -.068889 3BALESD -.226667 + 3RT1CAP 3BALESN -.056667 3EPKWD -3.855558 + 3RT1CAP 3EPKSD -.527132 + 1RT3CAP PRICER 16.528961 1BALDSL -1.818181 + 1RT3CAP 1CPTRT3 1. 1DEMRT 1. + 2RT3CAP PRICER 12.351457 2BALDSL -1.818181 + 2RT3CAP 2CPTRT3 1. 2DEMRT 1. + 3RT3CAP PRICER 9.229751 3BALDSL -1.818181 + 3RT3CAP 3CPTRT3 1. 3DEMRT 1. + 1RT7CAP PRICER 19.469208 1BALGAS -1.538461 + 1RT7CAP 1CPTRT7 1. 1DEMRT 1. + 2RT7CAP PRICER 14.548593 2BALGAS -1.538461 + 2RT7CAP 2CPTRT7 1. 2DEMRT 1. + 3RT7CAP PRICER 10.871583 3BALGAS -1.538461 + 3RT7CAP 3CPTRT7 1. 3DEMRT 1. + 1RT8CAP PRICER 31.92157 1BALHCO -2. + 1RT8CAP 1CPTRT8 1. 1DEMRT 1. + 2RT8CAP PRICER 23.853745 2BALHCO -2. + 2RT8CAP 2CPTRT8 1. 2DEMRT 1. + 3RT8CAP PRICER 17.824951 3BALHCO -2. + 3RT8CAP 3CPTRT8 1. 3DEMRT 1. + 2RTBCAP PRICER 11.901143 2BALGAS -.833333 + 2RTBCAP 2CPTRTB 1. 2DEMRT 1. + 3RTBCAP PRICER 8.893249 3BALGAS -.833333 + 3RTBCAP 3CPTRTB 1. 3DEMRT 1. + 2RTCCAP PRICER 9.263595 2CPTRTC 1. + 2RTCCAP 2DEMRT 1. 2BALDHW -.563636 + 2RTCCAP 2BALDHI -.403896 2BALDHS -.331169 + 2RTCCAP 2HPKW -2.818182 + 3RTCCAP PRICER 6.922315 3CPTRTC 1. + 3RTCCAP 3DEMRT 1. 3BALDHW -.563636 + 3RTCCAP 3BALDHI -.403896 3BALDHS -.331169 + 3RTCCAP 3HPKW -2.818182 + 1RTYCAP 1BALHCO -.634921 1BALGAS -.952381 + 1RTYCAP 1DEMRT 1. + 2RTYCAP 2BALHCO -.3125 2BALGAS -1.25 + 2RTYCAP 2DEMRT 1. + 3RTYCAP 3BALGAS -1.538461 3DEMRT 1. + 1R50CAP PRICER 1.54959 1CPTR50 1. + 1R50CAP 1DEMR5 1. 1BALEWN -.248889 + 1R50CAP 1BALEIN -.23 1BALESN -.632222 + 2R50CAP PRICER 1.157948 2CPTR50 1. + 2R50CAP 2DEMR5 1. 2BALEWN -.248889 + 2R50CAP 2BALEIN -.23 2BALESN -.632222 + 3R50CAP PRICER .865289 3CPTR50 1. + 3R50CAP 3DEMR5 1. 3BALEWN -.248889 + 3R50CAP 3BALEIN -.23 3BALESN -.632222 + 1R51CAP 1CPTR51 1. 1DEMR5 1. + 1R51CAP 1BALEWD -.176667 1BALEWN -.072222 + 1R51CAP 1BALEID -.212222 1BALEIN -.017778 + 1R51CAP 1BALESD -.604444 1BALESN -.027778 + 1R51CAP 1EPKWD -1.766667 1EPKSD -1.405684 + 1R51CAP 1RAT004 -1. + 2R51CAP 2CPTR51 1. 2DEMR5 1. + 2R51CAP 2BALEWD -.176667 2BALEWN -.072222 + 2R51CAP 2BALEID -.212222 2BALEIN -.017778 + 2R51CAP 2BALESD -.604444 2BALESN -.027778 + 2R51CAP 2EPKWD -1.766667 2EPKSD -1.405684 + 2R51CAP 2RAT004 -1. + 3R51CAP 3CPTR51 1. 3DEMR5 1. + 3R51CAP 3BALEWD -.176667 3BALEWN -.072222 + 3R51CAP 3BALEID -.212222 3BALEIN -.017778 + 3R51CAP 3BALESD -.604444 3BALESN -.027778 + 3R51CAP 3EPKWD -1.766667 3EPKSD -1.405684 + 3R51CAP 3RAT004 -1. + 1R53CAP PRICER 16.528961 1BALDSL -1.818181 + 1R53CAP 1CPTR53 1. 1DEMR5 1. + 1R53CAP 1RAT005 -1. + 2R53CAP PRICER 12.351457 2BALDSL -1.818181 + 2R53CAP 2CPTR53 1. 2DEMR5 1. + 2R53CAP 2RAT005 -1. + 3R53CAP PRICER 9.229751 3BALDSL -1.818181 + 3R53CAP 3CPTR53 1. 3DEMR5 1. + 3R53CAP 3RAT005 -1. + 1R57CAP PRICER 19.469208 1BALGAS -1.538461 + 1R57CAP 1CPTR57 1. 1DEMR5 1. + 1R57CAP 1RAT006 -1. + 2R57CAP PRICER 14.548593 2BALGAS -1.538461 + 2R57CAP 2CPTR57 1. 2DEMR5 1. + 2R57CAP 2RAT006 -1. + 3R57CAP PRICER 10.871583 3BALGAS -1.538461 + 3R57CAP 3CPTR57 1. 3DEMR5 1. + 3R57CAP 3RAT006 -1. + 1R58CAP PRICER 31.92157 1BALHCO -2. + 1R58CAP 1CPTR58 1. 1DEMR5 1. + 1R58CAP 1RAT007 -1. + 2R58CAP PRICER 23.853745 2BALHCO -2. + 2R58CAP 2CPTR58 1. 2DEMR5 1. + 2R58CAP 2RAT007 -1. + 3R58CAP PRICER 17.824951 3BALHCO -2. + 3R58CAP 3CPTR58 1. 3DEMR5 1. + 3R58CAP 3RAT007 -1. + 2R5ACAP PRICER 6.947694 2CPTR5A 1. + 2R5ACAP 2DEMR5 1. 2BALEWD -.045429 + 2R5ACAP 2BALEWN -.018571 2BALEID -.054571 + 2R5ACAP 2BALEIN -.004571 2BALESD -.155429 + 2R5ACAP 2BALESN -.007143 2EPKWD -.454286 + 2R5ACAP 2EPKSD -.361462 2RAT008 -1. + 3R5ACAP PRICER 5.191734 3CPTR5A 1. + 3R5ACAP 3DEMR5 1. 3BALEWD -.045429 + 3R5ACAP 3BALEWN -.018571 3BALEID -.054571 + 3R5ACAP 3BALEIN -.004571 3BALESD -.155429 + 3R5ACAP 3BALESN -.007143 3EPKWD -.454286 + 3R5ACAP 3EPKSD -.361462 3RAT008 -1. + 3R5CCAP PRICER 6.922315 3CPTR5C 1. + 3R5CCAP 3DEMR5 1. 3BALDHW -.329412 + 3R5CCAP 3BALDHI -.304412 3BALDHS -.836765 + 3R5CCAP 3HPKW -1.647059 3RAT012 -1. + 1R5HCAP PRICER 85.948608 1BALGAS -1.960784 + 1R5HCAP 1CPTR5H 1. 1DEMR5 1. + 1R5HCAP 1RAT001 1. 1RAT003 1. + 1R5HCAP 1RAT013 -1. + 2R5HCAP PRICER 64.001907 2BALGAS -1.923077 + 2R5HCAP 2CPTR5H 1. 2DEMR5 1. + 2R5HCAP 2RAT001 1. 2RAT003 1. + 2R5HCAP 2RAT013 -1. + 3R5HCAP PRICER 47.664902 3BALGAS -1.886792 + 3R5HCAP 3CPTR5H 1. 3DEMR5 1. + 3R5HCAP 3RAT001 1. 3RAT003 1. + 3R5HCAP 3RAT013 -1. + 1R5LCAP 1CPTR5L 1. 1DEMR5 1. + 1R5LCAP 1BALEWD -.223944 1BALEWN -.091549 + 1R5LCAP 1BALEID -.269014 1BALEIN -.022535 + 1R5LCAP 1BALESD -.766197 1BALESN -.035211 + 1R5LCAP 1EPKWD -2.239438 1EPKSD -1.781854 + 1R5LCAP 1RAT001 1. 1RAT013 -1. + 2R5LCAP 2CPTR5L 1. 2DEMR5 1. + 2R5LCAP 2BALEWD -.220833 2BALEWN -.090278 + 2R5LCAP 2BALEID -.265278 2BALEIN -.022222 + 2R5LCAP 2BALESD -.755556 2BALESN -.034722 + 2R5LCAP 2EPKWD -2.208334 2EPKSD -1.757106 + 2R5LCAP 2RAT001 1. 2RAT013 -1. + 3R5LCAP 3CPTR5L 1. 3DEMR5 1. + 3R5LCAP 3BALEWD -.217808 3BALEWN -.089041 + 3R5LCAP 3BALEID -.261644 3BALEIN -.021918 + 3R5LCAP 3BALESD -.745205 3BALESN -.034247 + 3R5LCAP 3EPKWD -2.178082 3EPKSD -1.733036 + 3R5LCAP 3RAT001 1. 3RAT013 -1. + 1R5MCAP 1CPTR5M 1. 1DEMR5 1. + 1R5MCAP 1BALEWD -.223944 1BALEWN -.091549 + 1R5MCAP 1BALEID -.269014 1BALEIN -.022535 + 1R5MCAP 1BALESD -.766197 1BALESN -.035211 + 1R5MCAP 1EPKWD -2.239438 1EPKSD -1.781854 + 1R5MCAP 1RAT003 1. 1RAT013 -1. + 2R5MCAP 2CPTR5M 1. 2DEMR5 1. + 2R5MCAP 2BALEWD -.220833 2BALEWN -.090278 + 2R5MCAP 2BALEID -.265278 2BALEIN -.022222 + 2R5MCAP 2BALESD -.755556 2BALESN -.034722 + 2R5MCAP 2EPKWD -2.208334 2EPKSD -1.757106 + 2R5MCAP 2RAT003 1. 2RAT013 -1. + 3R5MCAP 3CPTR5M 1. 3DEMR5 1. + 3R5MCAP 3BALEWD -.217808 3BALEWN -.089041 + 3R5MCAP 3BALEID -.261644 3BALEIN -.021918 + 3R5MCAP 3BALESD -.745205 3BALESN -.034247 + 3R5MCAP 3EPKWD -2.178082 3EPKSD -1.733036 + 3R5MCAP 3RAT003 1. 3RAT013 -1. + 1RDYCAP 1BALHCO -.034892 1BALCOK -.009677 + 1RDYCAP 1BALDSL -.332697 1BALGAS -.371269 + 1RDYCAP 1DEMRD 1. 1BALEWD -.148042 + 1RDYCAP 1BALEWN -.082314 1BALEID -.119785 + 1RDYCAP 1BALEIN -.033786 1BALESD -.181214 + 1RDYCAP 1BALESN -.049143 1EPKWD -1.480425 + 1RDYCAP 1EPKSD -.421427 + 2RDYCAP 2BALHCO -.030143 2BALCOK -.007975 + 2RDYCAP 2BALDSL -.282779 2BALGAS -.410787 + 2RDYCAP 2DEMRD 1. 2BALEWD -.149428 + 2RDYCAP 2BALEWN -.083084 2BALEID -.120906 + 2RDYCAP 2BALEIN -.034102 2BALESD -.182909 + 2RDYCAP 2BALESN -.049603 2EPKWD -1.494279 + 2RDYCAP 2EPKSD -.425371 + 3RDYCAP 3BALHCO -.02846 3BALCOK -.007786 + 3RDYCAP 3BALDSL -.26084 3BALGAS -.411062 + 3RDYCAP 3DEMRD 1. 3BALEWD -.152869 + 3RDYCAP 3BALEWN -.084998 3BALEID -.123691 + 3RDYCAP 3BALEIN -.034887 3BALESD -.187122 + 3RDYCAP 3BALESN -.050745 3EPKWD -1.528695 + 3RDYCAP 3EPKSD -.435168 + 1T80CAP 2GRCT80 -1.227805 1DEMT8 1. + 1T80CAP 1BALEWN -.1 1BALEIN -.1 + 1T80CAP 1BALESN -.3 + 2T80CAP 3GRCT80 -1.227805 2GRCT80 1. + 2T80CAP 2DEMT8 1. 2BALEWN -.1 + 2T80CAP 2BALEIN -.1 2BALESN -.3 + 3T80CAP 3GRCT80 1. 3DEMT8 1. + 3T80CAP 3BALEWN -.1 3BALEIN -.1 + 3T80CAP 3BALESN -.3 + 1T83CAP PRICER 5.475219 1BALDSL -1. + 1T83CAP 1DEMT8 1. + 2T83CAP PRICER 4.091419 2BALDSL -1. + 2T83CAP 2DEMT8 1. + 3T83CAP PRICER 3.057354 3BALDSL -1. + 3T83CAP 3DEMT8 1. + 1T8FCAP 1BALGSL -1. 1DEMT8 1. + 2T8FCAP 2BALGSL -1. 2DEMT8 1. + 3T8FCAP 3BALGSL -1. 3DEMT8 1. + 1TXYCAP 1BALDSL -.9792 1DEMTX 1. + 1TXYCAP 1BALEWD -.00208 1BALEWN -.00208 + 1TXYCAP 1BALEID -.002704 1BALEIN -.001456 + 1TXYCAP 1BALESD -.008944 1BALESN -.003536 + 1TXYCAP 1EPKWD -.0208 1EPKSD -.0208 + 2TXYCAP 2BALDSL -.9808 2DEMTX 1. + 2TXYCAP 2BALEWD -.00192 2BALEWN -.00192 + 2TXYCAP 2BALEID -.002496 2BALEIN -.001344 + 2TXYCAP 2BALESD -.008256 2BALESN -.003264 + 2TXYCAP 2EPKWD -.0192 2EPKSD -.0192 + 3TXYCAP 3BALDSL -.9981 3DEMTX 1. + 3TXYCAP 3BALEWD -.00189 3BALEWN -.00189 + 3TXYCAP 3BALEID -.002457 3BALEIN -.001323 + 3TXYCAP 3BALESD -.008127 3BALESN -.003213 + 3TXYCAP 3EPKWD -.0189 3EPKSD -.0189 + 3S01CAP PRICER 4.961 3CPTS01 1. + 3S01CAP 3UTLS01 -.85 + 3S04CAP PRICER 5.710909 3CPTS04 1. + 3S04CAP 3UTLS04 -.85 + 1S06CAP 1CPTS06 1. 1UTLS06 -.9 + 2S06CAP 2CPTS06 1. 2UTLS06 -.9 + 3S06CAP 3CPTS06 1. 3UTLS06 -.9 + 1S08CAP 1CPTS08 1. 1UTLS08 -.9 + 2S08CAP 2CPTS08 1. 2UTLS08 -.9 + 3S08CAP 3CPTS08 1. 3UTLS08 -.9 + 1S09CAP 1CPTS09 1. 1UTLS09 -1. + 2S09CAP 2CPTS09 1. 2UTLS09 -1. + 3S09CAP 3CPTS09 1. 3UTLS09 -1. + 1S21CAP 1CPTS21 1. 1UTLS21 -1. + 2S21CAP 2CPTS21 1. 2UTLS21 -1. + 3S21CAP 3CPTS21 1. 3UTLS21 -1. + 1S23CAP 1CPTS23 1. 1UTLS23 -1. + 2S23CAP 2CPTS23 1. 2UTLS23 -1. + 3S23CAP 3CPTS23 1. 3UTLS23 -1. + 1S28CAP 1CPTS28 1. 1UTLS28 -1. + 2S28CAP 2CPTS28 1. 2UTLS28 -1. + 3S28CAP 3CPTS28 1. 3UTLS28 -1. + 3S29CAP 3CPTS29 1. 3UTLS29 -1. + 1S44CAP 1BALURN -1.02 1BALMAG .744 + 1S44CAP 2BALMAG .256 + 2S44CAP 2BALURN -1.02 2BALMAG .744 + 2S44CAP 3BALMAG .256 + 3S44CAP 3BALURN -1.02 3BALMAG .744 + 1S45CAP PRICER 2.89257 1BALURN -4.4348 + 1S45CAP 1BALUDP 3.4348 1BALAGR .634 + 1S45CAP 2BALAGR .366 + 2S45CAP PRICER 2.161505 2BALURN -4.4348 + 2S45CAP 2BALUDP 3.4348 2BALAGR .634 + 2S45CAP 3BALAGR .366 + 3S45CAP PRICER 1.615207 3BALURN -4.4348 + 3S45CAP 3BALUDP 3.4348 3BALAGR .634 + 1S46CAP PRICER .619836 1BALURN -.9841 + 1S46CAP 1BALPLU -.01591 1BALAGR .734 + 1S46CAP 2BALAGR .266 + 2S46CAP PRICER .46318 2BALURN -.9841 + 2S46CAP 2BALPLU -.01591 2BALAGR .734 + 2S46CAP 3BALAGR .266 + 3S46CAP PRICER .346116 3BALURN -.9841 + 3S46CAP 3BALPLU -.01591 3BALAGR .734 + 1S47CAP PRICER .619836 1BALUDP -.9796 + 1S47CAP 1BALPLU -.02045 1BALAGR .734 + 1S47CAP 2BALAGR .266 + 2S47CAP PRICER .46318 2BALUDP -.9796 + 2S47CAP 2BALPLU -.02045 2BALAGR .734 + 2S47CAP 3BALAGR .266 + 3S47CAP PRICER .346116 3BALUDP -.9796 + 3S47CAP 3BALPLU -.02045 3BALAGR .734 + 1S4ACAP PRICER .619836 1BALUDP -.9476 + 1S4ACAP 1BALPLU -.05237 1BALLMF .95 + 1S4ACAP 2BALLMF .05 + 2S4ACAP PRICER .46318 2BALUDP -.9476 + 2S4ACAP 2BALPLU -.05237 2BALLMF .95 + 2S4ACAP 3BALLMF .05 + 3S4ACAP PRICER .346116 3BALUDP -.9476 + 3S4ACAP 3BALPLU -.05237 3BALLMF .95 + 1S54CAP PRICER 4.752079 1BALUDP .9282 + 1S54CAP 1BALPLU .06318 1BALLMS -1. + 2S54CAP PRICER 3.551044 2BALUDP .9282 + 2S54CAP 2BALPLU .06318 2BALLMS -.9 + 2S54CAP 1BALLMS -.1 + 3S54CAP PRICER 2.653554 3BALUDP .9282 + 3S54CAP 3BALPLU .06318 3BALLMS -.9 + 3S54CAP 2BALLMS -.1 + 1S55CAP PRICER 4.752079 1BALURN 1.047 + 1S55CAP 1BALPLU .004783 1BALAGS -1. + 2S55CAP PRICER 3.551044 2BALURN 1.047 + 2S55CAP 2BALPLU .004783 2BALAGS -.8 + 2S55CAP 1BALAGS -.2 + 3S55CAP PRICER 2.653554 3BALURN 1.047 + 3S55CAP 3BALPLU .004783 3BALAGS -.8 + 3S55CAP 2BALAGS -.2 + 1S6HCAP 1BALGAS .95 1BALHYD -1. + 2S6HCAP 2BALGAS .95 2BALHYD -1. + 3S6HCAP 3BALGAS .95 3BALHYD -1. + 1S71CAP 1BALGSL 1. 1BALALC -1. + 2S71CAP 2BALGSL 1. 2BALALC -1. + 3S71CAP 3BALGSL 1. 3BALALC -1. + 1S72CAP 1BALDSH 1. 1BALDSR -1. + 2S72CAP 2BALDSH 1. 2BALDSR -1. + 3S72CAP 3BALDSH 1. 3BALDSR -1. + 1S79CAP 1BALGAK -1. 1BALGAS .95 + 1S79CAP 1RAT010 2.66 + 2S79CAP 2BALGAK -1. 2BALGAS .95 + 2S79CAP 2RAT010 2.66 + 3S79CAP 3BALGAK -1. 3BALGAS .95 + 3S79CAP 3RAT010 2.66 + 1S7ACAP 1BALOIK -1. 1BALOIL 1. + 1S7ACAP 1RAT011 2.66 + 2S7ACAP 2BALOIK -1. 2BALOIL 1. + 2S7ACAP 2RAT011 2.66 + 3S7ACAP 3BALOIK -1. 3BALOIL 1. + 3S7ACAP 3RAT011 2.66 + 3S80CAP PRICER 1.211405 3CPTS80 1. + 3S80CAP 3UTLS80 -.9 + 3S01ACT PRICER 1.817107 3BALHCO -1. + 3S01ACT 3BALGAS .665 3UTLS01 1. + 3S04ACT PRICER 1.586364 3BALHCO -1. + 3S04ACT 3BALALC .3 3UTLS04 1. + 1S06ACT PRICER 1.497937 1BALHCO -1. + 1S06ACT 1BALCOK .6 1BALGAS .1425 + 1S06ACT 1UTLS06 1. + 2S06ACT PRICER 1.11935 2BALHCO -1. + 2S06ACT 2BALCOK .6 2BALGAS .1425 + 2S06ACT 2UTLS06 1. + 3S06ACT PRICER .836446 3BALHCO -1. + 3S06ACT 3BALCOK .6 3BALGAS .1425 + 3S06ACT 3UTLS06 1. + 1S08ACT PRICER 1.497937 1BALHCO -1. + 1S08ACT 1BALCOK .64 1BALGAS .152 + 1S08ACT 1UTLS08 1. + 2S08ACT PRICER 1.11935 2BALHCO -1. + 2S08ACT 2BALCOK .64 2BALGAS .152 + 2S08ACT 2UTLS08 1. + 3S08ACT PRICER .836446 3BALHCO -1. + 3S08ACT 3BALCOK .64 3BALGAS .152 + 3S08ACT 3UTLS08 1. + 1S09ACT PRICER 1.497937 1BALHCO -1. + 1S09ACT 1BALCOK .64 1BALGAS .152 + 1S09ACT 1UTLS09 1. + 2S09ACT PRICER 1.11935 2BALHCO -1. + 2S09ACT 2BALCOK .64 2BALGAS .152 + 2S09ACT 2UTLS09 1. + 3S09ACT PRICER .836446 3BALHCO -1. + 3S09ACT 3BALCOK .64 3BALGAS .152 + 3S09ACT 3UTLS09 1. + 1S21ACT 1BALOIL -1. 1BALGSL .16 + 1S21ACT 1BALDSL .32 1BALDSR .46 + 1S21ACT 1UTLS21 1. + 2S21ACT 2BALOIL -1. 2BALGSL .16 + 2S21ACT 2BALDSL .32 2BALDSR .46 + 2S21ACT 2UTLS21 1. + 3S21ACT 3BALOIL -1. 3BALGSL .16 + 3S21ACT 3BALDSL .32 3BALDSR .46 + 3S21ACT 3UTLS21 1. + 1S23ACT 1BALDSL .5 1BALDSH .5 + 1S23ACT 1BALDSR -1. 1UTLS23 1. + 2S23ACT 2BALDSL .5 2BALDSH .5 + 2S23ACT 2BALDSR -1. 2UTLS23 1. + 3S23ACT 3BALDSL .5 3BALDSH .5 + 3S23ACT 3BALDSR -1. 3UTLS23 1. + 1S28ACT 1BALGSL .67 1BALDSL -1. + 1S28ACT 1UTLS28 1. + 2S28ACT 2BALGSL .67 2BALDSL -1. + 2S28ACT 2UTLS28 1. + 3S28ACT 3BALGSL .67 3BALDSL -1. + 3S28ACT 3UTLS28 1. + 3S29ACT 3BALGSL .87 3BALDSL -1. + 3S29ACT 3UTLS29 1. + 3S80ACT PRICER .365152 3BALHYD .722 + 3S80ACT 3UTLS80 1. 3BALEWN -.2 + 3S80ACT 3BALEIN -.2 3BALESN -.6 + 1EC1WM 1UTLEC1 1. 1EWDEC1 .5 + 1EC1WM 1EWNEC1 .5 + 1EC1IM 1UTLEC1 1. 1EIDEC1 .65 + 1EC1IM 1EINEC1 .35 + 1EC1SM 1UTLEC1 1. 1ESDEC1 .716667 + 1EC1SM 1ESNEC1 .283333 + 2EC1WM 2UTLEC1 1. 2EWDEC1 .5 + 2EC1WM 2EWNEC1 .5 + 2EC1IM 2UTLEC1 1. 2EIDEC1 .65 + 2EC1IM 2EINEC1 .35 + 2EC1SM 2UTLEC1 1. 2ESDEC1 .716667 + 2EC1SM 2ESNEC1 .283333 + 3EC1WM 3UTLEC1 1. 3EWDEC1 .5 + 3EC1WM 3EWNEC1 .5 + 3EC1IM 3UTLEC1 1. 3EIDEC1 .65 + 3EC1IM 3EINEC1 .35 + 3EC1SM 3UTLEC1 1. 3ESDEC1 .716667 + 3EC1SM 3ESNEC1 .283333 + 1EC2WM 1UTLEC2 1. 1EWDEC2 .5 + 1EC2WM 1EWNEC2 .5 + 1EC2IM 1UTLEC2 1. 1EIDEC2 .65 + 1EC2IM 1EINEC2 .35 + 1EC2SM 1UTLEC2 1. 1ESDEC2 .716667 + 1EC2SM 1ESNEC2 .283333 + 2EC2WM 2UTLEC2 1. 2EWDEC2 .5 + 2EC2WM 2EWNEC2 .5 + 2EC2IM 2UTLEC2 1. 2EIDEC2 .65 + 2EC2IM 2EINEC2 .35 + 2EC2SM 2UTLEC2 1. 2ESDEC2 .716667 + 2EC2SM 2ESNEC2 .283333 + 3EC2WM 3UTLEC2 1. 3EWDEC2 .5 + 3EC2WM 3EWNEC2 .5 + 3EC2IM 3UTLEC2 1. 3EIDEC2 .65 + 3EC2IM 3EINEC2 .35 + 3EC2SM 3UTLEC2 1. 3ESDEC2 .716667 + 3EC2SM 3ESNEC2 .283333 + 1EP1WM 1UTLEP1 1. 1EWDEP1 .5 + 1EP1WM 1EWNEP1 .5 + 1EP1IM 1UTLEP1 1. 1EIDEP1 .65 + 1EP1IM 1EINEP1 .35 + 1EP1SM 1UTLEP1 1. 1ESDEP1 .716667 + 1EP1SM 1ESNEP1 .283333 + 2EP1WM 2UTLEP1 1. 2EWDEP1 .5 + 2EP1WM 2EWNEP1 .5 + 2EP1IM 2UTLEP1 1. 2EIDEP1 .65 + 2EP1IM 2EINEP1 .35 + 2EP1SM 2UTLEP1 1. 2ESDEP1 .716667 + 2EP1SM 2ESNEP1 .283333 + 3EP1WM 3UTLEP1 1. 3EWDEP1 .5 + 3EP1WM 3EWNEP1 .5 + 3EP1IM 3UTLEP1 1. 3EIDEP1 .65 + 3EP1IM 3EINEP1 .35 + 3EP1SM 3UTLEP1 1. 3ESDEP1 .716667 + 3EP1SM 3ESNEP1 .283333 + 1E22WM 1UTLE22 1. 1EWDE22 1. + 1E22IM 1UTLE22 1. 1EIDE22 1. + 1E22SM 1UTLE22 1. 1ESDE22 1. + 2E22WM 2UTLE22 1. 2EWDE22 1. + 2E22IM 2UTLE22 1. 2EIDE22 1. + 2E22SM 2UTLE22 1. 2ESDE22 1. + 3E22WM 3UTLE22 1. 3EWDE22 1. + 3E22IM 3UTLE22 1. 3EIDE22 1. + 3E22SM 3UTLE22 1. 3ESDE22 1. + 1E23WM 1UTLE23 1. 1EWDE23 1. + 1E23IM 1UTLE23 1. 1EIDE23 1. + 1E23SM 1UTLE23 1. 1ESDE23 1. + 2E23WM 2UTLE23 1. 2EWDE23 1. + 2E23IM 2UTLE23 1. 2EIDE23 1. + 2E23SM 2UTLE23 1. 2ESDE23 1. + 3E23WM 3UTLE23 1. 3EWDE23 1. + 3E23IM 3UTLE23 1. 3EIDE23 1. + 3E23SM 3UTLE23 1. 3ESDE23 1. + 1EC1CAP PRICER 289.256836 1UTLEC1 -4.4184 + 1EC1CAP 1EPKWD 24.213669 1EPKSD 24.213669 + 1EC1CAP 1EWDEC1 -2.714158 1EWNEC1 -2.714158 + 1EC1CAP 1EIDEC1 -3.528407 1EINEC1 -1.899911 + 1EC1CAP 1ESDEC1 -11.670885 1ESNEC1 -4.61407 + 2EC1CAP PRICER 216.150574 2UTLEC1 -4.4184 + 2EC1CAP 2EPKWD 24.213669 2EPKSD 24.213669 + 2EC1CAP 2EWDEC1 -2.714158 2EWNEC1 -2.714158 + 2EC1CAP 2EIDEC1 -3.528407 2EINEC1 -1.899911 + 2EC1CAP 2ESDEC1 -11.670885 2ESNEC1 -4.61407 + 3EC1CAP PRICER 161.520706 3UTLEC1 -4.4184 + 3EC1CAP 3EPKWD 24.213669 3EPKSD 24.213669 + 3EC1CAP 3EWDEC1 -2.714158 3EWNEC1 -2.714158 + 3EC1CAP 3EIDEC1 -3.528407 3EINEC1 -1.899911 + 3EC1CAP 3ESDEC1 -11.670885 3ESNEC1 -4.61407 + 1EC2CAP PRICER 289.256836 1UTLEC2 -5.049611 + 1EC2CAP 1EPKWD 24.213669 1EPKSD 24.213669 + 1EC2CAP 1EWDEC2 -2.777279 1EWNEC2 -2.777279 + 1EC2CAP 1EIDEC2 -3.610465 1EINEC2 -1.944096 + 1EC2CAP 1ESDEC2 -11.942307 1ESNEC2 -4.721376 + 2EC2CAP PRICER 216.150574 2UTLEC2 -5.049611 + 2EC2CAP 2EPKWD 24.213669 2EPKSD 24.213669 + 2EC2CAP 2EWDEC2 -2.777279 2EWNEC2 -2.777279 + 2EC2CAP 2EIDEC2 -3.610465 2EINEC2 -1.944096 + 2EC2CAP 2ESDEC2 -11.942307 2ESNEC2 -4.721376 + 3EC2CAP PRICER 161.520706 3UTLEC2 -5.049611 + 3EC2CAP 3EPKWD 24.213669 3EPKSD 24.213669 + 3EC2CAP 3EWDEC2 -2.777279 3EWNEC2 -2.777279 + 3EC2CAP 3EIDEC2 -3.610465 3EINEC2 -1.944096 + 3EC2CAP 3ESDEC2 -11.942307 3ESNEC2 -4.721376 + 1EC3CAP PRICER 114.669724 1CPTEC3 1. + 1EC3CAP 1EPKWD 24.213669 1EPKSD 24.213669 + 1EC3CAP 1EWDEC3 -2.114518 1EWNEC3 -2.114518 + 1EC3CAP 1EIDEC3 -2.748875 1EINEC3 -1.480163 + 1EC3CAP 1ESDEC3 -9.092433 1ESNEC3 -3.594682 + 2EC3CAP PRICER 85.688248 2CPTEC3 1. + 2EC3CAP 2EPKWD 24.213669 2EPKSD 24.213669 + 2EC3CAP 2EWDEC3 -2.114518 2EWNEC3 -2.114518 + 2EC3CAP 2EIDEC3 -2.748875 2EINEC3 -1.480163 + 2EC3CAP 2ESDEC3 -9.092433 2ESNEC3 -3.594682 + 3EC3CAP PRICER 64.031403 3CPTEC3 1. + 3EC3CAP 3EPKWD 24.213669 3EPKSD 24.213669 + 3EC3CAP 3EWDEC3 -2.114518 3EWNEC3 -2.114518 + 3EC3CAP 3EIDEC3 -2.748875 3EINEC3 -1.480163 + 3EC3CAP 3ESDEC3 -9.092433 3ESNEC3 -3.594682 + 1EP1CAP PRICER 114.669724 1CPTEP1 1. + 1EP1CAP 1UTLEP1 -4.4184 1EPKWD 24.213669 + 1EP1CAP 1EPKSD 24.213669 1EWDEP1 -2.714158 + 1EP1CAP 1EWNEP1 -2.714158 1EIDEP1 -3.528407 + 1EP1CAP 1EINEP1 -1.899911 1ESDEP1 -11.670885 + 1EP1CAP 1ESNEP1 -4.61407 + 2EP1CAP PRICER 85.688248 2CPTEP1 1. + 2EP1CAP 2UTLEP1 -4.4184 2EPKWD 24.213669 + 2EP1CAP 2EPKSD 24.213669 2EWDEP1 -2.714158 + 2EP1CAP 2EWNEP1 -2.714158 2EIDEP1 -3.528407 + 2EP1CAP 2EINEP1 -1.899911 2ESDEP1 -11.670885 + 2EP1CAP 2ESNEP1 -4.61407 + 3EP1CAP PRICER 64.031403 3CPTEP1 1. + 3EP1CAP 3UTLEP1 -4.4184 3EPKWD 24.213669 + 3EP1CAP 3EPKSD 24.213669 3EWDEP1 -2.714158 + 3EP1CAP 3EWNEP1 -2.714158 3EIDEP1 -3.528407 + 3EP1CAP 3EINEP1 -1.899911 3ESDEP1 -11.670885 + 3EP1CAP 3ESNEP1 -4.61407 + 1E14CAP PRICER 72.83078 1CPTE14 1. + 1E14CAP 1EPKWD 24.213669 1EPKSD 24.213669 + 1E14CAP 1EWDE14 -2.998198 1EWNE14 -2.998198 + 1E14CAP 1EIDE14 -3.897659 1EINE14 -2.098739 + 1E14CAP 1ESDE14 -12.892257 1ESNE14 -5.096938 + 2E14CAP PRICER 54.423615 2CPTE14 1. + 2E14CAP 2EPKWD 24.213669 2EPKSD 24.213669 + 2E14CAP 2EWDE14 -2.998198 2EWNE14 -2.998198 + 2E14CAP 2EIDE14 -3.897659 2EINE14 -2.098739 + 2E14CAP 2ESDE14 -12.892257 2ESNE14 -5.096938 + 3E14CAP PRICER 40.668594 3CPTE14 1. + 3E14CAP 3EPKWD 24.213669 3EPKSD 24.213669 + 3E14CAP 3EWDE14 -2.998198 3EWNE14 -2.998198 + 3E14CAP 3EIDE14 -3.897659 3EINE14 -2.098739 + 3E14CAP 3ESDE14 -12.892257 3ESNE14 -5.096938 + 1E22CAP PRICER 81.611801 1CPTE22 1. + 1E22CAP 1UTLE22 -6.311683 1EPKWD 24.213669 + 1E22CAP 1EPKSD 24.213669 1EWDE22 -5.365133 + 1E22CAP 1EIDE22 -5.365135 1ESDE22 -16.095398 + 2E22CAP PRICER 60.985336 2CPTE22 1. + 2E22CAP 2UTLE22 -6.311683 2EPKWD 24.213669 + 2E22CAP 2EPKSD 24.213669 2EWDE22 -5.365133 + 2E22CAP 2EIDE22 -5.365135 2ESDE22 -16.095398 + 3E22CAP PRICER 45.5719 3CPTE22 1. + 3E22CAP 3UTLE22 -6.311683 3EPKWD 24.213669 + 3E22CAP 3EPKSD 24.213669 3EWDE22 -5.365133 + 3E22CAP 3EIDE22 -5.365135 3ESDE22 -16.095398 + 1E23CAP PRICER 74.380371 1CPTE23 1. + 1E23CAP 1UTLE23 -6.311683 1EPKWD 24.213669 + 1E23CAP 1EPKSD 24.213669 1EWDE23 -5.365133 + 1E23CAP 1EIDE23 -5.365135 1ESDE23 -16.095398 + 2E23CAP PRICER 55.581573 2CPTE23 1. + 2E23CAP 2UTLE23 -6.311683 2EPKWD 24.213669 + 2E23CAP 2EPKSD 24.213669 2EWDE23 -5.365133 + 2E23CAP 2EIDE23 -5.365135 2ESDE23 -16.095398 + 3E23CAP PRICER 41.53389 3CPTE23 1. + 3E23CAP 3UTLE23 -6.311683 3EPKWD 24.213669 + 3E23CAP 3EPKSD 24.213669 3EWDE23 -5.365133 + 3E23CAP 3EIDE23 -5.365135 3ESDE23 -16.095398 + 1E31CAP 1CPTE31 1. 1EPKWD 24.213669 + 1E31CAP 1EPKSD 24.213669 1EWDE31 -1.199279 + 1E31CAP 1EWNE31 -1.199279 1EIDE31 -.738504 + 1E31CAP 1EINE31 -.397656 1ESDE31 -2.442742 + 1E31CAP 1ESNE31 -.965735 + 2E31CAP 2CPTE31 1. 2EPKWD 24.213669 + 2E31CAP 2EPKSD 24.213669 2EWDE31 -1.199279 + 2E31CAP 2EWNE31 -1.199279 2EIDE31 -.738504 + 2E31CAP 2EINE31 -.397656 2ESDE31 -2.442742 + 2E31CAP 2ESNE31 -.965735 + 3E31CAP 3CPTE31 1. 3EPKWD 24.213669 + 3E31CAP 3EPKSD 24.213669 3EWDE31 -1.199279 + 3E31CAP 3EWNE31 -1.199279 3EIDE31 -.738504 + 3E31CAP 3EINE31 -.397656 3ESDE31 -2.442742 + 3E31CAP 3ESNE31 -.965735 + 2E35CAP PRICER 21.229065 2CPTE35 1. + 2E35CAP 3GRCE35 -32. 2EWDE35 -.883679 + 2E35CAP 2EWNE35 -.883679 2EIDE35 -1.148784 + 2E35CAP 2EINE35 -.618576 2ESDE35 -3.121283 + 2E35CAP 2ESNE35 -1.234 + 3E35CAP PRICER 15.863641 3CPTE35 1. + 3E35CAP 3GRCE35 1. 3EWDE35 -.883679 + 3E35CAP 3EWNE35 -.883679 3EIDE35 -1.148784 + 3E35CAP 3EINE35 -.618576 3ESDE35 -3.121283 + 3E35CAP 3ESNE35 -1.234 + 3E94CAP PRICER 61.723953 3CPTE94 1. + 3E94CAP 3EPKWD 26.521011 3EPKSD 26.521011 + 3E94CAP 3EWDE94 -3.156 3EWNE94 -3.156 + 3E94CAP 3EIDE94 -4.1028 3EINE94 -2.2092 + 3E94CAP 3ESDE94 -13.570797 3ESNE94 -5.365198 + 3E60CAP PRICER 74.414856 3CPTE60 1. + 3E60CAP 3EPKWD 26.521011 3EPKSD 26.521011 + 3E60CAP 3EWDE60 -2.114518 3EWNE60 -2.114518 + 3E60CAP 3EIDE60 -2.748875 3EINE60 -1.480163 + 3E60CAP 3ESDE60 -9.092433 3ESNE60 -3.594682 + 3E60CAP 3HPKW 31.56 + 1E51CAP PRICER 71.281189 1CPTE51 1. + 1E51CAP 1EPKWD 24.213669 1EPKSD 24.213669 + 1E51CAP 1EWDE51 -2.840398 1EIDE51 -3.692519 + 1E51CAP 1ESDE51 -12.213717 + 2E51CAP PRICER 53.265671 2CPTE51 1. + 2E51CAP 2EPKWD 24.213669 2EPKSD 24.213669 + 2E51CAP 2EWDE51 -2.840398 2EIDE51 -3.692519 + 2E51CAP 2ESDE51 -12.213717 + 3E51CAP PRICER 39.803314 3CPTE51 1. + 3E51CAP 3EPKWD 24.213669 3EPKSD 24.213669 + 3E51CAP 3EWDE51 -2.840398 3EIDE51 -3.692519 + 3E51CAP 3ESDE51 -12.213717 + 1EC1WD PRICER 5.448 1BALHCO -3.637 + 1EC1WD 1BALDSL -.066667 1BALEWD .913 + 1EC1WD 1EWDEC1 1. + 1EC1ID PRICER 5.448 1BALHCO -3.637 + 1EC1ID 1BALDSL -.066667 1BALEID .913 + 1EC1ID 1EIDEC1 1. + 1EC1SD PRICER 5.448 1BALHCO -3.637 + 1EC1SD 1BALDSL -.066667 1BALESD .913 + 1EC1SD 1ESDEC1 1. + 1EC1WN PRICER 5.448 1BALHCO -3.637 + 1EC1WN 1BALDSL -.066667 1BALEWN .913 + 1EC1WN 1EWNEC1 1. 1BASW -.77605 + 1EC1IN PRICER 5.448 1BALHCO -3.637 + 1EC1IN 1BALDSL -.066667 1BALEIN .913 + 1EC1IN 1EINEC1 1. 1BASI -.77605 + 1EC1SN PRICER 5.448 1BALHCO -3.637 + 1EC1SN 1BALDSL -.066667 1BALESN .913 + 1EC1SN 1ESNEC1 1. 1BASS -.77605 + 2EC1WD PRICER 4.071078 2BALHCO -3.637 + 2EC1WD 2BALDSL -.066667 2BALEWD .913 + 2EC1WD 2EWDEC1 1. + 2EC1ID PRICER 4.071078 2BALHCO -3.637 + 2EC1ID 2BALDSL -.066667 2BALEID .913 + 2EC1ID 2EIDEC1 1. + 2EC1SD PRICER 4.071078 2BALHCO -3.637 + 2EC1SD 2BALDSL -.066667 2BALESD .913 + 2EC1SD 2ESDEC1 1. + 2EC1WN PRICER 4.071078 2BALHCO -3.637 + 2EC1WN 2BALDSL -.066667 2BALEWN .913 + 2EC1WN 2EWNEC1 1. 2BASW -.77605 + 2EC1IN PRICER 4.071078 2BALHCO -3.637 + 2EC1IN 2BALDSL -.066667 2BALEIN .913 + 2EC1IN 2EINEC1 1. 2BASI -.77605 + 2EC1SN PRICER 4.071078 2BALHCO -3.637 + 2EC1SN 2BALDSL -.066667 2BALESN .913 + 2EC1SN 2ESNEC1 1. 2BASS -.77605 + 3EC1WD PRICER 3.042154 3BALHCO -3.637 + 3EC1WD 3BALDSL -.066667 3BALEWD .913 + 3EC1WD 3EWDEC1 1. + 3EC1ID PRICER 3.042154 3BALHCO -3.637 + 3EC1ID 3BALDSL -.066667 3BALEID .913 + 3EC1ID 3EIDEC1 1. + 3EC1SD PRICER 3.042154 3BALHCO -3.637 + 3EC1SD 3BALDSL -.066667 3BALESD .913 + 3EC1SD 3ESDEC1 1. + 3EC1WN PRICER 3.042154 3BALHCO -3.637 + 3EC1WN 3BALDSL -.066667 3BALEWN .913 + 3EC1WN 3EWNEC1 1. 3BASW -.77605 + 3EC1IN PRICER 3.042154 3BALHCO -3.637 + 3EC1IN 3BALDSL -.066667 3BALEIN .913 + 3EC1IN 3EINEC1 1. 3BASI -.77605 + 3EC1SN PRICER 3.042154 3BALHCO -3.637 + 3EC1SN 3BALDSL -.066667 3BALESN .913 + 3EC1SN 3ESNEC1 1. 3BASS -.77605 + 1EC2WD PRICER 4.457562 1BALHCO -2.9758 + 1EC2WD 1BALDSL -.054545 1BALEWD .913 + 1EC2WD 1EWDEC2 1. + 1EC2ID PRICER 4.457562 1BALHCO -2.9758 + 1EC2ID 1BALDSL -.054545 1BALEID .913 + 1EC2ID 1EIDEC2 1. + 1EC2SD PRICER 4.457562 1BALHCO -2.9758 + 1EC2SD 1BALDSL -.054545 1BALESD .913 + 1EC2SD 1ESDEC2 1. + 1EC2WN PRICER 4.457562 1BALHCO -2.9758 + 1EC2WN 1BALDSL -.054545 1BALEWN .913 + 1EC2WN 1EWNEC2 1. 1BASW -.77605 + 1EC2IN PRICER 4.457562 1BALHCO -2.9758 + 1EC2IN 1BALDSL -.054545 1BALEIN .913 + 1EC2IN 1EINEC2 1. 1BASI -.77605 + 1EC2SN PRICER 4.457562 1BALHCO -2.9758 + 1EC2SN 1BALDSL -.054545 1BALESN .913 + 1EC2SN 1ESNEC2 1. 1BASS -.77605 + 2EC2WD PRICER 3.330964 2BALHCO -2.9758 + 2EC2WD 2BALDSL -.054545 2BALEWD .913 + 2EC2WD 2EWDEC2 1. + 2EC2ID PRICER 3.330964 2BALHCO -2.9758 + 2EC2ID 2BALDSL -.054545 2BALEID .913 + 2EC2ID 2EIDEC2 1. + 2EC2SD PRICER 3.330964 2BALHCO -2.9758 + 2EC2SD 2BALDSL -.054545 2BALESD .913 + 2EC2SD 2ESDEC2 1. + 2EC2WN PRICER 3.330964 2BALHCO -2.9758 + 2EC2WN 2BALDSL -.054545 2BALEWN .913 + 2EC2WN 2EWNEC2 1. 2BASW -.77605 + 2EC2IN PRICER 3.330964 2BALHCO -2.9758 + 2EC2IN 2BALDSL -.054545 2BALEIN .913 + 2EC2IN 2EINEC2 1. 2BASI -.77605 + 2EC2SN PRICER 3.330964 2BALHCO -2.9758 + 2EC2SN 2BALDSL -.054545 2BALESN .913 + 2EC2SN 2ESNEC2 1. 2BASS -.77605 + 3EC2WD PRICER 2.489097 3BALHCO -2.9758 + 3EC2WD 3BALDSL -.054545 3BALEWD .913 + 3EC2WD 3EWDEC2 1. + 3EC2ID PRICER 2.489097 3BALHCO -2.9758 + 3EC2ID 3BALDSL -.054545 3BALEID .913 + 3EC2ID 3EIDEC2 1. + 3EC2SD PRICER 2.489097 3BALHCO -2.9758 + 3EC2SD 3BALDSL -.054545 3BALESD .913 + 3EC2SD 3ESDEC2 1. + 3EC2WN PRICER 2.489097 3BALHCO -2.9758 + 3EC2WN 3BALDSL -.054545 3BALEWN .913 + 3EC2WN 3EWNEC2 1. 3BASW -.77605 + 3EC2IN PRICER 2.489097 3BALHCO -2.9758 + 3EC2IN 3BALDSL -.054545 3BALEIN .913 + 3EC2IN 3EINEC2 1. 3BASI -.77605 + 3EC2SN PRICER 2.489097 3BALHCO -2.9758 + 3EC2SN 3BALDSL -.054545 3BALESN .913 + 3EC2SN 3ESNEC2 1. 3BASS -.77605 + 1EC3WD PRICER 5.635665 1BALHCO -2.7278 + 1EC3WD 1BALDSL -.05 1BALEWD .913 + 1EC3WD 1EWDEC3 1. + 1EC3ID PRICER 5.635665 1BALHCO -2.7278 + 1EC3ID 1BALDSL -.05 1BALEID .913 + 1EC3ID 1EIDEC3 1. + 1EC3SD PRICER 5.635665 1BALHCO -2.7278 + 1EC3SD 1BALDSL -.05 1BALESD .913 + 1EC3SD 1ESDEC3 1. + 1EC3WN PRICER 5.635665 1BALHCO -2.7278 + 1EC3WN 1BALDSL -.05 1BALEWN .913 + 1EC3WN 1EWNEC3 1. 1BASW -.77605 + 1EC3IN PRICER 5.635665 1BALHCO -2.7278 + 1EC3IN 1BALDSL -.05 1BALEIN .913 + 1EC3IN 1EINEC3 1. 1BASI -.77605 + 1EC3SN PRICER 5.635665 1BALHCO -2.7278 + 1EC3SN 1BALDSL -.05 1BALESN .913 + 1EC3SN 1ESNEC3 1. 1BASS -.77605 + 2EC3WD PRICER 4.211314 2BALHCO -2.7278 + 2EC3WD 2BALDSL -.05 2BALEWD .913 + 2EC3WD 2EWDEC3 1. + 2EC3ID PRICER 4.211314 2BALHCO -2.7278 + 2EC3ID 2BALDSL -.05 2BALEID .913 + 2EC3ID 2EIDEC3 1. + 2EC3SD PRICER 4.211314 2BALHCO -2.7278 + 2EC3SD 2BALDSL -.05 2BALESD .913 + 2EC3SD 2ESDEC3 1. + 2EC3WN PRICER 4.211314 2BALHCO -2.7278 + 2EC3WN 2BALDSL -.05 2BALEWN .913 + 2EC3WN 2EWNEC3 1. 2BASW -.77605 + 2EC3IN PRICER 4.211314 2BALHCO -2.7278 + 2EC3IN 2BALDSL -.05 2BALEIN .913 + 2EC3IN 2EINEC3 1. 2BASI -.77605 + 2EC3SN PRICER 4.211314 2BALHCO -2.7278 + 2EC3SN 2BALDSL -.05 2BALESN .913 + 2EC3SN 2ESNEC3 1. 2BASS -.77605 + 3EC3WD PRICER 3.146947 3BALHCO -2.7278 + 3EC3WD 3BALDSL -.05 3BALEWD .913 + 3EC3WD 3EWDEC3 1. + 3EC3ID PRICER 3.146947 3BALHCO -2.7278 + 3EC3ID 3BALDSL -.05 3BALEID .913 + 3EC3ID 3EIDEC3 1. + 3EC3SD PRICER 3.146947 3BALHCO -2.7278 + 3EC3SD 3BALDSL -.05 3BALESD .913 + 3EC3SD 3ESDEC3 1. + 3EC3WN PRICER 3.146947 3BALHCO -2.7278 + 3EC3WN 3BALDSL -.05 3BALEWN .913 + 3EC3WN 3EWNEC3 1. 3BASW -.77605 + 3EC3IN PRICER 3.146947 3BALHCO -2.7278 + 3EC3IN 3BALDSL -.05 3BALEIN .913 + 3EC3IN 3EINEC3 1. 3BASI -.77605 + 3EC3SN PRICER 3.146947 3BALHCO -2.7278 + 3EC3SN 3BALDSL -.05 3BALESN .913 + 3EC3SN 3ESNEC3 1. 3BASS -.77605 + 1EP1WD PRICER 22.382751 1BALDSH -3.3333 + 1EP1WD 1BNDEP1L 1. 1BALEWD .913 + 1EP1WD 1EWDEP1 1. + 1EP1ID PRICER 22.382751 1BALDSH -3.3333 + 1EP1ID 1BNDEP1L 1. 1BALEID .913 + 1EP1ID 1EIDEP1 1. + 1EP1SD PRICER 22.382751 1BALDSH -3.3333 + 1EP1SD 1BNDEP1L 1. 1BALESD .913 + 1EP1SD 1ESDEP1 1. + 1EP1WN PRICER 22.382751 1BALDSH -3.3333 + 1EP1WN 1BNDEP1L 1. 1BALEWN .913 + 1EP1WN 1EWNEP1 1. 1BASW -.77605 + 1EP1IN PRICER 22.382751 1BALDSH -3.3333 + 1EP1IN 1BNDEP1L 1. 1BALEIN .913 + 1EP1IN 1EINEP1 1. 1BASI -.77605 + 1EP1SN PRICER 22.382751 1BALDSH -3.3333 + 1EP1SN 1BNDEP1L 1. 1BALESN .913 + 1EP1SN 1ESNEP1 1. 1BASS -.77605 + 2EP1WD PRICER 16.725754 2BALDSH -3.3333 + 2EP1WD 2BNDEP1L 1. 2BALEWD .913 + 2EP1WD 2EWDEP1 1. + 2EP1ID PRICER 16.725754 2BALDSH -3.3333 + 2EP1ID 2BNDEP1L 1. 2BALEID .913 + 2EP1ID 2EIDEP1 1. + 2EP1SD PRICER 16.725754 2BALDSH -3.3333 + 2EP1SD 2BNDEP1L 1. 2BALESD .913 + 2EP1SD 2ESDEP1 1. + 2EP1WN PRICER 16.725754 2BALDSH -3.3333 + 2EP1WN 2BNDEP1L 1. 2BALEWN .913 + 2EP1WN 2EWNEP1 1. 2BASW -.77605 + 2EP1IN PRICER 16.725754 2BALDSH -3.3333 + 2EP1IN 2BNDEP1L 1. 2BALEIN .913 + 2EP1IN 2EINEP1 1. 2BASI -.77605 + 2EP1SN PRICER 16.725754 2BALDSH -3.3333 + 2EP1SN 2BNDEP1L 1. 2BALESN .913 + 2EP1SN 2ESNEP1 1. 2BASS -.77605 + 3EP1WD PRICER 12.498495 3BALDSH -3.3333 + 3EP1WD 3BALEWD .913 3EWDEP1 1. + 3EP1ID PRICER 12.498495 3BALDSH -3.3333 + 3EP1ID 3BALEID .913 3EIDEP1 1. + 3EP1SD PRICER 12.498495 3BALDSH -3.3333 + 3EP1SD 3BALESD .913 3ESDEP1 1. + 3EP1WN PRICER 12.498495 3BALDSH -3.3333 + 3EP1WN 3BALEWN .913 3EWNEP1 1. + 3EP1WN 3BASW -.77605 + 3EP1IN PRICER 12.498495 3BALDSH -3.3333 + 3EP1IN 3BALEIN .913 3EINEP1 1. + 3EP1IN 3BASI -.77605 + 3EP1SN PRICER 12.498495 3BALDSH -3.3333 + 3EP1SN 3BALESN .913 3ESNEP1 1. + 3EP1SN 3BASS -.77605 + 1E14WD PRICER 4.183896 1BALDSL -3.5971 + 1E14WD 1BALEWD .913 1EWDE14 1. + 1E14ID PRICER 4.183896 1BALDSL -3.5971 + 1E14ID 1BALEID .913 1EIDE14 1. + 1E14SD PRICER 4.183896 1BALDSL -3.5971 + 1E14SD 1BALESD .913 1ESDE14 1. + 1E14WN PRICER 4.183896 1BALDSL -3.5971 + 1E14WN 1BALEWN .913 1EWNE14 1. + 1E14WN 1BASW -.77605 + 1E14IN PRICER 4.183896 1BALDSL -3.5971 + 1E14IN 1BALEIN .913 1EINE14 1. + 1E14IN 1BASI -.77605 + 1E14SN PRICER 4.183896 1BALDSL -3.5971 + 1E14SN 1BALESN .913 1ESNE14 1. + 1E14SN 1BASS -.77605 + 2E14WD PRICER 3.126463 2BALDSL -3.5971 + 2E14WD 2BALEWD .913 2EWDE14 1. + 2E14ID PRICER 3.126463 2BALDSL -3.5971 + 2E14ID 2BALEID .913 2EIDE14 1. + 2E14SD PRICER 3.126463 2BALDSL -3.5971 + 2E14SD 2BALESD .913 2ESDE14 1. + 2E14WN PRICER 3.126463 2BALDSL -3.5971 + 2E14WN 2BALEWN .913 2EWNE14 1. + 2E14WN 2BASW -.77605 + 2E14IN PRICER 3.126463 2BALDSL -3.5971 + 2E14IN 2BALEIN .913 2EINE14 1. + 2E14IN 2BASI -.77605 + 2E14SN PRICER 3.126463 2BALDSL -3.5971 + 2E14SN 2BALESN .913 2ESNE14 1. + 2E14SN 2BASS -.77605 + 3E14WD PRICER 2.336281 3BALDSL -3.5971 + 3E14WD 3BALEWD .913 3EWDE14 1. + 3E14ID PRICER 2.336281 3BALDSL -3.5971 + 3E14ID 3BALEID .913 3EIDE14 1. + 3E14SD PRICER 2.336281 3BALDSL -3.5971 + 3E14SD 3BALESD .913 3ESDE14 1. + 3E14WN PRICER 2.336281 3BALDSL -3.5971 + 3E14WN 3BALEWN .913 3EWNE14 1. + 3E14WN 3BASW -.77605 + 3E14IN PRICER 2.336281 3BALDSL -3.5971 + 3E14IN 3BALEIN .913 3EINE14 1. + 3E14IN 3BASI -.77605 + 3E14SN PRICER 2.336281 3BALDSL -3.5971 + 3E14SN 3BALESN .913 3ESNE14 1. + 3E14SN 3BASS -.77605 + 1E22WD PRICER 1.807856 1BALPLU .016627 + 1E22WD 1BALMAG -12.6582 2BALPLU .007126 + 1E22WD 1BALEWD .4565 1BALEWN .4565 + 1E22WD 1EWDE22 1. 1BASW .068475 + 1E22ID PRICER 1.807856 1BALPLU .016627 + 1E22ID 1BALMAG -12.6582 2BALPLU .007126 + 1E22ID 1BALEID .59345 1BALEIN .31955 + 1E22ID 1EIDE22 1. 1BASI .047932 + 1E22SD PRICER 1.807856 1BALPLU .016627 + 1E22SD 1BALMAG -12.6582 2BALPLU .007126 + 1E22SD 1BALESD .654317 1BALESN .258683 + 1E22SD 1ESDE22 1. 1BASS .038802 + 2E22WD PRICER 1.350941 2BALPLU .016627 + 2E22WD 2BALMAG -12.6582 3BALPLU .007126 + 2E22WD 2BALEWD .4565 2BALEWN .4565 + 2E22WD 2EWDE22 1. 2BASW .068475 + 2E22ID PRICER 1.350941 2BALPLU .016627 + 2E22ID 2BALMAG -12.6582 3BALPLU .007126 + 2E22ID 2BALEID .59345 2BALEIN .31955 + 2E22ID 2EIDE22 1. 2BASI .047932 + 2E22SD PRICER 1.350941 2BALPLU .016627 + 2E22SD 2BALMAG -12.6582 3BALPLU .007126 + 2E22SD 2BALESD .654317 2BALESN .258683 + 2E22SD 2ESDE22 1. 2BASS .038802 + 3E22WD PRICER 1.009503 3BALPLU .016627 + 3E22WD 3BALMAG -12.6582 3BALEWD .4565 + 3E22WD 3BALEWN .4565 3EWDE22 1. + 3E22WD 3BASW .068475 + 3E22ID PRICER 1.009503 3BALPLU .016627 + 3E22ID 3BALMAG -12.6582 3BALEID .59345 + 3E22ID 3BALEIN .31955 3EIDE22 1. + 3E22ID 3BASI .047932 + 3E22SD PRICER 1.009503 3BALPLU .016627 + 3E22SD 3BALMAG -12.6582 3BALESD .654317 + 3E22SD 3BALESN .258683 3ESDE22 1. + 3E22SD 3BASS .038802 + 1E23WD PRICER 1.136366 1BALAGR -1.457729 + 1E23WD 1BALAGS 1.457729 1BALEWD .4565 + 1E23WD 1BALEWN .4565 1EWDE23 1. + 1E23WD 1BASW .068475 + 1E23ID PRICER 1.136366 1BALAGR -1.457729 + 1E23ID 1BALAGS 1.457729 1BALEID .59345 + 1E23ID 1BALEIN .31955 1EIDE23 1. + 1E23ID 1BASI .047932 + 1E23SD PRICER 1.136366 1BALAGR -1.457729 + 1E23SD 1BALAGS 1.457729 1BALESD .654317 + 1E23SD 1BALESN .258683 1ESDE23 1. + 1E23SD 1BASS .038802 + 2E23WD PRICER .849163 2BALAGR -1.457729 + 2E23WD 2BALAGS 1.457729 2BALEWD .4565 + 2E23WD 2BALEWN .4565 2EWDE23 1. + 2E23WD 2BASW .068475 + 2E23ID PRICER .849163 2BALAGR -1.457729 + 2E23ID 2BALAGS 1.457729 2BALEID .59345 + 2E23ID 2BALEIN .31955 2EIDE23 1. + 2E23ID 2BASI .047932 + 2E23SD PRICER .849163 2BALAGR -1.457729 + 2E23SD 2BALAGS 1.457729 2BALESD .654317 + 2E23SD 2BALESN .258683 2ESDE23 1. + 2E23SD 2BASS .038802 + 3E23WD PRICER .634546 3BALAGR -1.457729 + 3E23WD 3BALAGS 1.457729 3BALEWD .4565 + 3E23WD 3BALEWN .4565 3EWDE23 1. + 3E23WD 3BASW .068475 + 3E23ID PRICER .634546 3BALAGR -1.457729 + 3E23ID 3BALAGS 1.457729 3BALEID .59345 + 3E23ID 3BALEIN .31955 3EIDE23 1. + 3E23ID 3BASI .047932 + 3E23SD PRICER .634546 3BALAGR -1.457729 + 3E23SD 3BALAGS 1.457729 3BALESD .654317 + 3E23SD 3BALESN .258683 3ESDE23 1. + 3E23SD 3BASS .038802 + 1E31WD 1BALEWD .913 1EWDE31 1. + 1E31ID 1BALEID .913 1EIDE31 1. + 1E31SD 1BALESD .913 1ESDE31 1. + 1E31WN 1BALEWN .913 1EWNE31 1. + 1E31WN 1BASW -.77605 + 1E31IN 1BALEIN .913 1EINE31 1. + 1E31IN 1BASI -.77605 + 1E31SN 1BALESN .913 1ESNE31 1. + 1E31SN 1BASS -.77605 + 2E31WD 2BALEWD .913 2EWDE31 1. + 2E31ID 2BALEID .913 2EIDE31 1. + 2E31SD 2BALESD .913 2ESDE31 1. + 2E31WN 2BALEWN .913 2EWNE31 1. + 2E31WN 2BASW -.77605 + 2E31IN 2BALEIN .913 2EINE31 1. + 2E31IN 2BASI -.77605 + 2E31SN 2BALESN .913 2ESNE31 1. + 2E31SN 2BASS -.77605 + 3E31WD 3BALEWD .913 3EWDE31 1. + 3E31ID 3BALEID .913 3EIDE31 1. + 3E31SD 3BALESD .913 3ESDE31 1. + 3E31WN 3BALEWN .913 3EWNE31 1. + 3E31WN 3BASW -.77605 + 3E31IN 3BALEIN .913 3EINE31 1. + 3E31IN 3BASI -.77605 + 3E31SN 3BALESN .913 3ESNE31 1. + 3E31SN 3BASS -.77605 + 2E35WD 2BALEWD .913 2EWDE35 1. + 2E35ID 2BALEID .913 2EIDE35 1. + 2E35SD 2BALESD .913 2ESDE35 1. + 2E35WN 2BALEWN .913 2EWNE35 1. + 2E35WN 2BASW -.77605 + 2E35IN 2BALEIN .913 2EINE35 1. + 2E35IN 2BASI -.77605 + 2E35SN 2BALESN .913 2ESNE35 1. + 2E35SN 2BASS -.77605 + 3E35WD 3BALEWD .913 3EWDE35 1. + 3E35ID 3BALEID .913 3EIDE35 1. + 3E35SD 3BALESD .913 3ESDE35 1. + 3E35WN 3BALEWN .913 3EWNE35 1. + 3E35WN 3BASW -.77605 + 3E35IN 3BALEIN .913 3EINE35 1. + 3E35IN 3BASI -.77605 + 3E35SN 3BALESN .913 3ESNE35 1. + 3E35SN 3BASS -.77605 + 3E94WD PRICER 41.750214 3BALGAS -2.5 + 3E94WD 3BALEWD 1. 3EWDE94 1. + 3E94ID PRICER 41.750214 3BALGAS -2.5 + 3E94ID 3BALEID 1. 3EIDE94 1. + 3E94SD PRICER 41.750214 3BALGAS -2.5 + 3E94SD 3BALESD 1. 3ESDE94 1. + 3E94WN PRICER 41.750214 3BALGAS -2.5 + 3E94WN 3BALEWN 1. 3EWNE94 1. + 3E94WN 3BASW -.85 + 3E94IN PRICER 41.750214 3BALGAS -2.5 + 3E94IN 3BALEIN 1. 3EINE94 1. + 3E94IN 3BASI -.85 + 3E94SN PRICER 41.750214 3BALGAS -2.5 + 3E94SN 3BALESN 1. 3ESNE94 1. + 3E94SN 3BASS -.85 + 3E60WD PRICER 3.533263 3BALHCO -2.5 + 3E60WD 3BALEWD 1. 3EWDE60 1. + 3E60WD 3BALDHW 2. + 3E60ID PRICER 3.533263 3BALHCO -2.5 + 3E60ID 3BALEID 1. 3EIDE60 1. + 3E60ID 3BALDHI 2. + 3E60SD PRICER 3.533263 3BALHCO -2.5 + 3E60SD 3BALESD 1. 3ESDE60 1. + 3E60SD 3BALDHS 2. + 3E60WN PRICER 3.533263 3BALHCO -2.5 + 3E60WN 3BALEWN 1. 3EWNE60 1. + 3E60WN 3BASW -.85 3BALDHW 2. + 3E60IN PRICER 3.533263 3BALHCO -2.5 + 3E60IN 3BALEIN 1. 3EINE60 1. + 3E60IN 3BASI -.85 3BALDHI 2. + 3E60SN PRICER 3.533263 3BALHCO -2.5 + 3E60SN 3BALESN 1. 3ESNE60 1. + 3E60SN 3BASS -.85 3BALDHS 2. + 1E51WD 1BALEWD .913 1BALEWN -1.304311 + 1E51WD 1EWDE51 1. + 1E51ID 1BALEID .913 1BALEIN -1.304311 + 1E51ID 1EIDE51 1. + 1E51SD 1BALESD .913 1BALESN -1.304311 + 1E51SD 1ESDE51 1. + 2E51WD 2BALEWD .913 2BALEWN -1.292807 + 2E51WD 2EWDE51 1. + 2E51ID 2BALEID .913 2BALEIN -1.292807 + 2E51ID 2EIDE51 1. + 2E51SD 2BALESD .913 2BALESN -1.292807 + 2E51SD 2ESDE51 1. + 3E51WD 3BALEWD .913 3BALEWN -1.281395 + 3E51WD 3EWDE51 1. + 3E51ID 3BALEID .913 3BALEIN -1.281395 + 3E51ID 3EIDE51 1. + 3E51SD 3BALESD .913 3BALESN -1.281395 + 3E51SD 3ESDE51 1. +RHS + REST 1CPTEP1 12.355 1CPTE14 3.487 + REST 1CPTE22 3.727 1CPTE23 2. + REST 1CPTE31 1.686 1CPTE51 1. + REST 1CPTS06 555. 1CPTS21 4088. + REST 1CPTS23 728. 1CPTS28 445. + REST 1CPTIJ6 248.21 1CPTIJ7 126.78 + REST 1CPTIJ8 61.21 1CPTR20 38.95 + REST 1CPTR21 24.79 1CPTR23 43.24 + REST 1CPTR27 235.17 1CPTR28 52.4 + REST 1CPTRT0 30.689987 1CPTRT1 61.37 + REST 1CPTRT3 85.93 1CPTRT7 76.63 + REST 1CPTRT8 16.63 1CPTR50 4. + REST 1CPTR51 65.64 1CPTR53 34.019989 + REST 1CPTR57 157.73 1CPTR58 26.34 + REST 2CPTEP1 8.303 2CPTE14 2.838 + REST 2CPTE22 3.727 2CPTE23 2. + REST 2CPTE31 1.686 2CPTE51 1. + REST 2CPTS06 229. 2CPTS21 3270. + REST 2CPTS23 582. 2CPTS28 356. + REST 2CPTIJ6 150. 2CPTIJ7 70. + REST 2CPTIJ8 30. 2CPTR20 20. + REST 2CPTR21 12. 2CPTR23 22. + REST 2CPTR27 118. 2CPTR28 26. + REST 2CPTRT0 15. 2CPTRT1 30. + REST 2CPTRT3 43. 2CPTRT7 38. + REST 2CPTRT8 8. 2CPTR50 2. + REST 2CPTR51 32. 2CPTR53 17. + REST 2CPTR57 80. 2CPTR58 13. + REST 3CPTEP1 7.765 3CPTE14 2.838 + REST 3CPTE22 2.906 3CPTE23 2. + REST 3CPTE31 1.686 3CPTE51 1. + REST 3CPTS06 153. 3CPTS21 2453. + REST 3CPTS23 437. 3CPTS28 267. + REST 3CPTIJ6 50. 3CPTIJ7 30. + REST 3CPTR20 10. 3CPTR21 6. + REST 3CPTR23 11. 3CPTR27 59. + REST 3CPTR28 13. 3CPTRT0 7.5 + REST 3CPTRT1 15. 3CPTRT3 21. + REST 3CPTRT7 19. 3CPTRT8 4. + REST 3CPTR50 1. 3CPTR51 16. + REST 3CPTR53 8.5 3CPTR57 40. + REST 3CPTR58 6.5 3GRCE35 .01 + REST 1DEMI1 332.829834 1DEMII 826.959961 + REST 1DEMIJ 436.189941 1DEMNY 616.079834 + REST 1DEMR2 617.72998 1DEMRT 277.599854 + REST 1DEMR5 287.72998 1DEMRD 417.99 + REST 1DEMT8 1161.799805 1DEMTX 327.7 + REST 2DEMI1 328.219971 2DEMII 827.689941 + REST 2DEMIJ 397.099854 2DEMNY 626.849854 + REST 2DEMR2 606.099854 2DEMRT 268.7 + REST 2DEMR5 277.139893 2DEMRD 413.799805 + REST 2DEMT8 1200. 2DEMTX 338.5 + REST 3DEMI1 291.689941 3DEMII 855.269775 + REST 3DEMIJ 376.829834 3DEMNY 634.919922 + REST 3DEMR2 576.839844 3DEMRT 264.799805 + REST 3DEMR5 264.829834 3DEMRD 418.579834 + REST 3DEMT8 1201.599854 3DEMTX 358.9 + REST 1BNDEP1L 64.659988 2BNDEP1L 24.25 +BOUNDS + FX BNDSET1 1MINHCO1 3084.099854 + UP BNDSET1 2MINHCO1 3084.099854 + UP BNDSET1 3MINHCO1 3039. + UP BNDSET1 1STKOIK1 28940. + FX BNDSET1 1EXPDSH1 91. + FX BNDSET1 2EXPDSH1 61. + FX BNDSET1 3EXPDSH1 61. + FX BNDSET1 1EXPDSL1 23. + FX BNDSET1 2EXPDSL1 17. + FX BNDSET1 3EXPDSL1 17. + UP BNDSET1 1EXPGAS1 .1 + UP BNDSET1 2EXPGAS1 .1 + UP BNDSET1 3EXPGAS1 .1 + UP BNDSET1 1STKGAK1 12058. + UP BNDSET1 1STKURN1 .1 + UP BNDSET1 1STKUDP1 .1 + UP BNDSET1 1STKPLU1 1.5 + UP BNDSET1 1STKAGS1 .0001 + UP BNDSET1 1STKLMS1 .0001 + UP BNDSET1 2E35INV .0001 + UP BNDSET1 3E35INV .0001 + UP BNDSET1 3E94INV .0001 + UP BNDSET1 3E60INV .0001 + UP BNDSET1 3S80INV .001 + LO BNDSET1 1IJ6CAP 248.21 + LO BNDSET1 2IJ6CAP 150. + LO BNDSET1 3IJ6CAP 50. + LO BNDSET1 1IJ7CAP 126.78 + LO BNDSET1 2IJ7CAP 70. + LO BNDSET1 3IJ7CAP 30. + LO BNDSET1 1IJ8CAP 61.21 + LO BNDSET1 2IJ8CAP 30. + LO BNDSET1 1R20CAP 38.95 + LO BNDSET1 2R20CAP 20. + LO BNDSET1 3R20CAP 10. + LO BNDSET1 1R21CAP 24.79 + LO BNDSET1 2R21CAP 12. + LO BNDSET1 3R21CAP 6. + LO BNDSET1 1R23CAP 43.24 + LO BNDSET1 2R23CAP 22. + LO BNDSET1 3R23CAP 11. + LO BNDSET1 1R27CAP 235.17 + LO BNDSET1 2R27CAP 118. + LO BNDSET1 3R27CAP 59. + LO BNDSET1 1R28CAP 52.4 + LO BNDSET1 2R28CAP 26. + LO BNDSET1 3R28CAP 13. + UP BNDSET1 2R2ACAP .29 + UP BNDSET1 3R2ACAP .58 + FX BNDSET1 1R2YCAP 223.18 + FX BNDSET1 2R2YCAP 218.49 + FX BNDSET1 3R2YCAP 205.62 + FX BNDSET1 1RT0CAP 30.689987 + LO BNDSET1 2RT0CAP 15. + LO BNDSET1 3RT0CAP 7.5 + FX BNDSET1 1RT1CAP 61.37 + LO BNDSET1 2RT1CAP 30. + LO BNDSET1 3RT1CAP 15. + FX BNDSET1 1RT7CAP 76.63 + LO BNDSET1 2RT7CAP 38. + LO BNDSET1 3RT7CAP 19. + FX BNDSET1 1RT8CAP 16.63 + LO BNDSET1 2RT8CAP 8. + LO BNDSET1 3RT8CAP 4. + FX BNDSET1 1RTYCAP 6.3 + FX BNDSET1 2RTYCAP 4.9 + FX BNDSET1 3RTYCAP 4.2 + FX BNDSET1 1R50CAP 4. + LO BNDSET1 2R50CAP 2. + LO BNDSET1 3R50CAP 1. + FX BNDSET1 1R53CAP 34.019989 + LO BNDSET1 2R53CAP 17. + LO BNDSET1 3R53CAP 8.5 + FX BNDSET1 1R57CAP 157.73 + LO BNDSET1 2R57CAP 80. + LO BNDSET1 3R57CAP 40. + FX BNDSET1 1R58CAP 26.34 + LO BNDSET1 2R58CAP 13. + LO BNDSET1 3R58CAP 6.5 + UP BNDSET1 2R5ACAP .09 + UP BNDSET1 3R5ACAP .18 + FX BNDSET1 1T80CAP 8.32 + FX BNDSET1 1T8FCAP 754.629883 + FX BNDSET1 2T8FCAP 728.629883 + FX BNDSET1 3T8FCAP 702.629883 + FX BNDSET1 1S06CAP 555. + FX BNDSET1 2S06CAP 229. + FX BNDSET1 3S06CAP 153. + UP BNDSET1 1S08CAP 115. + UP BNDSET1 2S08CAP 384. + UP BNDSET1 3S08CAP 458. + FX BNDSET1 1S79CAP 1457. + UP BNDSET1 2S79CAP 1840. + UP BNDSET1 3S79CAP 2060. + FX BNDSET1 1S7ACAP 3640. + UP BNDSET1 2S7ACAP 4967. + UP BNDSET1 3S7ACAP 4290. + FX BNDSET1 1EC1CAP 9.536 + FX BNDSET1 2EC1CAP 4.392 + FX BNDSET1 3EC1CAP .622 + FX BNDSET1 1EC2CAP 35.288 + FX BNDSET1 2EC2CAP 34.874 + FX BNDSET1 3EC2CAP 33.635986 + LO BNDSET1 3EC3CAP 1.875 + FX BNDSET1 1EP1CAP 12.355 + FX BNDSET1 2EP1CAP 14.817 + LO BNDSET1 2E14CAP 3.109 + FX BNDSET1 1E22CAP 3.727 + FX BNDSET1 2E22CAP 3.727 + FX BNDSET1 3E22CAP 2.906 + FX BNDSET1 1E23CAP 2. + FX BNDSET1 2E23CAP 5.112 + FX BNDSET1 3E23CAP 7.592 + UP BNDSET1 1E31CAP 1.686 + UP BNDSET1 2E31CAP 1.686 + UP BNDSET1 3E31CAP 1.686 + UP BNDSET1 2E35CAP .005 + UP BNDSET1 3E35CAP 1. + UP BNDSET1 3E60CAP 3. + FX BNDSET1 1E51CAP 1.3 + UP BNDSET1 2E51CAP 1.301 + UP BNDSET1 3E51CAP 1.301 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenet.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenet.mps new file mode 100644 index 000000000..2dfc38d8f --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenet.mps @@ -0,0 +1,34 @@ +NAME galenet +ROWS + L S1 + L S2 + L S3 + E NODE4 + E NODE5 + G D6 + G D7 + G D8 + N COST +COLUMNS + T14 S1 1. NODE4 1. + T24 S2 1. NODE4 1. + T25 S2 1. NODE5 1. + T35 S3 1. NODE5 1. + T46 D6 1. NODE4 -1. + T47 D7 1. NODE4 -1. + T57 D7 1. NODE5 -1. + T58 D8 1. NODE5 -1. +RHS + RHS S1 20. S2 20. + RHS S3 20. D6 10. + RHS D7 20. D8 30. +BOUNDS + UP BND T14 30. + UP BND T24 20. + UP BND T25 10. + UP BND T35 10. + UP BND T46 10. + UP BND T47 2. + UP BND T57 20. + UP BND T58 30. +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenetbnds.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenetbnds.mps new file mode 100644 index 000000000..393e174f1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/galenetbnds.mps @@ -0,0 +1,81 @@ +* Modified galenet with equalities converted to a pair of inequalities and +* implicit bounds converted to explicit inequalities. All inequalities then +* converted to less than. In other words, the classic canonical form for +* conversion to dual, so that we can do an algebraic test of getDualRays +* for solvers that don't return the column components. +NAME galenetbnds +ROWS + L S1 + L S2 + L S3 + L NODE4U + L NODE4L + L NODE5U + L NODE5L + L D6 + L D7 + L D8 + L T14UB + L T14LB + L T24UB + L T24LB + L T25UB + L T25LB + L T35UB + L T35LB + L T46UB + L T46LB + L T47UB + L T47LB + L T57UB + L T57LB + L T58UB + L T58LB + N COST +COLUMNS + T14 S1 1. NODE4U 1. + T14 NODE4L -1 + T14 T14UB 1. T14LB -1. + T24 S2 1. NODE4U 1. + T24 NODE4L -1 + T24 T24UB 1. T24LB -1. + T25 S2 1. NODE5U 1. + T25 NODE5L -1. + T25 T25UB 1. T25LB -1. + T35 S3 1. NODE5U 1. + T35 NODE5L -1. + T35 T35UB 1. T35LB -1. + T46 D6 -1. NODE4U -1. + T46 NODE4L 1 + T46 T46UB 1. T46LB -1. + T47 D7 -1. NODE4U -1. + T47 NODE4L 1 + T47 T47UB 1. T47LB -1. + T57 D7 -1. NODE5U -1. + T57 NODE5L 1. + T57 T57UB 1. T57LB -1. + T58 D8 -1. NODE5U -1. + T58 NODE5L 1. + T58 T58UB 1. T58LB -1. +RHS + RHS S1 20. S2 20. + RHS S3 20. D6 -10. + RHS D7 -20. D8 -30. + RHS T14UB 30. + RHS T24UB 20. + RHS T25UB 10. + RHS T35UB 10. + RHS T46UB 10. + RHS T47UB 2. + RHS T57UB 20. + RHS T58UB 30. +BOUNDS + FR BND T14 + FR BND T24 + FR BND T25 + FR BND T35 + FR BND T46 + FR BND T47 + FR BND T57 + FR BND T58 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/hello.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/hello.mps new file mode 100644 index 000000000..9c9b117f8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/hello.mps @@ -0,0 +1,263 @@ +NAME Hello +ROWS + N OBJROW + L R0000000 + L R0000001 + L R0000002 + L R0000003 + L R0000004 + L R0000005 + L R0000006 + L R0000007 + L R0000008 + L R0000009 + L R0000010 + L R0000011 + L R0000012 + L R0000013 + L R0000014 + L R0000015 + L R0000016 + L R0000017 + L R0000018 + L R0000019 + L R0000020 +COLUMNS + C0000000 OBJROW 1. R0000000 1. + C0000000 R0000001 1. R0000002 1. + C0000000 R0000003 1. R0000004 1. + C0000000 R0000005 1. R0000006 1. + C0000000 R0000007 1. R0000008 1. + C0000000 R0000011 1. R0000012 1. + C0000000 R0000013 1. R0000014 1. + C0000000 R0000015 1. R0000016 1. + C0000000 R0000017 1. + C0000001 OBJROW 1. R0000004 1. + C0000001 R0000018 1. + C0000002 OBJROW 1. R0000004 1. + C0000002 R0000019 1. + C0000003 OBJROW 1. R0000004 1. + C0000003 R0000018 1. + C0000004 OBJROW 1. R0000004 1. + C0000004 R0000017 1. + C0000005 OBJROW 1. R0000004 1. + C0000005 R0000018 1. + C0000006 OBJROW 1. R0000004 1. + C0000006 R0000019 1. + C0000007 OBJROW 1. R0000004 1. + C0000007 R0000018 1. + C0000008 OBJROW 1. R0000000 1. + C0000008 R0000001 1. R0000002 1. + C0000008 R0000003 1. R0000004 1. + C0000008 R0000005 1. R0000006 1. + C0000008 R0000007 1. R0000008 1. + C0000008 R0000011 1. R0000012 1. + C0000008 R0000013 1. R0000014 1. + C0000008 R0000015 1. R0000016 1. + C0000008 R0000017 1. + C0000009 OBJROW 1. + C0000010 OBJROW 1. + C0000011 OBJROW 1. R0000000 1. + C0000011 R0000001 1. R0000002 1. + C0000011 R0000003 1. R0000004 1. + C0000011 R0000005 1. R0000006 1. + C0000011 R0000007 1. R0000008 1. + C0000011 R0000013 1. R0000014 1. + C0000011 R0000015 1. R0000016 1. + C0000011 R0000017 1. + C0000012 OBJROW 1. R0000000 1. + C0000012 R0000004 1. R0000008 1. + C0000012 R0000012 1. R0000018 1. + C0000013 OBJROW 1. R0000000 1. + C0000013 R0000004 1. R0000008 1. + C0000013 R0000011 1. R0000019 1. + C0000014 OBJROW 1. R0000000 1. + C0000014 R0000004 1. R0000008 1. + C0000014 R0000011 1. R0000019 1. + C0000015 OBJROW 1. R0000000 1. + C0000015 R0000004 1. R0000008 1. + C0000015 R0000011 1. R0000019 1. + C0000016 OBJROW 1. R0000000 1. + C0000016 R0000004 1. R0000008 1. + C0000016 R0000011 1. R0000019 1. + C0000017 OBJROW 1. R0000000 1. + C0000017 R0000008 1. R0000011 1. + C0000017 R0000019 1. + C0000018 OBJROW 1. R0000000 1. + C0000018 R0000008 1. R0000012 1. + C0000018 R0000018 1. + C0000019 OBJROW 1. R0000000 1. + C0000019 R0000008 1. R0000013 1. + C0000019 R0000014 1. R0000015 1. + C0000019 R0000016 1. R0000017 1. + C0000020 OBJROW 1. + C0000021 OBJROW 1. + C0000022 OBJROW 1. R0000000 1. + C0000022 R0000001 1. R0000002 1. + C0000022 R0000003 1. R0000004 1. + C0000022 R0000005 1. R0000006 1. + C0000022 R0000007 1. R0000008 1. + C0000022 R0000011 1. R0000012 1. + C0000022 R0000013 1. R0000014 1. + C0000022 R0000015 1. R0000016 1. + C0000022 R0000017 1. R0000018 1. + C0000022 R0000019 1. + C0000023 OBJROW 1. R0000008 1. + C0000023 R0000011 1. R0000015 1. + C0000024 OBJROW 1. R0000008 1. + C0000024 R0000011 1. R0000015 1. + C0000025 OBJROW 1. R0000008 1. + C0000025 R0000011 1. R0000015 1. + C0000025 R0000016 1. + C0000026 OBJROW 1. R0000008 1. + C0000026 R0000011 1. R0000015 1. + C0000026 R0000017 1. + C0000027 OBJROW 1. R0000008 1. + C0000027 R0000012 1. R0000014 1. + C0000027 R0000018 1. + C0000028 OBJROW 1. R0000008 1. + C0000028 R0000013 1. R0000014 1. + C0000028 R0000019 1. + C0000029 OBJROW 1. R0000008 1. + C0000030 OBJROW 1. R0000008 1. + C0000031 OBJROW 1. + C0000032 OBJROW 1. + C0000033 OBJROW 1. R0000000 1. + C0000033 R0000001 1. R0000002 1. + C0000033 R0000003 1. R0000004 1. + C0000033 R0000005 1. R0000006 1. + C0000033 R0000007 1. R0000008 1. + C0000033 R0000011 1. R0000012 1. + C0000033 R0000013 1. R0000014 1. + C0000033 R0000015 1. R0000016 1. + C0000033 R0000017 1. R0000018 1. + C0000033 R0000019 1. + C0000034 OBJROW 1. R0000008 1. + C0000034 R0000019 1. + C0000035 OBJROW 1. R0000008 1. + C0000035 R0000019 1. + C0000036 OBJROW 1. R0000008 1. + C0000036 R0000019 1. + C0000037 OBJROW 1. R0000008 1. + C0000037 R0000019 1. + C0000038 OBJROW 1. R0000008 1. + C0000038 R0000019 1. + C0000039 OBJROW 1. R0000008 1. + C0000039 R0000019 1. + C0000040 OBJROW 1. R0000008 1. + C0000040 R0000019 1. + C0000041 OBJROW 1. R0000008 1. + C0000041 R0000019 1. + C0000042 OBJROW 1. + C0000043 OBJROW 1. + C0000044 OBJROW 1. R0000002 1. + C0000044 R0000003 1. R0000004 1. + C0000044 R0000005 1. R0000006 1. + C0000044 R0000011 1. R0000012 1. + C0000044 R0000013 1. R0000014 1. + C0000044 R0000015 1. R0000016 1. + C0000044 R0000017 1. R0000018 1. + C0000044 R0000019 1. + C0000045 OBJROW 1. R0000001 1. + C0000045 R0000007 1. R0000011 1. + C0000045 R0000019 1. + C0000046 OBJROW 1. R0000000 1. + C0000046 R0000008 1. R0000011 1. + C0000046 R0000019 1. + C0000047 OBJROW 1. R0000000 1. + C0000047 R0000008 1. R0000011 1. + C0000047 R0000019 1. + C0000048 OBJROW 1. R0000000 1. + C0000048 R0000008 1. R0000011 1. + C0000048 R0000019 1. + C0000049 OBJROW 1. R0000000 1. + C0000049 R0000008 1. R0000012 1. + C0000049 R0000018 1. + C0000050 OBJROW 1. R0000000 1. + C0000050 R0000008 1. R0000013 1. + C0000050 R0000017 1. + C0000051 OBJROW 1. R0000001 1. + C0000051 R0000007 1. R0000014 1. + C0000051 R0000015 1. R0000016 1. + C0000052 OBJROW 1. R0000002 1. + C0000052 R0000003 1. R0000004 1. + C0000052 R0000005 1. R0000006 1. +RHS + RHS R0000000 1. R0000001 1. + RHS R0000002 1. R0000003 1. + RHS R0000004 1. R0000005 1. + RHS R0000006 1. R0000007 1. + RHS R0000008 1. R0000009 1. + RHS R0000010 1. R0000011 1. + RHS R0000012 1. R0000013 1. + RHS R0000014 1. R0000015 1. + RHS R0000016 1. R0000017 1. + RHS R0000018 1. R0000019 1. + RHS R0000020 1. +RANGES + RANGE R0000000 1. R0000001 1. + RANGE R0000002 1. R0000003 1. + RANGE R0000004 1. R0000005 1. + RANGE R0000006 1. R0000007 1. + RANGE R0000008 1. R0000009 1. + RANGE R0000010 1. R0000011 1. + RANGE R0000012 1. R0000013 1. + RANGE R0000014 1. R0000015 1. + RANGE R0000016 1. R0000017 1. + RANGE R0000018 1. R0000019 1. + RANGE R0000020 1. +BOUNDS + UP BOUND C0000000 1. + UP BOUND C0000001 1. + UP BOUND C0000002 1. + UP BOUND C0000003 1. + UP BOUND C0000004 1. + UP BOUND C0000005 1. + UP BOUND C0000006 1. + UP BOUND C0000007 1. + UP BOUND C0000008 1. + UP BOUND C0000009 1. + UP BOUND C0000010 1. + UP BOUND C0000011 1. + UP BOUND C0000012 1. + UP BOUND C0000013 1. + UP BOUND C0000014 1. + UP BOUND C0000015 1. + UP BOUND C0000016 1. + UP BOUND C0000017 1. + UP BOUND C0000018 1. + UP BOUND C0000019 1. + UP BOUND C0000020 1. + UP BOUND C0000021 1. + UP BOUND C0000022 1. + UP BOUND C0000023 1. + UP BOUND C0000024 1. + UP BOUND C0000025 1. + UP BOUND C0000026 1. + UP BOUND C0000027 1. + UP BOUND C0000028 1. + UP BOUND C0000029 1. + UP BOUND C0000030 1. + UP BOUND C0000031 1. + UP BOUND C0000032 1. + UP BOUND C0000033 1. + UP BOUND C0000034 1. + UP BOUND C0000035 1. + UP BOUND C0000036 1. + UP BOUND C0000037 1. + UP BOUND C0000038 1. + UP BOUND C0000039 1. + UP BOUND C0000040 1. + UP BOUND C0000041 1. + UP BOUND C0000042 1. + UP BOUND C0000043 1. + UP BOUND C0000044 1. + UP BOUND C0000045 1. + UP BOUND C0000046 1. + UP BOUND C0000047 1. + UP BOUND C0000048 1. + UP BOUND C0000049 1. + UP BOUND C0000050 1. + UP BOUND C0000051 1. + UP BOUND C0000052 1. +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/input.130 b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/input.130 new file mode 100644 index 000000000..79f0a92c0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/input.130 @@ -0,0 +1,13508 @@ +BEGIN +NETGEN PROBLEM 130 5000 NODES AND 12500 ARCS +USER: 25440925 500 500 1 100 250000 +DATA: 500 500 0 100 1 1000 +SUPPLY + 1 223 + 2 220 + 3 1103 + 4 75 + 5 800 + 6 392 + 7 132 + 8 622 + 9 309 + 10 145 + 11 113 + 12 206 + 13 427 + 14 480 + 15 797 + 16 963 + 17 339 + 18 865 + 19 826 + 20 1291 + 21 117 + 22 481 + 23 547 + 24 837 + 25 935 + 26 34 + 27 354 + 28 390 + 29 1016 + 30 934 + 31 693 + 32 411 + 33 137 + 34 800 + 35 48 + 36 854 + 37 817 + 38 756 + 39 523 + 40 1074 + 41 507 + 42 440 + 43 256 + 44 22 + 45 569 + 46 341 + 47 410 + 48 129 + 49 1269 + 50 570 + 51 456 + 52 320 + 53 415 + 54 105 + 55 445 + 56 863 + 57 104 + 58 620 + 59 300 + 60 286 + 61 435 + 62 87 + 63 97 + 64 435 + 65 773 + 66 137 + 67 99 + 68 792 + 69 544 + 70 558 + 71 275 + 72 467 + 73 350 + 74 477 + 75 1231 + 76 486 + 77 773 + 78 422 + 79 526 + 80 402 + 81 602 + 82 262 + 83 321 + 84 1135 + 85 459 + 86 915 + 87 505 + 88 193 + 89 1133 + 90 500 + 91 742 + 92 403 + 93 442 + 94 1077 + 95 552 + 96 398 + 97 292 + 98 1180 + 99 449 + 100 618 + 101 623 + 102 695 + 103 312 + 104 447 + 105 420 + 106 758 + 107 880 + 108 846 + 109 694 + 110 804 + 111 411 + 112 299 + 113 395 + 114 120 + 115 702 + 116 269 + 117 703 + 118 619 + 119 172 + 120 689 + 121 341 + 122 699 + 123 735 + 124 4 + 125 764 + 126 735 + 127 271 + 128 564 + 129 28 + 130 32 + 131 822 + 132 654 + 133 561 + 134 644 + 135 621 + 136 392 + 137 964 + 138 108 + 139 394 + 140 1149 + 141 284 + 142 433 + 143 346 + 144 168 + 145 982 + 146 790 + 147 469 + 148 287 + 149 427 + 150 763 + 151 407 + 152 323 + 153 776 + 154 1109 + 155 896 + 156 288 + 157 680 + 158 1632 + 159 385 + 160 364 + 161 1053 + 162 382 + 163 582 + 164 378 + 165 217 + 166 412 + 167 378 + 168 371 + 169 420 + 170 1017 + 171 719 + 172 24 + 173 476 + 174 692 + 175 334 + 176 426 + 177 26 + 178 71 + 179 45 + 180 97 + 181 619 + 182 803 + 183 236 + 184 293 + 185 571 + 186 497 + 187 390 + 188 451 + 189 545 + 190 524 + 191 27 + 192 402 + 193 468 + 194 721 + 195 497 + 196 584 + 197 630 + 198 755 + 199 308 + 200 853 + 201 1693 + 202 1352 + 203 224 + 204 247 + 205 688 + 206 585 + 207 334 + 208 526 + 209 399 + 210 270 + 211 826 + 212 150 + 213 472 + 214 545 + 215 275 + 216 732 + 217 675 + 218 351 + 219 897 + 220 572 + 221 270 + 222 68 + 223 843 + 224 352 + 225 395 + 226 584 + 227 192 + 228 379 + 229 325 + 230 843 + 231 105 + 232 978 + 233 446 + 234 102 + 235 315 + 236 368 + 237 293 + 238 391 + 239 816 + 240 456 + 241 490 + 242 123 + 243 146 + 244 498 + 245 595 + 246 229 + 247 761 + 248 520 + 249 1198 + 250 463 + 251 497 + 252 529 + 253 913 + 254 543 + 255 584 + 256 193 + 257 614 + 258 449 + 259 1 + 260 612 + 261 349 + 262 355 + 263 511 + 264 1586 + 265 383 + 266 192 + 267 92 + 268 842 + 269 601 + 270 39 + 271 276 + 272 363 + 273 371 + 274 53 + 275 486 + 276 348 + 277 407 + 278 647 + 279 417 + 280 1070 + 281 32 + 282 887 + 283 387 + 284 339 + 285 882 + 286 400 + 287 410 + 288 534 + 289 932 + 290 367 + 291 747 + 292 470 + 293 202 + 294 680 + 295 354 + 296 730 + 297 451 + 298 408 + 299 559 + 300 1159 + 301 153 + 302 260 + 303 689 + 304 914 + 305 83 + 306 256 + 307 52 + 308 194 + 309 1290 + 310 473 + 311 717 + 312 163 + 313 728 + 314 756 + 315 353 + 316 294 + 317 316 + 318 213 + 319 698 + 320 407 + 321 416 + 322 385 + 323 532 + 324 277 + 325 593 + 326 972 + 327 694 + 328 289 + 329 1387 + 330 296 + 331 922 + 332 184 + 333 535 + 334 1428 + 335 384 + 336 271 + 337 74 + 338 427 + 339 400 + 340 584 + 341 411 + 342 656 + 343 453 + 344 327 + 345 729 + 346 265 + 347 663 + 348 968 + 349 246 + 350 250 + 351 144 + 352 189 + 353 713 + 354 317 + 355 439 + 356 404 + 357 937 + 358 218 + 359 803 + 360 333 + 361 215 + 362 217 + 363 757 + 364 437 + 365 888 + 366 318 + 367 104 + 368 358 + 369 451 + 370 451 + 371 135 + 372 753 + 373 273 + 374 22 + 375 284 + 376 15 + 377 1020 + 378 326 + 379 436 + 380 360 + 381 389 + 382 949 + 383 311 + 384 990 + 385 75 + 386 563 + 387 481 + 388 546 + 389 455 + 390 356 + 391 496 + 392 525 + 393 682 + 394 215 + 395 632 + 396 339 + 397 91 + 398 326 + 399 8 + 400 413 + 401 448 + 402 597 + 403 854 + 404 227 + 405 337 + 406 326 + 407 402 + 408 212 + 409 265 + 410 415 + 411 239 + 412 659 + 413 603 + 414 827 + 415 28 + 416 309 + 417 384 + 418 115 + 419 386 + 420 342 + 421 523 + 422 309 + 423 204 + 424 264 + 425 632 + 426 692 + 427 930 + 428 648 + 429 404 + 430 264 + 431 1014 + 432 298 + 433 498 + 434 36 + 435 141 + 436 957 + 437 574 + 438 507 + 439 257 + 440 531 + 441 1178 + 442 689 + 443 445 + 444 422 + 445 1222 + 446 404 + 447 516 + 448 298 + 449 359 + 450 196 + 451 394 + 452 412 + 453 276 + 454 484 + 455 635 + 456 204 + 457 826 + 458 169 + 459 361 + 460 906 + 461 1143 + 462 484 + 463 670 + 464 248 + 465 94 + 466 109 + 467 506 + 468 718 + 469 381 + 470 1110 + 471 414 + 472 1002 + 473 327 + 474 452 + 475 379 + 476 315 + 477 1012 + 478 572 + 479 421 + 480 653 + 481 492 + 482 485 + 483 91 + 484 667 + 485 793 + 486 192 + 487 631 + 488 404 + 489 635 + 490 60 + 491 252 + 492 739 + 493 117 + 494 412 + 495 804 + 496 472 + 497 672 + 498 833 + 499 1251 + 500 638 +ARCS + 1 1890 47 223 + 1 1745 90 194 + 1 2252 68 612 + 505 3498 71 223 + 505 4707 94 223 + 505 2628 71 375 + 941 3285 33 223 + 941 649 1 308 + 941 1930 21 351 + 1730 2231 5 223 + 1730 2634 42 263 + 1730 167 50 156 + 1890 505 61 223 + 1890 1204 93 959 + 2231 4450 90 223 + 2231 1227 77 670 + 2231 2893 61 898 + 3285 1730 90 223 + 3285 2960 2 572 + 3285 2496 79 227 + 3498 941 63 223 + 3498 570 14 579 + 3498 3089 5 165 + 4450 4932 35 223 + 4450 2364 18 89 + 4450 1331 34 61 + 2 3149 96 220 + 2 4853 6 753 + 1256 3667 25 220 + 1256 4279 83 645 + 1256 3207 53 466 + 2358 4513 73 220 + 2358 202 63 151 + 2770 4472 36 220 + 2770 2837 91 401 + 3149 3856 15 220 + 3149 1948 55 604 + 3149 2839 94 172 + 3667 2358 69 220 + 3667 3172 12 305 + 3667 3591 70 846 + 3856 4243 52 220 + 3856 4684 33 220 + 3856 3273 39 430 + 4243 2770 30 220 + 4243 837 85 347 + 4243 4038 95 343 + 4472 1256 78 220 + 4472 2370 2 984 + 3 3225 42 1103 + 3 2531 61 326 + 3 433 2 3 + 2280 3684 82 1103 + 2280 715 53 919 + 2280 514 41 275 + 2608 3932 17 1103 + 2608 2138 64 293 + 2608 1694 49 504 + 3225 3734 36 1103 + 3225 3688 86 893 + 3365 2280 5 1103 + 3365 4245 17 654 + 3684 2608 99 1103 + 3684 4319 1 377 + 3684 1271 64 104 + 3734 3365 72 1103 + 3734 4578 94 1103 + 3734 3581 65 175 + 3734 484 57 539 + 3932 4774 95 1103 + 3932 820 31 479 + 3932 3144 36 30 + 4 3408 51 75 + 4 1634 14 68 + 4 4261 21 402 + 683 4122 86 75 + 683 4788 98 75 + 683 4142 75 57 + 683 1337 77 506 + 1857 2877 31 75 + 1857 2111 22 479 + 1857 1672 7 908 + 2160 683 89 75 + 2160 1842 56 797 + 2877 4822 46 75 + 2877 4887 67 45 + 3408 2160 24 75 + 3408 2475 7 705 + 3408 2044 30 727 + 4122 1857 35 75 + 4122 1102 23 480 + 5 2037 20 800 + 5 3900 58 72 + 5 4855 99 527 + 859 4848 37 800 + 859 2944 29 40 + 859 3611 46 806 + 864 859 51 800 + 864 1514 29 725 + 864 360 95 421 + 1516 4074 39 800 + 1516 878 3 910 + 1516 890 53 47 + 1950 864 16 800 + 1950 4648 80 800 + 1950 1965 76 897 + 2037 3311 71 800 + 2037 2166 99 478 + 3311 1516 44 800 + 3311 104 62 576 + 3311 4481 77 158 + 3786 1950 38 800 + 3786 159 38 685 + 3786 3893 27 47 + 4074 3786 24 800 + 4074 2348 71 720 + 6 1315 57 392 + 6 3193 78 763 + 521 2260 90 392 + 521 3029 27 210 + 1315 2412 30 392 + 1315 2691 77 852 + 1315 3526 24 565 + 2260 2737 62 392 + 2260 4233 61 486 + 2412 4019 99 392 + 2412 1325 75 322 + 2412 488 44 558 + 2641 4464 38 392 + 2641 4649 45 756 + 2641 1336 25 238 + 2737 2641 25 392 + 2737 3789 14 65 + 2737 378 43 616 + 2818 4008 20 392 + 2818 1081 19 814 + 2818 280 5 694 + 4008 521 1 392 + 4008 3922 48 516 + 4019 2818 83 392 + 4019 4776 12 392 + 4019 1938 65 532 + 4464 4634 88 392 + 4464 305 23 632 + 7 3805 73 132 + 7 2369 76 718 + 714 3037 87 132 + 714 1258 71 90 + 2715 4016 11 132 + 2715 4484 79 988 + 2715 1299 58 621 + 3037 4663 68 132 + 3037 3922 34 170 + 3037 2295 45 980 + 3733 2715 72 132 + 3733 1463 6 424 + 3805 4205 17 132 + 3805 4730 76 132 + 3805 3271 56 196 + 4016 714 24 132 + 4016 1210 69 380 + 4016 2371 61 209 + 4205 3733 90 132 + 4205 2075 10 677 + 4205 4365 95 361 + 8 2573 32 622 + 8 265 96 567 + 8 2946 23 597 + 1265 1299 50 622 + 1265 1230 18 451 + 1299 3374 13 622 + 1299 4280 61 408 + 1299 459 59 186 + 1326 4821 7 622 + 1326 4788 37 622 + 1326 1052 47 231 + 1326 1812 100 433 + 2573 3698 82 622 + 2573 1276 99 401 + 3374 1326 52 622 + 3374 4855 58 489 + 3698 1265 46 622 + 3698 653 41 113 + 9 2743 8 309 + 9 721 55 372 + 580 1398 98 309 + 580 4563 16 33 + 580 3738 66 973 + 1226 4640 45 309 + 1226 4243 80 667 + 1398 3675 94 309 + 1398 229 78 249 + 2203 2594 68 309 + 2203 4043 16 851 + 2203 857 37 514 + 2291 3081 63 309 + 2291 2627 94 252 + 2291 3559 89 982 + 2594 2291 34 309 + 2594 4656 12 309 + 2594 745 54 682 + 2602 2203 55 309 + 2602 3319 91 771 + 2743 580 13 309 + 2743 3750 42 94 + 3081 1226 65 309 + 3081 570 53 162 + 3675 2602 55 309 + 3675 1871 59 328 + 10 928 55 145 + 10 2851 51 732 + 10 2902 16 315 + 699 3326 64 145 + 699 4752 53 10 + 928 4458 11 145 + 928 4497 82 450 + 928 952 66 863 + 1663 3769 59 145 + 1663 576 49 256 + 3326 3817 47 145 + 3326 4344 69 141 + 3326 3536 30 702 + 3550 3867 34 145 + 3550 3793 41 534 + 3769 3550 82 145 + 3769 4795 92 145 + 3769 2302 9 817 + 3769 3809 88 349 + 3817 4596 68 145 + 3817 1627 100 326 + 3867 699 20 145 + 3867 2216 13 13 + 3867 1415 17 931 + 4458 1663 79 145 + 4458 3546 100 624 + 11 609 79 113 + 11 3674 75 260 + 11 4712 21 389 + 609 3975 63 113 + 609 2367 41 146 + 2190 2966 39 113 + 2190 3788 100 811 + 2190 4752 39 12 + 2748 3889 15 113 + 2748 2441 26 516 + 2748 3825 74 667 + 2832 3236 45 113 + 2832 4130 47 134 + 2832 447 34 941 + 2966 3963 54 113 + 2966 4560 94 189 + 3236 2748 40 113 + 3236 2307 22 333 + 3236 4629 41 916 + 3889 2190 35 113 + 3889 4118 48 172 + 3963 4524 42 113 + 3963 4739 30 113 + 3963 1077 38 589 + 3975 2832 7 113 + 3975 578 97 293 + 3975 4418 45 880 + 12 1959 7 206 + 12 321 43 854 + 12 586 28 298 + 1959 3989 66 206 + 1959 3783 74 508 + 2413 4730 1 206 + 2413 3221 5 206 + 2413 4688 34 37 + 2990 2413 32 206 + 2990 2386 68 56 + 2990 833 78 110 + 3039 4107 89 206 + 3039 4793 57 106 + 3039 328 60 358 + 3221 3484 4 206 + 3221 3605 4 179 + 3484 3760 86 206 + 3484 2298 80 497 + 3484 1964 55 761 + 3760 4518 38 206 + 3760 2698 94 508 + 3760 1927 66 694 + 3989 3039 30 206 + 3989 2577 34 305 + 4107 2990 48 206 + 4107 1964 22 218 + 4107 4722 21 276 + 13 3789 28 427 + 13 4977 8 84 + 741 2359 47 427 + 741 2114 26 351 + 741 1350 97 675 + 1090 4651 98 427 + 1090 2134 7 137 + 1090 1865 14 820 + 1551 3036 87 427 + 1551 1157 80 775 + 1551 3476 70 230 + 1885 1551 30 427 + 1885 4891 34 214 + 2359 3956 22 427 + 2359 3563 23 54 + 2799 741 11 427 + 2799 1066 32 84 + 2799 2255 33 447 + 3036 1090 9 427 + 3036 4640 52 427 + 3036 4898 55 884 + 3789 2799 23 427 + 3789 4552 85 207 + 3956 1885 16 427 + 3956 1336 53 744 + 3956 2873 20 242 + 14 2070 1 480 + 14 4783 56 820 + 14 2062 84 32 + 2053 3584 53 480 + 2053 2633 76 657 + 2070 3088 57 480 + 2070 3355 9 217 + 2070 1278 14 707 + 2092 4916 60 480 + 2092 3997 37 842 + 3088 4181 76 480 + 3088 2766 60 763 + 3584 2092 9 480 + 3584 422 26 69 + 4181 2053 99 480 + 4181 4874 11 480 + 4181 3870 26 759 + 4181 3938 20 814 + 15 3785 3 797 + 15 2265 67 471 + 15 1304 59 113 + 587 658 87 797 + 587 3791 23 185 + 658 4110 12 797 + 658 1445 65 69 + 658 4126 90 724 + 726 857 9 797 + 726 1085 60 104 + 726 4105 95 13 + 857 587 81 797 + 857 4974 45 797 + 857 1412 66 385 + 857 4441 20 230 + 1738 4242 8 797 + 1738 2194 82 647 + 2454 4965 57 797 + 2454 8 24 559 + 3785 726 58 797 + 3785 3286 34 208 + 3785 2162 81 681 + 4110 1738 99 797 + 4110 3466 16 607 + 4110 1027 9 4 + 4242 2454 55 797 + 4242 2802 81 214 + 16 2713 68 963 + 16 2425 2 2 + 541 4655 82 963 + 541 2793 33 963 + 541 1084 57 402 + 541 1056 35 72 + 681 3351 36 963 + 681 4280 82 741 + 681 2257 100 514 + 1130 2064 54 963 + 1130 3856 17 328 + 1130 2286 1 697 + 2064 3806 7 963 + 2064 4586 90 963 + 2064 2927 44 399 + 2083 681 81 963 + 2083 4034 14 781 + 2083 3692 17 329 + 2713 541 65 963 + 2713 2456 16 2 + 2793 3811 14 963 + 2793 912 39 559 + 3331 2083 60 963 + 3331 3700 95 148 + 3351 3658 7 963 + 3351 3122 29 810 + 3351 133 72 668 + 3658 4719 51 963 + 3658 1969 21 307 + 3658 1951 62 365 + 3806 4358 21 963 + 3806 2538 53 955 + 3811 1130 55 963 + 3811 1971 12 511 + 4358 3331 71 963 + 4358 3762 84 208 + 4358 2800 67 139 + 17 3009 71 339 + 17 2373 26 939 + 17 629 3 38 + 559 2633 38 339 + 559 4107 95 887 + 1610 3588 63 339 + 1610 1247 27 480 + 1610 1184 57 133 + 1694 2652 43 339 + 1694 4901 91 766 + 1694 4972 8 139 + 1864 4981 18 339 + 1864 4836 81 339 + 1864 339 33 138 + 2633 1694 99 339 + 2633 889 72 547 + 2633 315 93 255 + 2652 4133 24 339 + 2652 3483 42 711 + 2652 1340 68 19 + 2939 1864 81 339 + 2939 2101 39 359 + 2939 431 65 368 + 3009 559 39 339 + 3009 803 90 67 + 3588 2939 76 339 + 3588 2656 97 123 + 4133 1610 64 339 + 4133 4576 39 371 + 18 1662 78 865 + 18 3741 4 401 + 1155 4588 18 865 + 1155 3272 11 356 + 1662 4901 87 865 + 1662 4432 57 865 + 1662 4319 77 186 + 1676 3847 25 865 + 1676 3898 33 556 + 1911 2680 76 865 + 1911 177 35 495 + 2680 1676 99 865 + 2680 832 52 121 + 3847 4196 77 865 + 3847 3230 26 559 + 3847 3187 28 702 + 4196 1155 95 865 + 4196 2598 36 191 + 4196 2774 99 249 + 4432 1911 40 865 + 4432 180 58 30 + 4432 499 29 222 + 19 3610 77 826 + 19 3267 7 860 + 630 1214 86 826 + 630 4134 58 353 + 845 3372 59 826 + 845 2587 22 735 + 1101 4948 81 826 + 1101 630 80 826 + 1101 3243 90 434 + 1101 1994 98 356 + 1214 845 6 826 + 1214 4503 32 965 + 2693 3346 77 826 + 2693 2633 66 44 + 2693 4799 24 88 + 3346 3482 11 826 + 3346 2527 98 789 + 3372 4925 41 826 + 3372 1536 79 31 + 3372 2936 32 283 + 3482 1101 68 826 + 3482 289 67 875 + 3610 2693 88 826 + 3610 3190 94 4 + 3610 3966 43 734 + 20 3791 46 1291 + 20 2288 69 488 + 633 2383 12 1291 + 633 209 8 673 + 1309 1441 43 1291 + 1309 521 96 478 + 1441 3428 12 1291 + 1441 3278 15 224 + 1937 4987 69 1291 + 1937 3362 84 1291 + 1937 1364 33 214 + 2383 1937 23 1291 + 2383 702 95 467 + 3234 633 14 1291 + 3234 1150 14 269 + 3362 4651 97 1291 + 3362 184 1 27 + 3428 3234 6 1291 + 3428 1060 62 583 + 3428 3282 18 76 + 3791 1309 37 1291 + 3791 4565 10 757 + 3791 2018 42 773 + 21 3582 73 117 + 21 3167 62 463 + 990 2685 74 117 + 990 4158 96 572 + 1157 3155 69 117 + 1157 143 64 275 + 1157 4362 94 767 + 1473 4815 80 117 + 1473 105 40 383 + 1473 3025 98 348 + 1669 4590 75 117 + 1669 990 55 117 + 1669 2942 83 910 + 1669 4649 90 252 + 2522 1157 65 117 + 2522 2383 54 633 + 2685 4398 10 117 + 2685 4538 35 736 + 2685 1740 8 951 + 3155 1473 31 117 + 3155 1577 38 923 + 3155 1991 29 277 + 3412 2522 61 117 + 3412 2179 74 811 + 3582 4305 92 117 + 3582 2058 42 483 + 3582 4129 98 816 + 4305 1669 25 117 + 4305 303 92 414 + 4305 221 14 989 + 4398 3412 41 117 + 4398 2947 25 871 + 22 3778 14 481 + 22 900 48 461 + 803 4738 52 481 + 803 4571 53 481 + 803 2873 28 461 + 1216 2035 5 481 + 1216 4115 99 436 + 1216 4443 79 59 + 2035 2103 31 481 + 2035 2779 90 661 + 2084 4299 100 481 + 2084 1541 3 810 + 2103 2084 22 481 + 2103 3419 73 332 + 3048 803 64 481 + 3048 4506 52 655 + 3048 1767 85 482 + 3778 1216 41 481 + 3778 4603 41 897 + 3778 657 19 61 + 4299 3048 49 481 + 4299 1121 28 860 + 4299 1549 77 724 + 23 2534 69 547 + 23 1265 74 141 + 661 1053 21 547 + 661 504 47 897 + 1053 2735 41 547 + 1053 4992 41 15 + 1053 4483 100 523 + 1191 4867 59 547 + 1191 1193 12 547 + 1191 2700 13 928 + 1191 367 28 456 + 1193 3725 40 547 + 1193 945 7 373 + 1193 4005 59 850 + 1471 1191 2 547 + 1471 4584 88 595 + 1471 83 22 739 + 2534 1471 50 547 + 2534 3661 12 715 + 2735 4966 35 547 + 2735 1322 43 577 + 3725 661 48 547 + 3725 390 27 436 + 24 4457 47 837 + 24 4668 34 873 + 24 429 17 101 + 543 1437 18 837 + 543 4928 63 837 + 543 1307 70 824 + 1437 4866 97 837 + 1437 1758 36 524 + 2372 543 9 837 + 2372 4117 28 703 + 3264 4046 64 837 + 3264 873 81 406 + 3264 1517 55 135 + 3646 3731 88 837 + 3646 2221 30 246 + 3646 4595 20 494 + 3731 3264 71 837 + 3731 927 73 792 + 3731 2397 40 747 + 4046 2372 72 837 + 4046 634 36 861 + 4046 926 7 940 + 4457 3646 25 837 + 4457 1426 97 486 + 25 2894 36 935 + 25 809 2 584 + 1206 4932 38 935 + 1206 3131 1 935 + 1206 4086 70 875 + 1236 3393 13 935 + 1236 1195 72 363 + 1729 3141 13 935 + 1729 3841 67 468 + 1729 189 31 887 + 1770 1236 95 935 + 1770 2191 51 43 + 1770 4043 54 149 + 2342 3069 57 935 + 2342 4573 96 184 + 2342 3366 88 849 + 2843 4486 66 935 + 2843 1161 65 622 + 2894 1206 82 935 + 2894 4764 73 431 + 3069 4749 13 935 + 3069 3236 31 219 + 3131 1729 96 935 + 3131 4740 55 935 + 3131 3230 14 293 + 3131 143 6 848 + 3141 2843 13 935 + 3141 3303 4 85 + 3141 4616 93 1 + 3393 2342 55 935 + 3393 1114 24 672 + 4486 1770 20 935 + 4486 512 5 844 + 4486 2383 84 593 + 26 3964 23 34 + 26 88 89 25 + 26 3771 52 111 + 766 4431 99 34 + 766 4076 65 129 + 2115 2337 3 34 + 2115 1875 91 939 + 2115 102 71 353 + 2337 2765 11 34 + 2337 313 64 715 + 2337 1718 82 771 + 2765 4223 25 34 + 2765 4771 23 34 + 2765 1325 89 827 + 2765 4937 5 9 + 2789 766 18 34 + 2789 3674 98 648 + 3802 2789 29 34 + 3802 3973 99 625 + 3964 4203 11 34 + 3964 4253 67 942 + 3964 2583 47 275 + 4203 3802 97 34 + 4203 3843 16 197 + 4203 3364 99 239 + 4223 4916 55 34 + 4223 3397 62 977 + 4431 2115 15 34 + 4431 1414 69 985 + 27 3355 77 354 + 27 318 84 121 + 713 896 84 354 + 713 585 63 56 + 896 3314 31 354 + 896 1767 100 158 + 896 1772 71 441 + 1378 713 99 354 + 1378 4414 48 118 + 2209 1378 100 354 + 2209 1751 28 819 + 2209 4077 32 969 + 2842 2209 98 354 + 2842 4558 44 549 + 3314 4737 74 354 + 3314 4566 9 354 + 3314 3610 39 894 + 3314 4266 5 773 + 3355 2842 82 354 + 3355 2738 45 279 + 28 2340 50 390 + 28 1982 54 445 + 560 2334 91 390 + 560 1510 69 633 + 560 666 92 437 + 617 2686 36 390 + 617 2587 22 779 + 645 3807 37 390 + 645 1605 62 503 + 2122 617 53 390 + 2122 2762 61 59 + 2254 3154 17 390 + 2254 333 92 864 + 2254 3435 55 473 + 2316 2122 50 390 + 2316 2518 23 763 + 2334 2316 63 390 + 2334 4267 18 674 + 2340 2254 3 390 + 2340 3061 100 179 + 2340 4507 41 202 + 2686 645 1 390 + 2686 2929 79 826 + 3154 4610 12 390 + 3154 3538 37 390 + 3154 4792 92 390 + 3154 4611 27 271 + 3538 560 84 390 + 3538 4853 93 919 + 3538 1937 27 971 + 3807 4684 37 390 + 3807 3971 68 205 + 29 1844 11 1016 + 29 3884 99 824 + 563 3095 57 1016 + 563 3829 97 843 + 1453 563 15 1016 + 1453 3142 87 591 + 1844 2592 80 1016 + 1844 2843 6 110 + 1844 709 70 88 + 1928 4776 85 1016 + 1928 2803 69 1 + 1928 3326 31 604 + 2364 1928 98 1016 + 2364 4619 42 1016 + 2364 2473 71 126 + 2592 1453 72 1016 + 2592 4521 40 601 + 2592 2724 97 701 + 3095 2364 91 1016 + 3095 4927 98 568 + 30 1010 8 934 + 30 2846 60 424 + 30 150 26 269 + 738 1858 73 934 + 738 3868 12 68 + 738 4739 86 202 + 940 2759 71 934 + 940 1583 11 131 + 1010 3657 67 934 + 1010 2971 99 250 + 1010 2032 3 138 + 1202 940 18 934 + 1202 3707 54 977 + 1354 1202 50 934 + 1354 4869 46 402 + 1354 1572 70 15 + 1858 1884 21 934 + 1858 4829 60 934 + 1858 1583 33 228 + 1884 4777 63 934 + 1884 3888 38 554 + 1884 2302 45 475 + 2759 738 44 934 + 2759 186 46 16 + 2759 1726 68 458 + 3061 1354 69 934 + 3061 3047 70 388 + 3657 3061 29 934 + 3657 428 57 154 + 31 3585 56 693 + 31 2769 78 723 + 31 2254 90 998 + 1098 2549 46 693 + 1098 4765 15 654 + 1098 2717 34 551 + 1599 3521 54 693 + 1599 4951 60 351 + 2549 1599 46 693 + 2549 2542 49 814 + 2549 598 87 50 + 3359 4623 29 693 + 3359 394 39 846 + 3521 4389 29 693 + 3521 4017 20 64 + 3585 4683 33 693 + 3585 1098 12 693 + 3585 4715 12 895 + 3585 3642 83 718 + 4389 3359 43 693 + 4389 627 94 555 + 4389 4511 6 944 + 32 2825 46 411 + 32 2989 91 980 + 32 1897 68 9 + 1288 1615 24 411 + 1288 509 25 468 + 1288 2936 80 696 + 1615 3404 97 411 + 1615 3488 41 115 + 1615 3306 54 27 + 2133 1288 99 411 + 2133 4729 87 411 + 2133 3863 73 751 + 2133 4040 71 512 + 2825 3505 95 411 + 2825 4473 53 527 + 2825 3891 46 237 + 3404 4834 67 411 + 3404 3830 29 812 + 3404 2916 24 767 + 3505 2133 65 411 + 3505 4669 14 628 + 33 1176 8 137 + 33 4361 58 798 + 721 1294 31 137 + 721 4754 31 137 + 721 3277 97 408 + 1176 2038 82 137 + 1176 602 47 250 + 1294 1347 19 137 + 1294 125 98 413 + 1347 4647 79 137 + 1347 16 91 482 + 1347 2851 87 933 + 2038 2597 16 137 + 2038 669 70 798 + 2038 4531 67 123 + 2237 721 39 137 + 2237 123 69 216 + 2237 4967 81 591 + 2597 2237 3 137 + 2597 646 54 553 + 2597 406 92 542 + 34 2794 77 800 + 34 4830 9 908 + 1621 3767 20 800 + 1621 3714 67 28 + 1973 4244 45 800 + 1973 1898 75 241 + 2046 1973 9 800 + 2046 4724 1 863 + 2046 118 52 537 + 2227 4662 37 800 + 2227 4459 22 187 + 2227 3336 40 341 + 2794 2046 89 800 + 2794 2739 90 599 + 3157 1621 49 800 + 3157 3494 34 679 + 3767 2227 16 800 + 3767 4744 7 800 + 3767 4758 63 873 + 3767 108 74 694 + 4244 3157 30 800 + 4244 415 73 281 + 4244 4987 70 88 + 35 1564 72 48 + 35 782 20 274 + 35 4287 64 419 + 1037 1934 67 48 + 1037 4996 20 12 + 1037 1692 64 363 + 1491 3086 32 48 + 1491 2746 11 353 + 1491 3621 57 92 + 1564 3918 54 48 + 1564 3481 45 900 + 1564 4688 74 847 + 1934 4622 31 48 + 1934 2244 75 48 + 1934 3761 73 563 + 2055 1491 20 48 + 2055 201 21 38 + 2244 2055 2 48 + 2244 3991 51 879 + 2244 3475 70 551 + 3086 4611 70 48 + 3086 2405 47 654 + 3274 1037 9 48 + 3274 433 64 259 + 3918 3274 18 48 + 3918 2824 7 248 + 36 1696 4 854 + 36 2848 31 1 + 36 290 28 614 + 1148 2960 84 854 + 1148 3924 89 820 + 1496 1602 49 854 + 1496 3642 4 280 + 1602 3091 60 854 + 1602 4234 70 312 + 1696 1148 93 854 + 1696 3222 15 496 + 1696 1215 7 858 + 2960 1496 96 854 + 2960 4626 61 854 + 2960 698 43 688 + 2960 2782 32 372 + 3091 4894 91 854 + 3091 628 71 276 + 3091 251 86 953 + 37 2345 91 817 + 37 3013 51 683 + 1590 4423 14 817 + 1590 2464 8 613 + 1590 1745 7 503 + 1979 4828 7 817 + 1979 2257 23 35 + 1979 4348 83 120 + 2345 1590 46 817 + 2345 3215 14 872 + 2345 1180 76 400 + 2520 2682 49 817 + 2520 4436 50 295 + 2682 2970 93 817 + 2682 4471 51 731 + 2682 4480 27 149 + 2970 1979 57 817 + 2970 4300 64 61 + 4423 2520 63 817 + 4423 4892 68 817 + 4423 725 59 15 + 4423 4290 23 799 + 38 829 79 756 + 38 3503 67 779 + 746 2810 28 756 + 746 4212 67 550 + 746 54 84 390 + 829 2542 89 756 + 829 2095 15 630 + 829 382 24 86 + 1394 746 54 756 + 1394 2185 91 484 + 1394 3163 33 187 + 1896 4834 90 756 + 1896 4926 47 756 + 1896 428 59 433 + 1896 2645 95 507 + 2397 2598 69 756 + 2397 4720 12 42 + 2542 1394 19 756 + 2542 4653 36 898 + 2542 2690 14 265 + 2598 2965 34 756 + 2598 827 96 888 + 2810 2397 62 756 + 2810 4491 48 6 + 2810 1478 99 113 + 2965 1896 96 756 + 2965 845 75 851 + 2965 4859 48 396 + 39 2567 59 523 + 39 3648 49 726 + 39 3825 63 948 + 1054 3118 44 523 + 1054 1625 1 467 + 2567 3818 45 523 + 2567 2959 89 834 + 2567 1602 93 144 + 3118 3873 31 523 + 3118 4637 28 523 + 3118 3543 50 330 + 3118 4222 45 497 + 3818 1054 76 523 + 3818 4726 100 727 + 3818 98 70 6 + 3873 4970 91 523 + 3873 2000 95 380 + 3873 635 45 472 + 40 4274 99 1074 + 40 2809 28 357 + 725 4100 70 1074 + 725 4451 64 946 + 1654 2888 92 1074 + 1654 1221 24 529 + 1654 2703 58 368 + 2047 4607 100 1074 + 2047 3772 63 212 + 2047 4680 88 842 + 2888 2047 48 1074 + 2888 4876 3 623 + 2888 1160 22 191 + 3909 725 19 1074 + 3909 3232 1 840 + 4100 1654 88 1074 + 4100 4706 56 1074 + 4100 203 43 426 + 4100 1749 25 426 + 4274 3909 39 1074 + 4274 2248 63 485 + 41 3449 56 507 + 41 397 81 544 + 41 1861 20 632 + 1081 1616 4 507 + 1081 4 39 423 + 1106 4774 87 507 + 1106 3689 13 783 + 1106 1812 71 237 + 1483 1618 41 507 + 1483 890 28 476 + 1483 3393 73 447 + 1616 1752 9 507 + 1616 1551 61 983 + 1618 3105 35 507 + 1618 4080 7 261 + 1618 4920 57 111 + 1625 1982 62 507 + 1625 4272 65 195 + 1736 4597 94 507 + 1736 4516 7 507 + 1736 1625 52 507 + 1736 503 80 731 + 1736 3257 4 361 + 1752 1483 82 507 + 1752 3205 51 988 + 1752 3889 98 222 + 1982 2524 22 507 + 1982 4474 87 611 + 2524 1081 37 507 + 2524 389 35 262 + 2524 1375 34 833 + 3105 1106 81 507 + 3105 4638 20 238 + 3105 804 25 188 + 3449 1736 97 507 + 3449 2279 80 137 + 3449 1044 15 141 + 42 2077 67 440 + 42 4332 100 141 + 613 4919 27 440 + 613 1899 66 519 + 1681 4160 91 440 + 1681 3786 56 163 + 2077 2706 40 440 + 2077 959 30 200 + 2077 3667 35 424 + 2197 613 21 440 + 2197 4641 64 440 + 2197 4096 22 518 + 2706 1681 85 440 + 2706 2325 81 152 + 3106 2197 52 440 + 3106 1384 4 469 + 3106 2615 19 359 + 4160 3106 82 440 + 4160 2284 21 160 + 43 2021 87 256 + 43 1635 22 683 + 43 1329 26 210 + 823 2089 78 256 + 823 2676 33 796 + 1503 4794 79 256 + 1503 2656 65 256 + 1503 4115 14 196 + 1503 2627 64 743 + 2021 2915 9 256 + 2021 4760 25 425 + 2021 4047 75 325 + 2089 1503 96 256 + 2089 3708 89 189 + 2089 2977 15 488 + 2208 4700 55 256 + 2208 445 73 623 + 2208 303 37 855 + 2656 2208 66 256 + 2656 3339 96 872 + 2915 823 55 256 + 2915 4917 69 269 + 2915 1994 100 708 + 44 690 67 22 + 44 1066 29 199 + 44 3296 48 687 + 626 2181 71 22 + 626 4649 76 22 + 626 1886 27 838 + 690 626 82 22 + 690 3598 71 335 + 690 3316 1 596 + 1905 3323 3 22 + 1905 3004 1 985 + 1905 1010 23 51 + 2181 2343 2 22 + 2181 2100 89 716 + 2181 3750 62 955 + 2343 1905 50 22 + 2343 2871 89 974 + 2343 2443 38 573 + 3323 3702 59 22 + 3323 3031 95 425 + 3702 4206 93 22 + 3702 841 45 19 + 4206 4650 76 22 + 4206 1552 27 596 + 4206 2502 71 17 + 45 1079 52 569 + 45 922 37 300 + 592 4803 16 569 + 592 3624 25 48 + 592 3722 80 88 + 706 592 9 569 + 706 3615 46 729 + 768 4076 30 569 + 768 1924 18 215 + 768 2998 6 202 + 819 706 95 569 + 819 3972 72 985 + 819 4224 52 352 + 1079 4889 8 569 + 1079 768 87 569 + 1079 1151 79 131 + 1702 819 65 569 + 1702 3541 7 483 + 1887 2437 49 569 + 1887 3033 80 429 + 2437 1702 10 569 + 2437 3282 86 449 + 2437 4751 33 886 + 4076 1887 5 569 + 4076 2663 8 711 + 46 2891 93 341 + 46 4458 48 81 + 1022 4972 75 341 + 1022 1045 49 341 + 1022 2418 13 953 + 1045 3912 39 341 + 1045 1869 58 256 + 1493 3248 33 341 + 1493 4138 65 397 + 1787 1493 66 341 + 1787 3113 64 654 + 2891 3467 7 341 + 2891 1947 32 398 + 3248 4700 90 341 + 3248 4937 49 804 + 3248 4185 15 223 + 3467 1022 94 341 + 3467 3537 87 390 + 3467 536 28 396 + 3912 1787 55 341 + 3912 3383 6 358 + 47 2683 39 410 + 47 320 49 882 + 679 3860 94 410 + 679 1966 27 118 + 679 3483 57 990 + 1308 4580 34 410 + 1308 3612 16 410 + 1308 1960 24 827 + 1308 2161 52 838 + 2683 679 79 410 + 2683 3492 19 918 + 3001 1308 2 410 + 3001 3893 68 788 + 3612 4286 44 410 + 3612 4230 45 461 + 3612 4093 40 20 + 3674 4979 37 410 + 3674 896 44 524 + 3674 1309 41 196 + 3860 3001 38 410 + 3860 1443 87 266 + 3860 2255 66 81 + 4232 3674 67 410 + 4232 3687 59 364 + 4232 1782 10 109 + 4286 4232 15 410 + 4286 392 51 959 + 48 2385 11 129 + 48 707 31 118 + 729 3792 77 129 + 729 2665 82 588 + 729 4717 23 809 + 2385 3960 91 129 + 2385 769 58 905 + 2385 1296 84 628 + 2387 4887 70 129 + 2387 1475 92 175 + 2869 4168 20 129 + 2869 1753 77 91 + 2869 151 16 373 + 3503 2869 85 129 + 3503 650 94 423 + 3503 613 24 725 + 3792 2387 7 129 + 3792 2555 42 906 + 3960 4888 59 129 + 3960 4322 93 129 + 3960 4948 81 708 + 3960 2367 25 551 + 4036 3503 77 129 + 4036 2959 34 506 + 4168 729 95 129 + 4168 4034 33 89 + 4168 266 88 723 + 4322 4036 88 129 + 4322 3 21 160 + 4322 4094 48 418 + 49 831 52 1269 + 49 4763 79 982 + 49 112 59 271 + 518 1259 68 1269 + 518 617 70 841 + 518 1359 70 261 + 831 4098 33 1269 + 831 1415 41 93 + 1170 2605 6 1269 + 1170 3414 3 114 + 1182 518 28 1269 + 1182 4911 59 649 + 1259 1726 31 1269 + 1259 4868 38 770 + 1671 4705 51 1269 + 1671 4843 61 1269 + 1671 2219 63 741 + 1671 3913 49 816 + 1726 1170 83 1269 + 1726 279 41 235 + 1726 171 84 55 + 2605 1671 93 1269 + 2605 2151 56 170 + 4098 1182 23 1269 + 4098 3460 32 877 + 4098 1990 74 206 + 50 736 67 570 + 50 689 49 520 + 50 4628 87 256 + 736 1069 61 570 + 736 866 78 533 + 1041 4041 81 570 + 1041 4857 3 575 + 1041 4917 44 924 + 1069 1041 75 570 + 1069 2729 18 666 + 1983 2773 71 570 + 1983 4799 34 570 + 1983 4945 95 261 + 1983 905 11 965 + 2773 4754 15 570 + 2773 3892 38 182 + 4041 1983 6 570 + 4041 3488 52 471 + 4041 4606 45 649 + 51 4422 85 456 + 51 3598 3 180 + 51 4132 86 142 + 1513 3060 24 456 + 1513 3803 88 786 + 1608 4139 2 456 + 1608 846 37 403 + 2068 1608 26 456 + 2068 4811 36 456 + 2068 3222 9 730 + 3060 4999 23 456 + 3060 2524 56 227 + 3060 4274 33 767 + 4139 1513 74 456 + 4139 3143 96 624 + 4422 2068 74 456 + 4422 1284 66 479 + 4422 1505 42 635 + 52 3133 7 320 + 52 1910 43 481 + 52 811 21 836 + 1000 1865 59 320 + 1000 195 41 151 + 1000 1768 68 366 + 1529 1000 94 320 + 1529 610 85 990 + 1865 4715 61 320 + 1865 1574 38 4 + 2245 1529 65 320 + 2245 949 2 327 + 2769 2245 78 320 + 2769 814 11 339 + 2957 4485 10 320 + 2957 408 93 874 + 2957 655 40 584 + 3133 3524 12 320 + 3133 3451 75 611 + 3133 4482 57 50 + 3448 2957 5 320 + 3448 4934 48 320 + 3448 4273 29 268 + 3448 4348 19 797 + 3524 3448 40 320 + 3524 4545 42 788 + 4485 2769 98 320 + 4485 377 80 435 + 53 2073 98 415 + 53 3346 73 301 + 53 1342 48 348 + 739 3864 100 415 + 739 2868 60 828 + 739 39 58 677 + 814 4923 80 415 + 814 2812 4 678 + 1881 3361 31 415 + 1881 4213 2 866 + 2032 739 22 415 + 2032 3538 23 391 + 2073 4215 92 415 + 2073 2024 13 930 + 2073 712 17 366 + 2433 814 77 415 + 2433 1467 8 561 + 2433 2861 80 395 + 3361 4026 74 415 + 3361 4527 18 415 + 3361 4942 40 113 + 3361 1488 4 395 + 3864 2433 89 415 + 3864 3304 78 632 + 4026 2032 45 415 + 4026 2360 60 900 + 4215 1881 86 415 + 4215 4976 42 811 + 4215 4052 82 551 + 54 3488 82 105 + 54 3267 82 322 + 1637 4384 11 105 + 1637 502 55 571 + 1637 4616 96 636 + 1886 2130 48 105 + 1886 1918 49 536 + 1977 1637 10 105 + 1977 1861 20 902 + 2130 4820 64 105 + 2130 142 59 874 + 3488 4593 35 105 + 3488 1977 15 105 + 3488 2491 9 984 + 4384 1886 75 105 + 4384 3337 67 909 + 55 1163 96 445 + 55 1296 46 957 + 55 4058 17 439 + 603 2477 43 445 + 603 2582 98 323 + 603 2797 7 370 + 1126 603 15 445 + 1126 1352 28 458 + 1126 223 89 748 + 1163 3640 61 445 + 1163 739 20 289 + 1275 1126 64 445 + 1275 1885 53 343 + 1275 738 87 438 + 1283 3442 45 445 + 1283 2625 98 204 + 1584 4762 79 445 + 1584 4701 37 445 + 1584 1740 58 710 + 2477 1584 93 445 + 2477 3216 93 870 + 3442 1275 9 445 + 3442 3694 21 575 + 3489 1283 67 445 + 3489 4987 41 12 + 3489 2740 27 196 + 3640 3489 22 445 + 3640 1046 59 665 + 3640 3084 58 498 + 56 3594 78 863 + 56 2228 77 437 + 860 4304 98 863 + 860 4602 90 863 + 860 3131 74 416 + 860 3277 97 610 + 912 2752 78 863 + 912 4897 42 445 + 912 3106 99 23 + 2752 860 53 863 + 2752 1607 38 677 + 3003 4594 57 863 + 3003 3133 12 205 + 3003 4846 26 471 + 3349 912 96 863 + 3349 3759 54 971 + 3349 2706 97 660 + 3594 3349 81 863 + 3594 4409 40 36 + 3594 4462 88 261 + 4304 3003 57 863 + 4304 2786 24 430 + 4304 2732 100 468 + 57 4329 93 104 + 57 3653 23 686 + 57 369 55 298 + 1776 2666 82 104 + 1776 4366 49 624 + 1776 1710 8 400 + 1941 3161 72 104 + 1941 4800 10 104 + 1941 287 48 991 + 1941 1086 11 840 + 1952 1776 14 104 + 1952 714 72 62 + 2666 4734 36 104 + 2666 4359 3 261 + 3161 4342 78 104 + 3161 4778 30 960 + 3161 1180 21 761 + 3876 1952 44 104 + 3876 3034 70 104 + 3876 2921 92 133 + 4329 1941 30 104 + 4329 3528 74 872 + 4342 3876 11 104 + 4342 737 3 397 + 58 4273 55 620 + 58 66 85 33 + 58 3027 30 167 + 2097 3231 6 620 + 2097 1633 90 546 + 2097 1925 76 513 + 2488 2097 100 620 + 2488 3135 72 819 + 2488 3412 20 329 + 3089 3202 27 620 + 3089 2693 53 370 + 3089 4454 97 961 + 3202 3224 94 620 + 3202 3935 1 466 + 3224 4569 63 620 + 3224 1096 34 917 + 3224 3894 4 791 + 3231 3451 58 620 + 3231 4797 56 243 + 3231 2411 45 177 + 3451 4343 64 620 + 3451 4940 62 620 + 3451 2881 44 225 + 3451 1564 37 100 + 4273 2488 25 620 + 4273 1289 97 902 + 4343 3089 31 620 + 4343 1132 74 677 + 4343 2234 33 142 + 59 2523 21 300 + 59 4912 50 128 + 59 1419 19 300 + 1205 2110 3 300 + 1205 102 28 616 + 1305 2375 15 300 + 1305 4581 78 674 + 2110 4505 36 300 + 2110 1305 21 300 + 2110 4032 88 487 + 2375 4829 33 300 + 2375 1027 26 645 + 2523 1205 78 300 + 2523 4168 38 806 + 60 1061 97 286 + 60 2677 12 71 + 1061 3241 46 286 + 1061 199 19 311 + 1061 498 23 238 + 1832 2673 98 286 + 1832 2189 98 186 + 1832 4795 10 893 + 2257 1832 55 286 + 2257 72 87 587 + 2673 4720 48 286 + 2673 2709 75 498 + 2673 812 9 966 + 2852 4860 73 286 + 2852 3175 55 286 + 2852 1221 9 519 + 3175 4461 28 286 + 3175 4032 60 705 + 3241 2852 69 286 + 3241 2373 85 517 + 3241 4544 61 258 + 4461 2257 93 286 + 4461 770 90 63 + 61 1250 83 435 + 61 3215 52 624 + 853 1703 49 435 + 853 4587 76 435 + 853 4742 52 223 + 853 2132 7 837 + 1250 853 51 435 + 1250 2087 3 773 + 1642 1876 27 435 + 1642 476 86 887 + 1642 3153 81 22 + 1703 1642 51 435 + 1703 1191 76 648 + 1703 49 70 89 + 1840 4603 85 435 + 1840 2050 83 521 + 1876 1840 65 435 + 1876 2208 77 633 + 62 3309 9 87 + 62 1942 79 920 + 62 3568 53 381 + 608 2161 23 87 + 608 4530 50 822 + 869 1823 74 87 + 869 3054 90 511 + 1269 2117 7 87 + 1269 4954 77 941 + 1269 4888 12 115 + 1296 869 54 87 + 1296 4273 100 677 + 1823 3005 54 87 + 1823 1083 75 793 + 2117 3162 4 87 + 2117 2757 35 722 + 2161 4860 55 87 + 2161 3921 4 832 + 3005 1269 28 87 + 3005 4285 20 16 + 3005 4287 8 593 + 3162 608 90 87 + 3162 455 22 967 + 3162 3909 40 926 + 3309 1296 49 87 + 3309 4966 31 87 + 3309 782 53 985 + 3309 4448 88 294 + 63 3454 86 97 + 63 638 63 630 + 1403 3243 61 97 + 1403 1559 6 502 + 1820 3208 43 97 + 1820 559 78 466 + 2419 4796 27 97 + 2419 4603 61 97 + 2419 3740 11 470 + 2419 4129 38 45 + 3208 3302 77 97 + 3208 2553 36 354 + 3208 439 95 431 + 3243 1820 58 97 + 3243 3795 9 260 + 3302 2419 52 97 + 3302 2706 32 398 + 3302 4356 90 158 + 3454 4394 67 97 + 3454 1459 48 190 + 3454 565 91 112 + 4394 1403 1 97 + 4394 4806 92 587 + 64 1925 100 435 + 64 305 62 484 + 837 4637 99 435 + 837 4972 90 435 + 837 1592 25 557 + 1032 2365 87 435 + 1032 748 65 242 + 1032 4487 89 863 + 1925 3996 98 435 + 1925 612 63 423 + 2264 3514 13 435 + 2264 1353 17 411 + 2365 837 7 435 + 2365 2697 14 954 + 3514 1032 79 435 + 3514 3878 59 966 + 3996 2264 35 435 + 3996 262 31 909 + 65 2164 93 773 + 65 1415 53 502 + 65 2070 16 376 + 841 4400 1 773 + 841 1984 37 785 + 841 3727 28 374 + 893 3948 48 773 + 893 3871 37 777 + 893 4641 76 243 + 1036 3308 74 773 + 1036 4033 70 625 + 1036 4103 53 850 + 1812 4567 11 773 + 1812 3367 87 289 + 2164 841 24 773 + 2164 1199 86 255 + 3308 893 75 773 + 3308 2179 74 774 + 3308 708 99 202 + 3948 1812 70 773 + 3948 4554 41 773 + 3948 3541 34 928 + 4400 1036 34 773 + 4400 4887 93 405 + 4400 1783 46 65 + 66 3072 83 137 + 66 3650 87 350 + 66 1791 22 190 + 590 4593 92 137 + 590 2433 52 64 + 590 4904 74 151 + 2615 4126 23 137 + 2615 4509 55 259 + 2615 289 75 744 + 3072 3136 92 137 + 3072 2589 35 6 + 3136 3344 61 137 + 3136 1095 48 726 + 3344 4875 51 137 + 3344 3592 74 137 + 3344 3991 40 431 + 3592 4010 100 137 + 3592 2868 87 636 + 3592 1704 23 941 + 4010 2615 33 137 + 4010 2707 63 258 + 4126 590 6 137 + 4126 2656 93 897 + 67 3090 6 99 + 67 84 17 240 + 67 3155 62 118 + 1183 3743 90 99 + 1183 2073 69 980 + 2378 2824 79 99 + 2378 1857 45 773 + 2378 3229 44 126 + 2824 3581 70 99 + 2824 2975 68 257 + 2824 42 1 695 + 3090 2378 4 99 + 3090 92 47 815 + 3090 4016 26 584 + 3411 3961 7 99 + 3411 4708 42 99 + 3411 439 29 152 + 3411 587 41 59 + 3581 3411 45 99 + 3581 2234 22 470 + 3743 4733 97 99 + 3743 1519 2 793 + 3961 1183 92 99 + 3961 1054 34 250 + 68 1111 52 792 + 68 734 28 318 + 68 118 36 853 + 591 4388 20 792 + 591 2805 54 228 + 838 3038 57 792 + 838 97 78 544 + 861 2054 41 792 + 861 1963 37 996 + 861 1123 28 665 + 1111 3718 1 792 + 1111 1459 71 689 + 1111 592 17 290 + 1978 838 88 792 + 1978 762 32 884 + 1978 674 56 781 + 2054 1978 12 792 + 2054 1869 14 835 + 2054 4450 6 708 + 2314 4527 79 792 + 2314 3221 67 465 + 2314 3227 56 185 + 3038 591 59 792 + 3038 4955 70 792 + 3038 777 12 603 + 3038 2711 2 45 + 3718 861 8 792 + 3718 3504 68 528 + 4388 2314 42 792 + 4388 2991 26 849 + 4388 1894 24 105 + 69 751 81 544 + 69 3944 47 339 + 751 1333 24 544 + 751 22 81 656 + 751 2806 95 124 + 1310 3121 83 544 + 1310 3636 76 556 + 1333 3732 45 544 + 1333 4301 56 823 + 1333 360 35 655 + 2152 1310 5 544 + 2152 499 6 103 + 2152 94 15 174 + 2538 4520 44 544 + 2538 2906 81 544 + 2538 1297 41 185 + 2906 3209 49 544 + 2906 3993 60 657 + 3121 4549 13 544 + 3121 2815 16 951 + 3121 3812 7 523 + 3209 2152 56 544 + 3209 1089 48 475 + 3209 4396 23 766 + 3732 2538 31 544 + 3732 4575 95 410 + 3732 4807 54 534 + 70 3020 92 558 + 70 2643 28 138 + 576 3833 82 558 + 576 4608 94 646 + 680 4864 94 558 + 680 1614 6 558 + 680 2544 60 25 + 999 1991 45 558 + 999 4688 73 558 + 999 3409 96 835 + 999 324 20 534 + 1108 999 10 558 + 1108 1926 8 964 + 1108 2698 98 160 + 1189 2583 13 558 + 1189 1627 78 159 + 1189 4858 47 797 + 1588 4625 97 558 + 1588 438 69 735 + 1588 706 60 928 + 1614 576 30 558 + 1614 4896 65 945 + 1991 1189 22 558 + 1991 1443 56 873 + 2583 4017 86 558 + 2583 1043 24 678 + 2583 4064 25 393 + 3020 1108 13 558 + 3020 4924 68 646 + 3833 1588 33 558 + 3833 1509 10 440 + 4017 680 45 558 + 4017 1692 5 779 + 4017 3333 62 343 + 71 3590 78 275 + 71 1512 32 518 + 71 3566 55 276 + 971 1350 84 275 + 971 2908 18 125 + 1011 2849 4 275 + 1011 3385 17 722 + 1268 1011 40 275 + 1268 583 31 507 + 1268 1493 63 191 + 1350 1268 82 275 + 1350 4975 20 275 + 1350 4048 32 719 + 2543 4784 72 275 + 2543 2018 17 205 + 2849 2543 43 275 + 2849 1350 93 924 + 3240 971 63 275 + 3240 2980 51 965 + 3240 2638 59 331 + 3415 3240 24 275 + 3415 2088 21 438 + 3590 4092 64 275 + 3590 3998 69 935 + 4092 3415 70 275 + 4092 4350 88 751 + 72 1817 36 467 + 72 1927 31 60 + 795 4877 6 467 + 795 3051 97 442 + 1817 4529 20 467 + 1817 4247 83 467 + 1817 653 86 8 + 1817 4265 64 86 + 2667 795 22 467 + 2667 118 88 209 + 2667 1924 38 119 + 2911 2976 96 467 + 2911 218 88 726 + 2911 6 33 538 + 2976 2667 63 467 + 2976 2351 13 372 + 2976 1188 1 470 + 3999 2911 31 467 + 3999 435 5 512 + 4247 3999 91 467 + 4247 760 72 391 + 4247 881 41 911 + 73 1860 76 350 + 73 550 69 788 + 73 957 25 889 + 578 4355 45 350 + 578 544 28 866 + 1068 3881 7 350 + 1068 3793 5 129 + 1068 4257 46 192 + 1860 578 89 350 + 1860 4833 60 350 + 1860 2842 37 825 + 2075 1068 19 350 + 2075 2035 91 23 + 2646 4625 92 350 + 2646 97 11 977 + 2646 4851 18 499 + 2838 2075 35 350 + 2838 2389 61 682 + 3881 4495 8 350 + 3881 3367 13 121 + 4334 2646 88 350 + 4334 3033 32 691 + 4334 1914 56 676 + 4355 2838 63 350 + 4355 4316 29 331 + 4495 4334 64 350 + 4495 444 73 167 + 74 1293 3 477 + 74 2001 79 749 + 74 73 98 410 + 524 4730 53 477 + 524 4896 71 366 + 524 3647 48 716 + 1293 4350 43 477 + 1293 4609 7 537 + 1293 3988 84 852 + 1432 3030 4 477 + 1432 4616 86 884 + 2124 3850 36 477 + 2124 1651 39 638 + 2124 2499 75 831 + 3030 2124 16 477 + 3030 2488 51 132 + 3030 4990 59 679 + 3850 524 23 477 + 3850 4003 28 500 + 3850 1910 90 86 + 4350 1432 57 477 + 4350 4785 13 477 + 4350 1306 16 886 + 4350 4830 59 126 + 75 3613 48 1231 + 75 1858 10 886 + 75 2110 17 162 + 1153 2657 24 1231 + 1153 4470 34 591 + 1153 1279 71 708 + 1215 4933 28 1231 + 1215 1572 45 938 + 1457 1215 64 1231 + 1457 4897 11 368 + 1568 1690 82 1231 + 1568 3105 93 800 + 1690 1457 34 1231 + 1690 1454 92 186 + 2657 1568 32 1231 + 2657 4954 17 575 + 2657 2941 29 94 + 3613 3949 50 1231 + 3613 1747 53 757 + 3949 4411 32 1231 + 3949 4761 47 528 + 4411 1153 35 1231 + 4411 4868 81 1231 + 4411 2760 75 454 + 4411 1081 53 963 + 76 1468 11 486 + 76 650 39 678 + 791 3902 90 486 + 791 4226 36 985 + 791 2773 2 356 + 972 3556 50 486 + 972 695 32 173 + 972 2163 3 235 + 1369 972 33 486 + 1369 666 88 597 + 1396 791 100 486 + 1396 1051 67 905 + 1468 1396 80 486 + 1468 534 71 398 + 3556 3762 24 486 + 3556 2610 84 919 + 3556 4489 5 833 + 3762 4749 27 486 + 3762 4516 9 486 + 3762 2717 97 653 + 3902 4013 42 486 + 3902 2667 39 468 + 4013 1369 30 486 + 4013 272 67 749 + 77 3700 69 773 + 77 2638 66 273 + 77 3307 4 750 + 1469 2090 19 773 + 1469 1544 38 86 + 1469 965 42 690 + 1678 2577 3 773 + 1678 987 80 998 + 2090 2400 3 773 + 2090 4557 28 773 + 2090 3561 100 6 + 2090 1032 38 575 + 2400 2758 79 773 + 2400 2159 98 351 + 2577 2841 37 773 + 2577 3387 69 700 + 2758 3203 42 773 + 2758 4693 64 723 + 2758 552 57 811 + 2841 3637 71 773 + 2841 4068 59 106 + 2841 2948 67 830 + 3203 4587 25 773 + 3203 2169 97 486 + 3203 3487 23 856 + 3637 1469 54 773 + 3637 169 91 773 + 3637 4803 5 656 + 3700 1678 14 773 + 3700 4894 100 749 + 3700 3254 5 674 + 78 4195 37 422 + 78 2431 96 456 + 78 1292 25 432 + 637 3080 91 422 + 637 361 16 278 + 2287 4810 89 422 + 2287 4366 83 881 + 2287 2684 42 75 + 2977 2287 9 422 + 2977 3539 46 913 + 2977 3959 10 970 + 3080 4770 49 422 + 3080 2977 56 422 + 3080 3993 16 344 + 3080 3976 98 35 + 4195 637 73 422 + 4195 2336 77 837 + 79 3474 78 526 + 79 4411 1 145 + 79 399 97 616 + 1874 2949 39 526 + 1874 317 31 257 + 1874 2915 58 817 + 2949 4569 12 526 + 2949 166 35 134 + 2949 4792 72 924 + 3474 4057 50 526 + 3474 4597 20 526 + 3474 4563 20 94 + 3474 3032 78 434 + 3629 3803 56 526 + 3629 2282 54 710 + 3803 4289 48 526 + 3803 1246 87 997 + 4012 1874 53 526 + 4012 2941 54 652 + 4012 3666 39 471 + 4057 3629 90 526 + 4057 1023 39 876 + 4289 4012 42 526 + 4289 2646 67 205 + 4289 4670 72 21 + 80 2921 95 402 + 80 2138 7 282 + 1532 2135 73 402 + 1532 3684 21 760 + 1891 3908 63 402 + 1891 259 38 652 + 1891 1941 3 248 + 2135 4515 67 402 + 2135 3691 95 279 + 2141 3959 14 402 + 2141 341 28 309 + 2921 4198 45 402 + 2921 3242 72 376 + 3628 4492 9 402 + 3628 2332 61 715 + 3908 4011 60 402 + 3908 2677 85 525 + 3959 3628 14 402 + 3959 215 51 625 + 4011 1532 33 402 + 4011 3063 93 192 + 4198 2141 91 402 + 4198 4839 50 402 + 4198 1710 94 229 + 4198 3047 50 553 + 4492 1891 52 402 + 4492 2274 69 268 + 81 2434 6 602 + 81 4235 63 785 + 951 3027 53 602 + 951 3188 58 380 + 951 708 3 825 + 1026 2166 78 602 + 1026 1759 42 779 + 1822 3316 41 602 + 1822 451 10 517 + 2166 4572 35 602 + 2166 1001 19 234 + 2434 2636 55 602 + 2434 2924 58 924 + 2636 3298 64 602 + 2636 1171 34 755 + 2636 714 4 199 + 3027 4265 74 602 + 3027 1070 78 93 + 3298 951 91 602 + 3298 212 26 911 + 3298 3070 33 905 + 3316 4051 2 602 + 3316 4868 65 296 + 3316 2303 80 96 + 4051 1026 73 602 + 4051 48 32 377 + 4265 1822 77 602 + 4265 4840 89 602 + 4265 333 2 811 + 82 3207 87 262 + 82 2016 98 787 + 82 4323 23 472 + 2156 3102 41 262 + 2156 4856 43 262 + 2156 194 91 342 + 2156 4406 12 241 + 2282 2156 87 262 + 2282 3600 21 878 + 2282 2105 3 180 + 2902 4754 8 262 + 2902 188 2 596 + 2902 2611 63 49 + 3102 3922 97 262 + 3102 4150 64 565 + 3102 4750 97 446 + 3207 2282 12 262 + 3207 3378 88 279 + 3922 2902 19 262 + 3922 2040 45 500 + 83 2167 34 321 + 83 3772 54 32 + 554 2414 11 321 + 554 924 9 413 + 554 613 83 57 + 966 4272 91 321 + 966 4552 33 321 + 966 4564 56 797 + 966 4208 47 501 + 2167 3000 69 321 + 2167 4888 82 209 + 2167 3364 6 731 + 2171 2511 42 321 + 2171 1086 29 50 + 2296 2171 44 321 + 2296 4443 1 861 + 2296 4169 21 480 + 2351 2296 66 321 + 2351 2404 68 775 + 2351 2335 88 897 + 2414 966 34 321 + 2414 3381 71 435 + 2511 554 80 321 + 2511 67 17 398 + 3000 2351 63 321 + 3000 3369 54 444 + 3000 822 11 704 + 4272 4572 65 321 + 4272 4649 41 936 + 4272 922 10 679 + 84 2517 5 1135 + 84 3461 36 852 + 1073 2399 56 1135 + 1073 4178 75 920 + 1073 2453 84 839 + 1535 1073 19 1135 + 1535 3869 58 188 + 2399 3891 62 1135 + 2399 4528 98 855 + 2399 507 60 98 + 2517 4478 49 1135 + 2517 1570 85 993 + 3834 1535 36 1135 + 3834 1298 55 903 + 3834 4853 68 572 + 3891 4717 60 1135 + 3891 1586 72 318 + 3891 1121 94 954 + 4478 3834 28 1135 + 4478 4875 64 1135 + 4478 3712 34 959 + 4478 234 26 160 + 85 2828 6 459 + 85 2695 75 62 + 622 2427 33 459 + 622 4996 62 897 + 830 4765 48 459 + 830 4872 82 921 + 830 1500 35 109 + 1763 3735 12 459 + 1763 4070 78 274 + 2427 830 36 459 + 2427 4905 23 459 + 2427 3147 1 569 + 2427 421 19 618 + 2489 3755 83 459 + 2489 1477 94 293 + 2489 4960 89 480 + 2828 2489 14 459 + 2828 4961 64 644 + 2828 2108 24 513 + 3735 622 74 459 + 3735 4532 36 50 + 3735 58 65 672 + 3755 1763 34 459 + 3755 955 82 247 + 3755 216 99 975 + 86 3172 63 915 + 86 2576 5 971 + 974 3007 94 915 + 974 3226 30 773 + 1178 4784 12 915 + 1178 4710 94 915 + 1178 2987 36 508 + 2059 974 21 915 + 2059 4526 76 557 + 3007 1178 64 915 + 3007 4610 45 967 + 3172 3315 51 915 + 3172 1790 8 66 + 3315 2059 90 915 + 3315 3801 47 499 + 3315 2909 98 704 + 87 1958 92 505 + 87 2342 15 288 + 826 1629 34 505 + 826 2435 93 127 + 826 508 22 516 + 1272 1969 66 505 + 1272 127 96 585 + 1272 3733 90 796 + 1629 4035 58 505 + 1629 827 6 311 + 1629 2318 79 500 + 1958 4668 44 505 + 1958 1272 91 505 + 1958 4991 24 322 + 1969 2916 59 505 + 1969 992 56 723 + 1969 2053 72 260 + 2546 4815 11 505 + 2546 962 34 28 + 2916 826 37 505 + 2916 3974 97 202 + 4035 2546 6 505 + 4035 4988 15 268 + 88 957 70 193 + 88 4453 34 366 + 88 2187 93 135 + 957 3275 33 193 + 957 4735 79 193 + 957 4367 2 158 + 1474 2586 78 193 + 1474 1806 56 318 + 1474 1342 52 728 + 1747 2529 55 193 + 1747 948 13 955 + 1747 4244 43 745 + 2529 4468 95 193 + 2529 3203 98 350 + 2529 4454 45 919 + 2586 5000 32 193 + 2586 1293 79 987 + 3275 1747 74 193 + 3275 4297 8 884 + 3574 1474 46 193 + 3574 339 77 766 + 3574 997 41 384 + 4468 3574 7 193 + 4468 1611 60 173 + 4468 2428 46 43 + 89 3013 85 1133 + 89 3914 36 527 + 868 2491 88 1133 + 868 1531 28 467 + 868 2073 87 769 + 1102 1358 79 1133 + 1102 556 20 37 + 1102 575 3 956 + 1358 868 71 1133 + 1358 4483 83 798 + 1358 3712 11 50 + 2162 2350 14 1133 + 2162 690 11 222 + 2350 4544 40 1133 + 2350 4967 68 1133 + 2350 4682 39 920 + 2491 2162 68 1133 + 2491 3853 51 995 + 2491 2110 59 856 + 3013 1102 38 1133 + 3013 3523 71 167 + 3013 4563 3 313 + 90 1245 75 500 + 90 1680 96 485 + 90 4649 37 725 + 1121 3880 23 500 + 1121 1891 25 391 + 1121 948 78 448 + 1245 3043 40 500 + 1245 4679 83 89 + 1522 3570 99 500 + 1522 4310 5 416 + 1522 2656 94 363 + 2819 1522 62 500 + 2819 364 54 844 + 2819 76 55 366 + 3043 2819 10 500 + 3043 2593 27 516 + 3043 1101 13 674 + 3093 4559 39 500 + 3093 3399 17 746 + 3093 2913 56 943 + 3570 1121 82 500 + 3570 4712 98 500 + 3570 1172 76 522 + 3880 3093 84 500 + 3880 1111 7 690 + 91 3168 47 742 + 91 4704 57 882 + 781 4696 8 742 + 781 576 37 512 + 788 2622 17 742 + 788 3437 63 272 + 1772 2993 98 742 + 1772 2661 16 990 + 1772 2140 9 737 + 2622 3350 91 742 + 2622 3593 6 913 + 2993 4377 77 742 + 2993 371 47 668 + 3168 788 62 742 + 3168 255 71 602 + 3350 1772 78 742 + 3350 4117 63 355 + 3350 3346 66 779 + 4239 781 12 742 + 4239 3199 98 142 + 4377 4239 63 742 + 4377 4705 63 742 + 4377 896 46 419 + 92 3911 81 403 + 92 4815 47 696 + 696 2855 33 403 + 696 4512 92 403 + 696 3725 12 387 + 908 696 37 403 + 908 2771 45 110 + 2855 3616 33 403 + 2855 2413 8 439 + 2855 1667 63 520 + 2884 3185 81 403 + 2884 1845 28 715 + 2884 142 72 774 + 3185 908 100 403 + 3185 2943 72 437 + 3185 676 41 556 + 3616 4787 8 403 + 3616 4802 75 969 + 3911 2884 81 403 + 3911 2032 26 148 + 3911 3155 92 273 + 93 1285 13 442 + 93 1256 87 384 + 1085 4094 36 442 + 1085 3504 39 934 + 1285 2258 26 442 + 1285 3527 79 807 + 1285 2768 34 598 + 1442 1485 8 442 + 1442 915 6 951 + 1485 2654 64 442 + 1485 3834 80 555 + 1485 3994 82 761 + 1524 1085 67 442 + 1524 2940 59 917 + 1524 4380 67 454 + 2258 2506 49 442 + 2258 888 40 968 + 2258 980 67 841 + 2506 4121 61 442 + 2506 3016 83 650 + 2506 3243 39 246 + 2654 1524 38 442 + 2654 4535 30 722 + 2654 988 53 548 + 4094 4685 12 442 + 4094 4510 64 442 + 4094 1033 91 642 + 4094 4770 80 996 + 4121 1442 10 442 + 4121 2192 41 977 + 4121 4085 72 940 + 94 2229 77 1077 + 94 864 62 198 + 94 2522 67 40 + 880 1030 94 1077 + 880 1133 98 242 + 1030 2196 41 1077 + 1030 2607 30 569 + 1030 435 7 884 + 1064 2095 28 1077 + 1064 3483 14 555 + 2095 4002 9 1077 + 2095 1959 43 780 + 2095 1025 39 552 + 2196 1064 24 1077 + 2196 4604 60 1077 + 2196 4337 15 88 + 2196 349 100 413 + 2229 2555 86 1077 + 2229 3259 20 993 + 2555 880 4 1077 + 2555 1875 31 461 + 2555 1770 13 923 + 4002 4553 25 1077 + 4002 4973 4 739 + 4002 2160 63 399 + 95 1105 13 552 + 95 1626 85 155 + 95 4780 39 558 + 1105 2469 94 552 + 1105 4968 42 897 + 1105 4017 36 39 + 1499 4104 9 552 + 1499 4566 47 818 + 1656 4810 20 552 + 1656 1681 15 267 + 1660 1656 44 552 + 1660 4967 14 552 + 1660 4458 23 433 + 1796 3838 1 552 + 1796 1269 23 47 + 1796 2440 84 947 + 2469 4224 56 552 + 2469 4494 33 344 + 2469 1318 46 254 + 3838 1499 38 552 + 3838 863 68 932 + 3838 782 32 273 + 4104 1660 84 552 + 4104 2815 49 146 + 4104 384 12 65 + 4224 1796 64 552 + 4224 635 59 561 + 96 2831 40 398 + 96 360 76 538 + 547 4551 17 398 + 547 1488 19 398 + 547 4603 31 55 + 1488 3555 81 398 + 1488 2938 23 23 + 2831 3052 95 398 + 2831 899 82 38 + 2831 4748 86 300 + 3052 3437 46 398 + 3052 1237 7 945 + 3437 547 12 398 + 3437 4121 8 414 + 3555 4805 20 398 + 3555 3697 82 315 + 3555 1512 94 36 + 97 1262 55 292 + 97 4976 40 928 + 97 893 79 428 + 1262 4226 15 292 + 1262 2843 85 105 + 1430 2530 25 292 + 1430 764 7 449 + 1430 184 27 848 + 1708 4755 43 292 + 1708 4704 7 292 + 1708 4758 48 752 + 1708 3301 98 375 + 2034 2518 94 292 + 2034 1290 40 415 + 2034 4317 58 149 + 2328 1430 61 292 + 2328 660 86 174 + 2518 1708 29 292 + 2518 1002 64 215 + 2518 1546 19 458 + 2530 2034 78 292 + 2530 248 11 55 + 3405 2328 16 292 + 3405 4212 34 459 + 4226 3405 58 292 + 4226 2372 48 85 + 4226 1179 5 406 + 98 2206 11 1180 + 98 3981 19 359 + 1984 3801 60 1180 + 1984 4359 19 396 + 1984 3450 12 763 + 2206 3327 96 1180 + 2206 3614 67 34 + 3252 4910 24 1180 + 3252 1444 42 463 + 3252 2544 3 384 + 3327 4406 84 1180 + 3327 3531 4 797 + 3327 1981 6 795 + 3801 3252 2 1180 + 3801 4954 42 1180 + 3801 3455 84 818 + 3801 2733 58 253 + 4406 1984 50 1180 + 4406 1363 99 20 + 4406 4460 43 221 + 99 1426 5 449 + 99 3868 45 417 + 1033 1707 48 449 + 1033 4540 34 582 + 1033 4390 90 537 + 1426 1033 78 449 + 1426 1973 39 859 + 1707 3075 4 449 + 1707 340 77 364 + 1707 2656 45 407 + 1932 3458 38 449 + 1932 3174 52 401 + 1932 1745 10 567 + 3075 3507 61 449 + 3075 3216 81 904 + 3458 3826 95 449 + 3458 2361 3 445 + 3507 1932 53 449 + 3507 4667 64 449 + 3507 3187 15 596 + 3507 3053 56 624 + 3826 4596 82 449 + 3826 4735 85 173 + 100 2933 66 618 + 100 3283 61 752 + 2214 3465 33 618 + 2214 3105 74 368 + 2214 926 45 504 + 2232 2964 45 618 + 2232 2912 36 528 + 2232 4912 71 46 + 2330 2214 78 618 + 2330 2796 55 197 + 2330 218 27 27 + 2933 2232 39 618 + 2933 4575 75 595 + 2933 1473 100 380 + 2964 3977 38 618 + 2964 4738 66 618 + 2964 1513 88 211 + 3465 4825 68 618 + 3465 4019 41 614 + 3465 591 47 214 + 3492 3893 28 618 + 3492 934 35 584 + 3492 1613 20 543 + 3893 2330 20 618 + 3893 3425 71 204 + 3893 3098 31 885 + 3977 3492 8 618 + 3977 3337 12 273 + 3977 3129 20 758 + 101 4093 64 623 + 101 2346 8 300 + 101 44 7 833 + 581 4515 1 623 + 581 4648 40 623 + 581 3785 70 671 + 663 2620 53 623 + 663 4200 45 426 + 663 65 57 748 + 854 663 35 623 + 854 303 73 904 + 2620 3539 84 623 + 2620 3922 50 374 + 2668 4037 51 623 + 2668 1316 27 241 + 2668 3846 14 378 + 3539 3848 10 623 + 3539 2802 15 714 + 3848 2668 27 623 + 3848 2410 35 272 + 3848 4371 33 940 + 4037 581 52 623 + 4037 576 59 823 + 4037 1292 35 881 + 4093 854 82 623 + 4093 1696 56 733 + 102 3112 28 695 + 102 3029 38 598 + 102 2659 38 981 + 2175 3605 34 695 + 2175 2253 93 235 + 2753 4730 80 695 + 2753 3869 40 866 + 2798 2753 99 695 + 2798 3814 70 302 + 2798 4260 61 4 + 3112 4378 66 695 + 3112 2573 13 60 + 3112 3788 71 86 + 3605 4170 12 695 + 3605 2818 7 272 + 4170 2798 3 695 + 4170 871 90 79 + 4170 1376 9 36 + 4378 2175 26 695 + 4378 4797 22 695 + 4378 1485 9 200 + 4378 4627 45 690 + 103 3419 15 312 + 103 2244 64 796 + 103 2117 79 659 + 947 2066 83 312 + 947 3735 96 965 + 1948 3017 56 312 + 1948 2771 57 977 + 2066 1948 64 312 + 2066 4188 27 372 + 2066 4544 28 588 + 2112 3443 48 312 + 2112 1716 54 109 + 2112 4894 22 304 + 3017 4141 34 312 + 3017 4301 73 957 + 3419 947 67 312 + 3419 4750 34 312 + 3419 3115 100 96 + 3443 4657 46 312 + 3443 942 97 720 + 4141 2112 95 312 + 4141 1181 53 447 + 104 2878 76 447 + 104 4104 20 324 + 1954 4886 8 447 + 1954 4766 88 447 + 1954 2827 74 192 + 2294 4148 42 447 + 2294 1573 49 409 + 2294 4413 80 13 + 2391 1954 75 447 + 2391 1108 87 753 + 2756 4154 15 447 + 2756 2520 91 33 + 2756 2135 93 408 + 2878 3339 85 447 + 2878 4528 76 683 + 3339 2294 58 447 + 3339 4840 79 699 + 3339 4820 36 967 + 4148 4298 63 447 + 4148 791 1 923 + 4148 2585 20 422 + 4154 2391 75 447 + 4154 2537 20 355 + 4154 277 45 56 + 4298 2756 73 447 + 4298 2377 88 435 + 4298 4252 51 701 + 105 1001 71 420 + 105 2579 88 601 + 833 2678 76 420 + 833 1794 18 418 + 833 3106 63 31 + 994 4763 79 420 + 994 4061 63 81 + 1001 4216 92 420 + 1001 4109 33 335 + 1083 4536 60 420 + 1083 2547 16 420 + 1083 2002 79 132 + 1083 3648 77 215 + 2547 833 40 420 + 2547 4180 84 654 + 2678 994 62 420 + 2678 3643 5 149 + 2678 1533 37 43 + 3729 1083 24 420 + 3729 2255 53 328 + 4216 3729 45 420 + 4216 4242 39 204 + 4216 4976 93 602 + 106 3301 71 758 + 106 2686 44 985 + 106 199 88 235 + 1169 3067 79 758 + 1169 3709 96 789 + 1428 4660 62 758 + 1428 4888 14 636 + 1428 1697 39 813 + 1444 4367 62 758 + 1444 2320 9 838 + 1444 3097 7 274 + 3067 3795 71 758 + 3067 4295 59 590 + 3067 4706 29 278 + 3301 1169 90 758 + 3301 1202 78 441 + 3795 1444 99 758 + 3795 4829 100 758 + 3795 4709 16 476 + 3795 3983 67 935 + 4114 1428 21 758 + 4114 1864 41 593 + 4367 4114 40 758 + 4367 805 3 511 + 107 2540 86 880 + 107 2668 22 456 + 895 1987 75 880 + 895 2896 6 989 + 983 2551 67 880 + 983 4718 3 495 + 1512 895 53 880 + 1512 181 60 240 + 1512 2698 69 965 + 1570 983 22 880 + 1570 1900 73 724 + 1667 4916 85 880 + 1667 3330 59 880 + 1667 3571 43 110 + 1667 2116 81 807 + 1987 2581 93 880 + 1987 780 39 157 + 1987 4944 20 768 + 2540 1512 39 880 + 2540 2122 92 42 + 2551 4790 13 880 + 2551 2309 52 484 + 2581 1667 33 880 + 2581 871 83 442 + 3330 1570 17 880 + 3330 3209 88 945 + 108 3607 73 846 + 108 1800 86 435 + 1025 1773 28 846 + 1025 2608 23 157 + 1025 2268 47 965 + 1322 4862 35 846 + 1322 4583 43 846 + 1322 3588 96 849 + 1322 4764 23 146 + 1773 3946 34 846 + 1773 322 31 415 + 3607 1025 41 846 + 3607 4179 67 886 + 3607 2565 70 93 + 3946 1322 37 846 + 3946 756 32 706 + 109 1749 60 694 + 109 3051 11 184 + 109 2236 22 649 + 568 2613 61 694 + 568 255 53 590 + 568 374 53 803 + 1239 4856 55 694 + 1239 3194 100 694 + 1239 1299 92 291 + 1239 3546 34 740 + 1251 4172 42 694 + 1251 475 16 175 + 1251 4904 48 902 + 1544 4583 7 694 + 1544 4730 36 197 + 1544 1211 89 358 + 1620 1251 16 694 + 1620 4713 50 172 + 1622 1544 38 694 + 1622 3232 60 996 + 1749 1620 19 694 + 1749 618 1 254 + 1749 1726 16 968 + 1789 1239 26 694 + 1789 4819 63 757 + 1789 3838 47 153 + 2613 1622 75 694 + 2613 4476 1 813 + 2613 2275 6 969 + 3194 568 30 694 + 3194 4056 7 257 + 3194 1569 78 566 + 4172 1789 77 694 + 4172 426 45 737 + 110 1161 35 804 + 110 117 69 728 + 110 1036 10 858 + 703 4759 4 804 + 703 3335 76 757 + 703 4688 45 675 + 1161 3797 82 804 + 1161 4874 8 804 + 1161 3205 24 221 + 2890 703 12 804 + 2890 4144 76 835 + 3371 2890 15 804 + 3371 227 30 310 + 3513 3371 92 804 + 3513 1640 37 248 + 3513 3683 85 358 + 3797 3513 40 804 + 3797 4718 94 93 + 3797 2972 5 234 + 111 1888 14 411 + 111 2668 25 341 + 111 3079 95 760 + 1640 2502 26 411 + 1640 4795 10 662 + 1640 1519 82 70 + 1888 3608 70 411 + 1888 4742 50 411 + 1888 2482 93 513 + 2502 4534 58 411 + 2502 630 5 648 + 3608 4217 41 411 + 3608 2222 5 320 + 3608 4762 45 245 + 4217 1640 94 411 + 4217 1433 9 561 + 112 1346 53 299 + 112 298 83 310 + 654 2031 96 299 + 654 2253 15 433 + 654 1739 64 472 + 1222 2494 23 299 + 1222 4628 63 299 + 1222 4556 13 349 + 1346 2432 53 299 + 1346 1128 67 194 + 1346 543 9 705 + 2031 1222 57 299 + 2031 4374 62 700 + 2031 2103 14 325 + 2368 4477 56 299 + 2368 666 5 721 + 2432 3220 1 299 + 2432 2012 6 975 + 2432 4552 52 555 + 2494 4945 65 299 + 2494 2905 57 47 + 2494 4580 98 129 + 3220 4038 69 299 + 3220 4983 2 445 + 4038 2368 2 299 + 4038 3190 30 593 + 4477 654 45 299 + 4477 2949 61 947 + 113 754 93 395 + 113 1813 53 198 + 113 3854 25 26 + 515 3335 20 395 + 515 2833 21 615 + 515 1637 100 326 + 754 515 65 395 + 754 3831 24 626 + 754 1669 69 783 + 1057 3491 20 395 + 1057 897 51 407 + 1057 2162 96 537 + 3165 4968 37 395 + 3165 4577 18 395 + 3165 1797 99 665 + 3165 1336 26 534 + 3335 4059 46 395 + 3335 3208 40 330 + 3491 3165 82 395 + 3491 1163 29 187 + 3491 1744 94 974 + 4059 1057 2 395 + 4059 568 41 729 + 4059 2388 4 479 + 114 2310 33 120 + 114 3611 70 478 + 114 918 81 456 + 1223 4788 2 120 + 1223 1286 98 875 + 1223 1580 57 657 + 1899 3692 57 120 + 1899 2726 72 224 + 2310 4336 56 120 + 2310 1041 12 89 + 2310 2204 29 864 + 3044 1223 68 120 + 3044 2074 40 767 + 3692 4530 40 120 + 3692 3044 34 120 + 3692 2483 42 171 + 4336 1899 41 120 + 4336 643 98 207 + 4336 305 2 253 + 115 1859 32 702 + 115 3428 21 22 + 115 2699 93 499 + 704 2349 72 702 + 704 2259 49 540 + 704 3383 66 245 + 1219 704 57 702 + 1219 3454 5 850 + 1373 3500 61 702 + 1373 342 23 149 + 1859 1373 11 702 + 1859 1685 90 424 + 2349 4525 10 702 + 2349 4947 19 702 + 2349 3722 98 304 + 2349 4928 12 629 + 2402 1219 80 702 + 2402 669 69 560 + 2402 1028 21 286 + 3500 4347 17 702 + 3500 1162 92 7 + 4347 2402 32 702 + 4347 2493 68 41 + 4347 3658 77 500 + 116 3472 94 269 + 116 3011 21 963 + 956 4498 9 269 + 956 4617 74 147 + 2026 3303 4 269 + 2026 2098 15 78 + 3148 956 66 269 + 3148 552 91 938 + 3148 3512 35 688 + 3303 4301 38 269 + 3303 89 74 854 + 3303 1872 73 21 + 3472 2026 47 269 + 3472 672 87 889 + 3472 1741 57 527 + 4138 4649 37 269 + 4138 4543 7 269 + 4138 3018 44 628 + 4301 3148 36 269 + 4301 2178 25 181 + 4498 4138 72 269 + 4498 1577 72 975 + 4498 4183 5 827 + 117 4128 78 703 + 117 264 69 513 + 1699 4150 42 703 + 1699 2277 79 706 + 1794 4883 24 703 + 1794 1832 64 882 + 2498 1794 83 703 + 2498 1294 35 266 + 2498 2121 2 18 + 2512 4928 1 703 + 2512 3284 16 703 + 2512 1223 69 416 + 3277 2498 69 703 + 3277 4795 31 48 + 3277 1040 27 137 + 3284 3277 51 703 + 3284 3449 30 413 + 4128 1699 23 703 + 4128 2104 54 85 + 4150 2512 40 703 + 4150 1941 18 464 + 118 1609 88 619 + 118 4697 41 760 + 118 826 4 502 + 535 675 96 619 + 535 1075 79 479 + 675 1038 72 619 + 675 487 18 743 + 675 4320 33 362 + 1038 3824 6 619 + 1038 4386 71 518 + 1609 1647 89 619 + 1609 2067 34 627 + 1647 3466 92 619 + 1647 4522 57 619 + 1647 343 9 366 + 2367 3885 56 619 + 2367 3625 15 305 + 3466 2367 79 619 + 3466 1300 79 325 + 3466 2507 83 743 + 3824 4726 97 619 + 3824 2840 81 405 + 3824 4816 83 130 + 3885 535 86 619 + 3885 201 66 832 + 3885 2978 18 655 + 119 4219 12 172 + 119 1544 35 516 + 119 3889 43 710 + 512 1168 68 172 + 512 298 96 29 + 946 512 2 172 + 946 2531 64 33 + 1168 3651 15 172 + 1168 4770 28 172 + 1168 1233 54 295 + 1168 3464 75 267 + 1425 1679 88 172 + 1425 1241 97 379 + 1425 3227 73 1 + 1679 4496 92 172 + 1679 2097 51 872 + 1679 3031 37 688 + 1988 4042 55 172 + 1988 2769 82 381 + 1988 2698 17 471 + 2225 946 34 172 + 2225 2395 76 464 + 3398 2225 13 172 + 3398 4601 5 172 + 3398 4878 46 79 + 3651 1988 32 172 + 3651 1517 64 128 + 3651 4114 16 105 + 4042 1425 12 172 + 4042 4466 41 713 + 4219 3398 35 172 + 4219 441 13 574 + 4219 1796 45 690 + 4496 4810 19 172 + 4496 3296 39 98 + 120 4365 19 689 + 120 1075 25 988 + 120 2207 27 184 + 820 2807 35 689 + 820 2419 39 338 + 820 4397 96 963 + 1372 1975 15 689 + 1372 3149 90 680 + 1372 3700 73 292 + 1975 4043 41 689 + 1975 388 63 788 + 1975 2044 35 563 + 2188 2731 16 689 + 2188 4506 13 885 + 2188 3230 79 908 + 2731 4631 68 689 + 2731 207 2 314 + 2731 783 58 661 + 2807 2188 89 689 + 2807 606 90 393 + 4043 820 28 689 + 4043 4608 91 689 + 4043 1801 66 76 + 4043 4369 56 871 + 4365 1372 62 689 + 4365 1360 20 639 + 121 2262 5 341 + 121 3747 54 648 + 121 18 31 874 + 558 4135 59 341 + 558 795 65 37 + 558 3855 84 43 + 2094 3281 49 341 + 2094 559 72 785 + 2262 3360 16 341 + 2262 2799 10 419 + 2262 865 84 478 + 3281 4706 33 341 + 3281 3742 35 885 + 3360 3722 85 341 + 3360 3222 62 226 + 3722 4270 33 341 + 3722 4870 8 965 + 3722 1500 1 519 + 4135 2094 52 341 + 4135 3919 17 875 + 4270 558 26 341 + 4270 4602 67 341 + 4270 2459 98 811 + 4270 3188 58 73 + 122 3280 22 699 + 122 2561 51 773 + 122 2655 53 102 + 1351 1687 27 699 + 1351 1176 37 228 + 1687 3313 97 699 + 1687 3242 71 883 + 1687 2122 64 887 + 2216 4211 52 699 + 2216 3888 43 420 + 2216 644 54 304 + 3280 1351 43 699 + 3280 1340 56 864 + 3313 2216 69 699 + 3313 4701 100 699 + 3313 2388 50 175 + 3313 3213 33 388 + 4211 4924 19 699 + 4211 22 24 331 + 123 2475 78 735 + 123 2266 9 704 + 123 1573 74 424 + 1188 3606 80 735 + 1188 3915 8 68 + 1188 4877 69 945 + 1472 4876 57 735 + 1472 1916 12 964 + 1472 2662 37 68 + 2475 1188 19 735 + 2475 4078 11 427 + 2475 3127 20 517 + 2607 4844 79 735 + 2607 3433 61 735 + 2607 199 60 411 + 3433 1472 27 735 + 3433 4405 93 585 + 3606 4255 63 735 + 3606 4748 78 304 + 4255 2607 50 735 + 4255 325 77 991 + 4255 892 97 292 + 124 3596 64 4 + 124 4368 60 49 + 124 3217 77 289 + 847 3066 78 4 + 847 4912 36 430 + 1298 4667 36 4 + 1298 3310 99 4 + 1298 893 31 975 + 1744 3076 75 4 + 1744 1192 85 648 + 1818 1298 14 4 + 1818 3783 53 137 + 1818 1529 18 872 + 2284 3659 68 4 + 2284 1297 74 108 + 2783 1818 93 4 + 2783 4998 94 4 + 2783 1969 21 18 + 2783 4629 28 689 + 3066 1744 77 4 + 3066 2926 37 772 + 3066 332 97 136 + 3076 3223 7 4 + 3076 4141 97 22 + 3223 2783 30 4 + 3223 891 98 884 + 3223 3195 37 514 + 3310 4926 61 4 + 3310 4954 61 422 + 3596 2284 23 4 + 3596 1874 63 206 + 3659 847 76 4 + 3659 3640 22 32 + 125 1993 54 764 + 125 4987 76 870 + 125 3091 95 293 + 664 2548 41 764 + 664 637 13 835 + 1112 2531 72 764 + 1112 3485 25 449 + 1181 4049 65 764 + 1181 478 37 631 + 1181 2186 2 806 + 1993 1181 45 764 + 1993 2201 77 504 + 1993 1525 41 197 + 2531 4271 22 764 + 2531 1503 76 945 + 2531 4226 96 172 + 2548 3751 64 764 + 2548 489 35 981 + 3523 4409 55 764 + 3523 3440 95 732 + 3523 4523 40 738 + 3751 4879 11 764 + 3751 359 57 565 + 4049 3523 1 764 + 4049 4660 26 764 + 4049 4212 67 644 + 4271 664 53 764 + 4271 4598 79 155 + 4271 1712 20 722 + 4409 1112 24 764 + 4409 4155 80 476 + 126 4165 53 735 + 126 584 21 507 + 1438 4500 61 735 + 1438 4798 13 967 + 3139 1438 3 735 + 3139 4992 68 735 + 3139 1051 24 573 + 3648 4994 40 735 + 3648 2837 22 721 + 3648 1622 71 835 + 4165 4248 54 735 + 4165 147 71 593 + 4248 3139 88 735 + 4248 500 79 485 + 4248 4940 29 680 + 4500 3648 90 735 + 4500 4866 2 159 + 127 2147 34 271 + 127 4410 84 207 + 127 3844 82 943 + 1675 4806 38 271 + 1675 3433 52 132 + 2147 2952 17 271 + 2147 39 85 421 + 2147 4785 98 371 + 2952 4306 4 271 + 2952 2164 80 69 + 2952 986 95 186 + 3476 1675 75 271 + 3476 2737 16 898 + 3619 3476 35 271 + 3619 2258 80 9 + 4306 3619 47 271 + 4306 4771 18 271 + 4306 3907 56 556 + 128 2837 21 564 + 128 1928 27 887 + 598 3924 20 564 + 598 4518 82 915 + 2061 3167 61 564 + 2061 2424 26 941 + 2061 325 38 880 + 2651 598 45 564 + 2651 1699 88 20 + 2651 389 30 734 + 2837 2061 47 564 + 2837 4020 89 956 + 3113 2651 59 564 + 3113 2404 47 12 + 3113 2178 70 722 + 3167 3113 76 564 + 3167 4789 33 564 + 3167 3946 93 328 + 3167 994 21 841 + 3924 4853 77 564 + 3924 4269 86 725 + 3924 4869 97 877 + 129 3812 7 28 + 129 1562 38 294 + 903 2198 15 28 + 903 2683 28 412 + 1149 4897 90 28 + 1149 4884 48 28 + 1149 912 80 34 + 1149 1450 74 565 + 1582 903 12 28 + 1582 3299 27 628 + 1582 2590 36 999 + 2198 1149 43 28 + 2198 1144 20 556 + 2198 4263 96 112 + 3631 3992 20 28 + 3631 4895 85 483 + 3631 3912 37 279 + 3812 4222 61 28 + 3812 2515 28 262 + 3846 1582 51 28 + 3846 4482 41 499 + 3846 4056 67 564 + 3992 3846 31 28 + 3992 2691 83 408 + 3992 856 31 57 + 4222 3631 89 28 + 4222 2351 8 138 + 130 1565 64 32 + 130 3887 50 636 + 1091 2754 63 32 + 1091 57 15 30 + 1091 1758 1 487 + 1565 2201 89 32 + 1565 4254 99 150 + 1565 2314 13 227 + 2201 4595 37 32 + 2201 4112 85 32 + 2201 4874 30 499 + 2754 3965 55 32 + 2754 2253 45 309 + 2754 1120 63 529 + 2892 3387 37 32 + 2892 217 44 605 + 3387 1091 89 32 + 3387 4465 53 173 + 3387 1803 81 714 + 3445 2892 78 32 + 3445 4357 34 283 + 3445 169 77 960 + 3965 4767 84 32 + 3965 4426 34 600 + 4112 3445 19 32 + 4112 4597 3 79 + 4112 1924 94 58 + 131 1799 2 822 + 131 4556 21 673 + 131 4570 63 595 + 678 1021 64 822 + 678 4990 75 194 + 1021 3945 76 822 + 1021 4277 96 422 + 1040 3726 37 822 + 1040 3321 40 266 + 1040 4071 2 790 + 1799 4446 4 822 + 1799 4923 42 822 + 1799 2206 8 973 + 3726 4892 8 822 + 3726 2050 49 383 + 3945 4269 89 822 + 3945 228 85 205 + 3945 4522 19 388 + 4269 1040 29 822 + 4269 144 35 525 + 4446 678 64 822 + 4446 2143 53 862 + 4446 817 34 367 + 132 2525 51 654 + 132 1895 70 719 + 132 1168 18 831 + 629 4361 35 654 + 629 2976 76 284 + 629 359 57 794 + 1408 1648 10 654 + 1408 4244 23 285 + 1408 1535 92 408 + 1439 1701 67 654 + 1439 1550 50 471 + 1648 4556 94 654 + 1648 3997 100 654 + 1648 2672 48 568 + 1701 2868 34 654 + 1701 3380 20 511 + 2199 629 45 654 + 2199 339 19 189 + 2199 1600 76 691 + 2525 1408 65 654 + 2525 2053 2 219 + 2857 2199 75 654 + 2857 4895 49 654 + 2857 4005 72 960 + 2857 2821 39 448 + 2868 2908 21 654 + 2868 2080 18 558 + 2868 290 7 821 + 2908 4802 59 654 + 2908 3721 85 178 + 3997 2857 34 654 + 3997 2669 47 849 + 3997 580 35 590 + 4361 1439 75 654 + 4361 1403 86 684 + 4361 756 95 458 + 133 2497 100 561 + 133 1777 51 131 + 1139 4617 9 561 + 1139 211 56 613 + 2497 2956 93 561 + 2497 2803 17 814 + 2780 1139 27 561 + 2780 3344 1 445 + 2780 2169 83 175 + 2956 3019 46 561 + 2956 4965 72 413 + 3019 4060 37 561 + 3019 1628 18 115 + 3019 2506 32 15 + 3776 4117 45 561 + 3776 2299 45 517 + 3776 4820 70 606 + 4060 3776 11 561 + 4060 4715 82 561 + 4060 492 61 872 + 4060 4546 83 438 + 4075 2780 38 561 + 4075 831 33 946 + 4075 2563 94 837 + 4117 4075 10 561 + 4117 135 77 863 + 4117 63 79 713 + 134 660 6 644 + 134 1816 4 489 + 660 2303 41 644 + 660 2500 35 92 + 1459 1953 13 644 + 1459 1188 39 46 + 1459 2692 64 582 + 1834 2436 66 644 + 1834 1833 7 796 + 1953 1834 86 644 + 1953 3624 64 265 + 1953 251 82 647 + 1968 2007 26 644 + 1968 2195 58 730 + 2007 1459 11 644 + 2007 1715 32 750 + 2303 1968 20 644 + 2303 2988 24 205 + 2303 4063 39 107 + 2436 4895 95 644 + 2436 4746 61 644 + 2436 4240 18 67 + 2436 4684 95 715 + 135 3666 1 621 + 135 2190 15 452 + 135 4593 48 459 + 747 1463 70 621 + 747 2066 47 365 + 1463 3377 23 621 + 1463 1927 76 623 + 1463 431 51 453 + 2063 4767 32 621 + 2063 227 14 166 + 2411 2755 89 621 + 2411 4075 45 652 + 2411 2417 85 132 + 2755 3627 15 621 + 2755 4905 53 621 + 2755 3395 27 291 + 3377 2411 74 621 + 3377 1376 29 315 + 3627 2063 48 621 + 3627 4233 99 647 + 3666 747 16 621 + 3666 436 18 794 + 136 2134 65 392 + 136 3839 32 727 + 136 2365 89 308 + 783 4022 2 392 + 783 4956 62 167 + 783 2609 35 390 + 866 783 99 392 + 866 3016 42 306 + 938 2785 63 392 + 938 31 95 769 + 1352 1797 85 392 + 1352 2098 46 692 + 1797 866 78 392 + 1797 303 7 64 + 1797 1049 70 940 + 2134 938 37 392 + 2134 1379 17 3 + 2785 1352 21 392 + 2785 2756 24 440 + 2785 2882 67 86 + 2796 4893 56 392 + 2796 1810 10 388 + 4022 4252 25 392 + 4022 4600 4 392 + 4022 4796 86 128 + 4022 4685 37 214 + 4252 2796 42 392 + 4252 291 73 616 + 137 900 47 964 + 137 4185 47 824 + 137 2051 99 811 + 900 2204 20 964 + 900 1697 28 221 + 900 2493 49 451 + 1405 4069 19 964 + 1405 4465 89 773 + 1805 1405 35 964 + 1805 1453 52 900 + 1805 2929 3 90 + 1944 4996 74 964 + 1944 3144 7 937 + 2204 1805 77 964 + 2204 4904 22 964 + 2204 1203 60 280 + 2535 1944 78 964 + 2535 4303 88 810 + 2535 3415 7 211 + 4069 2535 83 964 + 4069 3519 3 206 + 4069 1305 1 96 + 138 4081 79 108 + 138 1075 15 988 + 138 4232 57 654 + 1114 2078 67 108 + 1114 2360 9 357 + 2078 4399 47 108 + 2078 4613 61 763 + 2078 1780 74 484 + 2527 1114 15 108 + 2527 1486 70 772 + 2527 693 83 281 + 2930 2527 83 108 + 2930 218 80 134 + 2930 931 55 838 + 3018 2930 16 108 + 3018 446 17 363 + 3018 2856 20 847 + 3974 3018 27 108 + 3974 4316 3 697 + 4081 3974 97 108 + 4081 1614 13 874 + 4399 4821 55 108 + 4399 4573 54 108 + 4399 2033 93 197 + 4399 3687 83 37 + 139 4335 46 394 + 139 792 20 410 + 139 4082 4 965 + 659 4860 61 394 + 659 2461 60 72 + 1525 1743 75 394 + 1525 138 27 864 + 1525 2743 4 163 + 1743 4158 77 394 + 1743 4046 35 812 + 1743 4592 97 977 + 1746 1525 71 394 + 1746 3023 28 569 + 2459 3092 2 394 + 2459 3152 89 788 + 2459 3837 24 167 + 3092 659 51 394 + 3092 1493 35 546 + 3238 4280 97 394 + 3238 3582 37 244 + 4158 2459 38 394 + 4158 4702 59 394 + 4158 1764 43 48 + 4280 1746 7 394 + 4280 3187 55 503 + 4280 544 14 130 + 4335 3238 51 394 + 4335 3847 2 516 + 4335 2380 67 335 + 140 2591 16 1149 + 140 4714 44 325 + 140 3703 74 9 + 982 1996 85 1149 + 982 3684 73 558 + 982 4080 20 64 + 1996 3034 29 1149 + 1996 4613 86 1149 + 1996 906 60 247 + 1996 4963 49 76 + 2591 4484 32 1149 + 2591 3792 93 524 + 3034 4976 98 1149 + 3034 3777 45 910 + 4341 982 91 1149 + 4341 1294 11 543 + 4484 4341 75 1149 + 4484 1347 7 996 + 4484 1123 55 290 + 141 3033 89 284 + 141 1191 92 26 + 552 3545 95 284 + 552 437 10 936 + 552 2653 60 705 + 1412 1824 2 284 + 1412 3981 9 278 + 1412 924 71 109 + 1824 4629 79 284 + 1824 4811 63 284 + 1824 4684 36 209 + 1824 4078 90 946 + 2467 552 67 284 + 2467 128 96 789 + 2467 673 89 398 + 2834 2467 85 284 + 2834 375 21 955 + 3033 2834 93 284 + 3033 4597 82 408 + 3033 4499 26 628 + 3545 4214 52 284 + 3545 3725 87 900 + 4214 1412 92 284 + 4214 2377 25 57 + 4214 1319 30 573 + 142 2604 62 433 + 142 4060 64 690 + 142 2123 90 783 + 566 4791 17 433 + 566 4567 34 737 + 566 4291 76 481 + 789 566 65 433 + 789 2826 61 487 + 789 6 47 257 + 1166 3096 43 433 + 1166 2782 96 645 + 1166 2808 62 680 + 2003 4841 7 433 + 2003 3914 33 433 + 2003 3193 33 376 + 2374 1166 42 433 + 2374 976 36 483 + 2374 571 9 338 + 2604 2003 14 433 + 2604 2912 39 98 + 3096 789 24 433 + 3096 682 8 402 + 3402 4240 20 433 + 3402 2935 26 43 + 3554 2374 21 433 + 3554 1113 97 364 + 3914 3402 71 433 + 3914 669 65 731 + 4240 3554 96 433 + 4240 1376 6 94 + 4240 900 66 397 + 143 844 34 346 + 143 91 45 771 + 143 2657 33 456 + 502 3245 92 346 + 502 2215 62 138 + 844 1889 19 346 + 844 2679 84 535 + 884 502 11 346 + 884 1377 23 30 + 884 4443 14 37 + 1889 3057 11 346 + 1889 1097 53 874 + 2645 4762 69 346 + 2645 1973 50 840 + 2645 2630 55 445 + 3057 4296 52 346 + 3057 4692 97 128 + 3245 4764 89 346 + 3245 4435 3 346 + 3245 510 99 5 + 3245 1963 55 928 + 4296 884 17 346 + 4296 896 53 294 + 4435 2645 1 346 + 4435 4081 62 73 + 144 2105 2 168 + 144 525 100 589 + 144 605 47 287 + 522 4872 12 168 + 522 1453 20 233 + 784 1915 23 168 + 784 4759 41 136 + 784 2463 92 518 + 1915 2423 5 168 + 1915 464 44 425 + 1915 2404 17 455 + 2105 4374 62 168 + 2105 3321 7 391 + 2105 1546 49 777 + 2217 3794 57 168 + 2217 966 3 621 + 2217 3056 60 880 + 2423 522 8 168 + 2423 4677 87 168 + 2423 951 24 636 + 2423 2368 69 610 + 2972 2217 51 168 + 2972 3811 50 855 + 3794 784 70 168 + 3794 1949 3 704 + 4374 2972 89 168 + 4374 2433 18 805 + 145 4444 66 982 + 145 3341 69 554 + 145 897 80 164 + 583 1174 81 982 + 583 1128 57 810 + 770 583 46 982 + 770 850 83 278 + 1174 4715 68 982 + 1174 3271 73 66 + 1174 2077 44 861 + 3062 4311 57 982 + 3062 4993 79 982 + 3062 4247 88 111 + 4311 770 82 982 + 4311 325 76 618 + 4444 3062 42 982 + 4444 4434 1 11 + 146 3260 67 790 + 146 1511 58 874 + 1587 3753 25 790 + 1587 2548 47 317 + 2074 4903 41 790 + 2074 4053 70 887 + 2074 719 100 432 + 3260 1587 38 790 + 3260 588 85 928 + 3260 4761 4 209 + 3753 4072 62 790 + 3753 369 50 245 + 3981 2074 25 790 + 3981 1852 73 578 + 3981 1754 28 257 + 4072 4179 83 790 + 4072 4601 64 790 + 4072 1505 2 676 + 4072 1326 71 403 + 4179 3981 81 790 + 4179 4802 5 309 + 4179 1935 32 694 + 147 3071 36 469 + 147 3942 11 241 + 147 2741 21 509 + 526 3369 7 469 + 526 3362 63 64 + 1260 3942 63 469 + 1260 4089 2 725 + 2914 4197 38 469 + 2914 1871 34 876 + 3071 2914 61 469 + 3071 1008 48 767 + 3258 3968 14 469 + 3258 4860 27 469 + 3258 355 98 132 + 3258 425 73 390 + 3369 4396 89 469 + 3369 2158 21 860 + 3942 526 94 469 + 3942 2620 51 865 + 3968 4576 42 469 + 3968 3473 84 917 + 4197 1260 54 469 + 4197 3690 95 623 + 4396 3258 91 469 + 4396 4110 50 387 + 148 865 36 287 + 148 3154 45 303 + 865 2948 96 287 + 865 4598 28 287 + 865 4387 3 739 + 865 4447 72 810 + 1670 2445 91 287 + 1670 1654 91 1000 + 1670 3422 16 340 + 2176 1670 44 287 + 2176 4864 83 580 + 2445 2509 10 287 + 2445 2282 72 329 + 2509 4931 13 287 + 2509 243 15 855 + 2509 3203 97 786 + 2948 2176 36 287 + 2948 3331 60 459 + 149 4364 83 427 + 149 2765 49 322 + 762 1727 73 427 + 762 4078 69 255 + 888 2111 64 427 + 888 311 57 42 + 1421 4118 50 427 + 1421 4582 14 761 + 1421 3259 54 416 + 1727 4101 44 427 + 1727 4283 9 601 + 1727 3345 19 193 + 2111 1421 77 427 + 2111 1061 64 339 + 2111 4690 28 27 + 2471 762 51 427 + 2471 4605 16 427 + 2471 1117 95 467 + 4101 4760 43 427 + 4101 3619 58 243 + 4118 2471 78 427 + 4118 4842 45 31 + 4364 888 57 427 + 4364 4082 45 883 + 150 3184 41 763 + 150 2928 66 501 + 589 777 67 763 + 589 3922 43 445 + 589 1237 31 632 + 777 1416 81 763 + 777 932 41 145 + 777 1917 53 950 + 1416 3430 95 763 + 1416 4977 28 763 + 1416 4483 28 23 + 3184 4202 31 763 + 3184 4900 19 902 + 3184 2263 19 95 + 3430 4647 55 763 + 3430 2094 99 224 + 3430 2603 31 332 + 4202 589 87 763 + 4202 3459 23 459 + 4202 1031 4 278 + 151 3389 79 407 + 151 3457 12 340 + 612 2040 64 407 + 612 3191 65 2 + 612 485 61 73 + 804 3662 43 407 + 804 4291 43 23 + 804 4394 62 35 + 1227 3497 75 407 + 1227 4827 76 816 + 2040 804 26 407 + 2040 1184 81 140 + 2805 1227 59 407 + 2805 2649 69 303 + 2805 756 44 685 + 3389 612 97 407 + 3389 3208 49 672 + 3497 4692 58 407 + 3497 4359 85 551 + 3662 3890 82 407 + 3662 4883 79 407 + 3662 2077 24 86 + 3662 4330 5 881 + 3890 2805 5 407 + 3890 3265 15 280 + 3890 3305 52 1 + 152 3586 62 323 + 152 3457 90 763 + 1552 2896 23 323 + 1552 3728 91 890 + 2029 3701 44 323 + 2029 3505 10 416 + 2873 2029 42 323 + 2873 3334 68 254 + 2896 3283 89 323 + 2896 1497 8 225 + 2896 76 87 68 + 3283 4359 94 323 + 3283 4637 11 323 + 3283 2985 98 761 + 3586 2873 34 323 + 3586 4702 74 413 + 3701 3825 27 323 + 3701 4964 82 295 + 3825 1552 96 323 + 3825 3781 23 724 + 3825 1772 61 276 + 4359 4829 64 323 + 4359 4296 58 681 + 153 4184 51 776 + 153 529 42 847 + 1076 4537 96 776 + 1076 3570 12 82 + 1076 4410 55 768 + 1931 1076 20 776 + 1931 1393 85 784 + 3796 4676 43 776 + 3796 1931 50 776 + 3796 448 52 367 + 3796 3715 62 314 + 4184 4393 33 776 + 4184 513 95 767 + 4393 3796 87 776 + 4393 1252 26 977 + 154 3599 19 1109 + 154 564 16 6 + 154 1947 60 285 + 810 1244 33 1109 + 810 4957 42 61 + 810 4467 52 730 + 1177 3232 78 1109 + 1177 671 43 469 + 1177 554 39 921 + 1244 4893 68 1109 + 1244 1856 40 362 + 1244 2133 83 922 + 2259 810 25 1109 + 2259 3132 2 40 + 2259 4765 8 586 + 3232 2259 97 1109 + 3232 4640 1 1109 + 3232 4985 95 927 + 3232 2464 26 81 + 3599 1177 63 1109 + 3599 2220 6 58 + 3599 2092 81 300 + 155 501 49 896 + 155 1905 92 377 + 501 1841 6 896 + 501 4621 67 896 + 501 1402 100 148 + 501 1863 64 988 + 827 2687 41 896 + 827 213 72 810 + 827 4248 67 647 + 1841 827 96 896 + 1841 1484 56 166 + 2687 3399 66 896 + 2687 898 28 566 + 3399 4726 78 896 + 3399 3934 70 786 + 3399 4651 3 600 + 156 1455 2 288 + 156 428 42 902 + 525 4583 53 288 + 525 2203 95 57 + 525 197 87 456 + 975 3844 62 288 + 975 1842 44 554 + 1118 525 40 288 + 1118 592 1 672 + 1118 1612 56 493 + 1345 3892 11 288 + 1345 2758 61 984 + 1345 1963 63 332 + 1455 4953 45 288 + 1455 4033 23 288 + 1455 3167 22 555 + 1455 3639 10 512 + 3844 1345 71 288 + 3844 4147 37 53 + 3892 1118 47 288 + 3892 680 56 539 + 3892 4073 4 591 + 4033 4354 3 288 + 4033 663 31 189 + 4033 201 72 973 + 4354 975 85 288 + 4354 2219 39 271 + 4354 1730 18 182 + 157 4237 35 680 + 157 2116 99 342 + 157 2488 78 412 + 1760 3744 85 680 + 1760 2328 64 291 + 1760 4646 100 50 + 2128 4417 35 680 + 2128 379 67 576 + 2312 4879 50 680 + 2312 2394 98 69 + 2728 3063 18 680 + 2728 708 83 589 + 2817 2728 23 680 + 2817 3789 23 145 + 2817 2960 65 649 + 3063 1760 1 680 + 3063 3149 73 591 + 3063 162 71 714 + 3744 2128 11 680 + 3744 3051 73 409 + 3947 4638 36 680 + 3947 2312 6 680 + 3947 2854 97 411 + 3947 4619 87 582 + 4237 2817 40 680 + 4237 2534 9 473 + 4417 3947 67 680 + 4417 3364 11 605 + 158 2428 84 1632 + 158 4403 51 450 + 910 3921 11 1632 + 910 4614 99 524 + 910 3175 32 220 + 939 2655 28 1632 + 939 4145 69 958 + 939 1357 82 594 + 1940 2670 99 1632 + 1940 4710 41 1632 + 1940 1307 69 260 + 2065 4660 37 1632 + 2065 4448 60 150 + 2428 1940 49 1632 + 2428 2600 90 127 + 2655 910 25 1632 + 2655 2257 84 622 + 2655 1462 37 407 + 2670 939 74 1632 + 2670 1810 65 333 + 3921 2065 73 1632 + 3921 1173 28 704 + 159 3672 75 385 + 159 3077 72 203 + 159 1473 26 511 + 579 3293 11 385 + 579 1752 78 135 + 579 4647 39 952 + 790 4750 13 385 + 790 681 90 967 + 1071 1160 41 385 + 1071 3135 37 535 + 1160 3366 67 385 + 1160 3628 34 957 + 1385 2751 21 385 + 1385 624 35 485 + 2751 3677 61 385 + 2751 4012 24 626 + 3293 1385 51 385 + 3293 2496 41 24 + 3293 467 84 484 + 3366 579 100 385 + 3366 2747 92 148 + 3672 1071 71 385 + 3672 4976 30 385 + 3672 3284 50 123 + 3672 2428 20 208 + 3677 790 35 385 + 3677 1577 26 867 + 160 3589 62 364 + 160 619 83 667 + 160 1778 89 801 + 881 1125 99 364 + 881 3647 89 342 + 1039 1856 29 364 + 1039 708 53 434 + 1039 3704 83 974 + 1125 2574 51 364 + 1125 4960 96 364 + 1125 4614 22 597 + 1125 910 1 90 + 1856 2982 95 364 + 1856 1195 85 106 + 1856 2441 40 135 + 1862 1039 29 364 + 1862 3931 32 549 + 2574 1862 86 364 + 2574 4154 32 936 + 2574 2115 6 169 + 2898 881 67 364 + 2898 815 39 336 + 2898 2146 87 414 + 2982 4581 15 364 + 2982 2350 22 211 + 2982 788 96 283 + 3589 2898 73 364 + 3589 3483 97 178 + 161 3887 58 1053 + 161 4993 55 503 + 673 1527 88 1053 + 673 837 25 554 + 822 4143 5 1053 + 822 4982 20 43 + 1527 2777 81 1053 + 1527 501 42 388 + 2366 4920 51 1053 + 2366 4828 27 1053 + 2366 1295 90 617 + 2777 4020 4 1053 + 2777 3193 45 97 + 2777 3024 6 508 + 2994 673 90 1053 + 2994 607 73 116 + 3887 2994 13 1053 + 3887 4893 19 281 + 3887 1589 97 244 + 4020 822 96 1053 + 4020 4904 91 360 + 4020 3773 61 861 + 4143 2366 94 1053 + 4143 469 86 879 + 162 2564 15 382 + 162 2026 70 338 + 1024 2750 38 382 + 1024 4735 14 382 + 1024 3907 84 7 + 1024 4638 13 426 + 1451 1024 58 382 + 1451 3725 99 754 + 2564 2918 11 382 + 2564 4072 81 293 + 2750 4649 99 382 + 2750 1607 46 645 + 2750 1888 9 686 + 2918 1451 34 382 + 2918 1403 93 762 + 163 2127 94 582 + 163 3987 45 308 + 163 391 57 704 + 1312 4005 63 582 + 1312 2082 39 41 + 1762 3417 1 582 + 1762 4672 81 582 + 1762 560 40 224 + 2127 3919 71 582 + 2127 4131 100 369 + 3417 1312 69 582 + 3417 3561 91 626 + 3919 1762 13 582 + 3919 1079 79 543 + 3919 2970 97 574 + 4005 4697 75 582 + 4005 1670 79 582 + 4005 3172 19 731 + 164 702 70 378 + 164 1795 70 625 + 692 4797 11 378 + 692 4695 16 378 + 692 2750 68 879 + 702 3553 71 378 + 702 3853 98 104 + 702 4604 74 207 + 3098 3257 55 378 + 3098 2757 17 127 + 3098 1537 72 828 + 3257 3682 9 378 + 3257 3627 56 603 + 3257 1553 62 450 + 3304 3098 92 378 + 3304 4956 48 117 + 3304 4657 26 198 + 3553 3304 83 378 + 3553 4400 2 401 + 3553 3770 26 400 + 3682 692 29 378 + 3682 784 12 192 + 165 961 49 217 + 165 1380 48 692 + 961 2784 74 217 + 961 2345 2 867 + 961 1756 55 253 + 1320 2420 51 217 + 1320 2368 12 648 + 1320 1715 55 632 + 1381 2306 90 217 + 1381 1271 2 747 + 1717 4922 25 217 + 1717 4773 60 973 + 1717 3259 86 878 + 2306 4264 85 217 + 2306 4614 52 294 + 2420 4667 3 217 + 2420 2771 20 217 + 2420 4577 75 330 + 2420 4412 35 896 + 2771 4208 46 217 + 2771 2495 82 293 + 2784 2882 6 217 + 2784 4701 52 235 + 2882 1320 73 217 + 2882 2780 6 457 + 4208 1381 14 217 + 4208 1141 15 811 + 4264 1717 9 217 + 4264 1573 100 459 + 166 3886 28 412 + 166 3909 77 439 + 1253 1997 25 412 + 1253 362 97 14 + 1997 4797 83 412 + 1997 1817 44 780 + 2009 1253 59 412 + 2009 3142 30 256 + 2309 2009 18 412 + 2309 815 82 985 + 2309 2355 62 464 + 3475 2309 55 412 + 3475 4606 26 412 + 3475 3507 92 66 + 3475 4006 10 312 + 3886 3475 43 412 + 3886 1791 89 136 + 3886 1869 78 179 + 167 4260 31 378 + 167 1040 11 157 + 167 2308 68 828 + 607 932 81 378 + 607 2639 83 513 + 932 3895 67 378 + 932 591 33 305 + 932 3264 33 537 + 2550 3198 7 378 + 2550 3578 54 538 + 2550 1683 72 993 + 2663 4748 25 378 + 2663 4895 47 378 + 2663 478 78 838 + 3198 2663 91 378 + 3198 89 48 122 + 3198 3062 27 370 + 3823 2550 42 378 + 3823 3836 83 347 + 3895 3823 20 378 + 3895 893 25 549 + 4260 607 22 378 + 4260 1714 70 39 + 4260 1038 19 777 + 168 2513 56 371 + 168 1425 90 794 + 168 253 18 388 + 562 3562 51 371 + 562 2570 75 189 + 562 376 52 318 + 616 4934 77 371 + 616 3055 46 371 + 616 294 41 299 + 616 1626 41 692 + 2513 3668 6 371 + 2513 423 2 621 + 2513 4207 23 345 + 2848 3580 54 371 + 2848 2368 47 885 + 2848 3362 64 921 + 3055 3099 76 371 + 3055 990 36 554 + 3055 4638 4 339 + 3099 562 27 371 + 3099 1711 69 233 + 3099 387 10 279 + 3562 3814 9 371 + 3562 2971 93 527 + 3562 2047 29 976 + 3580 3703 46 371 + 3580 413 74 246 + 3580 3272 75 443 + 3668 2848 77 371 + 3668 2764 67 886 + 3703 616 53 371 + 3703 2004 12 665 + 3814 4585 27 371 + 3814 1013 51 42 + 3814 4249 77 224 + 169 2409 28 420 + 169 4148 6 931 + 169 2556 93 512 + 1100 2069 99 420 + 1100 4926 71 423 + 1698 4633 16 420 + 1698 4590 48 769 + 1811 2584 75 420 + 1811 4612 62 356 + 1811 4810 92 113 + 2069 4757 83 420 + 2069 1811 8 420 + 2069 3603 72 504 + 2069 4393 69 267 + 2324 3436 38 420 + 2324 2885 81 937 + 2409 2324 45 420 + 2409 4553 92 513 + 2409 1120 5 497 + 2584 1698 49 420 + 2584 1322 24 785 + 2584 4061 86 532 + 3436 1100 36 420 + 3436 4956 76 114 + 170 1801 13 1017 + 170 3196 73 82 + 170 1505 86 258 + 665 779 76 1017 + 665 4306 53 648 + 779 4405 85 1017 + 779 4265 4 90 + 779 2909 89 796 + 992 665 22 1017 + 992 1103 16 27 + 992 1382 55 79 + 1361 2741 67 1017 + 1361 4816 74 639 + 1361 895 67 909 + 1801 4633 63 1017 + 1801 3782 47 1017 + 1801 3096 59 13 + 1801 2934 27 518 + 2741 4091 56 1017 + 2741 3436 3 95 + 3782 1361 87 1017 + 3782 4164 67 790 + 4091 4368 64 1017 + 4091 1943 59 981 + 4368 992 3 1017 + 4368 16 7 708 + 4368 2046 88 736 + 4405 4745 62 1017 + 4405 1958 31 740 + 4405 3636 2 15 + 171 2395 72 719 + 171 4135 8 921 + 171 4728 41 685 + 1539 1725 47 719 + 1539 2128 31 550 + 1725 2669 33 719 + 1725 2902 75 316 + 1725 2209 40 381 + 2395 2880 85 719 + 2395 340 80 728 + 2395 3890 98 842 + 2669 4856 36 719 + 2669 3716 99 1000 + 2880 3079 60 719 + 2880 1840 91 622 + 2880 2826 26 440 + 3079 1539 22 719 + 3079 4937 3 719 + 3079 1322 15 801 + 3079 3186 61 756 + 172 3420 64 24 + 172 3232 71 11 + 734 769 45 24 + 734 796 50 10 + 769 4587 57 24 + 769 4842 25 24 + 769 1449 39 378 + 769 2599 42 825 + 1237 2766 50 24 + 1237 4270 35 29 + 1237 2300 81 180 + 2766 734 77 24 + 2766 2336 66 702 + 2992 1237 13 24 + 2992 1015 80 141 + 2992 1181 35 165 + 3420 2992 42 24 + 3420 4916 53 307 + 173 3146 3 476 + 173 1662 76 798 + 173 1909 66 846 + 874 2664 39 476 + 874 310 3 27 + 1162 874 70 476 + 1162 3372 78 297 + 1162 4154 48 309 + 2576 3135 45 476 + 2576 1697 49 44 + 2664 4542 65 476 + 2664 3597 41 984 + 3135 4625 37 476 + 3135 1162 68 476 + 3135 4061 45 687 + 3135 448 33 998 + 3146 4161 44 476 + 3146 4004 100 869 + 4161 2576 35 476 + 4161 3684 68 389 + 174 3749 37 692 + 174 648 81 995 + 1115 4291 58 692 + 1115 651 93 580 + 1115 1010 15 590 + 2362 4390 52 692 + 2362 4509 24 692 + 2362 2951 80 384 + 2362 2630 59 259 + 3664 4880 68 692 + 3664 736 32 51 + 3664 1941 78 792 + 3749 1115 52 692 + 3749 3625 28 263 + 3749 4257 61 52 + 4291 2362 8 692 + 4291 4315 98 792 + 4390 3664 26 692 + 4390 96 81 366 + 175 1397 41 334 + 175 3617 58 252 + 1397 2585 38 334 + 1397 3031 92 532 + 1397 3842 88 45 + 2281 3473 11 334 + 2281 1676 8 392 + 2281 1692 65 60 + 2585 3986 41 334 + 2585 4850 68 334 + 2585 3478 35 115 + 2744 2281 67 334 + 2744 1271 47 504 + 2744 3945 39 205 + 2937 4604 72 334 + 2937 3410 77 176 + 3473 2937 99 334 + 3473 4767 98 951 + 3473 2713 37 463 + 3986 2744 4 334 + 3986 1060 15 589 + 176 763 44 426 + 176 1162 69 174 + 176 1775 36 536 + 763 2931 68 426 + 763 4340 93 254 + 763 913 66 791 + 2192 4963 13 426 + 2192 2310 56 623 + 2205 2967 4 426 + 2205 2795 77 389 + 2775 3542 24 426 + 2775 1707 98 178 + 2775 207 58 421 + 2931 2775 25 426 + 2931 4955 96 391 + 2931 658 91 440 + 2967 2192 97 426 + 2967 4342 41 273 + 3542 2205 62 426 + 3542 4929 61 426 + 3542 3761 70 771 + 3542 1640 48 943 + 177 1645 85 26 + 177 603 88 814 + 892 2625 94 26 + 892 2977 100 844 + 892 3419 60 435 + 1645 892 38 26 + 1645 4589 43 26 + 1645 3455 97 264 + 1645 1893 28 360 + 1956 4360 85 26 + 1956 1988 64 752 + 2625 4279 71 26 + 2625 4149 95 262 + 2625 470 35 946 + 2954 4671 13 26 + 2954 657 45 521 + 2954 4790 96 560 + 4279 1956 14 26 + 4279 4354 37 189 + 4279 3564 92 148 + 4360 2954 53 26 + 4360 2037 22 125 + 178 3808 67 71 + 178 1550 50 992 + 1447 4549 5 71 + 1447 4703 97 71 + 1447 4775 44 551 + 1447 4506 22 303 + 2472 2851 59 71 + 2472 232 72 775 + 2851 4385 14 71 + 2851 4944 77 94 + 3808 2472 93 71 + 3808 4641 79 893 + 3808 867 2 689 + 4385 1447 28 71 + 4385 4824 5 413 + 4385 1984 72 491 + 179 3687 6 45 + 179 3045 60 241 + 179 1887 87 890 + 1386 3401 50 45 + 1386 4981 29 45 + 1386 4034 98 58 + 1545 2709 51 45 + 1545 2715 38 360 + 1545 3227 7 926 + 2709 3875 72 45 + 2709 1212 80 603 + 2709 1553 97 486 + 3401 1545 41 45 + 3401 93 2 494 + 3401 1233 82 261 + 3687 1386 78 45 + 3687 1228 63 777 + 3875 4976 64 45 + 3875 4608 52 131 + 180 4366 16 97 + 180 778 79 317 + 978 3213 64 97 + 978 2071 33 507 + 978 2680 86 161 + 1146 4173 12 97 + 1146 862 40 616 + 1146 1724 75 36 + 1750 978 94 97 + 1750 1427 21 100 + 1750 3950 65 44 + 2361 1750 61 97 + 2361 4611 96 97 + 2361 3365 71 949 + 2361 4782 88 499 + 3201 4916 54 97 + 3201 4342 15 740 + 3201 2133 2 318 + 3213 1146 50 97 + 3213 1701 13 195 + 3213 1376 82 531 + 4173 3201 31 97 + 4173 4514 60 684 + 4173 4200 8 225 + 4366 2361 49 97 + 4366 416 74 668 + 4366 4407 50 424 + 181 1624 100 619 + 181 4493 3 842 + 181 3159 43 138 + 698 1400 49 619 + 698 37 66 273 + 698 906 44 583 + 1400 4791 11 619 + 1400 1392 29 229 + 1624 4082 12 619 + 1624 3987 60 688 + 2071 4645 83 619 + 2071 3756 49 619 + 2071 2811 63 767 + 2071 3371 58 625 + 3756 4474 41 619 + 3756 4684 30 985 + 3756 3183 14 369 + 4082 4178 99 619 + 4082 330 67 349 + 4178 2071 32 619 + 4178 4712 98 133 + 4474 698 39 619 + 4474 341 66 475 + 182 1137 74 803 + 182 1051 33 749 + 182 4160 10 103 + 1137 2881 13 803 + 1137 3651 81 734 + 1137 4082 58 906 + 1506 3819 13 803 + 1506 2014 66 851 + 1506 2967 18 223 + 2501 1506 40 803 + 2501 2538 6 920 + 2501 4541 82 424 + 2721 3717 61 803 + 2721 4305 32 461 + 2721 402 22 313 + 2738 4980 95 803 + 2738 4799 43 396 + 2738 3115 97 613 + 2881 2501 87 803 + 2881 1100 85 702 + 2973 2721 54 803 + 2973 4851 58 187 + 3623 2973 17 803 + 3623 4549 23 803 + 3623 3861 95 942 + 3717 2738 18 803 + 3717 3553 44 900 + 3819 3623 90 803 + 3819 2305 7 798 + 3819 1700 25 912 + 183 942 40 236 + 183 2355 60 227 + 879 3988 5 236 + 879 4347 39 953 + 942 2030 86 236 + 942 3270 54 729 + 1204 879 16 236 + 1204 4906 83 360 + 1204 2925 4 844 + 2030 1204 2 236 + 2030 4694 59 577 + 2288 2619 61 236 + 2288 4741 11 236 + 2288 3085 22 44 + 2288 1113 82 492 + 2619 4810 56 236 + 2619 828 48 925 + 3988 2288 88 236 + 3988 778 84 203 + 3988 633 5 478 + 184 2639 5 293 + 184 4235 15 317 + 184 1643 12 610 + 1639 4768 22 293 + 1639 1245 44 635 + 1639 4439 45 89 + 1980 3643 88 293 + 1980 379 88 764 + 2639 3669 49 293 + 2639 441 82 528 + 2639 329 69 484 + 3643 4386 24 293 + 3643 1004 96 488 + 3669 3931 8 293 + 3669 4260 90 771 + 3669 4080 30 625 + 3931 4707 72 293 + 3931 1980 83 293 + 3931 1462 40 897 + 3931 81 58 917 + 4386 1639 23 293 + 4386 3052 24 91 + 185 3085 69 571 + 185 822 8 423 + 1540 2320 20 571 + 1540 3318 64 728 + 1540 4718 48 284 + 1636 4608 57 571 + 1636 4604 13 571 + 1636 1188 62 169 + 1742 2804 33 571 + 1742 925 24 903 + 1742 1960 63 372 + 2159 1742 43 571 + 2159 3213 95 860 + 2320 1636 15 571 + 2320 3067 12 549 + 2390 1540 54 571 + 2390 3219 86 61 + 2390 4089 46 602 + 2804 2390 97 571 + 2804 1861 64 826 + 3085 2159 5 571 + 3085 4476 21 735 + 186 2448 36 497 + 186 3572 68 738 + 1129 1277 28 497 + 1129 4745 99 118 + 1277 4880 72 497 + 1277 2929 95 497 + 1277 4659 16 253 + 1633 2184 48 497 + 1633 4819 10 743 + 1633 2276 56 763 + 2184 3649 52 497 + 2184 823 92 576 + 2448 1633 65 497 + 2448 2484 44 522 + 2448 3462 37 267 + 2929 3152 63 497 + 2929 1203 8 387 + 2929 963 62 984 + 3152 4578 20 497 + 3152 888 77 202 + 3152 2650 11 929 + 3649 1129 94 497 + 3649 1169 29 943 + 3649 3644 97 457 + 187 2599 68 390 + 187 446 8 782 + 187 2558 91 240 + 935 2346 50 390 + 935 113 26 881 + 2285 4328 26 390 + 2285 2952 74 654 + 2285 1792 77 301 + 2346 3758 33 390 + 2346 4961 95 276 + 2346 2275 83 478 + 2599 2285 46 390 + 2599 160 89 775 + 3153 4928 3 390 + 3153 250 93 468 + 3307 935 61 390 + 3307 4339 80 931 + 3307 1942 76 125 + 3758 3153 30 390 + 3758 4988 27 390 + 3758 3486 100 197 + 3758 4202 83 854 + 4328 3307 7 390 + 4328 1555 72 548 + 4328 44 70 385 + 188 3559 18 451 + 188 597 93 255 + 949 1080 10 451 + 949 1877 46 211 + 949 2423 39 250 + 1080 1739 27 451 + 1080 49 20 278 + 1080 780 15 892 + 1498 3501 100 451 + 1498 4541 57 451 + 1498 266 71 16 + 1498 1136 10 888 + 1739 1498 91 451 + 1739 1385 71 747 + 2017 4798 6 451 + 2017 3450 53 482 + 2017 4571 2 920 + 3490 949 58 451 + 3490 3951 37 903 + 3490 3240 88 764 + 3501 2017 69 451 + 3501 2400 29 977 + 3501 3957 52 126 + 3559 3490 85 451 + 3559 4500 49 594 + 189 708 95 545 + 189 4237 79 784 + 708 3906 24 545 + 708 4508 2 545 + 708 4311 3 854 + 708 3313 24 733 + 1974 2123 19 545 + 1974 3500 21 234 + 1974 2761 77 854 + 2123 2446 20 545 + 2123 4057 13 619 + 2123 4271 15 199 + 2426 3966 94 545 + 2426 3631 25 997 + 2426 1702 61 890 + 2446 4822 97 545 + 2446 3377 1 173 + 3906 2426 1 545 + 3906 2461 58 905 + 3966 1974 15 545 + 3966 2280 42 282 + 190 4116 8 524 + 190 2149 6 569 + 799 1919 74 524 + 799 2581 21 131 + 1591 799 93 524 + 1591 1192 36 263 + 1919 3515 76 524 + 1919 2717 40 511 + 1919 4008 98 793 + 2271 4759 88 524 + 2271 4846 96 524 + 2271 2784 24 253 + 2271 3431 80 561 + 3515 3913 84 524 + 3515 556 16 860 + 3913 2271 44 524 + 3913 4350 100 664 + 3913 2735 41 586 + 4116 4404 56 524 + 4116 205 67 943 + 4404 1591 70 524 + 4404 3045 4 607 + 191 1718 80 27 + 191 4569 63 388 + 191 1735 40 299 + 529 3508 97 27 + 529 1186 69 4 + 550 2493 79 27 + 550 945 35 87 + 1718 550 52 27 + 1718 4815 45 116 + 1740 4949 81 27 + 1740 203 28 97 + 1740 3514 74 816 + 2493 529 1 27 + 2493 4954 12 27 + 2493 1971 95 673 + 3508 1740 6 27 + 3508 2246 50 977 + 192 3267 42 402 + 192 3082 40 585 + 192 631 37 485 + 625 4540 94 402 + 625 4929 49 968 + 1353 1715 96 402 + 1353 1289 85 137 + 1695 4402 22 402 + 1695 3701 55 769 + 1715 4892 37 402 + 1715 2136 5 402 + 1715 4391 34 497 + 1715 4013 93 67 + 2136 1695 52 402 + 2136 3599 79 278 + 2136 243 32 885 + 2907 625 65 402 + 2907 2107 37 151 + 2907 3797 60 222 + 3267 3694 68 402 + 3267 1568 92 650 + 3694 1353 54 402 + 3694 4959 56 311 + 3694 4443 27 74 + 4402 2907 55 402 + 4402 250 50 394 + 193 730 97 468 + 193 4684 70 965 + 599 3532 10 468 + 599 3962 5 10 + 730 2570 63 468 + 730 4633 10 201 + 730 4033 38 991 + 1132 1930 58 468 + 1132 3687 24 525 + 1209 1132 70 468 + 1209 3351 57 278 + 1930 2450 7 468 + 1930 2914 38 791 + 1930 3853 41 420 + 2450 4954 70 468 + 2450 2052 5 518 + 2450 3252 92 845 + 2570 599 28 468 + 2570 4183 52 25 + 3532 1209 8 468 + 3532 4845 37 468 + 3532 1343 31 636 + 194 3540 60 721 + 194 3544 97 123 + 194 3036 63 566 + 570 2612 56 721 + 570 4479 98 16 + 570 3850 51 843 + 921 4833 11 721 + 921 1927 17 721 + 921 1565 50 441 + 1246 570 64 721 + 1246 2014 23 115 + 1246 1890 19 365 + 1682 2104 73 721 + 1682 2920 64 853 + 1927 4463 63 721 + 1927 4364 66 578 + 2104 1246 94 721 + 2104 4501 95 780 + 2104 4783 79 849 + 2612 4745 5 721 + 2612 167 22 568 + 2768 921 26 721 + 2768 450 38 135 + 2768 4139 40 253 + 3540 2768 48 721 + 3540 1320 2 63 + 3540 3259 5 568 + 4024 1682 87 721 + 4024 960 2 541 + 4463 4024 29 721 + 4463 1106 23 799 + 195 2711 36 497 + 195 3230 87 843 + 794 2545 25 497 + 794 295 9 192 + 1716 3597 84 497 + 1716 3373 44 812 + 2218 1716 63 497 + 2218 4578 8 993 + 2545 4227 2 497 + 2545 1233 64 931 + 2545 959 3 459 + 2587 2218 77 497 + 2587 4256 29 335 + 2711 794 60 497 + 2711 3525 85 764 + 3320 4687 33 497 + 3320 3378 18 497 + 3320 3381 58 423 + 3320 1556 10 109 + 3378 4987 36 497 + 3378 3623 94 702 + 3378 4903 2 613 + 3597 3320 26 497 + 3597 689 70 946 + 3597 2743 60 715 + 4227 2587 47 497 + 4227 4508 20 429 + 196 2108 41 584 + 196 340 61 440 + 196 179 7 603 + 1414 2919 93 584 + 1414 4394 50 863 + 1477 1414 1 584 + 1477 1630 32 81 + 1505 4984 37 584 + 1505 4694 97 584 + 1505 1176 37 268 + 1596 1477 96 584 + 1596 1394 76 267 + 1596 1046 55 775 + 2108 1596 18 584 + 2108 2935 22 71 + 2108 1895 40 39 + 2919 1505 10 584 + 2919 4841 45 932 + 2919 1614 55 327 + 197 3865 30 630 + 197 2580 77 448 + 719 4078 2 630 + 719 4869 43 630 + 719 3557 77 839 + 846 3600 45 630 + 846 4965 47 829 + 1435 2272 22 630 + 1435 3803 51 333 + 1803 1435 38 630 + 1803 2101 56 632 + 1803 565 69 632 + 2272 719 19 630 + 2272 3553 62 225 + 3600 4939 80 630 + 3600 3189 53 642 + 3865 1803 85 630 + 3865 2297 5 556 + 4078 846 11 630 + 4078 3392 55 136 + 4078 4389 36 238 + 198 1775 78 755 + 198 122 43 937 + 198 968 64 773 + 1330 3477 53 755 + 1330 2669 76 518 + 1330 4415 93 652 + 1775 4475 18 755 + 1775 3869 78 937 + 2662 3414 14 755 + 2662 1188 86 17 + 3414 1330 30 755 + 3414 2945 21 403 + 3414 1211 24 259 + 3477 4309 44 755 + 3477 4590 19 755 + 3477 80 25 235 + 3477 3222 74 669 + 3609 3630 62 755 + 3609 523 62 320 + 3609 2263 58 864 + 3630 2662 99 755 + 3630 3389 47 676 + 4309 4792 93 755 + 4309 1649 93 583 + 4309 270 31 386 + 4475 3609 49 755 + 4475 47 13 292 + 199 1295 52 308 + 199 2003 14 893 + 199 4091 44 551 + 1295 3424 9 308 + 1295 3754 89 668 + 1722 3357 44 308 + 1722 1572 3 931 + 2691 1722 73 308 + 2691 155 60 613 + 3357 4535 9 308 + 3357 3410 29 595 + 3407 2691 26 308 + 3407 1558 18 647 + 3407 463 69 651 + 3424 3407 92 308 + 3424 4957 84 308 + 3424 1850 65 27 + 3424 3258 43 272 + 200 4337 27 853 + 200 3348 82 747 + 943 4259 58 853 + 943 1484 98 695 + 1433 4066 19 853 + 1433 2212 20 522 + 2708 3291 3 853 + 2708 3517 82 868 + 2708 4620 11 917 + 3291 4176 45 853 + 3291 2920 3 486 + 3300 943 97 853 + 3300 172 4 899 + 3300 3999 85 450 + 3770 1433 57 853 + 3770 1800 84 918 + 3770 4044 94 510 + 4066 4863 96 853 + 4066 2745 93 593 + 4176 3770 30 853 + 4176 2159 38 412 + 4176 2898 47 669 + 4259 2708 19 853 + 4259 4742 16 853 + 4259 4599 22 676 + 4337 3300 25 853 + 4337 2383 51 80 + 201 3928 96 1693 + 201 4850 64 110 + 201 811 33 652 + 744 2455 38 1693 + 744 4007 36 753 + 1006 4516 83 1693 + 1006 4946 98 1693 + 1006 716 21 22 + 1893 4415 21 1693 + 1893 1070 45 729 + 2455 1893 15 1693 + 2455 4568 78 516 + 2455 4546 53 848 + 3928 744 47 1693 + 3928 1142 100 711 + 3928 944 29 401 + 4415 1006 88 1693 + 4415 1909 39 790 + 202 1955 66 1352 + 202 3407 45 665 + 202 2568 31 708 + 731 3421 26 1352 + 731 3 66 673 + 1764 731 97 1352 + 1764 4988 63 1352 + 1764 24 97 799 + 1955 2872 78 1352 + 1955 2330 50 263 + 2872 1764 60 1352 + 2872 4006 81 328 + 3050 4625 23 1352 + 3050 3838 73 932 + 3050 4545 56 794 + 3421 3951 19 1352 + 3421 4602 12 84 + 3951 3050 71 1352 + 3951 3775 76 125 + 203 3736 26 224 + 203 4225 99 405 + 203 4158 27 165 + 1806 2963 53 224 + 1806 1585 31 575 + 1806 4029 9 571 + 2800 3845 41 224 + 2800 854 28 904 + 2800 1961 2 341 + 2963 4839 91 224 + 2963 2800 9 224 + 2963 4641 81 4 + 3736 1806 99 224 + 3736 2942 50 728 + 3736 3037 50 374 + 3845 4755 26 224 + 3845 1338 33 894 + 3845 4345 46 885 + 204 2922 36 247 + 204 170 65 462 + 856 1992 99 247 + 856 1724 63 628 + 856 3776 23 178 + 871 998 46 247 + 871 3734 45 442 + 871 4449 25 557 + 998 3352 85 247 + 998 4770 42 148 + 998 164 19 316 + 1409 871 84 247 + 1409 2782 98 993 + 1547 4938 46 247 + 1547 4511 44 247 + 1547 2833 9 149 + 1986 2384 65 247 + 1986 3249 53 198 + 1992 1409 30 247 + 1992 2270 50 737 + 2384 1547 44 247 + 2384 2009 58 799 + 2922 856 81 247 + 2922 3810 15 517 + 2922 4178 86 906 + 3352 1986 54 247 + 3352 4995 55 31 + 3352 1840 31 510 + 205 1238 2 688 + 205 3823 58 369 + 1084 2701 42 688 + 1084 1645 1 855 + 1238 1084 70 688 + 1238 1789 29 371 + 2236 4659 36 688 + 2236 3472 95 587 + 2701 2943 6 688 + 2701 2551 3 392 + 2943 3006 49 688 + 2943 4369 70 996 + 3006 4445 84 688 + 3006 4538 55 688 + 3006 2708 52 192 + 3006 4497 84 223 + 4257 2236 20 688 + 4257 2776 56 248 + 4445 4257 21 688 + 4445 2834 90 689 + 206 3883 22 585 + 206 2943 10 322 + 551 2261 61 585 + 551 1742 34 649 + 601 2988 71 585 + 601 4949 66 585 + 601 1046 71 709 + 743 4212 62 585 + 743 934 34 725 + 2261 2867 7 585 + 2261 590 87 320 + 2867 601 42 585 + 2867 4725 55 997 + 2867 4892 13 362 + 2988 4642 73 585 + 2988 3793 44 80 + 3883 743 69 585 + 3883 802 72 370 + 3883 640 34 337 + 4212 551 51 585 + 4212 306 54 262 + 4212 1788 47 358 + 207 1327 25 334 + 207 1665 68 196 + 207 4224 73 311 + 1180 4253 32 334 + 1180 2630 90 327 + 1180 1749 15 155 + 1327 3233 33 334 + 1327 3285 54 811 + 1807 4531 15 334 + 1807 4180 38 334 + 1807 1990 33 347 + 3233 1180 68 334 + 3233 1631 26 315 + 3233 1890 50 861 + 4180 4672 3 334 + 4180 4800 6 76 + 4253 1807 78 334 + 4253 3433 27 789 + 4253 227 70 250 + 208 3041 6 526 + 208 2741 31 541 + 948 1399 92 526 + 948 3297 12 404 + 1159 3170 80 526 + 1159 2227 65 562 + 1159 692 5 340 + 1399 1159 3 526 + 1399 645 88 275 + 1877 4267 58 526 + 1877 2102 20 65 + 1877 163 3 274 + 2224 3907 63 526 + 2224 4084 2 285 + 3041 4662 34 526 + 3041 948 99 526 + 3041 4624 28 204 + 3170 1877 25 526 + 3170 3010 50 638 + 3170 502 10 271 + 3907 4914 90 526 + 3907 671 80 198 + 4267 2224 38 526 + 4267 4064 43 399 + 209 3971 39 399 + 209 4521 6 462 + 209 1163 79 548 + 1196 2812 4 399 + 1196 1855 2 499 + 1631 1196 8 399 + 1631 4274 100 383 + 1631 147 82 410 + 2000 4591 6 399 + 2000 4391 60 528 + 2812 2000 2 399 + 2812 4776 36 668 + 2812 3753 76 204 + 2833 1631 43 399 + 2833 4655 28 399 + 2833 4347 53 594 + 3971 2833 84 399 + 3971 1341 88 559 + 3971 3517 18 264 + 210 657 62 270 + 210 4827 16 359 + 657 3614 57 270 + 657 3216 95 65 + 767 4561 33 270 + 767 526 32 697 + 767 3044 92 989 + 1391 2980 11 270 + 1391 1113 31 62 + 1391 191 88 921 + 2980 3031 95 270 + 2980 4196 77 834 + 2980 1503 18 969 + 3031 767 34 270 + 3031 4934 32 681 + 3031 2102 71 85 + 3614 1391 47 270 + 3614 4734 84 270 + 3614 1122 18 786 + 211 3937 30 826 + 211 1230 12 252 + 574 2295 60 826 + 574 2625 84 714 + 1093 2355 41 826 + 1093 1048 89 335 + 1470 3453 46 826 + 1470 287 99 24 + 1470 746 83 422 + 1827 2293 23 826 + 1827 1541 6 597 + 2293 574 59 826 + 2293 1908 53 2 + 2293 722 9 687 + 2295 3534 19 826 + 2295 4355 72 133 + 2355 1827 34 826 + 2355 2583 94 775 + 3453 3622 45 826 + 3453 4355 58 640 + 3453 2875 72 205 + 3534 1470 72 826 + 3534 655 42 220 + 3622 3763 98 826 + 3622 3519 11 886 + 3763 4858 53 826 + 3763 4782 12 826 + 3763 4639 50 826 + 3763 2261 51 559 + 3937 1093 41 826 + 3937 2660 34 399 + 212 2559 42 150 + 212 1109 57 697 + 212 925 25 918 + 1786 4103 59 150 + 1786 4648 19 150 + 1786 3409 86 986 + 1786 2634 46 809 + 2157 2301 13 150 + 2157 4851 54 381 + 2157 2703 36 606 + 2301 3510 56 150 + 2301 3545 39 537 + 2301 1617 27 597 + 2559 3836 94 150 + 2559 2738 21 967 + 2559 1075 34 313 + 2776 1786 99 150 + 2776 3155 67 825 + 3510 2776 4 150 + 3510 2494 40 519 + 3510 4861 74 874 + 3836 2157 48 150 + 3836 3720 26 219 + 3836 1336 21 406 + 4103 4852 80 150 + 4103 806 93 360 + 213 4099 5 472 + 213 170 28 197 + 855 2822 45 472 + 855 1828 52 885 + 855 3707 5 728 + 934 3432 55 472 + 934 1882 20 958 + 934 1371 57 543 + 1028 1970 51 472 + 1028 2403 26 477 + 1028 143 75 173 + 1374 1028 13 472 + 1374 3507 24 711 + 1374 836 95 291 + 1970 4629 53 472 + 1970 2478 43 94 + 2822 4672 50 472 + 2822 934 45 472 + 2822 2410 49 984 + 2822 4399 37 462 + 3078 855 96 472 + 3078 591 97 679 + 3078 3812 4 702 + 3432 1374 79 472 + 3432 4976 10 400 + 3432 4085 30 973 + 4027 3078 17 472 + 4027 3276 39 758 + 4027 3232 47 341 + 4099 4027 35 472 + 4099 719 78 784 + 214 4034 81 545 + 214 589 87 380 + 214 3758 18 932 + 887 3544 96 545 + 887 4130 15 773 + 952 887 29 545 + 952 303 70 556 + 952 1367 44 405 + 1097 1110 35 545 + 1097 849 1 261 + 1110 952 58 545 + 1110 2489 92 389 + 1110 901 16 298 + 1829 4807 12 545 + 1829 3118 81 506 + 1829 3107 85 98 + 3544 1829 33 545 + 3544 4834 61 545 + 3544 3117 86 942 + 4034 1097 52 545 + 4034 1089 23 147 + 4034 1889 61 347 + 215 2045 57 275 + 215 4995 30 86 + 215 4506 78 342 + 1487 4896 3 275 + 1487 4984 3 275 + 1487 126 64 185 + 1487 2774 67 918 + 1578 1487 7 275 + 1578 1786 5 649 + 1828 3464 26 275 + 1828 2898 52 50 + 1828 898 90 22 + 2045 1828 99 275 + 2045 4782 28 170 + 2045 4018 85 940 + 3464 4136 92 275 + 3464 2447 8 322 + 3464 153 63 518 + 4136 4459 72 275 + 4136 829 87 582 + 4136 1426 44 24 + 4459 1578 70 275 + 4459 1762 29 331 + 4459 4683 57 128 + 216 2403 42 732 + 216 3159 72 244 + 1404 2801 7 732 + 1404 2272 81 949 + 1404 4511 64 231 + 2321 3049 42 732 + 2321 4547 90 732 + 2321 825 45 831 + 2403 2321 77 732 + 2403 2438 59 506 + 2561 1404 39 732 + 2561 1430 48 416 + 2801 4810 86 732 + 2801 361 64 481 + 2801 1073 6 554 + 3049 3084 48 732 + 3049 3652 35 509 + 3084 2561 95 732 + 3084 2578 40 882 + 3084 2549 74 152 + 217 1816 78 675 + 217 3882 43 533 + 217 4007 33 252 + 917 4725 98 675 + 917 2612 60 906 + 1500 4433 70 675 + 1500 2298 16 126 + 1500 3395 42 166 + 1689 917 73 675 + 1689 4090 66 389 + 1816 3219 41 675 + 1816 4951 4 618 + 1816 2436 41 41 + 3219 1500 45 675 + 3219 2162 41 66 + 3329 1689 85 675 + 3329 2603 47 498 + 3329 3829 91 424 + 3635 3329 8 675 + 3635 4752 88 675 + 3635 2550 9 917 + 4433 3635 55 675 + 4433 1716 24 356 + 218 1088 25 351 + 218 3638 76 823 + 1016 3788 62 351 + 1016 1467 18 355 + 1016 972 78 194 + 1088 3288 71 351 + 1088 4996 91 351 + 1088 3287 18 920 + 2859 2861 91 351 + 2859 2429 57 418 + 2861 1016 61 351 + 2861 2172 85 949 + 3288 3593 68 351 + 3288 2625 6 640 + 3593 2859 35 351 + 3593 1702 38 610 + 3593 3730 78 168 + 3788 4882 21 351 + 3788 4861 20 144 + 219 4155 26 897 + 219 1102 33 424 + 219 4317 95 782 + 565 2360 36 897 + 565 2052 88 122 + 565 459 55 710 + 1593 2659 45 897 + 1593 4030 6 634 + 1593 4410 50 906 + 2325 4469 91 897 + 2325 3794 14 307 + 2360 4609 54 897 + 2360 4501 16 664 + 2360 923 86 249 + 2462 2325 78 897 + 2462 148 17 585 + 2659 565 20 897 + 2659 4645 19 897 + 2659 2946 74 983 + 4155 2462 86 897 + 4155 3746 30 334 + 4469 1593 5 897 + 4469 1841 85 596 + 4469 1428 12 661 + 220 3294 60 572 + 220 1290 17 806 + 516 929 32 572 + 516 4103 29 843 + 516 1995 62 622 + 724 2163 87 572 + 724 1676 34 862 + 839 1116 65 572 + 839 3193 33 768 + 929 4910 45 572 + 929 3531 23 572 + 929 91 43 982 + 929 3490 32 48 + 1012 724 75 572 + 1012 4315 75 551 + 1012 2168 49 318 + 1116 1165 10 572 + 1116 4030 36 767 + 1165 1012 20 572 + 1165 757 24 457 + 1165 1304 2 259 + 2163 516 94 572 + 2163 3775 32 594 + 3294 839 80 572 + 3294 4547 38 476 + 3531 4759 22 572 + 3531 13 21 67 + 221 4235 56 270 + 221 2474 31 10 + 1627 3306 42 270 + 1627 3943 17 173 + 1627 4681 17 152 + 3306 4714 6 270 + 3306 1392 93 78 + 3306 4969 10 560 + 3328 4070 89 270 + 3328 3611 14 278 + 3328 650 5 157 + 4070 4418 85 270 + 4070 4983 8 270 + 4070 1841 82 312 + 4235 3328 57 270 + 4235 3358 35 171 + 4418 1627 48 270 + 4418 777 2 296 + 4418 3631 72 207 + 222 926 76 68 + 222 3995 35 917 + 926 4023 41 68 + 926 339 5 207 + 1957 4889 6 68 + 1957 4456 48 68 + 1957 4433 67 895 + 1957 3965 87 124 + 2036 3434 24 68 + 2036 674 22 444 + 2036 2825 20 611 + 3269 1957 20 68 + 3269 2400 19 548 + 3269 4469 78 847 + 3434 4694 7 68 + 3434 2473 36 312 + 3990 3269 55 68 + 3990 714 45 883 + 4023 3990 76 68 + 4023 364 29 326 + 4456 2036 53 68 + 4456 1976 21 579 + 223 2684 83 843 + 223 3028 91 829 + 648 3373 3 843 + 648 3209 81 596 + 648 995 45 563 + 1198 4958 63 843 + 1198 439 78 645 + 1198 775 32 248 + 1479 3688 45 843 + 1479 763 70 78 + 2684 648 40 843 + 2684 4535 99 940 + 2684 224 24 399 + 3045 3815 22 843 + 3045 4400 41 663 + 3373 3045 12 843 + 3373 201 84 981 + 3688 1198 53 843 + 3688 4177 66 193 + 3815 1479 86 843 + 3815 4694 89 843 + 3815 224 21 990 + 224 4319 50 352 + 224 595 28 950 + 1027 4958 53 352 + 1027 2502 15 148 + 2080 4950 17 352 + 2080 3341 73 352 + 2080 1422 35 263 + 2999 1027 82 352 + 2999 3991 45 384 + 3268 4045 44 352 + 3268 1148 75 342 + 3341 2999 45 352 + 3341 3744 92 284 + 3341 1419 22 999 + 4045 2080 17 352 + 4045 3774 44 812 + 4319 3268 10 352 + 4319 149 56 764 + 225 2644 8 395 + 225 3812 66 308 + 225 4158 26 410 + 1650 4685 1 395 + 1650 147 61 75 + 1880 1650 99 395 + 1880 3521 60 810 + 1880 2599 44 884 + 2424 3780 97 395 + 2424 905 49 735 + 2631 1880 93 395 + 2631 2462 56 339 + 2631 4630 65 682 + 2644 2808 65 395 + 2644 1033 39 4 + 2808 2424 96 395 + 2808 3638 54 1000 + 2808 556 75 149 + 3780 2631 100 395 + 3780 4609 33 395 + 3780 3862 41 507 + 226 1902 77 584 + 226 3564 41 863 + 745 4834 34 584 + 745 2704 61 142 + 817 4348 42 584 + 817 3488 85 435 + 873 2464 70 584 + 873 3897 15 237 + 873 1995 98 784 + 1561 817 67 584 + 1561 4667 88 528 + 1561 2742 7 74 + 1902 2588 56 584 + 1902 3248 99 77 + 2131 873 76 584 + 2131 3075 70 433 + 2464 745 29 584 + 2464 816 39 843 + 2464 2792 68 969 + 2588 1561 16 584 + 2588 4830 58 584 + 2588 1558 83 85 + 2588 3467 11 77 + 3525 2131 68 584 + 3525 1326 56 874 + 4348 3525 14 584 + 4348 72 10 876 + 227 3681 74 192 + 227 869 51 79 + 227 3365 57 384 + 2129 3116 94 192 + 2129 4914 10 192 + 2129 1700 6 349 + 2924 4531 66 192 + 2924 731 49 246 + 2924 3473 34 379 + 3116 3263 45 192 + 3116 2171 92 626 + 3116 2063 92 314 + 3263 2924 2 192 + 3263 3985 47 224 + 3276 2129 25 192 + 3276 2599 11 373 + 3276 4340 27 114 + 3681 3276 70 192 + 3681 1911 70 346 + 228 4230 43 379 + 228 4758 69 289 + 980 3193 58 379 + 980 4941 1 411 + 1291 1691 94 379 + 1291 4118 26 567 + 1691 2440 65 379 + 1691 4059 28 567 + 1691 1466 25 912 + 2276 3639 95 379 + 2276 2621 6 544 + 2276 2569 12 675 + 2440 3840 92 379 + 2440 4665 84 270 + 3193 2276 97 379 + 3193 2846 42 329 + 3639 1291 23 379 + 3639 4752 22 379 + 3639 3099 28 273 + 3639 2609 34 87 + 3840 4869 86 379 + 3840 3047 99 97 + 4230 980 89 379 + 4230 2500 82 415 + 4230 1724 36 97 + 229 2699 38 325 + 229 1075 86 358 + 229 4133 13 241 + 802 1611 95 325 + 802 1836 82 795 + 802 2372 67 499 + 851 802 6 325 + 851 465 28 778 + 851 3706 96 489 + 976 4869 18 325 + 976 1176 7 615 + 1611 976 70 325 + 1611 3777 31 957 + 1611 2416 2 153 + 2699 3456 2 325 + 2699 4523 16 325 + 2699 3671 12 541 + 3456 3463 82 325 + 3456 1624 47 446 + 3463 851 12 325 + 3463 4847 35 790 + 230 1951 64 843 + 230 3913 77 339 + 230 2007 75 435 + 1141 4009 39 843 + 1141 3344 17 486 + 1951 4189 76 843 + 1951 4667 87 469 + 1951 1986 7 91 + 2051 4146 79 843 + 2051 23 52 847 + 2621 4591 76 843 + 2621 3745 42 843 + 2621 963 10 62 + 2621 2814 46 330 + 3745 2051 69 843 + 3745 792 28 186 + 4009 2621 11 843 + 4009 4668 9 504 + 4146 4516 79 843 + 4146 4982 33 698 + 4146 3194 59 857 + 4186 1141 70 843 + 4186 3961 62 368 + 4186 3096 27 203 + 4189 4186 88 843 + 4189 109 72 372 + 4189 29 1 879 + 231 3218 45 105 + 231 1169 10 240 + 800 1935 56 105 + 800 4842 55 422 + 969 3784 86 105 + 969 3984 40 624 + 969 3992 82 723 + 1413 969 71 105 + 1413 4893 30 105 + 1413 4804 52 900 + 1935 2624 3 105 + 1935 3491 58 310 + 1935 2448 66 135 + 2624 3899 21 105 + 2624 3850 75 431 + 3218 800 80 105 + 3218 3875 17 609 + 3218 4677 48 546 + 3784 4684 93 105 + 3784 3221 97 654 + 3899 1413 88 105 + 3899 820 52 691 + 3899 4188 32 334 + 232 584 79 978 + 232 4487 51 377 + 232 4489 1 635 + 584 4294 24 978 + 584 1737 10 296 + 584 365 68 681 + 1140 3511 9 978 + 1140 420 46 760 + 1140 4568 53 906 + 2406 4580 17 978 + 2406 1350 59 100 + 2995 3985 51 978 + 2995 454 96 341 + 3511 2406 39 978 + 3511 2303 77 17 + 3511 2541 99 929 + 3985 1140 91 978 + 3985 1181 51 627 + 4231 4701 62 978 + 4231 2995 100 978 + 4231 645 28 383 + 4294 4231 81 978 + 4294 617 1 181 + 233 1049 41 446 + 233 1268 51 975 + 233 4940 71 383 + 968 3140 48 446 + 968 2661 72 988 + 1049 968 11 446 + 1049 1609 71 898 + 1049 929 83 152 + 3140 4297 26 446 + 3140 2279 88 626 + 3140 1332 31 655 + 3159 4600 44 446 + 3159 454 31 676 + 3159 903 44 82 + 3765 4164 74 446 + 3765 1284 38 137 + 3765 2646 56 354 + 4164 3159 86 446 + 4164 4194 50 465 + 4164 4466 40 967 + 4297 3765 74 446 + 4297 4782 77 446 + 4297 4859 57 499 + 4297 655 15 548 + 234 919 67 102 + 234 1052 46 486 + 843 3502 52 102 + 843 2196 75 382 + 843 3816 28 864 + 919 3024 19 102 + 919 4960 75 102 + 919 4932 69 844 + 919 2559 48 308 + 1344 3816 43 102 + 1344 3427 6 868 + 1344 3952 86 899 + 3024 3230 18 102 + 3024 234 21 10 + 3230 843 1 102 + 3230 676 13 158 + 3502 1344 55 102 + 3502 4769 47 974 + 3502 3338 60 390 + 3816 4755 3 102 + 3816 488 21 923 + 3816 3060 68 645 + 235 967 73 315 + 235 1606 40 290 + 967 1926 25 315 + 967 4187 63 219 + 1297 2700 10 315 + 1297 1854 31 692 + 1926 4085 80 315 + 1926 4475 57 424 + 2202 3278 93 315 + 2202 4149 41 510 + 2202 2195 12 35 + 2315 3661 53 315 + 2315 1941 69 271 + 2315 102 49 98 + 2560 4800 10 315 + 2560 4513 78 932 + 2560 3963 60 765 + 2700 2315 62 315 + 2700 1458 47 718 + 2700 1693 86 676 + 3278 2560 79 315 + 3278 3371 87 814 + 3278 1175 17 372 + 3661 2202 22 315 + 3661 3866 100 866 + 4085 4709 86 315 + 4085 4144 26 315 + 4085 1701 21 391 + 4085 2212 73 159 + 4144 1297 5 315 + 4144 3706 11 412 + 4144 2030 55 859 + 236 3740 51 368 + 236 262 54 438 + 236 1060 11 657 + 902 4715 94 368 + 902 844 22 566 + 2398 3634 49 368 + 2398 4129 88 593 + 2398 4652 53 61 + 2418 2398 63 368 + 2418 4581 22 303 + 2418 3563 69 5 + 3634 4312 26 368 + 3634 4753 65 368 + 3634 1090 41 998 + 3634 3367 42 43 + 3740 2418 99 368 + 3740 1383 72 457 + 4312 902 72 368 + 4312 3703 27 877 + 4312 1296 92 248 + 237 4000 14 293 + 237 207 44 707 + 695 4543 75 293 + 695 2375 78 712 + 2647 695 93 293 + 2647 1338 52 846 + 3706 4220 25 293 + 3706 3675 71 715 + 4000 3706 35 293 + 4000 1207 94 630 + 4220 2647 9 293 + 4220 4596 13 293 + 4220 4513 52 513 + 4220 3485 80 503 + 238 1029 91 391 + 238 2508 29 331 + 1029 4062 62 391 + 1029 1888 23 744 + 1029 2913 96 728 + 1424 3296 49 391 + 1424 2785 1 48 + 1628 1424 57 391 + 1628 727 98 739 + 1628 2940 34 614 + 1632 1628 42 391 + 1632 2664 5 765 + 1632 4902 97 487 + 1765 1632 13 391 + 1765 4575 100 391 + 1765 392 33 23 + 1765 2822 16 138 + 3296 4744 71 391 + 3296 4909 47 229 + 4062 1765 65 391 + 4062 3630 14 464 + 4062 3551 52 979 + 239 2048 81 816 + 239 3523 29 323 + 239 3648 52 672 + 870 3828 3 816 + 870 260 63 412 + 1674 2533 52 816 + 1674 4656 40 816 + 1674 2651 72 889 + 2048 4108 73 816 + 2048 2066 67 593 + 2048 884 70 414 + 2533 4975 86 816 + 2533 4483 85 815 + 2533 2116 64 985 + 3828 1674 24 816 + 3828 2613 20 823 + 4108 870 80 816 + 4108 2387 18 842 + 4108 458 41 904 + 240 3888 76 456 + 240 785 17 496 + 2185 3761 12 456 + 2185 3305 38 618 + 2928 4363 35 456 + 2928 2584 30 245 + 2928 4534 88 605 + 3132 2928 78 456 + 3132 922 86 105 + 3292 3132 9 456 + 3292 3590 32 710 + 3292 3400 9 615 + 3761 4838 63 456 + 3761 447 89 295 + 3888 4387 66 456 + 3888 219 95 714 + 4363 2185 25 456 + 4363 4045 78 222 + 4363 4473 100 515 + 4387 3292 46 456 + 4387 4930 25 456 + 4387 588 63 106 + 4387 671 79 94 + 241 1821 98 490 + 241 3717 33 386 + 241 846 2 129 + 1521 3345 28 490 + 1521 1633 29 436 + 1821 3558 42 490 + 1821 4863 17 827 + 1821 569 81 799 + 2274 1521 2 490 + 2274 1292 44 612 + 2274 4498 94 162 + 2515 2274 28 490 + 2515 1960 64 998 + 2515 2100 50 674 + 3345 3839 54 490 + 3345 4757 63 490 + 3345 3654 54 14 + 3345 1077 54 30 + 3558 4430 84 490 + 3558 2860 92 510 + 3558 1275 35 31 + 3839 4826 51 490 + 3839 4845 80 887 + 4430 2515 8 490 + 4430 493 39 763 + 4430 4019 23 825 + 242 2763 32 123 + 242 4406 3 318 + 877 3253 58 123 + 877 2018 60 918 + 1156 2088 73 123 + 1156 690 88 207 + 1156 4044 69 214 + 2088 4506 15 123 + 2088 4980 20 553 + 2088 2879 97 802 + 2465 877 72 123 + 2465 2351 6 454 + 2763 4083 40 123 + 2763 134 39 244 + 2883 1156 63 123 + 2883 3338 95 971 + 3253 3261 26 123 + 3253 4824 23 388 + 3261 4854 29 123 + 3261 2883 38 123 + 3261 1749 57 109 + 4083 2465 37 123 + 4083 4978 82 739 + 243 2220 42 146 + 243 3109 80 592 + 1559 1598 61 146 + 1559 4731 56 146 + 1559 2661 79 898 + 1576 4353 42 146 + 1576 1737 33 725 + 1576 3522 97 16 + 1598 1790 32 146 + 1598 1477 51 912 + 1598 4910 91 619 + 1668 2650 8 146 + 1668 4523 88 619 + 1790 1576 70 146 + 1790 1246 48 437 + 2220 1559 58 146 + 2220 2181 39 307 + 2220 3102 25 699 + 2650 4900 33 146 + 2650 2016 60 449 + 4353 1668 86 146 + 4353 3998 36 407 + 4353 4196 9 891 + 244 1641 63 498 + 244 2800 83 498 + 1017 1142 7 498 + 1017 1641 39 673 + 1142 2871 46 498 + 1142 1842 43 509 + 1395 1871 85 498 + 1395 3358 48 374 + 1641 1395 51 498 + 1641 178 86 552 + 1641 246 94 68 + 1728 2453 67 498 + 1728 4600 15 498 + 1728 1819 92 887 + 1871 1728 85 498 + 1871 3504 26 742 + 1871 980 5 979 + 2453 2786 97 498 + 2453 4099 20 987 + 2786 1017 41 498 + 2786 3790 86 654 + 2871 3016 85 498 + 2871 2740 100 566 + 2871 4614 78 863 + 3016 4741 25 498 + 3016 1142 23 1 + 3016 1952 88 220 + 245 883 76 595 + 245 225 23 134 + 245 2882 11 774 + 883 4152 64 595 + 883 239 85 961 + 883 3565 68 303 + 1383 3054 17 595 + 1383 878 55 231 + 1867 2143 21 595 + 1867 1903 22 630 + 2143 3799 3 595 + 2143 1249 13 75 + 3054 1867 100 595 + 3054 1521 16 341 + 3054 2723 3 951 + 3187 4102 30 595 + 3187 4831 48 595 + 3187 2597 29 967 + 3799 3187 88 595 + 3799 903 92 967 + 4063 1383 6 595 + 4063 3342 79 268 + 4102 4758 41 595 + 4102 538 24 983 + 4152 4063 42 595 + 4152 4943 44 543 + 246 787 61 229 + 246 890 65 56 + 246 105 91 685 + 787 4802 58 229 + 787 1768 36 229 + 787 3448 21 708 + 787 4336 5 610 + 1768 3270 72 229 + 1768 4574 75 371 + 1768 2262 50 20 + 1791 3940 58 229 + 1791 454 12 821 + 1791 4757 7 891 + 2228 3471 67 229 + 2228 3701 59 342 + 2228 4174 77 661 + 2327 4938 59 229 + 2327 449 25 381 + 2327 2620 58 775 + 2726 2327 97 229 + 2726 4333 68 345 + 2726 1496 88 203 + 3270 1791 22 229 + 3270 1048 66 15 + 3270 4979 76 859 + 3471 2726 38 229 + 3471 22 65 757 + 3940 2228 37 229 + 3940 1375 2 568 + 3940 4938 48 712 + 247 1693 57 761 + 247 3380 75 857 + 572 1961 27 761 + 572 4465 82 591 + 600 4953 14 761 + 600 1579 70 85 + 600 2345 2 664 + 1510 572 59 761 + 1510 4960 58 761 + 1510 582 51 594 + 1693 4096 24 761 + 1693 77 80 364 + 1693 3189 59 678 + 1961 4369 44 761 + 1961 2554 15 250 + 1961 966 11 485 + 1995 600 81 761 + 1995 1855 16 555 + 4096 4371 99 761 + 4096 1349 33 528 + 4369 1995 50 761 + 4369 4193 75 15 + 4369 1503 89 467 + 4371 1510 1 761 + 4371 260 11 275 + 248 3495 8 520 + 248 2414 85 388 + 631 915 29 520 + 631 3825 15 996 + 631 581 57 893 + 915 1848 82 520 + 915 1432 35 413 + 915 1939 54 969 + 1131 2986 9 520 + 1131 2642 31 246 + 1825 1936 51 520 + 1825 3859 49 493 + 1848 1131 83 520 + 1848 4183 12 646 + 1936 4671 83 520 + 1936 4734 75 520 + 1936 4903 58 636 + 2986 3379 20 520 + 2986 3404 4 514 + 3379 1825 21 520 + 3379 2725 5 372 + 3495 631 65 520 + 3495 4059 46 287 + 3495 2822 50 82 + 249 1179 60 1198 + 249 3700 41 737 + 249 546 77 643 + 931 2863 6 1198 + 931 4928 57 71 + 1179 2194 22 1198 + 1179 4774 41 1198 + 1179 1580 38 23 + 1563 4763 32 1198 + 1563 3557 2 595 + 2194 4482 11 1198 + 2194 4564 42 483 + 2194 150 99 907 + 2430 1563 66 1198 + 2430 3450 54 107 + 2863 2430 95 1198 + 2863 3873 66 699 + 4482 931 80 1198 + 4482 1783 5 784 + 4482 4806 12 928 + 250 1462 3 463 + 250 3952 14 483 + 1462 2920 60 463 + 1462 1796 22 350 + 1462 292 45 159 + 1504 4440 73 463 + 1504 1263 43 579 + 1504 1893 26 504 + 1813 4538 45 463 + 1813 1504 12 463 + 1813 2903 25 804 + 2118 4788 73 463 + 2118 2368 23 210 + 2920 4194 16 463 + 2920 232 97 843 + 2920 4620 20 548 + 3129 1813 49 463 + 3129 1256 93 524 + 3129 3955 84 443 + 3239 3129 30 463 + 3239 609 23 657 + 3239 1753 39 769 + 3438 3239 80 463 + 3438 4804 45 959 + 4194 3438 68 463 + 4194 463 66 719 + 4194 284 55 478 + 4440 2118 19 463 + 4440 4239 79 63 + 4440 4474 47 149 + 251 1692 99 497 + 251 3642 86 285 + 540 2712 57 497 + 540 3744 97 474 + 689 4960 50 497 + 689 1375 23 363 + 773 689 26 497 + 773 2016 94 658 + 773 2304 74 212 + 1692 3774 66 497 + 1692 4795 10 497 + 1692 2371 82 529 + 1692 4970 30 217 + 2339 2593 25 497 + 2339 2396 15 968 + 2339 17 90 177 + 2593 3191 77 497 + 2593 2271 50 325 + 2593 3615 19 337 + 2712 2339 32 497 + 2712 1823 97 898 + 2764 773 74 497 + 2764 581 85 561 + 2971 540 75 497 + 2971 1510 54 535 + 2971 1054 73 322 + 3070 4657 28 497 + 3070 2764 26 497 + 3070 4066 6 957 + 3070 1915 57 42 + 3191 3070 31 497 + 3191 4096 29 237 + 3774 2971 12 497 + 3774 3399 44 625 + 252 988 3 529 + 252 1350 71 463 + 252 406 95 663 + 655 3738 26 529 + 655 2414 14 496 + 655 3589 21 462 + 988 2694 45 529 + 988 4634 13 52 + 1249 1603 64 529 + 1249 4532 78 366 + 1249 1714 30 349 + 1603 2019 99 529 + 1603 3494 5 659 + 2019 655 35 529 + 2019 1354 51 486 + 2694 1249 77 529 + 2694 4587 69 529 + 2694 26 61 681 + 2694 1751 52 441 + 3738 4690 72 529 + 3738 4684 99 122 + 3738 4449 66 160 + 253 1966 92 913 + 253 636 33 275 + 761 3025 68 913 + 761 2291 11 840 + 761 3077 73 449 + 1107 4302 36 913 + 1107 3975 32 617 + 1966 4316 57 913 + 1966 1381 3 876 + 1966 4255 43 44 + 3025 4476 3 913 + 3025 930 89 451 + 3025 3265 37 87 + 3591 4509 41 913 + 3591 1200 49 356 + 3936 3591 34 913 + 3936 64 7 370 + 4302 3936 67 913 + 4302 1432 69 901 + 4302 3987 28 642 + 4316 761 29 913 + 4316 4314 30 398 + 4476 1107 82 913 + 4476 4620 60 913 + 4476 2452 90 346 + 4476 4972 15 576 + 254 3083 62 543 + 254 1824 56 746 + 2132 2554 3 543 + 2132 3771 91 141 + 2132 1444 12 260 + 2487 2132 61 543 + 2487 3435 69 394 + 2487 1184 59 982 + 2554 2978 59 543 + 2554 2412 6 458 + 2978 4119 17 543 + 2978 1069 84 593 + 3083 2487 20 543 + 3083 4560 62 543 + 3083 1102 18 821 + 3246 4709 85 543 + 3246 3023 99 115 + 4119 4175 54 543 + 4119 1879 63 626 + 4119 4358 80 159 + 4175 3246 86 543 + 4175 183 77 40 + 4175 1021 6 615 + 255 4420 20 584 + 255 133 55 598 + 255 1365 82 50 + 878 3265 41 584 + 878 4899 56 897 + 1086 1464 15 584 + 1086 4518 69 319 + 1464 3752 56 584 + 1464 1404 52 156 + 3265 3853 54 584 + 3265 142 60 476 + 3265 1668 83 745 + 3752 878 71 584 + 3752 4515 8 584 + 3752 1200 45 36 + 3752 146 25 796 + 3853 4809 66 584 + 3853 2247 6 902 + 3853 430 6 168 + 4420 1086 99 584 + 4420 123 61 439 + 256 735 9 193 + 256 4601 44 807 + 667 1075 69 193 + 667 3097 69 598 + 735 4127 18 193 + 735 3254 15 260 + 818 4928 90 193 + 818 54 70 905 + 818 3718 91 49 + 1046 3615 70 193 + 1046 2515 19 995 + 1046 4769 53 562 + 1075 2969 37 193 + 1075 80 13 487 + 1075 2474 84 780 + 1733 4532 82 193 + 1733 818 77 193 + 1733 2435 31 111 + 1733 237 82 660 + 2689 1733 6 193 + 2689 332 100 44 + 2969 2689 13 193 + 2969 2169 53 260 + 3615 667 43 193 + 3615 4062 32 593 + 4127 1046 63 193 + 4127 2696 59 695 + 257 1078 91 614 + 257 1771 8 49 + 624 4606 92 614 + 624 4894 25 614 + 624 2384 28 135 + 624 4024 86 429 + 984 2876 82 614 + 984 3626 18 494 + 1078 3998 29 614 + 1078 1700 21 298 + 1144 984 82 614 + 1144 4826 90 614 + 1144 3394 49 832 + 1144 1250 19 45 + 1555 1851 15 614 + 1555 2712 58 685 + 1555 3117 43 52 + 1851 4193 85 614 + 1851 3639 28 780 + 1851 1469 10 86 + 2001 624 49 614 + 2001 2669 94 455 + 2001 1666 37 137 + 2823 2001 99 614 + 2823 4343 12 285 + 2876 1555 68 614 + 2876 2253 50 42 + 3097 1144 93 614 + 3097 4106 24 527 + 3998 3097 67 614 + 3998 2264 59 987 + 4193 2823 27 614 + 4193 875 31 147 + 258 2806 1 449 + 258 3451 70 110 + 749 4693 61 449 + 749 170 22 735 + 1314 3930 28 449 + 1314 3492 51 622 + 1338 2846 93 449 + 1338 1021 54 37 + 1338 311 50 698 + 2148 2938 86 449 + 2148 1924 72 211 + 2519 749 21 449 + 2519 4932 75 449 + 2519 3877 80 487 + 2519 3260 25 200 + 2806 1314 17 449 + 2806 209 78 442 + 2846 3535 9 449 + 2846 1194 77 364 + 2938 1338 86 449 + 2938 4949 94 978 + 3186 4149 52 449 + 3186 2698 95 580 + 3535 3186 75 449 + 3535 1498 47 674 + 3535 2102 78 41 + 3930 2148 89 449 + 3930 757 11 714 + 3930 4396 54 79 + 4149 2519 20 449 + 4149 4512 32 449 + 4149 3468 70 465 + 259 3124 22 1 + 259 2540 61 415 + 1077 1849 2 1 + 1077 709 21 480 + 1077 2337 33 43 + 1774 1077 85 1 + 1774 4718 42 255 + 1849 2816 89 1 + 1849 4822 78 58 + 1849 2953 79 223 + 2571 4593 100 1 + 2571 4944 23 1 + 2571 247 13 908 + 2571 3861 95 277 + 2816 3403 62 1 + 2816 2348 17 590 + 3124 4123 81 1 + 3124 313 47 419 + 3403 3878 1 1 + 3403 4162 92 635 + 3878 2571 93 1 + 3878 1809 35 494 + 3878 1816 69 706 + 4123 1774 98 1 + 4123 2126 7 251 + 260 4183 35 612 + 260 4784 64 218 + 260 2371 28 247 + 727 4916 49 612 + 727 3764 1 612 + 727 786 74 368 + 1478 4538 68 612 + 1478 4134 36 112 + 1478 4123 95 548 + 1557 727 49 612 + 1557 2208 38 137 + 3764 3855 89 612 + 3764 1382 22 451 + 3855 1478 44 612 + 3855 1992 10 23 + 4183 4479 8 612 + 4183 2116 82 567 + 4183 1494 97 615 + 4479 1557 67 612 + 4479 4161 5 998 + 261 2642 50 349 + 261 2663 11 763 + 530 4761 76 349 + 530 765 79 464 + 530 435 26 953 + 1087 2482 88 349 + 1087 1405 2 128 + 1185 530 74 349 + 1185 296 39 530 + 1723 1087 80 349 + 1723 1245 72 864 + 2213 1723 93 349 + 2213 4786 87 349 + 2213 3689 10 1000 + 2213 3766 94 321 + 2482 1185 70 349 + 2482 752 18 694 + 2642 2213 84 349 + 2642 632 72 210 + 2642 3593 69 958 + 262 1704 100 355 + 262 323 99 206 + 716 2242 62 355 + 716 1520 96 809 + 891 716 20 355 + 891 1311 42 163 + 996 4508 56 355 + 996 3836 17 654 + 1704 3697 12 355 + 1704 1133 47 542 + 1704 1776 38 305 + 2242 996 96 355 + 2242 3935 29 489 + 2242 59 92 647 + 3697 891 90 355 + 3697 4868 42 355 + 3697 2282 19 679 + 3697 1858 96 197 + 263 2844 49 511 + 263 1082 8 162 + 1560 1754 74 511 + 1560 3827 44 186 + 1560 3266 13 498 + 1735 2661 71 511 + 1735 3848 12 598 + 1754 4419 2 511 + 1754 4564 67 185 + 1754 3435 72 647 + 2191 1560 96 511 + 2191 1388 58 853 + 2318 4694 18 511 + 2318 3744 37 848 + 2661 4163 89 511 + 2661 1945 63 641 + 2844 2961 93 511 + 2844 2987 10 891 + 2936 2191 53 511 + 2936 2432 16 92 + 2961 1735 85 511 + 2961 2504 95 159 + 2961 528 4 612 + 4163 4668 13 511 + 4163 2936 13 511 + 4163 4676 19 338 + 4163 3896 95 605 + 4419 2318 55 511 + 4419 4681 57 185 + 4419 1112 83 232 + 264 1878 76 1586 + 264 1256 87 161 + 264 1483 80 875 + 793 1407 61 1586 + 793 2598 64 263 + 1290 3642 20 1586 + 1290 1995 44 697 + 1290 2662 67 691 + 1407 4654 83 1586 + 1407 3645 37 1586 + 1407 906 37 400 + 1784 3577 40 1586 + 1784 829 24 858 + 1784 958 10 235 + 1878 793 81 1586 + 1878 3798 7 375 + 1878 4843 70 981 + 3145 4307 45 1586 + 3145 234 9 587 + 3214 4790 47 1586 + 3214 1887 55 168 + 3214 4544 73 389 + 3217 4849 2 1586 + 3217 3145 82 1586 + 3217 1214 21 628 + 3577 3217 99 1586 + 3577 4306 6 683 + 3642 3214 25 1586 + 3642 2833 82 116 + 3645 1784 41 1586 + 3645 4753 3 338 + 3645 4609 65 882 + 4307 1290 85 1586 + 4307 3244 88 977 + 265 1316 36 383 + 265 1788 95 887 + 815 3380 31 383 + 815 3446 76 463 + 815 3126 25 467 + 1060 3130 40 383 + 1060 4530 7 383 + 1060 3372 18 16 + 1316 4483 24 383 + 1316 3744 48 349 + 1461 3915 52 383 + 1461 1512 28 683 + 1461 2986 80 785 + 2474 1461 50 383 + 2474 2110 86 779 + 2474 1560 8 769 + 3130 815 74 383 + 3130 2717 10 304 + 3130 4319 45 272 + 3250 1060 35 383 + 3250 3377 18 465 + 3380 2474 84 383 + 3380 3680 16 704 + 3380 2304 87 812 + 3915 4847 90 383 + 3915 2688 77 791 + 4483 3250 59 383 + 4483 3692 94 995 + 266 619 97 192 + 266 4688 30 661 + 266 721 88 832 + 545 3952 21 192 + 545 1016 11 733 + 545 3775 19 335 + 619 3858 31 192 + 619 19 92 313 + 641 3775 13 192 + 641 3947 33 640 + 641 3571 25 196 + 682 641 76 192 + 682 4735 53 192 + 682 2994 34 176 + 682 4822 27 743 + 1466 545 19 192 + 1466 1039 11 505 + 3775 4018 36 192 + 3775 1162 49 977 + 3775 3955 16 547 + 3858 682 26 192 + 3858 3952 74 106 + 3858 2446 1 179 + 3952 4602 30 192 + 3952 3897 12 683 + 3952 2477 79 340 + 4018 1466 27 192 + 4018 2062 46 231 + 267 2537 73 92 + 267 2596 56 656 + 267 995 80 335 + 671 3541 29 92 + 671 1002 21 145 + 671 3792 67 271 + 707 3548 30 92 + 707 3516 74 96 + 2067 3690 5 92 + 2067 1516 43 95 + 2067 1421 46 587 + 2307 4804 20 92 + 2307 2699 69 314 + 2537 4330 25 92 + 2537 380 37 625 + 3541 2067 76 92 + 3541 2008 38 392 + 3548 2307 91 92 + 3548 1521 95 124 + 3690 707 11 92 + 3690 1371 91 874 + 4330 671 49 92 + 4330 4993 87 92 + 4330 18 57 105 + 4330 3518 23 750 + 268 2072 21 842 + 268 3731 35 216 + 646 4266 34 842 + 646 1774 99 816 + 646 2274 99 220 + 669 4357 91 842 + 669 1253 5 633 + 669 4999 72 364 + 1167 1371 75 842 + 1167 1584 82 632 + 1371 669 94 842 + 1371 1847 41 905 + 2072 4564 22 842 + 2072 4317 46 842 + 2072 2889 41 18 + 2072 3822 90 241 + 4030 4826 62 842 + 4030 2682 93 578 + 4266 4030 99 842 + 4266 285 74 182 + 4266 732 86 335 + 4317 1167 14 842 + 4317 3279 70 497 + 4357 646 32 842 + 4357 1454 28 286 + 4357 3239 71 700 + 269 4134 58 601 + 269 395 69 300 + 269 1841 98 555 + 1173 2243 23 601 + 1173 4186 45 221 + 1173 3505 33 375 + 1657 3576 15 601 + 1657 2815 80 39 + 1666 2925 7 601 + 1666 616 19 890 + 2243 4453 52 601 + 2243 3018 92 967 + 2243 4568 73 946 + 2925 4771 12 601 + 2925 4831 92 160 + 3249 1173 21 601 + 3249 2724 86 330 + 3249 3990 82 449 + 3576 4996 98 601 + 3576 4229 90 601 + 3576 3883 23 774 + 4134 1657 52 601 + 4134 3816 44 164 + 4134 4252 21 75 + 4229 3249 37 601 + 4229 1951 73 221 + 4229 2987 100 953 + 4453 1666 65 601 + 4453 4690 22 447 + 270 1661 83 39 + 270 1388 93 762 + 511 4748 15 39 + 511 1970 100 133 + 511 4921 34 800 + 717 2575 92 39 + 717 3205 3 24 + 1661 4499 55 39 + 1661 1889 58 432 + 2052 511 22 39 + 2052 4838 74 39 + 2052 4603 6 239 + 2052 2116 75 841 + 2575 2052 93 39 + 2575 4287 33 684 + 2609 3216 15 39 + 2609 2314 89 952 + 2609 1874 65 23 + 2820 2609 85 39 + 2820 2553 11 351 + 3156 2820 100 39 + 3156 2083 59 563 + 3156 1384 47 527 + 3216 717 87 39 + 3216 41 70 962 + 3686 3156 38 39 + 3686 2431 75 856 + 4499 3686 96 39 + 4499 3037 7 960 + 271 3506 40 276 + 271 592 88 628 + 670 2425 99 276 + 670 171 92 362 + 670 3738 63 984 + 914 2299 47 276 + 914 885 2 50 + 1706 1947 81 276 + 1706 1710 54 867 + 1947 2606 89 276 + 1947 3419 62 227 + 1947 3746 63 600 + 2299 1706 50 276 + 2299 417 76 890 + 2425 914 27 276 + 2425 2974 10 793 + 2425 4166 48 993 + 2606 3663 99 276 + 2606 4743 85 276 + 2606 4239 38 435 + 3506 670 56 276 + 3506 3888 24 914 + 3506 3747 90 120 + 3663 4898 19 276 + 3663 1417 31 839 + 3663 4095 83 79 + 272 1467 17 363 + 272 3815 90 140 + 715 4113 65 363 + 715 3382 30 978 + 1467 1943 75 363 + 1467 3217 46 820 + 1467 325 14 910 + 1830 715 9 363 + 1830 1366 94 388 + 1943 1830 59 363 + 1943 3362 67 497 + 1943 4006 14 657 + 2893 4372 62 363 + 2893 641 51 523 + 4113 4421 76 363 + 4113 1072 100 556 + 4113 4457 21 864 + 4372 4833 27 363 + 4372 4718 66 363 + 4372 843 53 742 + 4372 3161 60 564 + 4421 2893 45 363 + 4421 4721 71 695 + 273 2634 6 371 + 273 25 16 547 + 514 2354 98 371 + 514 4981 57 803 + 1460 4803 14 371 + 1460 1476 8 371 + 1460 2452 77 21 + 1460 3766 8 902 + 1476 514 34 371 + 1476 3936 94 871 + 2354 3647 33 371 + 2354 650 15 649 + 2634 4015 12 371 + 2634 1643 95 926 + 3647 4740 24 371 + 3647 2340 43 155 + 4015 1460 3 371 + 4015 406 75 383 + 4015 1438 22 362 + 274 4397 86 53 + 274 401 96 28 + 274 3190 20 62 + 1043 4667 42 53 + 1043 3026 94 53 + 1043 3080 78 312 + 1517 3367 26 53 + 1517 4209 13 469 + 1845 3695 69 53 + 1845 1814 88 369 + 2761 3683 51 53 + 2761 4437 83 957 + 2761 2240 83 25 + 2934 1845 27 53 + 2934 4659 33 654 + 2996 1517 37 53 + 2996 134 19 287 + 3026 2934 90 53 + 3026 1757 2 150 + 3367 2761 1 53 + 3367 3308 60 650 + 3683 4974 14 53 + 3683 2285 40 932 + 3683 2165 49 76 + 3695 2996 3 53 + 3695 1411 64 402 + 4397 1043 25 53 + 4397 1426 11 384 + 275 3676 9 486 + 275 484 89 844 + 275 710 16 357 + 809 1753 98 486 + 809 2762 81 236 + 809 2029 60 335 + 1062 2566 100 486 + 1062 3092 100 384 + 1062 542 97 234 + 1089 2747 85 486 + 1089 2321 47 730 + 1533 3984 45 486 + 1533 4774 34 538 + 1753 1757 84 486 + 1753 3312 50 325 + 1753 2802 58 824 + 1757 4548 58 486 + 1757 4922 25 486 + 1757 1459 70 630 + 1757 2124 49 142 + 1923 1062 28 486 + 1923 4008 50 684 + 2566 1089 22 486 + 2566 2391 49 455 + 2566 3540 69 938 + 2747 3127 96 486 + 2747 1894 25 482 + 3127 809 51 486 + 3127 947 43 817 + 3676 4951 41 486 + 3676 1533 39 486 + 3676 2354 25 80 + 3984 1923 12 486 + 3984 4794 14 979 + 3984 2573 21 755 + 276 993 32 348 + 276 4462 4 844 + 276 2644 58 738 + 993 3358 64 348 + 993 4715 91 348 + 993 1460 89 650 + 993 780 12 726 + 1261 4147 32 348 + 1261 2399 18 804 + 1920 4710 58 348 + 1920 2118 63 346 + 3358 1261 41 348 + 3358 998 19 597 + 3358 176 80 812 + 4147 4467 63 348 + 4147 216 53 938 + 4467 1920 82 348 + 4467 1807 85 213 + 277 4300 31 407 + 277 1245 51 180 + 277 3369 82 665 + 555 3679 75 407 + 555 977 99 918 + 555 1190 94 643 + 1008 4835 82 407 + 1008 3579 57 407 + 1008 391 49 376 + 1558 1008 56 407 + 1558 3784 54 101 + 1558 837 34 59 + 1589 2912 17 407 + 1589 4505 30 407 + 1589 2636 7 825 + 2091 1589 33 407 + 2091 2921 98 717 + 2091 4397 76 428 + 2508 2091 73 407 + 2508 1568 90 225 + 2508 1330 10 519 + 2589 1558 20 407 + 2589 1010 15 289 + 2589 1746 31 196 + 2610 4677 1 407 + 2610 4553 97 768 + 2912 2589 54 407 + 2912 3610 38 361 + 3579 2610 63 407 + 3579 2131 90 419 + 3579 4826 71 345 + 3679 2508 79 407 + 3679 984 30 590 + 4300 555 57 407 + 4300 1485 61 524 + 278 4278 77 647 + 278 1401 73 713 + 653 1534 75 647 + 653 350 85 251 + 653 4765 30 724 + 1337 1793 32 647 + 1337 4129 11 1000 + 1337 2035 49 789 + 1534 4589 90 647 + 1534 377 51 83 + 1534 1798 96 160 + 1709 4086 32 647 + 1709 4528 83 647 + 1709 2496 98 656 + 1709 2431 31 337 + 1793 4190 22 647 + 1793 2343 84 506 + 3337 1337 39 647 + 3337 4645 78 74 + 3337 3263 28 811 + 4086 3337 25 647 + 4086 3774 11 363 + 4086 3148 51 510 + 4190 653 79 647 + 4190 823 41 326 + 4190 3186 14 541 + 4278 1709 15 647 + 4278 2290 16 609 + 4278 2734 20 15 + 279 674 18 417 + 279 990 60 282 + 656 2579 62 417 + 656 4550 79 613 + 674 2637 83 417 + 674 4393 32 984 + 890 1367 10 417 + 890 4694 13 116 + 890 180 90 581 + 1367 4816 94 417 + 1367 1819 44 643 + 2579 4471 7 417 + 2579 1749 81 578 + 2637 656 2 417 + 2637 1634 97 6 + 3318 4958 38 417 + 3318 890 28 417 + 3318 4676 52 509 + 3318 348 93 572 + 4471 3318 25 417 + 4471 859 90 258 + 280 1745 55 1070 + 280 665 100 143 + 1511 4351 76 1070 + 1511 4406 100 416 + 1713 3188 55 1070 + 1713 2292 59 503 + 1745 2681 32 1070 + 1745 4765 57 134 + 2096 3205 92 1070 + 2096 3670 64 405 + 2096 1232 87 591 + 2178 1713 16 1070 + 2178 3477 98 738 + 2681 2178 40 1070 + 2681 2772 92 97 + 2681 1215 2 631 + 3188 1511 57 1070 + 3188 4025 57 438 + 3205 4504 15 1070 + 3205 4045 82 301 + 3205 918 12 850 + 4351 2096 43 1070 + 4351 4731 10 1070 + 4351 879 33 704 + 281 3422 36 32 + 281 3113 7 995 + 1128 2638 73 32 + 1128 2796 57 795 + 1128 2739 33 441 + 2297 1128 1 32 + 2297 1272 9 373 + 2297 4313 73 677 + 2638 2998 24 32 + 2638 4672 97 32 + 2638 3345 2 741 + 2998 4826 86 32 + 2998 4992 28 459 + 2998 778 54 273 + 3422 2297 34 32 + 3422 4316 64 828 + 282 811 40 887 + 282 358 42 739 + 282 4225 91 164 + 811 2802 87 887 + 811 4961 10 887 + 811 1999 39 523 + 1673 4512 83 887 + 1673 3797 37 897 + 1673 3243 31 184 + 2353 4131 37 887 + 2353 344 40 477 + 2802 3656 34 887 + 2802 1451 77 733 + 3656 4321 72 887 + 3656 4241 78 620 + 3656 1839 72 668 + 4131 1673 4 887 + 4131 264 44 371 + 4131 4514 38 889 + 4321 2353 62 887 + 4321 1474 90 181 + 283 1257 39 387 + 283 291 79 733 + 759 3117 36 387 + 759 2103 8 191 + 1117 759 34 387 + 1117 250 98 899 + 1257 2486 10 387 + 1257 4978 53 519 + 1257 2889 36 507 + 1484 2811 95 387 + 1484 4598 24 387 + 1484 536 28 717 + 1484 2395 50 218 + 2027 2120 33 387 + 2027 1754 49 626 + 2027 4210 39 815 + 2120 4004 45 387 + 2120 4693 64 387 + 2120 4392 14 719 + 2120 4282 67 50 + 2486 1484 92 387 + 2486 2950 44 490 + 2811 1117 62 387 + 2811 1695 51 836 + 2811 4554 100 539 + 3117 2027 23 387 + 3117 3690 64 331 + 3117 4616 69 638 + 3813 4909 28 387 + 3813 2823 18 620 + 3813 400 7 102 + 4004 4376 98 387 + 4004 4894 39 53 + 4004 202 62 436 + 4376 3813 44 387 + 4376 1321 7 719 + 4376 722 49 502 + 284 3279 66 339 + 284 1049 76 96 + 284 4340 21 904 + 1683 4413 82 339 + 1683 358 70 940 + 2404 4657 93 339 + 2404 4119 84 245 + 2404 2343 15 55 + 2710 2404 70 339 + 2710 1734 99 531 + 3279 4251 59 339 + 3279 3648 2 78 + 3279 4216 71 485 + 3493 2710 44 339 + 3493 3180 86 475 + 3493 231 48 85 + 3665 4530 91 339 + 3665 1683 13 339 + 3665 4543 1 33 + 4251 3665 98 339 + 4251 4918 6 77 + 4251 1117 75 865 + 4413 3493 24 339 + 4413 30 90 955 + 285 1147 54 882 + 285 3609 59 774 + 701 1145 15 882 + 701 723 8 570 + 701 1408 22 426 + 1145 1519 43 882 + 1145 4057 100 194 + 1145 548 87 825 + 1147 701 57 882 + 1147 481 97 740 + 1147 2138 55 975 + 1519 2452 79 882 + 1519 3952 72 904 + 2174 3251 99 882 + 2174 4629 8 882 + 2174 3033 14 435 + 2174 3371 27 484 + 2298 2174 93 882 + 2298 2277 8 287 + 2452 2792 61 882 + 2452 44 74 263 + 2792 3242 11 882 + 2792 4986 68 73 + 3242 2298 69 882 + 3242 575 61 70 + 3242 1143 95 169 + 3251 4684 79 882 + 3251 769 52 530 + 286 4303 31 400 + 286 1041 82 678 + 286 4841 81 931 + 1201 1389 26 400 + 1201 4991 38 739 + 1375 1201 36 400 + 1375 693 92 427 + 1375 2942 83 867 + 1389 2495 41 400 + 1389 4698 10 244 + 1389 2191 4 1000 + 1548 3487 14 400 + 1548 4643 19 622 + 1548 1751 53 133 + 1875 1548 22 400 + 1875 4619 2 400 + 1875 3637 36 808 + 1875 4168 49 298 + 2140 1375 63 400 + 2140 4815 73 899 + 2495 4856 24 400 + 2495 584 96 559 + 3376 1875 76 400 + 3376 4783 7 604 + 3376 4847 17 308 + 3487 2140 77 400 + 3487 4985 27 799 + 4249 3376 53 400 + 4249 193 74 471 + 4249 757 23 752 + 4303 4249 25 400 + 4303 246 32 999 + 4303 615 83 346 + 287 4029 78 410 + 287 3554 14 440 + 287 2555 91 435 + 556 848 96 410 + 556 346 16 358 + 848 2885 2 410 + 848 2419 54 950 + 848 4282 58 342 + 2447 3435 26 410 + 2447 1635 73 361 + 2885 4288 95 410 + 2885 4731 99 410 + 2885 3122 52 778 + 2955 3455 58 410 + 2955 635 61 866 + 3435 2955 18 410 + 3435 1436 23 301 + 3435 2607 66 435 + 3455 556 12 410 + 3455 1407 81 560 + 4029 2447 39 410 + 4029 1998 21 430 + 4029 1302 55 378 + 4288 4770 38 410 + 4288 4746 82 508 + 4288 4401 12 994 + 288 3125 12 534 + 288 459 76 866 + 672 4922 15 534 + 672 1277 81 793 + 672 4763 89 982 + 987 2665 86 534 + 987 1711 10 101 + 987 342 98 367 + 1450 2044 87 534 + 1450 3110 16 875 + 1450 1876 48 266 + 1604 672 97 534 + 1604 2756 53 181 + 1604 2836 29 823 + 1839 4891 36 534 + 1839 1450 5 534 + 1839 1511 35 437 + 1839 4487 66 769 + 1910 3877 9 534 + 1910 2454 18 6 + 1910 581 76 856 + 2044 1910 67 534 + 2044 1291 69 229 + 2044 3589 77 988 + 2356 3370 39 534 + 2356 4509 37 534 + 2356 2916 9 577 + 2356 4430 53 825 + 2665 2356 63 534 + 2665 4856 97 884 + 3125 987 27 534 + 3125 1727 39 525 + 3370 1839 68 534 + 3370 4911 51 323 + 3877 1604 16 534 + 3877 4057 99 534 + 289 3962 17 932 + 289 813 60 307 + 289 2110 6 64 + 963 4375 56 932 + 963 727 78 746 + 963 851 48 212 + 1051 1592 66 932 + 1051 4800 84 932 + 1051 1815 60 826 + 1501 1741 61 932 + 1501 755 33 1 + 1592 4766 10 932 + 1592 4930 26 288 + 1592 2554 54 313 + 1741 963 86 932 + 1741 1637 41 427 + 2357 1051 99 932 + 2357 1858 92 147 + 2357 3210 51 650 + 3962 1501 36 932 + 3962 2318 96 368 + 4375 2357 92 932 + 4375 2755 98 537 + 290 3479 55 367 + 290 3686 85 78 + 290 789 95 939 + 2169 2947 2 367 + 2169 3409 56 37 + 2169 3126 10 706 + 2484 3804 49 367 + 2484 2673 47 847 + 2484 1874 42 6 + 2947 3189 13 367 + 2947 1148 17 93 + 2947 4748 8 824 + 3189 4068 8 367 + 3189 2915 37 553 + 3418 4947 24 367 + 3418 662 42 19 + 3418 4749 71 440 + 3479 2484 19 367 + 3479 4560 66 464 + 3804 2169 73 367 + 3804 873 91 72 + 4068 3418 79 367 + 4068 4932 83 367 + 4068 3704 39 422 + 291 4254 25 747 + 291 2018 97 145 + 291 3167 28 629 + 586 4089 28 747 + 586 2680 80 816 + 1569 4961 74 747 + 1569 4627 3 747 + 1569 3489 57 724 + 1569 1398 48 640 + 2180 586 31 747 + 2180 4085 84 437 + 4089 4356 65 747 + 4089 885 36 740 + 4254 4491 16 747 + 4254 3763 61 320 + 4356 1569 71 747 + 4356 2586 16 481 + 4356 3751 39 405 + 4491 2180 88 747 + 4491 4221 25 381 + 4491 1200 27 660 + 292 3820 76 470 + 292 64 70 101 + 292 2612 63 413 + 537 2085 90 470 + 537 278 8 749 + 981 4512 49 470 + 981 752 77 247 + 1972 2989 34 470 + 1972 3900 58 331 + 1972 4315 3 940 + 2085 1972 71 470 + 2085 3232 1 12 + 2085 202 34 668 + 2989 981 53 470 + 2989 4135 61 682 + 3757 537 16 470 + 3757 4292 67 853 + 3757 1098 27 551 + 3820 3757 58 470 + 3820 4766 11 470 + 3820 1722 31 810 + 293 954 95 202 + 293 491 83 717 + 293 2886 91 944 + 954 997 68 202 + 954 623 45 134 + 997 1838 29 202 + 997 4801 51 93 + 997 4336 49 925 + 1013 4789 18 202 + 1013 3096 2 149 + 1838 2510 86 202 + 1838 1039 48 570 + 2510 4345 6 202 + 2510 1717 59 320 + 2510 3246 83 36 + 4345 1013 8 202 + 4345 4625 19 202 + 4345 3274 39 589 + 4345 69 99 36 + 294 882 91 680 + 294 3735 25 561 + 882 1092 67 680 + 882 1028 35 544 + 882 3148 70 142 + 1044 2720 31 680 + 1044 432 65 667 + 1092 4151 26 680 + 1092 1333 76 145 + 2720 4846 31 680 + 2720 3200 20 283 + 2720 715 13 172 + 2897 3111 43 680 + 2897 4506 11 680 + 2897 1800 80 842 + 2897 683 63 238 + 3111 1044 79 680 + 3111 4679 53 633 + 3111 1748 9 667 + 4151 2897 72 680 + 4151 4794 97 683 + 4151 1461 68 564 + 295 4275 9 354 + 295 4475 29 326 + 295 4538 33 9 + 548 2772 85 354 + 548 2749 9 298 + 652 4490 5 354 + 652 3291 96 615 + 652 3333 98 44 + 1384 4680 67 354 + 1384 2504 74 143 + 1653 2717 18 354 + 1653 2709 32 139 + 1653 1969 99 295 + 1879 652 77 354 + 1879 2538 13 523 + 2012 1653 42 354 + 2012 1954 51 799 + 2012 70 53 686 + 2717 1384 100 354 + 2717 3774 76 676 + 2772 4542 53 354 + 2772 4182 31 354 + 2772 494 34 691 + 4182 2012 32 354 + 4182 2517 9 86 + 4182 4318 69 124 + 4275 1879 58 354 + 4275 1207 48 124 + 4275 1335 36 527 + 4490 548 3 354 + 4490 1088 93 174 + 4490 624 53 600 + 296 3716 18 730 + 296 1419 75 781 + 296 3413 29 623 + 904 3322 2 730 + 904 3470 7 967 + 904 4370 29 230 + 1229 3518 96 730 + 1229 3507 48 785 + 1229 2254 61 593 + 1509 1815 37 730 + 1509 4130 41 233 + 1815 4513 65 730 + 1815 4748 33 730 + 1815 4417 73 509 + 1815 4465 68 761 + 3322 1229 58 730 + 3322 2661 12 888 + 3322 3001 25 653 + 3496 1509 4 730 + 3496 6 22 296 + 3496 943 59 981 + 3518 4047 43 730 + 3518 4393 61 719 + 3518 2245 41 223 + 3716 904 48 730 + 3716 1043 52 939 + 3716 890 30 54 + 4047 3496 61 730 + 4047 3144 11 832 + 297 643 94 451 + 297 446 100 861 + 297 2259 99 248 + 643 3011 2 451 + 643 1181 75 130 + 1266 3671 31 451 + 1266 1769 98 928 + 1843 1266 8 451 + 1843 3082 51 994 + 2381 3262 81 451 + 2381 4741 4 451 + 2381 266 34 650 + 2381 3030 40 664 + 3011 1843 94 451 + 3011 1445 49 177 + 3011 4317 68 567 + 3262 4669 59 451 + 3262 4403 36 448 + 3262 4027 17 748 + 3671 4185 22 451 + 3671 30 96 243 + 4185 2381 52 451 + 4185 739 85 602 + 298 3809 36 408 + 298 35 82 975 + 298 3738 67 242 + 1573 4705 12 408 + 1573 2865 43 408 + 1573 544 80 308 + 1945 2189 88 408 + 1945 3996 55 294 + 2189 4382 2 408 + 2189 1085 35 131 + 2865 3827 49 408 + 2865 3037 96 33 + 2865 4242 76 389 + 3572 4106 55 408 + 3572 1419 97 426 + 3572 3004 14 214 + 3809 1945 6 408 + 3809 4547 47 508 + 3809 526 38 447 + 3827 4518 43 408 + 3827 4034 2 992 + 3827 948 62 505 + 4106 1573 7 408 + 4106 2372 25 20 + 4382 3572 48 408 + 4382 803 91 651 + 4382 2601 99 880 + 299 757 33 559 + 299 4995 33 494 + 299 200 7 839 + 757 1520 64 559 + 757 3872 74 781 + 757 196 70 475 + 1307 4588 98 559 + 1307 301 46 410 + 1307 327 60 919 + 1520 2745 88 559 + 1520 2052 53 562 + 1520 4721 45 578 + 2371 4442 56 559 + 2371 1233 5 567 + 2371 3728 77 977 + 2745 3022 95 559 + 2745 4827 6 702 + 3022 2371 76 559 + 3022 4986 2 127 + 3022 3379 40 36 + 3529 3861 43 559 + 3529 4797 87 421 + 3529 2134 72 96 + 3551 1307 8 559 + 3551 3286 42 133 + 3551 1615 15 931 + 3861 3551 28 559 + 3861 2594 16 875 + 4442 3529 60 559 + 4442 4613 66 559 + 4442 3985 57 350 + 300 2049 20 1159 + 300 3666 8 114 + 2049 2240 53 1159 + 2049 1517 75 435 + 2240 2813 66 1159 + 2240 4833 6 1159 + 2240 2994 31 776 + 2267 3440 46 1159 + 2267 3048 64 720 + 2313 3955 32 1159 + 2313 3271 20 340 + 2813 2267 97 1159 + 2813 4977 43 440 + 2813 3486 18 484 + 3440 2313 11 1159 + 3440 3193 21 243 + 3440 1393 66 28 + 3955 4427 84 1159 + 3955 2747 48 832 + 4427 4968 83 1159 + 4427 4157 1 881 + 4427 2341 67 491 + 301 812 85 153 + 301 2132 7 363 + 301 3919 15 486 + 812 3517 8 153 + 812 4266 2 888 + 1325 3993 96 153 + 1325 391 85 214 + 1393 4707 8 153 + 1393 3068 72 153 + 1393 743 61 766 + 1393 3361 78 758 + 1546 4890 57 153 + 1546 747 66 755 + 1546 3799 1 634 + 2081 1546 41 153 + 2081 4737 85 217 + 2081 2481 33 180 + 2974 2081 89 153 + 2974 1418 20 816 + 2974 2758 39 456 + 3068 2974 89 153 + 3068 1913 51 304 + 3068 1230 26 32 + 3517 1325 93 153 + 3517 4400 6 28 + 3993 1393 21 153 + 3993 2215 88 673 + 3993 1508 89 420 + 302 3854 58 260 + 302 3386 51 514 + 1714 2539 62 260 + 1714 3765 28 757 + 1714 4617 40 426 + 1897 4157 37 260 + 1897 3497 35 348 + 2079 1897 77 260 + 2079 1715 43 317 + 2079 2759 59 745 + 2444 3122 71 260 + 2444 799 49 653 + 2473 4979 93 260 + 2473 2444 8 260 + 2473 1897 43 734 + 2473 3072 92 741 + 2539 2079 87 260 + 2539 3572 50 76 + 2539 2673 10 208 + 3122 1714 23 260 + 3122 2407 88 538 + 3122 1287 36 790 + 3854 2473 94 260 + 3854 1713 59 614 + 4084 4429 11 260 + 4084 268 35 476 + 4157 4084 65 260 + 4157 371 67 672 + 4157 1360 7 112 + 4429 4781 80 260 + 4429 2761 59 576 + 4429 149 29 720 + 303 1918 48 689 + 303 4081 42 166 + 875 1113 57 689 + 875 1763 79 739 + 875 851 4 80 + 1113 1712 3 689 + 1113 1881 88 142 + 1712 4661 19 689 + 1712 3316 96 383 + 1712 4570 26 291 + 1918 3053 31 689 + 1918 3398 76 525 + 1918 2224 47 701 + 2086 2210 84 689 + 2086 1090 3 821 + 2210 3900 67 689 + 2210 2756 23 483 + 3053 2086 28 689 + 3053 535 27 268 + 3053 2036 38 319 + 3900 875 17 689 + 3900 4666 71 689 + 3900 2354 19 587 + 3900 4205 41 235 + 304 3259 69 914 + 304 3667 62 7 + 748 2945 52 914 + 748 4215 99 428 + 1854 4503 66 914 + 1854 3830 17 914 + 1854 1196 20 840 + 2004 3109 21 914 + 2004 4102 24 666 + 2004 707 43 508 + 2215 2449 42 914 + 2215 4391 8 61 + 2215 2673 6 585 + 2449 4623 42 914 + 2449 4376 4 845 + 2945 1854 1 914 + 2945 223 35 158 + 2945 3691 48 140 + 2946 2004 58 914 + 2946 1158 76 104 + 3109 2215 81 914 + 3109 180 47 601 + 3109 1092 99 866 + 3259 4381 9 914 + 3259 3186 93 305 + 3830 2946 50 914 + 3830 1838 11 623 + 3830 3092 56 794 + 4381 748 10 914 + 4381 4003 41 552 + 4381 1142 6 89 + 305 3604 41 83 + 305 3154 70 608 + 305 4420 49 335 + 977 2716 44 83 + 977 4317 37 332 + 977 1751 59 519 + 1301 2099 6 83 + 1301 2396 20 237 + 1301 1038 7 335 + 1579 977 83 83 + 1579 3126 76 828 + 1579 1725 39 615 + 1600 2595 68 83 + 1600 2892 6 626 + 1705 4949 22 83 + 1705 2695 57 992 + 2008 1579 77 83 + 2008 3396 18 381 + 2099 1600 86 83 + 2099 4583 73 83 + 2099 4550 7 360 + 2116 1705 100 83 + 2116 4515 68 113 + 2595 2008 87 83 + 2595 4942 98 83 + 2595 1661 81 209 + 2716 3382 10 83 + 2716 2135 51 24 + 2716 3199 88 376 + 3382 2116 46 83 + 3382 234 55 682 + 3382 1952 56 560 + 3604 1301 28 83 + 3604 4268 100 86 + 306 2514 96 256 + 306 3235 33 909 + 306 3932 57 807 + 758 1836 23 256 + 758 1663 18 563 + 1440 1863 11 256 + 1440 851 84 577 + 1613 1440 42 256 + 1613 3004 100 909 + 1836 1613 28 256 + 1836 1769 34 983 + 1863 4648 71 256 + 1863 4994 94 256 + 1863 3514 81 534 + 2431 758 96 256 + 2431 3247 53 486 + 2431 2667 37 759 + 2514 2431 25 256 + 2514 3104 95 216 + 307 2601 31 52 + 307 233 26 813 + 1377 4976 50 52 + 1377 2233 73 52 + 1377 99 81 813 + 1553 4434 15 52 + 1553 2430 64 214 + 1553 1069 4 931 + 1804 1377 44 52 + 1804 3311 35 109 + 2233 3520 56 52 + 2233 3810 90 575 + 2601 3282 39 52 + 2601 196 47 19 + 2601 172 63 728 + 3282 4489 64 52 + 3282 3781 44 149 + 3282 666 54 272 + 3520 1553 57 52 + 3520 2624 21 599 + 4434 4796 71 52 + 4434 3458 68 821 + 4489 1804 55 52 + 4489 302 19 99 + 308 3598 98 194 + 308 291 76 609 + 634 4989 6 194 + 634 2102 87 194 + 634 647 62 590 + 1136 4742 13 194 + 1136 3880 16 148 + 2102 1136 38 194 + 2102 676 66 202 + 2139 634 70 194 + 2139 3687 72 835 + 2139 1756 80 975 + 3598 3783 15 194 + 3598 4699 66 929 + 3598 4647 78 352 + 3783 2139 93 194 + 3783 854 82 177 + 309 4284 96 1290 + 309 1790 26 78 + 309 4580 83 456 + 508 4579 53 1290 + 508 3170 90 647 + 508 1557 23 595 + 1034 508 82 1290 + 1034 4697 45 217 + 1034 4837 42 666 + 1597 2552 78 1290 + 1597 4016 53 244 + 1597 3370 10 315 + 2552 1034 100 1290 + 2552 418 47 331 + 2552 2025 65 964 + 4263 1597 74 1290 + 4263 4654 54 1290 + 4263 2169 13 187 + 4263 3316 11 874 + 4284 4426 55 1290 + 4284 2774 57 544 + 4426 4263 24 1290 + 4426 1293 29 415 + 4426 1231 66 85 + 310 1274 58 473 + 310 3545 6 767 + 825 2466 32 473 + 825 4941 48 265 + 1274 825 33 473 + 1274 4763 28 473 + 1274 2298 44 401 + 1274 1681 41 524 + 1883 2879 51 473 + 1883 635 42 711 + 1883 1526 69 654 + 1998 1883 91 473 + 1998 749 45 538 + 1998 3760 68 216 + 2268 1998 55 473 + 2268 3547 20 277 + 2466 4025 94 473 + 2466 4362 72 981 + 2466 220 96 188 + 2879 4508 60 473 + 2879 3287 44 41 + 4025 2268 9 473 + 4025 4039 67 250 + 311 3938 42 717 + 311 4002 62 283 + 311 2995 10 540 + 662 4979 3 717 + 662 128 9 966 + 662 1194 15 390 + 862 3934 57 717 + 862 4886 60 717 + 862 4811 8 195 + 862 2920 44 931 + 1781 662 5 717 + 1781 22 74 477 + 2439 4156 91 717 + 2439 1332 37 601 + 3934 2439 62 717 + 3934 583 4 760 + 3938 4145 80 717 + 3938 3536 90 729 + 4145 862 72 717 + 4145 1672 33 660 + 4145 3177 16 650 + 4156 1781 53 717 + 4156 4023 21 970 + 312 2840 34 163 + 312 3786 53 525 + 1341 3779 90 163 + 1341 2288 53 930 + 1990 2421 13 163 + 1990 2998 81 514 + 1990 4607 31 832 + 2394 1341 87 163 + 2394 2059 84 6 + 2421 4087 76 163 + 2421 4408 62 999 + 2421 2322 72 504 + 2840 1990 78 163 + 2840 2343 98 312 + 2840 1542 84 861 + 3779 4742 17 163 + 3779 4969 64 163 + 3779 4486 28 659 + 4087 2394 26 163 + 4087 4510 80 803 + 313 2503 6 728 + 313 3690 20 189 + 313 1243 92 605 + 611 2821 59 728 + 611 3971 27 921 + 710 4428 55 728 + 710 3442 38 832 + 1542 611 70 728 + 1542 53 20 532 + 1542 2111 35 975 + 2279 3462 100 728 + 2279 1263 50 987 + 2503 710 33 728 + 2503 2985 76 116 + 2503 4920 11 559 + 2821 4584 71 728 + 2821 2279 70 728 + 2821 1743 3 717 + 2821 989 73 987 + 3462 4682 75 728 + 3462 2639 86 749 + 4428 1542 64 728 + 4428 4531 98 943 + 4428 524 83 352 + 314 3512 17 756 + 314 3235 31 964 + 573 3494 96 756 + 573 174 98 874 + 573 2010 69 162 + 916 2249 97 756 + 916 4741 84 756 + 916 3010 47 665 + 1186 916 27 756 + 1186 1633 22 113 + 1186 2455 42 901 + 2249 573 63 756 + 2249 850 27 984 + 2249 4565 5 158 + 3494 4691 73 756 + 3494 1579 36 602 + 3512 1186 57 756 + 3512 1151 59 700 + 315 2082 46 353 + 315 551 35 417 + 513 3567 2 353 + 513 2390 56 385 + 513 3148 92 913 + 1419 2815 65 353 + 1419 391 3 985 + 1419 3826 83 59 + 1536 3058 65 353 + 1536 2849 11 705 + 1720 3837 40 353 + 1720 1864 82 712 + 1720 3918 29 187 + 1967 4890 72 353 + 1967 1720 64 353 + 1967 2487 100 974 + 1967 283 18 549 + 2082 513 25 353 + 2082 4962 57 353 + 2082 1971 96 248 + 2815 4541 61 353 + 2815 1583 42 790 + 2815 1217 1 616 + 3058 3957 98 353 + 3058 3856 54 525 + 3058 1256 72 199 + 3567 4283 80 353 + 3567 1032 7 89 + 3567 265 90 24 + 3837 1536 32 353 + 3837 390 81 253 + 3957 1419 43 353 + 3957 4438 37 821 + 4109 1967 25 353 + 4109 1313 100 908 + 4109 1827 63 364 + 4283 4109 3 353 + 4283 2576 67 857 + 4283 3397 83 26 + 316 1009 10 294 + 316 4747 11 372 + 316 4770 1 521 + 894 4750 99 294 + 894 4937 76 294 + 894 3222 34 986 + 1009 2909 96 294 + 1009 950 7 966 + 1009 3138 43 370 + 1248 2170 62 294 + 1248 3302 86 374 + 2170 894 95 294 + 2170 912 58 45 + 2170 2088 8 285 + 2909 1248 99 294 + 2909 3557 66 346 + 2909 4505 73 677 + 317 2932 2 316 + 317 4149 14 922 + 317 1570 29 687 + 546 4690 65 316 + 546 3229 76 316 + 546 1214 76 552 + 546 3183 18 178 + 2932 3200 43 316 + 2932 1767 30 377 + 2932 2621 3 806 + 3200 3863 45 316 + 3200 762 43 90 + 3229 4040 76 316 + 3229 1000 77 708 + 3229 838 14 104 + 3746 4877 91 316 + 3746 4554 18 301 + 3863 546 25 316 + 3863 2356 54 743 + 3863 2706 40 849 + 4040 3746 22 316 + 4040 1090 100 499 + 4040 3554 25 519 + 318 557 8 213 + 318 38 24 281 + 318 592 18 956 + 523 4645 18 213 + 523 1358 30 199 + 523 3522 28 656 + 549 911 35 213 + 549 1511 12 188 + 549 392 49 754 + 557 3388 99 213 + 557 2800 52 857 + 557 451 78 514 + 911 523 39 213 + 911 3427 63 474 + 1528 549 48 213 + 1528 4888 81 213 + 1528 4545 87 389 + 1528 4236 35 158 + 1761 1528 20 213 + 1761 2539 28 290 + 1761 673 53 30 + 2596 1761 24 213 + 2596 2419 82 245 + 3388 2596 4 213 + 3388 1882 47 939 + 3388 2597 63 229 + 319 2630 31 698 + 319 3985 49 852 + 319 630 24 614 + 650 3004 73 698 + 650 2592 7 388 + 842 2935 26 698 + 842 1684 92 795 + 1917 650 87 698 + 1917 1665 32 331 + 2005 3741 26 698 + 2005 1032 58 107 + 2005 34 85 332 + 2630 3721 74 698 + 2630 4926 77 38 + 2630 2382 33 330 + 2697 1917 35 698 + 2697 4537 73 654 + 2697 3595 99 804 + 2935 4527 30 698 + 2935 2697 23 698 + 2935 3675 59 554 + 3004 4692 26 698 + 3004 3735 44 711 + 3721 2005 98 698 + 3721 1681 53 98 + 3721 760 77 855 + 3741 842 8 698 + 3741 2342 96 330 + 3741 1771 35 840 + 320 506 89 407 + 320 3938 40 274 + 506 1537 70 407 + 506 2372 54 112 + 1258 4686 78 407 + 1258 1994 78 713 + 1258 1362 78 584 + 1328 3884 82 407 + 1328 485 28 881 + 1328 1116 53 368 + 1537 2643 42 407 + 1537 2351 80 255 + 1846 1258 22 407 + 1846 2945 17 832 + 1846 4995 42 739 + 2643 1328 46 407 + 2643 3989 87 391 + 2643 664 51 64 + 3074 3926 47 407 + 3074 209 22 7 + 3884 3074 35 407 + 3884 1684 81 22 + 3884 1064 91 886 + 3926 1846 47 407 + 3926 4755 13 407 + 3926 2784 32 609 + 321 897 23 416 + 321 72 37 180 + 321 304 75 496 + 694 2238 44 416 + 694 3970 75 160 + 694 513 88 666 + 897 1697 67 416 + 897 1198 31 445 + 1697 2632 23 416 + 1697 4862 67 416 + 1697 3054 32 67 + 2238 2410 26 416 + 2238 176 60 112 + 2410 3447 56 416 + 2410 1269 29 484 + 2632 694 87 416 + 2632 196 38 787 + 2632 881 97 925 + 3447 4904 92 416 + 3447 3988 57 62 + 322 3114 82 385 + 322 2243 47 600 + 1074 1685 29 385 + 1074 2136 42 459 + 1234 2101 9 385 + 1234 598 65 4 + 1242 1074 21 385 + 1242 502 58 496 + 1242 4074 6 354 + 1685 1234 44 385 + 1685 4738 17 80 + 2101 4848 77 385 + 2101 4014 11 245 + 3114 1242 97 385 + 3114 4716 12 385 + 3114 1038 45 934 + 323 4448 86 532 + 323 1422 24 805 + 323 812 93 190 + 764 1497 35 532 + 764 4956 97 532 + 764 4485 68 695 + 1212 4065 27 532 + 1212 2622 72 528 + 1212 3103 46 731 + 1497 1212 4 532 + 1497 3735 64 672 + 2950 764 52 532 + 2950 1663 83 990 + 2950 3947 4 781 + 4065 4614 21 532 + 4065 1251 67 669 + 4065 2299 71 239 + 4448 2950 55 532 + 4448 1896 59 900 + 324 2211 67 277 + 324 2739 81 52 + 324 3090 88 930 + 1014 4798 43 277 + 1014 4599 80 662 + 1489 2341 86 277 + 1489 1749 24 774 + 1489 357 39 312 + 2211 4315 5 277 + 2211 4547 70 277 + 2211 3152 93 287 + 2317 2326 25 277 + 2317 1398 17 276 + 2317 4477 13 115 + 2326 1014 39 277 + 2326 4617 43 616 + 2341 2317 36 277 + 2341 1154 6 925 + 2341 3362 43 420 + 4315 4318 18 277 + 4315 4312 14 999 + 4318 1489 1 277 + 4318 2545 27 569 + 325 1852 76 593 + 325 67 36 110 + 325 3376 24 796 + 632 3748 67 593 + 632 1434 82 28 + 1852 3522 29 593 + 1852 1785 71 515 + 1852 623 16 315 + 2981 4571 87 593 + 2981 3299 2 446 + 3522 632 47 593 + 3522 2607 4 870 + 3522 733 40 61 + 3711 4924 13 593 + 3711 2981 29 593 + 3711 4334 18 784 + 3711 2665 62 549 + 3748 3711 72 593 + 3748 3847 52 508 + 326 3499 48 972 + 326 828 83 444 + 326 1565 45 633 + 544 3759 38 972 + 544 4414 86 819 + 544 44 2 559 + 1349 3910 33 972 + 1349 826 71 672 + 1349 571 78 533 + 2393 4140 5 972 + 2393 1290 10 898 + 3325 4533 89 972 + 3325 2393 70 972 + 3325 1415 62 623 + 3499 544 64 972 + 3499 3808 87 162 + 3759 1349 10 972 + 3759 4467 16 669 + 3910 3325 2 972 + 3910 1411 2 276 + 3910 3142 36 368 + 3967 4914 84 972 + 3967 1466 72 853 + 4140 3967 53 972 + 4140 1531 9 374 + 4140 4187 76 557 + 327 3624 7 694 + 327 3428 100 248 + 327 4988 82 432 + 1225 3051 10 694 + 1225 1833 56 103 + 1225 4619 22 513 + 2382 4914 21 694 + 2382 4638 19 919 + 2382 153 60 938 + 2405 1225 61 694 + 2405 3607 29 619 + 3051 2382 27 694 + 3051 3850 14 767 + 3624 4941 20 694 + 3624 4115 38 694 + 3624 3527 78 6 + 4115 2405 65 694 + 4115 3431 36 331 + 4115 4640 92 745 + 328 3059 99 289 + 328 1350 64 434 + 328 1797 81 732 + 732 4137 99 289 + 732 3099 22 537 + 899 1187 54 289 + 899 1694 42 95 + 1187 1721 66 289 + 1187 4875 65 289 + 1187 154 31 200 + 1721 732 61 289 + 1721 1890 75 344 + 2942 899 46 289 + 2942 2631 80 929 + 2942 3459 51 51 + 3059 3206 64 289 + 3059 108 6 2 + 3059 3323 16 604 + 3206 2942 7 289 + 3206 2439 76 226 + 3206 587 49 295 + 4137 4928 10 289 + 4137 541 6 759 + 329 577 27 1387 + 329 4573 56 216 + 329 3796 76 154 + 577 3179 84 1387 + 577 574 71 178 + 577 2552 81 963 + 872 4722 79 1387 + 872 4538 22 211 + 872 1711 70 293 + 1318 2767 48 1387 + 1318 98 9 291 + 1318 4562 75 778 + 2376 4031 8 1387 + 2376 4387 79 476 + 2376 2672 57 470 + 2480 1318 77 1387 + 2480 2223 85 804 + 2480 33 10 309 + 2767 872 99 1387 + 2767 1933 19 786 + 3179 2376 9 1387 + 3179 3356 96 679 + 3179 4931 96 359 + 4031 2480 3 1387 + 4031 4709 99 1387 + 4031 3192 96 340 + 4031 4681 77 176 + 330 2458 54 296 + 330 52 76 175 + 561 4097 44 296 + 561 4512 10 291 + 1538 3446 61 296 + 1538 3224 7 623 + 1686 1771 96 296 + 1686 1524 85 245 + 1771 3015 42 296 + 1771 4939 33 282 + 1771 4602 25 106 + 2458 1686 86 296 + 2458 2586 97 749 + 3015 3983 55 296 + 3015 2116 42 99 + 3035 4708 90 296 + 3035 4551 60 296 + 3035 2226 43 558 + 3035 2693 9 380 + 3446 3035 73 296 + 3446 662 5 142 + 3446 2923 2 548 + 3983 4438 54 296 + 3983 957 59 935 + 4097 1538 46 296 + 4097 2983 16 902 + 4438 561 71 296 + 4438 168 22 513 + 331 2050 2 922 + 331 526 86 618 + 782 1566 52 922 + 782 4934 50 922 + 782 2977 79 913 + 1007 1921 84 922 + 1007 3597 54 2 + 1007 1882 22 503 + 1566 3903 13 922 + 1566 3891 37 393 + 1566 281 49 282 + 1921 3944 99 922 + 1921 4210 94 754 + 2050 3174 99 922 + 2050 1556 40 920 + 3174 1007 15 922 + 3174 1858 23 496 + 3903 4528 55 922 + 3903 808 41 810 + 3944 782 11 922 + 3944 1455 88 223 + 332 3334 32 184 + 332 2538 76 459 + 593 4523 85 184 + 593 2521 58 751 + 593 3038 19 994 + 1319 4579 64 184 + 1319 2719 17 184 + 1319 2068 66 55 + 2719 593 81 184 + 2719 3621 32 477 + 3334 4346 40 184 + 3334 3013 34 696 + 4346 1319 54 184 + 4346 3885 28 530 + 333 3356 73 535 + 333 1613 95 612 + 333 3147 1 57 + 636 4258 78 535 + 636 87 67 240 + 636 3801 11 838 + 2983 3573 93 535 + 2983 4335 16 967 + 3021 3082 55 535 + 3021 141 32 314 + 3021 3181 1 798 + 3082 636 45 535 + 3082 99 16 8 + 3082 1421 99 147 + 3356 3021 100 535 + 3356 4977 32 535 + 3356 2051 97 161 + 3356 4564 18 209 + 3573 4787 22 535 + 3573 4243 67 86 + 3573 4711 27 236 + 4073 2983 87 535 + 4073 2807 62 936 + 4177 4073 2 535 + 4177 4478 27 628 + 4177 1560 55 760 + 4258 4177 41 535 + 4258 4224 47 709 + 334 4245 65 1428 + 334 1409 17 172 + 334 3886 20 787 + 1254 3413 28 1428 + 1254 4214 42 766 + 1254 1510 81 578 + 2173 2905 36 1428 + 2173 4683 38 1428 + 2173 3880 15 700 + 2173 1950 52 553 + 2723 2173 16 1428 + 2723 4186 91 519 + 2723 2895 94 389 + 2905 1254 86 1428 + 2905 1232 41 78 + 3413 4665 84 1428 + 3413 2056 25 383 + 4245 2723 59 1428 + 4245 4979 18 713 + 4245 980 64 116 + 335 1894 66 384 + 335 994 1 620 + 335 1036 10 46 + 1042 4625 44 384 + 1042 43 72 509 + 1042 2674 94 140 + 1224 4132 1 384 + 1224 3426 94 704 + 1317 2628 95 384 + 1317 4730 54 384 + 1317 2514 69 585 + 1638 1317 31 384 + 1638 3243 18 241 + 1894 1224 7 384 + 1894 1256 19 95 + 2628 3150 27 384 + 2628 1951 74 359 + 2628 4899 78 53 + 3150 1042 46 384 + 3150 2027 74 613 + 4132 1638 42 384 + 4132 1642 58 242 + 4132 1842 43 687 + 336 1780 12 271 + 336 1340 2 373 + 336 2455 72 205 + 588 1486 97 271 + 588 467 7 689 + 588 871 42 439 + 1486 3181 28 271 + 1486 2066 64 521 + 1486 2055 87 831 + 1780 2109 3 271 + 1780 2933 75 787 + 1780 4038 33 17 + 2109 2528 59 271 + 2109 4483 58 727 + 2109 4251 71 842 + 2528 588 86 271 + 2528 3536 27 734 + 2528 1360 91 71 + 3181 4584 33 271 + 3181 4877 4 271 + 3181 4349 76 23 + 337 4218 39 74 + 337 2481 16 863 + 2093 3478 34 74 + 2093 1390 38 774 + 2392 4313 64 74 + 2392 4705 77 74 + 2392 4295 64 603 + 3375 2093 26 74 + 3375 4381 36 119 + 3478 4403 36 74 + 3478 2687 15 772 + 3478 1908 35 156 + 4218 3375 49 74 + 4218 55 91 325 + 4313 4924 34 74 + 4313 57 21 306 + 4403 2392 58 74 + 4403 1117 66 944 + 338 2835 73 427 + 338 3938 40 145 + 597 3750 67 427 + 597 4775 31 295 + 780 2457 23 427 + 780 1126 1 394 + 2457 597 94 427 + 2457 4727 40 427 + 2457 1625 95 648 + 2803 4003 77 427 + 2803 906 32 725 + 2835 2803 77 427 + 2835 4202 50 173 + 3486 780 53 427 + 3486 2971 86 923 + 3486 2496 36 560 + 3602 4414 59 427 + 3602 4477 66 540 + 3602 1126 77 425 + 3750 3602 54 427 + 3750 2191 18 606 + 4003 3486 56 427 + 4003 2871 75 511 + 4003 797 36 817 + 4414 4760 7 427 + 4414 1343 27 181 + 4414 4943 71 452 + 339 1913 81 400 + 339 4296 70 640 + 339 2699 80 355 + 1912 4683 58 400 + 1912 4204 51 877 + 1913 2114 62 400 + 1913 3685 50 500 + 2114 3450 95 400 + 2114 505 46 796 + 2114 943 68 322 + 2347 4576 94 400 + 2347 3587 30 400 + 2347 1270 6 366 + 2347 134 53 42 + 3450 2347 79 400 + 3450 3400 52 860 + 3587 3894 51 400 + 3587 1259 96 916 + 3894 1912 87 400 + 3894 887 53 554 + 340 1127 85 584 + 340 3969 66 139 + 775 2270 94 584 + 775 223 49 86 + 775 50 29 59 + 1127 1626 96 584 + 1127 2995 95 549 + 1127 4541 14 919 + 1207 3255 70 584 + 1207 4321 75 984 + 1207 2065 88 110 + 1431 2248 39 584 + 1431 3103 38 552 + 1431 4573 45 739 + 1626 1431 94 584 + 1626 4080 17 320 + 1626 3420 2 511 + 1861 2015 7 584 + 1861 3150 98 355 + 2015 775 2 584 + 2015 4682 45 584 + 2015 737 91 604 + 2248 1207 45 584 + 2248 510 28 672 + 2248 2943 91 29 + 2270 4776 29 584 + 2270 2419 85 292 + 2270 4192 78 467 + 3255 1861 41 584 + 3255 2991 6 382 + 3255 3947 75 467 + 341 1514 65 411 + 341 4750 1 753 + 341 2443 46 500 + 1514 3237 93 411 + 1514 4714 73 925 + 1550 3904 73 411 + 1550 4991 72 411 + 1550 4587 79 710 + 1550 721 59 75 + 3002 4290 60 411 + 3002 4409 45 305 + 3002 3867 2 280 + 3237 3002 51 411 + 3237 1915 80 501 + 3237 2422 67 882 + 3904 4810 49 411 + 3904 4510 37 378 + 4290 1550 91 411 + 4290 4818 83 666 + 342 1436 72 656 + 342 1545 87 221 + 342 3166 53 130 + 697 3338 2 656 + 697 4442 12 978 + 697 4362 3 13 + 1436 1855 90 656 + 1436 3191 76 715 + 1855 697 28 656 + 1855 4616 75 656 + 1855 1040 51 165 + 1855 1810 96 554 + 2056 3256 36 656 + 2056 152 91 769 + 3256 4765 82 656 + 3256 4453 6 654 + 3338 2056 97 656 + 3338 4626 84 939 + 343 2623 19 453 + 343 4213 58 971 + 343 623 24 867 + 1164 4052 71 453 + 1164 1678 61 143 + 1164 4802 68 194 + 1809 1164 88 453 + 1809 1242 88 568 + 1809 3193 90 453 + 1929 1809 52 453 + 1929 4534 97 864 + 1929 4495 39 543 + 2623 1929 35 453 + 2623 4574 65 453 + 2623 4652 75 525 + 2623 4789 55 144 + 3655 4277 20 453 + 3655 813 79 914 + 3655 2676 41 446 + 4052 4201 63 453 + 4052 1747 5 345 + 4052 2436 10 992 + 4201 3655 100 453 + 4201 2178 22 326 + 4201 3974 49 987 + 4277 4614 97 453 + 4277 1703 82 731 + 4277 1775 91 733 + 344 1909 59 327 + 344 154 60 81 + 886 4956 56 327 + 886 4887 88 327 + 886 4579 2 740 + 1454 2014 80 327 + 1454 4180 90 145 + 1800 1454 15 327 + 1800 2170 16 400 + 1800 1536 41 214 + 1909 4466 87 327 + 1909 2110 51 634 + 2014 3950 46 327 + 2014 3710 95 794 + 3516 886 81 327 + 3516 396 55 647 + 3516 442 13 179 + 3829 3516 94 327 + 3829 26 11 392 + 3829 657 2 243 + 3950 3829 18 327 + 3950 2647 33 444 + 3950 4433 54 640 + 4466 1800 28 327 + 4466 4859 85 999 + 4466 1114 45 111 + 345 1267 97 729 + 345 4640 100 944 + 925 4794 73 729 + 925 873 76 332 + 1267 2106 24 729 + 1267 3276 64 342 + 1267 29 55 837 + 1365 2558 16 729 + 1365 825 30 766 + 1541 925 29 729 + 1541 4789 73 729 + 1541 2175 8 2 + 1541 1142 85 78 + 2106 3254 67 729 + 2106 1665 21 629 + 2106 2048 5 810 + 2558 1541 79 729 + 2558 3766 17 736 + 2558 4867 67 154 + 3254 1365 54 729 + 3254 3099 69 909 + 346 4326 36 265 + 346 3471 100 922 + 1066 4999 8 265 + 1066 4918 88 683 + 1942 2724 6 265 + 1942 926 91 884 + 2438 3504 97 265 + 2438 2630 70 265 + 2438 2604 62 268 + 2724 2438 35 265 + 2724 2647 35 315 + 2856 3859 54 265 + 2856 4898 29 265 + 2856 2881 13 422 + 2856 4721 43 83 + 3504 2856 22 265 + 3504 784 12 803 + 3504 1962 30 348 + 3859 1066 24 265 + 3859 2158 45 905 + 3859 4927 16 661 + 4326 1942 70 265 + 4326 4244 8 808 + 4326 2038 24 858 + 347 691 54 663 + 347 2933 24 303 + 347 4336 81 314 + 691 1672 34 663 + 691 1848 68 187 + 691 154 74 302 + 760 1562 21 663 + 760 2586 89 554 + 1434 3363 49 663 + 1434 1776 53 712 + 1434 4747 69 868 + 1562 4700 56 663 + 1562 4952 18 663 + 1562 3625 44 893 + 1562 4263 48 386 + 1672 3617 17 663 + 1672 2691 93 480 + 1672 1448 45 264 + 1732 1434 47 663 + 1732 594 55 835 + 3363 3537 94 663 + 3363 551 38 342 + 3363 183 57 976 + 3537 760 7 663 + 3537 12 30 98 + 3537 1729 80 390 + 3617 1732 98 663 + 3617 1764 8 227 + 348 687 78 968 + 348 219 95 898 + 348 712 37 10 + 687 3709 83 968 + 687 1827 14 892 + 687 2231 48 110 + 959 3235 49 968 + 959 3231 77 511 + 959 1684 68 673 + 962 3429 23 968 + 962 2368 85 75 + 1119 1415 37 968 + 1119 2891 57 38 + 1119 1208 40 716 + 1143 959 2 968 + 1143 3383 98 980 + 1143 1405 16 163 + 1415 3995 43 968 + 1415 4995 97 968 + 1415 4472 97 184 + 2042 1119 97 968 + 2042 4793 21 968 + 2042 1545 33 33 + 2042 625 95 873 + 3235 962 100 968 + 3235 4404 31 524 + 3429 4557 29 968 + 3429 2178 50 534 + 3429 557 42 69 + 3709 3822 35 968 + 3709 3257 49 412 + 3822 2042 19 968 + 3822 1842 4 577 + 3822 3432 62 394 + 3995 1143 71 968 + 3995 4684 67 131 + 3995 1438 98 282 + 349 3192 93 246 + 349 36 41 516 + 2221 2887 39 246 + 2221 4735 76 89 + 2221 407 89 118 + 2703 4626 91 246 + 2703 4098 32 976 + 2703 50 2 153 + 2887 3685 58 246 + 2887 1954 53 46 + 2887 528 20 419 + 3142 2221 57 246 + 3142 4629 29 246 + 3142 3790 57 33 + 3142 3968 11 510 + 3192 3142 54 246 + 3192 3793 94 589 + 3685 2703 7 246 + 3685 3728 44 477 + 350 1737 62 250 + 350 2076 56 883 + 350 966 24 26 + 1035 2557 26 250 + 1035 4554 25 250 + 1035 1108 2 883 + 1737 1964 85 250 + 1737 779 91 833 + 1737 1841 41 308 + 1964 3543 62 250 + 1964 1374 60 311 + 1964 3415 2 629 + 2247 2676 42 250 + 2247 1325 8 144 + 2247 3232 5 720 + 2541 3673 78 250 + 2541 4151 6 181 + 2557 4963 82 250 + 2557 4267 36 543 + 2676 3101 10 250 + 2676 15 2 160 + 2676 518 33 386 + 3101 1035 10 250 + 3101 512 39 329 + 3273 2247 78 250 + 3273 493 5 180 + 3543 2541 98 250 + 3543 2081 57 405 + 3673 3273 29 250 + 3673 4491 49 643 + 3673 944 93 15 + 351 582 76 144 + 351 4378 70 566 + 351 4262 3 876 + 582 2435 31 144 + 582 1907 81 199 + 635 1356 87 144 + 635 3247 60 524 + 635 1975 61 361 + 651 3173 25 144 + 651 3837 63 86 + 651 4015 99 879 + 1356 3480 41 144 + 1356 486 33 72 + 1356 4674 61 759 + 2435 651 2 144 + 2435 369 7 48 + 2435 3642 15 419 + 2698 635 45 144 + 2698 4788 70 144 + 2698 2327 90 531 + 2698 101 22 433 + 3173 2698 30 144 + 3173 3110 12 267 + 3173 4298 32 556 + 3480 4805 10 144 + 3480 367 31 984 + 352 2223 94 189 + 352 2006 27 841 + 709 4600 33 189 + 709 2171 47 803 + 1976 4088 38 189 + 1976 1574 86 507 + 1976 1270 92 74 + 2223 4199 14 189 + 2223 981 85 768 + 2223 1609 95 391 + 2289 4840 27 189 + 2289 709 35 189 + 2289 1902 25 711 + 2289 2273 30 483 + 4088 2289 65 189 + 4088 1374 99 919 + 4088 4691 99 632 + 4199 1976 92 189 + 4199 3882 59 591 + 4199 4969 72 520 + 353 835 27 713 + 353 3652 25 882 + 835 4362 48 713 + 835 4127 96 355 + 898 1343 79 713 + 898 4542 56 685 + 898 4661 27 236 + 1343 4401 2 713 + 1343 2007 2 236 + 4362 898 6 713 + 4362 4069 94 174 + 4401 4601 22 713 + 4401 4637 11 713 + 4401 2825 34 995 + 354 1646 96 317 + 354 789 37 471 + 354 2060 48 577 + 792 1526 67 317 + 792 3412 31 164 + 792 1117 84 929 + 850 792 95 317 + 850 1153 39 210 + 1526 4513 9 317 + 1526 1330 75 146 + 1526 495 47 591 + 1646 2600 58 317 + 1646 255 68 1000 + 1646 2947 86 399 + 2600 2866 74 317 + 2600 1630 27 244 + 2600 2420 54 978 + 2866 3898 90 317 + 2866 4397 13 19 + 2866 4966 88 133 + 3898 850 17 317 + 3898 4570 10 317 + 3898 3033 50 386 + 3898 2722 58 893 + 355 1306 24 439 + 355 2183 51 909 + 355 4811 95 813 + 531 2874 21 439 + 531 979 65 661 + 1306 3557 63 439 + 1306 4318 58 576 + 1306 535 93 487 + 1355 2618 92 439 + 1355 4272 20 479 + 1355 3155 93 774 + 2618 4416 57 439 + 2618 4807 98 439 + 2618 3151 51 650 + 2874 1355 75 439 + 2874 4171 99 810 + 2874 2002 99 899 + 3557 531 97 439 + 3557 4761 66 227 + 3557 4109 4 285 + 4416 4542 6 439 + 4416 3569 64 599 + 4416 4118 22 94 + 356 936 9 404 + 356 1174 64 848 + 356 358 99 503 + 936 1850 20 404 + 936 4609 55 512 + 936 234 88 914 + 1390 3713 96 404 + 1390 3664 4 208 + 1390 1957 75 354 + 1850 3042 33 404 + 1850 1174 77 851 + 3042 1390 53 404 + 3042 4214 82 250 + 3042 590 14 843 + 3713 3800 73 404 + 3713 4824 66 404 + 3713 213 25 740 + 3800 4848 83 404 + 3800 2918 42 283 + 3800 3456 69 761 + 357 1655 97 937 + 357 1902 1 81 + 357 93 86 451 + 737 836 7 937 + 737 3022 23 188 + 836 1630 63 937 + 836 2642 78 179 + 836 147 79 291 + 1281 3754 11 937 + 1281 4867 27 51 + 1281 638 79 456 + 1339 4517 58 937 + 1339 3140 80 960 + 1339 1232 19 876 + 1630 4061 80 937 + 1630 4978 56 992 + 1655 1281 69 937 + 1655 4634 96 937 + 1655 431 3 729 + 1802 737 99 937 + 1802 2842 1 440 + 3754 1802 51 937 + 3754 3111 28 89 + 3754 1084 68 261 + 4061 1339 25 937 + 4061 3273 98 639 + 4061 2800 100 856 + 358 1417 35 218 + 358 3667 46 531 + 358 4882 28 242 + 1417 4210 84 218 + 1417 4629 84 218 + 1417 2373 83 493 + 3394 3979 55 218 + 3394 445 87 258 + 3394 858 100 218 + 3632 3866 89 218 + 3632 3505 57 936 + 3632 3229 79 246 + 3866 4053 8 218 + 3866 733 44 916 + 3866 202 85 209 + 3979 4597 21 218 + 3979 903 56 765 + 3979 98 56 284 + 4053 3394 17 218 + 4053 3418 71 632 + 4053 4065 45 682 + 4210 4241 15 218 + 4210 1320 80 792 + 4210 1040 99 623 + 4241 3632 70 218 + 4241 2023 61 280 + 4241 1910 22 629 + 359 2797 95 803 + 359 4335 44 982 + 359 3080 39 943 + 1748 4951 4 803 + 1748 1484 70 437 + 2041 4494 80 803 + 2041 4194 12 856 + 2797 3969 16 803 + 2797 1085 77 51 + 2797 1411 60 464 + 3483 4898 86 803 + 3483 1748 85 803 + 3483 163 26 741 + 3483 3024 49 923 + 3969 2041 25 803 + 3969 4263 52 616 + 4494 3483 14 803 + 4494 4326 5 348 + 4494 784 43 767 + 360 2658 72 333 + 360 1900 68 122 + 1103 1594 46 333 + 1103 3560 52 338 + 1594 4700 10 333 + 1594 3387 75 671 + 1594 4390 98 607 + 2266 4913 23 333 + 2266 1103 47 333 + 2266 761 65 210 + 2266 3704 58 45 + 2658 3336 72 333 + 2658 2459 87 762 + 3183 2266 76 333 + 3183 1421 44 18 + 3183 4819 68 190 + 3336 3183 26 333 + 3336 1437 37 351 + 3336 1855 19 841 + 361 1231 38 215 + 361 1161 5 403 + 361 914 77 715 + 534 3790 59 215 + 534 1441 80 982 + 534 2904 14 450 + 1231 2212 65 215 + 1231 4795 67 215 + 1231 3495 71 907 + 1231 2986 28 637 + 1523 534 23 215 + 1523 2883 25 477 + 1523 2072 55 582 + 1605 1523 18 215 + 1605 2349 27 668 + 1605 4272 63 150 + 2212 3571 34 215 + 2212 673 64 334 + 3571 1605 40 215 + 3571 3523 98 947 + 3790 4855 37 215 + 3790 4355 14 168 + 362 4209 13 217 + 362 2727 71 289 + 362 4696 41 759 + 1096 3340 48 217 + 1096 217 71 959 + 1096 1382 41 618 + 1531 4815 58 217 + 1531 2506 70 298 + 1531 1856 83 878 + 1758 1096 79 217 + 1758 1076 68 36 + 3340 4221 86 217 + 3340 2707 45 557 + 3340 2677 37 947 + 4209 1758 95 217 + 4209 2264 43 139 + 4209 4419 50 357 + 4221 1531 84 217 + 4221 4783 49 217 + 4221 2417 37 5 + 363 1448 51 757 + 363 4112 33 623 + 363 3321 45 463 + 538 3929 43 757 + 538 2771 89 878 + 538 1054 8 50 + 705 3295 26 757 + 705 4065 22 176 + 1448 2408 73 757 + 1448 214 84 92 + 1448 2588 24 76 + 2028 2422 50 757 + 2028 4978 13 76 + 2408 3459 2 757 + 2408 1788 68 923 + 2408 523 83 865 + 2422 4882 59 757 + 2422 2458 47 193 + 2864 538 3 757 + 2864 2557 12 713 + 3295 2864 96 757 + 3295 1448 22 113 + 3295 2742 59 596 + 3459 705 72 757 + 3459 4961 73 757 + 3459 859 52 961 + 3459 4099 91 703 + 3929 2028 73 757 + 3929 911 72 806 + 3929 2667 13 410 + 364 644 39 437 + 364 2131 9 511 + 571 965 64 437 + 571 3548 38 123 + 571 1116 46 876 + 644 1150 100 437 + 644 1649 9 968 + 644 4205 6 131 + 700 4548 14 437 + 700 1122 68 527 + 965 4535 95 437 + 965 1070 5 437 + 965 4662 37 437 + 965 2299 44 309 + 1070 3395 49 437 + 1070 908 76 863 + 1070 3670 2 892 + 1150 1882 21 437 + 1150 1053 90 551 + 1150 2291 26 811 + 1423 3104 39 437 + 1423 4854 94 54 + 1423 3225 51 338 + 1882 1423 96 437 + 1882 2076 54 585 + 2854 571 2 437 + 2854 4848 70 400 + 2854 362 47 84 + 2991 4028 84 437 + 2991 978 13 244 + 3104 2854 58 437 + 3104 2588 91 113 + 3104 2082 38 520 + 3353 700 26 437 + 3353 312 92 730 + 3395 2991 92 437 + 3395 3342 67 329 + 4028 3353 22 437 + 4028 4421 61 147 + 365 3103 98 888 + 365 3950 98 890 + 365 1103 7 508 + 1481 1495 46 888 + 1481 1367 76 915 + 1495 3444 86 888 + 1495 4025 68 953 + 3103 3390 82 888 + 3103 2339 49 21 + 3390 4324 37 888 + 3390 4454 45 298 + 3390 4584 80 487 + 3444 4886 53 888 + 3444 432 1 30 + 3444 3725 6 55 + 3869 1481 95 888 + 3869 4965 49 888 + 3869 1677 10 874 + 4324 3869 29 888 + 4324 3583 41 943 + 4324 4265 47 90 + 366 2997 75 318 + 366 1927 56 281 + 686 1651 51 318 + 686 4713 47 135 + 1556 4746 63 318 + 1556 3180 51 318 + 1556 299 17 457 + 1556 2877 30 828 + 1651 4920 8 318 + 1651 4019 17 187 + 1651 4865 61 946 + 2481 1556 22 318 + 2481 2225 71 410 + 2481 4087 1 85 + 2997 2481 65 318 + 2997 4506 16 328 + 3120 4171 55 318 + 3120 4564 37 383 + 3120 590 30 97 + 3180 3871 91 318 + 3180 2875 55 984 + 3871 3120 7 318 + 3871 2367 18 907 + 3871 2532 80 645 + 4171 686 75 318 + 4171 3886 55 866 + 4171 1118 64 281 + 367 1826 39 104 + 367 3744 23 483 + 776 3773 87 104 + 776 2619 65 685 + 776 4924 42 643 + 1172 2251 28 104 + 1172 2428 87 980 + 1172 1267 31 982 + 1387 776 39 104 + 1387 1421 34 848 + 1387 1968 77 464 + 1826 2018 9 104 + 1826 2752 57 197 + 2018 1172 78 104 + 2018 4940 6 947 + 2251 3014 80 104 + 2251 3482 35 265 + 2269 2456 96 104 + 2269 1544 47 328 + 2456 2953 29 104 + 2456 4721 61 104 + 2456 2198 24 488 + 2953 4861 80 104 + 2953 4838 29 104 + 2953 1373 26 677 + 2953 4629 85 330 + 3014 1387 86 104 + 3014 1078 76 245 + 3126 2269 58 104 + 3126 327 61 788 + 3126 815 58 920 + 3773 3126 30 104 + 3773 4657 2 370 + 3773 3786 62 996 + 368 1406 9 358 + 368 3565 66 772 + 368 4802 42 875 + 1406 1586 18 358 + 1406 3908 49 466 + 1406 1413 98 463 + 1586 2565 64 358 + 1586 482 19 240 + 1586 498 70 99 + 1985 4729 68 358 + 1985 445 46 580 + 2338 4837 3 358 + 2338 2582 33 358 + 2338 3834 73 440 + 2565 2338 74 358 + 2565 133 96 590 + 2582 3396 58 358 + 2582 2325 82 705 + 2582 4556 25 722 + 3396 1985 88 358 + 3396 4969 82 184 + 3396 1466 45 768 + 369 3470 22 451 + 369 198 40 175 + 594 4064 99 451 + 594 1830 10 335 + 1120 2377 14 451 + 1120 4833 51 632 + 1151 2496 83 451 + 1151 2864 67 385 + 1151 1037 72 764 + 1158 1151 29 451 + 1158 2829 95 653 + 1158 2619 55 133 + 1649 2718 73 451 + 1649 4672 88 451 + 1649 2267 59 944 + 2256 1158 62 451 + 2256 89 27 837 + 2256 3364 42 853 + 2377 1649 100 451 + 2377 3979 36 516 + 2377 268 78 111 + 2496 594 66 451 + 2496 2470 97 879 + 2496 2086 35 749 + 2718 2256 38 451 + 2718 2506 84 740 + 3222 4797 6 451 + 3222 1123 10 78 + 3222 2853 94 233 + 3470 4940 30 451 + 3470 1120 77 451 + 3470 1551 14 70 + 3470 512 86 703 + 4064 3222 93 451 + 4064 3363 66 404 + 370 840 14 451 + 370 852 52 705 + 840 3163 14 451 + 840 4131 79 369 + 991 4558 6 451 + 991 4982 57 451 + 991 2052 35 416 + 1783 991 46 451 + 1783 2864 17 212 + 2722 1783 81 451 + 2722 2794 38 154 + 2722 4072 5 625 + 3163 3793 95 451 + 3163 2466 70 314 + 3793 4379 32 451 + 3793 1937 84 88 + 4379 2722 30 451 + 4379 3459 63 842 + 371 3457 93 135 + 371 4349 35 867 + 371 1497 82 755 + 1058 2043 76 135 + 1058 4446 24 720 + 1058 2513 3 694 + 1230 1058 69 135 + 1230 3774 59 24 + 1230 912 17 496 + 1420 1465 21 135 + 1420 4132 41 844 + 1465 4436 95 135 + 1465 1444 38 142 + 2043 2302 23 135 + 2043 2736 5 348 + 2043 2263 5 484 + 2302 4581 41 135 + 2302 3351 28 403 + 3457 1420 48 135 + 3457 4144 3 724 + 3457 960 47 692 + 4436 1230 97 135 + 4436 4851 93 135 + 4436 42 41 474 + 4436 3792 15 605 + 372 3680 2 753 + 372 1770 68 642 + 372 580 22 486 + 778 2154 85 753 + 778 4587 54 904 + 2154 2675 92 753 + 2154 4600 7 906 + 2675 4380 75 753 + 2675 4977 29 512 + 2730 4981 32 753 + 2730 1120 1 739 + 3680 778 73 753 + 3680 4694 7 753 + 3680 2199 26 813 + 3972 2730 63 753 + 3972 3167 15 550 + 4380 3972 92 753 + 4380 711 39 934 + 4380 3980 93 803 + 373 3691 62 273 + 373 2713 16 458 + 373 1781 78 658 + 1050 4981 75 273 + 1050 2416 71 273 + 1050 4132 23 485 + 1050 503 93 862 + 1382 4911 30 273 + 1382 3533 6 312 + 1382 4485 13 774 + 1652 3787 90 273 + 1652 496 31 189 + 1652 2648 55 470 + 2013 3595 74 273 + 2013 4801 32 102 + 2416 1382 42 273 + 2416 1183 29 878 + 2416 333 95 329 + 3595 4125 76 273 + 3595 2259 54 631 + 3595 2764 80 775 + 3691 4014 61 273 + 3691 3660 41 346 + 3787 4349 88 273 + 3787 603 68 732 + 3787 4347 94 164 + 4014 2013 43 273 + 4014 4877 24 207 + 4125 1652 35 273 + 4125 4778 10 426 + 4349 1050 4 273 + 4349 394 16 55 + 374 1782 16 22 + 374 1534 99 734 + 374 2856 24 967 + 532 676 38 22 + 532 2702 78 957 + 676 4071 73 22 + 676 284 40 321 + 1782 3227 22 22 + 1782 1049 97 538 + 1904 4741 47 22 + 1904 532 63 22 + 1904 4079 43 604 + 2137 1904 9 22 + 2137 3482 36 212 + 2774 2137 17 22 + 2774 1186 50 72 + 2774 84 64 521 + 3227 3392 8 22 + 3227 3503 20 685 + 3227 242 48 593 + 3392 3708 84 22 + 3392 4490 28 831 + 3392 1008 95 344 + 3708 2774 21 22 + 3708 4830 39 813 + 3708 1607 65 468 + 4071 4987 97 22 + 4071 232 68 986 + 4071 842 78 510 + 375 510 90 284 + 375 3764 16 245 + 375 1704 61 616 + 510 3077 75 284 + 510 3005 44 606 + 510 1190 19 953 + 602 4077 52 284 + 602 3994 70 719 + 602 2434 59 451 + 927 4054 24 284 + 927 1722 38 849 + 927 3202 93 730 + 2060 2507 26 284 + 2060 4268 75 493 + 2060 754 37 324 + 2183 602 68 284 + 2183 1477 56 656 + 2183 851 76 298 + 2507 4733 92 284 + 2507 4529 30 284 + 2507 3338 27 946 + 2507 1004 55 184 + 3077 4310 98 284 + 3077 4731 6 175 + 4054 2060 63 284 + 4054 3894 90 271 + 4054 645 18 363 + 4077 927 53 284 + 4077 935 71 670 + 4077 2811 54 694 + 4310 2183 15 284 + 4310 3321 98 390 + 4310 619 45 829 + 376 2150 71 15 + 376 4556 24 657 + 376 4303 100 416 + 798 1004 73 15 + 798 640 30 195 + 824 1340 24 15 + 824 2399 81 663 + 1004 2913 62 15 + 1004 3267 2 303 + 1004 4201 17 122 + 1243 824 52 15 + 1243 255 4 9 + 1340 798 86 15 + 1340 760 97 401 + 1922 2572 86 15 + 1922 4962 22 15 + 1922 418 71 247 + 2150 1243 71 15 + 2150 3295 11 370 + 2572 4710 40 15 + 2572 2710 29 283 + 2572 863 100 923 + 2913 1922 38 15 + 2913 4582 74 833 + 2913 1635 100 245 + 377 4320 74 1020 + 377 4370 81 803 + 796 4169 9 1020 + 796 1283 7 797 + 796 3285 51 552 + 1065 3385 73 1020 + 1065 4467 80 927 + 1443 4983 11 1020 + 1443 3640 69 22 + 3385 796 71 1020 + 3385 3081 59 350 + 3385 272 25 451 + 4169 1443 5 1020 + 4169 2497 52 155 + 4169 3519 1 717 + 4320 1065 73 1020 + 4320 4544 33 1020 + 4320 574 70 242 + 4320 1573 41 81 + 378 1901 43 326 + 378 379 73 844 + 378 1798 5 597 + 924 1724 40 326 + 924 1445 99 159 + 924 2550 54 979 + 1724 3348 57 326 + 1724 3203 86 263 + 1724 1593 86 523 + 1901 3935 47 326 + 1901 3508 62 703 + 2010 2460 39 326 + 2010 4835 59 326 + 2010 4282 43 272 + 2460 3354 48 326 + 2460 3093 37 657 + 3348 4250 83 326 + 3348 819 43 875 + 3348 1573 67 99 + 3354 924 1 326 + 3354 1690 37 919 + 3354 4629 87 918 + 3935 2010 74 326 + 3935 3751 87 903 + 4250 4803 28 326 + 4250 2248 93 708 + 379 569 46 436 + 379 4819 47 463 + 379 807 67 459 + 569 2332 10 436 + 569 1716 54 219 + 1518 2886 52 436 + 1518 1011 60 125 + 1518 3261 1 54 + 1684 4236 88 436 + 1684 4964 36 70 + 2332 4373 9 436 + 2332 4675 37 436 + 2332 2709 39 668 + 2886 3704 17 436 + 2886 4248 20 305 + 2886 2146 50 360 + 3601 1518 33 436 + 3601 164 49 256 + 3601 4700 4 706 + 3704 4653 58 436 + 3704 2995 94 952 + 3704 4374 26 368 + 3714 3601 57 436 + 3714 2889 50 25 + 4236 3714 48 436 + 4236 2590 84 349 + 4373 1684 7 436 + 4373 32 57 435 + 4373 1333 76 814 + 380 2563 41 360 + 380 2761 12 159 + 677 3196 6 360 + 677 1448 14 906 + 1192 4120 26 360 + 1192 730 97 390 + 1577 677 83 360 + 1577 29 50 517 + 1577 4902 50 183 + 2563 1577 28 360 + 2563 3743 51 205 + 2563 3182 19 824 + 3196 1192 100 360 + 3196 4693 20 360 + 3196 4500 75 649 + 3196 389 86 557 + 4120 4564 33 360 + 4120 3762 83 638 + 4120 3526 20 516 + 381 4325 82 389 + 381 3303 1 726 + 2100 3923 15 389 + 2100 3153 77 210 + 2100 959 75 718 + 3073 2100 61 389 + 3073 4771 85 389 + 3073 1952 25 908 + 3536 4167 12 389 + 3536 1210 43 689 + 3603 3073 52 389 + 3603 330 46 128 + 3923 4609 83 389 + 3923 4181 92 5 + 4167 3603 72 389 + 4167 1300 80 989 + 4325 3536 76 389 + 4325 873 64 22 + 382 2344 42 949 + 382 1912 9 996 + 382 994 88 659 + 889 4544 2 949 + 889 4643 94 949 + 889 3987 39 907 + 909 2590 34 949 + 909 4455 23 760 + 1658 909 13 949 + 1658 1123 99 702 + 1658 3303 31 39 + 1680 1719 12 949 + 1680 562 55 605 + 1680 1692 54 181 + 1719 1778 89 949 + 1719 2586 39 629 + 1778 889 4 949 + 1778 632 6 406 + 2344 1658 21 949 + 2344 357 43 557 + 2344 719 13 451 + 2590 1680 62 949 + 2590 326 60 366 + 2590 3482 55 792 + 383 2979 74 311 + 383 625 71 780 + 383 968 98 679 + 1005 3137 40 311 + 1005 903 35 406 + 1255 4582 62 311 + 1255 1421 57 450 + 2352 3939 44 311 + 2352 2844 98 153 + 2483 4631 84 311 + 2483 2352 88 311 + 2483 584 27 242 + 2979 3032 79 311 + 2979 5000 1 649 + 2979 3402 49 609 + 3032 3215 10 311 + 3032 1105 78 387 + 3032 2354 99 989 + 3137 1255 19 311 + 3137 2328 96 917 + 3137 1037 92 964 + 3215 2483 39 311 + 3215 2723 38 435 + 3939 1005 17 311 + 3939 3280 45 30 + 3939 2025 72 89 + 384 3431 21 990 + 384 3698 23 489 + 384 4140 46 248 + 1278 3832 62 990 + 1278 1690 82 782 + 1422 4323 19 990 + 1422 295 78 266 + 1422 4784 4 556 + 3138 4830 52 990 + 3138 4968 30 990 + 3138 1076 34 499 + 3138 603 55 984 + 3147 3546 98 990 + 3147 3929 43 441 + 3147 4561 82 17 + 3431 3147 57 990 + 3431 2469 32 430 + 3431 2935 37 28 + 3546 3728 91 990 + 3546 2669 76 143 + 3728 1278 87 990 + 3728 4164 1 29 + 3832 1422 84 990 + 3832 2405 90 950 + 3832 1764 97 491 + 4323 3138 87 990 + 4323 2087 78 981 + 385 1279 41 75 + 385 869 38 962 + 1279 4333 93 75 + 1279 1742 10 258 + 2779 3290 6 75 + 2779 2393 77 90 + 2779 4930 98 427 + 3290 3917 52 75 + 3290 3154 71 582 + 3461 4497 96 75 + 3461 1103 23 462 + 3461 2757 57 487 + 3917 4451 26 75 + 3917 3797 88 584 + 3917 4912 47 69 + 4333 2779 14 75 + 4333 1628 17 850 + 4451 3461 54 75 + 4451 4780 71 75 + 4451 2610 67 223 + 4451 4718 84 469 + 4497 4610 5 75 + 4497 712 26 972 + 4497 3213 64 901 + 386 649 73 563 + 386 734 9 58 + 649 1711 35 563 + 649 561 46 39 + 1003 1492 73 563 + 1003 2423 68 824 + 1152 2578 12 563 + 1152 4780 98 563 + 1152 3704 71 976 + 1152 2249 74 261 + 1492 2526 38 563 + 1492 207 67 573 + 1492 3608 33 46 + 1711 1971 84 563 + 1711 796 72 404 + 1971 2959 59 563 + 1971 1230 17 351 + 2526 1152 5 563 + 2526 4873 74 629 + 2578 4556 46 563 + 2578 373 80 83 + 2578 75 66 408 + 2959 3178 40 563 + 2959 2915 65 878 + 3164 1003 100 563 + 3164 4282 17 857 + 3178 3164 82 563 + 3178 2449 88 546 + 387 2850 33 481 + 387 264 48 31 + 711 4510 57 481 + 711 2174 31 822 + 711 2141 39 462 + 1554 711 5 481 + 1554 898 22 394 + 1554 2711 91 31 + 1583 3879 41 481 + 1583 2385 90 453 + 2850 4615 62 481 + 2850 4130 11 481 + 2850 1588 29 330 + 2850 2201 45 290 + 3879 1554 22 481 + 3879 1228 28 766 + 3879 1463 82 360 + 4130 1583 7 481 + 4130 3235 43 976 + 388 4056 25 546 + 388 3304 61 512 + 807 1688 22 546 + 807 188 25 897 + 1235 4443 78 546 + 1235 731 8 779 + 1235 1875 3 666 + 1688 4789 51 546 + 1688 2391 63 839 + 1914 1235 63 546 + 1914 3907 84 31 + 2039 807 100 546 + 2039 4454 98 784 + 2521 1914 40 546 + 2521 2488 72 389 + 2521 3175 98 627 + 4056 4207 12 546 + 4056 1926 40 323 + 4207 2521 47 546 + 4207 3001 62 547 + 4225 2039 34 546 + 4225 4527 18 546 + 4225 3417 25 515 + 4443 4225 9 546 + 4443 4150 45 429 + 4443 3293 33 330 + 389 885 19 455 + 389 4326 84 914 + 885 1357 37 455 + 885 3657 57 493 + 1203 4992 57 455 + 1203 2417 75 220 + 1203 515 65 655 + 1357 4603 99 455 + 1357 4460 93 455 + 1357 892 53 724 + 1357 244 74 12 + 2158 3509 43 455 + 2158 532 88 947 + 2158 799 17 194 + 2853 3882 6 455 + 2853 3672 29 167 + 2853 2665 24 989 + 3509 4067 50 455 + 3509 1470 46 71 + 3509 1468 44 44 + 3882 4292 27 455 + 3882 3375 47 67 + 4067 1203 68 455 + 4067 2910 50 908 + 4292 2158 75 455 + 4292 4013 93 74 + 4460 4462 91 455 + 4460 2996 9 752 + 4462 2853 64 455 + 4462 3824 84 711 + 4462 1708 39 859 + 390 4105 59 356 + 390 2400 22 402 + 390 3138 5 780 + 816 2740 100 356 + 816 2979 4 525 + 1048 1677 67 356 + 1048 1261 81 335 + 1048 2265 17 831 + 1549 1048 26 356 + 1549 3993 73 12 + 1677 2380 84 356 + 1677 1085 97 58 + 1677 4156 32 908 + 2380 3441 74 356 + 2380 4315 63 193 + 2740 3730 25 356 + 2740 4961 60 742 + 2740 1262 27 726 + 3441 816 64 356 + 3441 4713 64 567 + 3730 4700 89 356 + 3730 2756 39 585 + 4105 1549 96 356 + 4105 4907 100 356 + 4105 1240 1 591 + 391 1376 38 496 + 391 69 38 533 + 964 4285 78 496 + 964 2500 5 526 + 964 2752 41 553 + 1376 4755 28 496 + 1376 2729 67 496 + 1376 535 58 183 + 1376 988 93 871 + 1916 2640 76 496 + 1916 1559 54 588 + 1916 3804 79 918 + 2151 4937 59 496 + 2151 4931 28 872 + 2500 1916 33 496 + 2500 2561 18 296 + 2500 3110 93 896 + 2640 964 64 496 + 2640 430 53 556 + 2640 226 31 800 + 2729 2500 38 496 + 2729 4623 55 400 + 4285 2151 48 496 + 4285 4598 87 881 + 4285 802 82 730 + 392 4268 57 525 + 392 480 35 16 + 623 797 23 525 + 623 1721 67 47 + 623 375 24 951 + 797 4261 71 525 + 797 4128 37 983 + 1020 4725 1 525 + 1020 2813 88 893 + 1020 2555 92 242 + 1052 623 5 525 + 1052 2768 94 752 + 1052 5 16 606 + 2727 3364 16 525 + 2727 4855 51 525 + 2727 4697 10 85 + 2727 828 35 261 + 3364 3857 91 525 + 3364 1071 63 18 + 3364 2853 73 612 + 3857 1020 47 525 + 3857 3695 56 200 + 4228 1052 100 525 + 4228 653 70 1 + 4261 2727 20 525 + 4261 4466 45 864 + 4268 4228 38 525 + 4268 2592 22 337 + 393 2504 30 682 + 393 4283 32 652 + 1280 4864 1 682 + 1280 2165 85 682 + 1280 308 10 506 + 1280 4202 48 230 + 1289 1280 95 682 + 1289 4837 75 249 + 1289 4142 37 796 + 1452 3439 64 682 + 1452 3231 91 471 + 1452 1521 36 617 + 2165 4191 91 682 + 2165 31 57 483 + 2386 3343 29 682 + 2386 1260 17 808 + 2504 2386 97 682 + 2504 1206 50 176 + 3343 1289 57 682 + 3343 4919 34 32 + 3343 4552 61 135 + 3439 4843 61 682 + 3439 2604 39 393 + 3439 3499 23 887 + 4191 1452 19 682 + 4191 1979 16 173 + 394 2331 14 215 + 394 2618 5 946 + 394 619 31 819 + 527 4558 2 215 + 527 4908 52 215 + 527 2845 76 235 + 953 3151 27 215 + 953 1482 72 949 + 1220 953 74 215 + 1220 3665 12 241 + 1220 2389 8 60 + 2331 1220 3 215 + 2331 769 53 239 + 2331 986 16 404 + 2441 2616 30 215 + 2441 315 1 562 + 2616 3271 65 215 + 2616 4736 20 468 + 2616 1441 100 720 + 3151 2441 42 215 + 3151 3801 74 622 + 3151 1241 34 73 + 3271 527 72 215 + 3271 4457 8 577 + 3271 3227 63 681 + 395 2336 32 632 + 395 598 62 456 + 395 2358 15 857 + 832 1837 35 632 + 832 4076 38 912 + 832 3239 16 27 + 1300 1792 43 632 + 1300 1846 40 180 + 1580 3771 69 632 + 1580 926 36 996 + 1580 2806 47 458 + 1792 3849 6 632 + 1792 1267 65 245 + 1837 1300 3 632 + 1837 4352 85 362 + 1837 1414 14 423 + 2336 1580 63 632 + 2336 3085 35 901 + 3481 832 31 632 + 3481 189 91 209 + 3583 3481 94 632 + 3583 4634 69 771 + 3583 2969 52 943 + 3771 3583 98 632 + 3771 976 90 845 + 3849 4911 21 632 + 3849 4697 48 632 + 3849 1939 34 517 + 396 1360 75 339 + 396 1692 87 499 + 973 4760 33 339 + 973 379 89 566 + 1360 3874 16 339 + 1360 2341 100 405 + 1360 3201 63 992 + 1853 2193 38 339 + 1853 4771 93 550 + 1853 4865 76 133 + 2193 4159 94 339 + 2193 1126 57 32 + 2193 1054 27 55 + 2253 4281 91 339 + 2253 4729 77 155 + 3874 2253 43 339 + 3874 4901 58 339 + 3874 4846 92 790 + 3874 3486 34 108 + 4159 973 33 339 + 4159 4106 48 428 + 4159 3081 77 265 + 4281 1853 46 339 + 4281 1232 36 202 + 4281 4690 46 919 + 397 1323 66 91 + 397 3119 77 45 + 397 3057 73 161 + 1323 3798 46 91 + 1323 4112 60 897 + 1585 2910 86 91 + 1585 341 60 539 + 1585 1105 89 469 + 2553 3547 47 91 + 2553 3022 90 963 + 2829 3468 29 91 + 2829 4765 78 91 + 2829 2982 54 583 + 2910 2829 93 91 + 2910 1201 66 123 + 2910 1817 18 243 + 3468 2553 9 91 + 3468 1383 2 67 + 3547 4784 21 91 + 3547 4507 99 348 + 3547 449 89 489 + 3798 1585 25 91 + 3798 1916 51 739 + 398 755 55 326 + 398 3184 88 482 + 398 4595 78 249 + 528 3552 27 326 + 528 386 96 199 + 755 528 78 326 + 755 4644 33 326 + 755 2791 19 354 + 755 3028 68 348 + 1379 4007 37 326 + 1379 1363 99 488 + 3552 1379 92 326 + 3552 1088 84 140 + 4007 4816 12 326 + 4007 548 60 292 + 4007 128 82 698 + 399 2611 38 8 + 399 832 89 188 + 399 1731 54 191 + 1247 2058 41 8 + 1247 1245 31 602 + 1247 4282 100 368 + 1359 1751 46 8 + 1359 4509 18 8 + 1359 710 48 840 + 1751 3400 79 8 + 1751 348 41 83 + 1751 4477 54 578 + 2058 4987 26 8 + 2058 616 78 879 + 2058 4516 19 583 + 2611 1359 46 8 + 2611 2427 37 56 + 2611 2678 63 460 + 3400 1247 28 8 + 3400 1961 33 39 + 3400 3807 17 296 + 400 922 44 413 + 400 2971 29 483 + 753 3176 37 413 + 753 4849 87 341 + 753 1831 12 52 + 922 1769 53 413 + 922 3604 51 471 + 1769 4338 71 413 + 1769 4946 42 413 + 1769 4436 64 721 + 3176 3696 100 413 + 3176 1857 35 299 + 3176 4607 77 123 + 3324 4761 95 413 + 3324 1012 30 975 + 3696 3324 40 413 + 3696 2864 42 734 + 3696 1379 65 19 + 4338 753 47 413 + 4338 1301 51 174 + 401 1938 92 448 + 401 3173 94 849 + 401 4047 18 566 + 1869 4649 79 448 + 1869 1655 96 189 + 1869 189 32 542 + 1938 1963 5 448 + 1938 3299 51 577 + 1938 3018 37 568 + 1963 3920 62 448 + 1963 2496 81 61 + 2142 4976 11 448 + 2142 3563 15 448 + 2142 4255 25 668 + 2142 3871 77 802 + 3563 3715 24 448 + 3563 4554 60 976 + 3715 1869 56 448 + 3715 2918 100 950 + 3920 2142 51 448 + 3920 1467 86 546 + 402 3171 38 597 + 402 2192 84 882 + 402 3855 69 90 + 2125 2858 79 597 + 2125 3193 32 516 + 2858 4383 46 597 + 2858 918 40 444 + 2858 2765 42 495 + 3171 3868 27 597 + 3171 4145 78 521 + 3868 2125 47 597 + 3868 4675 90 597 + 3868 4806 32 930 + 3868 4054 76 777 + 4383 4956 53 597 + 4383 4792 41 223 + 403 2900 42 854 + 403 546 51 229 + 403 1431 11 459 + 750 4545 55 854 + 750 4841 52 854 + 750 1007 81 958 + 1271 4001 97 854 + 1271 944 99 773 + 1623 3916 15 854 + 1623 936 63 32 + 1623 1364 57 487 + 1949 1623 8 854 + 1949 2706 64 431 + 2627 1949 18 854 + 2627 3645 34 483 + 2900 1271 96 854 + 2900 1270 68 958 + 3916 750 97 854 + 3916 3650 93 102 + 4001 2627 90 854 + 4001 2494 17 683 + 404 1962 35 227 + 404 2090 4 729 + 404 3234 84 559 + 1264 4395 71 227 + 1264 782 68 411 + 1264 1237 46 120 + 1962 2451 12 227 + 1962 4824 59 262 + 1962 1837 32 323 + 2076 4480 78 227 + 2076 3800 1 10 + 2076 2684 40 464 + 2451 2562 86 227 + 2451 4880 84 451 + 2562 1264 75 227 + 2562 3105 48 654 + 2562 1968 43 223 + 3065 4630 23 227 + 3065 194 84 423 + 3065 2165 59 539 + 3204 2076 65 227 + 3204 4412 17 594 + 3204 2492 100 16 + 4395 3204 65 227 + 4395 2480 89 581 + 4480 3065 37 227 + 4480 4972 16 227 + 4480 3924 95 606 + 4480 4499 13 616 + 405 2987 5 337 + 405 201 21 391 + 867 2113 51 337 + 867 1483 99 141 + 867 4932 48 330 + 2113 2707 3 337 + 2113 4403 72 5 + 2707 4965 11 337 + 2707 3591 89 281 + 2707 2775 71 308 + 2926 3195 71 337 + 2926 4510 57 51 + 2926 521 60 908 + 2987 2926 13 337 + 2987 1956 14 528 + 2987 1534 9 865 + 3195 867 13 337 + 3195 4916 3 337 + 3195 3030 15 319 + 406 1023 94 326 + 406 1736 28 13 + 1023 3028 77 326 + 1023 4696 39 326 + 1023 1908 56 200 + 1023 1821 54 766 + 2335 3896 5 326 + 2335 2740 54 946 + 2335 1191 30 272 + 3028 2335 59 326 + 3028 1583 84 22 + 3028 4744 34 528 + 3896 4553 84 326 + 3896 119 83 532 + 407 668 100 402 + 407 768 52 659 + 407 4505 84 935 + 668 2263 78 402 + 668 1020 42 607 + 945 1895 38 402 + 945 4705 51 172 + 1895 3087 13 402 + 1895 2498 38 857 + 1895 3231 26 68 + 2263 945 66 402 + 2263 2304 51 790 + 3087 3720 72 402 + 3087 4919 85 402 + 3087 289 4 891 + 3087 282 98 840 + 3720 4834 50 402 + 3720 2864 58 827 + 3720 3010 68 351 + 408 821 40 212 + 408 393 17 204 + 408 1466 89 501 + 740 4584 18 212 + 740 1541 28 222 + 740 4921 73 516 + 821 3660 59 212 + 821 2543 48 191 + 821 2493 10 149 + 1099 2239 23 212 + 1099 2143 80 459 + 1099 4072 16 677 + 2239 740 27 212 + 2239 2483 94 737 + 3530 4737 11 212 + 3530 1099 72 212 + 3530 4145 67 392 + 3660 3530 97 212 + 3660 3123 30 29 + 409 2839 69 265 + 409 1422 24 255 + 409 1368 40 874 + 536 4797 73 265 + 536 2819 64 547 + 728 3158 27 265 + 728 1432 62 892 + 728 1485 51 69 + 979 536 60 265 + 979 1477 58 148 + 979 1297 30 199 + 1055 2704 23 265 + 1055 1941 90 791 + 1055 618 5 191 + 2704 728 93 265 + 2704 1205 24 396 + 2839 1055 77 265 + 2839 4725 78 265 + 2839 13 83 837 + 2839 4698 18 495 + 3158 979 53 265 + 3158 4392 54 237 + 3158 2442 7 437 + 410 3197 54 415 + 410 2092 88 868 + 533 4811 77 415 + 533 805 54 799 + 533 992 57 221 + 849 2308 22 415 + 849 1054 55 335 + 1313 1456 50 415 + 1313 4687 56 415 + 1313 3569 25 298 + 1313 2378 1 176 + 1368 1313 51 415 + 1368 3322 21 48 + 1456 533 35 415 + 1456 2696 37 690 + 1456 519 89 424 + 2308 3177 93 415 + 2308 4977 81 708 + 2308 771 41 36 + 3177 1368 38 415 + 3177 4992 9 922 + 3177 349 75 59 + 3197 849 34 415 + 3197 2540 26 390 + 411 2250 34 239 + 411 2855 23 732 + 411 16 52 909 + 1232 1924 17 239 + 1232 2643 23 867 + 1429 1232 38 239 + 1429 4253 27 297 + 1429 4628 85 808 + 1924 2200 17 239 + 1924 1451 51 688 + 2168 1429 81 239 + 2168 635 93 648 + 2168 2206 27 342 + 2200 4838 93 239 + 2200 1889 34 341 + 2200 1169 93 85 + 2250 4810 17 239 + 2250 2749 36 239 + 2250 4392 94 422 + 2749 2168 45 239 + 2749 4741 95 377 + 2749 4404 75 620 + 412 1292 60 659 + 412 1801 77 143 + 412 2673 98 976 + 575 2705 38 659 + 575 2685 52 685 + 575 4980 89 662 + 907 4437 55 659 + 907 3897 34 380 + 907 1941 66 342 + 933 1380 33 659 + 933 3075 70 725 + 1217 933 50 659 + 1217 740 14 859 + 1292 907 69 659 + 1292 2586 57 101 + 1364 1217 68 659 + 1364 2406 78 763 + 1380 4895 19 659 + 1380 1798 30 469 + 1380 2935 19 430 + 2705 1364 62 659 + 2705 110 96 55 + 2705 2533 2 68 + 4437 575 6 659 + 4437 4737 24 659 + 4437 4501 10 922 + 4437 1983 45 540 + 413 3347 82 603 + 413 206 62 508 + 876 4640 89 603 + 876 4537 17 603 + 876 2106 61 550 + 876 2609 36 69 + 1635 876 17 603 + 1635 2738 81 181 + 1635 2929 76 703 + 3287 1635 24 603 + 3287 1694 51 220 + 3347 3739 15 603 + 3347 2744 32 508 + 3386 3287 75 603 + 3386 1612 96 869 + 3739 3386 45 603 + 3739 1869 83 680 + 3739 1050 32 660 + 414 3321 78 827 + 414 412 79 737 + 723 2006 58 827 + 723 1890 74 876 + 723 50 63 217 + 2006 3941 59 827 + 2006 209 75 429 + 2006 533 46 311 + 2505 4187 91 827 + 2505 2601 2 671 + 2505 2275 4 436 + 2649 723 68 827 + 2649 2547 74 786 + 3321 2505 59 827 + 3321 4869 58 827 + 3321 2533 65 58 + 3321 226 14 325 + 3941 4902 35 827 + 3941 1221 33 387 + 3941 656 43 694 + 4187 2649 8 827 + 4187 3910 88 688 + 415 4447 15 28 + 415 4347 66 705 + 415 4077 80 532 + 1363 4690 75 28 + 1363 4855 36 98 + 2492 1363 49 28 + 2492 4589 58 800 + 3210 3650 11 28 + 3210 2217 55 88 + 3210 2897 26 85 + 3333 2492 3 28 + 3333 2840 63 882 + 3650 3333 77 28 + 3650 4522 73 580 + 4447 3210 82 28 + 4447 4697 45 28 + 4447 1168 48 716 + 416 1575 33 309 + 416 3415 100 458 + 416 4499 89 882 + 693 4344 59 309 + 693 3800 79 904 + 1059 693 4 309 + 1059 2902 29 988 + 1575 2788 30 309 + 1575 1870 76 683 + 1575 63 50 344 + 1700 4856 90 309 + 1700 389 26 11 + 2788 4295 46 309 + 2788 706 56 42 + 2788 1608 80 868 + 4295 4828 87 309 + 4295 1059 52 309 + 4295 1714 38 63 + 4344 1700 64 309 + 4344 1288 71 268 + 417 828 33 384 + 417 1264 10 421 + 417 527 55 390 + 828 4392 4 384 + 828 3839 14 563 + 828 1551 63 982 + 1664 1873 12 384 + 1664 4746 68 593 + 1664 2159 9 203 + 1873 3094 80 384 + 1873 4611 90 384 + 1873 509 58 358 + 1873 2880 39 371 + 2787 1664 76 384 + 2787 4427 86 77 + 2904 4048 99 384 + 2904 4076 10 666 + 2904 4995 1 898 + 3094 2904 25 384 + 3094 3446 75 725 + 3772 2787 18 384 + 3772 1142 69 504 + 3772 312 30 919 + 4048 4906 68 384 + 4048 3177 20 877 + 4392 3772 94 384 + 4392 1233 46 485 + 418 2087 20 115 + 418 1212 64 356 + 618 1304 22 115 + 618 2146 98 633 + 642 4757 49 115 + 642 331 6 262 + 1200 618 42 115 + 1200 1111 58 764 + 1211 1900 10 115 + 1211 3669 60 669 + 1304 1211 19 115 + 1304 1377 17 935 + 1304 1508 93 57 + 1900 642 60 115 + 1900 2940 40 259 + 2087 2968 30 115 + 2087 4182 75 242 + 2968 1200 55 115 + 2968 4719 7 115 + 2968 3512 58 894 + 2968 2553 67 636 + 419 4050 58 386 + 419 4171 18 29 + 1194 2516 6 386 + 1194 1033 20 649 + 1263 1194 38 386 + 1263 1564 31 844 + 1263 1745 82 444 + 1324 2975 26 386 + 1324 1628 28 228 + 1324 3326 75 692 + 2516 3119 23 386 + 2516 1529 12 523 + 2516 3231 3 908 + 2951 4994 92 386 + 2951 1263 29 386 + 2951 313 65 822 + 2975 2951 34 386 + 2975 4927 1 982 + 3119 4619 56 386 + 3119 2982 57 774 + 3119 2334 47 827 + 4050 1324 34 386 + 4050 3856 57 246 + 420 805 82 342 + 420 3945 48 664 + 805 3991 86 342 + 805 1198 93 391 + 805 1093 76 265 + 1056 2277 70 342 + 1056 611 24 677 + 1056 1179 1 503 + 1366 2011 8 342 + 1366 3687 81 491 + 1366 467 10 332 + 2011 4851 91 342 + 2011 1056 94 342 + 2011 1565 56 655 + 2277 3943 18 342 + 2277 565 12 314 + 3943 4753 80 342 + 3943 2199 53 546 + 3991 1366 76 342 + 3991 4172 89 667 + 3991 4264 28 954 + 421 1063 74 523 + 421 4589 73 933 + 606 1302 96 523 + 606 3904 98 789 + 1063 2746 57 523 + 1063 522 94 274 + 1302 4570 17 523 + 1302 1370 16 523 + 1302 1038 25 324 + 1370 4408 55 523 + 1370 1890 2 604 + 2322 606 64 523 + 2322 761 53 11 + 2746 3654 45 523 + 2746 4433 10 952 + 2746 2508 24 131 + 3654 2322 76 523 + 3654 2504 8 228 + 4408 4565 21 523 + 4408 887 89 683 + 422 2476 68 309 + 422 318 56 149 + 1273 4200 12 309 + 1273 537 43 291 + 1411 2062 14 309 + 1411 3918 60 596 + 1411 4720 72 960 + 1866 4803 37 309 + 1866 4141 36 711 + 1866 3677 86 752 + 1903 4502 36 309 + 1903 4166 80 309 + 1903 308 13 974 + 1903 3450 67 613 + 2062 1866 50 309 + 2062 2119 31 375 + 2476 1273 22 309 + 2476 2697 81 125 + 3299 1903 76 309 + 3299 19 42 974 + 3299 4445 85 488 + 4166 1411 99 309 + 4166 42 19 618 + 4166 210 72 561 + 4200 3299 55 309 + 4200 196 44 742 + 4200 1940 97 524 + 423 1392 45 204 + 423 2126 67 347 + 423 2610 48 815 + 960 3781 65 204 + 960 4928 49 110 + 1392 2241 48 204 + 1392 1061 1 32 + 2241 3980 12 204 + 2241 376 84 807 + 2241 3984 30 552 + 3047 4546 51 204 + 3047 4535 90 176 + 3781 3047 78 204 + 3781 4796 36 204 + 3781 3178 41 395 + 3781 1563 95 617 + 3980 960 40 204 + 3980 3379 99 163 + 424 1908 38 264 + 424 1245 27 774 + 666 4535 74 264 + 666 3489 5 335 + 666 1423 10 855 + 1490 4021 29 264 + 1490 799 13 813 + 1490 713 27 301 + 1798 666 28 264 + 1798 2610 71 774 + 1908 1490 100 264 + 1908 1266 14 577 + 1908 3556 31 854 + 4021 1798 41 264 + 4021 4626 15 264 + 4021 4221 23 778 + 425 742 79 632 + 425 283 92 794 + 610 3427 69 632 + 610 2266 78 496 + 610 4716 53 474 + 742 1898 78 632 + 742 2133 26 278 + 742 975 88 640 + 1303 2901 48 632 + 1303 185 6 944 + 1303 902 20 550 + 1898 4238 43 632 + 1898 4634 87 632 + 1898 1825 92 951 + 2827 2941 87 632 + 2827 3296 33 57 + 2901 4953 70 632 + 2901 4677 49 632 + 2901 4661 80 995 + 2901 3433 19 55 + 2941 1303 82 632 + 2941 621 36 245 + 2941 4479 34 673 + 3427 3976 14 632 + 3427 1414 5 83 + 3533 610 40 632 + 3533 925 100 186 + 3533 1917 70 800 + 3976 2827 72 632 + 3976 4160 81 240 + 4238 4331 50 632 + 4238 3282 33 223 + 4238 4356 45 878 + 4331 3533 24 632 + 4331 2401 98 179 + 4331 184 48 798 + 426 3933 24 692 + 426 1951 90 104 + 426 3461 46 108 + 604 4909 33 692 + 604 3853 82 639 + 604 3610 6 262 + 2246 4683 52 692 + 2246 2300 92 692 + 2246 3774 88 313 + 2300 604 72 692 + 2300 2074 82 633 + 3933 4339 69 692 + 3933 4004 5 609 + 3933 1143 8 313 + 4339 2246 63 692 + 4339 2946 81 578 + 427 3526 56 930 + 427 2645 60 376 + 2478 4623 35 930 + 2478 3954 70 930 + 2478 2649 65 121 + 2478 896 1 534 + 3289 4079 8 930 + 3289 965 9 588 + 3526 3289 49 930 + 3526 2068 79 76 + 3526 757 14 885 + 3633 3810 35 930 + 3633 2958 42 333 + 3633 3627 4 384 + 3810 4829 21 930 + 3810 4860 97 746 + 3954 3633 76 930 + 3954 2150 76 304 + 4079 2478 22 930 + 4079 4414 42 237 + 428 2461 31 648 + 428 4556 8 434 + 428 1608 34 549 + 2155 4576 71 648 + 2155 2407 36 648 + 2155 4521 47 107 + 2155 1981 11 180 + 2407 4913 43 648 + 2407 4557 97 279 + 2461 4142 32 648 + 2461 3834 72 311 + 4142 2155 60 648 + 4142 297 30 514 + 4142 3369 22 726 + 429 2304 61 404 + 429 1033 16 225 + 2187 3410 63 404 + 2187 2531 50 443 + 2304 3927 12 404 + 2304 4540 9 404 + 2304 1716 9 670 + 2304 899 33 84 + 2305 2187 60 404 + 2305 4270 59 607 + 2305 3425 63 808 + 2369 2305 27 404 + 2369 1094 95 23 + 2369 2972 2 930 + 2895 2369 5 404 + 2895 4314 12 795 + 2895 3988 36 459 + 3410 4624 89 404 + 3410 3446 79 498 + 3410 3536 39 5 + 3927 4090 23 404 + 3927 1334 23 888 + 4090 2895 90 404 + 4090 868 25 406 + 4090 1244 20 233 + 430 3342 21 264 + 430 933 33 242 + 621 4439 18 264 + 621 4852 2 877 + 621 3474 46 807 + 3266 4974 54 264 + 3266 2799 68 775 + 3266 3876 75 314 + 3342 3978 47 264 + 3342 4703 89 988 + 3342 1512 60 720 + 3978 4737 57 264 + 3978 621 10 264 + 3978 4006 15 317 + 4439 3266 38 264 + 4439 2888 38 135 + 431 1123 63 1014 + 431 2610 86 52 + 1082 3897 9 1014 + 1082 2593 36 704 + 1082 4390 11 787 + 1123 1643 49 1014 + 1123 765 13 105 + 1123 3548 54 673 + 1643 4493 38 1014 + 1643 2835 13 297 + 1643 2331 94 223 + 3008 3843 62 1014 + 3008 1050 87 25 + 3123 3008 32 1014 + 3123 3740 51 184 + 3123 4929 83 469 + 3843 4845 87 1014 + 3843 1082 31 1014 + 3843 4650 1 432 + 3897 4573 10 1014 + 3897 4243 81 158 + 4493 3123 21 1014 + 4493 680 46 693 + 432 1731 91 298 + 432 3089 94 816 + 432 3482 54 964 + 1731 3406 71 298 + 1731 2667 54 715 + 1767 2725 61 298 + 1767 2041 12 747 + 1767 2160 18 812 + 1933 1767 54 298 + 1933 4937 71 298 + 1933 19 3 874 + 1933 2477 75 123 + 2696 4757 19 298 + 2696 4213 92 57 + 2725 2696 41 298 + 2725 3001 40 348 + 3406 1933 1 298 + 3406 1612 44 329 + 3406 2186 21 836 + 433 2958 38 498 + 433 742 67 917 + 1606 3852 70 498 + 1606 4918 4 776 + 2177 1606 61 498 + 2177 4430 83 407 + 2177 1288 66 602 + 2688 2177 20 498 + 2688 4510 16 498 + 2688 1322 75 651 + 2791 2688 25 498 + 2791 3957 85 566 + 2791 1103 75 170 + 2958 2791 23 498 + 2958 4833 78 14 + 2958 4857 60 499 + 3742 4862 98 498 + 3742 517 22 974 + 3742 3183 96 765 + 3852 3742 5 498 + 3852 4919 98 344 + 434 1276 86 36 + 434 4871 90 531 + 434 1378 72 399 + 1072 3128 81 36 + 1072 4959 73 36 + 1072 4181 33 116 + 1072 1532 30 297 + 1276 1072 93 36 + 1276 3779 57 103 + 1276 4545 1 534 + 1401 4643 64 36 + 1401 3103 81 825 + 1892 2144 8 36 + 1892 1992 94 274 + 1892 4899 59 619 + 2144 1401 36 36 + 2144 1634 19 34 + 2144 3635 44 660 + 3128 3416 91 36 + 3128 2561 20 223 + 3128 4679 87 756 + 3416 1892 100 36 + 3416 3117 75 861 + 435 585 11 141 + 435 2795 67 117 + 435 1996 38 507 + 585 3611 46 141 + 585 1921 97 277 + 585 286 51 527 + 944 4908 29 141 + 944 288 91 270 + 1665 4838 23 141 + 1665 3012 76 141 + 1665 869 94 142 + 1665 4774 44 965 + 3012 3029 14 141 + 3012 1802 57 826 + 3012 250 2 107 + 3029 944 74 141 + 3029 1857 86 290 + 3611 1665 58 141 + 3611 321 37 269 + 436 1154 99 957 + 436 1409 93 395 + 436 434 17 925 + 906 1595 5 957 + 906 4542 39 957 + 906 164 2 47 + 906 1126 69 963 + 1154 1335 15 957 + 1154 4305 54 456 + 1184 906 48 957 + 1184 2088 21 443 + 1335 4282 20 957 + 1335 446 74 128 + 1595 4873 79 957 + 1595 2784 72 784 + 1595 1143 97 23 + 2149 1184 37 957 + 2149 3905 55 63 + 2149 710 68 621 + 4282 2149 89 957 + 4282 2523 17 959 + 437 1134 60 574 + 437 4496 10 304 + 1018 3272 83 574 + 1018 2980 96 162 + 1031 3064 54 574 + 1031 2816 73 426 + 1134 1018 30 574 + 1134 4530 29 574 + 1134 2018 67 593 + 1134 2387 96 401 + 1710 1031 45 574 + 1710 1988 16 29 + 1710 3546 1 549 + 3064 4526 41 574 + 3064 3919 16 732 + 3272 1710 90 574 + 3272 2440 58 446 + 438 4256 99 507 + 438 4889 74 409 + 958 4192 10 507 + 958 1754 10 883 + 1287 2532 42 507 + 1287 1303 24 390 + 1287 973 64 502 + 2286 958 55 507 + 2286 3023 29 298 + 2532 3618 37 507 + 2532 253 56 375 + 2532 1873 17 946 + 3319 2286 89 507 + 3319 780 60 60 + 3319 3704 43 527 + 3618 4800 5 507 + 3618 4683 90 507 + 3618 3879 54 807 + 3618 4379 55 760 + 4192 1287 52 507 + 4256 4332 62 507 + 4256 4300 73 774 + 4332 3319 84 507 + 4332 222 70 19 + 439 4095 14 257 + 439 2258 9 709 + 1480 2311 22 257 + 1480 4749 82 257 + 2023 4633 69 257 + 2023 596 42 242 + 2311 2870 100 257 + 2311 1675 57 224 + 2311 2088 91 113 + 2648 1480 72 257 + 2870 2023 55 257 + 2870 1869 53 768 + 4095 2648 81 257 + 4095 3689 80 703 + 440 1284 37 531 + 440 686 57 423 + 440 1740 74 566 + 627 3768 56 531 + 722 4640 99 531 + 722 1111 44 183 + 985 3561 32 531 + 985 291 37 594 + 1284 627 47 531 + 1284 500 54 11 + 1284 407 9 21 + 2025 722 87 531 + 3286 2025 47 531 + 3286 837 78 468 + 3561 3286 5 531 + 3561 3990 13 447 + 3561 138 65 515 + 3768 4327 51 531 + 3768 4778 45 531 + 4327 985 28 531 + 441 509 77 1178 + 441 2704 41 431 + 509 2022 31 1178 + 509 61 51 433 + 509 2606 51 543 + 647 3409 44 1178 + 1572 647 5 1178 + 1572 2098 90 345 + 2022 3381 83 1178 + 2022 4743 3 1178 + 2219 3485 6 1178 + 2219 4198 2 234 + 2415 2219 44 1178 + 2415 1742 28 284 + 2671 3107 41 1178 + 2671 4613 45 292 + 3107 4781 69 1178 + 3107 1289 17 273 + 3381 1572 22 1178 + 3381 4547 75 909 + 3381 1073 33 581 + 3409 3575 91 1178 + 3409 4733 69 1178 + 3485 2671 45 1178 + 3575 2415 19 1178 + 3575 688 2 855 + 442 2809 76 689 + 442 4350 73 576 + 442 3644 90 721 + 772 4246 92 689 + 1218 1311 71 689 + 1218 4301 99 526 + 1218 1448 31 497 + 1311 4487 75 689 + 1348 1810 49 689 + 1348 3360 58 333 + 1810 3644 38 689 + 1810 1634 61 310 + 1810 1967 88 275 + 2569 4830 36 689 + 2809 772 86 689 + 2809 4685 33 306 + 3644 1218 73 689 + 3644 1504 5 219 + 3644 2419 46 269 + 4246 1348 27 689 + 4487 2569 66 689 + 4487 4824 70 689 + 443 2278 90 445 + 443 738 89 376 + 443 101 88 290 + 918 2830 54 445 + 1135 4910 64 445 + 1135 2556 32 864 + 1321 1946 70 445 + 1321 94 50 682 + 1612 3747 54 445 + 1612 1007 4 76 + 1946 1135 60 445 + 1946 4129 91 583 + 1946 4158 80 602 + 2278 918 11 445 + 2278 4512 30 445 + 2544 1321 3 445 + 2830 1612 73 445 + 2830 2721 57 98 + 3747 2544 60 445 + 3747 4874 17 505 + 3747 725 84 618 + 444 1756 55 422 + 1410 4552 99 422 + 1410 3226 68 201 + 1659 1872 88 422 + 1659 2856 98 478 + 1659 3267 63 773 + 1756 1659 50 422 + 1872 3621 58 422 + 1872 522 40 693 + 2348 1410 99 422 + 2348 4564 75 422 + 3621 3678 21 422 + 3621 4337 87 167 + 3678 4111 36 422 + 3678 443 79 644 + 4111 2348 54 422 + 4111 1892 35 420 + 445 1755 17 1222 + 445 3943 13 601 + 445 2542 79 88 + 995 4584 85 1222 + 1329 995 69 1222 + 1329 2491 88 540 + 1329 3914 88 257 + 1755 2923 22 1222 + 1870 2739 9 1222 + 1870 1971 64 39 + 2121 4044 13 1222 + 2121 21 1 507 + 2146 2734 36 1222 + 2146 3343 63 562 + 2146 3549 21 39 + 2734 4948 18 1222 + 2734 1870 53 1222 + 2739 1329 28 1222 + 2923 2121 36 1222 + 2923 2184 30 786 + 4044 2146 43 1222 + 4044 381 44 687 + 446 3737 67 404 + 446 1920 41 526 + 446 2117 39 641 + 1795 4925 89 404 + 1795 4854 11 404 + 2172 3905 33 404 + 3723 1795 43 404 + 3723 1588 53 584 + 3737 2172 20 404 + 3737 3410 84 277 + 3737 804 26 719 + 3905 3723 54 404 + 447 4470 69 516 + 447 2609 86 728 + 950 4608 95 516 + 950 582 83 719 + 2429 3549 96 516 + 2429 1407 32 282 + 2429 3634 54 996 + 2795 3705 9 516 + 3549 2795 73 516 + 3549 3319 50 178 + 3705 950 81 516 + 3705 1788 55 860 + 3705 955 73 438 + 4470 2429 5 516 + 4470 4844 97 516 + 448 2826 45 298 + 955 1122 47 298 + 955 3479 32 363 + 1122 1171 59 298 + 1122 4643 96 298 + 1171 3312 12 298 + 1171 1826 28 767 + 1171 1545 64 428 + 1788 4986 27 298 + 2826 955 37 298 + 2826 578 46 526 + 2826 4940 22 287 + 3312 1788 62 298 + 449 1336 86 359 + 449 2178 62 946 + 628 4986 16 359 + 628 132 51 224 + 1210 4985 61 359 + 1210 1907 59 359 + 1336 1210 47 359 + 1336 785 44 447 + 1907 628 15 359 + 1907 1879 57 527 + 450 596 16 196 + 450 709 40 193 + 596 2845 55 196 + 596 3765 30 312 + 596 3339 74 79 + 858 3925 38 196 + 937 1252 50 196 + 937 4691 9 886 + 989 937 19 196 + 989 4990 32 196 + 1252 858 1 196 + 1252 372 77 975 + 2845 989 86 196 + 2845 4952 16 771 + 3925 4913 29 196 + 3925 4068 15 906 + 451 2536 80 394 + 451 680 94 499 + 1819 4823 68 394 + 1819 1728 4 791 + 1835 2033 45 394 + 1835 1863 85 329 + 1835 2619 33 731 + 2033 2463 93 394 + 2388 1835 74 394 + 2388 892 63 318 + 2463 1819 14 394 + 2463 4830 34 394 + 2536 2690 72 394 + 2536 657 13 768 + 2690 2388 8 394 + 2690 2830 99 924 + 2690 1269 63 717 + 452 3638 17 412 + 638 2222 55 412 + 638 4801 44 171 + 1342 1777 21 412 + 1342 294 12 584 + 1607 4352 5 412 + 1607 3073 72 449 + 1607 2195 45 548 + 1619 638 7 412 + 1777 4841 78 412 + 1777 1906 66 412 + 1906 2002 1 412 + 1906 3759 2 38 + 1906 1997 21 610 + 2002 4514 58 412 + 2222 1607 27 412 + 2222 625 81 3 + 3368 1619 4 412 + 3368 3415 25 706 + 3368 1243 55 315 + 3452 4645 22 412 + 3452 1342 27 412 + 3638 3368 50 412 + 4352 3452 8 412 + 4352 4706 16 255 + 4352 4834 4 734 + 453 1241 77 276 + 1241 2329 69 276 + 1241 3434 57 216 + 1241 1835 12 16 + 2329 2379 2 276 + 2379 3528 31 276 + 2379 261 65 592 + 3010 4907 71 276 + 3010 4066 42 880 + 3528 3565 20 276 + 3528 4509 37 276 + 3565 3010 50 276 + 3565 3356 53 883 + 3565 4845 18 491 + 454 2333 58 484 + 542 2145 93 484 + 542 1147 53 410 + 786 3641 43 484 + 786 1396 12 603 + 786 4512 13 819 + 2016 542 78 484 + 2145 3578 29 484 + 2145 3048 7 22 + 2333 4412 34 484 + 2333 4518 80 282 + 2333 4173 23 438 + 2417 4204 52 484 + 3578 786 34 484 + 3578 3466 14 625 + 3641 4913 3 484 + 3641 665 68 346 + 4204 2016 51 484 + 4204 4542 51 484 + 4412 2417 35 484 + 4412 294 28 624 + 4412 3289 61 230 + 455 2814 72 635 + 1785 2273 44 635 + 1785 2312 20 949 + 1808 1785 90 635 + 1808 4525 16 268 + 1808 2134 22 249 + 2273 2292 47 635 + 2292 4410 2 635 + 2292 1905 60 684 + 2732 4793 30 635 + 2732 3900 1 501 + 2732 1011 69 909 + 2814 1808 25 635 + 2984 2732 60 635 + 2984 1046 22 402 + 3620 2984 76 635 + 3620 4676 70 938 + 3620 3628 52 343 + 4410 3620 27 635 + 4410 4962 59 635 + 456 1508 72 204 + 1233 2672 45 204 + 1233 2614 53 411 + 1482 1233 21 204 + 1482 505 90 879 + 1508 2679 27 204 + 1508 1683 34 51 + 1508 4526 83 883 + 1574 4774 26 204 + 2226 1574 97 204 + 2226 3461 16 276 + 2672 2226 24 204 + 2672 1078 42 600 + 2672 4104 34 693 + 2679 1482 34 204 + 2679 4817 99 204 + 457 2057 25 826 + 1047 1960 67 826 + 1047 4884 76 826 + 1449 4473 3 826 + 1449 183 87 454 + 1960 3190 84 826 + 1960 1588 29 253 + 1960 733 83 682 + 2057 1047 56 826 + 3190 1449 75 826 + 3190 1834 25 684 + 3190 3429 95 857 + 4473 4554 1 826 + 458 688 33 169 + 458 3560 79 587 + 688 1332 38 169 + 688 4861 69 169 + 1332 2790 39 169 + 1332 2326 79 722 + 1332 4161 100 253 + 2790 3226 70 169 + 3226 4129 66 169 + 3226 1544 51 811 + 3226 1015 51 848 + 4129 4934 58 169 + 459 2778 19 361 + 459 1608 22 283 + 685 3625 72 361 + 685 3346 32 832 + 685 1369 28 607 + 1175 2614 69 361 + 1515 1530 38 361 + 1515 785 78 272 + 1515 4211 34 995 + 1530 4996 37 361 + 2614 4039 88 361 + 2614 4608 2 361 + 2778 3247 72 361 + 2778 2811 20 948 + 3247 685 67 361 + 3247 1998 2 10 + 3625 1175 11 361 + 3625 268 84 16 + 4039 1515 38 361 + 4039 1433 65 536 + 460 4032 61 906 + 460 1230 54 949 + 460 3942 76 972 + 923 2252 56 906 + 1240 3199 63 906 + 1240 3890 69 991 + 1240 4353 60 31 + 2252 4788 32 906 + 2252 4685 7 906 + 2695 4454 71 906 + 3199 2695 3 906 + 3199 1789 2 554 + 3519 923 19 906 + 3519 3083 31 675 + 3519 242 59 887 + 4032 4340 49 906 + 4340 1240 71 906 + 4340 3480 56 50 + 4454 3519 36 906 + 4454 863 13 97 + 461 3212 70 1143 + 461 284 36 253 + 461 4996 93 135 + 564 913 96 1143 + 863 4879 87 1143 + 863 4981 93 1143 + 913 2479 43 1143 + 913 1786 16 992 + 913 2453 69 42 + 1494 863 100 1143 + 2126 4233 43 1143 + 2126 4272 4 733 + 2126 3969 67 784 + 2479 3425 98 1143 + 3212 2126 46 1143 + 3212 4687 90 256 + 3212 2716 10 560 + 3425 1494 47 1143 + 4233 564 59 1143 + 4233 2357 70 201 + 462 3872 6 484 + 462 306 57 119 + 752 1213 29 484 + 752 633 80 560 + 852 4488 39 484 + 852 3620 74 832 + 852 4280 2 118 + 920 2195 21 484 + 1213 852 76 484 + 1213 2627 19 865 + 1213 3699 51 35 + 2098 920 87 484 + 2195 2674 14 484 + 2195 4642 42 484 + 2674 3821 43 484 + 2674 1082 43 985 + 2674 1188 87 323 + 3821 752 66 484 + 3872 2098 68 484 + 3872 3065 93 711 + 4488 4916 63 484 + 4488 3428 96 536 + 463 4308 23 670 + 463 2581 4 130 + 463 3574 76 36 + 503 2186 6 670 + 905 4631 39 670 + 905 4274 32 574 + 905 990 23 55 + 1221 905 67 670 + 2186 4945 15 670 + 2186 1221 39 670 + 4308 503 40 670 + 4308 806 24 833 + 464 3391 55 248 + 464 393 39 694 + 1507 4789 18 248 + 1507 1449 86 875 + 2207 1507 5 248 + 2207 2070 9 596 + 2207 570 20 944 + 2363 3636 66 248 + 3391 2363 19 248 + 3391 3834 28 661 + 3391 221 4 699 + 3636 2207 100 248 + 3636 4573 55 248 + 465 2499 92 94 + 756 2235 34 94 + 756 4026 19 753 + 756 3461 29 976 + 785 1067 7 94 + 1067 1133 98 94 + 1067 4528 88 13 + 1133 756 86 94 + 1133 701 7 185 + 1133 2571 60 911 + 1734 2875 84 94 + 2235 4838 22 94 + 2235 1763 20 810 + 2499 3831 75 94 + 2499 2136 1 854 + 2875 4635 87 94 + 2875 785 69 94 + 3831 1734 15 94 + 3831 1890 69 466 + 3831 2931 45 215 + 466 2677 23 109 + 640 3670 53 109 + 640 2159 35 920 + 1362 3169 91 109 + 1362 3500 25 202 + 2468 3397 47 109 + 2468 284 54 819 + 2677 1362 57 109 + 2677 3378 83 278 + 2677 2712 58 521 + 3169 2468 16 109 + 3397 3973 18 109 + 3397 4836 50 235 + 3670 4728 56 109 + 3670 4608 68 109 + 3973 640 50 109 + 3973 3295 78 137 + 3973 4064 36 764 + 467 4153 77 506 + 774 3305 4 506 + 774 4988 92 387 + 774 2008 46 403 + 1095 1994 41 506 + 1994 774 38 506 + 1994 4963 26 908 + 2138 2626 21 506 + 2138 836 75 514 + 2138 938 2 810 + 2626 4961 18 506 + 2626 1095 48 506 + 2860 4293 90 506 + 3305 2860 31 506 + 3305 117 21 660 + 4153 2138 78 506 + 4153 2631 62 917 + 4293 4769 4 506 + 4293 3075 88 838 + 468 615 42 718 + 468 2001 61 706 + 615 3693 16 718 + 615 3101 27 543 + 684 4668 3 718 + 684 3134 91 718 + 813 4681 47 718 + 813 731 47 115 + 2733 684 27 718 + 2733 3238 52 128 + 2733 1752 58 809 + 3134 813 57 718 + 3460 2733 100 718 + 3460 3551 2 729 + 3693 3460 64 718 + 3693 1545 58 176 + 3693 4703 30 558 + 469 1388 44 381 + 520 1402 85 381 + 520 3704 94 431 + 1388 2617 6 381 + 1388 1347 25 885 + 1402 4949 78 381 + 1402 403 83 83 + 2617 4649 9 381 + 2617 3707 78 381 + 2917 4213 16 381 + 2917 1651 75 703 + 3160 2917 32 381 + 3160 3488 17 708 + 3707 3160 57 381 + 3707 4925 77 958 + 3707 4892 85 547 + 4213 520 36 381 + 470 1019 29 1110 + 470 1900 96 388 + 519 733 73 1110 + 519 3056 78 105 + 733 4932 97 1110 + 733 3137 22 177 + 733 4724 80 753 + 1019 2944 96 1110 + 2568 519 43 1110 + 2568 1364 30 90 + 2944 4234 51 1110 + 2944 4630 91 1110 + 4124 2568 46 1110 + 4124 1272 24 671 + 4124 1291 45 125 + 4234 4124 18 1110 + 471 3228 4 414 + 471 809 23 33 + 517 4774 98 414 + 517 3400 76 520 + 517 881 75 401 + 1634 517 11 414 + 1634 4967 11 414 + 2443 1634 48 414 + 3228 3564 48 414 + 3228 1877 38 867 + 3228 4718 41 479 + 3564 2443 94 414 + 472 3182 1 1002 + 472 4334 61 17 + 1195 4424 21 1002 + 1195 644 45 89 + 3182 3211 61 1002 + 3182 1228 38 331 + 3182 2767 83 414 + 3211 3469 53 1002 + 3469 1195 59 1002 + 3469 4626 65 1002 + 4424 4855 29 1002 + 4424 4598 45 750 + 473 801 85 327 + 473 3783 22 467 + 801 3108 97 327 + 801 4465 98 235 + 801 990 10 255 + 1109 3297 47 327 + 2736 1109 7 327 + 2736 3667 14 728 + 2736 1953 57 838 + 3108 4276 2 327 + 3108 4643 68 327 + 3297 4287 10 327 + 4276 2736 41 327 + 4276 2372 13 232 + 4276 659 98 203 + 4287 4511 41 327 + 474 1759 71 452 + 474 1202 60 963 + 474 1947 1 278 + 1418 3689 29 452 + 1581 1779 34 452 + 1581 155 27 674 + 1581 1757 23 5 + 1759 2940 17 452 + 1779 2020 14 452 + 1779 1126 28 687 + 2020 1418 78 452 + 2020 3331 78 461 + 2940 1581 91 452 + 2940 3331 33 696 + 2940 932 89 994 + 3689 4601 24 452 + 3689 4656 84 452 + 475 3835 33 379 + 3046 4856 71 379 + 3046 3842 31 379 + 3244 4914 19 379 + 3244 2721 15 574 + 3244 755 89 504 + 3835 3046 66 379 + 3842 4391 33 379 + 3842 397 39 528 + 3842 4182 90 694 + 4391 3244 39 379 + 476 2847 50 315 + 476 1987 52 512 + 1766 4735 19 315 + 1766 3943 75 348 + 1766 1717 60 682 + 2119 4795 92 315 + 2119 1766 62 315 + 2847 2889 11 315 + 2889 2119 68 315 + 2889 645 62 246 + 477 2234 37 1012 + 477 3926 94 40 + 477 4325 96 37 + 901 4586 63 1012 + 2234 3699 4 1012 + 2234 2332 32 190 + 2603 2702 32 1012 + 2603 2682 67 578 + 2702 901 96 1012 + 2702 1231 45 546 + 3699 4481 40 1012 + 3699 2501 39 825 + 3699 651 76 225 + 4481 2603 17 1012 + 4481 4777 74 1012 + 478 1138 29 572 + 620 2442 87 572 + 620 4799 25 572 + 712 4314 79 572 + 712 330 13 806 + 712 1036 94 380 + 718 4867 79 572 + 1002 620 56 572 + 1002 320 79 189 + 1002 1845 37 413 + 1138 1002 25 572 + 1831 3982 61 572 + 1831 2423 47 660 + 1831 83 95 457 + 2442 1831 1 572 + 3982 712 13 572 + 3982 4008 60 951 + 3982 804 28 389 + 4314 718 70 572 + 479 3056 99 421 + 479 1720 48 494 + 479 2994 87 983 + 614 3110 28 421 + 1190 1999 61 421 + 1190 4183 14 467 + 1999 2490 46 421 + 1999 4752 55 421 + 2490 614 54 421 + 2490 2830 63 120 + 2490 509 88 457 + 3056 1190 39 421 + 3110 4917 19 421 + 3110 4719 72 770 + 480 1197 79 653 + 480 2349 3 855 + 567 3560 30 653 + 567 3864 28 397 + 1197 2782 80 653 + 1197 3207 84 798 + 1197 2835 51 23 + 2265 2323 5 653 + 2323 2401 81 653 + 2323 2111 89 443 + 2401 4900 35 653 + 2401 4779 95 712 + 2580 567 92 653 + 2580 347 9 911 + 2580 272 2 574 + 2782 4452 83 653 + 3560 4663 7 653 + 3560 2265 68 653 + 4452 2580 1 653 + 4452 109 68 866 + 481 3653 30 492 + 481 1158 54 611 + 481 4867 73 62 + 970 4807 72 492 + 970 4674 41 492 + 2107 4188 5 492 + 2692 970 67 492 + 2692 3213 50 988 + 2692 4241 50 605 + 2985 2692 23 492 + 3653 2107 89 492 + 3653 2628 70 350 + 3653 532 77 650 + 4188 2985 96 492 + 482 3115 32 485 + 482 2195 58 890 + 482 451 30 743 + 2290 3710 74 485 + 3115 4441 79 485 + 3115 3739 9 273 + 3115 148 94 4 + 3317 4370 97 485 + 3626 2290 26 485 + 3626 4861 91 319 + 3710 4518 95 485 + 3710 4031 11 58 + 4370 4449 3 485 + 4370 4956 4 563 + 4370 3800 6 925 + 4441 3317 42 485 + 4449 3626 63 485 + 4449 4831 19 485 + 483 2903 65 91 + 483 4926 11 69 + 1617 4630 39 91 + 1617 1306 2 85 + 2899 3994 99 91 + 2899 4943 13 804 + 2899 1864 23 903 + 2903 2899 82 91 + 3568 3958 71 91 + 3568 4676 80 265 + 3568 368 89 470 + 3958 1617 2 91 + 3994 3568 45 91 + 3994 4698 67 91 + 484 930 24 667 + 484 1368 56 873 + 504 4557 5 667 + 504 4526 83 667 + 930 1228 12 667 + 930 134 46 698 + 1208 1965 21 667 + 1208 3324 36 250 + 1228 2396 49 667 + 1228 2148 57 84 + 1228 4310 100 47 + 1965 504 77 667 + 2396 1208 19 667 + 2396 4818 43 661 + 2396 2734 39 612 + 485 2653 69 793 + 806 3143 80 793 + 806 2430 84 292 + 806 4140 98 277 + 1868 2283 47 793 + 1981 1868 63 793 + 1981 334 29 143 + 2283 4825 39 793 + 2283 4971 73 793 + 2653 806 76 793 + 2653 523 86 727 + 2653 459 17 92 + 3143 1981 100 793 + 486 808 61 192 + 486 1234 8 729 + 605 2757 4 192 + 605 1666 13 180 + 808 1334 27 192 + 808 4553 84 192 + 986 2660 94 192 + 986 4876 64 635 + 1334 2389 38 192 + 1334 992 17 160 + 1334 2674 87 897 + 2389 2760 19 192 + 2660 3851 74 192 + 2660 1535 44 24 + 2660 1109 23 732 + 2757 986 94 192 + 2760 605 32 192 + 2760 4233 65 308 + 2760 1939 32 817 + 3851 4080 68 192 + 4080 4670 47 192 + 4080 2428 50 321 + 487 3862 93 631 + 487 2662 87 672 + 2275 2962 88 631 + 2275 1263 60 511 + 2962 3527 90 631 + 2962 4840 55 568 + 2962 30 37 313 + 3527 4892 17 631 + 3862 4455 86 631 + 3862 2891 77 680 + 4055 4955 45 631 + 4055 2275 18 631 + 4455 4055 61 631 + 4455 4452 23 503 + 488 3724 29 404 + 488 1273 40 139 + 488 3989 86 350 + 553 1989 92 404 + 1094 4548 54 404 + 1094 4568 20 404 + 1989 2370 65 404 + 1989 1907 65 885 + 1989 2064 20 235 + 2370 1094 28 404 + 3724 553 18 404 + 3724 2427 49 523 + 3724 2598 8 273 + 489 1124 21 635 + 507 4763 4 635 + 507 818 46 445 + 1124 1842 100 635 + 1124 915 74 515 + 1124 127 11 220 + 1842 3901 48 635 + 2556 4879 61 635 + 2556 3426 65 635 + 3426 507 28 635 + 3426 3730 76 572 + 3426 3251 23 355 + 3901 3970 52 635 + 3970 2556 67 635 + 3970 522 23 772 + 3970 3556 63 386 + 490 1601 85 60 + 1502 4174 71 60 + 1502 2646 67 431 + 1601 1502 4 60 + 1601 2227 62 652 + 2153 4407 70 60 + 2153 2783 47 808 + 2153 103 24 669 + 2781 4577 99 60 + 3766 4058 53 60 + 3766 158 4 916 + 4058 2781 81 60 + 4058 4795 29 60 + 4174 2153 24 60 + 4174 604 51 600 + 4174 3813 26 45 + 4407 3766 11 60 + 491 3953 91 252 + 491 202 28 44 + 491 2189 90 337 + 1282 2714 42 252 + 2714 4425 95 252 + 2714 4780 47 811 + 3712 4656 84 252 + 3712 644 1 753 + 3841 1282 33 252 + 3841 4305 5 918 + 3870 3841 64 252 + 3870 2399 11 578 + 3870 1084 72 711 + 3953 3870 4 252 + 4425 3712 74 252 + 4425 4949 43 252 + 492 1543 5 739 + 492 4164 96 549 + 720 4679 96 739 + 720 2743 81 594 + 1199 4746 21 739 + 1199 2230 7 739 + 1543 2742 66 739 + 1543 3269 33 508 + 2230 720 78 739 + 2230 1507 75 372 + 2742 1199 11 739 + 2742 440 28 422 + 493 539 25 117 + 493 345 11 946 + 539 1104 97 117 + 539 4135 56 631 + 765 3727 56 117 + 765 418 51 106 + 765 4865 82 943 + 1104 1427 39 117 + 1270 765 72 117 + 1270 3572 40 20 + 1427 2024 64 117 + 1427 1394 52 839 + 2024 1270 27 117 + 2024 3528 97 202 + 2629 4825 16 117 + 2629 4642 24 117 + 3727 2629 57 117 + 3727 2758 74 902 + 494 3166 22 412 + 494 88 34 479 + 595 4527 82 412 + 595 2959 69 973 + 595 292 13 391 + 771 2927 71 412 + 771 4571 63 412 + 834 595 29 412 + 1567 834 48 412 + 1567 2405 38 32 + 1567 2417 27 501 + 2927 3719 62 412 + 3040 771 1 412 + 3040 3488 33 468 + 3040 372 17 136 + 3166 3040 35 412 + 3569 1567 89 412 + 3569 248 33 103 + 3569 184 70 422 + 3719 3569 4 412 + 495 639 61 804 + 495 303 11 66 + 495 3767 42 178 + 639 1814 32 804 + 1458 3332 76 804 + 1458 1653 56 518 + 1458 99 88 693 + 1475 4465 60 804 + 1475 4752 53 804 + 1814 4162 65 804 + 2470 1475 65 804 + 2470 4743 20 939 + 2470 1129 44 475 + 2635 1458 32 804 + 3332 4916 2 804 + 3332 3363 89 506 + 3332 2003 4 734 + 3987 2635 97 804 + 4162 2470 96 804 + 4162 1159 51 634 + 4465 3987 42 804 + 4465 3464 65 125 + 496 4006 4 472 + 496 1569 32 916 + 496 3329 15 557 + 1644 4895 12 472 + 2485 3384 25 472 + 2485 3921 14 548 + 2485 4800 78 850 + 3144 3777 68 472 + 3384 1644 84 472 + 3384 3095 24 410 + 3777 2485 96 472 + 3777 2263 6 983 + 4006 3144 70 472 + 4006 4843 21 472 + 497 3652 98 672 + 497 1880 13 988 + 497 4595 38 640 + 1286 2373 41 672 + 1331 1286 46 672 + 1331 4069 66 114 + 1445 1833 90 672 + 1445 1802 66 201 + 1445 4101 31 77 + 1833 2862 54 672 + 2373 3023 51 672 + 2373 4652 55 672 + 2862 4634 48 672 + 2862 1806 93 847 + 2862 3228 48 18 + 3023 1445 48 672 + 3652 1331 25 672 + 3652 3832 73 64 + 3652 915 43 261 + 498 2182 23 833 + 1571 1847 31 833 + 1571 3728 39 468 + 1571 3669 32 943 + 1847 4657 100 833 + 2182 2836 97 833 + 2182 1969 77 153 + 2319 1571 14 833 + 2319 2103 83 602 + 2836 2319 83 833 + 2836 4958 78 833 + 499 2255 49 1251 + 499 2214 85 522 + 499 1111 8 694 + 1939 4556 52 1251 + 2179 3423 44 1251 + 2179 4580 54 894 + 2179 4216 11 716 + 2255 3383 7 1251 + 3383 4689 69 1251 + 3383 2179 85 1251 + 3423 1939 67 1251 + 3423 3313 38 767 + 500 1446 59 638 + 500 1573 90 877 + 1015 4751 77 638 + 1015 4618 23 638 + 1015 4773 27 638 + 1015 4723 60 638 + 1015 2762 17 638 + 1015 4857 26 638 + 1015 4563 46 638 + 1015 4997 87 638 + 1015 4678 29 638 + 1015 4899 48 638 + 1015 4921 8 638 + 1015 4632 64 638 + 1015 4870 55 638 + 1015 4859 30 638 + 1446 3566 64 638 + 1446 4521 94 638 + 1446 4812 86 638 + 1446 4927 59 638 + 1446 4612 74 638 + 1446 4818 71 638 + 1446 4713 28 638 + 1446 4918 16 638 + 1446 4592 57 638 + 1446 4756 79 638 + 1446 4664 67 638 + 1446 4871 17 638 + 2762 4885 22 638 + 2762 4562 7 638 + 2762 4912 7 638 + 2762 4819 53 638 + 2762 4724 24 638 + 2762 4964 82 638 + 2762 4878 87 638 + 2762 4711 40 638 + 2762 4775 66 638 + 2762 4262 68 638 + 2762 4779 20 638 + 2762 4814 13 638 + 2762 4599 86 638 + 3100 4943 23 638 + 3100 4936 90 638 + 3100 4933 82 638 + 3100 4915 64 638 + 3100 4501 1 638 + 3100 4801 45 638 + 3100 4732 14 638 + 3100 1015 10 638 + 3100 4832 86 638 + 3100 4973 10 638 + 3100 4813 62 638 + 3566 4550 61 638 + 3566 3100 1 638 + 3566 4865 19 638 + 3566 4808 38 638 + 3566 4519 65 638 + 3566 4772 47 638 + 3566 4881 1 638 + 3566 4636 10 638 + 3566 4646 62 638 + 3566 4555 71 638 + 3566 4507 51 638 + 3566 4673 16 638 + 3566 4747 87 638 + 4262 4613 78 638 + 4262 4736 26 638 + 4262 4539 16 638 + 4262 4935 8 638 + 4262 4699 12 638 + 4262 4658 50 638 + 4262 4978 2 638 + 4262 4827 12 638 + 4530 1476 21 514 + 4531 56 19 39 + 4532 4910 61 239 + 4532 214 36 426 + 4533 3283 38 810 + 4534 1362 64 724 + 4534 4172 77 766 + 4535 1271 9 530 + 4536 4178 2 800 + 4536 757 98 704 + 4537 506 59 323 + 4537 4215 37 284 + 4538 1386 60 797 + 4539 3111 15 779 + 4540 668 61 370 + 4541 783 78 874 + 4541 775 12 557 + 4542 3521 11 457 + 4543 2472 80 263 + 4543 3930 7 277 + 4544 170 23 980 + 4544 1593 74 93 + 4545 2985 6 259 + 4546 3274 64 481 + 4547 1709 81 666 + 4548 259 33 229 + 4548 901 98 731 + 4549 4598 26 141 + 4550 2231 59 885 + 4550 1429 47 367 + 4551 1291 54 538 + 4552 4147 79 76 + 4552 398 35 796 + 4553 2267 31 739 + 4553 1604 29 9 + 4554 3596 3 94 + 4555 2884 75 209 + 4556 4588 19 782 + 4556 4796 76 997 + 4557 4850 53 545 + 4558 367 4 458 + 4558 4656 100 668 + 4559 196 60 94 + 4560 3611 98 30 + 4560 4675 88 261 + 4561 1494 31 824 + 4562 710 92 226 + 4563 481 58 543 + 4564 984 26 659 + 4565 4911 44 387 + 4565 846 38 938 + 4566 1760 92 868 + 4567 872 31 790 + 4568 3739 53 196 + 4568 301 11 449 + 4569 4888 47 431 + 4569 268 14 788 + 4570 3083 40 138 + 4570 91 5 712 + 4571 3271 13 314 + 4571 362 10 205 + 4572 845 83 442 + 4573 793 26 928 + 4574 3158 67 624 + 4574 4123 45 540 + 4575 4727 91 569 + 4575 2996 59 101 + 4576 3220 19 2 + 4576 23 7 824 + 4577 1186 26 331 + 4577 4258 99 194 + 4578 22 15 156 + 4578 3660 66 367 + 4579 3687 42 346 + 4579 403 8 987 + 4580 757 26 863 + 4581 4975 31 95 + 4582 4012 93 157 + 4583 2694 43 200 + 4583 3069 58 415 + 4584 2502 45 867 + 4584 3416 9 206 + 4585 566 9 177 + 4586 2454 48 237 + 4586 1401 3 121 + 4587 2844 43 561 + 4587 1869 52 219 + 4588 4144 65 51 + 4589 1703 50 345 + 4589 778 82 168 + 4590 512 76 406 + 4591 3201 15 847 + 4591 955 1 540 + 4592 2492 97 567 + 4592 2478 64 798 + 4593 2172 81 389 + 4593 3337 84 257 + 4594 2263 20 920 + 4594 1987 5 598 + 4595 826 39 985 + 4596 791 9 100 + 4597 3801 64 604 + 4597 4330 12 897 + 4598 4946 31 141 + 4598 450 57 219 + 4599 4677 39 668 + 4600 3861 14 48 + 4600 3193 70 567 + 4601 2431 78 878 + 4602 908 78 885 + 4602 931 90 807 + 4603 928 35 687 + 4603 2346 82 398 + 4604 1361 77 767 + 4605 4368 58 341 + 4606 3018 25 667 + 4606 4131 4 891 + 4607 4968 80 853 + 4607 801 12 693 + 4608 649 55 100 + 4608 4917 14 459 + 4609 2106 60 451 + 4609 4257 87 530 + 4610 4221 1 950 + 4611 1513 10 483 + 4612 1378 12 387 + 4612 4696 86 789 + 4613 3688 90 414 + 4614 3393 8 853 + 4614 4289 94 219 + 4615 3009 71 645 + 4616 2096 44 157 + 4617 4446 34 754 + 4618 4512 85 232 + 4619 4659 68 690 + 4619 2747 26 182 + 4620 3659 52 938 + 4621 2748 95 484 + 4622 259 31 883 + 4623 4010 86 738 + 4623 1650 29 323 + 4624 3549 48 652 + 4624 344 42 922 + 4625 4212 43 812 + 4626 1977 55 940 + 4627 157 68 74 + 4628 127 21 198 + 4628 1156 80 184 + 4629 4639 1 114 + 4629 1359 34 968 + 4630 606 37 751 + 4630 2762 39 57 + 4631 1303 3 677 + 4632 3641 20 400 + 4632 3792 71 66 + 4633 3868 45 604 + 4633 3950 81 574 + 4634 1330 41 898 + 4634 1770 18 149 + 4635 2733 96 720 + 4636 3973 51 800 + 4636 3685 98 815 + 4637 3033 45 429 + 4637 3067 83 37 + 4638 4278 23 322 + 4638 2012 25 364 + 4639 2314 18 851 + 4639 1303 58 821 + 4640 158 4 744 + 4640 1313 94 834 + 4641 4549 80 232 + 4641 1553 90 353 + 4642 1528 16 105 + 4643 1986 23 206 + 4644 2525 19 105 + 4644 4116 10 627 + 4645 1652 81 881 + 4646 3973 19 873 + 4647 3284 18 48 + 4647 562 98 976 + 4648 592 17 734 + 4648 1602 52 76 + 4649 708 35 394 + 4650 2174 14 810 + 4650 661 67 202 + 4651 875 41 368 + 4652 4766 92 585 + 4653 3090 2 840 + 4653 956 80 765 + 4654 2022 92 478 + 4655 4912 64 315 + 4656 2300 88 93 + 4656 640 87 167 + 4657 841 82 826 + 4657 4027 42 659 + 4658 2266 47 550 + 4658 3865 18 254 + 4659 1332 78 781 + 4660 1273 6 324 + 4661 4463 70 610 + 4662 27 99 201 + 4663 40 54 314 + 4663 1533 84 600 + 4664 2987 44 628 + 4665 2752 59 163 + 4665 1445 78 221 + 4666 2649 93 248 + 4666 2615 4 187 + 4667 3098 95 522 + 4668 768 45 449 + 4669 943 46 794 + 4669 450 36 45 + 4670 3525 40 249 + 4671 1657 53 357 + 4672 2496 63 458 + 4672 4698 51 547 + 4673 1729 38 169 + 4673 2717 56 353 + 4674 555 20 770 + 4675 4713 50 968 + 4675 1729 20 182 + 4676 4229 90 259 + 4676 3097 56 125 + 4677 2078 41 409 + 4677 4510 66 743 + 4678 62 97 859 + 4679 1613 40 602 + 4679 2665 14 471 + 4680 1197 81 55 + 4680 1585 17 996 + 4681 4118 71 419 + 4682 665 93 696 + 4683 3367 2 312 + 4684 4905 78 879 + 4684 4673 60 822 + 4685 3405 8 157 + 4686 2923 46 419 + 4686 4925 53 484 + 4687 2673 25 285 + 4688 4256 59 627 + 4688 2685 53 501 + 4689 3476 24 92 + 4690 1745 90 965 + 4690 4879 26 795 + 4691 3785 3 939 + 4691 4372 32 981 + 4692 1361 4 867 + 4693 4351 38 142 + 4693 4872 5 942 + 4694 1620 66 846 + 4695 3514 57 58 + 4696 4376 72 479 + 4697 4593 2 912 + 4697 4013 66 270 + 4698 4620 87 107 + 4699 1924 12 818 + 4699 1293 36 223 + 4700 3705 58 592 + 4701 1681 65 856 + 4702 2754 74 76 + 4702 1349 4 284 + 4703 1967 54 853 + 4703 713 100 532 + 4704 4571 36 30 + 4705 3854 58 367 + 4706 958 9 12 + 4706 2074 65 640 + 4707 4186 46 735 + 4708 2015 64 891 + 4709 4629 50 857 + 4709 2016 87 929 + 4710 3633 45 29 + 4710 1341 75 764 + 4711 2264 100 163 + 4712 2292 3 987 + 4712 2531 9 576 + 4713 308 27 864 + 4714 4363 1 47 + 4715 3969 5 661 + 4715 3246 57 513 + 4716 4027 84 454 + 4717 3459 69 375 + 4718 1657 17 473 + 4719 582 26 625 + 4720 2502 95 724 + 4721 1072 33 296 + 4721 4047 98 718 + 4722 1161 2 925 + 4722 2171 80 693 + 4723 2188 33 899 + 4723 353 87 211 + 4724 4661 75 351 + 4724 149 25 52 + 4725 4835 98 130 + 4726 674 99 338 + 4727 747 70 312 + 4728 3552 20 732 + 4728 2710 78 146 + 4729 4875 52 981 + 4729 588 73 298 + 4730 488 87 867 + 4730 3759 95 760 + 4731 2213 64 499 + 4732 3284 79 714 + 4733 1977 86 728 + 4734 3027 17 796 + 4734 241 45 555 + 4735 3009 25 730 + 4735 2708 70 545 + 4736 4062 83 606 + 4737 170 87 717 + 4738 2673 72 291 + 4739 332 48 3 + 4739 3614 22 719 + 4740 2019 94 274 + 4741 4711 68 667 + 4741 2979 97 561 + 4742 2610 98 402 + 4742 3733 81 721 + 4743 422 89 521 + 4744 4840 99 191 + 4745 3995 39 574 + 4745 4820 52 213 + 4746 4096 63 92 + 4747 2232 33 341 + 4747 1883 91 191 + 4748 4742 91 354 + 4748 2422 52 456 + 4749 359 76 690 + 4749 2935 40 695 + 4750 768 34 243 + 4750 216 46 269 + 4751 2415 53 877 + 4752 2603 100 277 + 4753 444 1 457 + 4753 4381 54 69 + 4754 2049 18 806 + 4755 4020 3 379 + 4755 4025 2 812 + 4756 807 1 573 + 4757 791 29 981 + 4757 3051 31 335 + 4758 4435 92 558 + 4759 2508 58 623 + 4759 1269 10 784 + 4760 4458 35 194 + 4761 1276 1 262 + 4762 1933 43 865 + 4763 3027 35 473 + 4763 3357 57 763 + 4764 2129 33 426 + 4764 1779 61 492 + 4765 1439 69 309 + 4766 3735 62 481 + 4767 290 61 87 + 4768 3468 30 381 + 4768 4764 71 336 + 4769 3174 4 894 + 4770 1548 46 997 + 4770 1880 6 383 + 4771 3178 45 292 + 4771 1391 17 246 + 4772 1018 88 461 + 4772 2981 20 287 + 4773 2308 26 795 + 4774 1318 56 294 + 4774 2971 23 329 + 4775 2779 8 36 + 4776 4112 70 67 + 4777 2427 39 798 + 4777 4820 10 391 + 4778 1183 43 224 + 4778 3692 74 919 + 4779 1397 33 442 + 4780 1435 21 285 + 4780 3217 6 171 + 4781 4538 15 152 + 4781 4739 62 567 + 4782 2485 86 628 + 4782 2650 19 841 + 4783 4364 47 381 + 4784 3134 53 749 + 4784 2008 16 400 + 4785 1288 22 295 + 4786 4460 33 789 + 4786 4068 1 416 + 4787 4462 38 50 + 4788 181 3 984 + 4788 2182 42 137 + 4789 378 62 786 + 4790 1337 14 916 + 4790 3097 11 52 + 4791 4632 37 949 + 4791 1446 97 27 + 4792 2441 77 984 + 4792 2691 94 796 + 4793 197 81 683 + 4794 618 73 534 + 4795 2931 57 867 + 4796 51 98 114 + 4796 289 5 982 + 4797 4885 40 736 + 4797 3879 63 308 + 4798 3205 39 985 + 4798 3994 80 799 + 4799 3525 35 226 + 4799 2566 36 338 + 4800 116 58 761 + 4800 2711 88 618 + 4801 348 10 931 + 4802 3915 33 266 + 4803 3149 6 622 + 4803 2932 74 255 + 4804 2219 95 354 + 4805 2768 33 675 + 4806 4942 81 956 + 4807 4341 47 509 + 4808 3147 43 458 + 4808 421 6 614 + 4809 90 19 330 + 4810 2901 11 914 + 4811 4607 36 817 + 4811 577 92 656 + 4812 3498 15 785 + 4812 4179 24 42 + 4813 4925 99 249 + 4814 3168 4 291 + 4815 2198 60 673 + 4815 4245 42 476 + 4816 1425 86 9 + 4816 1956 98 238 + 4817 4399 61 937 + 4818 4143 69 603 + 4819 1506 4 932 + 4819 809 63 9 + 4820 81 84 325 + 4820 2783 6 812 + 4821 686 37 704 + 4821 1006 55 591 + 4822 3896 30 428 + 4822 100 25 240 + 4823 3868 44 964 + 4824 3158 8 583 + 4824 3442 71 117 + 4825 451 91 899 + 4826 3955 79 584 + 4827 3181 83 466 + 4827 4499 87 387 + 4828 3449 90 158 + 4829 412 41 932 + 4830 409 72 829 + 4831 1715 44 345 + 4831 804 98 596 + 4832 2219 49 790 + 4832 3452 29 727 + 4833 11 27 43 + 4833 2348 47 218 + 4834 1701 70 32 + 4835 2067 96 554 + 4836 3940 31 587 + 4837 3810 6 896 + 4837 2985 2 508 + 4838 471 15 118 + 4838 2535 21 718 + 4839 2030 47 497 + 4839 4383 28 734 + 4840 877 22 520 + 4840 95 61 522 + 4841 4608 1 684 + 4841 1219 17 479 + 4842 3803 20 16 + 4843 4026 91 311 + 4843 778 60 911 + 4844 2047 27 658 + 4844 332 52 591 + 4845 136 87 466 + 4845 513 92 76 + 4846 2925 34 333 + 4846 1576 14 50 + 4847 1221 96 708 + 4847 198 1 953 + 4847 2218 55 70 + 4848 4738 36 474 + 4848 2336 93 65 + 4849 1302 72 977 + 4849 2039 58 449 + 4849 1851 35 140 + 4849 3412 89 798 + 4850 1737 92 726 + 4850 3178 46 366 + 4850 4388 62 796 + 4851 4048 51 146 + 4851 4246 7 573 + 4851 2394 73 228 + 4852 1136 72 689 + 4852 2551 30 556 + 4852 3371 75 844 + 4852 5 46 569 + 4853 2347 56 658 + 4854 3003 31 478 + 4854 4619 63 621 + 4854 3456 77 712 + 4854 3418 55 826 + 4855 600 82 500 + 4855 3040 69 543 + 4855 2470 44 83 + 4856 1244 13 789 + 4857 2603 74 549 + 4857 425 23 938 + 4857 2308 73 966 + 4857 2357 77 700 + 4858 2377 45 310 + 4858 955 39 507 + 4858 2854 95 789 + 4859 2490 42 918 + 4860 3414 48 810 + 4860 4042 9 121 + 4860 4105 82 41 + 4860 4637 88 753 + 4861 69 35 447 + 4862 1121 49 519 + 4862 2644 57 292 + 4862 1437 11 816 + 4862 2328 33 173 + 4863 4654 87 291 + 4863 933 26 304 + 4864 4907 58 443 + 4864 3143 85 8 + 4865 2056 48 567 + 4865 3866 84 80 + 4865 149 57 29 + 4865 3558 62 665 + 4866 1030 100 502 + 4866 931 68 784 + 4867 955 96 177 + 4867 1192 65 240 + 4867 2857 14 317 + 4868 1193 26 848 + 4868 3474 48 852 + 4868 2661 93 982 + 4869 4909 50 958 + 4869 4675 44 179 + 4869 34 44 597 + 4869 343 2 128 + 4870 25 93 419 + 4870 4605 30 553 + 4870 3756 1 463 + 4870 766 45 697 + 4871 1745 35 595 + 4871 4354 54 162 + 4872 571 56 539 + 4872 1574 15 383 + 4872 4251 88 112 + 4872 990 86 229 + 4873 2630 63 489 + 4873 690 46 817 + 4874 3352 26 678 + 4875 3758 41 153 + 4875 2338 64 803 + 4875 2811 67 196 + 4876 4 51 78 + 4876 1047 34 657 + 4877 807 12 42 + 4878 1808 50 398 + 4878 99 90 692 + 4879 2263 37 849 + 4879 2173 9 417 + 4879 3324 11 568 + 4880 2260 59 84 + 4880 2951 79 557 + 4880 2574 81 361 + 4880 2068 68 19 + 4881 3775 8 524 + 4881 4055 61 900 + 4882 2464 29 354 + 4882 986 61 24 + 4883 1389 34 991 + 4883 3138 62 659 + 4884 1594 27 186 + 4884 4229 95 483 + 4885 4544 60 20 + 4886 4021 37 514 + 4887 4565 92 77 + 4887 1490 2 711 + 4887 4745 2 556 + 4887 921 62 941 + 4888 1724 8 672 + 4888 2455 99 956 + 4888 4649 15 762 + 4888 2648 21 354 + 4889 3691 85 169 + 4890 238 4 644 + 4890 4651 61 734 + 4891 2464 71 461 + 4892 743 13 110 + 4892 4523 79 687 + 4893 83 90 464 + 4893 4276 89 172 + 4893 4860 53 63 + 4893 3447 81 728 + 4894 4481 33 46 + 4894 1995 11 472 + 4894 496 96 240 + 4894 1155 25 965 + 4895 1904 14 702 + 4895 4710 42 198 + 4895 2039 87 985 + 4896 1552 100 977 + 4896 1266 42 340 + 4897 2566 88 810 + 4897 474 95 273 + 4898 2809 48 781 + 4898 357 40 551 + 4899 3353 57 595 + 4899 3298 77 24 + 4900 3997 35 433 + 4900 271 80 355 + 4900 2285 44 821 + 4901 1509 9 274 + 4901 57 16 143 + 4902 577 30 910 + 4902 3591 85 848 + 4903 1032 53 2 + 4903 4016 98 746 + 4903 1795 45 741 + 4904 1862 22 759 + 4905 2646 90 910 + 4905 4603 92 815 + 4905 1409 78 570 + 4905 4914 70 468 + 4906 3472 82 172 + 4906 4494 63 20 + 4906 855 100 561 + 4906 1629 57 333 + 4907 2340 14 714 + 4908 3718 48 58 + 4908 2080 97 33 + 4909 1858 78 536 + 4909 2896 44 775 + 4910 182 50 127 + 4910 2602 58 429 + 4911 4466 68 406 + 4912 745 83 897 + 4913 562 19 815 + 4913 3213 36 965 + 4913 3535 30 815 + 4913 27 26 558 + 4914 2822 31 151 + 4914 3194 72 65 + 4914 4473 13 979 + 4915 1223 32 508 + 4916 1225 63 722 + 4916 4223 68 599 + 4917 1295 70 704 + 4917 692 41 748 + 4917 325 45 233 + 4918 1433 92 515 + 4918 4309 70 99 + 4919 4251 86 969 + 4920 1024 59 608 + 4920 2922 11 146 + 4920 411 59 13 + 4921 85 29 753 + 4921 889 29 244 + 4922 4258 50 167 + 4923 216 56 341 + 4924 4834 26 515 + 4924 362 51 372 + 4925 1249 21 294 + 4925 3098 73 132 + 4925 2168 6 90 + 4926 377 35 347 + 4927 3231 97 673 + 4928 2125 74 457 + 4928 4213 75 84 + 4929 2515 64 761 + 4930 4205 21 589 + 4931 4782 74 946 + 4931 2280 86 845 + 4931 1942 33 971 + 4932 380 73 498 + 4932 4165 59 346 + 4933 2839 81 36 + 4933 3209 4 143 + 4933 4789 48 142 + 4934 1171 4 747 + 4934 4190 73 353 + 4934 1298 52 163 + 4934 3297 48 275 + 4935 2907 7 919 + 4936 1284 3 138 + 4936 915 60 2 + 4936 1454 11 712 + 4936 690 67 782 + 4937 3599 39 876 + 4937 347 83 985 + 4937 2567 29 617 + 4937 3596 20 21 + 4938 2187 66 76 + 4938 2619 65 787 + 4939 3259 12 191 + 4939 3160 92 836 + 4940 98 31 590 + 4940 4649 46 625 + 4940 4570 56 757 + 4941 4612 51 718 + 4941 2776 66 665 + 4942 2294 36 810 + 4942 831 90 593 + 4942 1908 83 598 + 4943 266 80 719 + 4943 621 87 218 + 4943 1201 87 187 + 4943 598 16 245 + 4943 2074 29 477 + 4943 1189 46 487 + 4944 2072 71 98 + 4944 2204 57 458 + 4944 328 39 765 + 4945 509 93 792 + 4946 2197 16 455 + 4946 12 33 649 + 4946 4846 9 631 + 4946 4762 20 130 + 4946 4312 14 807 + 4947 2045 8 508 + 4947 3558 15 314 + 4947 4308 46 280 + 4947 90 6 360 + 4948 4384 69 456 + 4949 2198 5 369 + 4949 4790 60 443 + 4950 254 34 92 + 4950 3858 55 120 + 4950 469 82 606 + 4950 2233 22 729 + 4950 1012 26 450 + 4950 200 86 760 + 4951 4072 45 606 + 4951 4852 42 191 + 4951 1400 50 665 + 4951 81 21 329 + 4951 4263 96 94 + 4951 513 84 769 + 4952 668 41 914 + 4952 148 16 48 + 4952 417 49 59 + 4952 4483 78 355 + 4952 2041 48 573 + 4952 1087 61 781 + 4953 3711 55 102 + 4953 289 70 144 + 4953 4938 1 934 + 4953 3108 59 889 + 4954 1348 68 754 + 4954 2786 18 373 + 4954 2458 10 259 + 4954 3579 27 608 + 4954 4277 64 926 + 4955 2738 87 16 + 4955 1487 66 337 + 4955 888 96 963 + 4955 3910 16 664 + 4956 291 11 676 + 4956 1009 70 574 + 4957 2057 88 702 + 4957 4988 46 478 + 4957 1831 5 313 + 4957 3137 98 563 + 4957 3857 1 257 + 4957 4061 53 642 + 4958 3582 82 675 + 4958 862 66 53 + 4958 490 25 825 + 4958 776 57 173 + 4959 512 2 456 + 4960 4562 32 72 + 4960 2771 64 256 + 4960 4093 49 110 + 4960 809 49 585 + 4961 2283 38 113 + 4961 3036 68 435 + 4961 2222 5 678 + 4961 3 7 161 + 4961 305 100 753 + 4962 237 95 664 + 4963 2554 37 991 + 4963 862 65 939 + 4964 4630 11 211 + 4964 3311 95 354 + 4964 3669 22 798 + 4964 1097 9 294 + 4964 1872 20 722 + 4965 49 87 314 + 4965 3264 5 516 + 4965 440 85 117 + 4965 3561 51 200 + 4965 358 89 720 + 4965 1622 16 380 + 4966 1161 52 826 + 4966 751 31 5 + 4966 147 35 743 + 4966 2193 2 107 + 4966 4596 20 586 + 4967 1489 27 205 + 4967 294 99 199 + 4968 1976 93 889 + 4968 3284 47 255 + 4968 3479 31 538 + 4968 2487 65 233 + 4968 3998 88 677 + 4968 3645 12 165 + 4969 4191 20 832 + 4969 3700 20 180 + 4970 1983 74 978 + 4970 1820 63 841 + 4970 2301 81 508 + 4971 356 49 767 + 4972 2869 97 432 + 4972 1779 59 440 + 4972 1863 30 721 + 4972 478 61 685 + 4972 2717 19 875 + 4973 1467 50 43 + 4974 694 62 123 + 4974 898 80 262 + 4974 1660 50 397 + 4974 2919 81 750 + 4974 734 28 492 + 4975 68 42 973 + 4975 1124 11 439 + 4975 1985 39 527 + 4975 3420 33 667 + 4975 667 38 457 + 4975 1827 11 189 + 4976 1358 99 772 + 4977 4229 62 554 + 4977 1027 99 839 + 4977 437 18 265 + 4977 4104 10 451 + 4977 4686 92 416 + 4978 1321 50 471 + 4979 287 42 449 + 4979 499 58 29 + 4979 3565 27 573 + 4979 2454 27 954 + 4980 1180 65 415 + 4980 1399 9 101 + 4980 2282 37 613 + 4981 656 71 212 + 4981 1529 55 440 + 4982 4862 49 926 + 4982 3493 70 577 + 4983 2439 45 194 + 4983 2931 71 379 + 4983 4821 15 762 + 4983 349 13 209 + 4983 4898 19 453 + 4984 4473 12 803 + 4984 2327 96 591 + 4984 879 11 672 + 4985 4141 48 942 + 4985 3061 56 255 + 4985 1479 23 900 + 4985 4597 37 122 + 4985 2493 6 900 + 4985 702 55 344 + 4985 59 84 366 + 4986 1167 13 640 + 4986 4925 10 682 + 4986 2740 34 475 + 4987 27 84 826 + 4987 2071 20 261 + 4987 651 65 562 + 4987 3525 48 370 + 4988 108 41 222 + 4988 1414 53 287 + 4988 2533 8 106 + 4988 1369 100 880 + 4989 2128 35 661 + 4989 2035 50 532 + 4989 1380 46 553 + 4989 124 10 647 + 4990 2668 50 212 + 4990 4813 93 3 + 4990 166 73 517 + 4990 3247 96 207 + 4990 3672 66 371 + 4990 3954 81 951 + 4991 442 79 689 + 4991 776 88 899 + 4991 623 31 282 + 4992 4697 23 803 + 4992 1679 31 4 + 4992 3837 20 240 + 4992 4301 52 666 + 4992 2450 6 941 + 4992 2486 31 379 + 4992 4039 80 902 + 4992 3099 41 935 + 4993 2788 32 140 + 4993 3695 41 659 + 4993 3818 63 850 + 4993 2220 29 542 + 4993 4947 70 422 + 4993 1138 18 977 + 4993 4527 23 350 + 4994 2461 87 32 + 4994 1994 14 205 + 4994 3496 51 444 + 4994 3272 53 103 + 4994 119 50 608 + 4994 3680 87 167 + 4994 1391 45 176 + 4994 179 80 320 + 4995 521 71 322 + 4996 2229 51 221 + 4997 4620 76 382 + 4997 2967 75 729 + 4997 549 28 654 + 4997 2696 75 399 + 4997 3519 52 762 + 4997 3261 4 562 + 4998 2734 61 88 + 4998 2788 54 78 + 4998 1377 33 55 + 4998 858 45 411 + 4998 2349 68 165 + 4998 2497 47 155 + 4998 3671 33 789 + 4998 3096 52 971 + 4999 1557 14 710 + 4999 3386 15 339 + 4999 659 46 813 + 4999 985 72 672 + 5000 2885 15 816 + 5000 4900 49 879 + 5000 3070 83 269 + 5000 273 99 25 + 5000 509 48 345 + 5000 808 90 288 + 5000 2694 21 249 +DEMAND + 4501 4 + 4502 150 + 4503 668 + 4504 535 + 4505 285 + 4506 740 + 4507 8 + 4508 567 + 4509 1283 + 4510 961 + 4511 335 + 4512 586 + 4513 1085 + 4514 25 + 4515 877 + 4516 1882 + 4517 469 + 4518 661 + 4519 11 + 4520 464 + 4521 5 + 4522 309 + 4523 248 + 4524 87 + 4525 512 + 4526 620 + 4527 1261 + 4528 1070 + 4529 211 + 4530 630 + 4531 107 + 4532 96 + 4533 486 + 4534 357 + 4535 316 + 4536 295 + 4537 564 + 4538 750 + 4539 2 + 4540 500 + 4541 375 + 4542 1809 + 4543 266 + 4544 1552 + 4545 427 + 4546 136 + 4547 19 + 4548 313 + 4549 509 + 4550 15 + 4551 312 + 4552 269 + 4553 501 + 4554 1145 + 4555 5 + 4556 680 + 4557 1303 + 4558 302 + 4559 495 + 4560 213 + 4561 83 + 4562 5 + 4563 7 + 4564 669 + 4565 18 + 4566 286 + 4567 387 + 4568 393 + 4569 451 + 4570 562 + 4571 286 + 4572 411 + 4573 974 + 4574 120 + 4575 181 + 4576 693 + 4577 204 + 4578 1117 + 4579 376 + 4580 755 + 4581 466 + 4582 156 + 4583 1187 + 4584 709 + 4585 123 + 4586 1242 + 4587 704 + 4588 703 + 4589 51 + 4590 319 + 4591 476 + 4592 13 + 4593 72 + 4594 120 + 4595 28 + 4596 505 + 4597 373 + 4598 243 + 4599 1 + 4600 818 + 4601 1175 + 4602 1013 + 4603 662 + 4604 1058 + 4605 275 + 4606 400 + 4607 537 + 4608 926 + 4609 708 + 4610 124 + 4611 372 + 4612 5 + 4613 511 + 4614 595 + 4615 240 + 4616 328 + 4617 187 + 4618 20 + 4619 1109 + 4620 423 + 4621 210 + 4622 24 + 4623 1041 + 4624 40 + 4625 1668 + 4626 1592 + 4627 373 + 4628 149 + 4629 875 + 4630 760 + 4631 1163 + 4632 18 + 4633 1372 + 4634 1160 + 4635 91 + 4636 13 + 4637 922 + 4638 340 + 4639 504 + 4640 1460 + 4641 425 + 4642 586 + 4643 690 + 4644 112 + 4645 1332 + 4646 20 + 4647 268 + 4648 770 + 4649 839 + 4650 11 + 4651 737 + 4652 336 + 4653 66 + 4654 1849 + 4655 483 + 4656 853 + 4657 1214 + 4658 1 + 4659 592 + 4660 1574 + 4661 84 + 4662 806 + 4663 606 + 4664 9 + 4665 1301 + 4666 605 + 4667 382 + 4668 903 + 4669 295 + 4670 44 + 4671 474 + 4672 729 + 4673 4 + 4674 174 + 4675 632 + 4676 513 + 4677 553 + 4678 27 + 4679 336 + 4680 33 + 4681 143 + 4682 561 + 4683 1105 + 4684 939 + 4685 441 + 4686 109 + 4687 315 + 4688 187 + 4689 791 + 4690 520 + 4691 378 + 4692 1028 + 4693 619 + 4694 1623 + 4695 310 + 4696 625 + 4697 630 + 4698 23 + 4699 10 + 4700 1020 + 4701 664 + 4702 326 + 4703 43 + 4704 238 + 4705 1654 + 4706 753 + 4707 393 + 4708 244 + 4709 1164 + 4710 1917 + 4711 18 + 4712 5 + 4713 9 + 4714 237 + 4715 1083 + 4716 268 + 4717 130 + 4718 154 + 4719 416 + 4720 143 + 4721 34 + 4722 694 + 4723 6 + 4724 8 + 4725 669 + 4726 996 + 4727 266 + 4728 53 + 4729 400 + 4730 829 + 4731 798 + 4732 6 + 4733 817 + 4734 298 + 4735 442 + 4736 3 + 4737 861 + 4738 769 + 4739 26 + 4740 792 + 4741 962 + 4742 557 + 4743 539 + 4744 645 + 4745 442 + 4746 795 + 4747 6 + 4748 284 + 4749 667 + 4750 587 + 4751 16 + 4752 1663 + 4753 296 + 4754 569 + 4755 883 + 4756 3 + 4757 450 + 4758 258 + 4759 416 + 4760 551 + 4761 532 + 4762 568 + 4763 1450 + 4764 158 + 4765 584 + 4766 1087 + 4767 84 + 4768 147 + 4769 349 + 4770 456 + 4771 626 + 4772 7 + 4773 8 + 4774 1255 + 4775 8 + 4776 780 + 4777 710 + 4778 13 + 4779 11 + 4780 406 + 4781 438 + 4782 415 + 4783 52 + 4784 258 + 4785 238 + 4786 201 + 4787 296 + 4788 1360 + 4789 762 + 4790 936 + 4791 313 + 4792 598 + 4793 576 + 4794 915 + 4795 301 + 4796 135 + 4797 1025 + 4798 502 + 4799 776 + 4800 897 + 4801 15 + 4802 476 + 4803 759 + 4804 46 + 4805 271 + 4806 163 + 4807 883 + 4808 4 + 4809 292 + 4810 1850 + 4811 600 + 4812 3 + 4813 9 + 4814 13 + 4815 653 + 4816 423 + 4817 103 + 4818 4 + 4819 8 + 4820 67 + 4821 369 + 4822 205 + 4823 197 + 4824 700 + 4825 764 + 4826 982 + 4827 7 + 4828 1199 + 4829 1588 + 4830 1708 + 4831 579 + 4832 15 + 4833 1397 + 4834 1131 + 4835 264 + 4836 133 + 4837 179 + 4838 381 + 4839 340 + 4840 408 + 4841 893 + 4842 6 + 4843 569 + 4844 565 + 4845 223 + 4846 264 + 4847 87 + 4848 549 + 4849 231 + 4850 256 + 4851 247 + 4852 53 + 4853 529 + 4854 276 + 4855 1039 + 4856 1348 + 4857 4 + 4858 128 + 4859 10 + 4860 325 + 4861 98 + 4862 594 + 4863 427 + 4864 543 + 4865 6 + 4866 262 + 4867 211 + 4868 995 + 4869 1268 + 4870 1 + 4871 2 + 4872 108 + 4873 320 + 4874 1013 + 4875 1252 + 4876 428 + 4877 510 + 4878 13 + 4879 1459 + 4880 594 + 4881 20 + 4882 613 + 4883 560 + 4884 251 + 4885 12 + 4886 1023 + 4887 116 + 4888 186 + 4889 247 + 4890 100 + 4891 98 + 4892 1012 + 4893 1292 + 4894 138 + 4895 1555 + 4896 157 + 4897 13 + 4898 424 + 4899 17 + 4900 157 + 4901 707 + 4902 65 + 4903 364 + 4904 881 + 4905 770 + 4906 47 + 4907 314 + 4908 244 + 4909 706 + 4910 1571 + 4911 539 + 4912 6 + 4913 1057 + 4914 1669 + 4915 6 + 4916 1703 + 4917 30 + 4918 6 + 4919 406 + 4920 774 + 4921 10 + 4922 394 + 4923 716 + 4924 1055 + 4925 992 + 4926 380 + 4927 8 + 4928 1217 + 4929 36 + 4930 251 + 4931 217 + 4932 1274 + 4933 568 + 4934 958 + 4935 8 + 4936 1 + 4937 538 + 4938 204 + 4939 315 + 4940 713 + 4941 261 + 4942 15 + 4943 10 + 4944 1 + 4945 298 + 4946 875 + 4947 227 + 4948 1229 + 4949 712 + 4950 176 + 4951 985 + 4952 332 + 4953 484 + 4954 920 + 4955 581 + 4956 881 + 4957 154 + 4958 1138 + 4959 6 + 4960 789 + 4961 1528 + 4962 415 + 4963 471 + 4964 2 + 4965 1008 + 4966 361 + 4967 1049 + 4968 885 + 4969 151 + 4970 204 + 4971 396 + 4972 477 + 4973 11 + 4974 494 + 4975 514 + 4976 1155 + 4977 991 + 4978 12 + 4979 576 + 4980 402 + 4981 1074 + 4982 226 + 4983 543 + 4984 384 + 4985 228 + 4986 299 + 4987 919 + 4988 508 + 4989 129 + 4990 98 + 4991 205 + 4992 434 + 4993 853 + 4994 769 + 4995 314 + 4996 1138 + 4997 20 + 4998 1 + 4999 465 + 5000 121 +END diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/lseu.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/lseu.mps new file mode 100644 index 000000000..00e6b5a53 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/lseu.mps @@ -0,0 +1,371 @@ +*NAME: lseu +*ROWS: 28 +*COLUMNS: 89 +*INTEGER: 89 +*NONZERO: 309 +*BEST SOLN: 1120 (opt) +*LP SOLN: 834.68 +*SOURCE: C. E. Lemke and K. Spielberg +* Ellis L. Johnson and Uwe H. Suhl +* John J. Forrest (IBM) +*APPLICATION: unknown +*COMMENTS: pure 0/1 IP +* +* +NAME LSEU +ROWS + N R100 + L R101 + L R102 + L R103 + L R104 + L R105 + L R106 + L R107 + L R108 + L R109 + L R110 + L R111 + L R112 + L R113 + L R114 + L R115 + L R116 + L R117 + L R118 + L R119 + L R120 + L R121 + L R122 + L R123 + L R124 + L R125 + L R126 + L R127 + L R128 +COLUMNS + MARK0000 'MARKER' 'INTORG' + C101 R100 7 R119 525 + C101 R120 -525 R122 -525 + C101 R123 -525 + C102 R100 10 R119 500 + C102 R120 -500 R122 -500 + C102 R123 -500 + C103 R100 179 R101 1 + C103 R119 475 R120 -475 + C103 R124 -475 R125 -475 + C104 R100 186 R101 1 + C104 R119 475 R120 -475 + C104 R122 -475 R123 -475 + C105 R100 179 R101 1 + C105 R119 475 R120 -475 + C105 R122 -190 R123 -190 + C105 R124 -285 R125 -285 + C106 R102 1 R118 -450 + C107 R102 1 R124 -450 + C107 R125 -450 + C108 R100 6 R102 1 + C108 R122 -450 R123 -450 + C109 R102 1 R122 -165 + C109 R123 -165 R124 -285 + C109 R125 -285 + C110 R102 1 R124 -150 + C110 R125 -150 + C111 R100 164 R103 1 + C111 R118 -435 + C112 R100 164 R103 1 + C112 R124 -435 R125 -435 + C113 R100 170 R103 1 + C113 R119 435 R120 -435 + C113 R123 -435 + C114 R100 164 R103 1 + C114 R119 435 R120 -435 + C114 R121 -435 + C115 R100 346 R104 1 + C115 R124 -435 R125 -435 + C116 R100 346 R104 1 + C116 R119 435 R120 -435 + C116 R125 -435 + C117 R100 248 R105 1 + C117 R119 435 R120 -435 + C117 R124 -435 R125 -435 + C118 R100 253 R105 1 + C118 R119 435 R120 -435 + C118 R122 -435 R123 -435 + C119 R100 248 R105 1 + C119 R119 435 R120 -435 + C119 R122 -300 R123 -300 + C119 R124 -135 R125 -135 + C120 R100 346 R106 1 + C120 R118 -435 + C121 R100 346 R106 1 + C121 R123 -400 + C122 R100 346 R106 1 + C122 R121 -400 + C123 R100 346 R106 1 + C123 R124 -100 R125 -100 + C123 R127 -300 + C124 R100 160 R107 1 + C124 R124 -400 R125 -400 + C125 R100 161 R107 1 + C125 R122 -400 R123 -400 + C126 R100 160 R107 1 + C126 R122 -115 R123 -115 + C126 R124 -285 R125 -285 + C127 R100 160 R107 1 + C127 R119 425 R120 -425 + C127 R125 -425 + C128 R100 161 R107 1 + C128 R119 425 R120 -425 + C128 R123 -425 + C129 R100 160 R107 1 + C129 R119 425 R120 -425 + C129 R123 -140 R125 -285 + C130 R100 160 R107 1 + C130 R124 -100 R125 -100 + C130 R126 -300 R127 -300 + C131 R100 278 R108 1 + C131 R118 -350 + C132 R100 278 R108 1 + C132 R124 -350 R125 -350 + C133 R100 278 R108 1 + C133 R121 -350 + C134 R100 86 R109 1 + C134 R122 -330 R123 -330 + C135 R100 86 R109 1 + C135 R126 -330 R127 -330 + C136 R100 86 R109 1 + C136 R119 330 R120 -330 + C136 R124 -330 R125 -330 + C137 R100 86 R109 1 + C137 R119 330 R120 -330 + C137 R123 -330 + C138 R100 86 R109 1 + C138 R119 330 R120 -330 + C138 R121 -330 + C139 R100 86 R119 330 + C139 R120 -330 R122 -330 + C139 R123 -330 + C140 R100 188 R110 1 + C140 R122 -330 R123 -330 + C141 R100 188 R110 1 + C141 R119 330 R120 -330 + C141 R124 -330 R125 -330 + C142 R100 188 R110 1 + C142 R119 330 R120 -330 + C142 R121 -330 + C143 R100 85 R111 1 + C143 R122 -325 R123 -325 + C144 R100 85 R111 1 + C144 R126 -325 R127 -325 + C145 R100 85 R111 1 + C145 R119 325 R120 -325 + C145 R124 -325 R125 -325 + C146 R100 85 R111 1 + C146 R119 325 R120 -325 + C146 R123 -325 + C147 R100 85 R111 1 + C147 R119 325 R120 -325 + C147 R121 -325 + C148 R100 78 R112 1 + C148 R122 -300 R123 -300 + C149 R100 78 R112 1 + C149 R119 300 R120 -300 + C149 R124 -300 R125 -300 + C150 R100 78 R112 1 + C150 R119 300 R120 -300 + C150 R121 -300 + C151 R100 78 R112 1 + C151 R128 -300 + C152 R100 78 R113 1 + C152 R122 -300 R123 -300 + C153 R100 78 R113 1 + C153 R126 -300 R127 -300 + C154 R100 78 R113 1 + C154 R119 300 R120 -300 + C154 R124 -300 R125 -300 + C155 R100 78 R113 1 + C155 R119 300 R120 -300 + C155 R123 -300 + C156 R100 78 R113 1 + C156 R119 300 R120 -300 + C156 R121 -300 + C157 R100 171 R114 1 + C157 R122 -300 R123 -300 + C158 R100 171 R114 1 + C158 R126 -300 R127 -300 + C159 R100 171 R114 1 + C159 R119 300 R120 -300 + C159 R123 -300 + C160 R100 171 R114 1 + C160 R119 300 R120 -300 + C160 R121 -300 + C161 R100 163 R115 1 + C161 R119 285 R120 -285 + C161 R124 -285 R125 -285 + C162 R100 163 R115 1 + C162 R119 285 R120 -285 + C162 R122 -285 R123 -285 + C163 R100 163 R115 1 + C163 R128 -285 + C164 R100 69 R116 1 + C164 R119 265 R120 -265 + C164 R124 -265 R125 -265 + C165 R100 69 R116 1 + C165 R119 265 R120 -265 + C165 R122 -265 R123 -265 + C166 R100 183 R117 1 + C166 R118 -230 + C167 R100 183 R117 1 + C167 R124 -230 R125 -230 + C168 R100 183 R117 1 + C168 R119 230 R120 -230 + C168 R125 -230 + C169 R100 183 R117 1 + C169 R119 230 R120 -230 + C169 R123 -230 + C170 R100 49 R119 190 + C170 R120 -190 R122 -190 + C170 R123 -190 + C171 R100 183 R117 1 + C172 R100 258 R118 -200 + C173 R100 517 R118 -400 + C174 R100 250 R126 -200 + C174 R127 -200 + C175 R100 500 R126 -400 + C175 R127 -400 + C176 R100 250 R127 -200 + C177 R100 500 R127 -400 + C178 R100 159 R119 200 + C178 R120 -200 R124 -200 + C178 R125 -200 + C179 R100 318 R119 400 + C179 R120 -400 R124 -400 + C179 R125 -400 + C180 R100 159 R119 200 + C180 R120 -200 R125 -200 + C181 R100 318 R119 400 + C181 R120 -400 R125 -400 + C182 R100 159 R119 200 + C182 R120 -200 R122 -200 + C182 R123 -200 + C183 R100 318 R119 400 + C183 R120 -400 R122 -400 + C183 R123 -400 + C184 R100 159 R119 200 + C184 R120 -200 R123 -200 + C185 R100 318 R119 400 + C185 R120 -400 R123 -400 + C186 R100 114 R119 200 + C186 R120 -200 R121 -200 + C187 R100 228 R119 400 + C187 R120 -400 R121 -400 + C188 R100 159 R128 -200 + C189 R100 318 R128 -400 + MARK0001 'MARKER' 'INTEND' +RHS + RHS R101 1 R102 1 + RHS R103 1 R104 1 + RHS R105 1 R106 1 + RHS R107 1 R108 1 + RHS R109 1 R110 1 + RHS R111 1 R112 1 + RHS R113 1 R114 1 + RHS R115 1 R116 1 + RHS R117 1 R118 -190 + RHS R119 2700 R120 -2600 + RHS R121 -630 R122 -900 + RHS R123 -1656 R124 -335 + RHS R125 -1026 R126 -150 + RHS R127 -500 R128 -270 +BOUNDS + UP ONE C101 1 + UP ONE C102 1 + UP ONE C103 1 + UP ONE C104 1 + UP ONE C105 1 + UP ONE C106 1 + UP ONE C107 1 + UP ONE C108 1 + UP ONE C109 1 + UP ONE C110 1 + UP ONE C111 1 + UP ONE C112 1 + UP ONE C113 1 + UP ONE C114 1 + UP ONE C115 1 + UP ONE C116 1 + UP ONE C117 1 + UP ONE C118 1 + UP ONE C119 1 + UP ONE C120 1 + UP ONE C121 1 + UP ONE C122 1 + UP ONE C123 1 + UP ONE C124 1 + UP ONE C125 1 + UP ONE C126 1 + UP ONE C127 1 + UP ONE C128 1 + UP ONE C129 1 + UP ONE C130 1 + UP ONE C131 1 + UP ONE C132 1 + UP ONE C133 1 + UP ONE C134 1 + UP ONE C135 1 + UP ONE C136 1 + UP ONE C137 1 + UP ONE C138 1 + UP ONE C139 1 + UP ONE C140 1 + UP ONE C141 1 + UP ONE C142 1 + UP ONE C143 1 + UP ONE C144 1 + UP ONE C145 1 + UP ONE C146 1 + UP ONE C147 1 + UP ONE C148 1 + UP ONE C149 1 + UP ONE C150 1 + UP ONE C151 1 + UP ONE C152 1 + UP ONE C153 1 + UP ONE C154 1 + UP ONE C155 1 + UP ONE C156 1 + UP ONE C157 1 + UP ONE C158 1 + UP ONE C159 1 + UP ONE C160 1 + UP ONE C161 1 + UP ONE C162 1 + UP ONE C163 1 + UP ONE C164 1 + UP ONE C165 1 + UP ONE C166 1 + UP ONE C167 1 + UP ONE C168 1 + UP ONE C169 1 + UP ONE C170 1 + UP ONE C171 1 + UP ONE C172 1 + UP ONE C173 1 + UP ONE C174 1 + UP ONE C175 1 + UP ONE C176 1 + UP ONE C177 1 + UP ONE C178 1 + UP ONE C179 1 + UP ONE C180 1 + UP ONE C181 1 + UP ONE C182 1 + UP ONE C183 1 + UP ONE C184 1 + UP ONE C185 1 + UP ONE C186 1 + UP ONE C187 1 + UP ONE C188 1 + UP ONE C189 1 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/nw460.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/nw460.mps new file mode 100644 index 000000000..0b126bd3b --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/nw460.mps @@ -0,0 +1,50 @@ +* +* small test problem from Nemhauser and Wolsey, page 460. +* +* knapsack problem with violated minimal covers +* +NAME nwp460 +ROWS + N obj + L knap1 + L knap2 +COLUMNS + SET00001 'MARKER' 'INTORG' + x1 obj -77.000000 + x1 knap1 774.000000 + x1 knap2 67.000000 + x2 obj -6.000000 + x2 knap1 76.000000 + x2 knap2 27.000000 + x3 obj -3.000000 + x3 knap1 22.000000 + x3 knap2 794.000000 + x4 obj -6.000000 + x4 knap1 42.000000 + x4 knap2 53.000000 + x5 obj -33.000000 + x5 knap1 21.000000 + x5 knap2 234.000000 + x6 obj -13.000000 + x6 knap1 760.000000 + x6 knap2 32.000000 + x7 obj -110.000000 + x7 knap1 818.000000 + x7 knap2 797.000000 + x8 obj -21.000000 + x8 knap1 62.000000 + x8 knap2 97.000000 + x9 obj -47.000000 + x9 knap1 785.000000 + x9 knap2 435.000000 +RHS + RHS knap1 1500.000000 + RHS knap2 1500.000000 +BOUNDS + BV ONE x1 1.000000 + BV ONE x2 1.000000 + BV ONE x3 1.000000 + BV ONE x4 1.000000 + BV ONE x5 1.000000 + BV ONE x6 1.000000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0033.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0033.mps new file mode 100644 index 000000000..7237e2594 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0033.mps @@ -0,0 +1,152 @@ +*NAME: p0033 +*ROWS: 16 +*COLUMNS: 33 +*INTEGER: 33 +*NONZERO: 98 +*BEST SOLN: 3089 (opt) +*LP SOLN: 2520.57 +*SOURCE: Crowder-Johnson-Padberg test set +* +* E. Andrew Boyd (Rice University) +*APPLICATION: unknown +*COMMENTS: pure 0/1 IP +* 5 SOS constraints +* +NAME P0033 +ROWS + N R100 + L R114 + L R115 + L R116 + L R117 + L R118 + L R119 + L R120 + L R121 + L R122 + L R123 + L R124 + L R125 + L R126 + L R127 + L R128 + L ZBESTROW +COLUMNS + MARK0000 'MARKER' 'INTORG' + C157 R100 171 R114 1 + C157 R122 -300 R123 -300 + C158 R100 171 R114 1 + C158 R126 -300 R127 -300 + C159 R100 171 R114 1 + C159 R119 300 R120 -300 + C159 R123 -300 + C160 R100 171 R114 1 + C160 R119 300 R120 -300 + C160 R121 -300 + C161 R100 163 R115 1 + C161 R119 285 R120 -285 + C161 R124 -285 R125 -285 + C162 R100 162 R115 1 + C162 R119 285 R120 -285 + C162 R122 -285 R123 -285 + C163 R100 163 R115 1 + C163 R128 -285 + C164 R100 69 R116 1 + C164 R119 265 R120 -265 + C164 R124 -265 R125 -265 + C165 R100 69 R116 1 + C165 R119 265 R120 -265 + C165 R122 -265 R123 -265 + C166 R100 183 R117 1 + C166 R118 -230 + C167 R100 183 R117 1 + C167 R124 -230 R125 -230 + C168 R100 183 R117 1 + C168 R119 230 R120 -230 + C168 R125 -230 + C169 R100 183 R117 1 + C169 R119 230 R120 -230 + C169 R123 -230 + C170 R100 49 R119 190 + C170 R120 -190 R122 -190 + C170 R123 -190 + C171 R100 183 R117 1 + C172 R100 258 R118 -200 + C173 R100 517 R118 -400 + C174 R100 250 R126 -200 + C174 R127 -200 + C175 R100 500 R126 -400 + C175 R127 -400 + C176 R100 250 R127 -200 + C177 R100 500 R127 -400 + C178 R100 159 R119 200 + C178 R120 -200 R124 -200 + C178 R125 -200 + C179 R100 318 R119 400 + C179 R120 -400 R124 -400 + C179 R125 -400 + C180 R100 159 R119 200 + C180 R120 -200 R125 -200 + C181 R100 318 R119 400 + C181 R120 -400 R125 -400 + C182 R100 159 R119 200 + C182 R120 -200 R122 -200 + C182 R123 -200 + C183 R100 318 R119 400 + C183 R120 -400 R122 -400 + C183 R123 -400 + C184 R100 159 R119 200 + C184 R120 -200 R123 -200 + C185 R100 318 R119 400 + C185 R120 -400 R123 -400 + C186 R100 114 R119 200 + C186 R120 -200 R121 -200 + C187 R100 228 R119 400 + C187 R120 -400 R121 -400 + C188 R100 159 R128 -200 + C189 R100 318 R128 -400 + MARK0001 'MARKER' 'INTEND' +RHS + RHS R114 1 R115 1 + RHS R116 1 R117 1 + RHS R118 -5 R119 2700 + RHS R120 -2600 R121 -100 + RHS R122 -900 R123 -1656 + RHS R124 -335 R125 -1026 + RHS R126 -5 R127 -500 + RHS R128 -270 +BOUNDS + UP ONE C157 1 + UP ONE C158 1 + UP ONE C159 1 + UP ONE C160 1 + UP ONE C161 1 + UP ONE C162 1 + UP ONE C163 1 + UP ONE C164 1 + UP ONE C165 1 + UP ONE C166 1 + UP ONE C167 1 + UP ONE C168 1 + UP ONE C169 1 + UP ONE C170 1 + UP ONE C171 1 + UP ONE C172 1 + UP ONE C173 1 + UP ONE C174 1 + UP ONE C175 1 + UP ONE C176 1 + UP ONE C177 1 + UP ONE C178 1 + UP ONE C179 1 + UP ONE C180 1 + UP ONE C181 1 + UP ONE C182 1 + UP ONE C183 1 + UP ONE C184 1 + UP ONE C185 1 + UP ONE C186 1 + UP ONE C187 1 + UP ONE C188 1 + UP ONE C189 1 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0201.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0201.mps new file mode 100644 index 000000000..41e7683f8 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0201.mps @@ -0,0 +1,1513 @@ +*NAME: p0201 +*ROWS: 133 +*COLUMNS: 201 +*INTEGER: 201 +*NONZERO: 1923 +*BEST SOLN: 7615 (opt) +*LP SOLN: 6875.0 +*SOURCE: Crowder-Johnson-Padberg test set +* +* E. Andrew Boyd (Rice University) +*APPLICATION: unknown +*COMMENTS: pure 0/1 IP +* 26 SOS constraints +* +NAME P0201 +ROWS + N R1001 + L R1002 + L R1003 + L R1004 + L R1005 + L R1006 + L R1007 + L R1008 + L R1009 + L R1010 + L R1011 + L R1012 + L R1013 + L R1014 + L R1015 + L R1016 + L R1017 + L R1018 + L R1019 + L R1020 + L R1021 + L R1022 + L R1023 + L R1024 + L R1025 + L R1026 + L R1027 + L R1028 + L R1029 + L R1030 + L R1031 + L R1032 + L R1033 + L R1034 + L R1035 + L R1036 + L R1037 + L R1038 + L R1039 + L R1040 + L R1041 + L R1042 + L R1043 + L R1044 + L R1045 + L R1046 + L R1047 + L R1048 + L R1049 + L R1050 + L R1051 + L R1052 + L R1053 + L R1054 + L R1055 + L R1056 + L R1057 + L R1058 + L R1059 + L R1060 + L R1061 + L R1062 + L R1063 + L R1064 + L R1065 + L R1066 + L R1067 + L R1068 + L R1069 + L R1070 + L R1071 + L R1072 + L R1073 + L R1074 + L R1075 + L R1076 + L R1077 + L R1078 + L R1079 + L R1080 + L R1081 + L R1082 + L R1083 + L R1084 + L R1085 + L R1086 + L R1087 + L R1088 + L R1089 + L R1090 + L R1091 + L R1092 + L R1093 + L R1094 + L R1095 + L R1096 + L R1097 + L R1098 + L R1099 + L R1100 + L R1101 + L R1102 + L R1103 + L R1104 + L R1105 + L R1106 + L R1107 + L R1108 + L R1109 + L R1110 + L R1111 + L R1112 + L R1113 + L R1114 + L R1115 + L R1116 + L R1117 + L R1118 + L R1119 + L R1120 + L R1121 + L R1122 + L R1123 + L R1124 + L R1125 + L R1126 + L R1127 + L R1128 + L R1129 + L R1130 + L R1131 + L R1132 + L R1133 + L R1134 +COLUMNS + MARK0000 'MARKER' 'INTORG' + C1001 R1001 50 R1002 1 + C1001 R1045 -1 R1048 -1 + C1001 R1051 -1 R1054 -1 + C1001 R1057 -1 R1060 -1 + C1001 R1063 -1 R1066 -1 + C1001 R1069 -1 R1072 -1 + C1002 R1001 100 R1002 2 + C1002 R1045 -2 R1048 -2 + C1002 R1051 -2 R1054 -2 + C1002 R1057 -2 R1060 -2 + C1002 R1063 -2 R1066 -2 + C1002 R1069 -2 R1072 -2 + C1003 R1001 200 R1002 4 + C1003 R1045 -4 R1048 -4 + C1003 R1051 -4 R1054 -4 + C1003 R1057 -4 R1060 -4 + C1003 R1063 -4 R1066 -4 + C1003 R1069 -4 R1072 -4 + C1004 R1001 400 R1002 8 + C1004 R1045 -8 R1048 -8 + C1004 R1051 -8 R1054 -8 + C1004 R1057 -8 R1060 -8 + C1004 R1063 -8 R1066 -8 + C1004 R1069 -8 R1072 -8 + C1005 R1001 800 R1002 16 + C1005 R1045 -16 R1048 -16 + C1005 R1051 -16 R1054 -16 + C1005 R1057 -16 R1060 -16 + C1005 R1063 -16 R1066 -16 + C1005 R1069 -16 R1072 -16 + C1006 R1001 1600 R1002 32 + C1006 R1045 -32 R1048 -32 + C1006 R1051 -32 R1054 -32 + C1006 R1057 -32 R1060 -32 + C1006 R1063 -32 R1066 -32 + C1006 R1069 -32 R1072 -32 + C1007 R1001 3200 R1002 64 + C1007 R1045 -64 R1048 -64 + C1007 R1051 -64 R1054 -64 + C1007 R1057 -64 R1060 -64 + C1007 R1063 -64 R1066 -64 + C1007 R1069 -64 R1072 -64 + C1008 R1001 50 R1003 1 + C1008 R1046 -1 R1049 -1 + C1008 R1052 -1 R1055 -1 + C1008 R1058 -1 R1061 -1 + C1008 R1064 -1 R1067 -1 + C1008 R1070 -1 R1073 -1 + C1009 R1001 100 R1003 2 + C1009 R1046 -2 R1049 -2 + C1009 R1052 -2 R1055 -2 + C1009 R1058 -2 R1061 -2 + C1009 R1064 -2 R1067 -2 + C1009 R1070 -2 R1073 -2 + C1010 R1001 200 R1003 4 + C1010 R1046 -4 R1049 -4 + C1010 R1052 -4 R1055 -4 + C1010 R1058 -4 R1061 -4 + C1010 R1064 -4 R1067 -4 + C1010 R1070 -4 R1073 -4 + C1011 R1001 400 R1003 8 + C1011 R1046 -8 R1049 -8 + C1011 R1052 -8 R1055 -8 + C1011 R1058 -8 R1061 -8 + C1011 R1064 -8 R1067 -8 + C1011 R1070 -8 R1073 -8 + C1012 R1001 800 R1003 16 + C1012 R1046 -16 R1049 -16 + C1012 R1052 -16 R1055 -16 + C1012 R1058 -16 R1061 -16 + C1012 R1064 -16 R1067 -16 + C1012 R1070 -16 R1073 -16 + C1013 R1001 1600 R1003 32 + C1013 R1046 -32 R1049 -32 + C1013 R1052 -32 R1055 -32 + C1013 R1058 -32 R1061 -32 + C1013 R1064 -32 R1067 -32 + C1013 R1070 -32 R1073 -32 + C1014 R1001 3200 R1003 64 + C1014 R1046 -64 R1049 -64 + C1014 R1052 -64 R1055 -64 + C1014 R1058 -64 R1061 -64 + C1014 R1064 -64 R1067 -64 + C1014 R1070 -64 R1073 -64 + C1015 R1001 150 R1004 1 + C1015 R1047 -1 R1050 -1 + C1015 R1053 -1 R1056 -1 + C1015 R1059 -1 R1062 -1 + C1015 R1065 -1 R1068 -1 + C1015 R1071 -1 R1074 -1 + C1016 R1001 300 R1004 2 + C1016 R1047 -2 R1050 -2 + C1016 R1053 -2 R1056 -2 + C1016 R1059 -2 R1062 -2 + C1016 R1065 -2 R1068 -2 + C1016 R1071 -2 R1074 -2 + C1017 R1001 600 R1004 4 + C1017 R1047 -4 R1050 -4 + C1017 R1053 -4 R1056 -4 + C1017 R1059 -4 R1062 -4 + C1017 R1065 -4 R1068 -4 + C1017 R1071 -4 R1074 -4 + C1018 R1001 1200 R1004 8 + C1018 R1047 -8 R1050 -8 + C1018 R1053 -8 R1056 -8 + C1018 R1059 -8 R1062 -8 + C1018 R1065 -8 R1068 -8 + C1018 R1071 -8 R1074 -8 + C1019 R1001 2400 R1004 16 + C1019 R1047 -16 R1050 -16 + C1019 R1053 -16 R1056 -16 + C1019 R1059 -16 R1062 -16 + C1019 R1065 -16 R1068 -16 + C1019 R1071 -16 R1074 -16 + C1020 R1001 4800 R1004 32 + C1020 R1047 -32 R1050 -32 + C1020 R1053 -32 R1056 -32 + C1020 R1059 -32 R1062 -32 + C1020 R1065 -32 R1068 -32 + C1020 R1071 -32 R1074 -32 + C1021 R1001 9600 R1004 64 + C1021 R1047 -64 R1050 -64 + C1021 R1053 -64 R1056 -64 + C1021 R1059 -64 R1062 -64 + C1021 R1065 -64 R1068 -64 + C1021 R1071 -64 R1074 -64 + C1022 R1001 500 R1005 1 + C1022 R1006 -1 R1045 -10 + C1022 R1048 -10 R1051 -10 + C1022 R1054 -10 R1057 -10 + C1022 R1060 -10 R1063 -10 + C1022 R1066 -10 R1069 -10 + C1022 R1072 -10 R1075 1 + C1022 R1081 -1 + C1023 R1001 560 R1005 1 + C1023 R1006 -1 R1045 -10 + C1023 R1048 -10 R1051 -10 + C1023 R1054 -10 R1057 -10 + C1023 R1060 -10 R1063 -10 + C1023 R1066 -10 R1069 -10 + C1023 R1072 -10 R1076 1 + C1023 R1081 -1 + C1024 R1001 600 R1005 1 + C1024 R1006 -1 R1045 -10 + C1024 R1048 -10 R1051 -10 + C1024 R1054 -10 R1057 -10 + C1024 R1060 -10 R1063 -10 + C1024 R1066 -10 R1069 -10 + C1024 R1072 -10 R1077 1 + C1024 R1081 -1 + C1025 R1001 560 R1005 1 + C1025 R1006 -1 R1046 -10 + C1025 R1049 -10 R1052 -10 + C1025 R1055 -10 R1058 -10 + C1025 R1061 -10 R1064 -10 + C1025 R1067 -10 R1070 -10 + C1025 R1073 -10 R1075 1 + C1025 R1082 -1 + C1026 R1001 500 R1005 1 + C1026 R1006 -1 R1046 -10 + C1026 R1049 -10 R1052 -10 + C1026 R1055 -10 R1058 -10 + C1026 R1061 -10 R1064 -10 + C1026 R1067 -10 R1070 -10 + C1026 R1073 -10 R1076 1 + C1026 R1082 -1 + C1027 R1001 600 R1005 1 + C1027 R1006 -1 R1046 -10 + C1027 R1049 -10 R1052 -10 + C1027 R1055 -10 R1058 -10 + C1027 R1061 -10 R1064 -10 + C1027 R1067 -10 R1070 -10 + C1027 R1073 -10 R1077 1 + C1027 R1082 -1 + C1028 R1001 850 R1005 1 + C1028 R1006 -1 R1047 -5 + C1028 R1050 -5 R1053 -5 + C1028 R1056 -5 R1059 -5 + C1028 R1062 -5 R1065 -5 + C1028 R1068 -5 R1071 -5 + C1028 R1074 -5 R1075 1 + C1028 R1083 -1 + C1029 R1001 850 R1005 1 + C1029 R1006 -1 R1047 -5 + C1029 R1050 -5 R1053 -5 + C1029 R1056 -5 R1059 -5 + C1029 R1062 -5 R1065 -5 + C1029 R1068 -5 R1071 -5 + C1029 R1074 -5 R1076 1 + C1029 R1083 -1 + C1030 R1001 750 R1005 1 + C1030 R1006 -1 R1047 -5 + C1030 R1050 -5 R1053 -5 + C1030 R1056 -5 R1059 -5 + C1030 R1062 -5 R1065 -5 + C1030 R1068 -5 R1071 -5 + C1030 R1074 -5 R1077 1 + C1030 R1083 -1 + C1031 R1001 500 R1007 1 + C1031 R1008 -1 R1045 -10 + C1031 R1048 -10 R1051 -10 + C1031 R1054 -10 R1057 -10 + C1031 R1060 -10 R1063 -10 + C1031 R1066 -10 R1069 -10 + C1031 R1072 -10 R1078 1 + C1031 R1084 -1 + C1032 R1001 560 R1007 1 + C1032 R1008 -1 R1045 -10 + C1032 R1048 -10 R1051 -10 + C1032 R1054 -10 R1057 -10 + C1032 R1060 -10 R1063 -10 + C1032 R1066 -10 R1069 -10 + C1032 R1072 -10 R1079 1 + C1032 R1084 -1 + C1033 R1001 600 R1007 1 + C1033 R1008 -1 R1045 -10 + C1033 R1048 -10 R1051 -10 + C1033 R1054 -10 R1057 -10 + C1033 R1060 -10 R1063 -10 + C1033 R1066 -10 R1069 -10 + C1033 R1072 -10 R1080 1 + C1033 R1084 -1 + C1034 R1001 560 R1007 1 + C1034 R1008 -1 R1046 -10 + C1034 R1049 -10 R1052 -10 + C1034 R1055 -10 R1058 -10 + C1034 R1061 -10 R1064 -10 + C1034 R1067 -10 R1070 -10 + C1034 R1073 -10 R1078 1 + C1034 R1085 -1 + C1035 R1001 500 R1007 1 + C1035 R1008 -1 R1046 -10 + C1035 R1049 -10 R1052 -10 + C1035 R1055 -10 R1058 -10 + C1035 R1061 -10 R1064 -10 + C1035 R1067 -10 R1070 -10 + C1035 R1073 -10 R1079 1 + C1035 R1085 -1 + C1036 R1001 600 R1007 1 + C1036 R1008 -1 R1046 -10 + C1036 R1049 -10 R1052 -10 + C1036 R1055 -10 R1058 -10 + C1036 R1061 -10 R1064 -10 + C1036 R1067 -10 R1070 -10 + C1036 R1073 -10 R1080 1 + C1036 R1085 -1 + C1037 R1001 850 R1007 1 + C1037 R1008 -1 R1047 -5 + C1037 R1050 -5 R1053 -5 + C1037 R1056 -5 R1059 -5 + C1037 R1062 -5 R1065 -5 + C1037 R1068 -5 R1071 -5 + C1037 R1074 -5 R1078 1 + C1037 R1086 -1 + C1038 R1001 850 R1007 1 + C1038 R1008 -1 R1047 -5 + C1038 R1050 -5 R1053 -5 + C1038 R1056 -5 R1059 -5 + C1038 R1062 -5 R1065 -5 + C1038 R1068 -5 R1071 -5 + C1038 R1074 -5 R1079 1 + C1038 R1086 -1 + C1039 R1001 750 R1007 1 + C1039 R1008 -1 R1047 -5 + C1039 R1050 -5 R1053 -5 + C1039 R1056 -5 R1059 -5 + C1039 R1062 -5 R1065 -5 + C1039 R1068 -5 R1071 -5 + C1039 R1074 -5 R1080 1 + C1039 R1086 -1 + C1040 R1001 450 R1009 1 + C1040 R1010 -1 R1048 -10 + C1040 R1051 -10 R1054 -10 + C1040 R1057 -10 R1060 -10 + C1040 R1063 -10 R1066 -10 + C1040 R1069 -10 R1072 -10 + C1040 R1081 1 R1087 -1 + C1041 R1001 510 R1009 1 + C1041 R1010 -1 R1048 -10 + C1041 R1051 -10 R1054 -10 + C1041 R1057 -10 R1060 -10 + C1041 R1063 -10 R1066 -10 + C1041 R1069 -10 R1072 -10 + C1041 R1082 1 R1087 -1 + C1042 R1001 550 R1009 1 + C1042 R1010 -1 R1048 -10 + C1042 R1051 -10 R1054 -10 + C1042 R1057 -10 R1060 -10 + C1042 R1063 -10 R1066 -10 + C1042 R1069 -10 R1072 -10 + C1042 R1083 1 R1087 -1 + C1043 R1001 510 R1009 1 + C1043 R1010 -1 R1049 -10 + C1043 R1052 -10 R1055 -10 + C1043 R1058 -10 R1061 -10 + C1043 R1064 -10 R1067 -10 + C1043 R1070 -10 R1073 -10 + C1043 R1081 1 R1088 -1 + C1044 R1001 450 R1009 1 + C1044 R1010 -1 R1049 -10 + C1044 R1052 -10 R1055 -10 + C1044 R1058 -10 R1061 -10 + C1044 R1064 -10 R1067 -10 + C1044 R1070 -10 R1073 -10 + C1044 R1082 1 R1088 -1 + C1045 R1001 550 R1009 1 + C1045 R1010 -1 R1049 -10 + C1045 R1052 -10 R1055 -10 + C1045 R1058 -10 R1061 -10 + C1045 R1064 -10 R1067 -10 + C1045 R1070 -10 R1073 -10 + C1045 R1083 1 R1088 -1 + C1046 R1001 775 R1009 1 + C1046 R1010 -1 R1050 -5 + C1046 R1053 -5 R1056 -5 + C1046 R1059 -5 R1062 -5 + C1046 R1065 -5 R1068 -5 + C1046 R1071 -5 R1074 -5 + C1046 R1081 1 R1089 -1 + C1047 R1001 775 R1009 1 + C1047 R1010 -1 R1050 -5 + C1047 R1053 -5 R1056 -5 + C1047 R1059 -5 R1062 -5 + C1047 R1065 -5 R1068 -5 + C1047 R1071 -5 R1074 -5 + C1047 R1082 1 R1089 -1 + C1048 R1001 675 R1009 1 + C1048 R1010 -1 R1050 -5 + C1048 R1053 -5 R1056 -5 + C1048 R1059 -5 R1062 -5 + C1048 R1065 -5 R1068 -5 + C1048 R1071 -5 R1074 -5 + C1048 R1083 1 R1089 -1 + C1049 R1001 450 R1011 1 + C1049 R1012 -1 R1048 -10 + C1049 R1051 -10 R1054 -10 + C1049 R1057 -10 R1060 -10 + C1049 R1063 -10 R1066 -10 + C1049 R1069 -10 R1072 -10 + C1049 R1084 1 R1090 -1 + C1050 R1001 510 R1011 1 + C1050 R1012 -1 R1048 -10 + C1050 R1051 -10 R1054 -10 + C1050 R1057 -10 R1060 -10 + C1050 R1063 -10 R1066 -10 + C1050 R1069 -10 R1072 -10 + C1050 R1085 1 R1090 -1 + C1051 R1001 550 R1011 1 + C1051 R1012 -1 R1048 -10 + C1051 R1051 -10 R1054 -10 + C1051 R1057 -10 R1060 -10 + C1051 R1063 -10 R1066 -10 + C1051 R1069 -10 R1072 -10 + C1051 R1086 1 R1090 -1 + C1052 R1001 510 R1011 1 + C1052 R1012 -1 R1049 -10 + C1052 R1052 -10 R1055 -10 + C1052 R1058 -10 R1061 -10 + C1052 R1064 -10 R1067 -10 + C1052 R1070 -10 R1073 -10 + C1052 R1084 1 R1091 -1 + C1053 R1001 450 R1011 1 + C1053 R1012 -1 R1049 -10 + C1053 R1052 -10 R1055 -10 + C1053 R1058 -10 R1061 -10 + C1053 R1064 -10 R1067 -10 + C1053 R1070 -10 R1073 -10 + C1053 R1085 1 R1091 -1 + C1054 R1001 550 R1011 1 + C1054 R1012 -1 R1049 -10 + C1054 R1052 -10 R1055 -10 + C1054 R1058 -10 R1061 -10 + C1054 R1064 -10 R1067 -10 + C1054 R1070 -10 R1073 -10 + C1054 R1086 1 R1091 -1 + C1055 R1001 775 R1011 1 + C1055 R1012 -1 R1050 -5 + C1055 R1053 -5 R1056 -5 + C1055 R1059 -5 R1062 -5 + C1055 R1065 -5 R1068 -5 + C1055 R1071 -5 R1074 -5 + C1055 R1084 1 R1092 -1 + C1056 R1001 775 R1011 1 + C1056 R1012 -1 R1050 -5 + C1056 R1053 -5 R1056 -5 + C1056 R1059 -5 R1062 -5 + C1056 R1065 -5 R1068 -5 + C1056 R1071 -5 R1074 -5 + C1056 R1085 1 R1092 -1 + C1057 R1001 675 R1011 1 + C1057 R1012 -1 R1050 -5 + C1057 R1053 -5 R1056 -5 + C1057 R1059 -5 R1062 -5 + C1057 R1065 -5 R1068 -5 + C1057 R1071 -5 R1074 -5 + C1057 R1086 1 R1092 -1 + C1058 R1001 400 R1013 1 + C1058 R1014 -1 R1051 -10 + C1058 R1054 -10 R1057 -10 + C1058 R1060 -10 R1063 -10 + C1058 R1066 -10 R1069 -10 + C1058 R1072 -10 R1087 1 + C1058 R1093 -1 + C1059 R1001 460 R1013 1 + C1059 R1014 -1 R1051 -10 + C1059 R1054 -10 R1057 -10 + C1059 R1060 -10 R1063 -10 + C1059 R1066 -10 R1069 -10 + C1059 R1072 -10 R1088 1 + C1059 R1093 -1 + C1060 R1001 500 R1013 1 + C1060 R1014 -1 R1051 -10 + C1060 R1054 -10 R1057 -10 + C1060 R1060 -10 R1063 -10 + C1060 R1066 -10 R1069 -10 + C1060 R1072 -10 R1089 1 + C1060 R1093 -1 + C1061 R1001 460 R1013 1 + C1061 R1014 -1 R1052 -10 + C1061 R1055 -10 R1058 -10 + C1061 R1061 -10 R1064 -10 + C1061 R1067 -10 R1070 -10 + C1061 R1073 -10 R1087 1 + C1061 R1094 -1 + C1062 R1001 400 R1013 1 + C1062 R1014 -1 R1052 -10 + C1062 R1055 -10 R1058 -10 + C1062 R1061 -10 R1064 -10 + C1062 R1067 -10 R1070 -10 + C1062 R1073 -10 R1088 1 + C1062 R1094 -1 + C1063 R1001 500 R1013 1 + C1063 R1014 -1 R1052 -10 + C1063 R1055 -10 R1058 -10 + C1063 R1061 -10 R1064 -10 + C1063 R1067 -10 R1070 -10 + C1063 R1073 -10 R1089 1 + C1063 R1094 -1 + C1064 R1001 700 R1013 1 + C1064 R1014 -1 R1053 -5 + C1064 R1056 -5 R1059 -5 + C1064 R1062 -5 R1065 -5 + C1064 R1068 -5 R1071 -5 + C1064 R1074 -5 R1087 1 + C1064 R1095 -1 + C1065 R1001 700 R1013 1 + C1065 R1014 -1 R1053 -5 + C1065 R1056 -5 R1059 -5 + C1065 R1062 -5 R1065 -5 + C1065 R1068 -5 R1071 -5 + C1065 R1074 -5 R1088 1 + C1065 R1095 -1 + C1066 R1001 600 R1013 1 + C1066 R1014 -1 R1053 -5 + C1066 R1056 -5 R1059 -5 + C1066 R1062 -5 R1065 -5 + C1066 R1068 -5 R1071 -5 + C1066 R1074 -5 R1089 1 + C1066 R1095 -1 + C1067 R1001 400 R1015 1 + C1067 R1016 -1 R1051 -10 + C1067 R1054 -10 R1057 -10 + C1067 R1060 -10 R1063 -10 + C1067 R1066 -10 R1069 -10 + C1067 R1072 -10 R1090 1 + C1067 R1096 -1 + C1068 R1001 460 R1015 1 + C1068 R1016 -1 R1051 -10 + C1068 R1054 -10 R1057 -10 + C1068 R1060 -10 R1063 -10 + C1068 R1066 -10 R1069 -10 + C1068 R1072 -10 R1091 1 + C1068 R1096 -1 + C1069 R1001 500 R1015 1 + C1069 R1016 -1 R1051 -10 + C1069 R1054 -10 R1057 -10 + C1069 R1060 -10 R1063 -10 + C1069 R1066 -10 R1069 -10 + C1069 R1072 -10 R1092 1 + C1069 R1096 -1 + C1070 R1001 460 R1015 1 + C1070 R1016 -1 R1052 -10 + C1070 R1055 -10 R1058 -10 + C1070 R1061 -10 R1064 -10 + C1070 R1067 -10 R1070 -10 + C1070 R1073 -10 R1090 1 + C1070 R1097 -1 + C1071 R1001 400 R1015 1 + C1071 R1016 -1 R1052 -10 + C1071 R1055 -10 R1058 -10 + C1071 R1061 -10 R1064 -10 + C1071 R1067 -10 R1070 -10 + C1071 R1073 -10 R1091 1 + C1071 R1097 -1 + C1072 R1001 500 R1015 1 + C1072 R1016 -1 R1052 -10 + C1072 R1055 -10 R1058 -10 + C1072 R1061 -10 R1064 -10 + C1072 R1067 -10 R1070 -10 + C1072 R1073 -10 R1092 1 + C1072 R1097 -1 + C1073 R1001 700 R1015 1 + C1073 R1016 -1 R1053 -5 + C1073 R1056 -5 R1059 -5 + C1073 R1062 -5 R1065 -5 + C1073 R1068 -5 R1071 -5 + C1073 R1074 -5 R1090 1 + C1073 R1098 -1 + C1074 R1001 700 R1015 1 + C1074 R1016 -1 R1053 -5 + C1074 R1056 -5 R1059 -5 + C1074 R1062 -5 R1065 -5 + C1074 R1068 -5 R1071 -5 + C1074 R1074 -5 R1091 1 + C1074 R1098 -1 + C1075 R1001 600 R1015 1 + C1075 R1016 -1 R1053 -5 + C1075 R1056 -5 R1059 -5 + C1075 R1062 -5 R1065 -5 + C1075 R1068 -5 R1071 -5 + C1075 R1074 -5 R1092 1 + C1075 R1098 -1 + C1076 R1001 350 R1017 1 + C1076 R1018 -1 R1054 -10 + C1076 R1057 -10 R1060 -10 + C1076 R1063 -10 R1066 -10 + C1076 R1069 -10 R1072 -10 + C1076 R1093 1 R1099 -1 + C1077 R1001 410 R1017 1 + C1077 R1018 -1 R1054 -10 + C1077 R1057 -10 R1060 -10 + C1077 R1063 -10 R1066 -10 + C1077 R1069 -10 R1072 -10 + C1077 R1094 1 R1099 -1 + C1078 R1001 450 R1017 1 + C1078 R1018 -1 R1054 -10 + C1078 R1057 -10 R1060 -10 + C1078 R1063 -10 R1066 -10 + C1078 R1069 -10 R1072 -10 + C1078 R1095 1 R1099 -1 + C1079 R1001 410 R1017 1 + C1079 R1018 -1 R1055 -10 + C1079 R1058 -10 R1061 -10 + C1079 R1064 -10 R1067 -10 + C1079 R1070 -10 R1073 -10 + C1079 R1093 1 R1100 -1 + C1080 R1001 350 R1017 1 + C1080 R1018 -1 R1055 -10 + C1080 R1058 -10 R1061 -10 + C1080 R1064 -10 R1067 -10 + C1080 R1070 -10 R1073 -10 + C1080 R1094 1 R1100 -1 + C1081 R1001 450 R1017 1 + C1081 R1018 -1 R1055 -10 + C1081 R1058 -10 R1061 -10 + C1081 R1064 -10 R1067 -10 + C1081 R1070 -10 R1073 -10 + C1081 R1095 1 R1100 -1 + C1082 R1001 625 R1017 1 + C1082 R1018 -1 R1056 -5 + C1082 R1059 -5 R1062 -5 + C1082 R1065 -5 R1068 -5 + C1082 R1071 -5 R1074 -5 + C1082 R1093 1 R1101 -1 + C1083 R1001 625 R1017 1 + C1083 R1018 -1 R1056 -5 + C1083 R1059 -5 R1062 -5 + C1083 R1065 -5 R1068 -5 + C1083 R1071 -5 R1074 -5 + C1083 R1094 1 R1101 -1 + C1084 R1001 525 R1017 1 + C1084 R1018 -1 R1056 -5 + C1084 R1059 -5 R1062 -5 + C1084 R1065 -5 R1068 -5 + C1084 R1071 -5 R1074 -5 + C1084 R1095 1 R1101 -1 + C1085 R1001 350 R1019 1 + C1085 R1020 -1 R1054 -10 + C1085 R1057 -10 R1060 -10 + C1085 R1063 -10 R1066 -10 + C1085 R1069 -10 R1072 -10 + C1085 R1096 1 R1102 -1 + C1086 R1001 410 R1019 1 + C1086 R1020 -1 R1054 -10 + C1086 R1057 -10 R1060 -10 + C1086 R1063 -10 R1066 -10 + C1086 R1069 -10 R1072 -10 + C1086 R1097 1 R1102 -1 + C1087 R1001 450 R1019 1 + C1087 R1020 -1 R1054 -10 + C1087 R1057 -10 R1060 -10 + C1087 R1063 -10 R1066 -10 + C1087 R1069 -10 R1072 -10 + C1087 R1098 1 R1102 -1 + C1088 R1001 410 R1019 1 + C1088 R1020 -1 R1055 -10 + C1088 R1058 -10 R1061 -10 + C1088 R1064 -10 R1067 -10 + C1088 R1070 -10 R1073 -10 + C1088 R1096 1 R1103 -1 + C1089 R1001 350 R1019 1 + C1089 R1020 -1 R1055 -10 + C1089 R1058 -10 R1061 -10 + C1089 R1064 -10 R1067 -10 + C1089 R1070 -10 R1073 -10 + C1089 R1097 1 R1103 -1 + C1090 R1001 450 R1019 1 + C1090 R1020 -1 R1055 -10 + C1090 R1058 -10 R1061 -10 + C1090 R1064 -10 R1067 -10 + C1090 R1070 -10 R1073 -10 + C1090 R1098 1 R1103 -1 + C1091 R1001 625 R1019 1 + C1091 R1020 -1 R1056 -5 + C1091 R1059 -5 R1062 -5 + C1091 R1065 -5 R1068 -5 + C1091 R1071 -5 R1074 -5 + C1091 R1096 1 R1104 -1 + C1092 R1001 625 R1019 1 + C1092 R1020 -1 R1056 -5 + C1092 R1059 -5 R1062 -5 + C1092 R1065 -5 R1068 -5 + C1092 R1071 -5 R1074 -5 + C1092 R1097 1 R1104 -1 + C1093 R1001 525 R1019 1 + C1093 R1020 -1 R1056 -5 + C1093 R1059 -5 R1062 -5 + C1093 R1065 -5 R1068 -5 + C1093 R1071 -5 R1074 -5 + C1093 R1098 1 R1104 -1 + C1094 R1001 300 R1021 1 + C1094 R1022 -1 R1057 -10 + C1094 R1060 -10 R1063 -10 + C1094 R1066 -10 R1069 -10 + C1094 R1072 -10 R1099 1 + C1094 R1105 -1 + C1095 R1001 360 R1021 1 + C1095 R1022 -1 R1057 -10 + C1095 R1060 -10 R1063 -10 + C1095 R1066 -10 R1069 -10 + C1095 R1072 -10 R1100 1 + C1095 R1105 -1 + C1096 R1001 400 R1021 1 + C1096 R1022 -1 R1057 -10 + C1096 R1060 -10 R1063 -10 + C1096 R1066 -10 R1069 -10 + C1096 R1072 -10 R1101 1 + C1096 R1105 -1 + C1097 R1001 360 R1021 1 + C1097 R1022 -1 R1058 -10 + C1097 R1061 -10 R1064 -10 + C1097 R1067 -10 R1070 -10 + C1097 R1073 -10 R1099 1 + C1097 R1106 -1 + C1098 R1001 300 R1021 1 + C1098 R1022 -1 R1058 -10 + C1098 R1061 -10 R1064 -10 + C1098 R1067 -10 R1070 -10 + C1098 R1073 -10 R1100 1 + C1098 R1106 -1 + C1099 R1001 400 R1021 1 + C1099 R1022 -1 R1058 -10 + C1099 R1061 -10 R1064 -10 + C1099 R1067 -10 R1070 -10 + C1099 R1073 -10 R1101 1 + C1099 R1106 -1 + C1100 R1001 550 R1021 1 + C1100 R1022 -1 R1059 -5 + C1100 R1062 -5 R1065 -5 + C1100 R1068 -5 R1071 -5 + C1100 R1074 -5 R1099 1 + C1100 R1107 -1 + C1101 R1001 550 R1021 1 + C1101 R1022 -1 R1059 -5 + C1101 R1062 -5 R1065 -5 + C1101 R1068 -5 R1071 -5 + C1101 R1074 -5 R1100 1 + C1101 R1107 -1 + C1102 R1001 450 R1021 1 + C1102 R1022 -1 R1059 -5 + C1102 R1062 -5 R1065 -5 + C1102 R1068 -5 R1071 -5 + C1102 R1074 -5 R1101 1 + C1102 R1107 -1 + C1103 R1001 300 R1023 1 + C1103 R1024 -1 R1057 -10 + C1103 R1060 -10 R1063 -10 + C1103 R1066 -10 R1069 -10 + C1103 R1072 -10 R1102 1 + C1103 R1108 -1 + C1104 R1001 360 R1023 1 + C1104 R1024 -1 R1057 -10 + C1104 R1060 -10 R1063 -10 + C1104 R1066 -10 R1069 -10 + C1104 R1072 -10 R1103 1 + C1104 R1108 -1 + C1105 R1001 400 R1023 1 + C1105 R1024 -1 R1057 -10 + C1105 R1060 -10 R1063 -10 + C1105 R1066 -10 R1069 -10 + C1105 R1072 -10 R1104 1 + C1105 R1108 -1 + C1106 R1001 360 R1023 1 + C1106 R1024 -1 R1058 -10 + C1106 R1061 -10 R1064 -10 + C1106 R1067 -10 R1070 -10 + C1106 R1073 -10 R1102 1 + C1106 R1109 -1 + C1107 R1001 300 R1023 1 + C1107 R1024 -1 R1058 -10 + C1107 R1061 -10 R1064 -10 + C1107 R1067 -10 R1070 -10 + C1107 R1073 -10 R1103 1 + C1107 R1109 -1 + C1108 R1001 400 R1023 1 + C1108 R1024 -1 R1058 -10 + C1108 R1061 -10 R1064 -10 + C1108 R1067 -10 R1070 -10 + C1108 R1073 -10 R1104 1 + C1108 R1109 -1 + C1109 R1001 550 R1023 1 + C1109 R1024 -1 R1059 -5 + C1109 R1062 -5 R1065 -5 + C1109 R1068 -5 R1071 -5 + C1109 R1074 -5 R1102 1 + C1109 R1110 -1 + C1110 R1001 550 R1023 1 + C1110 R1024 -1 R1059 -5 + C1110 R1062 -5 R1065 -5 + C1110 R1068 -5 R1071 -5 + C1110 R1074 -5 R1103 1 + C1110 R1110 -1 + C1111 R1001 450 R1023 1 + C1111 R1024 -1 R1059 -5 + C1111 R1062 -5 R1065 -5 + C1111 R1068 -5 R1071 -5 + C1111 R1074 -5 R1104 1 + C1111 R1110 -1 + C1112 R1001 250 R1025 1 + C1112 R1026 -1 R1060 -10 + C1112 R1063 -10 R1066 -10 + C1112 R1069 -10 R1072 -10 + C1112 R1105 1 R1111 -1 + C1113 R1001 310 R1025 1 + C1113 R1026 -1 R1060 -10 + C1113 R1063 -10 R1066 -10 + C1113 R1069 -10 R1072 -10 + C1113 R1106 1 R1111 -1 + C1114 R1001 350 R1025 1 + C1114 R1026 -1 R1060 -10 + C1114 R1063 -10 R1066 -10 + C1114 R1069 -10 R1072 -10 + C1114 R1107 1 R1111 -1 + C1115 R1001 310 R1025 1 + C1115 R1026 -1 R1061 -10 + C1115 R1064 -10 R1067 -10 + C1115 R1070 -10 R1073 -10 + C1115 R1105 1 R1112 -1 + C1116 R1001 250 R1025 1 + C1116 R1026 -1 R1061 -10 + C1116 R1064 -10 R1067 -10 + C1116 R1070 -10 R1073 -10 + C1116 R1106 1 R1112 -1 + C1117 R1001 350 R1025 1 + C1117 R1026 -1 R1061 -10 + C1117 R1064 -10 R1067 -10 + C1117 R1070 -10 R1073 -10 + C1117 R1107 1 R1112 -1 + C1118 R1001 475 R1025 1 + C1118 R1026 -1 R1062 -5 + C1118 R1065 -5 R1068 -5 + C1118 R1071 -5 R1074 -5 + C1118 R1105 1 R1113 -1 + C1119 R1001 475 R1025 1 + C1119 R1026 -1 R1062 -5 + C1119 R1065 -5 R1068 -5 + C1119 R1071 -5 R1074 -5 + C1119 R1106 1 R1113 -1 + C1120 R1001 375 R1025 1 + C1120 R1026 -1 R1062 -5 + C1120 R1065 -5 R1068 -5 + C1120 R1071 -5 R1074 -5 + C1120 R1107 1 R1113 -1 + C1121 R1001 250 R1027 1 + C1121 R1028 -1 R1060 -10 + C1121 R1063 -10 R1066 -10 + C1121 R1069 -10 R1072 -10 + C1121 R1108 1 R1114 -1 + C1122 R1001 310 R1027 1 + C1122 R1028 -1 R1060 -10 + C1122 R1063 -10 R1066 -10 + C1122 R1069 -10 R1072 -10 + C1122 R1109 1 R1114 -1 + C1123 R1001 350 R1027 1 + C1123 R1028 -1 R1060 -10 + C1123 R1063 -10 R1066 -10 + C1123 R1069 -10 R1072 -10 + C1123 R1110 1 R1114 -1 + C1124 R1001 310 R1027 1 + C1124 R1028 -1 R1061 -10 + C1124 R1064 -10 R1067 -10 + C1124 R1070 -10 R1073 -10 + C1124 R1108 1 R1115 -1 + C1125 R1001 250 R1027 1 + C1125 R1028 -1 R1061 -10 + C1125 R1064 -10 R1067 -10 + C1125 R1070 -10 R1073 -10 + C1125 R1109 1 R1115 -1 + C1126 R1001 350 R1027 1 + C1126 R1028 -1 R1061 -10 + C1126 R1064 -10 R1067 -10 + C1126 R1070 -10 R1073 -10 + C1126 R1110 1 R1115 -1 + C1127 R1001 475 R1027 1 + C1127 R1028 -1 R1062 -5 + C1127 R1065 -5 R1068 -5 + C1127 R1071 -5 R1074 -5 + C1127 R1108 1 R1116 -1 + C1128 R1001 475 R1027 1 + C1128 R1028 -1 R1062 -5 + C1128 R1065 -5 R1068 -5 + C1128 R1071 -5 R1074 -5 + C1128 R1109 1 R1116 -1 + C1129 R1001 375 R1027 1 + C1129 R1028 -1 R1062 -5 + C1129 R1065 -5 R1068 -5 + C1129 R1071 -5 R1074 -5 + C1129 R1110 1 R1116 -1 + C1130 R1001 200 R1029 1 + C1130 R1030 -1 R1063 -10 + C1130 R1066 -10 R1069 -10 + C1130 R1072 -10 R1111 1 + C1130 R1117 -1 + C1131 R1001 260 R1029 1 + C1131 R1030 -1 R1063 -10 + C1131 R1066 -10 R1069 -10 + C1131 R1072 -10 R1112 1 + C1131 R1117 -1 + C1132 R1001 300 R1029 1 + C1132 R1030 -1 R1063 -10 + C1132 R1066 -10 R1069 -10 + C1132 R1072 -10 R1113 1 + C1132 R1117 -1 + C1133 R1001 260 R1029 1 + C1133 R1030 -1 R1064 -10 + C1133 R1067 -10 R1070 -10 + C1133 R1073 -10 R1111 1 + C1133 R1118 -1 + C1134 R1001 200 R1029 1 + C1134 R1030 -1 R1064 -10 + C1134 R1067 -10 R1070 -10 + C1134 R1073 -10 R1112 1 + C1134 R1118 -1 + C1135 R1001 300 R1029 1 + C1135 R1030 -1 R1064 -10 + C1135 R1067 -10 R1070 -10 + C1135 R1073 -10 R1113 1 + C1135 R1118 -1 + C1136 R1001 400 R1029 1 + C1136 R1030 -1 R1065 -5 + C1136 R1068 -5 R1071 -5 + C1136 R1074 -5 R1111 1 + C1136 R1119 -1 + C1137 R1001 400 R1029 1 + C1137 R1030 -1 R1065 -5 + C1137 R1068 -5 R1071 -5 + C1137 R1074 -5 R1112 1 + C1137 R1119 -1 + C1138 R1001 300 R1029 1 + C1138 R1030 -1 R1065 -5 + C1138 R1068 -5 R1071 -5 + C1138 R1074 -5 R1113 1 + C1138 R1119 -1 + C1139 R1001 200 R1031 1 + C1139 R1032 -1 R1063 -10 + C1139 R1066 -10 R1069 -10 + C1139 R1072 -10 R1114 1 + C1139 R1120 -1 + C1140 R1001 260 R1031 1 + C1140 R1032 -1 R1063 -10 + C1140 R1066 -10 R1069 -10 + C1140 R1072 -10 R1115 1 + C1140 R1120 -1 + C1141 R1001 300 R1031 1 + C1141 R1032 -1 R1063 -10 + C1141 R1066 -10 R1069 -10 + C1141 R1072 -10 R1116 1 + C1141 R1120 -1 + C1142 R1001 260 R1031 1 + C1142 R1032 -1 R1064 -10 + C1142 R1067 -10 R1070 -10 + C1142 R1073 -10 R1114 1 + C1142 R1121 -1 + C1143 R1001 200 R1031 1 + C1143 R1032 -1 R1064 -10 + C1143 R1067 -10 R1070 -10 + C1143 R1073 -10 R1115 1 + C1143 R1121 -1 + C1144 R1001 300 R1031 1 + C1144 R1032 -1 R1064 -10 + C1144 R1067 -10 R1070 -10 + C1144 R1073 -10 R1116 1 + C1144 R1121 -1 + C1145 R1001 400 R1031 1 + C1145 R1032 -1 R1065 -5 + C1145 R1068 -5 R1071 -5 + C1145 R1074 -5 R1114 1 + C1145 R1122 -1 + C1146 R1001 400 R1031 1 + C1146 R1032 -1 R1065 -5 + C1146 R1068 -5 R1071 -5 + C1146 R1074 -5 R1115 1 + C1146 R1122 -1 + C1147 R1001 300 R1031 1 + C1147 R1032 -1 R1065 -5 + C1147 R1068 -5 R1071 -5 + C1147 R1074 -5 R1116 1 + C1147 R1122 -1 + C1148 R1001 150 R1033 1 + C1148 R1034 -1 R1066 -10 + C1148 R1069 -10 R1072 -10 + C1148 R1117 1 R1123 -1 + C1149 R1001 210 R1033 1 + C1149 R1034 -1 R1066 -10 + C1149 R1069 -10 R1072 -10 + C1149 R1118 1 R1123 -1 + C1150 R1001 250 R1033 1 + C1150 R1034 -1 R1066 -10 + C1150 R1069 -10 R1072 -10 + C1150 R1119 1 R1123 -1 + C1151 R1001 210 R1033 1 + C1151 R1034 -1 R1067 -10 + C1151 R1070 -10 R1073 -10 + C1151 R1117 1 R1124 -1 + C1152 R1001 150 R1033 1 + C1152 R1034 -1 R1067 -10 + C1152 R1070 -10 R1073 -10 + C1152 R1118 1 R1124 -1 + C1153 R1001 250 R1033 1 + C1153 R1034 -1 R1067 -10 + C1153 R1070 -10 R1073 -10 + C1153 R1119 1 R1124 -1 + C1154 R1001 325 R1033 1 + C1154 R1034 -1 R1068 -5 + C1154 R1071 -5 R1074 -5 + C1154 R1117 1 R1125 -1 + C1155 R1001 325 R1033 1 + C1155 R1034 -1 R1068 -5 + C1155 R1071 -5 R1074 -5 + C1155 R1118 1 R1125 -1 + C1156 R1001 225 R1033 1 + C1156 R1034 -1 R1068 -5 + C1156 R1071 -5 R1074 -5 + C1156 R1119 1 R1125 -1 + C1157 R1001 150 R1035 1 + C1157 R1036 -1 R1066 -10 + C1157 R1069 -10 R1072 -10 + C1157 R1120 1 R1126 -1 + C1158 R1001 210 R1035 1 + C1158 R1036 -1 R1066 -10 + C1158 R1069 -10 R1072 -10 + C1158 R1121 1 R1126 -1 + C1159 R1001 250 R1035 1 + C1159 R1036 -1 R1066 -10 + C1159 R1069 -10 R1072 -10 + C1159 R1122 1 R1126 -1 + C1160 R1001 210 R1035 1 + C1160 R1036 -1 R1067 -10 + C1160 R1070 -10 R1073 -10 + C1160 R1120 1 R1127 -1 + C1161 R1001 150 R1035 1 + C1161 R1036 -1 R1067 -10 + C1161 R1070 -10 R1073 -10 + C1161 R1121 1 R1127 -1 + C1162 R1001 250 R1035 1 + C1162 R1036 -1 R1067 -10 + C1162 R1070 -10 R1073 -10 + C1162 R1122 1 R1127 -1 + C1163 R1001 325 R1035 1 + C1163 R1036 -1 R1068 -5 + C1163 R1071 -5 R1074 -5 + C1163 R1120 1 R1128 -1 + C1164 R1001 325 R1035 1 + C1164 R1036 -1 R1068 -5 + C1164 R1071 -5 R1074 -5 + C1164 R1121 1 R1128 -1 + C1165 R1001 225 R1035 1 + C1165 R1036 -1 R1068 -5 + C1165 R1071 -5 R1074 -5 + C1165 R1122 1 R1128 -1 + C1166 R1001 100 R1037 1 + C1166 R1038 -1 R1069 -10 + C1166 R1072 -10 R1123 1 + C1166 R1129 -1 + C1167 R1001 160 R1037 1 + C1167 R1038 -1 R1069 -10 + C1167 R1072 -10 R1124 1 + C1167 R1129 -1 + C1168 R1001 200 R1037 1 + C1168 R1038 -1 R1069 -10 + C1168 R1072 -10 R1125 1 + C1168 R1129 -1 + C1169 R1001 160 R1037 1 + C1169 R1038 -1 R1070 -10 + C1169 R1073 -10 R1123 1 + C1169 R1130 -1 + C1170 R1001 100 R1037 1 + C1170 R1038 -1 R1070 -10 + C1170 R1073 -10 R1124 1 + C1170 R1130 -1 + C1171 R1001 200 R1037 1 + C1171 R1038 -1 R1070 -10 + C1171 R1073 -10 R1125 1 + C1171 R1130 -1 + C1172 R1001 250 R1037 1 + C1172 R1038 -1 R1071 -5 + C1172 R1074 -5 R1123 1 + C1172 R1131 -1 + C1173 R1001 250 R1037 1 + C1173 R1038 -1 R1071 -5 + C1173 R1074 -5 R1124 1 + C1173 R1131 -1 + C1174 R1001 150 R1037 1 + C1174 R1038 -1 R1071 -5 + C1174 R1074 -5 R1125 1 + C1174 R1131 -1 + C1175 R1001 100 R1039 1 + C1175 R1040 -1 R1069 -10 + C1175 R1072 -10 R1126 1 + C1175 R1132 -1 + C1176 R1001 160 R1039 1 + C1176 R1040 -1 R1069 -10 + C1176 R1072 -10 R1127 1 + C1176 R1132 -1 + C1177 R1001 200 R1039 1 + C1177 R1040 -1 R1069 -10 + C1177 R1072 -10 R1128 1 + C1177 R1132 -1 + C1178 R1001 160 R1039 1 + C1178 R1040 -1 R1070 -10 + C1178 R1073 -10 R1126 1 + C1178 R1133 -1 + C1179 R1001 100 R1039 1 + C1179 R1040 -1 R1070 -10 + C1179 R1073 -10 R1127 1 + C1179 R1133 -1 + C1180 R1001 200 R1039 1 + C1180 R1040 -1 R1070 -10 + C1180 R1073 -10 R1128 1 + C1180 R1133 -1 + C1181 R1001 250 R1039 1 + C1181 R1040 -1 R1071 -5 + C1181 R1074 -5 R1126 1 + C1181 R1134 -1 + C1182 R1001 250 R1039 1 + C1182 R1040 -1 R1071 -5 + C1182 R1074 -5 R1127 1 + C1182 R1134 -1 + C1183 R1001 150 R1039 1 + C1183 R1040 -1 R1071 -5 + C1183 R1074 -5 R1128 1 + C1183 R1134 -1 + C1184 R1001 50 R1041 1 + C1184 R1042 -1 R1072 -10 + C1184 R1129 1 + C1185 R1001 110 R1041 1 + C1185 R1042 -1 R1072 -10 + C1185 R1130 1 + C1186 R1001 150 R1041 1 + C1186 R1042 -1 R1072 -10 + C1186 R1131 1 + C1187 R1001 110 R1041 1 + C1187 R1042 -1 R1073 -10 + C1187 R1129 1 + C1188 R1001 50 R1041 1 + C1188 R1042 -1 R1073 -10 + C1188 R1130 1 + C1189 R1001 150 R1041 1 + C1189 R1042 -1 R1073 -10 + C1189 R1131 1 + C1190 R1001 175 R1041 1 + C1190 R1042 -1 R1074 -5 + C1190 R1129 1 + C1191 R1001 175 R1041 1 + C1191 R1042 -1 R1074 -5 + C1191 R1130 1 + C1192 R1001 75 R1041 1 + C1192 R1042 -1 R1074 -5 + C1192 R1131 1 + C1193 R1001 50 R1043 1 + C1193 R1044 -1 R1072 -10 + C1193 R1132 1 + C1194 R1001 110 R1043 1 + C1194 R1044 -1 R1072 -10 + C1194 R1133 1 + C1195 R1001 150 R1043 1 + C1195 R1044 -1 R1072 -10 + C1195 R1134 1 + C1196 R1001 110 R1043 1 + C1196 R1044 -1 R1073 -10 + C1196 R1132 1 + C1197 R1001 50 R1043 1 + C1197 R1044 -1 R1073 -10 + C1197 R1133 1 + C1198 R1001 150 R1043 1 + C1198 R1044 -1 R1073 -10 + C1198 R1134 1 + C1199 R1001 175 R1043 1 + C1199 R1044 -1 R1074 -5 + C1199 R1132 1 + C1200 R1001 175 R1043 1 + C1200 R1044 -1 R1074 -5 + C1200 R1133 1 + C1201 R1001 75 R1043 1 + C1201 R1044 -1 R1074 -5 + C1201 R1134 1 + MARK0001 'MARKER' 'INTEND' +RHS + RHS R1002 25 R1003 25 + RHS R1004 25 R1005 1 + RHS R1006 -1 R1007 1 + RHS R1008 -1 R1009 1 + RHS R1010 -1 R1011 1 + RHS R1012 -1 R1013 1 + RHS R1014 -1 R1015 1 + RHS R1016 -1 R1017 1 + RHS R1018 -1 R1019 1 + RHS R1020 -1 R1021 1 + RHS R1022 -1 R1023 1 + RHS R1024 -1 R1025 1 + RHS R1026 -1 R1027 1 + RHS R1028 -1 R1029 1 + RHS R1030 -1 R1031 1 + RHS R1032 -1 R1033 1 + RHS R1034 -1 R1035 1 + RHS R1036 -1 R1037 1 + RHS R1038 -1 R1039 1 + RHS R1040 -1 R1041 1 + RHS R1042 -1 R1043 1 + RHS R1044 -1 R1045 -5 + RHS R1046 -5 R1047 -5 + RHS R1048 -10 R1049 -10 + RHS R1050 -10 R1051 -15 + RHS R1052 -15 R1053 -15 + RHS R1054 -20 R1055 -20 + RHS R1056 -20 R1057 -25 + RHS R1058 -25 R1059 -25 + RHS R1060 -30 R1061 -30 + RHS R1062 -30 R1063 -35 + RHS R1064 -35 R1065 -35 + RHS R1066 -40 R1067 -40 + RHS R1068 -40 R1069 -45 + RHS R1070 -45 R1071 -45 + RHS R1072 -50 R1073 -50 + RHS R1074 -50 R1075 1 + RHS R1076 1 R1077 1 + RHS R1078 1 R1079 1 + RHS R1080 1 +BOUNDS + UP ONE C1001 1 + UP ONE C1002 1 + UP ONE C1003 1 + UP ONE C1004 1 + UP ONE C1005 1 + UP ONE C1006 1 + UP ONE C1007 1 + UP ONE C1008 1 + UP ONE C1009 1 + UP ONE C1010 1 + UP ONE C1011 1 + UP ONE C1012 1 + UP ONE C1013 1 + UP ONE C1014 1 + UP ONE C1015 1 + UP ONE C1016 1 + UP ONE C1017 1 + UP ONE C1018 1 + UP ONE C1019 1 + UP ONE C1020 1 + UP ONE C1021 1 + UP ONE C1022 1 + UP ONE C1023 1 + UP ONE C1024 1 + UP ONE C1025 1 + UP ONE C1026 1 + UP ONE C1027 1 + UP ONE C1028 1 + UP ONE C1029 1 + UP ONE C1030 1 + UP ONE C1031 1 + UP ONE C1032 1 + UP ONE C1033 1 + UP ONE C1034 1 + UP ONE C1035 1 + UP ONE C1036 1 + UP ONE C1037 1 + UP ONE C1038 1 + UP ONE C1039 1 + UP ONE C1040 1 + UP ONE C1041 1 + UP ONE C1042 1 + UP ONE C1043 1 + UP ONE C1044 1 + UP ONE C1045 1 + UP ONE C1046 1 + UP ONE C1047 1 + UP ONE C1048 1 + UP ONE C1049 1 + UP ONE C1050 1 + UP ONE C1051 1 + UP ONE C1052 1 + UP ONE C1053 1 + UP ONE C1054 1 + UP ONE C1055 1 + UP ONE C1056 1 + UP ONE C1057 1 + UP ONE C1058 1 + UP ONE C1059 1 + UP ONE C1060 1 + UP ONE C1061 1 + UP ONE C1062 1 + UP ONE C1063 1 + UP ONE C1064 1 + UP ONE C1065 1 + UP ONE C1066 1 + UP ONE C1067 1 + UP ONE C1068 1 + UP ONE C1069 1 + UP ONE C1070 1 + UP ONE C1071 1 + UP ONE C1072 1 + UP ONE C1073 1 + UP ONE C1074 1 + UP ONE C1075 1 + UP ONE C1076 1 + UP ONE C1077 1 + UP ONE C1078 1 + UP ONE C1079 1 + UP ONE C1080 1 + UP ONE C1081 1 + UP ONE C1082 1 + UP ONE C1083 1 + UP ONE C1084 1 + UP ONE C1085 1 + UP ONE C1086 1 + UP ONE C1087 1 + UP ONE C1088 1 + UP ONE C1089 1 + UP ONE C1090 1 + UP ONE C1091 1 + UP ONE C1092 1 + UP ONE C1093 1 + UP ONE C1094 1 + UP ONE C1095 1 + UP ONE C1096 1 + UP ONE C1097 1 + UP ONE C1098 1 + UP ONE C1099 1 + UP ONE C1100 1 + UP ONE C1101 1 + UP ONE C1102 1 + UP ONE C1103 1 + UP ONE C1104 1 + UP ONE C1105 1 + UP ONE C1106 1 + UP ONE C1107 1 + UP ONE C1108 1 + UP ONE C1109 1 + UP ONE C1110 1 + UP ONE C1111 1 + UP ONE C1112 1 + UP ONE C1113 1 + UP ONE C1114 1 + UP ONE C1115 1 + UP ONE C1116 1 + UP ONE C1117 1 + UP ONE C1118 1 + UP ONE C1119 1 + UP ONE C1120 1 + UP ONE C1121 1 + UP ONE C1122 1 + UP ONE C1123 1 + UP ONE C1124 1 + UP ONE C1125 1 + UP ONE C1126 1 + UP ONE C1127 1 + UP ONE C1128 1 + UP ONE C1129 1 + UP ONE C1130 1 + UP ONE C1131 1 + UP ONE C1132 1 + UP ONE C1133 1 + UP ONE C1134 1 + UP ONE C1135 1 + UP ONE C1136 1 + UP ONE C1137 1 + UP ONE C1138 1 + UP ONE C1139 1 + UP ONE C1140 1 + UP ONE C1141 1 + UP ONE C1142 1 + UP ONE C1143 1 + UP ONE C1144 1 + UP ONE C1145 1 + UP ONE C1146 1 + UP ONE C1147 1 + UP ONE C1148 1 + UP ONE C1149 1 + UP ONE C1150 1 + UP ONE C1151 1 + UP ONE C1152 1 + UP ONE C1153 1 + UP ONE C1154 1 + UP ONE C1155 1 + UP ONE C1156 1 + UP ONE C1157 1 + UP ONE C1158 1 + UP ONE C1159 1 + UP ONE C1160 1 + UP ONE C1161 1 + UP ONE C1162 1 + UP ONE C1163 1 + UP ONE C1164 1 + UP ONE C1165 1 + UP ONE C1166 1 + UP ONE C1167 1 + UP ONE C1168 1 + UP ONE C1169 1 + UP ONE C1170 1 + UP ONE C1171 1 + UP ONE C1172 1 + UP ONE C1173 1 + UP ONE C1174 1 + UP ONE C1175 1 + UP ONE C1176 1 + UP ONE C1177 1 + UP ONE C1178 1 + UP ONE C1179 1 + UP ONE C1180 1 + UP ONE C1181 1 + UP ONE C1182 1 + UP ONE C1183 1 + UP ONE C1184 1 + UP ONE C1185 1 + UP ONE C1186 1 + UP ONE C1187 1 + UP ONE C1188 1 + UP ONE C1189 1 + UP ONE C1190 1 + UP ONE C1191 1 + UP ONE C1192 1 + UP ONE C1193 1 + UP ONE C1194 1 + UP ONE C1195 1 + UP ONE C1196 1 + UP ONE C1197 1 + UP ONE C1198 1 + UP ONE C1199 1 + UP ONE C1200 1 + UP ONE C1201 1 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0548.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0548.mps new file mode 100644 index 000000000..88acad400 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/p0548.mps @@ -0,0 +1,1992 @@ +*NAME: p0548 +*ROWS: 176 +*COLUMNS: 548 +*INTEGER: 548 +*NONZERO: 1711 +*BEST SOLN: 8691 (opt) +*LP SOLN: 315.29 +*SOURCE: Crowder-Johnson-Padberg test set +* Ellis L. Johnson (IBM) +* E. Andrew Boyd (Rice University) +*APPLICATION: unknown +*COMMENTS: pure 0/1 IP +* 82 SOS constraints +* +NAME P0548 +ROWS + N R1001 + L R1002 + L R1003 + L R1004 + L R1005 + L R1006 + L R1007 + L R1008 + L R1009 + L R1010 + L R1011 + L R1012 + L R1013 + L R1014 + L R1015 + L R1016 + L R1017 + L R1018 + L R1019 + L R1020 + L R1021 + L R1022 + L R1023 + L R1024 + L R1025 + L R1026 + L R1027 + L R1028 + L R1029 + L R1030 + L R1031 + L R1032 + L R1033 + L R1034 + L R1035 + L R1036 + L R1037 + L R1038 + L R1039 + L R1040 + L R1041 + L R1042 + L R1043 + L R1044 + L R1045 + L R1046 + L R1047 + L R1048 + L R1049 + L R1050 + L R1051 + L R1052 + L R1053 + L R1054 + L R1055 + L R1056 + L R1057 + L R1058 + L R1059 + L R1060 + L R1061 + L R1062 + L R1063 + L R1064 + L R1065 + L R1066 + L R1067 + L R1068 + L R1069 + L R1070 + L R1071 + L R1072 + L R1073 + L R1074 + L R1075 + L R1076 + L R1077 + L R1078 + L R1079 + L R1080 + L R1081 + L R1082 + L R1083 + L R1084 + L R1085 + L R1086 + L R1087 + L R1088 + L R1089 + L R1090 + L R1091 + L R1092 + L R1093 + L R1094 + L R1095 + L R1096 + L R1097 + L R1098 + L R1099 + L R1100 + L R1101 + L R1102 + L R1103 + L R1104 + L R1105 + L R1106 + L R1107 + L R1108 + L R1109 + L R1110 + L R1111 + L R1112 + L R1113 + L R1114 + L R1115 + L R1116 + L R1117 + L R1118 + L R1119 + L R1120 + L R1121 + L R1122 + L R1123 + L R1124 + L R1125 + L R1126 + L R1127 + L R1128 + L R1129 + L R1130 + L R1131 + L R1132 + L R1133 + L R1134 + L R1135 + L R1136 + L R1137 + L R1138 + L R1139 + L R1140 + L R1141 + L R1142 + L R1143 + L R1144 + L R1145 + L R1146 + L R1147 + L R1148 + L R1149 + L R1150 + L R1151 + L R1152 + L R1153 + L R1154 + L R1155 + L R1156 + L R1157 + L R1158 + L R1159 + L R1160 + L R1161 + L R1162 + L R1163 + L R1164 + L R1165 + L R1166 + L R1167 + L R1168 + L R1169 + L R1170 + L R1171 + L R1172 + L R1173 + L R1174 + L R1175 + L R1176 + L R1177 +COLUMNS + MARK0000 'MARKER' 'INTORG' + C1001 R1001 169 R1002 -59 + C1001 R1051 -59 R1101 20 + C1002 R1001 10 R1002 -10 + C1002 R1051 -10 R1173 1 + C1003 R1001 235 R1002 -167 + C1003 R1051 -167 R1100 -35 + C1003 R1102 20 R1109 1 + C1004 R1001 59 R1002 161 + C1004 R1051 161 R1100 31 + C1004 R1103 -19 R1109 -1 + C1005 R1001 39 R1002 -35 + C1005 R1051 -35 R1100 -32 + C1005 R1104 20 R1109 1 + C1006 R1002 -120 R1051 -120 + C1006 R1110 1 + C1007 R1002 -189 R1051 -189 + C1007 R1110 1 + C1008 R1001 118 R1002 -68 + C1008 R1051 -68 R1174 1 + C1009 R1002 -68 R1051 -68 + C1009 R1105 20 + C1010 R1001 29 R1002 -71 + C1010 R1051 -71 R1106 20 + C1011 R1001 186 R1003 -106 + C1011 R1052 106 R1175 1 + C1012 R1001 110 R1003 -59 + C1012 R1052 59 R1101 13 + C1013 R1001 6 R1003 -10 + C1013 R1052 10 R1173 1 + C1014 R1001 154 R1003 -167 + C1014 R1052 167 R1100 -27 + C1014 R1102 13 R1111 1 + C1015 R1001 38 R1003 161 + C1015 R1052 -161 R1100 24 + C1015 R1103 -12 R1111 -1 + C1016 R1001 26 R1003 -35 + C1016 R1052 35 R1100 -25 + C1016 R1104 13 R1111 1 + C1017 R1003 -120 R1052 120 + C1017 R1112 1 + C1018 R1003 -189 R1052 189 + C1018 R1112 1 + C1019 R1001 77 R1003 -68 + C1019 R1052 68 R1174 1 + C1020 R1003 -68 R1052 68 + C1020 R1105 13 + C1021 R1001 19 R1003 -71 + C1021 R1052 71 R1106 13 + C1022 R1001 128 R1004 -59 + C1022 R1053 -59 R1101 15 + C1023 R1001 7 R1004 -10 + C1023 R1053 -10 R1173 1 + C1024 R1001 179 R1004 -167 + C1024 R1053 -167 R1100 -26 + C1024 R1102 15 R1113 1 + C1025 R1001 45 R1004 161 + C1025 R1053 161 R1100 23 + C1025 R1103 -14 R1113 -1 + C1026 R1001 30 R1004 -35 + C1026 R1053 -35 R1100 -24 + C1026 R1104 15 R1113 1 + C1027 R1004 -120 R1053 -120 + C1027 R1114 1 + C1028 R1004 -189 R1053 -189 + C1028 R1114 1 + C1029 R1001 89 R1004 -68 + C1029 R1053 -68 R1174 1 + C1030 R1001 22 R1004 -71 + C1030 R1053 -71 R1106 15 + C1031 R1001 674 R1005 -59 + C1031 R1054 59 R1101 78 + C1032 R1001 39 R1005 -10 + C1032 R1054 10 R1173 1 + C1033 R1001 941 R1005 -167 + C1033 R1054 167 R1100 -139 + C1033 R1102 78 R1115 1 + C1034 R1001 235 R1005 161 + C1034 R1054 -161 R1100 127 + C1034 R1103 -77 R1115 -1 + C1035 R1001 157 R1005 -35 + C1035 R1054 35 R1100 -128 + C1035 R1104 78 R1115 1 + C1036 R1005 -120 R1054 120 + C1036 R1116 1 + C1037 R1005 -189 R1054 189 + C1037 R1116 1 + C1038 R1001 470 R1005 -68 + C1038 R1054 68 R1174 1 + C1039 R1005 -68 R1054 68 + C1039 R1105 78 + C1040 R1001 118 R1005 -71 + C1040 R1054 71 R1106 78 + C1041 R1001 755 R1006 -106 + C1041 R1055 106 R1175 1 + C1042 R1001 445 R1006 -59 + C1042 R1055 59 R1101 52 + C1043 R1001 26 R1006 -10 + C1043 R1055 10 R1173 1 + C1044 R1001 622 R1006 -167 + C1044 R1055 167 R1100 -109 + C1044 R1102 52 R1117 1 + C1045 R1001 155 R1006 161 + C1045 R1055 -161 R1100 99 + C1045 R1103 -51 R1117 -1 + C1046 R1001 104 R1006 -35 + C1046 R1055 35 R1100 -100 + C1046 R1104 52 R1117 1 + C1047 R1006 -120 R1055 120 + C1047 R1118 1 + C1048 R1006 -189 R1055 189 + C1048 R1118 1 + C1049 R1001 311 R1006 -68 + C1049 R1055 68 R1174 1 + C1050 R1006 -68 R1055 68 + C1050 R1105 52 + C1051 R1001 78 R1006 -71 + C1051 R1055 71 R1106 52 + C1052 R1001 159 R1007 -106 + C1052 R1056 106 R1175 1 + C1053 R1001 94 R1007 -59 + C1053 R1056 59 R1101 11 + C1054 R1001 5 R1007 -10 + C1054 R1056 10 R1173 1 + C1055 R1001 251 R1007 45 + C1055 R1056 -45 R1107 -10 + C1055 R1108 11 + C1056 R1007 -120 R1056 120 + C1056 R1119 1 + C1057 R1007 -189 R1056 189 + C1057 R1119 1 + C1058 R1001 65 R1007 -68 + C1058 R1056 68 R1174 1 + C1059 R1007 -68 R1056 68 + C1059 R1105 11 + C1060 R1001 16 R1007 -71 + C1060 R1056 71 R1106 11 + C1061 R1001 6 R1008 -10 + C1061 R1057 10 R1173 1 + C1062 R1001 37 R1008 161 + C1062 R1057 -161 R1100 25 + C1062 R1103 -11 R1120 -1 + C1063 R1001 25 R1008 -35 + C1063 R1057 35 R1100 -26 + C1063 R1104 12 R1120 1 + C1064 R1001 74 R1008 -68 + C1064 R1057 68 R1174 1 + C1065 R1008 -68 R1057 68 + C1065 R1105 12 + C1066 R1001 18 R1008 -71 + C1066 R1057 71 R1106 12 + C1067 R1001 17 R1009 -10 + C1067 R1058 10 R1173 1 + C1068 R1001 101 R1009 161 + C1068 R1058 -161 R1100 80 + C1068 R1103 -33 R1121 -1 + C1069 R1001 67 R1009 -35 + C1069 R1058 35 R1100 -81 + C1069 R1104 34 R1121 1 + C1070 R1001 202 R1009 -68 + C1070 R1058 68 R1174 1 + C1071 R1009 -68 R1058 68 + C1071 R1105 34 + C1072 R1001 50 R1009 -71 + C1072 R1058 71 R1106 34 + C1073 R1001 74 R1010 -136 + C1073 R1059 136 R1176 1 + C1074 R1001 6 R1010 -10 + C1074 R1059 10 R1173 1 + C1075 R1001 37 R1010 161 + C1075 R1059 -161 R1100 15 + C1075 R1103 -11 R1122 -1 + C1076 R1001 25 R1010 -35 + C1076 R1059 35 R1100 -16 + C1076 R1104 12 R1122 1 + C1077 R1001 74 R1010 -68 + C1077 R1059 68 R1174 1 + C1078 R1010 -68 R1059 68 + C1078 R1105 12 + C1079 R1001 18 R1010 -71 + C1079 R1059 71 R1106 12 + C1080 R1001 265 R1011 -59 + C1080 R1060 59 R1101 31 + C1081 R1001 15 R1011 -10 + C1081 R1060 10 R1173 1 + C1082 R1001 370 R1011 -167 + C1082 R1060 167 R1100 -58 + C1082 R1102 31 R1123 1 + C1083 R1001 92 R1011 161 + C1083 R1060 -161 R1100 52 + C1083 R1103 -30 R1123 -1 + C1084 R1001 62 R1011 -35 + C1084 R1060 35 R1100 -53 + C1084 R1104 31 R1123 1 + C1085 R1011 -120 R1060 120 + C1085 R1124 1 + C1086 R1011 -189 R1060 189 + C1086 R1124 1 + C1087 R1001 185 R1011 -68 + C1087 R1060 68 R1174 1 + C1088 R1011 -68 R1060 68 + C1088 R1105 31 + C1089 R1001 46 R1011 -71 + C1089 R1060 71 R1106 31 + C1090 R1001 296 R1012 -106 + C1090 R1061 106 R1175 1 + C1091 R1001 175 R1012 -59 + C1091 R1061 59 R1101 20 + C1092 R1001 10 R1012 -10 + C1092 R1061 10 R1173 1 + C1093 R1001 244 R1012 -167 + C1093 R1061 167 R1100 -43 + C1093 R1102 20 R1125 1 + C1094 R1001 61 R1012 161 + C1094 R1061 -161 R1100 38 + C1094 R1103 -19 R1125 -1 + C1095 R1001 41 R1012 -35 + C1095 R1061 35 R1100 -39 + C1095 R1104 20 R1125 1 + C1096 R1012 -120 R1061 120 + C1096 R1126 1 + C1097 R1012 -189 R1061 189 + C1097 R1126 1 + C1098 R1001 122 R1012 -68 + C1098 R1061 68 R1174 1 + C1099 R1012 -68 R1061 68 + C1099 R1105 20 + C1100 R1001 30 R1012 -71 + C1100 R1061 71 R1106 20 + C1101 R1001 156 R1013 -59 + C1101 R1062 59 R1101 18 + C1102 R1001 9 R1013 -10 + C1102 R1062 10 R1173 1 + C1103 R1001 217 R1013 -167 + C1103 R1062 167 R1100 -33 + C1103 R1102 18 R1127 1 + C1104 R1001 54 R1013 161 + C1104 R1062 -161 R1100 30 + C1104 R1103 -17 R1127 -1 + C1105 R1001 36 R1013 -35 + C1105 R1062 35 R1100 -31 + C1105 R1104 18 R1127 1 + C1106 R1013 -120 R1062 120 + C1106 R1128 1 + C1107 R1013 -189 R1062 189 + C1107 R1128 1 + C1108 R1001 109 R1013 -68 + C1108 R1062 68 R1174 1 + C1109 R1001 27 R1013 -71 + C1109 R1062 71 R1106 18 + C1110 R1001 819 R1014 -59 + C1110 R1063 59 R1101 95 + C1111 R1001 48 R1014 -10 + C1111 R1063 10 R1173 1 + C1112 R1001 1142 R1014 -167 + C1112 R1063 167 R1100 -178 + C1112 R1102 95 R1129 1 + C1113 R1001 286 R1014 161 + C1113 R1063 -161 R1100 163 + C1113 R1103 -94 R1129 -1 + C1114 R1001 190 R1014 -35 + C1114 R1063 35 R1100 -164 + C1114 R1104 95 R1129 1 + C1115 R1014 -120 R1063 120 + C1115 R1130 1 + C1116 R1014 -189 R1063 189 + C1116 R1130 1 + C1117 R1001 571 R1014 -68 + C1117 R1063 68 R1174 1 + C1118 R1014 -68 R1063 68 + C1118 R1105 95 + C1119 R1001 143 R1014 -71 + C1119 R1063 71 R1106 95 + C1120 R1001 916 R1015 -106 + C1120 R1064 106 R1175 1 + C1121 R1001 541 R1015 -59 + C1121 R1064 59 R1101 63 + C1122 R1001 31 R1015 -10 + C1122 R1064 10 R1173 1 + C1123 R1001 755 R1015 -167 + C1123 R1064 167 R1100 -132 + C1123 R1102 63 R1131 1 + C1124 R1001 189 R1015 161 + C1124 R1064 -161 R1100 121 + C1124 R1103 -62 R1131 -1 + C1125 R1001 126 R1015 -35 + C1125 R1064 35 R1100 -122 + C1125 R1104 63 R1131 1 + C1126 R1015 -120 R1064 120 + C1126 R1132 1 + C1127 R1015 -189 R1064 189 + C1127 R1132 1 + C1128 R1001 377 R1015 -68 + C1128 R1064 68 R1174 1 + C1129 R1015 -68 R1064 68 + C1129 R1105 63 + C1130 R1001 94 R1015 -71 + C1130 R1064 71 R1106 63 + C1131 R1001 194 R1016 -106 + C1131 R1065 106 R1175 1 + C1132 R1001 114 R1016 -59 + C1132 R1065 59 R1101 13 + C1133 R1001 7 R1016 -10 + C1133 R1065 10 R1173 1 + C1134 R1001 306 R1016 45 + C1134 R1065 -45 R1107 -12 + C1134 R1108 13 + C1135 R1016 -120 R1065 120 + C1135 R1133 1 + C1136 R1016 -189 R1065 189 + C1136 R1133 1 + C1137 R1001 80 R1016 -68 + C1137 R1065 68 R1174 1 + C1138 R1016 -68 R1065 68 + C1138 R1105 13 + C1139 R1001 20 R1016 -71 + C1139 R1065 71 R1106 13 + C1140 R1001 5 R1017 -10 + C1140 R1066 10 R1173 1 + C1141 R1001 30 R1017 161 + C1141 R1066 -161 R1100 21 + C1141 R1103 -9 R1134 -1 + C1142 R1001 20 R1017 -35 + C1142 R1066 35 R1100 -22 + C1142 R1104 10 R1134 1 + C1143 R1001 61 R1017 -68 + C1143 R1066 68 R1174 1 + C1144 R1017 -68 R1066 68 + C1144 R1105 10 + C1145 R1001 15 R1017 -71 + C1145 R1066 71 R1106 10 + C1146 R1001 14 R1018 -10 + C1146 R1067 10 R1173 1 + C1147 R1001 83 R1018 161 + C1147 R1067 -161 R1100 69 + C1147 R1103 -27 R1135 -1 + C1148 R1001 55 R1018 -35 + C1148 R1067 35 R1100 -70 + C1148 R1104 28 R1135 1 + C1149 R1001 165 R1018 -68 + C1149 R1067 68 R1174 1 + C1150 R1018 -68 R1067 68 + C1150 R1105 28 + C1151 R1001 41 R1018 -71 + C1151 R1067 71 R1106 28 + C1152 R1001 60 R1019 -136 + C1152 R1068 136 R1176 1 + C1153 R1001 5 R1019 -10 + C1153 R1068 10 R1173 1 + C1154 R1001 30 R1019 161 + C1154 R1068 -161 R1100 12 + C1154 R1103 -9 R1136 -1 + C1155 R1001 20 R1019 -35 + C1155 R1068 35 R1100 -13 + C1155 R1104 10 R1136 1 + C1156 R1001 60 R1019 -68 + C1156 R1068 68 R1174 1 + C1157 R1019 -68 R1068 68 + C1157 R1105 10 + C1158 R1001 15 R1019 -71 + C1158 R1068 71 R1106 10 + C1159 R1001 192 R1020 -81 + C1159 R1069 81 R1177 1 + C1160 R1001 87 R1020 -59 + C1160 R1069 59 R1101 10 + C1161 R1001 5 R1020 -10 + C1161 R1069 10 R1173 1 + C1162 R1001 121 R1020 -167 + C1162 R1069 167 R1100 -20 + C1162 R1102 10 R1137 1 + C1163 R1001 30 R1020 161 + C1163 R1069 -161 R1100 17 + C1163 R1103 -9 R1137 -1 + C1164 R1001 20 R1020 -35 + C1164 R1069 35 R1100 -18 + C1164 R1104 10 R1137 1 + C1165 R1020 -120 R1069 120 + C1165 R1138 1 + C1166 R1020 -189 R1069 189 + C1166 R1138 1 + C1167 R1001 61 R1020 -68 + C1167 R1069 68 R1174 1 + C1168 R1001 455 R1020 -149 + C1168 R1069 149 + C1169 R1001 69 R1020 -100 + C1169 R1069 100 + C1170 R1001 55 R1020 -77 + C1170 R1069 77 + C1171 R1001 15 R1020 -71 + C1171 R1069 71 R1106 10 + C1172 R1001 209 R1021 -81 + C1172 R1070 81 R1177 1 + C1173 R1001 95 R1021 -59 + C1173 R1070 59 R1101 11 + C1174 R1001 6 R1021 -10 + C1174 R1070 10 R1173 1 + C1175 R1001 33 R1021 161 + C1175 R1070 -161 R1100 23 + C1175 R1103 -10 R1139 -1 + C1176 R1001 22 R1021 -35 + C1176 R1070 35 R1100 -24 + C1176 R1104 11 R1139 1 + C1177 R1021 -120 R1070 120 + C1177 R1140 1 + C1178 R1021 -189 R1070 189 + C1178 R1140 1 + C1179 R1001 66 R1021 -68 + C1179 R1070 68 R1174 1 + C1180 R1001 495 R1021 -149 + C1180 R1070 149 + C1181 R1001 75 R1021 -100 + C1181 R1070 100 + C1182 R1001 59 R1021 -77 + C1182 R1070 77 + C1183 R1001 17 R1021 -71 + C1183 R1070 71 R1106 11 + C1184 R1001 234 R1022 -81 + C1184 R1071 81 R1177 1 + C1185 R1001 106 R1022 -59 + C1185 R1071 59 R1101 12 + C1186 R1001 6 R1022 -10 + C1186 R1071 10 R1173 1 + C1187 R1001 37 R1022 161 + C1187 R1071 -161 R1100 26 + C1187 R1103 -11 R1141 -1 + C1188 R1001 25 R1022 -35 + C1188 R1071 35 R1100 -27 + C1188 R1104 12 R1141 1 + C1189 R1022 -120 R1071 120 + C1189 R1142 1 + C1190 R1022 -189 R1071 189 + C1190 R1142 1 + C1191 R1001 74 R1022 -68 + C1191 R1071 68 R1174 1 + C1192 R1001 554 R1022 -149 + C1192 R1071 149 + C1193 R1001 84 R1022 -100 + C1193 R1071 100 + C1194 R1001 66 R1022 -77 + C1194 R1071 77 + C1195 R1001 18 R1022 -71 + C1195 R1071 71 R1106 12 + C1196 R1001 229 R1023 -93 + C1196 R1072 -93 R1175 1 + C1197 R1001 266 R1023 -81 + C1197 R1072 -81 R1177 1 + C1198 R1001 120 R1023 -59 + C1198 R1072 -59 R1101 14 + C1199 R1001 7 R1023 -10 + C1199 R1072 -10 R1173 1 + C1200 R1001 168 R1023 -167 + C1200 R1072 -167 R1100 -32 + C1200 R1102 14 R1143 1 + C1201 R1001 42 R1023 161 + C1201 R1072 161 R1100 29 + C1201 R1103 -13 R1143 -1 + C1202 R1001 28 R1023 -35 + C1202 R1072 -35 R1100 -30 + C1202 R1104 14 R1143 1 + C1203 R1023 -120 R1072 -120 + C1203 R1144 1 + C1204 R1023 -189 R1072 -189 + C1204 R1144 1 + C1205 R1001 84 R1023 -68 + C1205 R1072 -68 R1174 1 + C1206 R1001 630 R1023 -149 + C1206 R1072 -149 + C1207 R1001 95 R1023 -100 + C1207 R1072 -100 + C1208 R1001 76 R1023 -77 + C1208 R1072 -77 + C1209 R1001 21 R1023 -71 + C1209 R1072 -71 R1106 14 + C1210 R1001 7 R1024 -10 + C1210 R1073 10 R1173 1 + C1211 R1001 44 R1024 161 + C1211 R1073 -161 R1100 36 + C1211 R1103 -14 R1145 -1 + C1212 R1001 29 R1024 -35 + C1212 R1073 35 R1100 -37 + C1212 R1104 15 R1145 1 + C1213 R1001 87 R1024 -68 + C1213 R1073 68 R1174 1 + C1214 R1001 653 R1024 -149 + C1214 R1073 149 + C1215 R1001 99 R1024 -100 + C1215 R1073 100 + C1216 R1001 22 R1024 -71 + C1216 R1073 71 R1106 15 + C1217 R1001 209 R1025 -81 + C1217 R1074 81 R1177 1 + C1218 R1001 95 R1025 -59 + C1218 R1074 59 R1101 11 + C1219 R1001 6 R1025 -10 + C1219 R1074 10 R1173 1 + C1220 R1001 33 R1025 161 + C1220 R1074 -161 R1100 23 + C1220 R1103 -10 R1146 -1 + C1221 R1001 22 R1025 -35 + C1221 R1074 35 R1100 -24 + C1221 R1104 11 R1146 1 + C1222 R1025 -120 R1074 120 + C1222 R1147 1 + C1223 R1025 -189 R1074 189 + C1223 R1147 1 + C1224 R1001 66 R1025 -68 + C1224 R1074 68 R1174 1 + C1225 R1001 495 R1025 -149 + C1225 R1074 149 + C1226 R1001 75 R1025 -100 + C1226 R1074 100 + C1227 R1001 59 R1025 -77 + C1227 R1074 77 + C1228 R1001 17 R1025 -71 + C1228 R1074 71 R1106 11 + C1229 R1001 494 R1026 -81 + C1229 R1075 81 R1177 1 + C1230 R1001 224 R1026 -59 + C1230 R1075 59 R1101 26 + C1231 R1001 13 R1026 -10 + C1231 R1075 10 R1173 1 + C1232 R1001 78 R1026 161 + C1232 R1075 -161 R1100 56 + C1232 R1103 -25 R1148 -1 + C1233 R1001 52 R1026 -35 + C1233 R1075 35 R1100 -57 + C1233 R1104 26 R1148 1 + C1234 R1026 -120 R1075 120 + C1234 R1149 1 + C1235 R1026 -189 R1075 189 + C1235 R1149 1 + C1236 R1001 156 R1026 -68 + C1236 R1075 68 R1174 1 + C1237 R1001 1170 R1026 -149 + C1237 R1075 149 + C1238 R1001 177 R1026 -100 + C1238 R1075 100 + C1239 R1001 140 R1026 -77 + C1239 R1075 77 + C1240 R1001 39 R1026 -71 + C1240 R1075 71 R1106 26 + C1241 R1001 208 R1027 -93 + C1241 R1076 -93 R1175 1 + C1242 R1001 241 R1027 -81 + C1242 R1076 -81 R1177 1 + C1243 R1001 109 R1027 -59 + C1243 R1076 -59 R1101 13 + C1244 R1001 76 R1027 -145 + C1244 R1076 -145 + C1245 R1001 6 R1027 -10 + C1245 R1076 -10 R1173 1 + C1246 R1001 292 R1027 45 + C1246 R1076 45 R1107 -12 + C1246 R1108 13 + C1247 R1027 -120 R1076 -120 + C1247 R1150 1 + C1248 R1027 -189 R1076 -189 + C1248 R1150 1 + C1249 R1001 76 R1027 -68 + C1249 R1076 -68 R1174 1 + C1250 R1001 571 R1027 -149 + C1250 R1076 -149 + C1251 R1001 86 R1027 -100 + C1251 R1076 -100 + C1252 R1001 69 R1027 -77 + C1252 R1076 -77 + C1253 R1001 19 R1027 -71 + C1253 R1076 -71 R1106 13 + C1254 R1001 110 R1028 -59 + C1254 R1077 59 R1101 13 + C1255 R1001 77 R1028 -145 + C1255 R1077 145 + C1256 R1001 6 R1028 -10 + C1256 R1077 10 R1173 1 + C1257 R1001 154 R1028 -167 + C1257 R1077 167 R1100 -28 + C1257 R1102 13 R1151 1 + C1258 R1001 38 R1028 161 + C1258 R1077 -161 R1100 25 + C1258 R1103 -12 R1151 -1 + C1259 R1001 26 R1028 -35 + C1259 R1077 35 R1100 -26 + C1259 R1104 13 R1151 1 + C1260 R1028 -120 R1077 120 + C1260 R1152 1 + C1261 R1028 -189 R1077 189 + C1261 R1152 1 + C1262 R1001 77 R1028 -68 + C1262 R1077 68 R1174 1 + C1263 R1001 261 R1028 -189 + C1263 R1077 189 + C1264 R1001 59 R1028 -104 + C1264 R1077 104 + C1265 R1001 51 R1028 -110 + C1265 R1077 110 + C1266 R1001 19 R1028 -71 + C1266 R1077 71 R1106 13 + C1267 R1001 583 R1029 -93 + C1267 R1078 93 R1175 1 + C1268 R1001 306 R1029 -59 + C1268 R1078 59 R1101 36 + C1269 R1001 214 R1029 -145 + C1269 R1078 145 + C1270 R1001 18 R1029 -10 + C1270 R1078 10 R1173 1 + C1271 R1001 427 R1029 -167 + C1271 R1078 167 R1100 -77 + C1271 R1102 36 R1153 1 + C1272 R1001 107 R1029 161 + C1272 R1078 -161 R1100 70 + C1272 R1103 -35 R1153 -1 + C1273 R1001 71 R1029 -35 + C1273 R1078 35 R1100 -71 + C1273 R1104 36 R1153 1 + C1274 R1029 -120 R1078 120 + C1274 R1154 1 + C1275 R1029 -189 R1078 189 + C1275 R1154 1 + C1276 R1001 214 R1029 -68 + C1276 R1078 68 R1174 1 + C1277 R1001 725 R1029 -189 + C1277 R1078 189 + C1278 R1001 164 R1029 -104 + C1278 R1078 104 + C1279 R1001 142 R1029 -110 + C1279 R1078 110 + C1280 R1001 53 R1029 -71 + C1280 R1078 71 R1106 36 + C1281 R1001 144 R1030 -59 + C1281 R1079 59 R1101 17 + C1282 R1001 42 R1030 -155 + C1282 R1079 155 + C1283 R1001 8 R1030 -10 + C1283 R1079 10 R1173 1 + C1284 R1001 202 R1030 -167 + C1284 R1079 167 R1100 -34 + C1284 R1102 17 R1155 1 + C1285 R1001 50 R1030 161 + C1285 R1079 -161 R1100 31 + C1285 R1103 -16 R1155 -1 + C1286 R1001 34 R1030 -35 + C1286 R1079 35 R1100 -32 + C1286 R1104 17 R1155 1 + C1287 R1030 -120 R1079 120 + C1287 R1156 1 + C1288 R1030 -189 R1079 189 + C1288 R1156 1 + C1289 R1001 101 R1030 -68 + C1289 R1079 68 R1174 1 + C1290 R1001 342 R1030 -189 + C1290 R1079 189 + C1291 R1001 77 R1030 -104 + C1291 R1079 104 + C1292 R1001 67 R1030 -110 + C1292 R1079 110 + C1293 R1001 25 R1030 -71 + C1293 R1079 71 R1106 17 + C1294 R1001 1193 R1031 -93 + C1294 R1080 93 R1175 1 + C1295 R1001 626 R1031 -59 + C1295 R1080 59 R1101 73 + C1296 R1001 437 R1031 -145 + C1296 R1080 145 + C1297 R1001 36 R1031 -10 + C1297 R1080 10 R1173 1 + C1298 R1001 874 R1031 -167 + C1298 R1080 167 R1100 -158 + C1298 R1102 73 R1157 1 + C1299 R1001 218 R1031 161 + C1299 R1080 -161 R1100 144 + C1299 R1103 -72 R1157 -1 + C1300 R1001 146 R1031 -35 + C1300 R1080 35 R1100 -145 + C1300 R1104 73 R1157 1 + C1301 R1031 -120 R1080 120 + C1301 R1158 1 + C1302 R1031 -189 R1080 189 + C1302 R1158 1 + C1303 R1001 437 R1031 -68 + C1303 R1080 68 R1174 1 + C1304 R1001 1482 R1031 -189 + C1304 R1080 189 + C1305 R1001 335 R1031 -104 + C1305 R1080 104 + C1306 R1001 291 R1031 -110 + C1306 R1080 110 + C1307 R1001 109 R1031 -71 + C1307 R1080 71 R1106 73 + C1308 R1001 328 R1032 -93 + C1308 R1081 93 R1175 1 + C1309 R1001 172 R1032 -59 + C1309 R1081 59 R1101 20 + C1310 R1001 120 R1032 -136 + C1310 R1081 136 R1176 1 + C1311 R1001 10 R1032 -10 + C1311 R1081 10 R1173 1 + C1312 R1001 240 R1032 -167 + C1312 R1081 167 R1100 -24 + C1312 R1102 20 R1159 1 + C1313 R1001 60 R1032 161 + C1313 R1081 -161 R1100 21 + C1313 R1103 -19 R1159 -1 + C1314 R1001 40 R1032 -35 + C1314 R1081 35 R1100 -22 + C1314 R1104 20 R1159 1 + C1315 R1032 -138 R1081 138 + C1316 R1001 120 R1032 -68 + C1316 R1081 68 R1174 1 + C1317 R1001 407 R1032 -189 + C1317 R1081 189 + C1318 R1001 92 R1032 -104 + C1318 R1081 104 + C1319 R1001 80 R1032 -110 + C1319 R1081 110 + C1320 R1001 30 R1032 -71 + C1320 R1081 71 R1106 20 + C1321 R1001 164 R1033 -93 + C1321 R1082 93 R1175 1 + C1322 R1001 60 R1033 -145 + C1322 R1082 145 + C1323 R1001 5 R1033 -10 + C1323 R1082 10 R1173 1 + C1324 R1001 30 R1033 161 + C1324 R1082 -161 R1100 22 + C1324 R1103 -9 R1160 -1 + C1325 R1001 20 R1033 -35 + C1325 R1082 35 R1100 -23 + C1325 R1104 10 R1160 1 + C1326 R1001 60 R1033 -68 + C1326 R1082 68 R1174 1 + C1327 R1001 204 R1033 -189 + C1327 R1082 189 + C1328 R1001 46 R1033 -104 + C1328 R1082 104 + C1329 R1001 15 R1033 -71 + C1329 R1082 71 R1106 10 + C1330 R1001 220 R1034 -93 + C1330 R1083 93 R1175 1 + C1331 R1001 80 R1034 -145 + C1331 R1083 145 + C1332 R1001 7 R1034 -10 + C1332 R1083 10 R1173 1 + C1333 R1001 27 R1034 -35 + C1333 R1083 35 R1100 -33 + C1333 R1104 13 R1161 1 + C1334 R1001 80 R1034 -68 + C1334 R1083 68 R1174 1 + C1335 R1001 273 R1034 -189 + C1335 R1083 189 + C1336 R1001 62 R1034 -104 + C1336 R1083 104 + C1337 R1001 20 R1034 -71 + C1337 R1083 71 R1106 13 + C1338 R1001 285 R1035 -93 + C1338 R1084 93 R1175 1 + C1339 R1001 104 R1035 -145 + C1339 R1084 145 + C1340 R1001 9 R1035 -10 + C1340 R1084 10 R1173 1 + C1341 R1035 -189 R1084 189 + C1342 R1001 104 R1035 -68 + C1342 R1084 68 R1174 1 + C1343 R1001 354 R1035 -189 + C1343 R1084 189 + C1344 R1001 80 R1035 -104 + C1344 R1084 104 + C1345 R1001 70 R1035 -110 + C1345 R1084 110 + C1346 R1001 26 R1035 -71 + C1346 R1084 71 R1106 17 + C1347 R1001 918 R1036 -93 + C1347 R1085 93 R1175 1 + C1348 R1001 336 R1036 -145 + C1348 R1085 145 + C1349 R1001 28 R1036 -10 + C1349 R1085 10 R1173 1 + C1350 R1036 -189 R1085 189 + C1351 R1001 336 R1036 -68 + C1351 R1085 68 R1174 1 + C1352 R1001 1140 R1036 -189 + C1352 R1085 189 + C1353 R1001 258 R1036 -104 + C1353 R1085 104 + C1354 R1001 224 R1036 -110 + C1354 R1085 110 + C1355 R1001 84 R1036 -71 + C1355 R1085 71 R1106 56 + C1356 R1001 256 R1037 -93 + C1356 R1086 -93 R1175 1 + C1357 R1001 94 R1037 -136 + C1357 R1086 -136 R1176 1 + C1358 R1001 8 R1037 -10 + C1358 R1086 -10 R1173 1 + C1359 R1001 187 R1037 -167 + C1359 R1086 -167 R1100 -19 + C1359 R1102 16 + C1360 R1037 -138 R1086 -138 + C1361 R1001 94 R1037 -68 + C1361 R1086 -68 R1174 1 + C1362 R1001 318 R1037 -189 + C1362 R1086 -189 + C1363 R1001 72 R1037 -104 + C1363 R1086 -104 + C1364 R1001 62 R1037 -110 + C1364 R1086 -110 + C1365 R1001 23 R1037 -71 + C1365 R1086 -71 R1106 16 + C1366 R1001 166 R1038 -93 + C1366 R1087 93 R1175 1 + C1367 R1001 87 R1038 -59 + C1367 R1087 59 R1101 10 + C1368 R1001 5 R1038 -10 + C1368 R1087 10 R1173 1 + C1369 R1001 121 R1038 -167 + C1369 R1087 167 R1100 -23 + C1369 R1102 10 R1162 1 + C1370 R1001 30 R1038 161 + C1370 R1087 -161 R1100 20 + C1370 R1103 -9 R1162 -1 + C1371 R1001 20 R1038 -35 + C1371 R1087 35 R1100 -21 + C1371 R1104 10 R1162 1 + C1372 R1038 -120 R1087 120 + C1372 R1163 1 + C1373 R1038 -189 R1087 189 + C1373 R1163 1 + C1374 R1001 61 R1038 -68 + C1374 R1087 68 R1174 1 + C1375 R1001 273 R1038 -180 + C1375 R1087 180 + C1376 R1001 56 R1038 -120 + C1376 R1087 120 + C1377 R1001 45 R1038 -100 + C1377 R1087 100 + C1378 R1001 15 R1038 -71 + C1378 R1087 71 R1106 10 + C1379 R1001 229 R1039 -59 + C1379 R1088 59 R1101 27 + C1380 R1001 36 R1039 -34 + C1380 R1088 34 + C1381 R1001 13 R1039 -10 + C1381 R1088 10 R1173 1 + C1382 R1001 319 R1039 -167 + C1382 R1088 167 R1100 -52 + C1382 R1102 27 R1164 1 + C1383 R1001 80 R1039 161 + C1383 R1088 -161 R1100 47 + C1383 R1103 -26 R1164 -1 + C1384 R1001 53 R1039 -35 + C1384 R1088 35 R1100 -48 + C1384 R1104 27 R1164 1 + C1385 R1039 -120 R1088 120 + C1385 R1165 1 + C1386 R1039 -189 R1088 189 + C1386 R1165 1 + C1387 R1001 160 R1039 -68 + C1387 R1088 68 R1174 1 + C1388 R1001 718 R1039 -180 + C1388 R1088 180 + C1389 R1001 146 R1039 -120 + C1389 R1088 120 + C1390 R1001 120 R1039 -100 + C1390 R1088 100 + C1391 R1001 40 R1039 -71 + C1391 R1088 71 R1106 27 + C1392 R1001 430 R1040 -59 + C1392 R1089 59 R1101 50 + C1393 R1001 25 R1040 -10 + C1393 R1089 10 R1173 1 + C1394 R1001 600 R1040 -167 + C1394 R1089 167 R1100 -120 + C1394 R1102 50 R1166 1 + C1395 R1001 150 R1040 161 + C1395 R1089 -161 R1100 109 + C1395 R1103 -49 R1166 -1 + C1396 R1001 100 R1040 -35 + C1396 R1089 35 R1100 -110 + C1396 R1104 50 R1166 1 + C1397 R1040 -120 R1089 120 + C1397 R1167 1 + C1398 R1040 -189 R1089 189 + C1398 R1167 1 + C1399 R1001 300 R1040 -68 + C1399 R1089 68 R1174 1 + C1400 R1001 1350 R1040 -180 + C1400 R1089 180 + C1401 R1001 275 R1040 -120 + C1401 R1089 120 + C1402 R1001 225 R1040 -100 + C1402 R1089 100 + C1403 R1001 75 R1040 -71 + C1403 R1089 71 R1106 50 + C1404 R1001 356 R1041 -93 + C1404 R1090 93 R1175 1 + C1405 R1001 187 R1041 -59 + C1405 R1090 59 R1101 22 + C1406 R1001 11 R1041 -10 + C1406 R1090 10 R1173 1 + C1407 R1001 260 R1041 -167 + C1407 R1090 167 R1100 -46 + C1407 R1102 22 R1168 1 + C1408 R1001 65 R1041 161 + C1408 R1090 -161 R1100 41 + C1408 R1103 -21 R1168 -1 + C1409 R1001 43 R1041 -35 + C1409 R1090 35 R1100 -42 + C1409 R1104 22 R1168 1 + C1410 R1041 -120 R1090 120 + C1410 R1169 1 + C1411 R1041 -189 R1090 189 + C1411 R1169 1 + C1412 R1001 130 R1041 -68 + C1412 R1090 68 R1174 1 + C1413 R1001 586 R1041 -180 + C1413 R1090 180 + C1414 R1001 119 R1041 -120 + C1414 R1090 120 + C1415 R1001 98 R1041 -100 + C1415 R1090 100 + C1416 R1001 33 R1041 -71 + C1416 R1090 71 R1106 22 + C1417 R1001 313 R1042 -93 + C1417 R1091 93 R1175 1 + C1418 R1001 26 R1042 -34 + C1418 R1091 34 + C1419 R1001 10 R1042 -10 + C1419 R1091 10 R1173 1 + C1420 R1001 229 R1042 -167 + C1420 R1091 167 R1100 -42 + C1420 R1102 19 R1170 1 + C1421 R1001 57 R1042 161 + C1421 R1091 -161 R1100 38 + C1421 R1103 -18 R1170 -1 + C1422 R1001 38 R1042 -35 + C1422 R1091 35 R1100 -39 + C1422 R1104 19 R1170 1 + C1423 R1042 -120 R1091 120 + C1423 R1171 1 + C1424 R1042 -189 R1091 189 + C1424 R1171 1 + C1425 R1001 115 R1042 -68 + C1425 R1091 68 R1174 1 + C1426 R1001 516 R1042 -180 + C1426 R1091 180 + C1427 R1001 105 R1042 -120 + C1427 R1091 120 + C1428 R1001 86 R1042 -100 + C1428 R1091 100 + C1429 R1001 29 R1042 -71 + C1429 R1091 71 R1106 19 + C1430 R1001 6 R1043 -10 + C1430 R1092 10 R1173 1 + C1431 R1001 24 R1043 -35 + C1431 R1092 35 R1100 -33 + C1431 R1104 12 R1172 1 + C1432 R1001 72 R1043 -68 + C1432 R1092 68 R1174 1 + C1433 R1001 324 R1043 -180 + C1433 R1092 180 + C1434 R1001 66 R1043 -120 + C1434 R1092 120 + C1435 R1001 18 R1043 -71 + C1435 R1092 71 R1106 12 + C1436 R1001 211 R1044 -93 + C1436 R1093 93 R1175 1 + C1437 R1001 17 R1044 -34 + C1437 R1093 34 + C1438 R1001 6 R1044 -10 + C1438 R1093 10 R1173 1 + C1439 R1001 39 R1044 161 + C1439 R1093 -161 R1100 23 + C1439 R1103 -12 + C1440 R1044 -189 R1093 189 + C1441 R1001 77 R1044 -68 + C1441 R1093 68 R1174 1 + C1442 R1001 348 R1044 -180 + C1442 R1093 180 + C1443 R1001 71 R1044 -120 + C1443 R1093 120 + C1444 R1001 58 R1044 -100 + C1444 R1093 100 + C1445 R1001 19 R1044 -71 + C1445 R1093 71 R1106 13 + C1446 R1001 285 R1045 -93 + C1446 R1094 93 R1175 1 + C1447 R1001 9 R1045 -10 + C1447 R1094 10 R1173 1 + C1448 R1045 -189 R1094 189 + C1449 R1001 104 R1045 -68 + C1449 R1094 68 R1174 1 + C1450 R1001 470 R1045 -180 + C1450 R1094 180 + C1451 R1001 96 R1045 -120 + C1451 R1094 120 + C1452 R1001 78 R1045 -100 + C1452 R1094 100 + C1453 R1001 26 R1045 -71 + C1453 R1094 71 R1106 17 + C1454 R1001 1454 R1046 -93 + C1454 R1095 93 R1175 1 + C1455 R1001 44 R1046 -10 + C1455 R1095 10 R1173 1 + C1456 R1046 -189 R1095 189 + C1457 R1001 532 R1046 -68 + C1457 R1095 68 R1174 1 + C1458 R1001 4435 R1046 -192 + C1458 R1095 192 + C1459 R1001 488 R1046 -120 + C1459 R1095 120 + C1460 R1001 399 R1046 -100 + C1460 R1095 100 + C1461 R1001 133 R1046 -71 + C1461 R1095 71 R1106 89 + C1462 R1001 295 R1047 -93 + C1462 R1096 93 R1175 1 + C1463 R1001 9 R1047 -10 + C1463 R1096 10 R1173 1 + C1464 R1047 -189 R1096 189 + C1465 R1001 108 R1047 -68 + C1465 R1096 68 R1174 1 + C1466 R1001 900 R1047 -192 + C1466 R1096 192 + C1467 R1001 99 R1047 -120 + C1467 R1096 120 + C1468 R1001 81 R1047 -100 + C1468 R1096 100 + C1469 R1001 27 R1047 -71 + C1469 R1096 71 R1106 18 + C1470 R1001 164 R1048 -93 + C1470 R1097 93 R1175 1 + C1471 R1001 60 R1048 -136 + C1471 R1097 136 R1176 1 + C1472 R1001 5 R1048 -10 + C1472 R1097 10 R1173 1 + C1473 R1048 -138 R1097 138 + C1474 R1001 60 R1048 -68 + C1474 R1097 68 R1174 1 + C1475 R1001 500 R1048 -192 + C1475 R1097 192 + C1476 R1001 55 R1048 -120 + C1476 R1097 120 + C1477 R1001 45 R1048 -100 + C1477 R1097 100 + C1478 R1001 15 R1048 -71 + C1478 R1097 71 R1106 10 + C1479 R1001 1165 R1049 -93 + C1479 R1098 -93 R1175 1 + C1480 R1001 36 R1049 -10 + C1480 R1098 -10 R1173 1 + C1481 R1049 -189 R1098 -189 + C1482 R1001 427 R1049 -68 + C1482 R1098 -68 R1174 1 + C1483 R1001 3555 R1049 -192 + C1483 R1098 -192 + C1484 R1001 391 R1049 -120 + C1484 R1098 -120 + C1485 R1001 320 R1049 -100 + C1485 R1098 -100 + C1486 R1001 107 R1049 -71 + C1486 R1098 -71 R1106 71 + C1487 R1001 399 R1050 -106 + C1487 R1099 106 R1175 1 + C1488 R1001 14 R1050 -10 + C1488 R1099 10 R1173 1 + C1489 R1050 -189 R1099 189 + C1490 R1001 164 R1050 -68 + C1490 R1099 68 R1174 1 + C1491 R1001 1370 R1050 -192 + C1491 R1099 192 + C1492 R1001 151 R1050 -120 + C1492 R1099 120 + C1493 R1001 123 R1050 -100 + C1493 R1099 100 + C1494 R1001 41 R1050 -71 + C1494 R1099 71 R1106 27 + C1495 R1001 100 R1173 -49 + C1496 R1001 1000 R1174 -49 + C1497 R1001 11000 R1175 -26 + C1498 R1001 2000 R1176 -5 + C1499 R1001 2600 R1177 -7 + C1500 R1002 9999 R1051 -9999 + C1500 R1100 -15 + C1501 R1003 9999 R1052 -9999 + C1501 R1100 -12 + C1502 R1004 9999 R1053 -9999 + C1502 R1100 -8 + C1503 R1005 9999 R1054 -9999 + C1503 R1100 -58 + C1504 R1006 9999 R1055 -9999 + C1504 R1100 -48 + C1505 R1007 9999 R1056 -9999 + C1505 R1100 -10 + C1506 R1008 9999 R1057 -9999 + C1506 R1100 -11 + C1507 R1009 9999 R1058 -9999 + C1507 R1100 -31 + C1508 R1010 9999 R1059 -9999 + C1508 R1100 -11 + C1509 R1011 9999 R1060 -9999 + C1509 R1100 -28 + C1510 R1012 9999 R1061 -9999 + C1510 R1100 -19 + C1511 R1013 9999 R1062 -9999 + C1511 R1100 -13 + C1512 R1014 9999 R1063 -9999 + C1512 R1100 -88 + C1513 R1015 9999 R1064 -9999 + C1513 R1100 -58 + C1514 R1016 9999 R1065 -9999 + C1514 R1100 -12 + C1515 R1017 9999 R1066 -9999 + C1515 R1100 -9 + C1516 R1018 9999 R1067 -9999 + C1516 R1100 -25 + C1517 R1019 9999 R1068 -9999 + C1517 R1100 -9 + C1518 R1020 9999 R1069 -9999 + C1518 R1100 -9 + C1519 R1021 9999 R1070 -9999 + C1519 R1100 -10 + C1520 R1022 9999 R1071 -9999 + C1520 R1100 -11 + C1521 R1023 9999 R1072 -9999 + C1521 R1100 -13 + C1522 R1024 9999 R1073 -9999 + C1522 R1100 -13 + C1523 R1025 9999 R1074 -9999 + C1523 R1100 -10 + C1524 R1026 9999 R1075 -9999 + C1524 R1100 -24 + C1525 R1027 9999 R1076 -9999 + C1525 R1100 -12 + C1526 R1028 9999 R1077 -9999 + C1526 R1100 -12 + C1527 R1029 9999 R1078 -9999 + C1527 R1100 -33 + C1528 R1030 9999 R1079 -9999 + C1528 R1100 -15 + C1529 R1031 9999 R1080 -9999 + C1529 R1100 -67 + C1530 R1032 9999 R1081 -9999 + C1530 R1100 -18 + C1531 R1033 9999 R1082 -9999 + C1531 R1100 -9 + C1532 R1034 9999 R1083 -9999 + C1532 R1100 -12 + C1533 R1035 9999 R1084 -9999 + C1533 R1100 -16 + C1534 R1036 9999 R1085 -9999 + C1534 R1100 -52 + C1535 R1037 9999 R1086 -9999 + C1535 R1100 -14 + C1536 R1038 9999 R1087 -9999 + C1536 R1100 -9 + C1537 R1039 9999 R1088 -9999 + C1537 R1100 -20 + C1538 R1040 9999 R1089 -9999 + C1538 R1100 -46 + C1539 R1041 9999 R1090 -9999 + C1539 R1100 -20 + C1540 R1042 9999 R1091 -9999 + C1540 R1100 -18 + C1541 R1043 9999 R1092 -9999 + C1541 R1100 -11 + C1542 R1044 9999 R1093 -9999 + C1542 R1100 -12 + C1543 R1045 9999 R1094 -9999 + C1543 R1100 -16 + C1544 R1046 9999 R1095 -9999 + C1544 R1100 -82 + C1545 R1047 9999 R1096 -9999 + C1545 R1100 -17 + C1546 R1048 9999 R1097 -9999 + C1546 R1100 -9 + C1547 R1049 9999 R1098 -9999 + C1547 R1100 -66 + C1548 R1050 9999 R1099 -9999 + C1548 R1100 -25 + MARK0001 'MARKER' 'INTEND' +RHS + RHS R1002 9303 R1003 9901 + RHS R1004 9509 R1005 9312 + RHS R1006 9805 R1007 9330 + RHS R1008 9446 R1009 9049 + RHS R1010 9485 R1011 10045 + RHS R1012 9740 R1013 9932 + RHS R1014 10018 R1015 9680 + RHS R1016 9240 R1017 9290 + RHS R1018 10053 R1019 9365 + RHS R1020 9826 R1021 9752 + RHS R1022 9544 R1023 9003 + RHS R1024 9827 R1025 9726 + RHS R1026 9774 R1027 8864 + RHS R1028 9910 R1029 9864 + RHS R1030 9910 R1031 9665 + RHS R1032 9653 R1033 9900 + RHS R1034 9559 R1035 9893 + RHS R1036 9605 R1037 8796 + RHS R1038 9078 R1039 9478 + RHS R1040 9647 R1041 10001 + RHS R1042 9601 R1043 9557 + RHS R1044 9729 R1045 9516 + RHS R1046 9179 R1047 9125 + RHS R1048 9723 R1049 8782 + RHS R1050 9690 R1051 154 + RHS R1052 -2 R1053 77 + RHS R1054 587 R1055 94 + RHS R1056 569 R1057 453 + RHS R1058 850 R1059 414 + RHS R1060 -146 R1061 159 + RHS R1062 -33 R1063 -119 + RHS R1064 219 R1065 659 + RHS R1066 609 R1067 -154 + RHS R1068 534 R1069 73 + RHS R1070 147 R1071 355 + RHS R1072 138 R1073 72 + RHS R1074 173 R1075 125 + RHS R1076 -1 R1077 -11 + RHS R1078 35 R1079 -11 + RHS R1080 234 R1081 246 + RHS R1082 -1 R1083 340 + RHS R1084 6 R1085 294 + RHS R1086 -69 R1087 821 + RHS R1088 421 R1089 252 + RHS R1090 -102 R1091 298 + RHS R1092 342 R1093 170 + RHS R1094 383 R1095 720 + RHS R1096 774 R1097 176 + RHS R1098 -83 R1099 209 + RHS R1100 -920 R1101 1200 + RHS R1102 350 R1103 -104 + RHS R1104 195 R1105 40 + RHS R1106 1564 R1107 198 + RHS R1110 1 R1112 1 + RHS R1114 1 R1116 1 + RHS R1118 1 R1119 1 + RHS R1124 1 R1126 1 + RHS R1128 1 R1130 1 + RHS R1132 1 R1133 1 + RHS R1138 1 R1140 1 + RHS R1142 1 R1144 1 + RHS R1147 1 R1149 1 + RHS R1150 1 R1152 1 + RHS R1154 1 R1156 1 + RHS R1158 1 R1161 1 + RHS R1163 1 R1165 1 + RHS R1167 1 R1169 1 + RHS R1171 1 R1172 1 +BOUNDS + UP ONE C1001 1 + UP ONE C1002 1 + UP ONE C1003 1 + UP ONE C1004 1 + UP ONE C1005 1 + UP ONE C1006 1 + UP ONE C1007 1 + UP ONE C1008 1 + UP ONE C1009 1 + UP ONE C1010 1 + UP ONE C1011 1 + UP ONE C1012 1 + UP ONE C1013 1 + UP ONE C1014 1 + UP ONE C1015 1 + UP ONE C1016 1 + UP ONE C1017 1 + UP ONE C1018 1 + UP ONE C1019 1 + UP ONE C1020 1 + UP ONE C1021 1 + UP ONE C1022 1 + UP ONE C1023 1 + UP ONE C1024 1 + UP ONE C1025 1 + UP ONE C1026 1 + UP ONE C1027 1 + UP ONE C1028 1 + UP ONE C1029 1 + UP ONE C1030 1 + UP ONE C1031 1 + UP ONE C1032 1 + UP ONE C1033 1 + UP ONE C1034 1 + UP ONE C1035 1 + UP ONE C1036 1 + UP ONE C1037 1 + UP ONE C1038 1 + UP ONE C1039 1 + UP ONE C1040 1 + UP ONE C1041 1 + UP ONE C1042 1 + UP ONE C1043 1 + UP ONE C1044 1 + UP ONE C1045 1 + UP ONE C1046 1 + UP ONE C1047 1 + UP ONE C1048 1 + UP ONE C1049 1 + UP ONE C1050 1 + UP ONE C1051 1 + UP ONE C1052 1 + UP ONE C1053 1 + UP ONE C1054 1 + UP ONE C1055 1 + UP ONE C1056 1 + UP ONE C1057 1 + UP ONE C1058 1 + UP ONE C1059 1 + UP ONE C1060 1 + UP ONE C1061 1 + UP ONE C1062 1 + UP ONE C1063 1 + UP ONE C1064 1 + UP ONE C1065 1 + UP ONE C1066 1 + UP ONE C1067 1 + UP ONE C1068 1 + UP ONE C1069 1 + UP ONE C1070 1 + UP ONE C1071 1 + UP ONE C1072 1 + UP ONE C1073 1 + UP ONE C1074 1 + UP ONE C1075 1 + UP ONE C1076 1 + UP ONE C1077 1 + UP ONE C1078 1 + UP ONE C1079 1 + UP ONE C1080 1 + UP ONE C1081 1 + UP ONE C1082 1 + UP ONE C1083 1 + UP ONE C1084 1 + UP ONE C1085 1 + UP ONE C1086 1 + UP ONE C1087 1 + UP ONE C1088 1 + UP ONE C1089 1 + UP ONE C1090 1 + UP ONE C1091 1 + UP ONE C1092 1 + UP ONE C1093 1 + UP ONE C1094 1 + UP ONE C1095 1 + UP ONE C1096 1 + UP ONE C1097 1 + UP ONE C1098 1 + UP ONE C1099 1 + UP ONE C1100 1 + UP ONE C1101 1 + UP ONE C1102 1 + UP ONE C1103 1 + UP ONE C1104 1 + UP ONE C1105 1 + UP ONE C1106 1 + UP ONE C1107 1 + UP ONE C1108 1 + UP ONE C1109 1 + UP ONE C1110 1 + UP ONE C1111 1 + UP ONE C1112 1 + UP ONE C1113 1 + UP ONE C1114 1 + UP ONE C1115 1 + UP ONE C1116 1 + UP ONE C1117 1 + UP ONE C1118 1 + UP ONE C1119 1 + UP ONE C1120 1 + UP ONE C1121 1 + UP ONE C1122 1 + UP ONE C1123 1 + UP ONE C1124 1 + UP ONE C1125 1 + UP ONE C1126 1 + UP ONE C1127 1 + UP ONE C1128 1 + UP ONE C1129 1 + UP ONE C1130 1 + UP ONE C1131 1 + UP ONE C1132 1 + UP ONE C1133 1 + UP ONE C1134 1 + UP ONE C1135 1 + UP ONE C1136 1 + UP ONE C1137 1 + UP ONE C1138 1 + UP ONE C1139 1 + UP ONE C1140 1 + UP ONE C1141 1 + UP ONE C1142 1 + UP ONE C1143 1 + UP ONE C1144 1 + UP ONE C1145 1 + UP ONE C1146 1 + UP ONE C1147 1 + UP ONE C1148 1 + UP ONE C1149 1 + UP ONE C1150 1 + UP ONE C1151 1 + UP ONE C1152 1 + UP ONE C1153 1 + UP ONE C1154 1 + UP ONE C1155 1 + UP ONE C1156 1 + UP ONE C1157 1 + UP ONE C1158 1 + UP ONE C1159 1 + UP ONE C1160 1 + UP ONE C1161 1 + UP ONE C1162 1 + UP ONE C1163 1 + UP ONE C1164 1 + UP ONE C1165 1 + UP ONE C1166 1 + UP ONE C1167 1 + UP ONE C1168 1 + UP ONE C1169 1 + UP ONE C1170 1 + UP ONE C1171 1 + UP ONE C1172 1 + UP ONE C1173 1 + UP ONE C1174 1 + UP ONE C1175 1 + UP ONE C1176 1 + UP ONE C1177 1 + UP ONE C1178 1 + UP ONE C1179 1 + UP ONE C1180 1 + UP ONE C1181 1 + UP ONE C1182 1 + UP ONE C1183 1 + UP ONE C1184 1 + UP ONE C1185 1 + UP ONE C1186 1 + UP ONE C1187 1 + UP ONE C1188 1 + UP ONE C1189 1 + UP ONE C1190 1 + UP ONE C1191 1 + UP ONE C1192 1 + UP ONE C1193 1 + UP ONE C1194 1 + UP ONE C1195 1 + UP ONE C1196 1 + UP ONE C1197 1 + UP ONE C1198 1 + UP ONE C1199 1 + UP ONE C1200 1 + UP ONE C1201 1 + UP ONE C1202 1 + UP ONE C1203 1 + UP ONE C1204 1 + UP ONE C1205 1 + UP ONE C1206 1 + UP ONE C1207 1 + UP ONE C1208 1 + UP ONE C1209 1 + UP ONE C1210 1 + UP ONE C1211 1 + UP ONE C1212 1 + UP ONE C1213 1 + UP ONE C1214 1 + UP ONE C1215 1 + UP ONE C1216 1 + UP ONE C1217 1 + UP ONE C1218 1 + UP ONE C1219 1 + UP ONE C1220 1 + UP ONE C1221 1 + UP ONE C1222 1 + UP ONE C1223 1 + UP ONE C1224 1 + UP ONE C1225 1 + UP ONE C1226 1 + UP ONE C1227 1 + UP ONE C1228 1 + UP ONE C1229 1 + UP ONE C1230 1 + UP ONE C1231 1 + UP ONE C1232 1 + UP ONE C1233 1 + UP ONE C1234 1 + UP ONE C1235 1 + UP ONE C1236 1 + UP ONE C1237 1 + UP ONE C1238 1 + UP ONE C1239 1 + UP ONE C1240 1 + UP ONE C1241 1 + UP ONE C1242 1 + UP ONE C1243 1 + UP ONE C1244 1 + UP ONE C1245 1 + UP ONE C1246 1 + UP ONE C1247 1 + UP ONE C1248 1 + UP ONE C1249 1 + UP ONE C1250 1 + UP ONE C1251 1 + UP ONE C1252 1 + UP ONE C1253 1 + UP ONE C1254 1 + UP ONE C1255 1 + UP ONE C1256 1 + UP ONE C1257 1 + UP ONE C1258 1 + UP ONE C1259 1 + UP ONE C1260 1 + UP ONE C1261 1 + UP ONE C1262 1 + UP ONE C1263 1 + UP ONE C1264 1 + UP ONE C1265 1 + UP ONE C1266 1 + UP ONE C1267 1 + UP ONE C1268 1 + UP ONE C1269 1 + UP ONE C1270 1 + UP ONE C1271 1 + UP ONE C1272 1 + UP ONE C1273 1 + UP ONE C1274 1 + UP ONE C1275 1 + UP ONE C1276 1 + UP ONE C1277 1 + UP ONE C1278 1 + UP ONE C1279 1 + UP ONE C1280 1 + UP ONE C1281 1 + UP ONE C1282 1 + UP ONE C1283 1 + UP ONE C1284 1 + UP ONE C1285 1 + UP ONE C1286 1 + UP ONE C1287 1 + UP ONE C1288 1 + UP ONE C1289 1 + UP ONE C1290 1 + UP ONE C1291 1 + UP ONE C1292 1 + UP ONE C1293 1 + UP ONE C1294 1 + UP ONE C1295 1 + UP ONE C1296 1 + UP ONE C1297 1 + UP ONE C1298 1 + UP ONE C1299 1 + UP ONE C1300 1 + UP ONE C1301 1 + UP ONE C1302 1 + UP ONE C1303 1 + UP ONE C1304 1 + UP ONE C1305 1 + UP ONE C1306 1 + UP ONE C1307 1 + UP ONE C1308 1 + UP ONE C1309 1 + UP ONE C1310 1 + UP ONE C1311 1 + UP ONE C1312 1 + UP ONE C1313 1 + UP ONE C1314 1 + UP ONE C1315 1 + UP ONE C1316 1 + UP ONE C1317 1 + UP ONE C1318 1 + UP ONE C1319 1 + UP ONE C1320 1 + UP ONE C1321 1 + UP ONE C1322 1 + UP ONE C1323 1 + UP ONE C1324 1 + UP ONE C1325 1 + UP ONE C1326 1 + UP ONE C1327 1 + UP ONE C1328 1 + UP ONE C1329 1 + UP ONE C1330 1 + UP ONE C1331 1 + UP ONE C1332 1 + UP ONE C1333 1 + UP ONE C1334 1 + UP ONE C1335 1 + UP ONE C1336 1 + UP ONE C1337 1 + UP ONE C1338 1 + UP ONE C1339 1 + UP ONE C1340 1 + UP ONE C1341 1 + UP ONE C1342 1 + UP ONE C1343 1 + UP ONE C1344 1 + UP ONE C1345 1 + UP ONE C1346 1 + UP ONE C1347 1 + UP ONE C1348 1 + UP ONE C1349 1 + UP ONE C1350 1 + UP ONE C1351 1 + UP ONE C1352 1 + UP ONE C1353 1 + UP ONE C1354 1 + UP ONE C1355 1 + UP ONE C1356 1 + UP ONE C1357 1 + UP ONE C1358 1 + UP ONE C1359 1 + UP ONE C1360 1 + UP ONE C1361 1 + UP ONE C1362 1 + UP ONE C1363 1 + UP ONE C1364 1 + UP ONE C1365 1 + UP ONE C1366 1 + UP ONE C1367 1 + UP ONE C1368 1 + UP ONE C1369 1 + UP ONE C1370 1 + UP ONE C1371 1 + UP ONE C1372 1 + UP ONE C1373 1 + UP ONE C1374 1 + UP ONE C1375 1 + UP ONE C1376 1 + UP ONE C1377 1 + UP ONE C1378 1 + UP ONE C1379 1 + UP ONE C1380 1 + UP ONE C1381 1 + UP ONE C1382 1 + UP ONE C1383 1 + UP ONE C1384 1 + UP ONE C1385 1 + UP ONE C1386 1 + UP ONE C1387 1 + UP ONE C1388 1 + UP ONE C1389 1 + UP ONE C1390 1 + UP ONE C1391 1 + UP ONE C1392 1 + UP ONE C1393 1 + UP ONE C1394 1 + UP ONE C1395 1 + UP ONE C1396 1 + UP ONE C1397 1 + UP ONE C1398 1 + UP ONE C1399 1 + UP ONE C1400 1 + UP ONE C1401 1 + UP ONE C1402 1 + UP ONE C1403 1 + UP ONE C1404 1 + UP ONE C1405 1 + UP ONE C1406 1 + UP ONE C1407 1 + UP ONE C1408 1 + UP ONE C1409 1 + UP ONE C1410 1 + UP ONE C1411 1 + UP ONE C1412 1 + UP ONE C1413 1 + UP ONE C1414 1 + UP ONE C1415 1 + UP ONE C1416 1 + UP ONE C1417 1 + UP ONE C1418 1 + UP ONE C1419 1 + UP ONE C1420 1 + UP ONE C1421 1 + UP ONE C1422 1 + UP ONE C1423 1 + UP ONE C1424 1 + UP ONE C1425 1 + UP ONE C1426 1 + UP ONE C1427 1 + UP ONE C1428 1 + UP ONE C1429 1 + UP ONE C1430 1 + UP ONE C1431 1 + UP ONE C1432 1 + UP ONE C1433 1 + UP ONE C1434 1 + UP ONE C1435 1 + UP ONE C1436 1 + UP ONE C1437 1 + UP ONE C1438 1 + UP ONE C1439 1 + UP ONE C1440 1 + UP ONE C1441 1 + UP ONE C1442 1 + UP ONE C1443 1 + UP ONE C1444 1 + UP ONE C1445 1 + UP ONE C1446 1 + UP ONE C1447 1 + UP ONE C1448 1 + UP ONE C1449 1 + UP ONE C1450 1 + UP ONE C1451 1 + UP ONE C1452 1 + UP ONE C1453 1 + UP ONE C1454 1 + UP ONE C1455 1 + UP ONE C1456 1 + UP ONE C1457 1 + UP ONE C1458 1 + UP ONE C1459 1 + UP ONE C1460 1 + UP ONE C1461 1 + UP ONE C1462 1 + UP ONE C1463 1 + UP ONE C1464 1 + UP ONE C1465 1 + UP ONE C1466 1 + UP ONE C1467 1 + UP ONE C1468 1 + UP ONE C1469 1 + UP ONE C1470 1 + UP ONE C1471 1 + UP ONE C1472 1 + UP ONE C1473 1 + UP ONE C1474 1 + UP ONE C1475 1 + UP ONE C1476 1 + UP ONE C1477 1 + UP ONE C1478 1 + UP ONE C1479 1 + UP ONE C1480 1 + UP ONE C1481 1 + UP ONE C1482 1 + UP ONE C1483 1 + UP ONE C1484 1 + UP ONE C1485 1 + UP ONE C1486 1 + UP ONE C1487 1 + UP ONE C1488 1 + UP ONE C1489 1 + UP ONE C1490 1 + UP ONE C1491 1 + UP ONE C1492 1 + UP ONE C1493 1 + UP ONE C1494 1 + UP ONE C1495 1 + UP ONE C1496 1 + UP ONE C1497 1 + UP ONE C1498 1 + UP ONE C1499 1 + UP ONE C1500 1 + UP ONE C1501 1 + UP ONE C1502 1 + UP ONE C1503 1 + UP ONE C1504 1 + UP ONE C1505 1 + UP ONE C1506 1 + UP ONE C1507 1 + UP ONE C1508 1 + UP ONE C1509 1 + UP ONE C1510 1 + UP ONE C1511 1 + UP ONE C1512 1 + UP ONE C1513 1 + UP ONE C1514 1 + UP ONE C1515 1 + UP ONE C1516 1 + UP ONE C1517 1 + UP ONE C1518 1 + UP ONE C1519 1 + UP ONE C1520 1 + UP ONE C1521 1 + UP ONE C1522 1 + UP ONE C1523 1 + UP ONE C1524 1 + UP ONE C1525 1 + UP ONE C1526 1 + UP ONE C1527 1 + UP ONE C1528 1 + UP ONE C1529 1 + UP ONE C1530 1 + UP ONE C1531 1 + UP ONE C1532 1 + UP ONE C1533 1 + UP ONE C1534 1 + UP ONE C1535 1 + UP ONE C1536 1 + UP ONE C1537 1 + UP ONE C1538 1 + UP ONE C1539 1 + UP ONE C1540 1 + UP ONE C1541 1 + UP ONE C1542 1 + UP ONE C1543 1 + UP ONE C1544 1 + UP ONE C1545 1 + UP ONE C1546 1 + UP ONE C1547 1 + UP ONE C1548 1 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/pack1.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/pack1.mps new file mode 100644 index 000000000..6db7ab885 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/pack1.mps @@ -0,0 +1,35 @@ +************************************************************************ +* +* The data in this file represents a tiny covering problem: +* +* Minimize or maximize Z = x1 + x2 + x3 +* +* Subject to: +* +* 1.0 <= x1 + x2 +* 1.0 <= x2 + x3 +* 1.0 <= x1 x3 +* +* where all variables are binary. +* +************************************************************************ +NAME EXAMPLE +ROWS + N OBJ + G ROW01 + G ROW02 + G ROW03 +COLUMNS + INT1 'MARKER' 'INTORG' + COL01 OBJ 1.0 + COL01 ROW01 1.0 ROW03 1.0 + COL02 OBJ 1.0 + COL02 ROW01 1.0 ROW02 1.0 + COL03 OBJ 1.0 + COL03 ROW02 1.0 ROW03 1.0 + INT1END 'MARKER' 'INTEND' +RHS + RHS1 ROW01 1.0 + RHS1 ROW02 1.0 + RHS1 ROW03 1.0 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.block b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.block new file mode 100644 index 000000000..dcd539464 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.block @@ -0,0 +1,200 @@ +0 3 +0 53 +0 103 +0 153 +1 4 +1 54 +1 104 +1 154 +2 5 +2 55 +2 105 +2 155 +3 6 +3 56 +3 106 +3 156 +4 7 +4 57 +4 107 +4 157 +5 8 +5 58 +5 108 +5 158 +6 9 +6 59 +6 109 +6 159 +7 10 +7 60 +7 110 +7 160 +8 11 +8 61 +8 111 +8 161 +9 12 +9 62 +9 112 +9 162 +10 13 +10 63 +10 113 +10 163 +11 14 +11 64 +11 114 +11 164 +12 15 +12 65 +12 115 +12 165 +13 16 +13 66 +13 116 +13 166 +14 17 +14 67 +14 117 +14 167 +15 18 +15 68 +15 118 +15 168 +16 19 +16 69 +16 119 +16 169 +17 20 +17 70 +17 120 +17 170 +18 21 +18 71 +18 121 +18 171 +19 22 +19 72 +19 122 +19 172 +20 23 +20 73 +20 123 +20 173 +21 24 +21 74 +21 124 +21 174 +22 25 +22 75 +22 125 +22 175 +23 26 +23 76 +23 126 +23 176 +24 27 +24 77 +24 127 +24 177 +25 28 +25 78 +25 128 +25 178 +26 29 +26 79 +26 129 +26 179 +27 30 +27 80 +27 130 +27 180 +28 31 +28 81 +28 131 +28 181 +29 32 +29 82 +29 132 +29 182 +30 33 +30 83 +30 133 +30 183 +31 34 +31 84 +31 134 +31 184 +32 35 +32 85 +32 135 +32 185 +33 36 +33 86 +33 136 +33 186 +34 37 +34 87 +34 137 +34 187 +35 38 +35 88 +35 138 +35 188 +36 39 +36 89 +36 139 +36 189 +37 40 +37 90 +37 140 +37 190 +38 41 +38 91 +38 141 +38 191 +39 42 +39 92 +39 142 +39 192 +40 43 +40 93 +40 143 +40 193 +41 44 +41 94 +41 144 +41 194 +42 45 +42 95 +42 145 +42 195 +43 46 +43 96 +43 146 +43 196 +44 47 +44 97 +44 147 +44 197 +45 48 +45 98 +45 148 +45 198 +46 49 +46 99 +46 149 +46 199 +47 50 +47 100 +47 150 +47 200 +48 51 +48 101 +48 151 +48 201 +49 52 +49 102 +49 152 +49 202 diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.mps new file mode 100644 index 000000000..b0af6d4b0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/retail3.mps @@ -0,0 +1,2218 @@ +NAME kohls3_ld1 +ROWS + N TotalCost + E material_balance[Pack1] + E material_balance[Pack2] + E material_balance[Pack3] + E demand_fit['71',S] + E demand_fit['73',S] + E demand_fit['86',S] + E demand_fit['99',S] + E demand_fit['103',S] + E demand_fit['126',S] + E demand_fit['221',S] + E demand_fit['225',S] + E demand_fit['251',S] + E demand_fit['270',S] + E demand_fit['272',S] + E demand_fit['275',S] + E demand_fit['276',S] + E demand_fit['280',S] + E demand_fit['282',S] + E demand_fit['283',S] + E demand_fit['293',S] + E demand_fit['298',S] + E demand_fit['299',S] + E demand_fit['301',S] + E demand_fit['309',S] + E demand_fit['310',S] + E demand_fit['375',S] + E demand_fit['378',S] + E demand_fit['379',S] + E demand_fit['381',S] + E demand_fit['383',S] + E demand_fit['384',S] + E demand_fit['386',S] + E demand_fit['388',S] + E demand_fit['389',S] + E demand_fit['390',S] + E demand_fit['397',S] + E demand_fit['398',S] + E demand_fit['403',S] + E demand_fit['418',S] + E demand_fit['430',S] + E demand_fit['431',S] + E demand_fit['479',S] + E demand_fit['502',S] + E demand_fit['504',S] + E demand_fit['512',S] + E demand_fit['528',S] + E demand_fit['533',S] + E demand_fit['538',S] + E demand_fit['552',S] + E demand_fit['621',S] + E demand_fit['639',S] + E demand_fit['712',S] + E demand_fit['781',S] + E demand_fit['71',M] + E demand_fit['73',M] + E demand_fit['86',M] + E demand_fit['99',M] + E demand_fit['103',M] + E demand_fit['126',M] + E demand_fit['221',M] + E demand_fit['225',M] + E demand_fit['251',M] + E demand_fit['270',M] + E demand_fit['272',M] + E demand_fit['275',M] + E demand_fit['276',M] + E demand_fit['280',M] + E demand_fit['282',M] + E demand_fit['283',M] + E demand_fit['293',M] + E demand_fit['298',M] + E demand_fit['299',M] + E demand_fit['301',M] + E demand_fit['309',M] + E demand_fit['310',M] + E demand_fit['375',M] + E demand_fit['378',M] + E demand_fit['379',M] + E demand_fit['381',M] + E demand_fit['383',M] + E demand_fit['384',M] + E demand_fit['386',M] + E demand_fit['388',M] + E demand_fit['389',M] + E demand_fit['390',M] + E demand_fit['397',M] + E demand_fit['398',M] + E demand_fit['403',M] + E demand_fit['418',M] + E demand_fit['430',M] + E demand_fit['431',M] + E demand_fit['479',M] + E demand_fit['502',M] + E demand_fit['504',M] + E demand_fit['512',M] + E demand_fit['528',M] + E demand_fit['533',M] + E demand_fit['538',M] + E demand_fit['552',M] + E demand_fit['621',M] + E demand_fit['639',M] + E demand_fit['712',M] + E demand_fit['781',M] + E demand_fit['71',L] + E demand_fit['73',L] + E demand_fit['86',L] + E demand_fit['99',L] + E demand_fit['103',L] + E demand_fit['126',L] + E demand_fit['221',L] + E demand_fit['225',L] + E demand_fit['251',L] + E demand_fit['270',L] + E demand_fit['272',L] + E demand_fit['275',L] + E demand_fit['276',L] + E demand_fit['280',L] + E demand_fit['282',L] + E demand_fit['283',L] + E demand_fit['293',L] + E demand_fit['298',L] + E demand_fit['299',L] + E demand_fit['301',L] + E demand_fit['309',L] + E demand_fit['310',L] + E demand_fit['375',L] + E demand_fit['378',L] + E demand_fit['379',L] + E demand_fit['381',L] + E demand_fit['383',L] + E demand_fit['384',L] + E demand_fit['386',L] + E demand_fit['388',L] + E demand_fit['389',L] + E demand_fit['390',L] + E demand_fit['397',L] + E demand_fit['398',L] + E demand_fit['403',L] + E demand_fit['418',L] + E demand_fit['430',L] + E demand_fit['431',L] + E demand_fit['479',L] + E demand_fit['502',L] + E demand_fit['504',L] + E demand_fit['512',L] + E demand_fit['528',L] + E demand_fit['533',L] + E demand_fit['538',L] + E demand_fit['552',L] + E demand_fit['621',L] + E demand_fit['639',L] + E demand_fit['712',L] + E demand_fit['781',L] + E demand_fit['71',XL] + E demand_fit['73',XL] + E demand_fit['86',XL] + E demand_fit['99',XL] + E demand_fit['103',XL] + E demand_fit['126',XL] + E demand_fit['221',XL] + E demand_fit['225',XL] + E demand_fit['251',XL] + E demand_fit['270',XL] + E demand_fit['272',XL] + E demand_fit['275',XL] + E demand_fit['276',XL] + E demand_fit['280',XL] + E demand_fit['282',XL] + E demand_fit['283',XL] + E demand_fit['293',XL] + E demand_fit['298',XL] + E demand_fit['299',XL] + E demand_fit['301',XL] + E demand_fit['309',XL] + E demand_fit['310',XL] + E demand_fit['375',XL] + E demand_fit['378',XL] + E demand_fit['379',XL] + E demand_fit['381',XL] + E demand_fit['383',XL] + E demand_fit['384',XL] + E demand_fit['386',XL] + E demand_fit['388',XL] + E demand_fit['389',XL] + E demand_fit['390',XL] + E demand_fit['397',XL] + E demand_fit['398',XL] + E demand_fit['403',XL] + E demand_fit['418',XL] + E demand_fit['430',XL] + E demand_fit['431',XL] + E demand_fit['479',XL] + E demand_fit['502',XL] + E demand_fit['504',XL] + E demand_fit['512',XL] + E demand_fit['528',XL] + E demand_fit['533',XL] + E demand_fit['538',XL] + E demand_fit['552',XL] + E demand_fit['621',XL] + E demand_fit['639',XL] + E demand_fit['712',XL] + E demand_fit['781',XL] +COLUMNS + .MRK0000 'MARKER' 'INTORG' + NumLooseInners['71',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['71',Pack1] demand_fit['71',S] 1 demand_fit['71',M] 3 + NumLooseInners['71',Pack1] demand_fit['71',L] 4 demand_fit['71',XL] 4 + NumLooseInners['73',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['73',Pack1] demand_fit['73',S] 1 demand_fit['73',M] 3 + NumLooseInners['73',Pack1] demand_fit['73',L] 4 demand_fit['73',XL] 4 + NumLooseInners['86',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['86',Pack1] demand_fit['86',S] 1 demand_fit['86',M] 3 + NumLooseInners['86',Pack1] demand_fit['86',L] 4 demand_fit['86',XL] 4 + NumLooseInners['99',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['99',Pack1] demand_fit['99',S] 1 demand_fit['99',M] 3 + NumLooseInners['99',Pack1] demand_fit['99',L] 4 demand_fit['99',XL] 4 + NumLooseInners['103',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['103',Pack1] demand_fit['103',S] 1 demand_fit['103',M] 3 + NumLooseInners['103',Pack1] demand_fit['103',L] 4 demand_fit['103',XL] 4 + NumLooseInners['126',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['126',Pack1] demand_fit['126',S] 1 demand_fit['126',M] 3 + NumLooseInners['126',Pack1] demand_fit['126',L] 4 demand_fit['126',XL] 4 + NumLooseInners['221',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['221',Pack1] demand_fit['221',S] 1 demand_fit['221',M] 3 + NumLooseInners['221',Pack1] demand_fit['221',L] 4 demand_fit['221',XL] 4 + NumLooseInners['225',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['225',Pack1] demand_fit['225',S] 1 demand_fit['225',M] 3 + NumLooseInners['225',Pack1] demand_fit['225',L] 4 demand_fit['225',XL] 4 + NumLooseInners['251',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['251',Pack1] demand_fit['251',S] 1 demand_fit['251',M] 3 + NumLooseInners['251',Pack1] demand_fit['251',L] 4 demand_fit['251',XL] 4 + NumLooseInners['270',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['270',Pack1] demand_fit['270',S] 1 demand_fit['270',M] 3 + NumLooseInners['270',Pack1] demand_fit['270',L] 4 demand_fit['270',XL] 4 + NumLooseInners['272',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['272',Pack1] demand_fit['272',S] 1 demand_fit['272',M] 3 + NumLooseInners['272',Pack1] demand_fit['272',L] 4 demand_fit['272',XL] 4 + NumLooseInners['275',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['275',Pack1] demand_fit['275',S] 1 demand_fit['275',M] 3 + NumLooseInners['275',Pack1] demand_fit['275',L] 4 demand_fit['275',XL] 4 + NumLooseInners['276',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['276',Pack1] demand_fit['276',S] 1 demand_fit['276',M] 3 + NumLooseInners['276',Pack1] demand_fit['276',L] 4 demand_fit['276',XL] 4 + NumLooseInners['280',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['280',Pack1] demand_fit['280',S] 1 demand_fit['280',M] 3 + NumLooseInners['280',Pack1] demand_fit['280',L] 4 demand_fit['280',XL] 4 + NumLooseInners['282',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['282',Pack1] demand_fit['282',S] 1 demand_fit['282',M] 3 + NumLooseInners['282',Pack1] demand_fit['282',L] 4 demand_fit['282',XL] 4 + NumLooseInners['283',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['283',Pack1] demand_fit['283',S] 1 demand_fit['283',M] 3 + NumLooseInners['283',Pack1] demand_fit['283',L] 4 demand_fit['283',XL] 4 + NumLooseInners['293',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['293',Pack1] demand_fit['293',S] 1 demand_fit['293',M] 3 + NumLooseInners['293',Pack1] demand_fit['293',L] 4 demand_fit['293',XL] 4 + NumLooseInners['298',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['298',Pack1] demand_fit['298',S] 1 demand_fit['298',M] 3 + NumLooseInners['298',Pack1] demand_fit['298',L] 4 demand_fit['298',XL] 4 + NumLooseInners['299',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['299',Pack1] demand_fit['299',S] 1 demand_fit['299',M] 3 + NumLooseInners['299',Pack1] demand_fit['299',L] 4 demand_fit['299',XL] 4 + NumLooseInners['301',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['301',Pack1] demand_fit['301',S] 1 demand_fit['301',M] 3 + NumLooseInners['301',Pack1] demand_fit['301',L] 4 demand_fit['301',XL] 4 + NumLooseInners['309',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['309',Pack1] demand_fit['309',S] 1 demand_fit['309',M] 3 + NumLooseInners['309',Pack1] demand_fit['309',L] 4 demand_fit['309',XL] 4 + NumLooseInners['310',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['310',Pack1] demand_fit['310',S] 1 demand_fit['310',M] 3 + NumLooseInners['310',Pack1] demand_fit['310',L] 4 demand_fit['310',XL] 4 + NumLooseInners['375',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['375',Pack1] demand_fit['375',S] 1 demand_fit['375',M] 3 + NumLooseInners['375',Pack1] demand_fit['375',L] 4 demand_fit['375',XL] 4 + NumLooseInners['378',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['378',Pack1] demand_fit['378',S] 1 demand_fit['378',M] 3 + NumLooseInners['378',Pack1] demand_fit['378',L] 4 demand_fit['378',XL] 4 + NumLooseInners['379',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['379',Pack1] demand_fit['379',S] 1 demand_fit['379',M] 3 + NumLooseInners['379',Pack1] demand_fit['379',L] 4 demand_fit['379',XL] 4 + NumLooseInners['381',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['381',Pack1] demand_fit['381',S] 1 demand_fit['381',M] 3 + NumLooseInners['381',Pack1] demand_fit['381',L] 4 demand_fit['381',XL] 4 + NumLooseInners['383',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['383',Pack1] demand_fit['383',S] 1 demand_fit['383',M] 3 + NumLooseInners['383',Pack1] demand_fit['383',L] 4 demand_fit['383',XL] 4 + NumLooseInners['384',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['384',Pack1] demand_fit['384',S] 1 demand_fit['384',M] 3 + NumLooseInners['384',Pack1] demand_fit['384',L] 4 demand_fit['384',XL] 4 + NumLooseInners['386',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['386',Pack1] demand_fit['386',S] 1 demand_fit['386',M] 3 + NumLooseInners['386',Pack1] demand_fit['386',L] 4 demand_fit['386',XL] 4 + NumLooseInners['388',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['388',Pack1] demand_fit['388',S] 1 demand_fit['388',M] 3 + NumLooseInners['388',Pack1] demand_fit['388',L] 4 demand_fit['388',XL] 4 + NumLooseInners['389',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['389',Pack1] demand_fit['389',S] 1 demand_fit['389',M] 3 + NumLooseInners['389',Pack1] demand_fit['389',L] 4 demand_fit['389',XL] 4 + NumLooseInners['390',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['390',Pack1] demand_fit['390',S] 1 demand_fit['390',M] 3 + NumLooseInners['390',Pack1] demand_fit['390',L] 4 demand_fit['390',XL] 4 + NumLooseInners['397',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['397',Pack1] demand_fit['397',S] 1 demand_fit['397',M] 3 + NumLooseInners['397',Pack1] demand_fit['397',L] 4 demand_fit['397',XL] 4 + NumLooseInners['398',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['398',Pack1] demand_fit['398',S] 1 demand_fit['398',M] 3 + NumLooseInners['398',Pack1] demand_fit['398',L] 4 demand_fit['398',XL] 4 + NumLooseInners['403',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['403',Pack1] demand_fit['403',S] 1 demand_fit['403',M] 3 + NumLooseInners['403',Pack1] demand_fit['403',L] 4 demand_fit['403',XL] 4 + NumLooseInners['418',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['418',Pack1] demand_fit['418',S] 1 demand_fit['418',M] 3 + NumLooseInners['418',Pack1] demand_fit['418',L] 4 demand_fit['418',XL] 4 + NumLooseInners['430',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['430',Pack1] demand_fit['430',S] 1 demand_fit['430',M] 3 + NumLooseInners['430',Pack1] demand_fit['430',L] 4 demand_fit['430',XL] 4 + NumLooseInners['431',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['431',Pack1] demand_fit['431',S] 1 demand_fit['431',M] 3 + NumLooseInners['431',Pack1] demand_fit['431',L] 4 demand_fit['431',XL] 4 + NumLooseInners['479',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['479',Pack1] demand_fit['479',S] 1 demand_fit['479',M] 3 + NumLooseInners['479',Pack1] demand_fit['479',L] 4 demand_fit['479',XL] 4 + NumLooseInners['502',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['502',Pack1] demand_fit['502',S] 1 demand_fit['502',M] 3 + NumLooseInners['502',Pack1] demand_fit['502',L] 4 demand_fit['502',XL] 4 + NumLooseInners['504',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['504',Pack1] demand_fit['504',S] 1 demand_fit['504',M] 3 + NumLooseInners['504',Pack1] demand_fit['504',L] 4 demand_fit['504',XL] 4 + NumLooseInners['512',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['512',Pack1] demand_fit['512',S] 1 demand_fit['512',M] 3 + NumLooseInners['512',Pack1] demand_fit['512',L] 4 demand_fit['512',XL] 4 + NumLooseInners['528',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['528',Pack1] demand_fit['528',S] 1 demand_fit['528',M] 3 + NumLooseInners['528',Pack1] demand_fit['528',L] 4 demand_fit['528',XL] 4 + NumLooseInners['533',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['533',Pack1] demand_fit['533',S] 1 demand_fit['533',M] 3 + NumLooseInners['533',Pack1] demand_fit['533',L] 4 demand_fit['533',XL] 4 + NumLooseInners['538',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['538',Pack1] demand_fit['538',S] 1 demand_fit['538',M] 3 + NumLooseInners['538',Pack1] demand_fit['538',L] 4 demand_fit['538',XL] 4 + NumLooseInners['552',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['552',Pack1] demand_fit['552',S] 1 demand_fit['552',M] 3 + NumLooseInners['552',Pack1] demand_fit['552',L] 4 demand_fit['552',XL] 4 + NumLooseInners['621',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['621',Pack1] demand_fit['621',S] 1 demand_fit['621',M] 3 + NumLooseInners['621',Pack1] demand_fit['621',L] 4 demand_fit['621',XL] 4 + NumLooseInners['639',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['639',Pack1] demand_fit['639',S] 1 demand_fit['639',M] 3 + NumLooseInners['639',Pack1] demand_fit['639',L] 4 demand_fit['639',XL] 4 + NumLooseInners['712',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['712',Pack1] demand_fit['712',S] 1 demand_fit['712',M] 3 + NumLooseInners['712',Pack1] demand_fit['712',L] 4 demand_fit['712',XL] 4 + NumLooseInners['781',Pack1] TotalCost 1 material_balance[Pack1] 1 + NumLooseInners['781',Pack1] demand_fit['781',S] 1 demand_fit['781',M] 3 + NumLooseInners['781',Pack1] demand_fit['781',L] 4 demand_fit['781',XL] 4 + NumLooseInners['71',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['71',Pack2] demand_fit['71',S] 1 demand_fit['71',M] 2 + NumLooseInners['71',Pack2] demand_fit['71',L] 4 demand_fit['71',XL] 5 + NumLooseInners['73',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['73',Pack2] demand_fit['73',S] 1 demand_fit['73',M] 2 + NumLooseInners['73',Pack2] demand_fit['73',L] 4 demand_fit['73',XL] 5 + NumLooseInners['86',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['86',Pack2] demand_fit['86',S] 1 demand_fit['86',M] 2 + NumLooseInners['86',Pack2] demand_fit['86',L] 4 demand_fit['86',XL] 5 + NumLooseInners['99',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['99',Pack2] demand_fit['99',S] 1 demand_fit['99',M] 2 + NumLooseInners['99',Pack2] demand_fit['99',L] 4 demand_fit['99',XL] 5 + NumLooseInners['103',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['103',Pack2] demand_fit['103',S] 1 demand_fit['103',M] 2 + NumLooseInners['103',Pack2] demand_fit['103',L] 4 demand_fit['103',XL] 5 + NumLooseInners['126',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['126',Pack2] demand_fit['126',S] 1 demand_fit['126',M] 2 + NumLooseInners['126',Pack2] demand_fit['126',L] 4 demand_fit['126',XL] 5 + NumLooseInners['221',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['221',Pack2] demand_fit['221',S] 1 demand_fit['221',M] 2 + NumLooseInners['221',Pack2] demand_fit['221',L] 4 demand_fit['221',XL] 5 + NumLooseInners['225',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['225',Pack2] demand_fit['225',S] 1 demand_fit['225',M] 2 + NumLooseInners['225',Pack2] demand_fit['225',L] 4 demand_fit['225',XL] 5 + NumLooseInners['251',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['251',Pack2] demand_fit['251',S] 1 demand_fit['251',M] 2 + NumLooseInners['251',Pack2] demand_fit['251',L] 4 demand_fit['251',XL] 5 + NumLooseInners['270',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['270',Pack2] demand_fit['270',S] 1 demand_fit['270',M] 2 + NumLooseInners['270',Pack2] demand_fit['270',L] 4 demand_fit['270',XL] 5 + NumLooseInners['272',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['272',Pack2] demand_fit['272',S] 1 demand_fit['272',M] 2 + NumLooseInners['272',Pack2] demand_fit['272',L] 4 demand_fit['272',XL] 5 + NumLooseInners['275',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['275',Pack2] demand_fit['275',S] 1 demand_fit['275',M] 2 + NumLooseInners['275',Pack2] demand_fit['275',L] 4 demand_fit['275',XL] 5 + NumLooseInners['276',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['276',Pack2] demand_fit['276',S] 1 demand_fit['276',M] 2 + NumLooseInners['276',Pack2] demand_fit['276',L] 4 demand_fit['276',XL] 5 + NumLooseInners['280',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['280',Pack2] demand_fit['280',S] 1 demand_fit['280',M] 2 + NumLooseInners['280',Pack2] demand_fit['280',L] 4 demand_fit['280',XL] 5 + NumLooseInners['282',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['282',Pack2] demand_fit['282',S] 1 demand_fit['282',M] 2 + NumLooseInners['282',Pack2] demand_fit['282',L] 4 demand_fit['282',XL] 5 + NumLooseInners['283',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['283',Pack2] demand_fit['283',S] 1 demand_fit['283',M] 2 + NumLooseInners['283',Pack2] demand_fit['283',L] 4 demand_fit['283',XL] 5 + NumLooseInners['293',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['293',Pack2] demand_fit['293',S] 1 demand_fit['293',M] 2 + NumLooseInners['293',Pack2] demand_fit['293',L] 4 demand_fit['293',XL] 5 + NumLooseInners['298',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['298',Pack2] demand_fit['298',S] 1 demand_fit['298',M] 2 + NumLooseInners['298',Pack2] demand_fit['298',L] 4 demand_fit['298',XL] 5 + NumLooseInners['299',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['299',Pack2] demand_fit['299',S] 1 demand_fit['299',M] 2 + NumLooseInners['299',Pack2] demand_fit['299',L] 4 demand_fit['299',XL] 5 + NumLooseInners['301',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['301',Pack2] demand_fit['301',S] 1 demand_fit['301',M] 2 + NumLooseInners['301',Pack2] demand_fit['301',L] 4 demand_fit['301',XL] 5 + NumLooseInners['309',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['309',Pack2] demand_fit['309',S] 1 demand_fit['309',M] 2 + NumLooseInners['309',Pack2] demand_fit['309',L] 4 demand_fit['309',XL] 5 + NumLooseInners['310',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['310',Pack2] demand_fit['310',S] 1 demand_fit['310',M] 2 + NumLooseInners['310',Pack2] demand_fit['310',L] 4 demand_fit['310',XL] 5 + NumLooseInners['375',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['375',Pack2] demand_fit['375',S] 1 demand_fit['375',M] 2 + NumLooseInners['375',Pack2] demand_fit['375',L] 4 demand_fit['375',XL] 5 + NumLooseInners['378',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['378',Pack2] demand_fit['378',S] 1 demand_fit['378',M] 2 + NumLooseInners['378',Pack2] demand_fit['378',L] 4 demand_fit['378',XL] 5 + NumLooseInners['379',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['379',Pack2] demand_fit['379',S] 1 demand_fit['379',M] 2 + NumLooseInners['379',Pack2] demand_fit['379',L] 4 demand_fit['379',XL] 5 + NumLooseInners['381',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['381',Pack2] demand_fit['381',S] 1 demand_fit['381',M] 2 + NumLooseInners['381',Pack2] demand_fit['381',L] 4 demand_fit['381',XL] 5 + NumLooseInners['383',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['383',Pack2] demand_fit['383',S] 1 demand_fit['383',M] 2 + NumLooseInners['383',Pack2] demand_fit['383',L] 4 demand_fit['383',XL] 5 + NumLooseInners['384',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['384',Pack2] demand_fit['384',S] 1 demand_fit['384',M] 2 + NumLooseInners['384',Pack2] demand_fit['384',L] 4 demand_fit['384',XL] 5 + NumLooseInners['386',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['386',Pack2] demand_fit['386',S] 1 demand_fit['386',M] 2 + NumLooseInners['386',Pack2] demand_fit['386',L] 4 demand_fit['386',XL] 5 + NumLooseInners['388',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['388',Pack2] demand_fit['388',S] 1 demand_fit['388',M] 2 + NumLooseInners['388',Pack2] demand_fit['388',L] 4 demand_fit['388',XL] 5 + NumLooseInners['389',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['389',Pack2] demand_fit['389',S] 1 demand_fit['389',M] 2 + NumLooseInners['389',Pack2] demand_fit['389',L] 4 demand_fit['389',XL] 5 + NumLooseInners['390',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['390',Pack2] demand_fit['390',S] 1 demand_fit['390',M] 2 + NumLooseInners['390',Pack2] demand_fit['390',L] 4 demand_fit['390',XL] 5 + NumLooseInners['397',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['397',Pack2] demand_fit['397',S] 1 demand_fit['397',M] 2 + NumLooseInners['397',Pack2] demand_fit['397',L] 4 demand_fit['397',XL] 5 + NumLooseInners['398',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['398',Pack2] demand_fit['398',S] 1 demand_fit['398',M] 2 + NumLooseInners['398',Pack2] demand_fit['398',L] 4 demand_fit['398',XL] 5 + NumLooseInners['403',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['403',Pack2] demand_fit['403',S] 1 demand_fit['403',M] 2 + NumLooseInners['403',Pack2] demand_fit['403',L] 4 demand_fit['403',XL] 5 + NumLooseInners['418',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['418',Pack2] demand_fit['418',S] 1 demand_fit['418',M] 2 + NumLooseInners['418',Pack2] demand_fit['418',L] 4 demand_fit['418',XL] 5 + NumLooseInners['430',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['430',Pack2] demand_fit['430',S] 1 demand_fit['430',M] 2 + NumLooseInners['430',Pack2] demand_fit['430',L] 4 demand_fit['430',XL] 5 + NumLooseInners['431',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['431',Pack2] demand_fit['431',S] 1 demand_fit['431',M] 2 + NumLooseInners['431',Pack2] demand_fit['431',L] 4 demand_fit['431',XL] 5 + NumLooseInners['479',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['479',Pack2] demand_fit['479',S] 1 demand_fit['479',M] 2 + NumLooseInners['479',Pack2] demand_fit['479',L] 4 demand_fit['479',XL] 5 + NumLooseInners['502',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['502',Pack2] demand_fit['502',S] 1 demand_fit['502',M] 2 + NumLooseInners['502',Pack2] demand_fit['502',L] 4 demand_fit['502',XL] 5 + NumLooseInners['504',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['504',Pack2] demand_fit['504',S] 1 demand_fit['504',M] 2 + NumLooseInners['504',Pack2] demand_fit['504',L] 4 demand_fit['504',XL] 5 + NumLooseInners['512',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['512',Pack2] demand_fit['512',S] 1 demand_fit['512',M] 2 + NumLooseInners['512',Pack2] demand_fit['512',L] 4 demand_fit['512',XL] 5 + NumLooseInners['528',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['528',Pack2] demand_fit['528',S] 1 demand_fit['528',M] 2 + NumLooseInners['528',Pack2] demand_fit['528',L] 4 demand_fit['528',XL] 5 + NumLooseInners['533',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['533',Pack2] demand_fit['533',S] 1 demand_fit['533',M] 2 + NumLooseInners['533',Pack2] demand_fit['533',L] 4 demand_fit['533',XL] 5 + NumLooseInners['538',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['538',Pack2] demand_fit['538',S] 1 demand_fit['538',M] 2 + NumLooseInners['538',Pack2] demand_fit['538',L] 4 demand_fit['538',XL] 5 + NumLooseInners['552',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['552',Pack2] demand_fit['552',S] 1 demand_fit['552',M] 2 + NumLooseInners['552',Pack2] demand_fit['552',L] 4 demand_fit['552',XL] 5 + NumLooseInners['621',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['621',Pack2] demand_fit['621',S] 1 demand_fit['621',M] 2 + NumLooseInners['621',Pack2] demand_fit['621',L] 4 demand_fit['621',XL] 5 + NumLooseInners['639',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['639',Pack2] demand_fit['639',S] 1 demand_fit['639',M] 2 + NumLooseInners['639',Pack2] demand_fit['639',L] 4 demand_fit['639',XL] 5 + NumLooseInners['712',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['712',Pack2] demand_fit['712',S] 1 demand_fit['712',M] 2 + NumLooseInners['712',Pack2] demand_fit['712',L] 4 demand_fit['712',XL] 5 + NumLooseInners['781',Pack2] TotalCost 1.5 material_balance[Pack2] 1 + NumLooseInners['781',Pack2] demand_fit['781',S] 1 demand_fit['781',M] 2 + NumLooseInners['781',Pack2] demand_fit['781',L] 4 demand_fit['781',XL] 5 + NumLooseInners['71',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['71',Pack3] demand_fit['71',S] 2 demand_fit['71',M] 4 + NumLooseInners['71',Pack3] demand_fit['71',L] 3 demand_fit['71',XL] 3 + NumLooseInners['73',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['73',Pack3] demand_fit['73',S] 2 demand_fit['73',M] 4 + NumLooseInners['73',Pack3] demand_fit['73',L] 3 demand_fit['73',XL] 3 + NumLooseInners['86',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['86',Pack3] demand_fit['86',S] 2 demand_fit['86',M] 4 + NumLooseInners['86',Pack3] demand_fit['86',L] 3 demand_fit['86',XL] 3 + NumLooseInners['99',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['99',Pack3] demand_fit['99',S] 2 demand_fit['99',M] 4 + NumLooseInners['99',Pack3] demand_fit['99',L] 3 demand_fit['99',XL] 3 + NumLooseInners['103',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['103',Pack3] demand_fit['103',S] 2 demand_fit['103',M] 4 + NumLooseInners['103',Pack3] demand_fit['103',L] 3 demand_fit['103',XL] 3 + NumLooseInners['126',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['126',Pack3] demand_fit['126',S] 2 demand_fit['126',M] 4 + NumLooseInners['126',Pack3] demand_fit['126',L] 3 demand_fit['126',XL] 3 + NumLooseInners['221',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['221',Pack3] demand_fit['221',S] 2 demand_fit['221',M] 4 + NumLooseInners['221',Pack3] demand_fit['221',L] 3 demand_fit['221',XL] 3 + NumLooseInners['225',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['225',Pack3] demand_fit['225',S] 2 demand_fit['225',M] 4 + NumLooseInners['225',Pack3] demand_fit['225',L] 3 demand_fit['225',XL] 3 + NumLooseInners['251',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['251',Pack3] demand_fit['251',S] 2 demand_fit['251',M] 4 + NumLooseInners['251',Pack3] demand_fit['251',L] 3 demand_fit['251',XL] 3 + NumLooseInners['270',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['270',Pack3] demand_fit['270',S] 2 demand_fit['270',M] 4 + NumLooseInners['270',Pack3] demand_fit['270',L] 3 demand_fit['270',XL] 3 + NumLooseInners['272',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['272',Pack3] demand_fit['272',S] 2 demand_fit['272',M] 4 + NumLooseInners['272',Pack3] demand_fit['272',L] 3 demand_fit['272',XL] 3 + NumLooseInners['275',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['275',Pack3] demand_fit['275',S] 2 demand_fit['275',M] 4 + NumLooseInners['275',Pack3] demand_fit['275',L] 3 demand_fit['275',XL] 3 + NumLooseInners['276',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['276',Pack3] demand_fit['276',S] 2 demand_fit['276',M] 4 + NumLooseInners['276',Pack3] demand_fit['276',L] 3 demand_fit['276',XL] 3 + NumLooseInners['280',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['280',Pack3] demand_fit['280',S] 2 demand_fit['280',M] 4 + NumLooseInners['280',Pack3] demand_fit['280',L] 3 demand_fit['280',XL] 3 + NumLooseInners['282',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['282',Pack3] demand_fit['282',S] 2 demand_fit['282',M] 4 + NumLooseInners['282',Pack3] demand_fit['282',L] 3 demand_fit['282',XL] 3 + NumLooseInners['283',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['283',Pack3] demand_fit['283',S] 2 demand_fit['283',M] 4 + NumLooseInners['283',Pack3] demand_fit['283',L] 3 demand_fit['283',XL] 3 + NumLooseInners['293',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['293',Pack3] demand_fit['293',S] 2 demand_fit['293',M] 4 + NumLooseInners['293',Pack3] demand_fit['293',L] 3 demand_fit['293',XL] 3 + NumLooseInners['298',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['298',Pack3] demand_fit['298',S] 2 demand_fit['298',M] 4 + NumLooseInners['298',Pack3] demand_fit['298',L] 3 demand_fit['298',XL] 3 + NumLooseInners['299',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['299',Pack3] demand_fit['299',S] 2 demand_fit['299',M] 4 + NumLooseInners['299',Pack3] demand_fit['299',L] 3 demand_fit['299',XL] 3 + NumLooseInners['301',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['301',Pack3] demand_fit['301',S] 2 demand_fit['301',M] 4 + NumLooseInners['301',Pack3] demand_fit['301',L] 3 demand_fit['301',XL] 3 + NumLooseInners['309',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['309',Pack3] demand_fit['309',S] 2 demand_fit['309',M] 4 + NumLooseInners['309',Pack3] demand_fit['309',L] 3 demand_fit['309',XL] 3 + NumLooseInners['310',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['310',Pack3] demand_fit['310',S] 2 demand_fit['310',M] 4 + NumLooseInners['310',Pack3] demand_fit['310',L] 3 demand_fit['310',XL] 3 + NumLooseInners['375',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['375',Pack3] demand_fit['375',S] 2 demand_fit['375',M] 4 + NumLooseInners['375',Pack3] demand_fit['375',L] 3 demand_fit['375',XL] 3 + NumLooseInners['378',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['378',Pack3] demand_fit['378',S] 2 demand_fit['378',M] 4 + NumLooseInners['378',Pack3] demand_fit['378',L] 3 demand_fit['378',XL] 3 + NumLooseInners['379',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['379',Pack3] demand_fit['379',S] 2 demand_fit['379',M] 4 + NumLooseInners['379',Pack3] demand_fit['379',L] 3 demand_fit['379',XL] 3 + NumLooseInners['381',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['381',Pack3] demand_fit['381',S] 2 demand_fit['381',M] 4 + NumLooseInners['381',Pack3] demand_fit['381',L] 3 demand_fit['381',XL] 3 + NumLooseInners['383',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['383',Pack3] demand_fit['383',S] 2 demand_fit['383',M] 4 + NumLooseInners['383',Pack3] demand_fit['383',L] 3 demand_fit['383',XL] 3 + NumLooseInners['384',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['384',Pack3] demand_fit['384',S] 2 demand_fit['384',M] 4 + NumLooseInners['384',Pack3] demand_fit['384',L] 3 demand_fit['384',XL] 3 + NumLooseInners['386',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['386',Pack3] demand_fit['386',S] 2 demand_fit['386',M] 4 + NumLooseInners['386',Pack3] demand_fit['386',L] 3 demand_fit['386',XL] 3 + NumLooseInners['388',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['388',Pack3] demand_fit['388',S] 2 demand_fit['388',M] 4 + NumLooseInners['388',Pack3] demand_fit['388',L] 3 demand_fit['388',XL] 3 + NumLooseInners['389',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['389',Pack3] demand_fit['389',S] 2 demand_fit['389',M] 4 + NumLooseInners['389',Pack3] demand_fit['389',L] 3 demand_fit['389',XL] 3 + NumLooseInners['390',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['390',Pack3] demand_fit['390',S] 2 demand_fit['390',M] 4 + NumLooseInners['390',Pack3] demand_fit['390',L] 3 demand_fit['390',XL] 3 + NumLooseInners['397',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['397',Pack3] demand_fit['397',S] 2 demand_fit['397',M] 4 + NumLooseInners['397',Pack3] demand_fit['397',L] 3 demand_fit['397',XL] 3 + NumLooseInners['398',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['398',Pack3] demand_fit['398',S] 2 demand_fit['398',M] 4 + NumLooseInners['398',Pack3] demand_fit['398',L] 3 demand_fit['398',XL] 3 + NumLooseInners['403',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['403',Pack3] demand_fit['403',S] 2 demand_fit['403',M] 4 + NumLooseInners['403',Pack3] demand_fit['403',L] 3 demand_fit['403',XL] 3 + NumLooseInners['418',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['418',Pack3] demand_fit['418',S] 2 demand_fit['418',M] 4 + NumLooseInners['418',Pack3] demand_fit['418',L] 3 demand_fit['418',XL] 3 + NumLooseInners['430',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['430',Pack3] demand_fit['430',S] 2 demand_fit['430',M] 4 + NumLooseInners['430',Pack3] demand_fit['430',L] 3 demand_fit['430',XL] 3 + NumLooseInners['431',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['431',Pack3] demand_fit['431',S] 2 demand_fit['431',M] 4 + NumLooseInners['431',Pack3] demand_fit['431',L] 3 demand_fit['431',XL] 3 + NumLooseInners['479',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['479',Pack3] demand_fit['479',S] 2 demand_fit['479',M] 4 + NumLooseInners['479',Pack3] demand_fit['479',L] 3 demand_fit['479',XL] 3 + NumLooseInners['502',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['502',Pack3] demand_fit['502',S] 2 demand_fit['502',M] 4 + NumLooseInners['502',Pack3] demand_fit['502',L] 3 demand_fit['502',XL] 3 + NumLooseInners['504',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['504',Pack3] demand_fit['504',S] 2 demand_fit['504',M] 4 + NumLooseInners['504',Pack3] demand_fit['504',L] 3 demand_fit['504',XL] 3 + NumLooseInners['512',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['512',Pack3] demand_fit['512',S] 2 demand_fit['512',M] 4 + NumLooseInners['512',Pack3] demand_fit['512',L] 3 demand_fit['512',XL] 3 + NumLooseInners['528',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['528',Pack3] demand_fit['528',S] 2 demand_fit['528',M] 4 + NumLooseInners['528',Pack3] demand_fit['528',L] 3 demand_fit['528',XL] 3 + NumLooseInners['533',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['533',Pack3] demand_fit['533',S] 2 demand_fit['533',M] 4 + NumLooseInners['533',Pack3] demand_fit['533',L] 3 demand_fit['533',XL] 3 + NumLooseInners['538',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['538',Pack3] demand_fit['538',S] 2 demand_fit['538',M] 4 + NumLooseInners['538',Pack3] demand_fit['538',L] 3 demand_fit['538',XL] 3 + NumLooseInners['552',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['552',Pack3] demand_fit['552',S] 2 demand_fit['552',M] 4 + NumLooseInners['552',Pack3] demand_fit['552',L] 3 demand_fit['552',XL] 3 + NumLooseInners['621',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['621',Pack3] demand_fit['621',S] 2 demand_fit['621',M] 4 + NumLooseInners['621',Pack3] demand_fit['621',L] 3 demand_fit['621',XL] 3 + NumLooseInners['639',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['639',Pack3] demand_fit['639',S] 2 demand_fit['639',M] 4 + NumLooseInners['639',Pack3] demand_fit['639',L] 3 demand_fit['639',XL] 3 + NumLooseInners['712',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['712',Pack3] demand_fit['712',S] 2 demand_fit['712',M] 4 + NumLooseInners['712',Pack3] demand_fit['712',L] 3 demand_fit['712',XL] 3 + NumLooseInners['781',Pack3] TotalCost 0.5 material_balance[Pack3] 1 + NumLooseInners['781',Pack3] demand_fit['781',S] 2 demand_fit['781',M] 4 + NumLooseInners['781',Pack3] demand_fit['781',L] 3 demand_fit['781',XL] 3 + NumUnopenedOuters['71',Pack1] TotalCost 1 demand_fit['71',S] 1 + NumUnopenedOuters['71',Pack1] demand_fit['71',M] 3 demand_fit['71',L] 4 + NumUnopenedOuters['71',Pack1] demand_fit['71',XL] 4 + NumUnopenedOuters['73',Pack1] TotalCost 1 demand_fit['73',S] 1 + NumUnopenedOuters['73',Pack1] demand_fit['73',M] 3 demand_fit['73',L] 4 + NumUnopenedOuters['73',Pack1] demand_fit['73',XL] 4 + NumUnopenedOuters['86',Pack1] TotalCost 1 demand_fit['86',S] 1 + NumUnopenedOuters['86',Pack1] demand_fit['86',M] 3 demand_fit['86',L] 4 + NumUnopenedOuters['86',Pack1] demand_fit['86',XL] 4 + NumUnopenedOuters['99',Pack1] TotalCost 1 demand_fit['99',S] 1 + NumUnopenedOuters['99',Pack1] demand_fit['99',M] 3 demand_fit['99',L] 4 + NumUnopenedOuters['99',Pack1] demand_fit['99',XL] 4 + NumUnopenedOuters['103',Pack1] TotalCost 1 demand_fit['103',S] 1 + NumUnopenedOuters['103',Pack1] demand_fit['103',M] 3 demand_fit['103',L] 4 + NumUnopenedOuters['103',Pack1] demand_fit['103',XL] 4 + NumUnopenedOuters['126',Pack1] TotalCost 1 demand_fit['126',S] 1 + NumUnopenedOuters['126',Pack1] demand_fit['126',M] 3 demand_fit['126',L] 4 + NumUnopenedOuters['126',Pack1] demand_fit['126',XL] 4 + NumUnopenedOuters['221',Pack1] TotalCost 1 demand_fit['221',S] 1 + NumUnopenedOuters['221',Pack1] demand_fit['221',M] 3 demand_fit['221',L] 4 + NumUnopenedOuters['221',Pack1] demand_fit['221',XL] 4 + NumUnopenedOuters['225',Pack1] TotalCost 1 demand_fit['225',S] 1 + NumUnopenedOuters['225',Pack1] demand_fit['225',M] 3 demand_fit['225',L] 4 + NumUnopenedOuters['225',Pack1] demand_fit['225',XL] 4 + NumUnopenedOuters['251',Pack1] TotalCost 1 demand_fit['251',S] 1 + NumUnopenedOuters['251',Pack1] demand_fit['251',M] 3 demand_fit['251',L] 4 + NumUnopenedOuters['251',Pack1] demand_fit['251',XL] 4 + NumUnopenedOuters['270',Pack1] TotalCost 1 demand_fit['270',S] 1 + NumUnopenedOuters['270',Pack1] demand_fit['270',M] 3 demand_fit['270',L] 4 + NumUnopenedOuters['270',Pack1] demand_fit['270',XL] 4 + NumUnopenedOuters['272',Pack1] TotalCost 1 demand_fit['272',S] 1 + NumUnopenedOuters['272',Pack1] demand_fit['272',M] 3 demand_fit['272',L] 4 + NumUnopenedOuters['272',Pack1] demand_fit['272',XL] 4 + NumUnopenedOuters['275',Pack1] TotalCost 1 demand_fit['275',S] 1 + NumUnopenedOuters['275',Pack1] demand_fit['275',M] 3 demand_fit['275',L] 4 + NumUnopenedOuters['275',Pack1] demand_fit['275',XL] 4 + NumUnopenedOuters['276',Pack1] TotalCost 1 demand_fit['276',S] 1 + NumUnopenedOuters['276',Pack1] demand_fit['276',M] 3 demand_fit['276',L] 4 + NumUnopenedOuters['276',Pack1] demand_fit['276',XL] 4 + NumUnopenedOuters['280',Pack1] TotalCost 1 demand_fit['280',S] 1 + NumUnopenedOuters['280',Pack1] demand_fit['280',M] 3 demand_fit['280',L] 4 + NumUnopenedOuters['280',Pack1] demand_fit['280',XL] 4 + NumUnopenedOuters['282',Pack1] TotalCost 1 demand_fit['282',S] 1 + NumUnopenedOuters['282',Pack1] demand_fit['282',M] 3 demand_fit['282',L] 4 + NumUnopenedOuters['282',Pack1] demand_fit['282',XL] 4 + NumUnopenedOuters['283',Pack1] TotalCost 1 demand_fit['283',S] 1 + NumUnopenedOuters['283',Pack1] demand_fit['283',M] 3 demand_fit['283',L] 4 + NumUnopenedOuters['283',Pack1] demand_fit['283',XL] 4 + NumUnopenedOuters['293',Pack1] TotalCost 1 demand_fit['293',S] 1 + NumUnopenedOuters['293',Pack1] demand_fit['293',M] 3 demand_fit['293',L] 4 + NumUnopenedOuters['293',Pack1] demand_fit['293',XL] 4 + NumUnopenedOuters['298',Pack1] TotalCost 1 demand_fit['298',S] 1 + NumUnopenedOuters['298',Pack1] demand_fit['298',M] 3 demand_fit['298',L] 4 + NumUnopenedOuters['298',Pack1] demand_fit['298',XL] 4 + NumUnopenedOuters['299',Pack1] TotalCost 1 demand_fit['299',S] 1 + NumUnopenedOuters['299',Pack1] demand_fit['299',M] 3 demand_fit['299',L] 4 + NumUnopenedOuters['299',Pack1] demand_fit['299',XL] 4 + NumUnopenedOuters['301',Pack1] TotalCost 1 demand_fit['301',S] 1 + NumUnopenedOuters['301',Pack1] demand_fit['301',M] 3 demand_fit['301',L] 4 + NumUnopenedOuters['301',Pack1] demand_fit['301',XL] 4 + NumUnopenedOuters['309',Pack1] TotalCost 1 demand_fit['309',S] 1 + NumUnopenedOuters['309',Pack1] demand_fit['309',M] 3 demand_fit['309',L] 4 + NumUnopenedOuters['309',Pack1] demand_fit['309',XL] 4 + NumUnopenedOuters['310',Pack1] TotalCost 1 demand_fit['310',S] 1 + NumUnopenedOuters['310',Pack1] demand_fit['310',M] 3 demand_fit['310',L] 4 + NumUnopenedOuters['310',Pack1] demand_fit['310',XL] 4 + NumUnopenedOuters['375',Pack1] TotalCost 1 demand_fit['375',S] 1 + NumUnopenedOuters['375',Pack1] demand_fit['375',M] 3 demand_fit['375',L] 4 + NumUnopenedOuters['375',Pack1] demand_fit['375',XL] 4 + NumUnopenedOuters['378',Pack1] TotalCost 1 demand_fit['378',S] 1 + NumUnopenedOuters['378',Pack1] demand_fit['378',M] 3 demand_fit['378',L] 4 + NumUnopenedOuters['378',Pack1] demand_fit['378',XL] 4 + NumUnopenedOuters['379',Pack1] TotalCost 1 demand_fit['379',S] 1 + NumUnopenedOuters['379',Pack1] demand_fit['379',M] 3 demand_fit['379',L] 4 + NumUnopenedOuters['379',Pack1] demand_fit['379',XL] 4 + NumUnopenedOuters['381',Pack1] TotalCost 1 demand_fit['381',S] 1 + NumUnopenedOuters['381',Pack1] demand_fit['381',M] 3 demand_fit['381',L] 4 + NumUnopenedOuters['381',Pack1] demand_fit['381',XL] 4 + NumUnopenedOuters['383',Pack1] TotalCost 1 demand_fit['383',S] 1 + NumUnopenedOuters['383',Pack1] demand_fit['383',M] 3 demand_fit['383',L] 4 + NumUnopenedOuters['383',Pack1] demand_fit['383',XL] 4 + NumUnopenedOuters['384',Pack1] TotalCost 1 demand_fit['384',S] 1 + NumUnopenedOuters['384',Pack1] demand_fit['384',M] 3 demand_fit['384',L] 4 + NumUnopenedOuters['384',Pack1] demand_fit['384',XL] 4 + NumUnopenedOuters['386',Pack1] TotalCost 1 demand_fit['386',S] 1 + NumUnopenedOuters['386',Pack1] demand_fit['386',M] 3 demand_fit['386',L] 4 + NumUnopenedOuters['386',Pack1] demand_fit['386',XL] 4 + NumUnopenedOuters['388',Pack1] TotalCost 1 demand_fit['388',S] 1 + NumUnopenedOuters['388',Pack1] demand_fit['388',M] 3 demand_fit['388',L] 4 + NumUnopenedOuters['388',Pack1] demand_fit['388',XL] 4 + NumUnopenedOuters['389',Pack1] TotalCost 1 demand_fit['389',S] 1 + NumUnopenedOuters['389',Pack1] demand_fit['389',M] 3 demand_fit['389',L] 4 + NumUnopenedOuters['389',Pack1] demand_fit['389',XL] 4 + NumUnopenedOuters['390',Pack1] TotalCost 1 demand_fit['390',S] 1 + NumUnopenedOuters['390',Pack1] demand_fit['390',M] 3 demand_fit['390',L] 4 + NumUnopenedOuters['390',Pack1] demand_fit['390',XL] 4 + NumUnopenedOuters['397',Pack1] TotalCost 1 demand_fit['397',S] 1 + NumUnopenedOuters['397',Pack1] demand_fit['397',M] 3 demand_fit['397',L] 4 + NumUnopenedOuters['397',Pack1] demand_fit['397',XL] 4 + NumUnopenedOuters['398',Pack1] TotalCost 1 demand_fit['398',S] 1 + NumUnopenedOuters['398',Pack1] demand_fit['398',M] 3 demand_fit['398',L] 4 + NumUnopenedOuters['398',Pack1] demand_fit['398',XL] 4 + NumUnopenedOuters['403',Pack1] TotalCost 1 demand_fit['403',S] 1 + NumUnopenedOuters['403',Pack1] demand_fit['403',M] 3 demand_fit['403',L] 4 + NumUnopenedOuters['403',Pack1] demand_fit['403',XL] 4 + NumUnopenedOuters['418',Pack1] TotalCost 1 demand_fit['418',S] 1 + NumUnopenedOuters['418',Pack1] demand_fit['418',M] 3 demand_fit['418',L] 4 + NumUnopenedOuters['418',Pack1] demand_fit['418',XL] 4 + NumUnopenedOuters['430',Pack1] TotalCost 1 demand_fit['430',S] 1 + NumUnopenedOuters['430',Pack1] demand_fit['430',M] 3 demand_fit['430',L] 4 + NumUnopenedOuters['430',Pack1] demand_fit['430',XL] 4 + NumUnopenedOuters['431',Pack1] TotalCost 1 demand_fit['431',S] 1 + NumUnopenedOuters['431',Pack1] demand_fit['431',M] 3 demand_fit['431',L] 4 + NumUnopenedOuters['431',Pack1] demand_fit['431',XL] 4 + NumUnopenedOuters['479',Pack1] TotalCost 1 demand_fit['479',S] 1 + NumUnopenedOuters['479',Pack1] demand_fit['479',M] 3 demand_fit['479',L] 4 + NumUnopenedOuters['479',Pack1] demand_fit['479',XL] 4 + NumUnopenedOuters['502',Pack1] TotalCost 1 demand_fit['502',S] 1 + NumUnopenedOuters['502',Pack1] demand_fit['502',M] 3 demand_fit['502',L] 4 + NumUnopenedOuters['502',Pack1] demand_fit['502',XL] 4 + NumUnopenedOuters['504',Pack1] TotalCost 1 demand_fit['504',S] 1 + NumUnopenedOuters['504',Pack1] demand_fit['504',M] 3 demand_fit['504',L] 4 + NumUnopenedOuters['504',Pack1] demand_fit['504',XL] 4 + NumUnopenedOuters['512',Pack1] TotalCost 1 demand_fit['512',S] 1 + NumUnopenedOuters['512',Pack1] demand_fit['512',M] 3 demand_fit['512',L] 4 + NumUnopenedOuters['512',Pack1] demand_fit['512',XL] 4 + NumUnopenedOuters['528',Pack1] TotalCost 1 demand_fit['528',S] 1 + NumUnopenedOuters['528',Pack1] demand_fit['528',M] 3 demand_fit['528',L] 4 + NumUnopenedOuters['528',Pack1] demand_fit['528',XL] 4 + NumUnopenedOuters['533',Pack1] TotalCost 1 demand_fit['533',S] 1 + NumUnopenedOuters['533',Pack1] demand_fit['533',M] 3 demand_fit['533',L] 4 + NumUnopenedOuters['533',Pack1] demand_fit['533',XL] 4 + NumUnopenedOuters['538',Pack1] TotalCost 1 demand_fit['538',S] 1 + NumUnopenedOuters['538',Pack1] demand_fit['538',M] 3 demand_fit['538',L] 4 + NumUnopenedOuters['538',Pack1] demand_fit['538',XL] 4 + NumUnopenedOuters['552',Pack1] TotalCost 1 demand_fit['552',S] 1 + NumUnopenedOuters['552',Pack1] demand_fit['552',M] 3 demand_fit['552',L] 4 + NumUnopenedOuters['552',Pack1] demand_fit['552',XL] 4 + NumUnopenedOuters['621',Pack1] TotalCost 1 demand_fit['621',S] 1 + NumUnopenedOuters['621',Pack1] demand_fit['621',M] 3 demand_fit['621',L] 4 + NumUnopenedOuters['621',Pack1] demand_fit['621',XL] 4 + NumUnopenedOuters['639',Pack1] TotalCost 1 demand_fit['639',S] 1 + NumUnopenedOuters['639',Pack1] demand_fit['639',M] 3 demand_fit['639',L] 4 + NumUnopenedOuters['639',Pack1] demand_fit['639',XL] 4 + NumUnopenedOuters['712',Pack1] TotalCost 1 demand_fit['712',S] 1 + NumUnopenedOuters['712',Pack1] demand_fit['712',M] 3 demand_fit['712',L] 4 + NumUnopenedOuters['712',Pack1] demand_fit['712',XL] 4 + NumUnopenedOuters['781',Pack1] TotalCost 1 demand_fit['781',S] 1 + NumUnopenedOuters['781',Pack1] demand_fit['781',M] 3 demand_fit['781',L] 4 + NumUnopenedOuters['781',Pack1] demand_fit['781',XL] 4 + NumUnopenedOuters['71',Pack2] TotalCost 1.5 demand_fit['71',S] 1 + NumUnopenedOuters['71',Pack2] demand_fit['71',M] 2 demand_fit['71',L] 4 + NumUnopenedOuters['71',Pack2] demand_fit['71',XL] 5 + NumUnopenedOuters['73',Pack2] TotalCost 1.5 demand_fit['73',S] 1 + NumUnopenedOuters['73',Pack2] demand_fit['73',M] 2 demand_fit['73',L] 4 + NumUnopenedOuters['73',Pack2] demand_fit['73',XL] 5 + NumUnopenedOuters['86',Pack2] TotalCost 1.5 demand_fit['86',S] 1 + NumUnopenedOuters['86',Pack2] demand_fit['86',M] 2 demand_fit['86',L] 4 + NumUnopenedOuters['86',Pack2] demand_fit['86',XL] 5 + NumUnopenedOuters['99',Pack2] TotalCost 1.5 demand_fit['99',S] 1 + NumUnopenedOuters['99',Pack2] demand_fit['99',M] 2 demand_fit['99',L] 4 + NumUnopenedOuters['99',Pack2] demand_fit['99',XL] 5 + NumUnopenedOuters['103',Pack2] TotalCost 1.5 demand_fit['103',S] 1 + NumUnopenedOuters['103',Pack2] demand_fit['103',M] 2 demand_fit['103',L] 4 + NumUnopenedOuters['103',Pack2] demand_fit['103',XL] 5 + NumUnopenedOuters['126',Pack2] TotalCost 1.5 demand_fit['126',S] 1 + NumUnopenedOuters['126',Pack2] demand_fit['126',M] 2 demand_fit['126',L] 4 + NumUnopenedOuters['126',Pack2] demand_fit['126',XL] 5 + NumUnopenedOuters['221',Pack2] TotalCost 1.5 demand_fit['221',S] 1 + NumUnopenedOuters['221',Pack2] demand_fit['221',M] 2 demand_fit['221',L] 4 + NumUnopenedOuters['221',Pack2] demand_fit['221',XL] 5 + NumUnopenedOuters['225',Pack2] TotalCost 1.5 demand_fit['225',S] 1 + NumUnopenedOuters['225',Pack2] demand_fit['225',M] 2 demand_fit['225',L] 4 + NumUnopenedOuters['225',Pack2] demand_fit['225',XL] 5 + NumUnopenedOuters['251',Pack2] TotalCost 1.5 demand_fit['251',S] 1 + NumUnopenedOuters['251',Pack2] demand_fit['251',M] 2 demand_fit['251',L] 4 + NumUnopenedOuters['251',Pack2] demand_fit['251',XL] 5 + NumUnopenedOuters['270',Pack2] TotalCost 1.5 demand_fit['270',S] 1 + NumUnopenedOuters['270',Pack2] demand_fit['270',M] 2 demand_fit['270',L] 4 + NumUnopenedOuters['270',Pack2] demand_fit['270',XL] 5 + NumUnopenedOuters['272',Pack2] TotalCost 1.5 demand_fit['272',S] 1 + NumUnopenedOuters['272',Pack2] demand_fit['272',M] 2 demand_fit['272',L] 4 + NumUnopenedOuters['272',Pack2] demand_fit['272',XL] 5 + NumUnopenedOuters['275',Pack2] TotalCost 1.5 demand_fit['275',S] 1 + NumUnopenedOuters['275',Pack2] demand_fit['275',M] 2 demand_fit['275',L] 4 + NumUnopenedOuters['275',Pack2] demand_fit['275',XL] 5 + NumUnopenedOuters['276',Pack2] TotalCost 1.5 demand_fit['276',S] 1 + NumUnopenedOuters['276',Pack2] demand_fit['276',M] 2 demand_fit['276',L] 4 + NumUnopenedOuters['276',Pack2] demand_fit['276',XL] 5 + NumUnopenedOuters['280',Pack2] TotalCost 1.5 demand_fit['280',S] 1 + NumUnopenedOuters['280',Pack2] demand_fit['280',M] 2 demand_fit['280',L] 4 + NumUnopenedOuters['280',Pack2] demand_fit['280',XL] 5 + NumUnopenedOuters['282',Pack2] TotalCost 1.5 demand_fit['282',S] 1 + NumUnopenedOuters['282',Pack2] demand_fit['282',M] 2 demand_fit['282',L] 4 + NumUnopenedOuters['282',Pack2] demand_fit['282',XL] 5 + NumUnopenedOuters['283',Pack2] TotalCost 1.5 demand_fit['283',S] 1 + NumUnopenedOuters['283',Pack2] demand_fit['283',M] 2 demand_fit['283',L] 4 + NumUnopenedOuters['283',Pack2] demand_fit['283',XL] 5 + NumUnopenedOuters['293',Pack2] TotalCost 1.5 demand_fit['293',S] 1 + NumUnopenedOuters['293',Pack2] demand_fit['293',M] 2 demand_fit['293',L] 4 + NumUnopenedOuters['293',Pack2] demand_fit['293',XL] 5 + NumUnopenedOuters['298',Pack2] TotalCost 1.5 demand_fit['298',S] 1 + NumUnopenedOuters['298',Pack2] demand_fit['298',M] 2 demand_fit['298',L] 4 + NumUnopenedOuters['298',Pack2] demand_fit['298',XL] 5 + NumUnopenedOuters['299',Pack2] TotalCost 1.5 demand_fit['299',S] 1 + NumUnopenedOuters['299',Pack2] demand_fit['299',M] 2 demand_fit['299',L] 4 + NumUnopenedOuters['299',Pack2] demand_fit['299',XL] 5 + NumUnopenedOuters['301',Pack2] TotalCost 1.5 demand_fit['301',S] 1 + NumUnopenedOuters['301',Pack2] demand_fit['301',M] 2 demand_fit['301',L] 4 + NumUnopenedOuters['301',Pack2] demand_fit['301',XL] 5 + NumUnopenedOuters['309',Pack2] TotalCost 1.5 demand_fit['309',S] 1 + NumUnopenedOuters['309',Pack2] demand_fit['309',M] 2 demand_fit['309',L] 4 + NumUnopenedOuters['309',Pack2] demand_fit['309',XL] 5 + NumUnopenedOuters['310',Pack2] TotalCost 1.5 demand_fit['310',S] 1 + NumUnopenedOuters['310',Pack2] demand_fit['310',M] 2 demand_fit['310',L] 4 + NumUnopenedOuters['310',Pack2] demand_fit['310',XL] 5 + NumUnopenedOuters['375',Pack2] TotalCost 1.5 demand_fit['375',S] 1 + NumUnopenedOuters['375',Pack2] demand_fit['375',M] 2 demand_fit['375',L] 4 + NumUnopenedOuters['375',Pack2] demand_fit['375',XL] 5 + NumUnopenedOuters['378',Pack2] TotalCost 1.5 demand_fit['378',S] 1 + NumUnopenedOuters['378',Pack2] demand_fit['378',M] 2 demand_fit['378',L] 4 + NumUnopenedOuters['378',Pack2] demand_fit['378',XL] 5 + NumUnopenedOuters['379',Pack2] TotalCost 1.5 demand_fit['379',S] 1 + NumUnopenedOuters['379',Pack2] demand_fit['379',M] 2 demand_fit['379',L] 4 + NumUnopenedOuters['379',Pack2] demand_fit['379',XL] 5 + NumUnopenedOuters['381',Pack2] TotalCost 1.5 demand_fit['381',S] 1 + NumUnopenedOuters['381',Pack2] demand_fit['381',M] 2 demand_fit['381',L] 4 + NumUnopenedOuters['381',Pack2] demand_fit['381',XL] 5 + NumUnopenedOuters['383',Pack2] TotalCost 1.5 demand_fit['383',S] 1 + NumUnopenedOuters['383',Pack2] demand_fit['383',M] 2 demand_fit['383',L] 4 + NumUnopenedOuters['383',Pack2] demand_fit['383',XL] 5 + NumUnopenedOuters['384',Pack2] TotalCost 1.5 demand_fit['384',S] 1 + NumUnopenedOuters['384',Pack2] demand_fit['384',M] 2 demand_fit['384',L] 4 + NumUnopenedOuters['384',Pack2] demand_fit['384',XL] 5 + NumUnopenedOuters['386',Pack2] TotalCost 1.5 demand_fit['386',S] 1 + NumUnopenedOuters['386',Pack2] demand_fit['386',M] 2 demand_fit['386',L] 4 + NumUnopenedOuters['386',Pack2] demand_fit['386',XL] 5 + NumUnopenedOuters['388',Pack2] TotalCost 1.5 demand_fit['388',S] 1 + NumUnopenedOuters['388',Pack2] demand_fit['388',M] 2 demand_fit['388',L] 4 + NumUnopenedOuters['388',Pack2] demand_fit['388',XL] 5 + NumUnopenedOuters['389',Pack2] TotalCost 1.5 demand_fit['389',S] 1 + NumUnopenedOuters['389',Pack2] demand_fit['389',M] 2 demand_fit['389',L] 4 + NumUnopenedOuters['389',Pack2] demand_fit['389',XL] 5 + NumUnopenedOuters['390',Pack2] TotalCost 1.5 demand_fit['390',S] 1 + NumUnopenedOuters['390',Pack2] demand_fit['390',M] 2 demand_fit['390',L] 4 + NumUnopenedOuters['390',Pack2] demand_fit['390',XL] 5 + NumUnopenedOuters['397',Pack2] TotalCost 1.5 demand_fit['397',S] 1 + NumUnopenedOuters['397',Pack2] demand_fit['397',M] 2 demand_fit['397',L] 4 + NumUnopenedOuters['397',Pack2] demand_fit['397',XL] 5 + NumUnopenedOuters['398',Pack2] TotalCost 1.5 demand_fit['398',S] 1 + NumUnopenedOuters['398',Pack2] demand_fit['398',M] 2 demand_fit['398',L] 4 + NumUnopenedOuters['398',Pack2] demand_fit['398',XL] 5 + NumUnopenedOuters['403',Pack2] TotalCost 1.5 demand_fit['403',S] 1 + NumUnopenedOuters['403',Pack2] demand_fit['403',M] 2 demand_fit['403',L] 4 + NumUnopenedOuters['403',Pack2] demand_fit['403',XL] 5 + NumUnopenedOuters['418',Pack2] TotalCost 1.5 demand_fit['418',S] 1 + NumUnopenedOuters['418',Pack2] demand_fit['418',M] 2 demand_fit['418',L] 4 + NumUnopenedOuters['418',Pack2] demand_fit['418',XL] 5 + NumUnopenedOuters['430',Pack2] TotalCost 1.5 demand_fit['430',S] 1 + NumUnopenedOuters['430',Pack2] demand_fit['430',M] 2 demand_fit['430',L] 4 + NumUnopenedOuters['430',Pack2] demand_fit['430',XL] 5 + NumUnopenedOuters['431',Pack2] TotalCost 1.5 demand_fit['431',S] 1 + NumUnopenedOuters['431',Pack2] demand_fit['431',M] 2 demand_fit['431',L] 4 + NumUnopenedOuters['431',Pack2] demand_fit['431',XL] 5 + NumUnopenedOuters['479',Pack2] TotalCost 1.5 demand_fit['479',S] 1 + NumUnopenedOuters['479',Pack2] demand_fit['479',M] 2 demand_fit['479',L] 4 + NumUnopenedOuters['479',Pack2] demand_fit['479',XL] 5 + NumUnopenedOuters['502',Pack2] TotalCost 1.5 demand_fit['502',S] 1 + NumUnopenedOuters['502',Pack2] demand_fit['502',M] 2 demand_fit['502',L] 4 + NumUnopenedOuters['502',Pack2] demand_fit['502',XL] 5 + NumUnopenedOuters['504',Pack2] TotalCost 1.5 demand_fit['504',S] 1 + NumUnopenedOuters['504',Pack2] demand_fit['504',M] 2 demand_fit['504',L] 4 + NumUnopenedOuters['504',Pack2] demand_fit['504',XL] 5 + NumUnopenedOuters['512',Pack2] TotalCost 1.5 demand_fit['512',S] 1 + NumUnopenedOuters['512',Pack2] demand_fit['512',M] 2 demand_fit['512',L] 4 + NumUnopenedOuters['512',Pack2] demand_fit['512',XL] 5 + NumUnopenedOuters['528',Pack2] TotalCost 1.5 demand_fit['528',S] 1 + NumUnopenedOuters['528',Pack2] demand_fit['528',M] 2 demand_fit['528',L] 4 + NumUnopenedOuters['528',Pack2] demand_fit['528',XL] 5 + NumUnopenedOuters['533',Pack2] TotalCost 1.5 demand_fit['533',S] 1 + NumUnopenedOuters['533',Pack2] demand_fit['533',M] 2 demand_fit['533',L] 4 + NumUnopenedOuters['533',Pack2] demand_fit['533',XL] 5 + NumUnopenedOuters['538',Pack2] TotalCost 1.5 demand_fit['538',S] 1 + NumUnopenedOuters['538',Pack2] demand_fit['538',M] 2 demand_fit['538',L] 4 + NumUnopenedOuters['538',Pack2] demand_fit['538',XL] 5 + NumUnopenedOuters['552',Pack2] TotalCost 1.5 demand_fit['552',S] 1 + NumUnopenedOuters['552',Pack2] demand_fit['552',M] 2 demand_fit['552',L] 4 + NumUnopenedOuters['552',Pack2] demand_fit['552',XL] 5 + NumUnopenedOuters['621',Pack2] TotalCost 1.5 demand_fit['621',S] 1 + NumUnopenedOuters['621',Pack2] demand_fit['621',M] 2 demand_fit['621',L] 4 + NumUnopenedOuters['621',Pack2] demand_fit['621',XL] 5 + NumUnopenedOuters['639',Pack2] TotalCost 1.5 demand_fit['639',S] 1 + NumUnopenedOuters['639',Pack2] demand_fit['639',M] 2 demand_fit['639',L] 4 + NumUnopenedOuters['639',Pack2] demand_fit['639',XL] 5 + NumUnopenedOuters['712',Pack2] TotalCost 1.5 demand_fit['712',S] 1 + NumUnopenedOuters['712',Pack2] demand_fit['712',M] 2 demand_fit['712',L] 4 + NumUnopenedOuters['712',Pack2] demand_fit['712',XL] 5 + NumUnopenedOuters['781',Pack2] TotalCost 1.5 demand_fit['781',S] 1 + NumUnopenedOuters['781',Pack2] demand_fit['781',M] 2 demand_fit['781',L] 4 + NumUnopenedOuters['781',Pack2] demand_fit['781',XL] 5 + NumUnopenedOuters['71',Pack3] TotalCost 0.5 demand_fit['71',S] 2 + NumUnopenedOuters['71',Pack3] demand_fit['71',M] 4 demand_fit['71',L] 3 + NumUnopenedOuters['71',Pack3] demand_fit['71',XL] 3 + NumUnopenedOuters['73',Pack3] TotalCost 0.5 demand_fit['73',S] 2 + NumUnopenedOuters['73',Pack3] demand_fit['73',M] 4 demand_fit['73',L] 3 + NumUnopenedOuters['73',Pack3] demand_fit['73',XL] 3 + NumUnopenedOuters['86',Pack3] TotalCost 0.5 demand_fit['86',S] 2 + NumUnopenedOuters['86',Pack3] demand_fit['86',M] 4 demand_fit['86',L] 3 + NumUnopenedOuters['86',Pack3] demand_fit['86',XL] 3 + NumUnopenedOuters['99',Pack3] TotalCost 0.5 demand_fit['99',S] 2 + NumUnopenedOuters['99',Pack3] demand_fit['99',M] 4 demand_fit['99',L] 3 + NumUnopenedOuters['99',Pack3] demand_fit['99',XL] 3 + NumUnopenedOuters['103',Pack3] TotalCost 0.5 demand_fit['103',S] 2 + NumUnopenedOuters['103',Pack3] demand_fit['103',M] 4 demand_fit['103',L] 3 + NumUnopenedOuters['103',Pack3] demand_fit['103',XL] 3 + NumUnopenedOuters['126',Pack3] TotalCost 0.5 demand_fit['126',S] 2 + NumUnopenedOuters['126',Pack3] demand_fit['126',M] 4 demand_fit['126',L] 3 + NumUnopenedOuters['126',Pack3] demand_fit['126',XL] 3 + NumUnopenedOuters['221',Pack3] TotalCost 0.5 demand_fit['221',S] 2 + NumUnopenedOuters['221',Pack3] demand_fit['221',M] 4 demand_fit['221',L] 3 + NumUnopenedOuters['221',Pack3] demand_fit['221',XL] 3 + NumUnopenedOuters['225',Pack3] TotalCost 0.5 demand_fit['225',S] 2 + NumUnopenedOuters['225',Pack3] demand_fit['225',M] 4 demand_fit['225',L] 3 + NumUnopenedOuters['225',Pack3] demand_fit['225',XL] 3 + NumUnopenedOuters['251',Pack3] TotalCost 0.5 demand_fit['251',S] 2 + NumUnopenedOuters['251',Pack3] demand_fit['251',M] 4 demand_fit['251',L] 3 + NumUnopenedOuters['251',Pack3] demand_fit['251',XL] 3 + NumUnopenedOuters['270',Pack3] TotalCost 0.5 demand_fit['270',S] 2 + NumUnopenedOuters['270',Pack3] demand_fit['270',M] 4 demand_fit['270',L] 3 + NumUnopenedOuters['270',Pack3] demand_fit['270',XL] 3 + NumUnopenedOuters['272',Pack3] TotalCost 0.5 demand_fit['272',S] 2 + NumUnopenedOuters['272',Pack3] demand_fit['272',M] 4 demand_fit['272',L] 3 + NumUnopenedOuters['272',Pack3] demand_fit['272',XL] 3 + NumUnopenedOuters['275',Pack3] TotalCost 0.5 demand_fit['275',S] 2 + NumUnopenedOuters['275',Pack3] demand_fit['275',M] 4 demand_fit['275',L] 3 + NumUnopenedOuters['275',Pack3] demand_fit['275',XL] 3 + NumUnopenedOuters['276',Pack3] TotalCost 0.5 demand_fit['276',S] 2 + NumUnopenedOuters['276',Pack3] demand_fit['276',M] 4 demand_fit['276',L] 3 + NumUnopenedOuters['276',Pack3] demand_fit['276',XL] 3 + NumUnopenedOuters['280',Pack3] TotalCost 0.5 demand_fit['280',S] 2 + NumUnopenedOuters['280',Pack3] demand_fit['280',M] 4 demand_fit['280',L] 3 + NumUnopenedOuters['280',Pack3] demand_fit['280',XL] 3 + NumUnopenedOuters['282',Pack3] TotalCost 0.5 demand_fit['282',S] 2 + NumUnopenedOuters['282',Pack3] demand_fit['282',M] 4 demand_fit['282',L] 3 + NumUnopenedOuters['282',Pack3] demand_fit['282',XL] 3 + NumUnopenedOuters['283',Pack3] TotalCost 0.5 demand_fit['283',S] 2 + NumUnopenedOuters['283',Pack3] demand_fit['283',M] 4 demand_fit['283',L] 3 + NumUnopenedOuters['283',Pack3] demand_fit['283',XL] 3 + NumUnopenedOuters['293',Pack3] TotalCost 0.5 demand_fit['293',S] 2 + NumUnopenedOuters['293',Pack3] demand_fit['293',M] 4 demand_fit['293',L] 3 + NumUnopenedOuters['293',Pack3] demand_fit['293',XL] 3 + NumUnopenedOuters['298',Pack3] TotalCost 0.5 demand_fit['298',S] 2 + NumUnopenedOuters['298',Pack3] demand_fit['298',M] 4 demand_fit['298',L] 3 + NumUnopenedOuters['298',Pack3] demand_fit['298',XL] 3 + NumUnopenedOuters['299',Pack3] TotalCost 0.5 demand_fit['299',S] 2 + NumUnopenedOuters['299',Pack3] demand_fit['299',M] 4 demand_fit['299',L] 3 + NumUnopenedOuters['299',Pack3] demand_fit['299',XL] 3 + NumUnopenedOuters['301',Pack3] TotalCost 0.5 demand_fit['301',S] 2 + NumUnopenedOuters['301',Pack3] demand_fit['301',M] 4 demand_fit['301',L] 3 + NumUnopenedOuters['301',Pack3] demand_fit['301',XL] 3 + NumUnopenedOuters['309',Pack3] TotalCost 0.5 demand_fit['309',S] 2 + NumUnopenedOuters['309',Pack3] demand_fit['309',M] 4 demand_fit['309',L] 3 + NumUnopenedOuters['309',Pack3] demand_fit['309',XL] 3 + NumUnopenedOuters['310',Pack3] TotalCost 0.5 demand_fit['310',S] 2 + NumUnopenedOuters['310',Pack3] demand_fit['310',M] 4 demand_fit['310',L] 3 + NumUnopenedOuters['310',Pack3] demand_fit['310',XL] 3 + NumUnopenedOuters['375',Pack3] TotalCost 0.5 demand_fit['375',S] 2 + NumUnopenedOuters['375',Pack3] demand_fit['375',M] 4 demand_fit['375',L] 3 + NumUnopenedOuters['375',Pack3] demand_fit['375',XL] 3 + NumUnopenedOuters['378',Pack3] TotalCost 0.5 demand_fit['378',S] 2 + NumUnopenedOuters['378',Pack3] demand_fit['378',M] 4 demand_fit['378',L] 3 + NumUnopenedOuters['378',Pack3] demand_fit['378',XL] 3 + NumUnopenedOuters['379',Pack3] TotalCost 0.5 demand_fit['379',S] 2 + NumUnopenedOuters['379',Pack3] demand_fit['379',M] 4 demand_fit['379',L] 3 + NumUnopenedOuters['379',Pack3] demand_fit['379',XL] 3 + NumUnopenedOuters['381',Pack3] TotalCost 0.5 demand_fit['381',S] 2 + NumUnopenedOuters['381',Pack3] demand_fit['381',M] 4 demand_fit['381',L] 3 + NumUnopenedOuters['381',Pack3] demand_fit['381',XL] 3 + NumUnopenedOuters['383',Pack3] TotalCost 0.5 demand_fit['383',S] 2 + NumUnopenedOuters['383',Pack3] demand_fit['383',M] 4 demand_fit['383',L] 3 + NumUnopenedOuters['383',Pack3] demand_fit['383',XL] 3 + NumUnopenedOuters['384',Pack3] TotalCost 0.5 demand_fit['384',S] 2 + NumUnopenedOuters['384',Pack3] demand_fit['384',M] 4 demand_fit['384',L] 3 + NumUnopenedOuters['384',Pack3] demand_fit['384',XL] 3 + NumUnopenedOuters['386',Pack3] TotalCost 0.5 demand_fit['386',S] 2 + NumUnopenedOuters['386',Pack3] demand_fit['386',M] 4 demand_fit['386',L] 3 + NumUnopenedOuters['386',Pack3] demand_fit['386',XL] 3 + NumUnopenedOuters['388',Pack3] TotalCost 0.5 demand_fit['388',S] 2 + NumUnopenedOuters['388',Pack3] demand_fit['388',M] 4 demand_fit['388',L] 3 + NumUnopenedOuters['388',Pack3] demand_fit['388',XL] 3 + NumUnopenedOuters['389',Pack3] TotalCost 0.5 demand_fit['389',S] 2 + NumUnopenedOuters['389',Pack3] demand_fit['389',M] 4 demand_fit['389',L] 3 + NumUnopenedOuters['389',Pack3] demand_fit['389',XL] 3 + NumUnopenedOuters['390',Pack3] TotalCost 0.5 demand_fit['390',S] 2 + NumUnopenedOuters['390',Pack3] demand_fit['390',M] 4 demand_fit['390',L] 3 + NumUnopenedOuters['390',Pack3] demand_fit['390',XL] 3 + NumUnopenedOuters['397',Pack3] TotalCost 0.5 demand_fit['397',S] 2 + NumUnopenedOuters['397',Pack3] demand_fit['397',M] 4 demand_fit['397',L] 3 + NumUnopenedOuters['397',Pack3] demand_fit['397',XL] 3 + NumUnopenedOuters['398',Pack3] TotalCost 0.5 demand_fit['398',S] 2 + NumUnopenedOuters['398',Pack3] demand_fit['398',M] 4 demand_fit['398',L] 3 + NumUnopenedOuters['398',Pack3] demand_fit['398',XL] 3 + NumUnopenedOuters['403',Pack3] TotalCost 0.5 demand_fit['403',S] 2 + NumUnopenedOuters['403',Pack3] demand_fit['403',M] 4 demand_fit['403',L] 3 + NumUnopenedOuters['403',Pack3] demand_fit['403',XL] 3 + NumUnopenedOuters['418',Pack3] TotalCost 0.5 demand_fit['418',S] 2 + NumUnopenedOuters['418',Pack3] demand_fit['418',M] 4 demand_fit['418',L] 3 + NumUnopenedOuters['418',Pack3] demand_fit['418',XL] 3 + NumUnopenedOuters['430',Pack3] TotalCost 0.5 demand_fit['430',S] 2 + NumUnopenedOuters['430',Pack3] demand_fit['430',M] 4 demand_fit['430',L] 3 + NumUnopenedOuters['430',Pack3] demand_fit['430',XL] 3 + NumUnopenedOuters['431',Pack3] TotalCost 0.5 demand_fit['431',S] 2 + NumUnopenedOuters['431',Pack3] demand_fit['431',M] 4 demand_fit['431',L] 3 + NumUnopenedOuters['431',Pack3] demand_fit['431',XL] 3 + NumUnopenedOuters['479',Pack3] TotalCost 0.5 demand_fit['479',S] 2 + NumUnopenedOuters['479',Pack3] demand_fit['479',M] 4 demand_fit['479',L] 3 + NumUnopenedOuters['479',Pack3] demand_fit['479',XL] 3 + NumUnopenedOuters['502',Pack3] TotalCost 0.5 demand_fit['502',S] 2 + NumUnopenedOuters['502',Pack3] demand_fit['502',M] 4 demand_fit['502',L] 3 + NumUnopenedOuters['502',Pack3] demand_fit['502',XL] 3 + NumUnopenedOuters['504',Pack3] TotalCost 0.5 demand_fit['504',S] 2 + NumUnopenedOuters['504',Pack3] demand_fit['504',M] 4 demand_fit['504',L] 3 + NumUnopenedOuters['504',Pack3] demand_fit['504',XL] 3 + NumUnopenedOuters['512',Pack3] TotalCost 0.5 demand_fit['512',S] 2 + NumUnopenedOuters['512',Pack3] demand_fit['512',M] 4 demand_fit['512',L] 3 + NumUnopenedOuters['512',Pack3] demand_fit['512',XL] 3 + NumUnopenedOuters['528',Pack3] TotalCost 0.5 demand_fit['528',S] 2 + NumUnopenedOuters['528',Pack3] demand_fit['528',M] 4 demand_fit['528',L] 3 + NumUnopenedOuters['528',Pack3] demand_fit['528',XL] 3 + NumUnopenedOuters['533',Pack3] TotalCost 0.5 demand_fit['533',S] 2 + NumUnopenedOuters['533',Pack3] demand_fit['533',M] 4 demand_fit['533',L] 3 + NumUnopenedOuters['533',Pack3] demand_fit['533',XL] 3 + NumUnopenedOuters['538',Pack3] TotalCost 0.5 demand_fit['538',S] 2 + NumUnopenedOuters['538',Pack3] demand_fit['538',M] 4 demand_fit['538',L] 3 + NumUnopenedOuters['538',Pack3] demand_fit['538',XL] 3 + NumUnopenedOuters['552',Pack3] TotalCost 0.5 demand_fit['552',S] 2 + NumUnopenedOuters['552',Pack3] demand_fit['552',M] 4 demand_fit['552',L] 3 + NumUnopenedOuters['552',Pack3] demand_fit['552',XL] 3 + NumUnopenedOuters['621',Pack3] TotalCost 0.5 demand_fit['621',S] 2 + NumUnopenedOuters['621',Pack3] demand_fit['621',M] 4 demand_fit['621',L] 3 + NumUnopenedOuters['621',Pack3] demand_fit['621',XL] 3 + NumUnopenedOuters['639',Pack3] TotalCost 0.5 demand_fit['639',S] 2 + NumUnopenedOuters['639',Pack3] demand_fit['639',M] 4 demand_fit['639',L] 3 + NumUnopenedOuters['639',Pack3] demand_fit['639',XL] 3 + NumUnopenedOuters['712',Pack3] TotalCost 0.5 demand_fit['712',S] 2 + NumUnopenedOuters['712',Pack3] demand_fit['712',M] 4 demand_fit['712',L] 3 + NumUnopenedOuters['712',Pack3] demand_fit['712',XL] 3 + NumUnopenedOuters['781',Pack3] TotalCost 0.5 demand_fit['781',S] 2 + NumUnopenedOuters['781',Pack3] demand_fit['781',M] 4 demand_fit['781',L] 3 + NumUnopenedOuters['781',Pack3] demand_fit['781',XL] 3 + NumOpenedOuters[Pack1] TotalCost 1 material_balance[Pack1] -1 + NumOpenedOuters[Pack2] TotalCost 1 material_balance[Pack2] -1 + NumOpenedOuters[Pack3] TotalCost 1 material_balance[Pack3] -1 + .MRK0001 'MARKER' 'INTEND' + NumOver['71',S] TotalCost 1 demand_fit['71',S] -1 + NumOver['73',S] TotalCost 1 demand_fit['73',S] -1 + NumOver['86',S] TotalCost 1 demand_fit['86',S] -1 + NumOver['99',S] TotalCost 1 demand_fit['99',S] -1 + NumOver['103',S] TotalCost 1 demand_fit['103',S] -1 + NumOver['126',S] TotalCost 1 demand_fit['126',S] -1 + NumOver['221',S] TotalCost 1 demand_fit['221',S] -1 + NumOver['225',S] TotalCost 1 demand_fit['225',S] -1 + NumOver['251',S] TotalCost 1 demand_fit['251',S] -1 + NumOver['270',S] TotalCost 1 demand_fit['270',S] -1 + NumOver['272',S] TotalCost 1 demand_fit['272',S] -1 + NumOver['275',S] TotalCost 1 demand_fit['275',S] -1 + NumOver['276',S] TotalCost 1 demand_fit['276',S] -1 + NumOver['280',S] TotalCost 1 demand_fit['280',S] -1 + NumOver['282',S] TotalCost 1 demand_fit['282',S] -1 + NumOver['283',S] TotalCost 1 demand_fit['283',S] -1 + NumOver['293',S] TotalCost 1 demand_fit['293',S] -1 + NumOver['298',S] TotalCost 1 demand_fit['298',S] -1 + NumOver['299',S] TotalCost 1 demand_fit['299',S] -1 + NumOver['301',S] TotalCost 1 demand_fit['301',S] -1 + NumOver['309',S] TotalCost 1 demand_fit['309',S] -1 + NumOver['310',S] TotalCost 1 demand_fit['310',S] -1 + NumOver['375',S] TotalCost 1 demand_fit['375',S] -1 + NumOver['378',S] TotalCost 1 demand_fit['378',S] -1 + NumOver['379',S] TotalCost 1 demand_fit['379',S] -1 + NumOver['381',S] TotalCost 1 demand_fit['381',S] -1 + NumOver['383',S] TotalCost 1 demand_fit['383',S] -1 + NumOver['384',S] TotalCost 1 demand_fit['384',S] -1 + NumOver['386',S] TotalCost 1 demand_fit['386',S] -1 + NumOver['388',S] TotalCost 1 demand_fit['388',S] -1 + NumOver['389',S] TotalCost 1 demand_fit['389',S] -1 + NumOver['390',S] TotalCost 1 demand_fit['390',S] -1 + NumOver['397',S] TotalCost 1 demand_fit['397',S] -1 + NumOver['398',S] TotalCost 1 demand_fit['398',S] -1 + NumOver['403',S] TotalCost 1 demand_fit['403',S] -1 + NumOver['418',S] TotalCost 1 demand_fit['418',S] -1 + NumOver['430',S] TotalCost 1 demand_fit['430',S] -1 + NumOver['431',S] TotalCost 1 demand_fit['431',S] -1 + NumOver['479',S] TotalCost 1 demand_fit['479',S] -1 + NumOver['502',S] TotalCost 1 demand_fit['502',S] -1 + NumOver['504',S] TotalCost 1 demand_fit['504',S] -1 + NumOver['512',S] TotalCost 1 demand_fit['512',S] -1 + NumOver['528',S] TotalCost 1 demand_fit['528',S] -1 + NumOver['533',S] TotalCost 1 demand_fit['533',S] -1 + NumOver['538',S] TotalCost 1 demand_fit['538',S] -1 + NumOver['552',S] TotalCost 1 demand_fit['552',S] -1 + NumOver['621',S] TotalCost 1 demand_fit['621',S] -1 + NumOver['639',S] TotalCost 1 demand_fit['639',S] -1 + NumOver['712',S] TotalCost 1 demand_fit['712',S] -1 + NumOver['781',S] TotalCost 1 demand_fit['781',S] -1 + NumOver['71',M] TotalCost 1 demand_fit['71',M] -1 + NumOver['73',M] TotalCost 1 demand_fit['73',M] -1 + NumOver['86',M] TotalCost 1 demand_fit['86',M] -1 + NumOver['99',M] TotalCost 1 demand_fit['99',M] -1 + NumOver['103',M] TotalCost 1 demand_fit['103',M] -1 + NumOver['126',M] TotalCost 1 demand_fit['126',M] -1 + NumOver['221',M] TotalCost 1 demand_fit['221',M] -1 + NumOver['225',M] TotalCost 1 demand_fit['225',M] -1 + NumOver['251',M] TotalCost 1 demand_fit['251',M] -1 + NumOver['270',M] TotalCost 1 demand_fit['270',M] -1 + NumOver['272',M] TotalCost 1 demand_fit['272',M] -1 + NumOver['275',M] TotalCost 1 demand_fit['275',M] -1 + NumOver['276',M] TotalCost 1 demand_fit['276',M] -1 + NumOver['280',M] TotalCost 1 demand_fit['280',M] -1 + NumOver['282',M] TotalCost 1 demand_fit['282',M] -1 + NumOver['283',M] TotalCost 1 demand_fit['283',M] -1 + NumOver['293',M] TotalCost 1 demand_fit['293',M] -1 + NumOver['298',M] TotalCost 1 demand_fit['298',M] -1 + NumOver['299',M] TotalCost 1 demand_fit['299',M] -1 + NumOver['301',M] TotalCost 1 demand_fit['301',M] -1 + NumOver['309',M] TotalCost 1 demand_fit['309',M] -1 + NumOver['310',M] TotalCost 1 demand_fit['310',M] -1 + NumOver['375',M] TotalCost 1 demand_fit['375',M] -1 + NumOver['378',M] TotalCost 1 demand_fit['378',M] -1 + NumOver['379',M] TotalCost 1 demand_fit['379',M] -1 + NumOver['381',M] TotalCost 1 demand_fit['381',M] -1 + NumOver['383',M] TotalCost 1 demand_fit['383',M] -1 + NumOver['384',M] TotalCost 1 demand_fit['384',M] -1 + NumOver['386',M] TotalCost 1 demand_fit['386',M] -1 + NumOver['388',M] TotalCost 1 demand_fit['388',M] -1 + NumOver['389',M] TotalCost 1 demand_fit['389',M] -1 + NumOver['390',M] TotalCost 1 demand_fit['390',M] -1 + NumOver['397',M] TotalCost 1 demand_fit['397',M] -1 + NumOver['398',M] TotalCost 1 demand_fit['398',M] -1 + NumOver['403',M] TotalCost 1 demand_fit['403',M] -1 + NumOver['418',M] TotalCost 1 demand_fit['418',M] -1 + NumOver['430',M] TotalCost 1 demand_fit['430',M] -1 + NumOver['431',M] TotalCost 1 demand_fit['431',M] -1 + NumOver['479',M] TotalCost 1 demand_fit['479',M] -1 + NumOver['502',M] TotalCost 1 demand_fit['502',M] -1 + NumOver['504',M] TotalCost 1 demand_fit['504',M] -1 + NumOver['512',M] TotalCost 1 demand_fit['512',M] -1 + NumOver['528',M] TotalCost 1 demand_fit['528',M] -1 + NumOver['533',M] TotalCost 1 demand_fit['533',M] -1 + NumOver['538',M] TotalCost 1 demand_fit['538',M] -1 + NumOver['552',M] TotalCost 1 demand_fit['552',M] -1 + NumOver['621',M] TotalCost 1 demand_fit['621',M] -1 + NumOver['639',M] TotalCost 1 demand_fit['639',M] -1 + NumOver['712',M] TotalCost 1 demand_fit['712',M] -1 + NumOver['781',M] TotalCost 1 demand_fit['781',M] -1 + NumOver['71',L] TotalCost 1 demand_fit['71',L] -1 + NumOver['73',L] TotalCost 1 demand_fit['73',L] -1 + NumOver['86',L] TotalCost 1 demand_fit['86',L] -1 + NumOver['99',L] TotalCost 1 demand_fit['99',L] -1 + NumOver['103',L] TotalCost 1 demand_fit['103',L] -1 + NumOver['126',L] TotalCost 1 demand_fit['126',L] -1 + NumOver['221',L] TotalCost 1 demand_fit['221',L] -1 + NumOver['225',L] TotalCost 1 demand_fit['225',L] -1 + NumOver['251',L] TotalCost 1 demand_fit['251',L] -1 + NumOver['270',L] TotalCost 1 demand_fit['270',L] -1 + NumOver['272',L] TotalCost 1 demand_fit['272',L] -1 + NumOver['275',L] TotalCost 1 demand_fit['275',L] -1 + NumOver['276',L] TotalCost 1 demand_fit['276',L] -1 + NumOver['280',L] TotalCost 1 demand_fit['280',L] -1 + NumOver['282',L] TotalCost 1 demand_fit['282',L] -1 + NumOver['283',L] TotalCost 1 demand_fit['283',L] -1 + NumOver['293',L] TotalCost 1 demand_fit['293',L] -1 + NumOver['298',L] TotalCost 1 demand_fit['298',L] -1 + NumOver['299',L] TotalCost 1 demand_fit['299',L] -1 + NumOver['301',L] TotalCost 1 demand_fit['301',L] -1 + NumOver['309',L] TotalCost 1 demand_fit['309',L] -1 + NumOver['310',L] TotalCost 1 demand_fit['310',L] -1 + NumOver['375',L] TotalCost 1 demand_fit['375',L] -1 + NumOver['378',L] TotalCost 1 demand_fit['378',L] -1 + NumOver['379',L] TotalCost 1 demand_fit['379',L] -1 + NumOver['381',L] TotalCost 1 demand_fit['381',L] -1 + NumOver['383',L] TotalCost 1 demand_fit['383',L] -1 + NumOver['384',L] TotalCost 1 demand_fit['384',L] -1 + NumOver['386',L] TotalCost 1 demand_fit['386',L] -1 + NumOver['388',L] TotalCost 1 demand_fit['388',L] -1 + NumOver['389',L] TotalCost 1 demand_fit['389',L] -1 + NumOver['390',L] TotalCost 1 demand_fit['390',L] -1 + NumOver['397',L] TotalCost 1 demand_fit['397',L] -1 + NumOver['398',L] TotalCost 1 demand_fit['398',L] -1 + NumOver['403',L] TotalCost 1 demand_fit['403',L] -1 + NumOver['418',L] TotalCost 1 demand_fit['418',L] -1 + NumOver['430',L] TotalCost 1 demand_fit['430',L] -1 + NumOver['431',L] TotalCost 1 demand_fit['431',L] -1 + NumOver['479',L] TotalCost 1 demand_fit['479',L] -1 + NumOver['502',L] TotalCost 1 demand_fit['502',L] -1 + NumOver['504',L] TotalCost 1 demand_fit['504',L] -1 + NumOver['512',L] TotalCost 1 demand_fit['512',L] -1 + NumOver['528',L] TotalCost 1 demand_fit['528',L] -1 + NumOver['533',L] TotalCost 1 demand_fit['533',L] -1 + NumOver['538',L] TotalCost 1 demand_fit['538',L] -1 + NumOver['552',L] TotalCost 1 demand_fit['552',L] -1 + NumOver['621',L] TotalCost 1 demand_fit['621',L] -1 + NumOver['639',L] TotalCost 1 demand_fit['639',L] -1 + NumOver['712',L] TotalCost 1 demand_fit['712',L] -1 + NumOver['781',L] TotalCost 1 demand_fit['781',L] -1 + NumOver['71',XL] TotalCost 1 demand_fit['71',XL] -1 + NumOver['73',XL] TotalCost 1 demand_fit['73',XL] -1 + NumOver['86',XL] TotalCost 1 demand_fit['86',XL] -1 + NumOver['99',XL] TotalCost 1 demand_fit['99',XL] -1 + NumOver['103',XL] TotalCost 1 demand_fit['103',XL] -1 + NumOver['126',XL] TotalCost 1 demand_fit['126',XL] -1 + NumOver['221',XL] TotalCost 1 demand_fit['221',XL] -1 + NumOver['225',XL] TotalCost 1 demand_fit['225',XL] -1 + NumOver['251',XL] TotalCost 1 demand_fit['251',XL] -1 + NumOver['270',XL] TotalCost 1 demand_fit['270',XL] -1 + NumOver['272',XL] TotalCost 1 demand_fit['272',XL] -1 + NumOver['275',XL] TotalCost 1 demand_fit['275',XL] -1 + NumOver['276',XL] TotalCost 1 demand_fit['276',XL] -1 + NumOver['280',XL] TotalCost 1 demand_fit['280',XL] -1 + NumOver['282',XL] TotalCost 1 demand_fit['282',XL] -1 + NumOver['283',XL] TotalCost 1 demand_fit['283',XL] -1 + NumOver['293',XL] TotalCost 1 demand_fit['293',XL] -1 + NumOver['298',XL] TotalCost 1 demand_fit['298',XL] -1 + NumOver['299',XL] TotalCost 1 demand_fit['299',XL] -1 + NumOver['301',XL] TotalCost 1 demand_fit['301',XL] -1 + NumOver['309',XL] TotalCost 1 demand_fit['309',XL] -1 + NumOver['310',XL] TotalCost 1 demand_fit['310',XL] -1 + NumOver['375',XL] TotalCost 1 demand_fit['375',XL] -1 + NumOver['378',XL] TotalCost 1 demand_fit['378',XL] -1 + NumOver['379',XL] TotalCost 1 demand_fit['379',XL] -1 + NumOver['381',XL] TotalCost 1 demand_fit['381',XL] -1 + NumOver['383',XL] TotalCost 1 demand_fit['383',XL] -1 + NumOver['384',XL] TotalCost 1 demand_fit['384',XL] -1 + NumOver['386',XL] TotalCost 1 demand_fit['386',XL] -1 + NumOver['388',XL] TotalCost 1 demand_fit['388',XL] -1 + NumOver['389',XL] TotalCost 1 demand_fit['389',XL] -1 + NumOver['390',XL] TotalCost 1 demand_fit['390',XL] -1 + NumOver['397',XL] TotalCost 1 demand_fit['397',XL] -1 + NumOver['398',XL] TotalCost 1 demand_fit['398',XL] -1 + NumOver['403',XL] TotalCost 1 demand_fit['403',XL] -1 + NumOver['418',XL] TotalCost 1 demand_fit['418',XL] -1 + NumOver['430',XL] TotalCost 1 demand_fit['430',XL] -1 + NumOver['431',XL] TotalCost 1 demand_fit['431',XL] -1 + NumOver['479',XL] TotalCost 1 demand_fit['479',XL] -1 + NumOver['502',XL] TotalCost 1 demand_fit['502',XL] -1 + NumOver['504',XL] TotalCost 1 demand_fit['504',XL] -1 + NumOver['512',XL] TotalCost 1 demand_fit['512',XL] -1 + NumOver['528',XL] TotalCost 1 demand_fit['528',XL] -1 + NumOver['533',XL] TotalCost 1 demand_fit['533',XL] -1 + NumOver['538',XL] TotalCost 1 demand_fit['538',XL] -1 + NumOver['552',XL] TotalCost 1 demand_fit['552',XL] -1 + NumOver['621',XL] TotalCost 1 demand_fit['621',XL] -1 + NumOver['639',XL] TotalCost 1 demand_fit['639',XL] -1 + NumOver['712',XL] TotalCost 1 demand_fit['712',XL] -1 + NumOver['781',XL] TotalCost 1 demand_fit['781',XL] -1 + NumUnder['71',S] TotalCost 6 demand_fit['71',S] 1 + NumUnder['73',S] TotalCost 6 demand_fit['73',S] 1 + NumUnder['86',S] TotalCost 6 demand_fit['86',S] 1 + NumUnder['99',S] TotalCost 6 demand_fit['99',S] 1 + NumUnder['103',S] TotalCost 6 demand_fit['103',S] 1 + NumUnder['126',S] TotalCost 6 demand_fit['126',S] 1 + NumUnder['221',S] TotalCost 6 demand_fit['221',S] 1 + NumUnder['225',S] TotalCost 6 demand_fit['225',S] 1 + NumUnder['251',S] TotalCost 6 demand_fit['251',S] 1 + NumUnder['270',S] TotalCost 6 demand_fit['270',S] 1 + NumUnder['272',S] TotalCost 6 demand_fit['272',S] 1 + NumUnder['275',S] TotalCost 6 demand_fit['275',S] 1 + NumUnder['276',S] TotalCost 6 demand_fit['276',S] 1 + NumUnder['280',S] TotalCost 6 demand_fit['280',S] 1 + NumUnder['282',S] TotalCost 6 demand_fit['282',S] 1 + NumUnder['283',S] TotalCost 6 demand_fit['283',S] 1 + NumUnder['293',S] TotalCost 6 demand_fit['293',S] 1 + NumUnder['298',S] TotalCost 6 demand_fit['298',S] 1 + NumUnder['299',S] TotalCost 6 demand_fit['299',S] 1 + NumUnder['301',S] TotalCost 6 demand_fit['301',S] 1 + NumUnder['309',S] TotalCost 6 demand_fit['309',S] 1 + NumUnder['310',S] TotalCost 6 demand_fit['310',S] 1 + NumUnder['375',S] TotalCost 6 demand_fit['375',S] 1 + NumUnder['378',S] TotalCost 6 demand_fit['378',S] 1 + NumUnder['379',S] TotalCost 6 demand_fit['379',S] 1 + NumUnder['381',S] TotalCost 6 demand_fit['381',S] 1 + NumUnder['383',S] TotalCost 6 demand_fit['383',S] 1 + NumUnder['384',S] TotalCost 6 demand_fit['384',S] 1 + NumUnder['386',S] TotalCost 6 demand_fit['386',S] 1 + NumUnder['388',S] TotalCost 6 demand_fit['388',S] 1 + NumUnder['389',S] TotalCost 6 demand_fit['389',S] 1 + NumUnder['390',S] TotalCost 15 demand_fit['390',S] 1 + NumUnder['397',S] TotalCost 6 demand_fit['397',S] 1 + NumUnder['398',S] TotalCost 6 demand_fit['398',S] 1 + NumUnder['403',S] TotalCost 6 demand_fit['403',S] 1 + NumUnder['418',S] TotalCost 6 demand_fit['418',S] 1 + NumUnder['430',S] TotalCost 6 demand_fit['430',S] 1 + NumUnder['431',S] TotalCost 6 demand_fit['431',S] 1 + NumUnder['479',S] TotalCost 6 demand_fit['479',S] 1 + NumUnder['502',S] TotalCost 6 demand_fit['502',S] 1 + NumUnder['504',S] TotalCost 6 demand_fit['504',S] 1 + NumUnder['512',S] TotalCost 6 demand_fit['512',S] 1 + NumUnder['528',S] TotalCost 6 demand_fit['528',S] 1 + NumUnder['533',S] TotalCost 6 demand_fit['533',S] 1 + NumUnder['538',S] TotalCost 6 demand_fit['538',S] 1 + NumUnder['552',S] TotalCost 6 demand_fit['552',S] 1 + NumUnder['621',S] TotalCost 6 demand_fit['621',S] 1 + NumUnder['639',S] TotalCost 6 demand_fit['639',S] 1 + NumUnder['712',S] TotalCost 6 demand_fit['712',S] 1 + NumUnder['781',S] TotalCost 6 demand_fit['781',S] 1 + NumUnder['71',M] TotalCost 6 demand_fit['71',M] 1 + NumUnder['73',M] TotalCost 6 demand_fit['73',M] 1 + NumUnder['86',M] TotalCost 6 demand_fit['86',M] 1 + NumUnder['99',M] TotalCost 6 demand_fit['99',M] 1 + NumUnder['103',M] TotalCost 6 demand_fit['103',M] 1 + NumUnder['126',M] TotalCost 6 demand_fit['126',M] 1 + NumUnder['221',M] TotalCost 6 demand_fit['221',M] 1 + NumUnder['225',M] TotalCost 6 demand_fit['225',M] 1 + NumUnder['251',M] TotalCost 6 demand_fit['251',M] 1 + NumUnder['270',M] TotalCost 6 demand_fit['270',M] 1 + NumUnder['272',M] TotalCost 6 demand_fit['272',M] 1 + NumUnder['275',M] TotalCost 6 demand_fit['275',M] 1 + NumUnder['276',M] TotalCost 6 demand_fit['276',M] 1 + NumUnder['280',M] TotalCost 6 demand_fit['280',M] 1 + NumUnder['282',M] TotalCost 6 demand_fit['282',M] 1 + NumUnder['283',M] TotalCost 6 demand_fit['283',M] 1 + NumUnder['293',M] TotalCost 6 demand_fit['293',M] 1 + NumUnder['298',M] TotalCost 6 demand_fit['298',M] 1 + NumUnder['299',M] TotalCost 6 demand_fit['299',M] 1 + NumUnder['301',M] TotalCost 6 demand_fit['301',M] 1 + NumUnder['309',M] TotalCost 6 demand_fit['309',M] 1 + NumUnder['310',M] TotalCost 6 demand_fit['310',M] 1 + NumUnder['375',M] TotalCost 6 demand_fit['375',M] 1 + NumUnder['378',M] TotalCost 6 demand_fit['378',M] 1 + NumUnder['379',M] TotalCost 6 demand_fit['379',M] 1 + NumUnder['381',M] TotalCost 6 demand_fit['381',M] 1 + NumUnder['383',M] TotalCost 6 demand_fit['383',M] 1 + NumUnder['384',M] TotalCost 6 demand_fit['384',M] 1 + NumUnder['386',M] TotalCost 6 demand_fit['386',M] 1 + NumUnder['388',M] TotalCost 6 demand_fit['388',M] 1 + NumUnder['389',M] TotalCost 6 demand_fit['389',M] 1 + NumUnder['390',M] TotalCost 15 demand_fit['390',M] 1 + NumUnder['397',M] TotalCost 6 demand_fit['397',M] 1 + NumUnder['398',M] TotalCost 6 demand_fit['398',M] 1 + NumUnder['403',M] TotalCost 6 demand_fit['403',M] 1 + NumUnder['418',M] TotalCost 6 demand_fit['418',M] 1 + NumUnder['430',M] TotalCost 6 demand_fit['430',M] 1 + NumUnder['431',M] TotalCost 6 demand_fit['431',M] 1 + NumUnder['479',M] TotalCost 6 demand_fit['479',M] 1 + NumUnder['502',M] TotalCost 6 demand_fit['502',M] 1 + NumUnder['504',M] TotalCost 6 demand_fit['504',M] 1 + NumUnder['512',M] TotalCost 6 demand_fit['512',M] 1 + NumUnder['528',M] TotalCost 6 demand_fit['528',M] 1 + NumUnder['533',M] TotalCost 6 demand_fit['533',M] 1 + NumUnder['538',M] TotalCost 6 demand_fit['538',M] 1 + NumUnder['552',M] TotalCost 6 demand_fit['552',M] 1 + NumUnder['621',M] TotalCost 6 demand_fit['621',M] 1 + NumUnder['639',M] TotalCost 6 demand_fit['639',M] 1 + NumUnder['712',M] TotalCost 6 demand_fit['712',M] 1 + NumUnder['781',M] TotalCost 6 demand_fit['781',M] 1 + NumUnder['71',L] TotalCost 6 demand_fit['71',L] 1 + NumUnder['73',L] TotalCost 6 demand_fit['73',L] 1 + NumUnder['86',L] TotalCost 6 demand_fit['86',L] 1 + NumUnder['99',L] TotalCost 6 demand_fit['99',L] 1 + NumUnder['103',L] TotalCost 6 demand_fit['103',L] 1 + NumUnder['126',L] TotalCost 6 demand_fit['126',L] 1 + NumUnder['221',L] TotalCost 6 demand_fit['221',L] 1 + NumUnder['225',L] TotalCost 6 demand_fit['225',L] 1 + NumUnder['251',L] TotalCost 6 demand_fit['251',L] 1 + NumUnder['270',L] TotalCost 6 demand_fit['270',L] 1 + NumUnder['272',L] TotalCost 6 demand_fit['272',L] 1 + NumUnder['275',L] TotalCost 6 demand_fit['275',L] 1 + NumUnder['276',L] TotalCost 6 demand_fit['276',L] 1 + NumUnder['280',L] TotalCost 6 demand_fit['280',L] 1 + NumUnder['282',L] TotalCost 6 demand_fit['282',L] 1 + NumUnder['283',L] TotalCost 6 demand_fit['283',L] 1 + NumUnder['293',L] TotalCost 6 demand_fit['293',L] 1 + NumUnder['298',L] TotalCost 6 demand_fit['298',L] 1 + NumUnder['299',L] TotalCost 6 demand_fit['299',L] 1 + NumUnder['301',L] TotalCost 6 demand_fit['301',L] 1 + NumUnder['309',L] TotalCost 6 demand_fit['309',L] 1 + NumUnder['310',L] TotalCost 6 demand_fit['310',L] 1 + NumUnder['375',L] TotalCost 6 demand_fit['375',L] 1 + NumUnder['378',L] TotalCost 6 demand_fit['378',L] 1 + NumUnder['379',L] TotalCost 6 demand_fit['379',L] 1 + NumUnder['381',L] TotalCost 6 demand_fit['381',L] 1 + NumUnder['383',L] TotalCost 6 demand_fit['383',L] 1 + NumUnder['384',L] TotalCost 6 demand_fit['384',L] 1 + NumUnder['386',L] TotalCost 6 demand_fit['386',L] 1 + NumUnder['388',L] TotalCost 6 demand_fit['388',L] 1 + NumUnder['389',L] TotalCost 6 demand_fit['389',L] 1 + NumUnder['390',L] TotalCost 6 demand_fit['390',L] 1 + NumUnder['397',L] TotalCost 6 demand_fit['397',L] 1 + NumUnder['398',L] TotalCost 6 demand_fit['398',L] 1 + NumUnder['403',L] TotalCost 6 demand_fit['403',L] 1 + NumUnder['418',L] TotalCost 6 demand_fit['418',L] 1 + NumUnder['430',L] TotalCost 6 demand_fit['430',L] 1 + NumUnder['431',L] TotalCost 6 demand_fit['431',L] 1 + NumUnder['479',L] TotalCost 6 demand_fit['479',L] 1 + NumUnder['502',L] TotalCost 6 demand_fit['502',L] 1 + NumUnder['504',L] TotalCost 6 demand_fit['504',L] 1 + NumUnder['512',L] TotalCost 6 demand_fit['512',L] 1 + NumUnder['528',L] TotalCost 6 demand_fit['528',L] 1 + NumUnder['533',L] TotalCost 6 demand_fit['533',L] 1 + NumUnder['538',L] TotalCost 6 demand_fit['538',L] 1 + NumUnder['552',L] TotalCost 6 demand_fit['552',L] 1 + NumUnder['621',L] TotalCost 6 demand_fit['621',L] 1 + NumUnder['639',L] TotalCost 6 demand_fit['639',L] 1 + NumUnder['712',L] TotalCost 6 demand_fit['712',L] 1 + NumUnder['781',L] TotalCost 6 demand_fit['781',L] 1 + NumUnder['71',XL] TotalCost 6 demand_fit['71',XL] 1 + NumUnder['73',XL] TotalCost 6 demand_fit['73',XL] 1 + NumUnder['86',XL] TotalCost 6 demand_fit['86',XL] 1 + NumUnder['99',XL] TotalCost 6 demand_fit['99',XL] 1 + NumUnder['103',XL] TotalCost 6 demand_fit['103',XL] 1 + NumUnder['126',XL] TotalCost 6 demand_fit['126',XL] 1 + NumUnder['221',XL] TotalCost 6 demand_fit['221',XL] 1 + NumUnder['225',XL] TotalCost 6 demand_fit['225',XL] 1 + NumUnder['251',XL] TotalCost 6 demand_fit['251',XL] 1 + NumUnder['270',XL] TotalCost 6 demand_fit['270',XL] 1 + NumUnder['272',XL] TotalCost 6 demand_fit['272',XL] 1 + NumUnder['275',XL] TotalCost 6 demand_fit['275',XL] 1 + NumUnder['276',XL] TotalCost 6 demand_fit['276',XL] 1 + NumUnder['280',XL] TotalCost 6 demand_fit['280',XL] 1 + NumUnder['282',XL] TotalCost 6 demand_fit['282',XL] 1 + NumUnder['283',XL] TotalCost 6 demand_fit['283',XL] 1 + NumUnder['293',XL] TotalCost 6 demand_fit['293',XL] 1 + NumUnder['298',XL] TotalCost 6 demand_fit['298',XL] 1 + NumUnder['299',XL] TotalCost 6 demand_fit['299',XL] 1 + NumUnder['301',XL] TotalCost 6 demand_fit['301',XL] 1 + NumUnder['309',XL] TotalCost 6 demand_fit['309',XL] 1 + NumUnder['310',XL] TotalCost 6 demand_fit['310',XL] 1 + NumUnder['375',XL] TotalCost 6 demand_fit['375',XL] 1 + NumUnder['378',XL] TotalCost 6 demand_fit['378',XL] 1 + NumUnder['379',XL] TotalCost 6 demand_fit['379',XL] 1 + NumUnder['381',XL] TotalCost 6 demand_fit['381',XL] 1 + NumUnder['383',XL] TotalCost 6 demand_fit['383',XL] 1 + NumUnder['384',XL] TotalCost 6 demand_fit['384',XL] 1 + NumUnder['386',XL] TotalCost 6 demand_fit['386',XL] 1 + NumUnder['388',XL] TotalCost 6 demand_fit['388',XL] 1 + NumUnder['389',XL] TotalCost 6 demand_fit['389',XL] 1 + NumUnder['390',XL] TotalCost 6 demand_fit['390',XL] 1 + NumUnder['397',XL] TotalCost 6 demand_fit['397',XL] 1 + NumUnder['398',XL] TotalCost 6 demand_fit['398',XL] 1 + NumUnder['403',XL] TotalCost 6 demand_fit['403',XL] 1 + NumUnder['418',XL] TotalCost 6 demand_fit['418',XL] 1 + NumUnder['430',XL] TotalCost 6 demand_fit['430',XL] 1 + NumUnder['431',XL] TotalCost 6 demand_fit['431',XL] 1 + NumUnder['479',XL] TotalCost 6 demand_fit['479',XL] 1 + NumUnder['502',XL] TotalCost 6 demand_fit['502',XL] 1 + NumUnder['504',XL] TotalCost 6 demand_fit['504',XL] 1 + NumUnder['512',XL] TotalCost 6 demand_fit['512',XL] 1 + NumUnder['528',XL] TotalCost 6 demand_fit['528',XL] 1 + NumUnder['533',XL] TotalCost 6 demand_fit['533',XL] 1 + NumUnder['538',XL] TotalCost 6 demand_fit['538',XL] 1 + NumUnder['552',XL] TotalCost 6 demand_fit['552',XL] 1 + NumUnder['621',XL] TotalCost 6 demand_fit['621',XL] 1 + NumUnder['639',XL] TotalCost 6 demand_fit['639',XL] 1 + NumUnder['712',XL] TotalCost 6 demand_fit['712',XL] 1 + NumUnder['781',XL] TotalCost 6 demand_fit['781',XL] 1 +RHS + .RHS. demand_fit['71',S] 3.64592208 + .RHS. demand_fit['73',S] 6.645651 + .RHS. demand_fit['86',S] 8.46011328 + .RHS. demand_fit['99',S] 5.2875708 + .RHS. demand_fit['103',S] 6.38036364 + .RHS. demand_fit['126',S] 9.3039114 + .RHS. demand_fit['221',S] 8.46011328 + .RHS. demand_fit['225',S] 2.11502832 + .RHS. demand_fit['251',S] 5.2875708 + .RHS. demand_fit['270',S] 2.73444156 + .RHS. demand_fit['272',S] 5.2875708 + .RHS. demand_fit['275',S] 7.40259912 + .RHS. demand_fit['276',S] 6.645651 + .RHS. demand_fit['280',S] 3.17254248 + .RHS. demand_fit['282',S] 9.3039114 + .RHS. demand_fit['283',S] 3.64592208 + .RHS. demand_fit['293',S] 2.11502832 + .RHS. demand_fit['298',S] 4.23005664 + .RHS. demand_fit['299',S] 7.40259912 + .RHS. demand_fit['301',S] 5.3165208 + .RHS. demand_fit['309',S] 6.645651 + .RHS. demand_fit['310',S] 4.5574026 + .RHS. demand_fit['375',S] 6.645651 + .RHS. demand_fit['378',S] 3.9873906 + .RHS. demand_fit['379',S] 6.38036364 + .RHS. demand_fit['381',S] 3.9873906 + .RHS. demand_fit['383',S] 5.2875708 + .RHS. demand_fit['384',S] 9.3039114 + .RHS. demand_fit['386',S] 5.3165208 + .RHS. demand_fit['388',S] 5.2875708 + .RHS. demand_fit['389',S] 8.46011328 + .RHS. demand_fit['390',S] 13.291302 + .RHS. demand_fit['397',S] 6.645651 + .RHS. demand_fit['398',S] 10.6330416 + .RHS. demand_fit['403',S] 9.1148052 + .RHS. demand_fit['418',S] 5.3165208 + .RHS. demand_fit['430',S] 5.3165208 + .RHS. demand_fit['431',S] 3.64592208 + .RHS. demand_fit['479',S] 3.9873906 + .RHS. demand_fit['502',S] 3.17254248 + .RHS. demand_fit['504',S] 5.2875708 + .RHS. demand_fit['512',S] 4.23005664 + .RHS. demand_fit['528',S] 2.11502832 + .RHS. demand_fit['533',S] 4.23005664 + .RHS. demand_fit['538',S] 5.2875708 + .RHS. demand_fit['552',S] 3.64592208 + .RHS. demand_fit['621',S] 6.38036364 + .RHS. demand_fit['639',S] 2.6582604 + .RHS. demand_fit['712',S] 3.9873906 + .RHS. demand_fit['781',S] 6.645651 + .RHS. demand_fit['71',M] 10.64293584 + .RHS. demand_fit['73',M] 15.4621008 + .RHS. demand_fit['86',M] 23.24756064 + .RHS. demand_fit['99',M] 14.5297254 + .RHS. demand_fit['103',M] 18.62513772 + .RHS. demand_fit['126',M] 21.64694112 + .RHS. demand_fit['221',M] 23.24756064 + .RHS. demand_fit['225',M] 5.81189016 + .RHS. demand_fit['251',M] 14.5297254 + .RHS. demand_fit['270',M] 7.98220188 + .RHS. demand_fit['272',M] 14.5297254 + .RHS. demand_fit['275',M] 20.34161556 + .RHS. demand_fit['276',M] 15.4621008 + .RHS. demand_fit['280',M] 8.71783524 + .RHS. demand_fit['282',M] 21.64694112 + .RHS. demand_fit['283',M] 10.64293584 + .RHS. demand_fit['293',M] 5.81189016 + .RHS. demand_fit['298',M] 11.62378032 + .RHS. demand_fit['299',M] 20.34161556 + .RHS. demand_fit['301',M] 12.36968064 + .RHS. demand_fit['309',M] 15.4621008 + .RHS. demand_fit['310',M] 13.3036698 + .RHS. demand_fit['375',M] 15.4621008 + .RHS. demand_fit['378',M] 9.27726048 + .RHS. demand_fit['379',M] 18.62513772 + .RHS. demand_fit['381',M] 9.27726048 + .RHS. demand_fit['383',M] 14.5297254 + .RHS. demand_fit['384',M] 21.64694112 + .RHS. demand_fit['386',M] 12.36968064 + .RHS. demand_fit['388',M] 14.5297254 + .RHS. demand_fit['389',M] 23.24756064 + .RHS. demand_fit['390',M] 30.9242016 + .RHS. demand_fit['397',M] 15.4621008 + .RHS. demand_fit['398',M] 24.73936128 + .RHS. demand_fit['403',M] 26.6073396 + .RHS. demand_fit['418',M] 12.36968064 + .RHS. demand_fit['430',M] 12.36968064 + .RHS. demand_fit['431',M] 10.64293584 + .RHS. demand_fit['479',M] 9.27726048 + .RHS. demand_fit['502',M] 8.71783524 + .RHS. demand_fit['504',M] 14.5297254 + .RHS. demand_fit['512',M] 11.62378032 + .RHS. demand_fit['528',M] 5.81189016 + .RHS. demand_fit['533',M] 11.62378032 + .RHS. demand_fit['538',M] 14.5297254 + .RHS. demand_fit['552',M] 10.64293584 + .RHS. demand_fit['621',M] 18.62513772 + .RHS. demand_fit['639',M] 6.18484032 + .RHS. demand_fit['712',M] 9.27726048 + .RHS. demand_fit['781',M] 15.4621008 + .RHS. demand_fit['71',L] 15.62372304 + .RHS. demand_fit['73',L] 18.2540478 + .RHS. demand_fit['86',L] 31.526496 + .RHS. demand_fit['99',L] 19.70406 + .RHS. demand_fit['103',L] 27.34151532 + .RHS. demand_fit['126',L] 25.55566692 + .RHS. demand_fit['221',L] 31.526496 + .RHS. demand_fit['225',L] 7.881624 + .RHS. demand_fit['251',L] 19.70406 + .RHS. demand_fit['270',L] 11.71779228 + .RHS. demand_fit['272',L] 19.70406 + .RHS. demand_fit['275',L] 27.585684 + .RHS. demand_fit['276',L] 18.2540478 + .RHS. demand_fit['280',L] 11.822436 + .RHS. demand_fit['282',L] 25.55566692 + .RHS. demand_fit['283',L] 15.62372304 + .RHS. demand_fit['293',L] 7.881624 + .RHS. demand_fit['298',L] 15.763248 + .RHS. demand_fit['299',L] 27.585684 + .RHS. demand_fit['301',L] 14.60323824 + .RHS. demand_fit['309',L] 18.2540478 + .RHS. demand_fit['310',L] 19.5296538 + .RHS. demand_fit['375',L] 18.2540478 + .RHS. demand_fit['378',L] 10.95242868 + .RHS. demand_fit['379',L] 27.34151532 + .RHS. demand_fit['381',L] 10.95242868 + .RHS. demand_fit['383',L] 19.70406 + .RHS. demand_fit['384',L] 25.55566692 + .RHS. demand_fit['386',L] 14.60323824 + .RHS. demand_fit['388',L] 19.70406 + .RHS. demand_fit['389',L] 31.526496 + .RHS. demand_fit['390',L] 36.5080956 + .RHS. demand_fit['397',L] 18.2540478 + .RHS. demand_fit['398',L] 29.20647648 + .RHS. demand_fit['403',L] 39.0593076 + .RHS. demand_fit['418',L] 14.60323824 + .RHS. demand_fit['430',L] 14.60323824 + .RHS. demand_fit['431',L] 15.62372304 + .RHS. demand_fit['479',L] 10.95242868 + .RHS. demand_fit['502',L] 11.822436 + .RHS. demand_fit['504',L] 19.70406 + .RHS. demand_fit['512',L] 15.763248 + .RHS. demand_fit['528',L] 7.881624 + .RHS. demand_fit['533',L] 15.763248 + .RHS. demand_fit['538',L] 19.70406 + .RHS. demand_fit['552',L] 15.62372304 + .RHS. demand_fit['621',L] 27.34151532 + .RHS. demand_fit['639',L] 7.30161912 + .RHS. demand_fit['712',L] 10.95242868 + .RHS. demand_fit['781',L] 18.2540478 + .RHS. demand_fit['71',XL] 18.08741904 + .RHS. demand_fit['73',XL] 19.6382004 + .RHS. demand_fit['86',XL] 32.76582912 + .RHS. demand_fit['99',XL] 20.4786432 + .RHS. demand_fit['103',XL] 31.65298332 + .RHS. demand_fit['126',XL] 27.49348056 + .RHS. demand_fit['221',XL] 32.76582912 + .RHS. demand_fit['225',XL] 8.19145728 + .RHS. demand_fit['251',XL] 20.4786432 + .RHS. demand_fit['270',XL] 13.56556428 + .RHS. demand_fit['272',XL] 20.4786432 + .RHS. demand_fit['275',XL] 28.67010048 + .RHS. demand_fit['276',XL] 19.6382004 + .RHS. demand_fit['280',XL] 12.28718592 + .RHS. demand_fit['282',XL] 27.49348056 + .RHS. demand_fit['283',XL] 18.08741904 + .RHS. demand_fit['293',XL] 8.19145728 + .RHS. demand_fit['298',XL] 16.38291456 + .RHS. demand_fit['299',XL] 28.67010048 + .RHS. demand_fit['301',XL] 15.71056032 + .RHS. demand_fit['309',XL] 19.6382004 + .RHS. demand_fit['310',XL] 22.6092738 + .RHS. demand_fit['375',XL] 19.6382004 + .RHS. demand_fit['378',XL] 11.78292024 + .RHS. demand_fit['379',XL] 31.65298332 + .RHS. demand_fit['381',XL] 11.78292024 + .RHS. demand_fit['383',XL] 20.4786432 + .RHS. demand_fit['384',XL] 27.49348056 + .RHS. demand_fit['386',XL] 15.71056032 + .RHS. demand_fit['388',XL] 20.4786432 + .RHS. demand_fit['389',XL] 32.76582912 + .RHS. demand_fit['390',XL] 39.2764008 + .RHS. demand_fit['397',XL] 19.6382004 + .RHS. demand_fit['398',XL] 31.42112064 + .RHS. demand_fit['403',XL] 45.2185476 + .RHS. demand_fit['418',XL] 15.71056032 + .RHS. demand_fit['430',XL] 15.71056032 + .RHS. demand_fit['431',XL] 18.08741904 + .RHS. demand_fit['479',XL] 11.78292024 + .RHS. demand_fit['502',XL] 12.28718592 + .RHS. demand_fit['504',XL] 20.4786432 + .RHS. demand_fit['512',XL] 16.38291456 + .RHS. demand_fit['528',XL] 8.19145728 + .RHS. demand_fit['533',XL] 16.38291456 + .RHS. demand_fit['538',XL] 20.4786432 + .RHS. demand_fit['552',XL] 18.08741904 + .RHS. demand_fit['621',XL] 31.65298332 + .RHS. demand_fit['639',XL] 7.85528016 + .RHS. demand_fit['712',XL] 11.78292024 + .RHS. demand_fit['781',XL] 19.6382004 +BOUNDS + FX .BOUNDS. NumLooseInners['71',Pack1] 0 + FX .BOUNDS. NumLooseInners['73',Pack1] 0 + FX .BOUNDS. NumLooseInners['86',Pack1] 0 + FX .BOUNDS. NumLooseInners['99',Pack1] 0 + FX .BOUNDS. NumLooseInners['103',Pack1] 0 + FX .BOUNDS. NumLooseInners['126',Pack1] 0 + FX .BOUNDS. NumLooseInners['221',Pack1] 0 + FX .BOUNDS. NumLooseInners['225',Pack1] 0 + FX .BOUNDS. NumLooseInners['251',Pack1] 0 + FX .BOUNDS. NumLooseInners['270',Pack1] 0 + FX .BOUNDS. NumLooseInners['272',Pack1] 0 + FX .BOUNDS. NumLooseInners['275',Pack1] 0 + FX .BOUNDS. NumLooseInners['276',Pack1] 0 + FX .BOUNDS. NumLooseInners['280',Pack1] 0 + FX .BOUNDS. NumLooseInners['282',Pack1] 0 + FX .BOUNDS. NumLooseInners['283',Pack1] 0 + FX .BOUNDS. NumLooseInners['293',Pack1] 0 + FX .BOUNDS. NumLooseInners['298',Pack1] 0 + FX .BOUNDS. NumLooseInners['299',Pack1] 0 + FX .BOUNDS. NumLooseInners['301',Pack1] 0 + FX .BOUNDS. NumLooseInners['309',Pack1] 0 + FX .BOUNDS. NumLooseInners['310',Pack1] 0 + FX .BOUNDS. NumLooseInners['375',Pack1] 0 + FX .BOUNDS. NumLooseInners['378',Pack1] 0 + FX .BOUNDS. NumLooseInners['379',Pack1] 0 + FX .BOUNDS. NumLooseInners['381',Pack1] 0 + FX .BOUNDS. NumLooseInners['383',Pack1] 0 + FX .BOUNDS. NumLooseInners['384',Pack1] 0 + FX .BOUNDS. NumLooseInners['386',Pack1] 0 + FX .BOUNDS. NumLooseInners['388',Pack1] 0 + FX .BOUNDS. NumLooseInners['389',Pack1] 0 + FX .BOUNDS. NumLooseInners['390',Pack1] 0 + FX .BOUNDS. NumLooseInners['397',Pack1] 0 + FX .BOUNDS. NumLooseInners['398',Pack1] 0 + FX .BOUNDS. NumLooseInners['403',Pack1] 0 + FX .BOUNDS. NumLooseInners['418',Pack1] 0 + FX .BOUNDS. NumLooseInners['430',Pack1] 0 + FX .BOUNDS. NumLooseInners['431',Pack1] 0 + FX .BOUNDS. NumLooseInners['479',Pack1] 0 + FX .BOUNDS. NumLooseInners['502',Pack1] 0 + FX .BOUNDS. NumLooseInners['504',Pack1] 0 + FX .BOUNDS. NumLooseInners['512',Pack1] 0 + FX .BOUNDS. NumLooseInners['528',Pack1] 0 + FX .BOUNDS. NumLooseInners['533',Pack1] 0 + FX .BOUNDS. NumLooseInners['538',Pack1] 0 + FX .BOUNDS. NumLooseInners['552',Pack1] 0 + FX .BOUNDS. NumLooseInners['621',Pack1] 0 + FX .BOUNDS. NumLooseInners['639',Pack1] 0 + FX .BOUNDS. NumLooseInners['712',Pack1] 0 + FX .BOUNDS. NumLooseInners['781',Pack1] 0 + FX .BOUNDS. NumLooseInners['71',Pack2] 0 + FX .BOUNDS. NumLooseInners['73',Pack2] 0 + FX .BOUNDS. NumLooseInners['86',Pack2] 0 + FX .BOUNDS. NumLooseInners['99',Pack2] 0 + FX .BOUNDS. NumLooseInners['103',Pack2] 0 + FX .BOUNDS. NumLooseInners['126',Pack2] 0 + FX .BOUNDS. NumLooseInners['221',Pack2] 0 + FX .BOUNDS. NumLooseInners['225',Pack2] 0 + FX .BOUNDS. NumLooseInners['251',Pack2] 0 + FX .BOUNDS. NumLooseInners['270',Pack2] 0 + FX .BOUNDS. NumLooseInners['272',Pack2] 0 + FX .BOUNDS. NumLooseInners['275',Pack2] 0 + FX .BOUNDS. NumLooseInners['276',Pack2] 0 + FX .BOUNDS. NumLooseInners['280',Pack2] 0 + FX .BOUNDS. NumLooseInners['282',Pack2] 0 + FX .BOUNDS. NumLooseInners['283',Pack2] 0 + FX .BOUNDS. NumLooseInners['293',Pack2] 0 + FX .BOUNDS. NumLooseInners['298',Pack2] 0 + FX .BOUNDS. NumLooseInners['299',Pack2] 0 + FX .BOUNDS. NumLooseInners['301',Pack2] 0 + FX .BOUNDS. NumLooseInners['309',Pack2] 0 + FX .BOUNDS. NumLooseInners['310',Pack2] 0 + FX .BOUNDS. NumLooseInners['375',Pack2] 0 + FX .BOUNDS. NumLooseInners['378',Pack2] 0 + FX .BOUNDS. NumLooseInners['379',Pack2] 0 + FX .BOUNDS. NumLooseInners['381',Pack2] 0 + FX .BOUNDS. NumLooseInners['383',Pack2] 0 + FX .BOUNDS. NumLooseInners['384',Pack2] 0 + FX .BOUNDS. NumLooseInners['386',Pack2] 0 + FX .BOUNDS. NumLooseInners['388',Pack2] 0 + FX .BOUNDS. NumLooseInners['389',Pack2] 0 + FX .BOUNDS. NumLooseInners['390',Pack2] 0 + FX .BOUNDS. NumLooseInners['397',Pack2] 0 + FX .BOUNDS. NumLooseInners['398',Pack2] 0 + FX .BOUNDS. NumLooseInners['403',Pack2] 0 + FX .BOUNDS. NumLooseInners['418',Pack2] 0 + FX .BOUNDS. NumLooseInners['430',Pack2] 0 + FX .BOUNDS. NumLooseInners['431',Pack2] 0 + FX .BOUNDS. NumLooseInners['479',Pack2] 0 + FX .BOUNDS. NumLooseInners['502',Pack2] 0 + FX .BOUNDS. NumLooseInners['504',Pack2] 0 + FX .BOUNDS. NumLooseInners['512',Pack2] 0 + FX .BOUNDS. NumLooseInners['528',Pack2] 0 + FX .BOUNDS. NumLooseInners['533',Pack2] 0 + FX .BOUNDS. NumLooseInners['538',Pack2] 0 + FX .BOUNDS. NumLooseInners['552',Pack2] 0 + FX .BOUNDS. NumLooseInners['621',Pack2] 0 + FX .BOUNDS. NumLooseInners['639',Pack2] 0 + FX .BOUNDS. NumLooseInners['712',Pack2] 0 + FX .BOUNDS. NumLooseInners['781',Pack2] 0 + FX .BOUNDS. NumLooseInners['71',Pack3] 0 + FX .BOUNDS. NumLooseInners['73',Pack3] 0 + FX .BOUNDS. NumLooseInners['86',Pack3] 0 + FX .BOUNDS. NumLooseInners['99',Pack3] 0 + FX .BOUNDS. NumLooseInners['103',Pack3] 0 + FX .BOUNDS. NumLooseInners['126',Pack3] 0 + FX .BOUNDS. NumLooseInners['221',Pack3] 0 + FX .BOUNDS. NumLooseInners['225',Pack3] 0 + FX .BOUNDS. NumLooseInners['251',Pack3] 0 + FX .BOUNDS. NumLooseInners['270',Pack3] 0 + FX .BOUNDS. NumLooseInners['272',Pack3] 0 + FX .BOUNDS. NumLooseInners['275',Pack3] 0 + FX .BOUNDS. NumLooseInners['276',Pack3] 0 + FX .BOUNDS. NumLooseInners['280',Pack3] 0 + FX .BOUNDS. NumLooseInners['282',Pack3] 0 + FX .BOUNDS. NumLooseInners['283',Pack3] 0 + FX .BOUNDS. NumLooseInners['293',Pack3] 0 + FX .BOUNDS. NumLooseInners['298',Pack3] 0 + FX .BOUNDS. NumLooseInners['299',Pack3] 0 + FX .BOUNDS. NumLooseInners['301',Pack3] 0 + FX .BOUNDS. NumLooseInners['309',Pack3] 0 + FX .BOUNDS. NumLooseInners['310',Pack3] 0 + FX .BOUNDS. NumLooseInners['375',Pack3] 0 + FX .BOUNDS. NumLooseInners['378',Pack3] 0 + FX .BOUNDS. NumLooseInners['379',Pack3] 0 + FX .BOUNDS. NumLooseInners['381',Pack3] 0 + FX .BOUNDS. NumLooseInners['383',Pack3] 0 + FX .BOUNDS. NumLooseInners['384',Pack3] 0 + FX .BOUNDS. NumLooseInners['386',Pack3] 0 + FX .BOUNDS. NumLooseInners['388',Pack3] 0 + FX .BOUNDS. NumLooseInners['389',Pack3] 0 + FX .BOUNDS. NumLooseInners['390',Pack3] 0 + FX .BOUNDS. NumLooseInners['397',Pack3] 0 + FX .BOUNDS. NumLooseInners['398',Pack3] 0 + FX .BOUNDS. NumLooseInners['403',Pack3] 0 + FX .BOUNDS. NumLooseInners['418',Pack3] 0 + FX .BOUNDS. NumLooseInners['430',Pack3] 0 + FX .BOUNDS. NumLooseInners['431',Pack3] 0 + FX .BOUNDS. NumLooseInners['479',Pack3] 0 + FX .BOUNDS. NumLooseInners['502',Pack3] 0 + FX .BOUNDS. NumLooseInners['504',Pack3] 0 + FX .BOUNDS. NumLooseInners['512',Pack3] 0 + FX .BOUNDS. NumLooseInners['528',Pack3] 0 + FX .BOUNDS. NumLooseInners['533',Pack3] 0 + FX .BOUNDS. NumLooseInners['538',Pack3] 0 + FX .BOUNDS. NumLooseInners['552',Pack3] 0 + FX .BOUNDS. NumLooseInners['621',Pack3] 0 + FX .BOUNDS. NumLooseInners['639',Pack3] 0 + FX .BOUNDS. NumLooseInners['712',Pack3] 0 + FX .BOUNDS. NumLooseInners['781',Pack3] 0 + UP .BOUNDS. NumUnopenedOuters['71',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['73',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['86',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['99',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['103',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['126',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['221',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['225',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['251',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['270',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['272',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['275',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['276',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['280',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['282',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['283',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['293',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['298',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['299',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['301',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['309',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['310',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['375',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['378',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['379',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['381',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['383',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['384',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['386',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['388',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['389',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['390',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['397',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['398',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['403',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['418',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['430',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['431',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['479',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['502',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['504',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['512',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['528',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['533',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['538',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['552',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['621',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['639',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['712',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['781',Pack1] 1000 + UP .BOUNDS. NumUnopenedOuters['71',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['73',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['86',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['99',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['103',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['126',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['221',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['225',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['251',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['270',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['272',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['275',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['276',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['280',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['282',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['283',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['293',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['298',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['299',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['301',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['309',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['310',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['375',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['378',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['379',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['381',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['383',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['384',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['386',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['388',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['389',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['390',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['397',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['398',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['403',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['418',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['430',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['431',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['479',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['502',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['504',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['512',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['528',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['533',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['538',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['552',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['621',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['639',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['712',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['781',Pack2] 1000 + UP .BOUNDS. NumUnopenedOuters['71',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['73',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['86',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['99',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['103',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['126',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['221',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['225',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['251',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['270',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['272',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['275',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['276',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['280',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['282',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['283',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['293',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['298',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['299',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['301',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['309',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['310',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['375',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['378',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['379',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['381',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['383',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['384',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['386',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['388',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['389',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['390',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['397',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['398',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['403',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['418',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['430',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['431',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['479',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['502',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['504',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['512',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['528',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['533',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['538',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['552',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['621',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['639',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['712',Pack3] 1000 + UP .BOUNDS. NumUnopenedOuters['781',Pack3] 1000 + FX .BOUNDS. NumOpenedOuters[Pack1] 0 + FX .BOUNDS. NumOpenedOuters[Pack2] 0 + FX .BOUNDS. NumOpenedOuters[Pack3] 0 + UP .BOUNDS. NumUnder['71',S] 3.64592208 + UP .BOUNDS. NumUnder['73',S] 6.645651 + UP .BOUNDS. NumUnder['86',S] 8.46011328 + UP .BOUNDS. NumUnder['99',S] 5.2875708 + UP .BOUNDS. NumUnder['103',S] 6.38036364 + UP .BOUNDS. NumUnder['126',S] 9.3039114 + UP .BOUNDS. NumUnder['221',S] 8.46011328 + UP .BOUNDS. NumUnder['225',S] 2.11502832 + UP .BOUNDS. NumUnder['251',S] 5.2875708 + UP .BOUNDS. NumUnder['270',S] 2.73444156 + UP .BOUNDS. NumUnder['272',S] 5.2875708 + UP .BOUNDS. NumUnder['275',S] 7.40259912 + UP .BOUNDS. NumUnder['276',S] 6.645651 + UP .BOUNDS. NumUnder['280',S] 3.17254248 + UP .BOUNDS. NumUnder['282',S] 9.3039114 + UP .BOUNDS. NumUnder['283',S] 3.64592208 + UP .BOUNDS. NumUnder['293',S] 2.11502832 + UP .BOUNDS. NumUnder['298',S] 4.23005664 + UP .BOUNDS. NumUnder['299',S] 7.40259912 + UP .BOUNDS. NumUnder['301',S] 5.3165208 + UP .BOUNDS. NumUnder['309',S] 6.645651 + UP .BOUNDS. NumUnder['310',S] 4.5574026 + UP .BOUNDS. NumUnder['375',S] 6.645651 + UP .BOUNDS. NumUnder['378',S] 3.9873906 + UP .BOUNDS. NumUnder['379',S] 6.38036364 + UP .BOUNDS. NumUnder['381',S] 3.9873906 + UP .BOUNDS. NumUnder['383',S] 5.2875708 + UP .BOUNDS. NumUnder['384',S] 9.3039114 + UP .BOUNDS. NumUnder['386',S] 5.3165208 + UP .BOUNDS. NumUnder['388',S] 5.2875708 + UP .BOUNDS. NumUnder['389',S] 8.46011328 + UP .BOUNDS. NumUnder['390',S] 13.291302 + UP .BOUNDS. NumUnder['397',S] 6.645651 + UP .BOUNDS. NumUnder['398',S] 10.6330416 + UP .BOUNDS. NumUnder['403',S] 9.1148052 + UP .BOUNDS. NumUnder['418',S] 5.3165208 + UP .BOUNDS. NumUnder['430',S] 5.3165208 + UP .BOUNDS. NumUnder['431',S] 3.64592208 + UP .BOUNDS. NumUnder['479',S] 3.9873906 + UP .BOUNDS. NumUnder['502',S] 3.17254248 + UP .BOUNDS. NumUnder['504',S] 5.2875708 + UP .BOUNDS. NumUnder['512',S] 4.23005664 + UP .BOUNDS. NumUnder['528',S] 2.11502832 + UP .BOUNDS. NumUnder['533',S] 4.23005664 + UP .BOUNDS. NumUnder['538',S] 5.2875708 + UP .BOUNDS. NumUnder['552',S] 3.64592208 + UP .BOUNDS. NumUnder['621',S] 6.38036364 + UP .BOUNDS. NumUnder['639',S] 2.6582604 + UP .BOUNDS. NumUnder['712',S] 3.9873906 + UP .BOUNDS. NumUnder['781',S] 6.645651 + UP .BOUNDS. NumUnder['71',M] 10.64293584 + UP .BOUNDS. NumUnder['73',M] 15.4621008 + UP .BOUNDS. NumUnder['86',M] 23.24756064 + UP .BOUNDS. NumUnder['99',M] 14.5297254 + UP .BOUNDS. NumUnder['103',M] 18.62513772 + UP .BOUNDS. NumUnder['126',M] 21.64694112 + UP .BOUNDS. NumUnder['221',M] 23.24756064 + UP .BOUNDS. NumUnder['225',M] 5.81189016 + UP .BOUNDS. NumUnder['251',M] 14.5297254 + UP .BOUNDS. NumUnder['270',M] 7.98220188 + UP .BOUNDS. NumUnder['272',M] 14.5297254 + UP .BOUNDS. NumUnder['275',M] 20.34161556 + UP .BOUNDS. NumUnder['276',M] 15.4621008 + UP .BOUNDS. NumUnder['280',M] 8.71783524 + UP .BOUNDS. NumUnder['282',M] 21.64694112 + UP .BOUNDS. NumUnder['283',M] 10.64293584 + UP .BOUNDS. NumUnder['293',M] 5.81189016 + UP .BOUNDS. NumUnder['298',M] 11.62378032 + UP .BOUNDS. NumUnder['299',M] 20.34161556 + UP .BOUNDS. NumUnder['301',M] 12.36968064 + UP .BOUNDS. NumUnder['309',M] 15.4621008 + UP .BOUNDS. NumUnder['310',M] 13.3036698 + UP .BOUNDS. NumUnder['375',M] 15.4621008 + UP .BOUNDS. NumUnder['378',M] 9.27726048 + UP .BOUNDS. NumUnder['379',M] 18.62513772 + UP .BOUNDS. NumUnder['381',M] 9.27726048 + UP .BOUNDS. NumUnder['383',M] 14.5297254 + UP .BOUNDS. NumUnder['384',M] 21.64694112 + UP .BOUNDS. NumUnder['386',M] 12.36968064 + UP .BOUNDS. NumUnder['388',M] 14.5297254 + UP .BOUNDS. NumUnder['389',M] 23.24756064 + UP .BOUNDS. NumUnder['390',M] 30.9242016 + UP .BOUNDS. NumUnder['397',M] 15.4621008 + UP .BOUNDS. NumUnder['398',M] 24.73936128 + UP .BOUNDS. NumUnder['403',M] 26.6073396 + UP .BOUNDS. NumUnder['418',M] 12.36968064 + UP .BOUNDS. NumUnder['430',M] 12.36968064 + UP .BOUNDS. NumUnder['431',M] 10.64293584 + UP .BOUNDS. NumUnder['479',M] 9.27726048 + UP .BOUNDS. NumUnder['502',M] 8.71783524 + UP .BOUNDS. NumUnder['504',M] 14.5297254 + UP .BOUNDS. NumUnder['512',M] 11.62378032 + UP .BOUNDS. NumUnder['528',M] 5.81189016 + UP .BOUNDS. NumUnder['533',M] 11.62378032 + UP .BOUNDS. NumUnder['538',M] 14.5297254 + UP .BOUNDS. NumUnder['552',M] 10.64293584 + UP .BOUNDS. NumUnder['621',M] 18.62513772 + UP .BOUNDS. NumUnder['639',M] 6.18484032 + UP .BOUNDS. NumUnder['712',M] 9.27726048 + UP .BOUNDS. NumUnder['781',M] 15.4621008 + UP .BOUNDS. NumUnder['71',L] 15.62372304 + UP .BOUNDS. NumUnder['73',L] 18.2540478 + UP .BOUNDS. NumUnder['86',L] 31.526496 + UP .BOUNDS. NumUnder['99',L] 19.70406 + UP .BOUNDS. NumUnder['103',L] 27.34151532 + UP .BOUNDS. NumUnder['126',L] 25.55566692 + UP .BOUNDS. NumUnder['221',L] 31.526496 + UP .BOUNDS. NumUnder['225',L] 7.881624 + UP .BOUNDS. NumUnder['251',L] 19.70406 + UP .BOUNDS. NumUnder['270',L] 11.71779228 + UP .BOUNDS. NumUnder['272',L] 19.70406 + UP .BOUNDS. NumUnder['275',L] 27.585684 + UP .BOUNDS. NumUnder['276',L] 18.2540478 + UP .BOUNDS. NumUnder['280',L] 11.822436 + UP .BOUNDS. NumUnder['282',L] 25.55566692 + UP .BOUNDS. NumUnder['283',L] 15.62372304 + UP .BOUNDS. NumUnder['293',L] 7.881624 + UP .BOUNDS. NumUnder['298',L] 15.763248 + UP .BOUNDS. NumUnder['299',L] 27.585684 + UP .BOUNDS. NumUnder['301',L] 14.60323824 + UP .BOUNDS. NumUnder['309',L] 18.2540478 + UP .BOUNDS. NumUnder['310',L] 19.5296538 + UP .BOUNDS. NumUnder['375',L] 18.2540478 + UP .BOUNDS. NumUnder['378',L] 10.95242868 + UP .BOUNDS. NumUnder['379',L] 27.34151532 + UP .BOUNDS. NumUnder['381',L] 10.95242868 + UP .BOUNDS. NumUnder['383',L] 19.70406 + UP .BOUNDS. NumUnder['384',L] 25.55566692 + UP .BOUNDS. NumUnder['386',L] 14.60323824 + UP .BOUNDS. NumUnder['388',L] 19.70406 + UP .BOUNDS. NumUnder['389',L] 31.526496 + UP .BOUNDS. NumUnder['390',L] 36.5080956 + UP .BOUNDS. NumUnder['397',L] 18.2540478 + UP .BOUNDS. NumUnder['398',L] 29.20647648 + UP .BOUNDS. NumUnder['403',L] 39.0593076 + UP .BOUNDS. NumUnder['418',L] 14.60323824 + UP .BOUNDS. NumUnder['430',L] 14.60323824 + UP .BOUNDS. NumUnder['431',L] 15.62372304 + UP .BOUNDS. NumUnder['479',L] 10.95242868 + UP .BOUNDS. NumUnder['502',L] 11.822436 + UP .BOUNDS. NumUnder['504',L] 19.70406 + UP .BOUNDS. NumUnder['512',L] 15.763248 + UP .BOUNDS. NumUnder['528',L] 7.881624 + UP .BOUNDS. NumUnder['533',L] 15.763248 + UP .BOUNDS. NumUnder['538',L] 19.70406 + UP .BOUNDS. NumUnder['552',L] 15.62372304 + UP .BOUNDS. NumUnder['621',L] 27.34151532 + UP .BOUNDS. NumUnder['639',L] 7.30161912 + UP .BOUNDS. NumUnder['712',L] 10.95242868 + UP .BOUNDS. NumUnder['781',L] 18.2540478 + UP .BOUNDS. NumUnder['71',XL] 18.08741904 + UP .BOUNDS. NumUnder['73',XL] 19.6382004 + UP .BOUNDS. NumUnder['86',XL] 32.76582912 + UP .BOUNDS. NumUnder['99',XL] 20.4786432 + UP .BOUNDS. NumUnder['103',XL] 31.65298332 + UP .BOUNDS. NumUnder['126',XL] 27.49348056 + UP .BOUNDS. NumUnder['221',XL] 32.76582912 + UP .BOUNDS. NumUnder['225',XL] 8.19145728 + UP .BOUNDS. NumUnder['251',XL] 20.4786432 + UP .BOUNDS. NumUnder['270',XL] 13.56556428 + UP .BOUNDS. NumUnder['272',XL] 20.4786432 + UP .BOUNDS. NumUnder['275',XL] 28.67010048 + UP .BOUNDS. NumUnder['276',XL] 19.6382004 + UP .BOUNDS. NumUnder['280',XL] 12.28718592 + UP .BOUNDS. NumUnder['282',XL] 27.49348056 + UP .BOUNDS. NumUnder['283',XL] 18.08741904 + UP .BOUNDS. NumUnder['293',XL] 8.19145728 + UP .BOUNDS. NumUnder['298',XL] 16.38291456 + UP .BOUNDS. NumUnder['299',XL] 28.67010048 + UP .BOUNDS. NumUnder['301',XL] 15.71056032 + UP .BOUNDS. NumUnder['309',XL] 19.6382004 + UP .BOUNDS. NumUnder['310',XL] 22.6092738 + UP .BOUNDS. NumUnder['375',XL] 19.6382004 + UP .BOUNDS. NumUnder['378',XL] 11.78292024 + UP .BOUNDS. NumUnder['379',XL] 31.65298332 + UP .BOUNDS. NumUnder['381',XL] 11.78292024 + UP .BOUNDS. NumUnder['383',XL] 20.4786432 + UP .BOUNDS. NumUnder['384',XL] 27.49348056 + UP .BOUNDS. NumUnder['386',XL] 15.71056032 + UP .BOUNDS. NumUnder['388',XL] 20.4786432 + UP .BOUNDS. NumUnder['389',XL] 32.76582912 + UP .BOUNDS. NumUnder['390',XL] 39.2764008 + UP .BOUNDS. NumUnder['397',XL] 19.6382004 + UP .BOUNDS. NumUnder['398',XL] 31.42112064 + UP .BOUNDS. NumUnder['403',XL] 45.2185476 + UP .BOUNDS. NumUnder['418',XL] 15.71056032 + UP .BOUNDS. NumUnder['430',XL] 15.71056032 + UP .BOUNDS. NumUnder['431',XL] 18.08741904 + UP .BOUNDS. NumUnder['479',XL] 11.78292024 + UP .BOUNDS. NumUnder['502',XL] 12.28718592 + UP .BOUNDS. NumUnder['504',XL] 20.4786432 + UP .BOUNDS. NumUnder['512',XL] 16.38291456 + UP .BOUNDS. NumUnder['528',XL] 8.19145728 + UP .BOUNDS. NumUnder['533',XL] 16.38291456 + UP .BOUNDS. NumUnder['538',XL] 20.4786432 + UP .BOUNDS. NumUnder['552',XL] 18.08741904 + UP .BOUNDS. NumUnder['621',XL] 31.65298332 + UP .BOUNDS. NumUnder['639',XL] 7.85528016 + UP .BOUNDS. NumUnder['712',XL] 11.78292024 + UP .BOUNDS. NumUnder['781',XL] 19.6382004 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/scOneInt.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/scOneInt.mps new file mode 100644 index 000000000..770d57720 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/scOneInt.mps @@ -0,0 +1,32 @@ +NAME scOnInt +ROWS + N obj + G row1 + G row2 + G row3 + G scrow1 + G scrow2 + G scrow3 +COLUMNS + INT1 'MARKER' 'INTORG' + x1 obj 24.000 scrow1 15.000 + x2 obj 12.000 scrow2 20.000 + x3 obj 16.000 scrow3 5.000 + INT1END 'MARKER' 'INTEND' + y1 obj 4.000 row1 1.000 + y1 row2 1.000 row3 2.000 + y1 scrow1 -1.000 + y2 obj 2.000 row1 3.000 + y2 row3 2.000 scrow2 -1.000 + y3 obj 3.000 row2 2.000 + y3 scrow3 -1.000 +RHS + RHS row1 15.000 + RHS row2 10.000 + RHS row3 20.000 + RHS scrow1 0.000 + RHS scrow2 0.000 + RHS scrow3 0.000 +BOUNDS + UP intbnd x3 7.0 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/share2qp.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/share2qp.mps new file mode 100644 index 000000000..b2e2dbed1 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/share2qp.mps @@ -0,0 +1,527 @@ +NAME SHARE2B +ROWS + N 000000 + L 000004 + L 000005 + L 000006 + L 000007 + L 000008 + L 000009 + L 000010 + L 000011 + L 000012 + E 000013 + L 000014 + L 000015 + L 000016 + L 000017 + L 000018 + L 000019 + L 000020 + L 000021 + L 000022 + E 000023 + L 000024 + L 000025 + L 000026 + L 000027 + L 000028 + L 000029 + L 000030 + L 000031 + L 000032 + E 000033 + L 000034 + L 000035 + L 000036 + L 000037 + L 000038 + L 000039 + L 000040 + L 000041 + L 000042 + E 000043 + L 000044 + L 000045 + L 000046 + L 000047 + L 000048 + L 000049 + L 000050 + L 000051 + L 000052 + E 000053 + L 000054 + L 000055 + L 000056 + L 000057 + L 000058 + L 000059 + L 000060 + L 000061 + L 000062 + E 000063 + L 000064 + L 000065 + L 000066 + L 000067 + L 000068 + L 000069 + L 000070 + L 000071 + L 000072 + L 000073 + L 000074 + L 000075 + L 000076 + L 000077 + L 000078 + L 000079 + L 000080 + L 000081 + E 000082 + E 000083 + E 000084 + E 000085 + E 000086 + E 000087 + L 000088 + L 000089 + L 000090 + L 000091 + L 000092 + L 000093 + L 000094 + L 000095 + L 000096 + L 000097 + L 000098 + E 000099 +COLUMNS + 010101 000004 65. 000005 1. + 010101 000006 -1. 000007 -1. + 010101 000008 -97.4 000009 -99.9 + 010101 000010 -83.7 000011 -85. + 010101 000013 1. + 010102 000004 5.5 000005 .68 + 010102 000006 -.96 000007 -1. + 010102 000008 -84. 000009 -88.1 + 010102 000010 -79.4 000011 -83.2 + 010102 000013 1. 000064 1. + 010103 000004 .8 000007 -.78 + 010103 000008 -87.9 000009 -82.9 + 010103 000010 -74.6 000011 -80.6 + 010103 000013 1. 000065 1. + 010104 000004 4.5 000005 .27 + 010104 000006 -.97 000007 -1. + 010104 000008 -97.9 000009 -100.3 + 010104 000010 -95. 000011 -98. + 010104 000013 1. 000088 1. + 010105 000004 1.5 000005 .12 + 010105 000006 -.36 000007 -.95 + 010105 000008 -60.6 000009 -76.3 + 010105 000010 -68.6 000011 -76.8 + 010105 000013 1. 000066 1. + 010106 000000 .03 000004 6. + 010106 000005 .19 000006 -.35 + 010106 000007 -.89 000008 -94.8 + 010106 000009 -96.6 000010 -83.8 + 010106 000011 -86.8 000013 1. + 010106 000066 1.1 + 010107 000000 .06 000004 3.3 + 010107 000005 .07 000006 -.29 + 010107 000007 -.97 000008 -97.9 + 010107 000009 -100.3 000010 -95. + 010107 000011 -98. 000013 1. + 010107 000066 1.2 + 010108 000004 5.8 000005 .5 + 010108 000006 -.62 000007 -.98 + 010108 000008 -96.5 000009 -98.1 + 010108 000010 -80.8 000011 -81.5 + 010108 000013 1. 000067 1. + 010120 000000 .09 000008 -2.1 + 010120 000009 -.7 000010 -2.3 + 010120 000011 -1. 000012 1. + 010131 000000 -3.8 000004 -11. + 010131 000005 -.5 000006 .5 + 010131 000007 .9 000008 100. + 010131 000009 100. 000010 90. + 010131 000011 90. 000012 -3. + 010131 000013 -1. 000082 1. + 010132 000000 -3.7 000082 -1. + 010132 000083 1. + 010133 000000 -3.5 000082 -1. + 010133 000084 1. + 010201 000014 65. 000015 1. + 010201 000016 -1. 000017 -1. + 010201 000018 -97.4 000019 -99.9 + 010201 000020 -83.7 000021 -85. + 010201 000023 1. + 010202 000014 5.5 000015 .57 + 010202 000016 -1. 000017 -1. + 010202 000018 -84. 000019 -88.1 + 010202 000020 -79.4 000021 -83.2 + 010202 000023 1. 000064 1. + 010203 000014 .8 000016 -.01 + 010203 000017 -.98 000018 -87.9 + 010203 000019 -82.9 000020 -74.6 + 010203 000021 -80.6 000023 1. + 010203 000065 1. + 010204 000014 1.5 000015 .12 + 010204 000016 -.36 000017 -.95 + 010204 000018 -60.6 000019 -76.3 + 010204 000020 -68.6 000021 -76.8 + 010204 000023 1. 000066 1. + 010205 000000 .1 000014 2.7 + 010205 000015 .13 000016 -.28 + 010205 000017 -.79 000018 -77.9 + 010205 000019 -81.4 000020 -70.6 + 010205 000021 -74. 000023 1. + 010205 000069 1. + 010206 000014 5.8 000015 .46 + 010206 000016 -.67 000017 -1. + 010206 000018 -96.5 000019 -98.1 + 010206 000020 -80.8 000021 -81.5 + 010206 000023 1. 000067 1. + 010220 000000 .09 000018 -3.5 + 010220 000019 -1.9 000020 -3.4 + 010220 000021 -1.8 000022 1. + 010231 000000 -3. 000014 -11. + 010231 000015 -.5 000016 .5 + 010231 000017 .9 000018 89. + 010231 000019 89. 000020 82. + 010231 000021 82. 000022 -3. + 010231 000023 -1. 000085 1. + 010231 000089 -.25 + 010301 000024 70. 000025 1. + 010301 000026 -1. 000027 -1. + 010301 000028 -97.8 000029 -102.3 + 010301 000030 -94.8 000031 -99.8 + 010301 000033 1. + 010302 000024 9.5 000025 .7 + 010302 000026 -.83 000027 -1. + 010302 000028 -89.1 000029 -92. + 010302 000030 -77.4 000031 -80.1 + 010302 000033 1. 000068 1. + 010303 000024 2.7 000025 .13 + 010303 000026 -.28 000027 -.79 + 010303 000028 -77.9 000029 -81.4 + 010303 000030 -70.6 000031 -74. + 010303 000033 1. 000069 1. + 010304 000024 10.8 000025 .97 + 010304 000026 -1. 000027 -1. + 010304 000028 -84.6 000029 -89.7 + 010304 000030 -83.6 000031 -89.4 + 010304 000033 1. 000070 1. + 010305 000024 1.5 000025 .12 + 010305 000026 -.36 000027 -.95 + 010305 000028 -60.6 000029 -76.3 + 010305 000030 -68.6 000031 -76.8 + 010305 000033 1. 000071 1. + 010306 000000 .06 000024 6.2 + 010306 000025 .19 000026 -.35 + 010306 000027 -.89 000028 -95.9 + 010306 000029 -97.6 000030 -85.4 + 010306 000031 -87.8 000033 1. + 010306 000071 1.2 + 010307 000000 .03 000024 6. + 010307 000025 .19 000026 -.35 + 010307 000027 -.89 000028 -94.8 + 010307 000029 -96.6 000030 -83.8 + 010307 000031 -86.8 000033 1. + 010307 000071 1.1 + 010308 000000 .1 000024 4.5 + 010308 000025 .27 000026 -.97 + 010308 000027 -1. 000028 -97.9 + 010308 000029 -100.3 000030 -95. + 010308 000031 -98. 000033 1. + 010308 000088 1. + 010309 000000 .1 000024 5.5 + 010309 000025 .68 000026 -.96 + 010309 000027 -1. 000028 -84. + 010309 000029 -88.1 000030 -79.4 + 010309 000031 -83.2 000033 1. + 010309 000064 1. + 010310 000000 .1 000024 6.5 + 010310 000025 .48 000026 -.56 + 010310 000027 -.97 000028 -96.5 + 010310 000029 -97.1 000030 -82.2 + 010310 000031 -83.3 000033 1. + 010310 000067 1. + 010320 000000 .09 000028 -1.9 + 010320 000029 -.9 000030 -2.4 + 010320 000031 -.9 000032 1. + 010331 000000 -3.7 000024 -11. + 010331 000025 -.5 000026 .5 + 010331 000027 .9 000028 100. + 010331 000029 100. 000030 90. + 010331 000031 90. 000033 -1. + 010331 000032 -3. 000083 1. + 010333 000000 -3.5 000083 -1. + 010333 000084 1. + 010401 000034 70. 000035 1. + 010401 000036 -1. 000037 -1. + 010401 000038 -97.8 000039 -102.3 + 010401 000040 -94.8 000041 -99.8 + 010401 000043 1. + 010402 000034 9.5 000035 .68 + 010402 000036 -.9 000037 -1. + 010402 000038 -89.1 000039 -92. + 010402 000040 -77.4 000041 -80.1 + 010402 000043 1. 000068 1. + 010403 000034 2.7 000035 .09 + 010403 000036 -.37 000037 -.92 + 010403 000038 -77.9 000039 -81.4 + 010403 000040 -70.6 000041 -74. + 010403 000043 1. 000069 1. + 010404 000034 10.8 000035 .93 + 010404 000036 -1. 000037 -1. + 010404 000038 -84.6 000039 -89.7 + 010404 000040 -83.6 000041 -89.4 + 010404 000043 1. 000070 1. + 010405 000000 .03 000034 6.2 + 010405 000035 .15 000036 -.45 + 010405 000037 -.98 000038 -95.9 + 010405 000039 -97.6 000040 -85.4 + 010405 000041 -87.8 000043 1. + 010405 000071 1.1 + 010406 000000 .1 000034 6.5 + 010406 000035 .45 000036 -.63 + 010406 000037 -1. 000038 -96.5 + 010406 000039 -97.1 000040 -82.2 + 010406 000041 -83.3 000043 1. + 010406 000067 1. + 010407 000034 1.5 000035 .12 + 010407 000036 -.36 000037 -.95 + 010407 000038 -60.6 000039 -76.3 + 010407 000040 -68.6 000041 -76.8 + 010407 000043 1. 000071 1. + 010408 000000 .1 000034 5.5 + 010408 000035 .68 000036 -.96 + 010408 000037 -1. 000038 -84. + 010408 000039 -88.1 000040 -79.4 + 010408 000041 -83.2 000043 1. + 010408 000064 1. + 010420 000000 .09 000038 -3.9 + 010420 000039 -1.4 000040 -3.5 + 010420 000041 -1.3 000042 1. + 010431 000000 -2.9 000034 -11. + 010431 000035 -.5 000036 .5 + 010431 000037 .9 000038 89. + 010431 000039 89. 000040 82. + 010431 000041 82. 000042 -3. + 010431 000043 -1. 000086 1. + 010432 000000 -2.8 000085 1. + 010432 000086 -1. 000089 .75 + 010501 000044 56. 000045 1. + 010501 000046 -1. 000047 -1. + 010501 000048 -99.4 000049 -103. + 010501 000050 -96.7 000051 -101.2 + 010501 000053 1. + 010502 000044 1.8 000047 -1. + 010502 000048 -87.9 000049 -91.6 + 010502 000050 -88.1 000051 -92. + 010502 000053 1. 000072 1. + 010503 000044 1.4 000047 -.54 + 010503 000048 -86.2 000049 -90. + 010503 000050 -88. 000051 -91.3 + 010503 000053 1. 000073 1. + 010504 000044 10.6 000045 .68 + 010504 000046 -.87 000047 -1. + 010504 000048 -99.9 000049 -100.4 + 010504 000050 -80.8 000051 -81.7 + 010504 000053 1. 000074 1. + 010505 000044 2.5 000047 -.65 + 010505 000048 -89.6 000049 -91.7 + 010505 000050 -79.3 000051 -82.1 + 010505 000053 1. 000075 1. + 010506 000044 11.5 000045 .77 + 010506 000046 -.93 000047 -1. + 010506 000048 -79.5 000049 -85.1 + 010506 000050 -80.2 000051 -86.2 + 010506 000053 1. 000076 1. + 010507 000044 1.5 000045 .12 + 010507 000046 -.36 000047 -.95 + 010507 000048 -60.6 000049 -76.3 + 010507 000050 -68.6 000051 -76.8 + 010507 000053 1. 000077 1. + 010508 000000 .03 000044 4.2 + 010508 000045 .08 000046 -.3 + 010508 000047 -.91 000048 -99.5 + 010508 000049 -99.9 000050 -87.6 + 010508 000051 -89. 000053 1. + 010508 000077 1.1 + 010509 000000 .06 000044 4.3 + 010509 000045 .07 000046 -.27 + 010509 000047 -.9 000048 -101.4 + 010509 000049 -101.5 000050 -89. + 010509 000051 -90.2 000053 1. + 010509 000077 1.2 + 010520 000000 .09 000048 -1.6 + 010520 000049 -.8 000050 -2. + 010520 000051 -.8 000052 1. + 010531 000000 -3.5 000044 -10. + 010531 000045 -.5 000046 .5 + 010531 000047 .9 000048 101. + 010531 000049 101. 000050 91. + 010531 000051 91. 000052 -3. + 010531 000053 -1. 000084 1. + 010601 000054 56. 000055 1. + 010601 000056 -1. 000057 -1. + 010601 000058 -97.7 000059 -100.6 + 010601 000060 -94.5 000061 -98.5 + 010601 000063 1. + 010602 000054 10.6 000055 .39 + 010602 000056 -1. 000057 -1. + 010602 000058 -98.2 000059 -98. + 010602 000060 -78.6 000061 -79. + 010602 000063 1. 000074 1. + 010603 000054 2.5 000057 -.87 + 010603 000058 -87.9 000059 -89.3 + 010603 000060 -77.1 000061 -79.4 + 010603 000063 1. 000075 1. + 010604 000054 3.6 000055 .27 + 010604 000056 -1. 000057 -1. + 010604 000058 -78.8 000059 -82.7 + 010604 000060 -75.1 000061 -80.5 + 010604 000063 1. 000078 1. + 010605 000054 11.5 000055 .73 + 010605 000056 -.98 000057 -1. + 010605 000058 -78.2 000059 -82.7 + 010605 000060 -78. 000061 -83.5 + 010605 000063 1. 000076 1. + 010606 000054 2. 000056 -.38 + 010606 000057 -1. 000058 -66.9 + 010606 000059 -71.4 000060 -67.6 + 010606 000061 -73.8 000063 1. + 010606 000079 1. + 010607 000054 14.6 000055 1. + 010607 000056 -1. 000057 -1. + 010607 000058 -74.7 000059 -79.8 + 010607 000060 -77.3 000061 -83. + 010607 000063 1. 000080 1. + 010608 000054 6.1 000055 .33 + 010608 000056 -.65 000057 -1. + 010608 000058 -70.7 000059 -75.9 + 010608 000060 -69.6 000061 -75.3 + 010608 000063 1. 000081 1. + 010609 000000 .03 000054 4.2 + 010609 000055 .04 000056 -.36 + 010609 000057 -.98 000058 -97.8 + 010609 000059 -97.5 000060 -85.4 + 010609 000061 -86.3 000063 1. + 010609 000077 1.1 + 010620 000000 .09 000058 -3.3 + 010620 000059 -1.6 000060 -4.2 + 010620 000061 -1.7 000062 1. + 010631 000000 -2.7 000054 -11. + 010631 000055 -.5 000056 .5 + 010631 000057 .9 000058 89. + 010631 000059 89. 000060 82. + 010631 000061 82. 000062 -3. + 010631 000063 -1. 000087 1. + 010632 000000 -2.7 000085 1. + 010632 000087 -1. 000089 .75 + 010633 000000 -2.7 000086 1. + 010633 000087 -1. + 010701 000090 56. 000091 1. + 010701 000092 -1. 000093 -1. + 010701 000094 -97.7 000095 -100.6 + 010701 000096 -94.5 000097 -98.5 + 010701 000099 1. + 010702 000074 1. 000090 10.6 + 010702 000091 .39 000092 -1. + 010702 000093 -1. 000094 -98.2 + 010702 000095 -98. 000096 -78.6 + 010702 000097 -79. 000099 1. + 010703 000075 1. 000090 2.5 + 010703 000093 -.87 000094 -87.9 + 010703 000095 -89.3 000096 -77.1 + 010703 000097 -79.4 000099 1. + 010704 000078 1. 000090 3.6 + 010704 000091 .27 000092 -1. + 010704 000093 -1. 000094 -78.8 + 010704 000095 -82.7 000096 -75.1 + 010704 000097 -80.5 000099 1. + 010705 000076 1. 000090 11.5 + 010705 000091 .73 000092 -.98 + 010705 000093 -1. 000094 -78.2 + 010705 000095 -82.7 000096 -78. + 010705 000097 -83.5 000099 1. + 010706 000079 1. 000090 2. + 010706 000092 -.38 000093 -1. + 010706 000094 -66.9 000095 -71.4 + 010706 000096 -67.6 000097 -73.8 + 010706 000099 1. + 010707 000080 1. 000090 14.6 + 010707 000091 1. 000092 -1. + 010707 000093 -1. 000094 -74.7 + 010707 000095 -79.8 000096 -77.3 + 010707 000097 -83. 000099 1. + 010708 000000 .03 000077 1.1 + 010708 000090 4.2 000091 .04 + 010708 000092 -.36 000093 -.98 + 010708 000094 -97.8 000095 -97.5 + 010708 000096 -85.4 000097 -86.3 + 010708 000099 1. + 010709 000000 .07 000077 1.2 + 010709 000090 4.3 000091 .07 + 010709 000092 -.27 000093 -.9 + 010709 000094 -101.4 000095 -101.5 + 010709 000096 -89. 000097 -90.2 + 010709 000099 1. + 010720 000000 .09 000094 -3.3 + 010720 000095 -1.6 000096 -4.2 + 010720 000097 -1.7 000098 1. + 010731 000000 -2.7 000090 -10. + 010731 000091 -.5 000092 .5 + 010731 000093 .9 000094 90. + 010731 000095 90. 000096 83. + 010731 000097 83. 000098 -3. + 010731 000099 -1. +RHS + RHS 000064 7. 000065 7. + RHS 000066 7. 000067 21. + RHS 000068 3. 000069 3. + RHS 000070 3. 000071 7. + RHS 000072 1.5 000073 1.5 + RHS 000074 10. 000075 10. + RHS 000076 8.5 000077 13. + RHS 000078 1.5 000079 1.5 + RHS 000080 1. 000081 1. + RHS 000082 15. 000083 15. + RHS 000084 20. 000085 20. + RHS 000086 15. 000088 1. +ENDATA +NAME SHARE2B +*QSECTION +QUADOBJ + 010101 010101 0.8849E+01 + 010101 010105 0.6270E+01 + 010101 010408 0.5408E+01 + 010101 010509 0.6205E+01 + 010105 010101 0.6270E+01 + 010105 010105 0.2591E+02 + 010105 010408 0.7510E+01 + 010105 010509 0.1418E+02 + 010105 010704 0.5939E+01 + 010105 010705 0.5249E+01 + 010408 010101 0.5408E+01 + 010408 010105 0.7510E+01 + 010408 010408 0.1270E+02 + 010408 010509 0.7433E+01 + 010509 010101 0.6205E+01 + 010509 010105 0.1418E+02 + 010509 010408 0.7433E+01 + 010509 010509 0.2358E+02 + 010509 010704 0.5230E+01 + 010509 010705 0.4622E+01 + 010704 010105 0.5939E+01 + 010704 010509 0.5230E+01 + 010704 010704 0.7815E+01 + 010704 010705 0.4934E+01 + 010705 010105 0.5249E+01 + 010705 010509 0.4622E+01 + 010705 010704 0.4934E+01 + 010705 010705 0.6105E+01 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/spec_sections.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/spec_sections.mps new file mode 100644 index 000000000..0cec9ab2d --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/spec_sections.mps @@ -0,0 +1,63 @@ +*NAME Test +*Author H.I. Gassmann +*Date 08/Oct/2013 +*Purpose This file tests the processing of the +* CoinMpsIO subsystem --- it does not make +* much sense as an optimization problem +* but is useful to illustrate a fully loaded MPS file +NAME +ROWS + N obj + L c1 +COLUMNS + x0 obj 1 c1 1 + INT 'MARKER' 'INTORG' + x1 obj -1 c1 10 + INT 'MARKER' 'INTEND' +* S1 NAME1 'MARKER' 'SOSORG' + x2 obj -9 c1 5 + x3 obj -6 c1 8 +* NAME1 'MARKER' 'SOSEND' + x4 obj 1 c1 1 + x5 obj -6 c1 8 + x6 obj 1 c1 1 + x7 obj 1 c1 1 + x8 obj -6 c1 8 + x9 obj -2 c1 1 + x10 obj -3 c1 1 + x11 obj -1 c1 -1 + x12 obj -2 c1 1 + x13 obj -3 c1 1 + x14 obj -9 c1 5 +RHS + rhs c1 10000 +RANGES + range c1 2000 +BOUNDS + LI BOUND x1 2 + UI BOUND x1 3 +SOS + S1 set1 + x2 + x3 + S2 set2 + x4 20 + x5 40 +QUADOBJ + x6 x6 1 + x6 x7 2 + x7 x7 7 +CSECTION cone1 0.0 QUAD + x8 + x9 + x10 +CSECTION cone2 0.0 RQUAD + x11 + x12 + x13 + x14 +*BASIS +* XU x6 c1 +* BS x7 +ENDATA + diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp3.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp3.mps new file mode 100644 index 000000000..c743f2471 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp3.mps @@ -0,0 +1,26 @@ +* +* small test problem derived from P0548 +* +NAME tp3 +ROWS + N R1001 + L R1006 + G ROWA + G ROWB +COLUMNS + SET00001 'MARKER' 'INTORG' + C1045 R1001 155.000000 + C1045 R1006 161.000000 + C1045 ROWA 1.000000 + C1047 R1006 -120.000000 + C1050 R1006 -68.000000 + C1050 ROWB 1.000000 +RHS + RHS R1006 -5.000000 + RHS ROWA 0.627000 + RHS ROWB 0.380000 +BOUNDS + BV ONE C1045 1.000000 + BV ONE C1047 1.000000 + BV ONE C1050 1.000000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp4.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp4.mps new file mode 100644 index 000000000..64757f213 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp4.mps @@ -0,0 +1,40 @@ +* +* small test problem - tp4.mps +* +* knapsack problem where lifted greedy cover cut +* moves lp objective function value +* +NAME tp4 +ROWS + N obj + L knap + G r1 + G r2 + G r3 +COLUMNS + SET00001 'MARKER' 'INTORG' + x1 knap 8.000000 + x1 r1 1.000000 + x2 knap 7.000000 + x2 r2 1.000000 + x3 knap 6.000000 + x3 r3 1.000000 + x4 knap 4.000000 + x4 obj -1.000000 + x5 knap 6.000000 + x5 obj -100.000000 + x6 knap 13.500000 + x6 obj -100.000000 +RHS + RHS knap 22.000000 + RHS r1 0.001000 + RHS r2 0.001000 + RHS r3 0.001000 +BOUNDS + BV ONE x1 1.000000 + BV ONE x2 1.000000 + BV ONE x3 1.000000 + BV ONE x4 1.000000 + BV ONE x5 1.000000 + BV ONE x6 1.000000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp5.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp5.mps new file mode 100644 index 000000000..d0b55ea80 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/tp5.mps @@ -0,0 +1,40 @@ +* +* small test problem - tp5.mps +* +* knapsack problem where the greedy cover cut +* approach leads to a violated min. cover +* +NAME tp5 +ROWS + N obj + L knap + G r1 + G r2 + G r3 +COLUMNS + SET00001 'MARKER' 'INTORG' + x1 knap 8.000000 + x1 r1 1.000000 + x2 knap 7.000000 + x2 r2 1.000000 + x3 knap 6.000000 + x3 r3 1.000000 + x4 knap 4.000000 + x4 obj -1.000000 + x5 knap 6.000000 + x5 obj -100.000000 + x6 knap 13.500000 + x6 obj -10.000000 +RHS + RHS knap 22.000000 + RHS r1 0.900000 + RHS r2 0.900000 + RHS r3 0.900000 +BOUNDS + BV ONE x1 1.000000 + BV ONE x2 1.000000 + BV ONE x3 1.000000 + BV ONE x4 1.000000 + BV ONE x5 1.000000 + BV ONE x6 1.000000 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.block b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.block new file mode 100644 index 000000000..2ff17e13c --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.block @@ -0,0 +1,605 @@ +0 0 +1 1 +2 2 +3 3 +4 4 +0 21 +0 22 +0 23 +0 24 +0 25 +0 26 +0 27 +0 28 +0 29 +0 30 +0 31 +0 32 +0 33 +0 34 +0 35 +0 36 +0 37 +0 38 +0 39 +0 40 +0 41 +0 42 +0 43 +0 44 +0 45 +1 46 +1 47 +1 48 +1 49 +1 50 +1 51 +1 52 +1 53 +1 54 +0 55 +1 56 +1 57 +1 58 +1 59 +1 60 +1 61 +1 62 +1 63 +1 64 +1 65 +0 66 +1 67 +1 68 +1 69 +1 70 +1 71 +1 72 +1 73 +1 74 +1 75 +1 76 +0 77 +1 78 +1 79 +1 80 +1 81 +1 82 +1 83 +1 84 +1 85 +1 86 +1 87 +0 88 +1 89 +1 90 +1 91 +1 92 +1 93 +1 94 +1 95 +1 96 +1 97 +1 98 +0 99 +1 100 +1 101 +1 102 +1 103 +1 104 +1 105 +1 106 +1 107 +1 108 +1 109 +0 110 +1 111 +1 112 +1 113 +1 114 +1 115 +1 116 +1 117 +1 118 +1 119 +1 120 +0 121 +1 122 +1 123 +1 124 +1 125 +1 126 +1 127 +1 128 +1 129 +1 130 +1 131 +0 132 +0 133 +1 134 +1 135 +1 136 +1 137 +1 138 +1 139 +1 140 +1 141 +1 142 +1 143 +0 144 +1 145 +1 146 +1 147 +1 148 +1 149 +1 150 +1 151 +1 152 +1 153 +1 154 +0 155 +1 156 +1 157 +1 158 +1 159 +1 160 +1 161 +1 162 +1 163 +1 164 +1 165 +0 166 +1 167 +1 168 +1 169 +1 170 +1 171 +1 172 +1 173 +1 174 +1 175 +1 176 +0 177 +1 178 +2 179 +2 180 +2 181 +2 182 +2 183 +2 184 +2 185 +2 186 +2 187 +0 188 +2 189 +2 190 +2 191 +2 192 +2 193 +2 194 +2 195 +2 196 +2 197 +2 198 +0 199 +2 200 +2 201 +2 202 +2 203 +2 204 +2 205 +2 206 +2 207 +2 208 +2 209 +0 210 +2 211 +2 212 +2 213 +2 214 +2 215 +2 216 +2 217 +2 218 +2 219 +2 220 +0 221 +2 222 +2 223 +2 224 +2 225 +2 226 +2 227 +2 228 +2 229 +2 230 +2 231 +0 232 +2 233 +2 234 +2 235 +2 236 +2 237 +2 238 +2 239 +2 240 +2 241 +2 242 +0 243 +0 244 +2 245 +2 246 +2 247 +2 248 +2 249 +2 250 +2 251 +2 252 +2 253 +2 254 +0 255 +2 256 +2 257 +2 258 +2 259 +2 260 +2 261 +2 262 +2 263 +2 264 +2 265 +0 266 +2 267 +2 268 +2 269 +2 270 +2 271 +2 272 +2 273 +2 274 +2 275 +2 276 +0 277 +2 278 +2 279 +2 280 +2 281 +2 282 +2 283 +2 284 +2 285 +2 286 +2 287 +0 288 +2 289 +2 290 +2 291 +2 292 +2 293 +2 294 +2 295 +2 296 +2 297 +2 298 +0 299 +2 300 +2 301 +2 302 +2 303 +2 304 +2 305 +2 306 +2 307 +2 308 +2 309 +0 310 +2 311 +3 312 +3 313 +3 314 +3 315 +3 316 +3 317 +3 318 +3 319 +3 320 +0 321 +3 322 +3 323 +3 324 +3 325 +3 326 +3 327 +3 328 +3 329 +3 330 +3 331 +0 332 +3 333 +3 334 +3 335 +3 336 +3 337 +3 338 +3 339 +3 340 +3 341 +3 342 +0 343 +3 344 +3 345 +3 346 +3 347 +3 348 +3 349 +3 350 +3 351 +3 352 +3 353 +0 354 +0 355 +3 356 +3 357 +3 358 +3 359 +3 360 +3 361 +3 362 +3 363 +3 364 +3 365 +0 366 +3 367 +3 368 +3 369 +3 370 +3 371 +3 372 +3 373 +3 374 +3 375 +3 376 +0 377 +3 378 +3 379 +3 380 +3 381 +3 382 +3 383 +3 384 +3 385 +3 386 +3 387 +0 388 +3 389 +3 390 +3 391 +3 392 +3 393 +3 394 +3 395 +3 396 +3 397 +3 398 +0 399 +3 400 +3 401 +3 402 +3 403 +3 404 +3 405 +3 406 +3 407 +3 408 +3 409 +0 410 +3 411 +3 412 +3 413 +3 414 +3 415 +3 416 +3 417 +3 418 +3 419 +3 420 +0 421 +3 422 +3 423 +3 424 +3 425 +3 426 +3 427 +3 428 +3 429 +3 430 +3 431 +0 432 +3 433 +3 434 +3 435 +3 436 +3 437 +3 438 +3 439 +3 440 +3 441 +3 442 +0 443 +3 444 +4 445 +4 446 +4 447 +4 448 +4 449 +4 450 +4 451 +4 452 +4 453 +0 454 +4 455 +4 456 +4 457 +4 458 +4 459 +4 460 +4 461 +4 462 +4 463 +4 464 +0 465 +0 466 +4 467 +4 468 +4 469 +4 470 +4 471 +4 472 +4 473 +4 474 +4 475 +4 476 +0 477 +4 478 +4 479 +4 480 +4 481 +4 482 +4 483 +4 484 +4 485 +4 486 +4 487 +0 488 +4 489 +4 490 +4 491 +4 492 +4 493 +4 494 +4 495 +4 496 +4 497 +4 498 +0 499 +4 500 +4 501 +4 502 +4 503 +4 504 +4 505 +4 506 +4 507 +4 508 +4 509 +0 510 +4 511 +4 512 +4 513 +4 514 +4 515 +4 516 +4 517 +4 518 +4 519 +4 520 +0 521 +4 522 +4 523 +4 524 +4 525 +4 526 +4 527 +4 528 +4 529 +4 530 +4 531 +0 532 +4 533 +4 534 +4 535 +4 536 +4 537 +4 538 +4 539 +4 540 +4 541 +4 542 +0 543 +4 544 +4 545 +4 546 +4 547 +4 548 +4 549 +4 550 +4 551 +4 552 +4 553 +0 554 +4 555 +4 556 +4 557 +4 558 +4 559 +4 560 +4 561 +4 562 +4 563 +4 564 +0 565 +4 566 +4 567 +4 568 +4 569 +4 570 +4 571 +4 572 +4 573 +4 574 +4 575 +0 576 +0 577 +4 578 +0 579 +0 580 +0 581 +0 582 +0 583 +0 584 +0 585 +0 586 +0 587 +0 588 +0 589 +0 590 +0 591 +0 592 +0 593 +0 594 +0 595 +0 596 +0 597 +0 598 +0 599 +0 600 +0 601 +0 602 +0 603 +0 604 +0 605 +0 606 +0 607 +0 608 +0 609 +0 610 +0 611 +0 612 +0 613 +0 614 +0 615 +0 616 +0 617 +0 618 +0 619 +0 620 diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.mps b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.mps new file mode 100644 index 000000000..b28e11249 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/Sample/wedding_16.mps @@ -0,0 +1,3297 @@ +* ENCODING=ISO-8859-1 +NAME wedding_main.lp +ROWS + N OBJ + L Maximum_table_size_0 + L Maximum_table_size_1 + L Maximum_table_size_2 + L Maximum_table_size_3 + L Maximum_table_size_4 + E Must_seat_A + E Must_seat_B + E Must_seat_C + E Must_seat_D + E Must_seat_E + E Must_seat_F + E Must_seat_G + E Must_seat_H + E Must_seat_I + E Must_seat_J + E Must_seat_K + E Must_seat_L + E Must_seat_M + E Must_seat_N + E Must_seat_O + E Must_seat_P + G _C1 + G _C10 + G _C100 + G _C101 + G _C102 + G _C103 + G _C104 + G _C105 + G _C106 + G _C107 + G _C108 + G _C109 + G _C11 + G _C110 + G _C111 + G _C112 + G _C113 + G _C114 + G _C115 + G _C116 + G _C117 + G _C118 + G _C119 + G _C12 + G _C120 + G _C121 + G _C122 + G _C123 + G _C124 + G _C125 + G _C126 + G _C127 + G _C128 + G _C129 + G _C13 + G _C130 + G _C131 + G _C132 + G _C133 + G _C134 + G _C135 + G _C136 + G _C137 + G _C138 + G _C139 + G _C14 + G _C140 + G _C141 + G _C142 + G _C143 + G _C144 + G _C145 + G _C146 + G _C147 + G _C148 + G _C149 + G _C15 + G _C150 + G _C151 + G _C152 + G _C153 + G _C154 + G _C155 + G _C156 + G _C157 + G _C158 + G _C159 + G _C16 + G _C160 + G _C161 + G _C162 + G _C163 + G _C164 + G _C165 + G _C166 + G _C167 + G _C168 + G _C169 + G _C17 + G _C170 + G _C171 + G _C172 + G _C173 + G _C174 + G _C175 + G _C176 + G _C177 + G _C178 + G _C179 + G _C18 + G _C180 + G _C181 + G _C182 + G _C183 + G _C184 + G _C185 + G _C186 + G _C187 + G _C188 + G _C189 + G _C19 + G _C190 + G _C191 + G _C192 + G _C193 + G _C194 + G _C195 + G _C196 + G _C197 + G _C198 + G _C199 + G _C2 + G _C20 + G _C200 + G _C201 + G _C202 + G _C203 + G _C204 + G _C205 + G _C206 + G _C207 + G _C208 + G _C209 + G _C21 + G _C210 + G _C211 + G _C212 + G _C213 + G _C214 + G _C215 + G _C216 + G _C217 + G _C218 + G _C219 + G _C22 + G _C220 + G _C221 + G _C222 + G _C223 + G _C224 + G _C225 + G _C226 + G _C227 + G _C228 + G _C229 + G _C23 + G _C230 + G _C231 + G _C232 + G _C233 + G _C234 + G _C235 + G _C236 + G _C237 + G _C238 + G _C239 + G _C24 + G _C240 + G _C241 + G _C242 + G _C243 + G _C244 + G _C245 + G _C246 + G _C247 + G _C248 + G _C249 + G _C25 + G _C250 + G _C251 + G _C252 + G _C253 + G _C254 + G _C255 + G _C256 + G _C257 + G _C258 + G _C259 + G _C26 + G _C260 + G _C261 + G _C262 + G _C263 + G _C264 + G _C265 + G _C266 + G _C267 + G _C268 + G _C269 + G _C27 + G _C270 + G _C271 + G _C272 + G _C273 + G _C274 + G _C275 + G _C276 + G _C277 + G _C278 + G _C279 + G _C28 + G _C280 + G _C281 + G _C282 + G _C283 + G _C284 + G _C285 + G _C286 + G _C287 + G _C288 + G _C289 + G _C29 + G _C290 + G _C291 + G _C292 + G _C293 + G _C294 + G _C295 + G _C296 + G _C297 + G _C298 + G _C299 + G _C3 + G _C30 + G _C300 + G _C301 + G _C302 + G _C303 + G _C304 + G _C305 + G _C306 + G _C307 + G _C308 + G _C309 + G _C31 + G _C310 + G _C311 + G _C312 + G _C313 + G _C314 + G _C315 + G _C316 + G _C317 + G _C318 + G _C319 + G _C32 + G _C320 + G _C321 + G _C322 + G _C323 + G _C324 + G _C325 + G _C326 + G _C327 + G _C328 + G _C329 + G _C33 + G _C330 + G _C331 + G _C332 + G _C333 + G _C334 + G _C335 + G _C336 + G _C337 + G _C338 + G _C339 + G _C34 + G _C340 + G _C341 + G _C342 + G _C343 + G _C344 + G _C345 + G _C346 + G _C347 + G _C348 + G _C349 + G _C35 + G _C350 + G _C351 + G _C352 + G _C353 + G _C354 + G _C355 + G _C356 + G _C357 + G _C358 + G _C359 + G _C36 + G _C360 + G _C361 + G _C362 + G _C363 + G _C364 + G _C365 + G _C366 + G _C367 + G _C368 + G _C369 + G _C37 + G _C370 + G _C371 + G _C372 + G _C373 + G _C374 + G _C375 + G _C376 + G _C377 + G _C378 + G _C379 + G _C38 + G _C380 + G _C381 + G _C382 + G _C383 + G _C384 + G _C385 + G _C386 + G _C387 + G _C388 + G _C389 + G _C39 + G _C390 + G _C391 + G _C392 + G _C393 + G _C394 + G _C395 + G _C396 + G _C397 + G _C398 + G _C399 + G _C4 + G _C40 + G _C400 + G _C401 + G _C402 + G _C403 + G _C404 + G _C405 + G _C406 + G _C407 + G _C408 + G _C409 + G _C41 + G _C410 + G _C411 + G _C412 + G _C413 + G _C414 + G _C415 + G _C416 + G _C417 + G _C418 + G _C419 + G _C42 + G _C420 + G _C421 + G _C422 + G _C423 + G _C424 + G _C425 + G _C426 + G _C427 + G _C428 + G _C429 + G _C43 + G _C430 + G _C431 + G _C432 + G _C433 + G _C434 + G _C435 + G _C436 + G _C437 + G _C438 + G _C439 + G _C44 + G _C440 + G _C441 + G _C442 + G _C443 + G _C444 + G _C445 + G _C446 + G _C447 + G _C448 + G _C449 + G _C45 + G _C450 + G _C451 + G _C452 + G _C453 + G _C454 + G _C455 + G _C456 + G _C457 + G _C458 + G _C459 + G _C46 + G _C460 + G _C461 + G _C462 + G _C463 + G _C464 + G _C465 + G _C466 + G _C467 + G _C468 + G _C469 + G _C47 + G _C470 + G _C471 + G _C472 + G _C473 + G _C474 + G _C475 + G _C476 + G _C477 + G _C478 + G _C479 + G _C48 + G _C480 + G _C481 + G _C482 + G _C483 + G _C484 + G _C485 + G _C486 + G _C487 + G _C488 + G _C489 + G _C49 + G _C490 + G _C491 + G _C492 + G _C493 + G _C494 + G _C495 + G _C496 + G _C497 + G _C498 + G _C499 + G _C5 + G _C50 + G _C500 + G _C501 + G _C502 + G _C503 + G _C504 + G _C505 + G _C506 + G _C507 + G _C508 + G _C509 + G _C51 + G _C510 + G _C511 + G _C512 + G _C513 + G _C514 + G _C515 + G _C516 + G _C517 + G _C518 + G _C519 + G _C52 + G _C520 + G _C521 + G _C522 + G _C523 + G _C524 + G _C525 + G _C526 + G _C527 + G _C528 + G _C529 + G _C53 + G _C530 + G _C531 + G _C532 + G _C533 + G _C534 + G _C535 + G _C536 + G _C537 + G _C538 + G _C539 + G _C54 + G _C540 + G _C541 + G _C542 + G _C543 + G _C544 + G _C545 + G _C546 + G _C547 + G _C548 + G _C549 + G _C55 + G _C550 + G _C551 + G _C552 + G _C553 + G _C554 + G _C555 + G _C556 + G _C557 + G _C558 + G _C559 + G _C56 + G _C560 + G _C561 + G _C562 + G _C563 + G _C564 + G _C565 + G _C566 + G _C567 + G _C568 + G _C569 + G _C57 + G _C570 + G _C571 + G _C572 + G _C573 + G _C574 + G _C575 + G _C576 + G _C577 + G _C578 + G _C579 + G _C58 + G _C580 + G _C581 + G _C582 + G _C583 + G _C584 + G _C585 + G _C586 + G _C587 + G _C588 + G _C589 + G _C59 + G _C590 + G _C591 + G _C592 + G _C593 + G _C594 + G _C595 + G _C596 + G _C597 + G _C598 + G _C599 + G _C6 + G _C60 + G _C600 + G _C61 + G _C62 + G _C63 + G _C64 + G _C65 + G _C66 + G _C67 + G _C68 + G _C69 + G _C7 + G _C70 + G _C71 + G _C72 + G _C73 + G _C74 + G _C75 + G _C76 + G _C77 + G _C78 + G _C79 + G _C8 + G _C80 + G _C81 + G _C82 + G _C83 + G _C84 + G _C85 + G _C86 + G _C87 + G _C88 + G _C89 + G _C9 + G _C90 + G _C91 + G _C92 + G _C93 + G _C94 + G _C95 + G _C96 + G _C97 + G _C98 + G _C99 +COLUMNS + table_happiness_0 OBJ 1 + table_happiness_0 _C1 1 + table_happiness_0 _C10 1 + table_happiness_0 _C100 1 + table_happiness_0 _C101 1 + table_happiness_0 _C102 1 + table_happiness_0 _C103 1 + table_happiness_0 _C104 1 + table_happiness_0 _C105 1 + table_happiness_0 _C106 1 + table_happiness_0 _C107 1 + table_happiness_0 _C108 1 + table_happiness_0 _C109 1 + table_happiness_0 _C11 1 + table_happiness_0 _C110 1 + table_happiness_0 _C111 1 + table_happiness_0 _C112 1 + table_happiness_0 _C113 1 + table_happiness_0 _C114 1 + table_happiness_0 _C115 1 + table_happiness_0 _C116 1 + table_happiness_0 _C117 1 + table_happiness_0 _C118 1 + table_happiness_0 _C119 1 + table_happiness_0 _C12 1 + table_happiness_0 _C120 1 + table_happiness_0 _C13 1 + table_happiness_0 _C14 1 + table_happiness_0 _C15 1 + table_happiness_0 _C16 1 + table_happiness_0 _C17 1 + table_happiness_0 _C18 1 + table_happiness_0 _C19 1 + table_happiness_0 _C2 1 + table_happiness_0 _C20 1 + table_happiness_0 _C21 1 + table_happiness_0 _C22 1 + table_happiness_0 _C23 1 + table_happiness_0 _C24 1 + table_happiness_0 _C25 1 + table_happiness_0 _C26 1 + table_happiness_0 _C27 1 + table_happiness_0 _C28 1 + table_happiness_0 _C29 1 + table_happiness_0 _C3 1 + table_happiness_0 _C30 1 + table_happiness_0 _C31 1 + table_happiness_0 _C32 1 + table_happiness_0 _C33 1 + table_happiness_0 _C34 1 + table_happiness_0 _C35 1 + table_happiness_0 _C36 1 + table_happiness_0 _C37 1 + table_happiness_0 _C38 1 + table_happiness_0 _C39 1 + table_happiness_0 _C4 1 + table_happiness_0 _C40 1 + table_happiness_0 _C41 1 + table_happiness_0 _C42 1 + table_happiness_0 _C43 1 + table_happiness_0 _C44 1 + table_happiness_0 _C45 1 + table_happiness_0 _C46 1 + table_happiness_0 _C47 1 + table_happiness_0 _C48 1 + table_happiness_0 _C49 1 + table_happiness_0 _C5 1 + table_happiness_0 _C50 1 + table_happiness_0 _C51 1 + table_happiness_0 _C52 1 + table_happiness_0 _C53 1 + table_happiness_0 _C54 1 + table_happiness_0 _C55 1 + table_happiness_0 _C56 1 + table_happiness_0 _C57 1 + table_happiness_0 _C58 1 + table_happiness_0 _C59 1 + table_happiness_0 _C6 1 + table_happiness_0 _C60 1 + table_happiness_0 _C61 1 + table_happiness_0 _C62 1 + table_happiness_0 _C63 1 + table_happiness_0 _C64 1 + table_happiness_0 _C65 1 + table_happiness_0 _C66 1 + table_happiness_0 _C67 1 + table_happiness_0 _C68 1 + table_happiness_0 _C69 1 + table_happiness_0 _C7 1 + table_happiness_0 _C70 1 + table_happiness_0 _C71 1 + table_happiness_0 _C72 1 + table_happiness_0 _C73 1 + table_happiness_0 _C74 1 + table_happiness_0 _C75 1 + table_happiness_0 _C76 1 + table_happiness_0 _C77 1 + table_happiness_0 _C78 1 + table_happiness_0 _C79 1 + table_happiness_0 _C8 1 + table_happiness_0 _C80 1 + table_happiness_0 _C81 1 + table_happiness_0 _C82 1 + table_happiness_0 _C83 1 + table_happiness_0 _C84 1 + table_happiness_0 _C85 1 + table_happiness_0 _C86 1 + table_happiness_0 _C87 1 + table_happiness_0 _C88 1 + table_happiness_0 _C89 1 + table_happiness_0 _C9 1 + table_happiness_0 _C90 1 + table_happiness_0 _C91 1 + table_happiness_0 _C92 1 + table_happiness_0 _C93 1 + table_happiness_0 _C94 1 + table_happiness_0 _C95 1 + table_happiness_0 _C96 1 + table_happiness_0 _C97 1 + table_happiness_0 _C98 1 + table_happiness_0 _C99 1 + table_happiness_1 OBJ 1 + table_happiness_1 _C121 1 + table_happiness_1 _C122 1 + table_happiness_1 _C123 1 + table_happiness_1 _C124 1 + table_happiness_1 _C125 1 + table_happiness_1 _C126 1 + table_happiness_1 _C127 1 + table_happiness_1 _C128 1 + table_happiness_1 _C129 1 + table_happiness_1 _C130 1 + table_happiness_1 _C131 1 + table_happiness_1 _C132 1 + table_happiness_1 _C133 1 + table_happiness_1 _C134 1 + table_happiness_1 _C135 1 + table_happiness_1 _C136 1 + table_happiness_1 _C137 1 + table_happiness_1 _C138 1 + table_happiness_1 _C139 1 + table_happiness_1 _C140 1 + table_happiness_1 _C141 1 + table_happiness_1 _C142 1 + table_happiness_1 _C143 1 + table_happiness_1 _C144 1 + table_happiness_1 _C145 1 + table_happiness_1 _C146 1 + table_happiness_1 _C147 1 + table_happiness_1 _C148 1 + table_happiness_1 _C149 1 + table_happiness_1 _C150 1 + table_happiness_1 _C151 1 + table_happiness_1 _C152 1 + table_happiness_1 _C153 1 + table_happiness_1 _C154 1 + table_happiness_1 _C155 1 + table_happiness_1 _C156 1 + table_happiness_1 _C157 1 + table_happiness_1 _C158 1 + table_happiness_1 _C159 1 + table_happiness_1 _C160 1 + table_happiness_1 _C161 1 + table_happiness_1 _C162 1 + table_happiness_1 _C163 1 + table_happiness_1 _C164 1 + table_happiness_1 _C165 1 + table_happiness_1 _C166 1 + table_happiness_1 _C167 1 + table_happiness_1 _C168 1 + table_happiness_1 _C169 1 + table_happiness_1 _C170 1 + table_happiness_1 _C171 1 + table_happiness_1 _C172 1 + table_happiness_1 _C173 1 + table_happiness_1 _C174 1 + table_happiness_1 _C175 1 + table_happiness_1 _C176 1 + table_happiness_1 _C177 1 + table_happiness_1 _C178 1 + table_happiness_1 _C179 1 + table_happiness_1 _C180 1 + table_happiness_1 _C181 1 + table_happiness_1 _C182 1 + table_happiness_1 _C183 1 + table_happiness_1 _C184 1 + table_happiness_1 _C185 1 + table_happiness_1 _C186 1 + table_happiness_1 _C187 1 + table_happiness_1 _C188 1 + table_happiness_1 _C189 1 + table_happiness_1 _C190 1 + table_happiness_1 _C191 1 + table_happiness_1 _C192 1 + table_happiness_1 _C193 1 + table_happiness_1 _C194 1 + table_happiness_1 _C195 1 + table_happiness_1 _C196 1 + table_happiness_1 _C197 1 + table_happiness_1 _C198 1 + table_happiness_1 _C199 1 + table_happiness_1 _C200 1 + table_happiness_1 _C201 1 + table_happiness_1 _C202 1 + table_happiness_1 _C203 1 + table_happiness_1 _C204 1 + table_happiness_1 _C205 1 + table_happiness_1 _C206 1 + table_happiness_1 _C207 1 + table_happiness_1 _C208 1 + table_happiness_1 _C209 1 + table_happiness_1 _C210 1 + table_happiness_1 _C211 1 + table_happiness_1 _C212 1 + table_happiness_1 _C213 1 + table_happiness_1 _C214 1 + table_happiness_1 _C215 1 + table_happiness_1 _C216 1 + table_happiness_1 _C217 1 + table_happiness_1 _C218 1 + table_happiness_1 _C219 1 + table_happiness_1 _C220 1 + table_happiness_1 _C221 1 + table_happiness_1 _C222 1 + table_happiness_1 _C223 1 + table_happiness_1 _C224 1 + table_happiness_1 _C225 1 + table_happiness_1 _C226 1 + table_happiness_1 _C227 1 + table_happiness_1 _C228 1 + table_happiness_1 _C229 1 + table_happiness_1 _C230 1 + table_happiness_1 _C231 1 + table_happiness_1 _C232 1 + table_happiness_1 _C233 1 + table_happiness_1 _C234 1 + table_happiness_1 _C235 1 + table_happiness_1 _C236 1 + table_happiness_1 _C237 1 + table_happiness_1 _C238 1 + table_happiness_1 _C239 1 + table_happiness_1 _C240 1 + table_happiness_2 OBJ 1 + table_happiness_2 _C241 1 + table_happiness_2 _C242 1 + table_happiness_2 _C243 1 + table_happiness_2 _C244 1 + table_happiness_2 _C245 1 + table_happiness_2 _C246 1 + table_happiness_2 _C247 1 + table_happiness_2 _C248 1 + table_happiness_2 _C249 1 + table_happiness_2 _C250 1 + table_happiness_2 _C251 1 + table_happiness_2 _C252 1 + table_happiness_2 _C253 1 + table_happiness_2 _C254 1 + table_happiness_2 _C255 1 + table_happiness_2 _C256 1 + table_happiness_2 _C257 1 + table_happiness_2 _C258 1 + table_happiness_2 _C259 1 + table_happiness_2 _C260 1 + table_happiness_2 _C261 1 + table_happiness_2 _C262 1 + table_happiness_2 _C263 1 + table_happiness_2 _C264 1 + table_happiness_2 _C265 1 + table_happiness_2 _C266 1 + table_happiness_2 _C267 1 + table_happiness_2 _C268 1 + table_happiness_2 _C269 1 + table_happiness_2 _C270 1 + table_happiness_2 _C271 1 + table_happiness_2 _C272 1 + table_happiness_2 _C273 1 + table_happiness_2 _C274 1 + table_happiness_2 _C275 1 + table_happiness_2 _C276 1 + table_happiness_2 _C277 1 + table_happiness_2 _C278 1 + table_happiness_2 _C279 1 + table_happiness_2 _C280 1 + table_happiness_2 _C281 1 + table_happiness_2 _C282 1 + table_happiness_2 _C283 1 + table_happiness_2 _C284 1 + table_happiness_2 _C285 1 + table_happiness_2 _C286 1 + table_happiness_2 _C287 1 + table_happiness_2 _C288 1 + table_happiness_2 _C289 1 + table_happiness_2 _C290 1 + table_happiness_2 _C291 1 + table_happiness_2 _C292 1 + table_happiness_2 _C293 1 + table_happiness_2 _C294 1 + table_happiness_2 _C295 1 + table_happiness_2 _C296 1 + table_happiness_2 _C297 1 + table_happiness_2 _C298 1 + table_happiness_2 _C299 1 + table_happiness_2 _C300 1 + table_happiness_2 _C301 1 + table_happiness_2 _C302 1 + table_happiness_2 _C303 1 + table_happiness_2 _C304 1 + table_happiness_2 _C305 1 + table_happiness_2 _C306 1 + table_happiness_2 _C307 1 + table_happiness_2 _C308 1 + table_happiness_2 _C309 1 + table_happiness_2 _C310 1 + table_happiness_2 _C311 1 + table_happiness_2 _C312 1 + table_happiness_2 _C313 1 + table_happiness_2 _C314 1 + table_happiness_2 _C315 1 + table_happiness_2 _C316 1 + table_happiness_2 _C317 1 + table_happiness_2 _C318 1 + table_happiness_2 _C319 1 + table_happiness_2 _C320 1 + table_happiness_2 _C321 1 + table_happiness_2 _C322 1 + table_happiness_2 _C323 1 + table_happiness_2 _C324 1 + table_happiness_2 _C325 1 + table_happiness_2 _C326 1 + table_happiness_2 _C327 1 + table_happiness_2 _C328 1 + table_happiness_2 _C329 1 + table_happiness_2 _C330 1 + table_happiness_2 _C331 1 + table_happiness_2 _C332 1 + table_happiness_2 _C333 1 + table_happiness_2 _C334 1 + table_happiness_2 _C335 1 + table_happiness_2 _C336 1 + table_happiness_2 _C337 1 + table_happiness_2 _C338 1 + table_happiness_2 _C339 1 + table_happiness_2 _C340 1 + table_happiness_2 _C341 1 + table_happiness_2 _C342 1 + table_happiness_2 _C343 1 + table_happiness_2 _C344 1 + table_happiness_2 _C345 1 + table_happiness_2 _C346 1 + table_happiness_2 _C347 1 + table_happiness_2 _C348 1 + table_happiness_2 _C349 1 + table_happiness_2 _C350 1 + table_happiness_2 _C351 1 + table_happiness_2 _C352 1 + table_happiness_2 _C353 1 + table_happiness_2 _C354 1 + table_happiness_2 _C355 1 + table_happiness_2 _C356 1 + table_happiness_2 _C357 1 + table_happiness_2 _C358 1 + table_happiness_2 _C359 1 + table_happiness_2 _C360 1 + table_happiness_3 OBJ 1 + table_happiness_3 _C361 1 + table_happiness_3 _C362 1 + table_happiness_3 _C363 1 + table_happiness_3 _C364 1 + table_happiness_3 _C365 1 + table_happiness_3 _C366 1 + table_happiness_3 _C367 1 + table_happiness_3 _C368 1 + table_happiness_3 _C369 1 + table_happiness_3 _C370 1 + table_happiness_3 _C371 1 + table_happiness_3 _C372 1 + table_happiness_3 _C373 1 + table_happiness_3 _C374 1 + table_happiness_3 _C375 1 + table_happiness_3 _C376 1 + table_happiness_3 _C377 1 + table_happiness_3 _C378 1 + table_happiness_3 _C379 1 + table_happiness_3 _C380 1 + table_happiness_3 _C381 1 + table_happiness_3 _C382 1 + table_happiness_3 _C383 1 + table_happiness_3 _C384 1 + table_happiness_3 _C385 1 + table_happiness_3 _C386 1 + table_happiness_3 _C387 1 + table_happiness_3 _C388 1 + table_happiness_3 _C389 1 + table_happiness_3 _C390 1 + table_happiness_3 _C391 1 + table_happiness_3 _C392 1 + table_happiness_3 _C393 1 + table_happiness_3 _C394 1 + table_happiness_3 _C395 1 + table_happiness_3 _C396 1 + table_happiness_3 _C397 1 + table_happiness_3 _C398 1 + table_happiness_3 _C399 1 + table_happiness_3 _C400 1 + table_happiness_3 _C401 1 + table_happiness_3 _C402 1 + table_happiness_3 _C403 1 + table_happiness_3 _C404 1 + table_happiness_3 _C405 1 + table_happiness_3 _C406 1 + table_happiness_3 _C407 1 + table_happiness_3 _C408 1 + table_happiness_3 _C409 1 + table_happiness_3 _C410 1 + table_happiness_3 _C411 1 + table_happiness_3 _C412 1 + table_happiness_3 _C413 1 + table_happiness_3 _C414 1 + table_happiness_3 _C415 1 + table_happiness_3 _C416 1 + table_happiness_3 _C417 1 + table_happiness_3 _C418 1 + table_happiness_3 _C419 1 + table_happiness_3 _C420 1 + table_happiness_3 _C421 1 + table_happiness_3 _C422 1 + table_happiness_3 _C423 1 + table_happiness_3 _C424 1 + table_happiness_3 _C425 1 + table_happiness_3 _C426 1 + table_happiness_3 _C427 1 + table_happiness_3 _C428 1 + table_happiness_3 _C429 1 + table_happiness_3 _C430 1 + table_happiness_3 _C431 1 + table_happiness_3 _C432 1 + table_happiness_3 _C433 1 + table_happiness_3 _C434 1 + table_happiness_3 _C435 1 + table_happiness_3 _C436 1 + table_happiness_3 _C437 1 + table_happiness_3 _C438 1 + table_happiness_3 _C439 1 + table_happiness_3 _C440 1 + table_happiness_3 _C441 1 + table_happiness_3 _C442 1 + table_happiness_3 _C443 1 + table_happiness_3 _C444 1 + table_happiness_3 _C445 1 + table_happiness_3 _C446 1 + table_happiness_3 _C447 1 + table_happiness_3 _C448 1 + table_happiness_3 _C449 1 + table_happiness_3 _C450 1 + table_happiness_3 _C451 1 + table_happiness_3 _C452 1 + table_happiness_3 _C453 1 + table_happiness_3 _C454 1 + table_happiness_3 _C455 1 + table_happiness_3 _C456 1 + table_happiness_3 _C457 1 + table_happiness_3 _C458 1 + table_happiness_3 _C459 1 + table_happiness_3 _C460 1 + table_happiness_3 _C461 1 + table_happiness_3 _C462 1 + table_happiness_3 _C463 1 + table_happiness_3 _C464 1 + table_happiness_3 _C465 1 + table_happiness_3 _C466 1 + table_happiness_3 _C467 1 + table_happiness_3 _C468 1 + table_happiness_3 _C469 1 + table_happiness_3 _C470 1 + table_happiness_3 _C471 1 + table_happiness_3 _C472 1 + table_happiness_3 _C473 1 + table_happiness_3 _C474 1 + table_happiness_3 _C475 1 + table_happiness_3 _C476 1 + table_happiness_3 _C477 1 + table_happiness_3 _C478 1 + table_happiness_3 _C479 1 + table_happiness_3 _C480 1 + table_happiness_4 OBJ 1 + table_happiness_4 _C481 1 + table_happiness_4 _C482 1 + table_happiness_4 _C483 1 + table_happiness_4 _C484 1 + table_happiness_4 _C485 1 + table_happiness_4 _C486 1 + table_happiness_4 _C487 1 + table_happiness_4 _C488 1 + table_happiness_4 _C489 1 + table_happiness_4 _C490 1 + table_happiness_4 _C491 1 + table_happiness_4 _C492 1 + table_happiness_4 _C493 1 + table_happiness_4 _C494 1 + table_happiness_4 _C495 1 + table_happiness_4 _C496 1 + table_happiness_4 _C497 1 + table_happiness_4 _C498 1 + table_happiness_4 _C499 1 + table_happiness_4 _C500 1 + table_happiness_4 _C501 1 + table_happiness_4 _C502 1 + table_happiness_4 _C503 1 + table_happiness_4 _C504 1 + table_happiness_4 _C505 1 + table_happiness_4 _C506 1 + table_happiness_4 _C507 1 + table_happiness_4 _C508 1 + table_happiness_4 _C509 1 + table_happiness_4 _C510 1 + table_happiness_4 _C511 1 + table_happiness_4 _C512 1 + table_happiness_4 _C513 1 + table_happiness_4 _C514 1 + table_happiness_4 _C515 1 + table_happiness_4 _C516 1 + table_happiness_4 _C517 1 + table_happiness_4 _C518 1 + table_happiness_4 _C519 1 + table_happiness_4 _C520 1 + table_happiness_4 _C521 1 + table_happiness_4 _C522 1 + table_happiness_4 _C523 1 + table_happiness_4 _C524 1 + table_happiness_4 _C525 1 + table_happiness_4 _C526 1 + table_happiness_4 _C527 1 + table_happiness_4 _C528 1 + table_happiness_4 _C529 1 + table_happiness_4 _C530 1 + table_happiness_4 _C531 1 + table_happiness_4 _C532 1 + table_happiness_4 _C533 1 + table_happiness_4 _C534 1 + table_happiness_4 _C535 1 + table_happiness_4 _C536 1 + table_happiness_4 _C537 1 + table_happiness_4 _C538 1 + table_happiness_4 _C539 1 + table_happiness_4 _C540 1 + table_happiness_4 _C541 1 + table_happiness_4 _C542 1 + table_happiness_4 _C543 1 + table_happiness_4 _C544 1 + table_happiness_4 _C545 1 + table_happiness_4 _C546 1 + table_happiness_4 _C547 1 + table_happiness_4 _C548 1 + table_happiness_4 _C549 1 + table_happiness_4 _C550 1 + table_happiness_4 _C551 1 + table_happiness_4 _C552 1 + table_happiness_4 _C553 1 + table_happiness_4 _C554 1 + table_happiness_4 _C555 1 + table_happiness_4 _C556 1 + table_happiness_4 _C557 1 + table_happiness_4 _C558 1 + table_happiness_4 _C559 1 + table_happiness_4 _C560 1 + table_happiness_4 _C561 1 + table_happiness_4 _C562 1 + table_happiness_4 _C563 1 + table_happiness_4 _C564 1 + table_happiness_4 _C565 1 + table_happiness_4 _C566 1 + table_happiness_4 _C567 1 + table_happiness_4 _C568 1 + table_happiness_4 _C569 1 + table_happiness_4 _C570 1 + table_happiness_4 _C571 1 + table_happiness_4 _C572 1 + table_happiness_4 _C573 1 + table_happiness_4 _C574 1 + table_happiness_4 _C575 1 + table_happiness_4 _C576 1 + table_happiness_4 _C577 1 + table_happiness_4 _C578 1 + table_happiness_4 _C579 1 + table_happiness_4 _C580 1 + table_happiness_4 _C581 1 + table_happiness_4 _C582 1 + table_happiness_4 _C583 1 + table_happiness_4 _C584 1 + table_happiness_4 _C585 1 + table_happiness_4 _C586 1 + table_happiness_4 _C587 1 + table_happiness_4 _C588 1 + table_happiness_4 _C589 1 + table_happiness_4 _C590 1 + table_happiness_4 _C591 1 + table_happiness_4 _C592 1 + table_happiness_4 _C593 1 + table_happiness_4 _C594 1 + table_happiness_4 _C595 1 + table_happiness_4 _C596 1 + table_happiness_4 _C597 1 + table_happiness_4 _C598 1 + table_happiness_4 _C599 1 + table_happiness_4 _C600 1 + MARK0000 'MARKER' 'INTORG' + possible_seatings_('A',_0) Maximum_table_size_0 1 + possible_seatings_('A',_0) Must_seat_A 1 + possible_seatings_('A',_0) _C1 -1 + possible_seatings_('A',_0) _C10 -10 + possible_seatings_('A',_0) _C11 -11 + possible_seatings_('A',_0) _C12 -12 + possible_seatings_('A',_0) _C13 -13 + possible_seatings_('A',_0) _C14 -14 + possible_seatings_('A',_0) _C15 -15 + possible_seatings_('A',_0) _C2 -2 + possible_seatings_('A',_0) _C3 -3 + possible_seatings_('A',_0) _C4 -4 + possible_seatings_('A',_0) _C5 -5 + possible_seatings_('A',_0) _C6 -6 + possible_seatings_('A',_0) _C7 -7 + possible_seatings_('A',_0) _C8 -8 + possible_seatings_('A',_0) _C9 -9 + possible_seatings_('B',_0) Maximum_table_size_0 1 + possible_seatings_('B',_0) Must_seat_B 1 + possible_seatings_('B',_0) _C1 -1 + possible_seatings_('B',_0) _C16 -1 + possible_seatings_('B',_0) _C17 -2 + possible_seatings_('B',_0) _C18 -3 + possible_seatings_('B',_0) _C19 -4 + possible_seatings_('B',_0) _C20 -5 + possible_seatings_('B',_0) _C21 -6 + possible_seatings_('B',_0) _C22 -7 + possible_seatings_('B',_0) _C23 -8 + possible_seatings_('B',_0) _C24 -9 + possible_seatings_('B',_0) _C25 -10 + possible_seatings_('B',_0) _C26 -11 + possible_seatings_('B',_0) _C27 -12 + possible_seatings_('B',_0) _C28 -13 + possible_seatings_('B',_0) _C29 -14 + possible_seatings_('C',_0) Maximum_table_size_0 1 + possible_seatings_('C',_0) Must_seat_C 1 + possible_seatings_('C',_0) _C16 -1 + possible_seatings_('C',_0) _C2 -2 + possible_seatings_('C',_0) _C30 -1 + possible_seatings_('C',_0) _C31 -2 + possible_seatings_('C',_0) _C32 -3 + possible_seatings_('C',_0) _C33 -4 + possible_seatings_('C',_0) _C34 -5 + possible_seatings_('C',_0) _C35 -6 + possible_seatings_('C',_0) _C36 -7 + possible_seatings_('C',_0) _C37 -8 + possible_seatings_('C',_0) _C38 -9 + possible_seatings_('C',_0) _C39 -10 + possible_seatings_('C',_0) _C40 -11 + possible_seatings_('C',_0) _C41 -12 + possible_seatings_('C',_0) _C42 -13 + possible_seatings_('D',_0) Maximum_table_size_0 1 + possible_seatings_('D',_0) Must_seat_D 1 + possible_seatings_('D',_0) _C17 -2 + possible_seatings_('D',_0) _C3 -3 + possible_seatings_('D',_0) _C30 -1 + possible_seatings_('D',_0) _C43 -1 + possible_seatings_('D',_0) _C44 -2 + possible_seatings_('D',_0) _C45 -3 + possible_seatings_('D',_0) _C46 -4 + possible_seatings_('D',_0) _C47 -5 + possible_seatings_('D',_0) _C48 -6 + possible_seatings_('D',_0) _C49 -7 + possible_seatings_('D',_0) _C50 -8 + possible_seatings_('D',_0) _C51 -9 + possible_seatings_('D',_0) _C52 -10 + possible_seatings_('D',_0) _C53 -11 + possible_seatings_('D',_0) _C54 -12 + possible_seatings_('E',_0) Maximum_table_size_0 1 + possible_seatings_('E',_0) Must_seat_E 1 + possible_seatings_('E',_0) _C18 -3 + possible_seatings_('E',_0) _C31 -2 + possible_seatings_('E',_0) _C4 -4 + possible_seatings_('E',_0) _C43 -1 + possible_seatings_('E',_0) _C55 -1 + possible_seatings_('E',_0) _C56 -2 + possible_seatings_('E',_0) _C57 -3 + possible_seatings_('E',_0) _C58 -4 + possible_seatings_('E',_0) _C59 -5 + possible_seatings_('E',_0) _C60 -6 + possible_seatings_('E',_0) _C61 -7 + possible_seatings_('E',_0) _C62 -8 + possible_seatings_('E',_0) _C63 -9 + possible_seatings_('E',_0) _C64 -10 + possible_seatings_('E',_0) _C65 -11 + possible_seatings_('F',_0) Maximum_table_size_0 1 + possible_seatings_('F',_0) Must_seat_F 1 + possible_seatings_('F',_0) _C19 -4 + possible_seatings_('F',_0) _C32 -3 + possible_seatings_('F',_0) _C44 -2 + possible_seatings_('F',_0) _C5 -5 + possible_seatings_('F',_0) _C55 -1 + possible_seatings_('F',_0) _C66 -1 + possible_seatings_('F',_0) _C67 -2 + possible_seatings_('F',_0) _C68 -3 + possible_seatings_('F',_0) _C69 -4 + possible_seatings_('F',_0) _C70 -5 + possible_seatings_('F',_0) _C71 -6 + possible_seatings_('F',_0) _C72 -7 + possible_seatings_('F',_0) _C73 -8 + possible_seatings_('F',_0) _C74 -9 + possible_seatings_('F',_0) _C75 -10 + possible_seatings_('G',_0) Maximum_table_size_0 1 + possible_seatings_('G',_0) Must_seat_G 1 + possible_seatings_('G',_0) _C20 -5 + possible_seatings_('G',_0) _C33 -4 + possible_seatings_('G',_0) _C45 -3 + possible_seatings_('G',_0) _C56 -2 + possible_seatings_('G',_0) _C6 -6 + possible_seatings_('G',_0) _C66 -1 + possible_seatings_('G',_0) _C76 -1 + possible_seatings_('G',_0) _C77 -2 + possible_seatings_('G',_0) _C78 -3 + possible_seatings_('G',_0) _C79 -4 + possible_seatings_('G',_0) _C80 -5 + possible_seatings_('G',_0) _C81 -6 + possible_seatings_('G',_0) _C82 -7 + possible_seatings_('G',_0) _C83 -8 + possible_seatings_('G',_0) _C84 -9 + possible_seatings_('H',_0) Maximum_table_size_0 1 + possible_seatings_('H',_0) Must_seat_H 1 + possible_seatings_('H',_0) _C21 -6 + possible_seatings_('H',_0) _C34 -5 + possible_seatings_('H',_0) _C46 -4 + possible_seatings_('H',_0) _C57 -3 + possible_seatings_('H',_0) _C67 -2 + possible_seatings_('H',_0) _C7 -7 + possible_seatings_('H',_0) _C76 -1 + possible_seatings_('H',_0) _C85 -1 + possible_seatings_('H',_0) _C86 -2 + possible_seatings_('H',_0) _C87 -3 + possible_seatings_('H',_0) _C88 -4 + possible_seatings_('H',_0) _C89 -5 + possible_seatings_('H',_0) _C90 -6 + possible_seatings_('H',_0) _C91 -7 + possible_seatings_('H',_0) _C92 -8 + possible_seatings_('I',_0) Maximum_table_size_0 1 + possible_seatings_('I',_0) Must_seat_I 1 + possible_seatings_('I',_0) _C22 -7 + possible_seatings_('I',_0) _C35 -6 + possible_seatings_('I',_0) _C47 -5 + possible_seatings_('I',_0) _C58 -4 + possible_seatings_('I',_0) _C68 -3 + possible_seatings_('I',_0) _C77 -2 + possible_seatings_('I',_0) _C8 -8 + possible_seatings_('I',_0) _C85 -1 + possible_seatings_('I',_0) _C93 -1 + possible_seatings_('I',_0) _C94 -2 + possible_seatings_('I',_0) _C95 -3 + possible_seatings_('I',_0) _C96 -4 + possible_seatings_('I',_0) _C97 -5 + possible_seatings_('I',_0) _C98 -6 + possible_seatings_('I',_0) _C99 -7 + possible_seatings_('J',_0) Maximum_table_size_0 1 + possible_seatings_('J',_0) Must_seat_J 1 + possible_seatings_('J',_0) _C100 -1 + possible_seatings_('J',_0) _C101 -2 + possible_seatings_('J',_0) _C102 -3 + possible_seatings_('J',_0) _C103 -4 + possible_seatings_('J',_0) _C104 -5 + possible_seatings_('J',_0) _C105 -6 + possible_seatings_('J',_0) _C23 -8 + possible_seatings_('J',_0) _C36 -7 + possible_seatings_('J',_0) _C48 -6 + possible_seatings_('J',_0) _C59 -5 + possible_seatings_('J',_0) _C69 -4 + possible_seatings_('J',_0) _C78 -3 + possible_seatings_('J',_0) _C86 -2 + possible_seatings_('J',_0) _C9 -9 + possible_seatings_('J',_0) _C93 -1 + possible_seatings_('K',_0) Maximum_table_size_0 1 + possible_seatings_('K',_0) Must_seat_K 1 + possible_seatings_('K',_0) _C10 -10 + possible_seatings_('K',_0) _C100 -1 + possible_seatings_('K',_0) _C106 -1 + possible_seatings_('K',_0) _C107 -2 + possible_seatings_('K',_0) _C108 -3 + possible_seatings_('K',_0) _C109 -4 + possible_seatings_('K',_0) _C110 -5 + possible_seatings_('K',_0) _C24 -9 + possible_seatings_('K',_0) _C37 -8 + possible_seatings_('K',_0) _C49 -7 + possible_seatings_('K',_0) _C60 -6 + possible_seatings_('K',_0) _C70 -5 + possible_seatings_('K',_0) _C79 -4 + possible_seatings_('K',_0) _C87 -3 + possible_seatings_('K',_0) _C94 -2 + possible_seatings_('L',_0) Maximum_table_size_0 1 + possible_seatings_('L',_0) Must_seat_L 1 + possible_seatings_('L',_0) _C101 -2 + possible_seatings_('L',_0) _C106 -1 + possible_seatings_('L',_0) _C11 -11 + possible_seatings_('L',_0) _C111 -1 + possible_seatings_('L',_0) _C112 -2 + possible_seatings_('L',_0) _C113 -3 + possible_seatings_('L',_0) _C114 -4 + possible_seatings_('L',_0) _C25 -10 + possible_seatings_('L',_0) _C38 -9 + possible_seatings_('L',_0) _C50 -8 + possible_seatings_('L',_0) _C61 -7 + possible_seatings_('L',_0) _C71 -6 + possible_seatings_('L',_0) _C80 -5 + possible_seatings_('L',_0) _C88 -4 + possible_seatings_('L',_0) _C95 -3 + possible_seatings_('M',_0) Maximum_table_size_0 1 + possible_seatings_('M',_0) Must_seat_M 1 + possible_seatings_('M',_0) _C102 -3 + possible_seatings_('M',_0) _C107 -2 + possible_seatings_('M',_0) _C111 -1 + possible_seatings_('M',_0) _C115 -1 + possible_seatings_('M',_0) _C116 -2 + possible_seatings_('M',_0) _C117 -3 + possible_seatings_('M',_0) _C12 -12 + possible_seatings_('M',_0) _C26 -11 + possible_seatings_('M',_0) _C39 -10 + possible_seatings_('M',_0) _C51 -9 + possible_seatings_('M',_0) _C62 -8 + possible_seatings_('M',_0) _C72 -7 + possible_seatings_('M',_0) _C81 -6 + possible_seatings_('M',_0) _C89 -5 + possible_seatings_('M',_0) _C96 -4 + possible_seatings_('N',_0) Maximum_table_size_0 1 + possible_seatings_('N',_0) Must_seat_N 1 + possible_seatings_('N',_0) _C103 -4 + possible_seatings_('N',_0) _C108 -3 + possible_seatings_('N',_0) _C112 -2 + possible_seatings_('N',_0) _C115 -1 + possible_seatings_('N',_0) _C118 -1 + possible_seatings_('N',_0) _C119 -2 + possible_seatings_('N',_0) _C13 -13 + possible_seatings_('N',_0) _C27 -12 + possible_seatings_('N',_0) _C40 -11 + possible_seatings_('N',_0) _C52 -10 + possible_seatings_('N',_0) _C63 -9 + possible_seatings_('N',_0) _C73 -8 + possible_seatings_('N',_0) _C82 -7 + possible_seatings_('N',_0) _C90 -6 + possible_seatings_('N',_0) _C97 -5 + possible_seatings_('O',_0) Maximum_table_size_0 1 + possible_seatings_('O',_0) Must_seat_O 1 + possible_seatings_('O',_0) _C104 -5 + possible_seatings_('O',_0) _C109 -4 + possible_seatings_('O',_0) _C113 -3 + possible_seatings_('O',_0) _C116 -2 + possible_seatings_('O',_0) _C118 -1 + possible_seatings_('O',_0) _C120 -1 + possible_seatings_('O',_0) _C14 -14 + possible_seatings_('O',_0) _C28 -13 + possible_seatings_('O',_0) _C41 -12 + possible_seatings_('O',_0) _C53 -11 + possible_seatings_('O',_0) _C64 -10 + possible_seatings_('O',_0) _C74 -9 + possible_seatings_('O',_0) _C83 -8 + possible_seatings_('O',_0) _C91 -7 + possible_seatings_('O',_0) _C98 -6 + possible_seatings_('P',_0) Maximum_table_size_0 1 + possible_seatings_('P',_0) Must_seat_P 1 + possible_seatings_('P',_0) _C105 -6 + possible_seatings_('P',_0) _C110 -5 + possible_seatings_('P',_0) _C114 -4 + possible_seatings_('P',_0) _C117 -3 + possible_seatings_('P',_0) _C119 -2 + possible_seatings_('P',_0) _C120 -1 + possible_seatings_('P',_0) _C15 -15 + possible_seatings_('P',_0) _C29 -14 + possible_seatings_('P',_0) _C42 -13 + possible_seatings_('P',_0) _C54 -12 + possible_seatings_('P',_0) _C65 -11 + possible_seatings_('P',_0) _C75 -10 + possible_seatings_('P',_0) _C84 -9 + possible_seatings_('P',_0) _C92 -8 + possible_seatings_('P',_0) _C99 -7 + possible_seatings_('A',_1) Maximum_table_size_1 1 + possible_seatings_('A',_1) Must_seat_A 1 + possible_seatings_('A',_1) _C121 -1 + possible_seatings_('A',_1) _C122 -2 + possible_seatings_('A',_1) _C123 -3 + possible_seatings_('A',_1) _C124 -4 + possible_seatings_('A',_1) _C125 -5 + possible_seatings_('A',_1) _C126 -6 + possible_seatings_('A',_1) _C127 -7 + possible_seatings_('A',_1) _C128 -8 + possible_seatings_('A',_1) _C129 -9 + possible_seatings_('A',_1) _C130 -10 + possible_seatings_('A',_1) _C131 -11 + possible_seatings_('A',_1) _C132 -12 + possible_seatings_('A',_1) _C133 -13 + possible_seatings_('A',_1) _C134 -14 + possible_seatings_('A',_1) _C135 -15 + possible_seatings_('B',_1) Maximum_table_size_1 1 + possible_seatings_('B',_1) Must_seat_B 1 + possible_seatings_('B',_1) _C121 -1 + possible_seatings_('B',_1) _C136 -1 + possible_seatings_('B',_1) _C137 -2 + possible_seatings_('B',_1) _C138 -3 + possible_seatings_('B',_1) _C139 -4 + possible_seatings_('B',_1) _C140 -5 + possible_seatings_('B',_1) _C141 -6 + possible_seatings_('B',_1) _C142 -7 + possible_seatings_('B',_1) _C143 -8 + possible_seatings_('B',_1) _C144 -9 + possible_seatings_('B',_1) _C145 -10 + possible_seatings_('B',_1) _C146 -11 + possible_seatings_('B',_1) _C147 -12 + possible_seatings_('B',_1) _C148 -13 + possible_seatings_('B',_1) _C149 -14 + possible_seatings_('C',_1) Maximum_table_size_1 1 + possible_seatings_('C',_1) Must_seat_C 1 + possible_seatings_('C',_1) _C122 -2 + possible_seatings_('C',_1) _C136 -1 + possible_seatings_('C',_1) _C150 -1 + possible_seatings_('C',_1) _C151 -2 + possible_seatings_('C',_1) _C152 -3 + possible_seatings_('C',_1) _C153 -4 + possible_seatings_('C',_1) _C154 -5 + possible_seatings_('C',_1) _C155 -6 + possible_seatings_('C',_1) _C156 -7 + possible_seatings_('C',_1) _C157 -8 + possible_seatings_('C',_1) _C158 -9 + possible_seatings_('C',_1) _C159 -10 + possible_seatings_('C',_1) _C160 -11 + possible_seatings_('C',_1) _C161 -12 + possible_seatings_('C',_1) _C162 -13 + possible_seatings_('D',_1) Maximum_table_size_1 1 + possible_seatings_('D',_1) Must_seat_D 1 + possible_seatings_('D',_1) _C123 -3 + possible_seatings_('D',_1) _C137 -2 + possible_seatings_('D',_1) _C150 -1 + possible_seatings_('D',_1) _C163 -1 + possible_seatings_('D',_1) _C164 -2 + possible_seatings_('D',_1) _C165 -3 + possible_seatings_('D',_1) _C166 -4 + possible_seatings_('D',_1) _C167 -5 + possible_seatings_('D',_1) _C168 -6 + possible_seatings_('D',_1) _C169 -7 + possible_seatings_('D',_1) _C170 -8 + possible_seatings_('D',_1) _C171 -9 + possible_seatings_('D',_1) _C172 -10 + possible_seatings_('D',_1) _C173 -11 + possible_seatings_('D',_1) _C174 -12 + possible_seatings_('E',_1) Maximum_table_size_1 1 + possible_seatings_('E',_1) Must_seat_E 1 + possible_seatings_('E',_1) _C124 -4 + possible_seatings_('E',_1) _C138 -3 + possible_seatings_('E',_1) _C151 -2 + possible_seatings_('E',_1) _C163 -1 + possible_seatings_('E',_1) _C175 -1 + possible_seatings_('E',_1) _C176 -2 + possible_seatings_('E',_1) _C177 -3 + possible_seatings_('E',_1) _C178 -4 + possible_seatings_('E',_1) _C179 -5 + possible_seatings_('E',_1) _C180 -6 + possible_seatings_('E',_1) _C181 -7 + possible_seatings_('E',_1) _C182 -8 + possible_seatings_('E',_1) _C183 -9 + possible_seatings_('E',_1) _C184 -10 + possible_seatings_('E',_1) _C185 -11 + possible_seatings_('F',_1) Maximum_table_size_1 1 + possible_seatings_('F',_1) Must_seat_F 1 + possible_seatings_('F',_1) _C125 -5 + possible_seatings_('F',_1) _C139 -4 + possible_seatings_('F',_1) _C152 -3 + possible_seatings_('F',_1) _C164 -2 + possible_seatings_('F',_1) _C175 -1 + possible_seatings_('F',_1) _C186 -1 + possible_seatings_('F',_1) _C187 -2 + possible_seatings_('F',_1) _C188 -3 + possible_seatings_('F',_1) _C189 -4 + possible_seatings_('F',_1) _C190 -5 + possible_seatings_('F',_1) _C191 -6 + possible_seatings_('F',_1) _C192 -7 + possible_seatings_('F',_1) _C193 -8 + possible_seatings_('F',_1) _C194 -9 + possible_seatings_('F',_1) _C195 -10 + possible_seatings_('G',_1) Maximum_table_size_1 1 + possible_seatings_('G',_1) Must_seat_G 1 + possible_seatings_('G',_1) _C126 -6 + possible_seatings_('G',_1) _C140 -5 + possible_seatings_('G',_1) _C153 -4 + possible_seatings_('G',_1) _C165 -3 + possible_seatings_('G',_1) _C176 -2 + possible_seatings_('G',_1) _C186 -1 + possible_seatings_('G',_1) _C196 -1 + possible_seatings_('G',_1) _C197 -2 + possible_seatings_('G',_1) _C198 -3 + possible_seatings_('G',_1) _C199 -4 + possible_seatings_('G',_1) _C200 -5 + possible_seatings_('G',_1) _C201 -6 + possible_seatings_('G',_1) _C202 -7 + possible_seatings_('G',_1) _C203 -8 + possible_seatings_('G',_1) _C204 -9 + possible_seatings_('H',_1) Maximum_table_size_1 1 + possible_seatings_('H',_1) Must_seat_H 1 + possible_seatings_('H',_1) _C127 -7 + possible_seatings_('H',_1) _C141 -6 + possible_seatings_('H',_1) _C154 -5 + possible_seatings_('H',_1) _C166 -4 + possible_seatings_('H',_1) _C177 -3 + possible_seatings_('H',_1) _C187 -2 + possible_seatings_('H',_1) _C196 -1 + possible_seatings_('H',_1) _C205 -1 + possible_seatings_('H',_1) _C206 -2 + possible_seatings_('H',_1) _C207 -3 + possible_seatings_('H',_1) _C208 -4 + possible_seatings_('H',_1) _C209 -5 + possible_seatings_('H',_1) _C210 -6 + possible_seatings_('H',_1) _C211 -7 + possible_seatings_('H',_1) _C212 -8 + possible_seatings_('I',_1) Maximum_table_size_1 1 + possible_seatings_('I',_1) Must_seat_I 1 + possible_seatings_('I',_1) _C128 -8 + possible_seatings_('I',_1) _C142 -7 + possible_seatings_('I',_1) _C155 -6 + possible_seatings_('I',_1) _C167 -5 + possible_seatings_('I',_1) _C178 -4 + possible_seatings_('I',_1) _C188 -3 + possible_seatings_('I',_1) _C197 -2 + possible_seatings_('I',_1) _C205 -1 + possible_seatings_('I',_1) _C213 -1 + possible_seatings_('I',_1) _C214 -2 + possible_seatings_('I',_1) _C215 -3 + possible_seatings_('I',_1) _C216 -4 + possible_seatings_('I',_1) _C217 -5 + possible_seatings_('I',_1) _C218 -6 + possible_seatings_('I',_1) _C219 -7 + possible_seatings_('J',_1) Maximum_table_size_1 1 + possible_seatings_('J',_1) Must_seat_J 1 + possible_seatings_('J',_1) _C129 -9 + possible_seatings_('J',_1) _C143 -8 + possible_seatings_('J',_1) _C156 -7 + possible_seatings_('J',_1) _C168 -6 + possible_seatings_('J',_1) _C179 -5 + possible_seatings_('J',_1) _C189 -4 + possible_seatings_('J',_1) _C198 -3 + possible_seatings_('J',_1) _C206 -2 + possible_seatings_('J',_1) _C213 -1 + possible_seatings_('J',_1) _C220 -1 + possible_seatings_('J',_1) _C221 -2 + possible_seatings_('J',_1) _C222 -3 + possible_seatings_('J',_1) _C223 -4 + possible_seatings_('J',_1) _C224 -5 + possible_seatings_('J',_1) _C225 -6 + possible_seatings_('K',_1) Maximum_table_size_1 1 + possible_seatings_('K',_1) Must_seat_K 1 + possible_seatings_('K',_1) _C130 -10 + possible_seatings_('K',_1) _C144 -9 + possible_seatings_('K',_1) _C157 -8 + possible_seatings_('K',_1) _C169 -7 + possible_seatings_('K',_1) _C180 -6 + possible_seatings_('K',_1) _C190 -5 + possible_seatings_('K',_1) _C199 -4 + possible_seatings_('K',_1) _C207 -3 + possible_seatings_('K',_1) _C214 -2 + possible_seatings_('K',_1) _C220 -1 + possible_seatings_('K',_1) _C226 -1 + possible_seatings_('K',_1) _C227 -2 + possible_seatings_('K',_1) _C228 -3 + possible_seatings_('K',_1) _C229 -4 + possible_seatings_('K',_1) _C230 -5 + possible_seatings_('L',_1) Maximum_table_size_1 1 + possible_seatings_('L',_1) Must_seat_L 1 + possible_seatings_('L',_1) _C131 -11 + possible_seatings_('L',_1) _C145 -10 + possible_seatings_('L',_1) _C158 -9 + possible_seatings_('L',_1) _C170 -8 + possible_seatings_('L',_1) _C181 -7 + possible_seatings_('L',_1) _C191 -6 + possible_seatings_('L',_1) _C200 -5 + possible_seatings_('L',_1) _C208 -4 + possible_seatings_('L',_1) _C215 -3 + possible_seatings_('L',_1) _C221 -2 + possible_seatings_('L',_1) _C226 -1 + possible_seatings_('L',_1) _C231 -1 + possible_seatings_('L',_1) _C232 -2 + possible_seatings_('L',_1) _C233 -3 + possible_seatings_('L',_1) _C234 -4 + possible_seatings_('M',_1) Maximum_table_size_1 1 + possible_seatings_('M',_1) Must_seat_M 1 + possible_seatings_('M',_1) _C132 -12 + possible_seatings_('M',_1) _C146 -11 + possible_seatings_('M',_1) _C159 -10 + possible_seatings_('M',_1) _C171 -9 + possible_seatings_('M',_1) _C182 -8 + possible_seatings_('M',_1) _C192 -7 + possible_seatings_('M',_1) _C201 -6 + possible_seatings_('M',_1) _C209 -5 + possible_seatings_('M',_1) _C216 -4 + possible_seatings_('M',_1) _C222 -3 + possible_seatings_('M',_1) _C227 -2 + possible_seatings_('M',_1) _C231 -1 + possible_seatings_('M',_1) _C235 -1 + possible_seatings_('M',_1) _C236 -2 + possible_seatings_('M',_1) _C237 -3 + possible_seatings_('N',_1) Maximum_table_size_1 1 + possible_seatings_('N',_1) Must_seat_N 1 + possible_seatings_('N',_1) _C133 -13 + possible_seatings_('N',_1) _C147 -12 + possible_seatings_('N',_1) _C160 -11 + possible_seatings_('N',_1) _C172 -10 + possible_seatings_('N',_1) _C183 -9 + possible_seatings_('N',_1) _C193 -8 + possible_seatings_('N',_1) _C202 -7 + possible_seatings_('N',_1) _C210 -6 + possible_seatings_('N',_1) _C217 -5 + possible_seatings_('N',_1) _C223 -4 + possible_seatings_('N',_1) _C228 -3 + possible_seatings_('N',_1) _C232 -2 + possible_seatings_('N',_1) _C235 -1 + possible_seatings_('N',_1) _C238 -1 + possible_seatings_('N',_1) _C239 -2 + possible_seatings_('O',_1) Maximum_table_size_1 1 + possible_seatings_('O',_1) Must_seat_O 1 + possible_seatings_('O',_1) _C134 -14 + possible_seatings_('O',_1) _C148 -13 + possible_seatings_('O',_1) _C161 -12 + possible_seatings_('O',_1) _C173 -11 + possible_seatings_('O',_1) _C184 -10 + possible_seatings_('O',_1) _C194 -9 + possible_seatings_('O',_1) _C203 -8 + possible_seatings_('O',_1) _C211 -7 + possible_seatings_('O',_1) _C218 -6 + possible_seatings_('O',_1) _C224 -5 + possible_seatings_('O',_1) _C229 -4 + possible_seatings_('O',_1) _C233 -3 + possible_seatings_('O',_1) _C236 -2 + possible_seatings_('O',_1) _C238 -1 + possible_seatings_('O',_1) _C240 -1 + possible_seatings_('P',_1) Maximum_table_size_1 1 + possible_seatings_('P',_1) Must_seat_P 1 + possible_seatings_('P',_1) _C135 -15 + possible_seatings_('P',_1) _C149 -14 + possible_seatings_('P',_1) _C162 -13 + possible_seatings_('P',_1) _C174 -12 + possible_seatings_('P',_1) _C185 -11 + possible_seatings_('P',_1) _C195 -10 + possible_seatings_('P',_1) _C204 -9 + possible_seatings_('P',_1) _C212 -8 + possible_seatings_('P',_1) _C219 -7 + possible_seatings_('P',_1) _C225 -6 + possible_seatings_('P',_1) _C230 -5 + possible_seatings_('P',_1) _C234 -4 + possible_seatings_('P',_1) _C237 -3 + possible_seatings_('P',_1) _C239 -2 + possible_seatings_('P',_1) _C240 -1 + possible_seatings_('A',_2) Maximum_table_size_2 1 + possible_seatings_('A',_2) Must_seat_A 1 + possible_seatings_('A',_2) _C241 -1 + possible_seatings_('A',_2) _C242 -2 + possible_seatings_('A',_2) _C243 -3 + possible_seatings_('A',_2) _C244 -4 + possible_seatings_('A',_2) _C245 -5 + possible_seatings_('A',_2) _C246 -6 + possible_seatings_('A',_2) _C247 -7 + possible_seatings_('A',_2) _C248 -8 + possible_seatings_('A',_2) _C249 -9 + possible_seatings_('A',_2) _C250 -10 + possible_seatings_('A',_2) _C251 -11 + possible_seatings_('A',_2) _C252 -12 + possible_seatings_('A',_2) _C253 -13 + possible_seatings_('A',_2) _C254 -14 + possible_seatings_('A',_2) _C255 -15 + possible_seatings_('B',_2) Maximum_table_size_2 1 + possible_seatings_('B',_2) Must_seat_B 1 + possible_seatings_('B',_2) _C241 -1 + possible_seatings_('B',_2) _C256 -1 + possible_seatings_('B',_2) _C257 -2 + possible_seatings_('B',_2) _C258 -3 + possible_seatings_('B',_2) _C259 -4 + possible_seatings_('B',_2) _C260 -5 + possible_seatings_('B',_2) _C261 -6 + possible_seatings_('B',_2) _C262 -7 + possible_seatings_('B',_2) _C263 -8 + possible_seatings_('B',_2) _C264 -9 + possible_seatings_('B',_2) _C265 -10 + possible_seatings_('B',_2) _C266 -11 + possible_seatings_('B',_2) _C267 -12 + possible_seatings_('B',_2) _C268 -13 + possible_seatings_('B',_2) _C269 -14 + possible_seatings_('C',_2) Maximum_table_size_2 1 + possible_seatings_('C',_2) Must_seat_C 1 + possible_seatings_('C',_2) _C242 -2 + possible_seatings_('C',_2) _C256 -1 + possible_seatings_('C',_2) _C270 -1 + possible_seatings_('C',_2) _C271 -2 + possible_seatings_('C',_2) _C272 -3 + possible_seatings_('C',_2) _C273 -4 + possible_seatings_('C',_2) _C274 -5 + possible_seatings_('C',_2) _C275 -6 + possible_seatings_('C',_2) _C276 -7 + possible_seatings_('C',_2) _C277 -8 + possible_seatings_('C',_2) _C278 -9 + possible_seatings_('C',_2) _C279 -10 + possible_seatings_('C',_2) _C280 -11 + possible_seatings_('C',_2) _C281 -12 + possible_seatings_('C',_2) _C282 -13 + possible_seatings_('D',_2) Maximum_table_size_2 1 + possible_seatings_('D',_2) Must_seat_D 1 + possible_seatings_('D',_2) _C243 -3 + possible_seatings_('D',_2) _C257 -2 + possible_seatings_('D',_2) _C270 -1 + possible_seatings_('D',_2) _C283 -1 + possible_seatings_('D',_2) _C284 -2 + possible_seatings_('D',_2) _C285 -3 + possible_seatings_('D',_2) _C286 -4 + possible_seatings_('D',_2) _C287 -5 + possible_seatings_('D',_2) _C288 -6 + possible_seatings_('D',_2) _C289 -7 + possible_seatings_('D',_2) _C290 -8 + possible_seatings_('D',_2) _C291 -9 + possible_seatings_('D',_2) _C292 -10 + possible_seatings_('D',_2) _C293 -11 + possible_seatings_('D',_2) _C294 -12 + possible_seatings_('E',_2) Maximum_table_size_2 1 + possible_seatings_('E',_2) Must_seat_E 1 + possible_seatings_('E',_2) _C244 -4 + possible_seatings_('E',_2) _C258 -3 + possible_seatings_('E',_2) _C271 -2 + possible_seatings_('E',_2) _C283 -1 + possible_seatings_('E',_2) _C295 -1 + possible_seatings_('E',_2) _C296 -2 + possible_seatings_('E',_2) _C297 -3 + possible_seatings_('E',_2) _C298 -4 + possible_seatings_('E',_2) _C299 -5 + possible_seatings_('E',_2) _C300 -6 + possible_seatings_('E',_2) _C301 -7 + possible_seatings_('E',_2) _C302 -8 + possible_seatings_('E',_2) _C303 -9 + possible_seatings_('E',_2) _C304 -10 + possible_seatings_('E',_2) _C305 -11 + possible_seatings_('F',_2) Maximum_table_size_2 1 + possible_seatings_('F',_2) Must_seat_F 1 + possible_seatings_('F',_2) _C245 -5 + possible_seatings_('F',_2) _C259 -4 + possible_seatings_('F',_2) _C272 -3 + possible_seatings_('F',_2) _C284 -2 + possible_seatings_('F',_2) _C295 -1 + possible_seatings_('F',_2) _C306 -1 + possible_seatings_('F',_2) _C307 -2 + possible_seatings_('F',_2) _C308 -3 + possible_seatings_('F',_2) _C309 -4 + possible_seatings_('F',_2) _C310 -5 + possible_seatings_('F',_2) _C311 -6 + possible_seatings_('F',_2) _C312 -7 + possible_seatings_('F',_2) _C313 -8 + possible_seatings_('F',_2) _C314 -9 + possible_seatings_('F',_2) _C315 -10 + possible_seatings_('G',_2) Maximum_table_size_2 1 + possible_seatings_('G',_2) Must_seat_G 1 + possible_seatings_('G',_2) _C246 -6 + possible_seatings_('G',_2) _C260 -5 + possible_seatings_('G',_2) _C273 -4 + possible_seatings_('G',_2) _C285 -3 + possible_seatings_('G',_2) _C296 -2 + possible_seatings_('G',_2) _C306 -1 + possible_seatings_('G',_2) _C316 -1 + possible_seatings_('G',_2) _C317 -2 + possible_seatings_('G',_2) _C318 -3 + possible_seatings_('G',_2) _C319 -4 + possible_seatings_('G',_2) _C320 -5 + possible_seatings_('G',_2) _C321 -6 + possible_seatings_('G',_2) _C322 -7 + possible_seatings_('G',_2) _C323 -8 + possible_seatings_('G',_2) _C324 -9 + possible_seatings_('H',_2) Maximum_table_size_2 1 + possible_seatings_('H',_2) Must_seat_H 1 + possible_seatings_('H',_2) _C247 -7 + possible_seatings_('H',_2) _C261 -6 + possible_seatings_('H',_2) _C274 -5 + possible_seatings_('H',_2) _C286 -4 + possible_seatings_('H',_2) _C297 -3 + possible_seatings_('H',_2) _C307 -2 + possible_seatings_('H',_2) _C316 -1 + possible_seatings_('H',_2) _C325 -1 + possible_seatings_('H',_2) _C326 -2 + possible_seatings_('H',_2) _C327 -3 + possible_seatings_('H',_2) _C328 -4 + possible_seatings_('H',_2) _C329 -5 + possible_seatings_('H',_2) _C330 -6 + possible_seatings_('H',_2) _C331 -7 + possible_seatings_('H',_2) _C332 -8 + possible_seatings_('I',_2) Maximum_table_size_2 1 + possible_seatings_('I',_2) Must_seat_I 1 + possible_seatings_('I',_2) _C248 -8 + possible_seatings_('I',_2) _C262 -7 + possible_seatings_('I',_2) _C275 -6 + possible_seatings_('I',_2) _C287 -5 + possible_seatings_('I',_2) _C298 -4 + possible_seatings_('I',_2) _C308 -3 + possible_seatings_('I',_2) _C317 -2 + possible_seatings_('I',_2) _C325 -1 + possible_seatings_('I',_2) _C333 -1 + possible_seatings_('I',_2) _C334 -2 + possible_seatings_('I',_2) _C335 -3 + possible_seatings_('I',_2) _C336 -4 + possible_seatings_('I',_2) _C337 -5 + possible_seatings_('I',_2) _C338 -6 + possible_seatings_('I',_2) _C339 -7 + possible_seatings_('J',_2) Maximum_table_size_2 1 + possible_seatings_('J',_2) Must_seat_J 1 + possible_seatings_('J',_2) _C249 -9 + possible_seatings_('J',_2) _C263 -8 + possible_seatings_('J',_2) _C276 -7 + possible_seatings_('J',_2) _C288 -6 + possible_seatings_('J',_2) _C299 -5 + possible_seatings_('J',_2) _C309 -4 + possible_seatings_('J',_2) _C318 -3 + possible_seatings_('J',_2) _C326 -2 + possible_seatings_('J',_2) _C333 -1 + possible_seatings_('J',_2) _C340 -1 + possible_seatings_('J',_2) _C341 -2 + possible_seatings_('J',_2) _C342 -3 + possible_seatings_('J',_2) _C343 -4 + possible_seatings_('J',_2) _C344 -5 + possible_seatings_('J',_2) _C345 -6 + possible_seatings_('K',_2) Maximum_table_size_2 1 + possible_seatings_('K',_2) Must_seat_K 1 + possible_seatings_('K',_2) _C250 -10 + possible_seatings_('K',_2) _C264 -9 + possible_seatings_('K',_2) _C277 -8 + possible_seatings_('K',_2) _C289 -7 + possible_seatings_('K',_2) _C300 -6 + possible_seatings_('K',_2) _C310 -5 + possible_seatings_('K',_2) _C319 -4 + possible_seatings_('K',_2) _C327 -3 + possible_seatings_('K',_2) _C334 -2 + possible_seatings_('K',_2) _C340 -1 + possible_seatings_('K',_2) _C346 -1 + possible_seatings_('K',_2) _C347 -2 + possible_seatings_('K',_2) _C348 -3 + possible_seatings_('K',_2) _C349 -4 + possible_seatings_('K',_2) _C350 -5 + possible_seatings_('L',_2) Maximum_table_size_2 1 + possible_seatings_('L',_2) Must_seat_L 1 + possible_seatings_('L',_2) _C251 -11 + possible_seatings_('L',_2) _C265 -10 + possible_seatings_('L',_2) _C278 -9 + possible_seatings_('L',_2) _C290 -8 + possible_seatings_('L',_2) _C301 -7 + possible_seatings_('L',_2) _C311 -6 + possible_seatings_('L',_2) _C320 -5 + possible_seatings_('L',_2) _C328 -4 + possible_seatings_('L',_2) _C335 -3 + possible_seatings_('L',_2) _C341 -2 + possible_seatings_('L',_2) _C346 -1 + possible_seatings_('L',_2) _C351 -1 + possible_seatings_('L',_2) _C352 -2 + possible_seatings_('L',_2) _C353 -3 + possible_seatings_('L',_2) _C354 -4 + possible_seatings_('M',_2) Maximum_table_size_2 1 + possible_seatings_('M',_2) Must_seat_M 1 + possible_seatings_('M',_2) _C252 -12 + possible_seatings_('M',_2) _C266 -11 + possible_seatings_('M',_2) _C279 -10 + possible_seatings_('M',_2) _C291 -9 + possible_seatings_('M',_2) _C302 -8 + possible_seatings_('M',_2) _C312 -7 + possible_seatings_('M',_2) _C321 -6 + possible_seatings_('M',_2) _C329 -5 + possible_seatings_('M',_2) _C336 -4 + possible_seatings_('M',_2) _C342 -3 + possible_seatings_('M',_2) _C347 -2 + possible_seatings_('M',_2) _C351 -1 + possible_seatings_('M',_2) _C355 -1 + possible_seatings_('M',_2) _C356 -2 + possible_seatings_('M',_2) _C357 -3 + possible_seatings_('N',_2) Maximum_table_size_2 1 + possible_seatings_('N',_2) Must_seat_N 1 + possible_seatings_('N',_2) _C253 -13 + possible_seatings_('N',_2) _C267 -12 + possible_seatings_('N',_2) _C280 -11 + possible_seatings_('N',_2) _C292 -10 + possible_seatings_('N',_2) _C303 -9 + possible_seatings_('N',_2) _C313 -8 + possible_seatings_('N',_2) _C322 -7 + possible_seatings_('N',_2) _C330 -6 + possible_seatings_('N',_2) _C337 -5 + possible_seatings_('N',_2) _C343 -4 + possible_seatings_('N',_2) _C348 -3 + possible_seatings_('N',_2) _C352 -2 + possible_seatings_('N',_2) _C355 -1 + possible_seatings_('N',_2) _C358 -1 + possible_seatings_('N',_2) _C359 -2 + possible_seatings_('O',_2) Maximum_table_size_2 1 + possible_seatings_('O',_2) Must_seat_O 1 + possible_seatings_('O',_2) _C254 -14 + possible_seatings_('O',_2) _C268 -13 + possible_seatings_('O',_2) _C281 -12 + possible_seatings_('O',_2) _C293 -11 + possible_seatings_('O',_2) _C304 -10 + possible_seatings_('O',_2) _C314 -9 + possible_seatings_('O',_2) _C323 -8 + possible_seatings_('O',_2) _C331 -7 + possible_seatings_('O',_2) _C338 -6 + possible_seatings_('O',_2) _C344 -5 + possible_seatings_('O',_2) _C349 -4 + possible_seatings_('O',_2) _C353 -3 + possible_seatings_('O',_2) _C356 -2 + possible_seatings_('O',_2) _C358 -1 + possible_seatings_('O',_2) _C360 -1 + possible_seatings_('P',_2) Maximum_table_size_2 1 + possible_seatings_('P',_2) Must_seat_P 1 + possible_seatings_('P',_2) _C255 -15 + possible_seatings_('P',_2) _C269 -14 + possible_seatings_('P',_2) _C282 -13 + possible_seatings_('P',_2) _C294 -12 + possible_seatings_('P',_2) _C305 -11 + possible_seatings_('P',_2) _C315 -10 + possible_seatings_('P',_2) _C324 -9 + possible_seatings_('P',_2) _C332 -8 + possible_seatings_('P',_2) _C339 -7 + possible_seatings_('P',_2) _C345 -6 + possible_seatings_('P',_2) _C350 -5 + possible_seatings_('P',_2) _C354 -4 + possible_seatings_('P',_2) _C357 -3 + possible_seatings_('P',_2) _C359 -2 + possible_seatings_('P',_2) _C360 -1 + possible_seatings_('A',_3) Maximum_table_size_3 1 + possible_seatings_('A',_3) Must_seat_A 1 + possible_seatings_('A',_3) _C361 -1 + possible_seatings_('A',_3) _C362 -2 + possible_seatings_('A',_3) _C363 -3 + possible_seatings_('A',_3) _C364 -4 + possible_seatings_('A',_3) _C365 -5 + possible_seatings_('A',_3) _C366 -6 + possible_seatings_('A',_3) _C367 -7 + possible_seatings_('A',_3) _C368 -8 + possible_seatings_('A',_3) _C369 -9 + possible_seatings_('A',_3) _C370 -10 + possible_seatings_('A',_3) _C371 -11 + possible_seatings_('A',_3) _C372 -12 + possible_seatings_('A',_3) _C373 -13 + possible_seatings_('A',_3) _C374 -14 + possible_seatings_('A',_3) _C375 -15 + possible_seatings_('B',_3) Maximum_table_size_3 1 + possible_seatings_('B',_3) Must_seat_B 1 + possible_seatings_('B',_3) _C361 -1 + possible_seatings_('B',_3) _C376 -1 + possible_seatings_('B',_3) _C377 -2 + possible_seatings_('B',_3) _C378 -3 + possible_seatings_('B',_3) _C379 -4 + possible_seatings_('B',_3) _C380 -5 + possible_seatings_('B',_3) _C381 -6 + possible_seatings_('B',_3) _C382 -7 + possible_seatings_('B',_3) _C383 -8 + possible_seatings_('B',_3) _C384 -9 + possible_seatings_('B',_3) _C385 -10 + possible_seatings_('B',_3) _C386 -11 + possible_seatings_('B',_3) _C387 -12 + possible_seatings_('B',_3) _C388 -13 + possible_seatings_('B',_3) _C389 -14 + possible_seatings_('C',_3) Maximum_table_size_3 1 + possible_seatings_('C',_3) Must_seat_C 1 + possible_seatings_('C',_3) _C362 -2 + possible_seatings_('C',_3) _C376 -1 + possible_seatings_('C',_3) _C390 -1 + possible_seatings_('C',_3) _C391 -2 + possible_seatings_('C',_3) _C392 -3 + possible_seatings_('C',_3) _C393 -4 + possible_seatings_('C',_3) _C394 -5 + possible_seatings_('C',_3) _C395 -6 + possible_seatings_('C',_3) _C396 -7 + possible_seatings_('C',_3) _C397 -8 + possible_seatings_('C',_3) _C398 -9 + possible_seatings_('C',_3) _C399 -10 + possible_seatings_('C',_3) _C400 -11 + possible_seatings_('C',_3) _C401 -12 + possible_seatings_('C',_3) _C402 -13 + possible_seatings_('D',_3) Maximum_table_size_3 1 + possible_seatings_('D',_3) Must_seat_D 1 + possible_seatings_('D',_3) _C363 -3 + possible_seatings_('D',_3) _C377 -2 + possible_seatings_('D',_3) _C390 -1 + possible_seatings_('D',_3) _C403 -1 + possible_seatings_('D',_3) _C404 -2 + possible_seatings_('D',_3) _C405 -3 + possible_seatings_('D',_3) _C406 -4 + possible_seatings_('D',_3) _C407 -5 + possible_seatings_('D',_3) _C408 -6 + possible_seatings_('D',_3) _C409 -7 + possible_seatings_('D',_3) _C410 -8 + possible_seatings_('D',_3) _C411 -9 + possible_seatings_('D',_3) _C412 -10 + possible_seatings_('D',_3) _C413 -11 + possible_seatings_('D',_3) _C414 -12 + possible_seatings_('E',_3) Maximum_table_size_3 1 + possible_seatings_('E',_3) Must_seat_E 1 + possible_seatings_('E',_3) _C364 -4 + possible_seatings_('E',_3) _C378 -3 + possible_seatings_('E',_3) _C391 -2 + possible_seatings_('E',_3) _C403 -1 + possible_seatings_('E',_3) _C415 -1 + possible_seatings_('E',_3) _C416 -2 + possible_seatings_('E',_3) _C417 -3 + possible_seatings_('E',_3) _C418 -4 + possible_seatings_('E',_3) _C419 -5 + possible_seatings_('E',_3) _C420 -6 + possible_seatings_('E',_3) _C421 -7 + possible_seatings_('E',_3) _C422 -8 + possible_seatings_('E',_3) _C423 -9 + possible_seatings_('E',_3) _C424 -10 + possible_seatings_('E',_3) _C425 -11 + possible_seatings_('F',_3) Maximum_table_size_3 1 + possible_seatings_('F',_3) Must_seat_F 1 + possible_seatings_('F',_3) _C365 -5 + possible_seatings_('F',_3) _C379 -4 + possible_seatings_('F',_3) _C392 -3 + possible_seatings_('F',_3) _C404 -2 + possible_seatings_('F',_3) _C415 -1 + possible_seatings_('F',_3) _C426 -1 + possible_seatings_('F',_3) _C427 -2 + possible_seatings_('F',_3) _C428 -3 + possible_seatings_('F',_3) _C429 -4 + possible_seatings_('F',_3) _C430 -5 + possible_seatings_('F',_3) _C431 -6 + possible_seatings_('F',_3) _C432 -7 + possible_seatings_('F',_3) _C433 -8 + possible_seatings_('F',_3) _C434 -9 + possible_seatings_('F',_3) _C435 -10 + possible_seatings_('G',_3) Maximum_table_size_3 1 + possible_seatings_('G',_3) Must_seat_G 1 + possible_seatings_('G',_3) _C366 -6 + possible_seatings_('G',_3) _C380 -5 + possible_seatings_('G',_3) _C393 -4 + possible_seatings_('G',_3) _C405 -3 + possible_seatings_('G',_3) _C416 -2 + possible_seatings_('G',_3) _C426 -1 + possible_seatings_('G',_3) _C436 -1 + possible_seatings_('G',_3) _C437 -2 + possible_seatings_('G',_3) _C438 -3 + possible_seatings_('G',_3) _C439 -4 + possible_seatings_('G',_3) _C440 -5 + possible_seatings_('G',_3) _C441 -6 + possible_seatings_('G',_3) _C442 -7 + possible_seatings_('G',_3) _C443 -8 + possible_seatings_('G',_3) _C444 -9 + possible_seatings_('H',_3) Maximum_table_size_3 1 + possible_seatings_('H',_3) Must_seat_H 1 + possible_seatings_('H',_3) _C367 -7 + possible_seatings_('H',_3) _C381 -6 + possible_seatings_('H',_3) _C394 -5 + possible_seatings_('H',_3) _C406 -4 + possible_seatings_('H',_3) _C417 -3 + possible_seatings_('H',_3) _C427 -2 + possible_seatings_('H',_3) _C436 -1 + possible_seatings_('H',_3) _C445 -1 + possible_seatings_('H',_3) _C446 -2 + possible_seatings_('H',_3) _C447 -3 + possible_seatings_('H',_3) _C448 -4 + possible_seatings_('H',_3) _C449 -5 + possible_seatings_('H',_3) _C450 -6 + possible_seatings_('H',_3) _C451 -7 + possible_seatings_('H',_3) _C452 -8 + possible_seatings_('I',_3) Maximum_table_size_3 1 + possible_seatings_('I',_3) Must_seat_I 1 + possible_seatings_('I',_3) _C368 -8 + possible_seatings_('I',_3) _C382 -7 + possible_seatings_('I',_3) _C395 -6 + possible_seatings_('I',_3) _C407 -5 + possible_seatings_('I',_3) _C418 -4 + possible_seatings_('I',_3) _C428 -3 + possible_seatings_('I',_3) _C437 -2 + possible_seatings_('I',_3) _C445 -1 + possible_seatings_('I',_3) _C453 -1 + possible_seatings_('I',_3) _C454 -2 + possible_seatings_('I',_3) _C455 -3 + possible_seatings_('I',_3) _C456 -4 + possible_seatings_('I',_3) _C457 -5 + possible_seatings_('I',_3) _C458 -6 + possible_seatings_('I',_3) _C459 -7 + possible_seatings_('J',_3) Maximum_table_size_3 1 + possible_seatings_('J',_3) Must_seat_J 1 + possible_seatings_('J',_3) _C369 -9 + possible_seatings_('J',_3) _C383 -8 + possible_seatings_('J',_3) _C396 -7 + possible_seatings_('J',_3) _C408 -6 + possible_seatings_('J',_3) _C419 -5 + possible_seatings_('J',_3) _C429 -4 + possible_seatings_('J',_3) _C438 -3 + possible_seatings_('J',_3) _C446 -2 + possible_seatings_('J',_3) _C453 -1 + possible_seatings_('J',_3) _C460 -1 + possible_seatings_('J',_3) _C461 -2 + possible_seatings_('J',_3) _C462 -3 + possible_seatings_('J',_3) _C463 -4 + possible_seatings_('J',_3) _C464 -5 + possible_seatings_('J',_3) _C465 -6 + possible_seatings_('K',_3) Maximum_table_size_3 1 + possible_seatings_('K',_3) Must_seat_K 1 + possible_seatings_('K',_3) _C370 -10 + possible_seatings_('K',_3) _C384 -9 + possible_seatings_('K',_3) _C397 -8 + possible_seatings_('K',_3) _C409 -7 + possible_seatings_('K',_3) _C420 -6 + possible_seatings_('K',_3) _C430 -5 + possible_seatings_('K',_3) _C439 -4 + possible_seatings_('K',_3) _C447 -3 + possible_seatings_('K',_3) _C454 -2 + possible_seatings_('K',_3) _C460 -1 + possible_seatings_('K',_3) _C466 -1 + possible_seatings_('K',_3) _C467 -2 + possible_seatings_('K',_3) _C468 -3 + possible_seatings_('K',_3) _C469 -4 + possible_seatings_('K',_3) _C470 -5 + possible_seatings_('L',_3) Maximum_table_size_3 1 + possible_seatings_('L',_3) Must_seat_L 1 + possible_seatings_('L',_3) _C371 -11 + possible_seatings_('L',_3) _C385 -10 + possible_seatings_('L',_3) _C398 -9 + possible_seatings_('L',_3) _C410 -8 + possible_seatings_('L',_3) _C421 -7 + possible_seatings_('L',_3) _C431 -6 + possible_seatings_('L',_3) _C440 -5 + possible_seatings_('L',_3) _C448 -4 + possible_seatings_('L',_3) _C455 -3 + possible_seatings_('L',_3) _C461 -2 + possible_seatings_('L',_3) _C466 -1 + possible_seatings_('L',_3) _C471 -1 + possible_seatings_('L',_3) _C472 -2 + possible_seatings_('L',_3) _C473 -3 + possible_seatings_('L',_3) _C474 -4 + possible_seatings_('M',_3) Maximum_table_size_3 1 + possible_seatings_('M',_3) Must_seat_M 1 + possible_seatings_('M',_3) _C372 -12 + possible_seatings_('M',_3) _C386 -11 + possible_seatings_('M',_3) _C399 -10 + possible_seatings_('M',_3) _C411 -9 + possible_seatings_('M',_3) _C422 -8 + possible_seatings_('M',_3) _C432 -7 + possible_seatings_('M',_3) _C441 -6 + possible_seatings_('M',_3) _C449 -5 + possible_seatings_('M',_3) _C456 -4 + possible_seatings_('M',_3) _C462 -3 + possible_seatings_('M',_3) _C467 -2 + possible_seatings_('M',_3) _C471 -1 + possible_seatings_('M',_3) _C475 -1 + possible_seatings_('M',_3) _C476 -2 + possible_seatings_('M',_3) _C477 -3 + possible_seatings_('N',_3) Maximum_table_size_3 1 + possible_seatings_('N',_3) Must_seat_N 1 + possible_seatings_('N',_3) _C373 -13 + possible_seatings_('N',_3) _C387 -12 + possible_seatings_('N',_3) _C400 -11 + possible_seatings_('N',_3) _C412 -10 + possible_seatings_('N',_3) _C423 -9 + possible_seatings_('N',_3) _C433 -8 + possible_seatings_('N',_3) _C442 -7 + possible_seatings_('N',_3) _C450 -6 + possible_seatings_('N',_3) _C457 -5 + possible_seatings_('N',_3) _C463 -4 + possible_seatings_('N',_3) _C468 -3 + possible_seatings_('N',_3) _C472 -2 + possible_seatings_('N',_3) _C475 -1 + possible_seatings_('N',_3) _C478 -1 + possible_seatings_('N',_3) _C479 -2 + possible_seatings_('O',_3) Maximum_table_size_3 1 + possible_seatings_('O',_3) Must_seat_O 1 + possible_seatings_('O',_3) _C374 -14 + possible_seatings_('O',_3) _C388 -13 + possible_seatings_('O',_3) _C401 -12 + possible_seatings_('O',_3) _C413 -11 + possible_seatings_('O',_3) _C424 -10 + possible_seatings_('O',_3) _C434 -9 + possible_seatings_('O',_3) _C443 -8 + possible_seatings_('O',_3) _C451 -7 + possible_seatings_('O',_3) _C458 -6 + possible_seatings_('O',_3) _C464 -5 + possible_seatings_('O',_3) _C469 -4 + possible_seatings_('O',_3) _C473 -3 + possible_seatings_('O',_3) _C476 -2 + possible_seatings_('O',_3) _C478 -1 + possible_seatings_('O',_3) _C480 -1 + possible_seatings_('P',_3) Maximum_table_size_3 1 + possible_seatings_('P',_3) Must_seat_P 1 + possible_seatings_('P',_3) _C375 -15 + possible_seatings_('P',_3) _C389 -14 + possible_seatings_('P',_3) _C402 -13 + possible_seatings_('P',_3) _C414 -12 + possible_seatings_('P',_3) _C425 -11 + possible_seatings_('P',_3) _C435 -10 + possible_seatings_('P',_3) _C444 -9 + possible_seatings_('P',_3) _C452 -8 + possible_seatings_('P',_3) _C459 -7 + possible_seatings_('P',_3) _C465 -6 + possible_seatings_('P',_3) _C470 -5 + possible_seatings_('P',_3) _C474 -4 + possible_seatings_('P',_3) _C477 -3 + possible_seatings_('P',_3) _C479 -2 + possible_seatings_('P',_3) _C480 -1 + possible_seatings_('A',_4) Maximum_table_size_4 1 + possible_seatings_('A',_4) Must_seat_A 1 + possible_seatings_('A',_4) _C481 -1 + possible_seatings_('A',_4) _C482 -2 + possible_seatings_('A',_4) _C483 -3 + possible_seatings_('A',_4) _C484 -4 + possible_seatings_('A',_4) _C485 -5 + possible_seatings_('A',_4) _C486 -6 + possible_seatings_('A',_4) _C487 -7 + possible_seatings_('A',_4) _C488 -8 + possible_seatings_('A',_4) _C489 -9 + possible_seatings_('A',_4) _C490 -10 + possible_seatings_('A',_4) _C491 -11 + possible_seatings_('A',_4) _C492 -12 + possible_seatings_('A',_4) _C493 -13 + possible_seatings_('A',_4) _C494 -14 + possible_seatings_('A',_4) _C495 -15 + possible_seatings_('B',_4) Maximum_table_size_4 1 + possible_seatings_('B',_4) Must_seat_B 1 + possible_seatings_('B',_4) _C481 -1 + possible_seatings_('B',_4) _C496 -1 + possible_seatings_('B',_4) _C497 -2 + possible_seatings_('B',_4) _C498 -3 + possible_seatings_('B',_4) _C499 -4 + possible_seatings_('B',_4) _C500 -5 + possible_seatings_('B',_4) _C501 -6 + possible_seatings_('B',_4) _C502 -7 + possible_seatings_('B',_4) _C503 -8 + possible_seatings_('B',_4) _C504 -9 + possible_seatings_('B',_4) _C505 -10 + possible_seatings_('B',_4) _C506 -11 + possible_seatings_('B',_4) _C507 -12 + possible_seatings_('B',_4) _C508 -13 + possible_seatings_('B',_4) _C509 -14 + possible_seatings_('C',_4) Maximum_table_size_4 1 + possible_seatings_('C',_4) Must_seat_C 1 + possible_seatings_('C',_4) _C482 -2 + possible_seatings_('C',_4) _C496 -1 + possible_seatings_('C',_4) _C510 -1 + possible_seatings_('C',_4) _C511 -2 + possible_seatings_('C',_4) _C512 -3 + possible_seatings_('C',_4) _C513 -4 + possible_seatings_('C',_4) _C514 -5 + possible_seatings_('C',_4) _C515 -6 + possible_seatings_('C',_4) _C516 -7 + possible_seatings_('C',_4) _C517 -8 + possible_seatings_('C',_4) _C518 -9 + possible_seatings_('C',_4) _C519 -10 + possible_seatings_('C',_4) _C520 -11 + possible_seatings_('C',_4) _C521 -12 + possible_seatings_('C',_4) _C522 -13 + possible_seatings_('D',_4) Maximum_table_size_4 1 + possible_seatings_('D',_4) Must_seat_D 1 + possible_seatings_('D',_4) _C483 -3 + possible_seatings_('D',_4) _C497 -2 + possible_seatings_('D',_4) _C510 -1 + possible_seatings_('D',_4) _C523 -1 + possible_seatings_('D',_4) _C524 -2 + possible_seatings_('D',_4) _C525 -3 + possible_seatings_('D',_4) _C526 -4 + possible_seatings_('D',_4) _C527 -5 + possible_seatings_('D',_4) _C528 -6 + possible_seatings_('D',_4) _C529 -7 + possible_seatings_('D',_4) _C530 -8 + possible_seatings_('D',_4) _C531 -9 + possible_seatings_('D',_4) _C532 -10 + possible_seatings_('D',_4) _C533 -11 + possible_seatings_('D',_4) _C534 -12 + possible_seatings_('E',_4) Maximum_table_size_4 1 + possible_seatings_('E',_4) Must_seat_E 1 + possible_seatings_('E',_4) _C484 -4 + possible_seatings_('E',_4) _C498 -3 + possible_seatings_('E',_4) _C511 -2 + possible_seatings_('E',_4) _C523 -1 + possible_seatings_('E',_4) _C535 -1 + possible_seatings_('E',_4) _C536 -2 + possible_seatings_('E',_4) _C537 -3 + possible_seatings_('E',_4) _C538 -4 + possible_seatings_('E',_4) _C539 -5 + possible_seatings_('E',_4) _C540 -6 + possible_seatings_('E',_4) _C541 -7 + possible_seatings_('E',_4) _C542 -8 + possible_seatings_('E',_4) _C543 -9 + possible_seatings_('E',_4) _C544 -10 + possible_seatings_('E',_4) _C545 -11 + possible_seatings_('F',_4) Maximum_table_size_4 1 + possible_seatings_('F',_4) Must_seat_F 1 + possible_seatings_('F',_4) _C485 -5 + possible_seatings_('F',_4) _C499 -4 + possible_seatings_('F',_4) _C512 -3 + possible_seatings_('F',_4) _C524 -2 + possible_seatings_('F',_4) _C535 -1 + possible_seatings_('F',_4) _C546 -1 + possible_seatings_('F',_4) _C547 -2 + possible_seatings_('F',_4) _C548 -3 + possible_seatings_('F',_4) _C549 -4 + possible_seatings_('F',_4) _C550 -5 + possible_seatings_('F',_4) _C551 -6 + possible_seatings_('F',_4) _C552 -7 + possible_seatings_('F',_4) _C553 -8 + possible_seatings_('F',_4) _C554 -9 + possible_seatings_('F',_4) _C555 -10 + possible_seatings_('G',_4) Maximum_table_size_4 1 + possible_seatings_('G',_4) Must_seat_G 1 + possible_seatings_('G',_4) _C486 -6 + possible_seatings_('G',_4) _C500 -5 + possible_seatings_('G',_4) _C513 -4 + possible_seatings_('G',_4) _C525 -3 + possible_seatings_('G',_4) _C536 -2 + possible_seatings_('G',_4) _C546 -1 + possible_seatings_('G',_4) _C556 -1 + possible_seatings_('G',_4) _C557 -2 + possible_seatings_('G',_4) _C558 -3 + possible_seatings_('G',_4) _C559 -4 + possible_seatings_('G',_4) _C560 -5 + possible_seatings_('G',_4) _C561 -6 + possible_seatings_('G',_4) _C562 -7 + possible_seatings_('G',_4) _C563 -8 + possible_seatings_('G',_4) _C564 -9 + possible_seatings_('H',_4) Maximum_table_size_4 1 + possible_seatings_('H',_4) Must_seat_H 1 + possible_seatings_('H',_4) _C487 -7 + possible_seatings_('H',_4) _C501 -6 + possible_seatings_('H',_4) _C514 -5 + possible_seatings_('H',_4) _C526 -4 + possible_seatings_('H',_4) _C537 -3 + possible_seatings_('H',_4) _C547 -2 + possible_seatings_('H',_4) _C556 -1 + possible_seatings_('H',_4) _C565 -1 + possible_seatings_('H',_4) _C566 -2 + possible_seatings_('H',_4) _C567 -3 + possible_seatings_('H',_4) _C568 -4 + possible_seatings_('H',_4) _C569 -5 + possible_seatings_('H',_4) _C570 -6 + possible_seatings_('H',_4) _C571 -7 + possible_seatings_('H',_4) _C572 -8 + possible_seatings_('I',_4) Maximum_table_size_4 1 + possible_seatings_('I',_4) Must_seat_I 1 + possible_seatings_('I',_4) _C488 -8 + possible_seatings_('I',_4) _C502 -7 + possible_seatings_('I',_4) _C515 -6 + possible_seatings_('I',_4) _C527 -5 + possible_seatings_('I',_4) _C538 -4 + possible_seatings_('I',_4) _C548 -3 + possible_seatings_('I',_4) _C557 -2 + possible_seatings_('I',_4) _C565 -1 + possible_seatings_('I',_4) _C573 -1 + possible_seatings_('I',_4) _C574 -2 + possible_seatings_('I',_4) _C575 -3 + possible_seatings_('I',_4) _C576 -4 + possible_seatings_('I',_4) _C577 -5 + possible_seatings_('I',_4) _C578 -6 + possible_seatings_('I',_4) _C579 -7 + possible_seatings_('J',_4) Maximum_table_size_4 1 + possible_seatings_('J',_4) Must_seat_J 1 + possible_seatings_('J',_4) _C489 -9 + possible_seatings_('J',_4) _C503 -8 + possible_seatings_('J',_4) _C516 -7 + possible_seatings_('J',_4) _C528 -6 + possible_seatings_('J',_4) _C539 -5 + possible_seatings_('J',_4) _C549 -4 + possible_seatings_('J',_4) _C558 -3 + possible_seatings_('J',_4) _C566 -2 + possible_seatings_('J',_4) _C573 -1 + possible_seatings_('J',_4) _C580 -1 + possible_seatings_('J',_4) _C581 -2 + possible_seatings_('J',_4) _C582 -3 + possible_seatings_('J',_4) _C583 -4 + possible_seatings_('J',_4) _C584 -5 + possible_seatings_('J',_4) _C585 -6 + possible_seatings_('K',_4) Maximum_table_size_4 1 + possible_seatings_('K',_4) Must_seat_K 1 + possible_seatings_('K',_4) _C490 -10 + possible_seatings_('K',_4) _C504 -9 + possible_seatings_('K',_4) _C517 -8 + possible_seatings_('K',_4) _C529 -7 + possible_seatings_('K',_4) _C540 -6 + possible_seatings_('K',_4) _C550 -5 + possible_seatings_('K',_4) _C559 -4 + possible_seatings_('K',_4) _C567 -3 + possible_seatings_('K',_4) _C574 -2 + possible_seatings_('K',_4) _C580 -1 + possible_seatings_('K',_4) _C586 -1 + possible_seatings_('K',_4) _C587 -2 + possible_seatings_('K',_4) _C588 -3 + possible_seatings_('K',_4) _C589 -4 + possible_seatings_('K',_4) _C590 -5 + possible_seatings_('L',_4) Maximum_table_size_4 1 + possible_seatings_('L',_4) Must_seat_L 1 + possible_seatings_('L',_4) _C491 -11 + possible_seatings_('L',_4) _C505 -10 + possible_seatings_('L',_4) _C518 -9 + possible_seatings_('L',_4) _C530 -8 + possible_seatings_('L',_4) _C541 -7 + possible_seatings_('L',_4) _C551 -6 + possible_seatings_('L',_4) _C560 -5 + possible_seatings_('L',_4) _C568 -4 + possible_seatings_('L',_4) _C575 -3 + possible_seatings_('L',_4) _C581 -2 + possible_seatings_('L',_4) _C586 -1 + possible_seatings_('L',_4) _C591 -1 + possible_seatings_('L',_4) _C592 -2 + possible_seatings_('L',_4) _C593 -3 + possible_seatings_('L',_4) _C594 -4 + possible_seatings_('M',_4) Maximum_table_size_4 1 + possible_seatings_('M',_4) Must_seat_M 1 + possible_seatings_('M',_4) _C492 -12 + possible_seatings_('M',_4) _C506 -11 + possible_seatings_('M',_4) _C519 -10 + possible_seatings_('M',_4) _C531 -9 + possible_seatings_('M',_4) _C542 -8 + possible_seatings_('M',_4) _C552 -7 + possible_seatings_('M',_4) _C561 -6 + possible_seatings_('M',_4) _C569 -5 + possible_seatings_('M',_4) _C576 -4 + possible_seatings_('M',_4) _C582 -3 + possible_seatings_('M',_4) _C587 -2 + possible_seatings_('M',_4) _C591 -1 + possible_seatings_('M',_4) _C595 -1 + possible_seatings_('M',_4) _C596 -2 + possible_seatings_('M',_4) _C597 -3 + possible_seatings_('N',_4) Maximum_table_size_4 1 + possible_seatings_('N',_4) Must_seat_N 1 + possible_seatings_('N',_4) _C493 -13 + possible_seatings_('N',_4) _C507 -12 + possible_seatings_('N',_4) _C520 -11 + possible_seatings_('N',_4) _C532 -10 + possible_seatings_('N',_4) _C543 -9 + possible_seatings_('N',_4) _C553 -8 + possible_seatings_('N',_4) _C562 -7 + possible_seatings_('N',_4) _C570 -6 + possible_seatings_('N',_4) _C577 -5 + possible_seatings_('N',_4) _C583 -4 + possible_seatings_('N',_4) _C588 -3 + possible_seatings_('N',_4) _C592 -2 + possible_seatings_('N',_4) _C595 -1 + possible_seatings_('N',_4) _C598 -1 + possible_seatings_('N',_4) _C599 -2 + possible_seatings_('O',_4) Maximum_table_size_4 1 + possible_seatings_('O',_4) Must_seat_O 1 + possible_seatings_('O',_4) _C494 -14 + possible_seatings_('O',_4) _C508 -13 + possible_seatings_('O',_4) _C521 -12 + possible_seatings_('O',_4) _C533 -11 + possible_seatings_('O',_4) _C544 -10 + possible_seatings_('O',_4) _C554 -9 + possible_seatings_('O',_4) _C563 -8 + possible_seatings_('O',_4) _C571 -7 + possible_seatings_('O',_4) _C578 -6 + possible_seatings_('O',_4) _C584 -5 + possible_seatings_('O',_4) _C589 -4 + possible_seatings_('O',_4) _C593 -3 + possible_seatings_('O',_4) _C596 -2 + possible_seatings_('O',_4) _C598 -1 + possible_seatings_('O',_4) _C600 -1 + possible_seatings_('P',_4) Maximum_table_size_4 1 + possible_seatings_('P',_4) Must_seat_P 1 + possible_seatings_('P',_4) _C495 -15 + possible_seatings_('P',_4) _C509 -14 + possible_seatings_('P',_4) _C522 -13 + possible_seatings_('P',_4) _C534 -12 + possible_seatings_('P',_4) _C545 -11 + possible_seatings_('P',_4) _C555 -10 + possible_seatings_('P',_4) _C564 -9 + possible_seatings_('P',_4) _C572 -8 + possible_seatings_('P',_4) _C579 -7 + possible_seatings_('P',_4) _C585 -6 + possible_seatings_('P',_4) _C590 -5 + possible_seatings_('P',_4) _C594 -4 + possible_seatings_('P',_4) _C597 -3 + possible_seatings_('P',_4) _C599 -2 + possible_seatings_('P',_4) _C600 -1 + MARK0001 'MARKER' 'INTEND' +RHS + rhs Maximum_table_size_0 4 + rhs Maximum_table_size_1 4 + rhs Maximum_table_size_2 4 + rhs Maximum_table_size_3 4 + rhs Maximum_table_size_4 4 + rhs Must_seat_A 1 + rhs Must_seat_B 1 + rhs Must_seat_C 1 + rhs Must_seat_D 1 + rhs Must_seat_E 1 + rhs Must_seat_F 1 + rhs Must_seat_G 1 + rhs Must_seat_H 1 + rhs Must_seat_I 1 + rhs Must_seat_J 1 + rhs Must_seat_K 1 + rhs Must_seat_L 1 + rhs Must_seat_M 1 + rhs Must_seat_N 1 + rhs Must_seat_O 1 + rhs Must_seat_P 1 + rhs _C1 -1 + rhs _C10 -10 + rhs _C100 -1 + rhs _C101 -2 + rhs _C102 -3 + rhs _C103 -4 + rhs _C104 -5 + rhs _C105 -6 + rhs _C106 -1 + rhs _C107 -2 + rhs _C108 -3 + rhs _C109 -4 + rhs _C11 -11 + rhs _C110 -5 + rhs _C111 -1 + rhs _C112 -2 + rhs _C113 -3 + rhs _C114 -4 + rhs _C115 -1 + rhs _C116 -2 + rhs _C117 -3 + rhs _C118 -1 + rhs _C119 -2 + rhs _C12 -12 + rhs _C120 -1 + rhs _C121 -1 + rhs _C122 -2 + rhs _C123 -3 + rhs _C124 -4 + rhs _C125 -5 + rhs _C126 -6 + rhs _C127 -7 + rhs _C128 -8 + rhs _C129 -9 + rhs _C13 -13 + rhs _C130 -10 + rhs _C131 -11 + rhs _C132 -12 + rhs _C133 -13 + rhs _C134 -14 + rhs _C135 -15 + rhs _C136 -1 + rhs _C137 -2 + rhs _C138 -3 + rhs _C139 -4 + rhs _C14 -14 + rhs _C140 -5 + rhs _C141 -6 + rhs _C142 -7 + rhs _C143 -8 + rhs _C144 -9 + rhs _C145 -10 + rhs _C146 -11 + rhs _C147 -12 + rhs _C148 -13 + rhs _C149 -14 + rhs _C15 -15 + rhs _C150 -1 + rhs _C151 -2 + rhs _C152 -3 + rhs _C153 -4 + rhs _C154 -5 + rhs _C155 -6 + rhs _C156 -7 + rhs _C157 -8 + rhs _C158 -9 + rhs _C159 -10 + rhs _C16 -1 + rhs _C160 -11 + rhs _C161 -12 + rhs _C162 -13 + rhs _C163 -1 + rhs _C164 -2 + rhs _C165 -3 + rhs _C166 -4 + rhs _C167 -5 + rhs _C168 -6 + rhs _C169 -7 + rhs _C17 -2 + rhs _C170 -8 + rhs _C171 -9 + rhs _C172 -10 + rhs _C173 -11 + rhs _C174 -12 + rhs _C175 -1 + rhs _C176 -2 + rhs _C177 -3 + rhs _C178 -4 + rhs _C179 -5 + rhs _C18 -3 + rhs _C180 -6 + rhs _C181 -7 + rhs _C182 -8 + rhs _C183 -9 + rhs _C184 -10 + rhs _C185 -11 + rhs _C186 -1 + rhs _C187 -2 + rhs _C188 -3 + rhs _C189 -4 + rhs _C19 -4 + rhs _C190 -5 + rhs _C191 -6 + rhs _C192 -7 + rhs _C193 -8 + rhs _C194 -9 + rhs _C195 -10 + rhs _C196 -1 + rhs _C197 -2 + rhs _C198 -3 + rhs _C199 -4 + rhs _C2 -2 + rhs _C20 -5 + rhs _C200 -5 + rhs _C201 -6 + rhs _C202 -7 + rhs _C203 -8 + rhs _C204 -9 + rhs _C205 -1 + rhs _C206 -2 + rhs _C207 -3 + rhs _C208 -4 + rhs _C209 -5 + rhs _C21 -6 + rhs _C210 -6 + rhs _C211 -7 + rhs _C212 -8 + rhs _C213 -1 + rhs _C214 -2 + rhs _C215 -3 + rhs _C216 -4 + rhs _C217 -5 + rhs _C218 -6 + rhs _C219 -7 + rhs _C22 -7 + rhs _C220 -1 + rhs _C221 -2 + rhs _C222 -3 + rhs _C223 -4 + rhs _C224 -5 + rhs _C225 -6 + rhs _C226 -1 + rhs _C227 -2 + rhs _C228 -3 + rhs _C229 -4 + rhs _C23 -8 + rhs _C230 -5 + rhs _C231 -1 + rhs _C232 -2 + rhs _C233 -3 + rhs _C234 -4 + rhs _C235 -1 + rhs _C236 -2 + rhs _C237 -3 + rhs _C238 -1 + rhs _C239 -2 + rhs _C24 -9 + rhs _C240 -1 + rhs _C241 -1 + rhs _C242 -2 + rhs _C243 -3 + rhs _C244 -4 + rhs _C245 -5 + rhs _C246 -6 + rhs _C247 -7 + rhs _C248 -8 + rhs _C249 -9 + rhs _C25 -10 + rhs _C250 -10 + rhs _C251 -11 + rhs _C252 -12 + rhs _C253 -13 + rhs _C254 -14 + rhs _C255 -15 + rhs _C256 -1 + rhs _C257 -2 + rhs _C258 -3 + rhs _C259 -4 + rhs _C26 -11 + rhs _C260 -5 + rhs _C261 -6 + rhs _C262 -7 + rhs _C263 -8 + rhs _C264 -9 + rhs _C265 -10 + rhs _C266 -11 + rhs _C267 -12 + rhs _C268 -13 + rhs _C269 -14 + rhs _C27 -12 + rhs _C270 -1 + rhs _C271 -2 + rhs _C272 -3 + rhs _C273 -4 + rhs _C274 -5 + rhs _C275 -6 + rhs _C276 -7 + rhs _C277 -8 + rhs _C278 -9 + rhs _C279 -10 + rhs _C28 -13 + rhs _C280 -11 + rhs _C281 -12 + rhs _C282 -13 + rhs _C283 -1 + rhs _C284 -2 + rhs _C285 -3 + rhs _C286 -4 + rhs _C287 -5 + rhs _C288 -6 + rhs _C289 -7 + rhs _C29 -14 + rhs _C290 -8 + rhs _C291 -9 + rhs _C292 -10 + rhs _C293 -11 + rhs _C294 -12 + rhs _C295 -1 + rhs _C296 -2 + rhs _C297 -3 + rhs _C298 -4 + rhs _C299 -5 + rhs _C3 -3 + rhs _C30 -1 + rhs _C300 -6 + rhs _C301 -7 + rhs _C302 -8 + rhs _C303 -9 + rhs _C304 -10 + rhs _C305 -11 + rhs _C306 -1 + rhs _C307 -2 + rhs _C308 -3 + rhs _C309 -4 + rhs _C31 -2 + rhs _C310 -5 + rhs _C311 -6 + rhs _C312 -7 + rhs _C313 -8 + rhs _C314 -9 + rhs _C315 -10 + rhs _C316 -1 + rhs _C317 -2 + rhs _C318 -3 + rhs _C319 -4 + rhs _C32 -3 + rhs _C320 -5 + rhs _C321 -6 + rhs _C322 -7 + rhs _C323 -8 + rhs _C324 -9 + rhs _C325 -1 + rhs _C326 -2 + rhs _C327 -3 + rhs _C328 -4 + rhs _C329 -5 + rhs _C33 -4 + rhs _C330 -6 + rhs _C331 -7 + rhs _C332 -8 + rhs _C333 -1 + rhs _C334 -2 + rhs _C335 -3 + rhs _C336 -4 + rhs _C337 -5 + rhs _C338 -6 + rhs _C339 -7 + rhs _C34 -5 + rhs _C340 -1 + rhs _C341 -2 + rhs _C342 -3 + rhs _C343 -4 + rhs _C344 -5 + rhs _C345 -6 + rhs _C346 -1 + rhs _C347 -2 + rhs _C348 -3 + rhs _C349 -4 + rhs _C35 -6 + rhs _C350 -5 + rhs _C351 -1 + rhs _C352 -2 + rhs _C353 -3 + rhs _C354 -4 + rhs _C355 -1 + rhs _C356 -2 + rhs _C357 -3 + rhs _C358 -1 + rhs _C359 -2 + rhs _C36 -7 + rhs _C360 -1 + rhs _C361 -1 + rhs _C362 -2 + rhs _C363 -3 + rhs _C364 -4 + rhs _C365 -5 + rhs _C366 -6 + rhs _C367 -7 + rhs _C368 -8 + rhs _C369 -9 + rhs _C37 -8 + rhs _C370 -10 + rhs _C371 -11 + rhs _C372 -12 + rhs _C373 -13 + rhs _C374 -14 + rhs _C375 -15 + rhs _C376 -1 + rhs _C377 -2 + rhs _C378 -3 + rhs _C379 -4 + rhs _C38 -9 + rhs _C380 -5 + rhs _C381 -6 + rhs _C382 -7 + rhs _C383 -8 + rhs _C384 -9 + rhs _C385 -10 + rhs _C386 -11 + rhs _C387 -12 + rhs _C388 -13 + rhs _C389 -14 + rhs _C39 -10 + rhs _C390 -1 + rhs _C391 -2 + rhs _C392 -3 + rhs _C393 -4 + rhs _C394 -5 + rhs _C395 -6 + rhs _C396 -7 + rhs _C397 -8 + rhs _C398 -9 + rhs _C399 -10 + rhs _C4 -4 + rhs _C40 -11 + rhs _C400 -11 + rhs _C401 -12 + rhs _C402 -13 + rhs _C403 -1 + rhs _C404 -2 + rhs _C405 -3 + rhs _C406 -4 + rhs _C407 -5 + rhs _C408 -6 + rhs _C409 -7 + rhs _C41 -12 + rhs _C410 -8 + rhs _C411 -9 + rhs _C412 -10 + rhs _C413 -11 + rhs _C414 -12 + rhs _C415 -1 + rhs _C416 -2 + rhs _C417 -3 + rhs _C418 -4 + rhs _C419 -5 + rhs _C42 -13 + rhs _C420 -6 + rhs _C421 -7 + rhs _C422 -8 + rhs _C423 -9 + rhs _C424 -10 + rhs _C425 -11 + rhs _C426 -1 + rhs _C427 -2 + rhs _C428 -3 + rhs _C429 -4 + rhs _C43 -1 + rhs _C430 -5 + rhs _C431 -6 + rhs _C432 -7 + rhs _C433 -8 + rhs _C434 -9 + rhs _C435 -10 + rhs _C436 -1 + rhs _C437 -2 + rhs _C438 -3 + rhs _C439 -4 + rhs _C44 -2 + rhs _C440 -5 + rhs _C441 -6 + rhs _C442 -7 + rhs _C443 -8 + rhs _C444 -9 + rhs _C445 -1 + rhs _C446 -2 + rhs _C447 -3 + rhs _C448 -4 + rhs _C449 -5 + rhs _C45 -3 + rhs _C450 -6 + rhs _C451 -7 + rhs _C452 -8 + rhs _C453 -1 + rhs _C454 -2 + rhs _C455 -3 + rhs _C456 -4 + rhs _C457 -5 + rhs _C458 -6 + rhs _C459 -7 + rhs _C46 -4 + rhs _C460 -1 + rhs _C461 -2 + rhs _C462 -3 + rhs _C463 -4 + rhs _C464 -5 + rhs _C465 -6 + rhs _C466 -1 + rhs _C467 -2 + rhs _C468 -3 + rhs _C469 -4 + rhs _C47 -5 + rhs _C470 -5 + rhs _C471 -1 + rhs _C472 -2 + rhs _C473 -3 + rhs _C474 -4 + rhs _C475 -1 + rhs _C476 -2 + rhs _C477 -3 + rhs _C478 -1 + rhs _C479 -2 + rhs _C48 -6 + rhs _C480 -1 + rhs _C481 -1 + rhs _C482 -2 + rhs _C483 -3 + rhs _C484 -4 + rhs _C485 -5 + rhs _C486 -6 + rhs _C487 -7 + rhs _C488 -8 + rhs _C489 -9 + rhs _C49 -7 + rhs _C490 -10 + rhs _C491 -11 + rhs _C492 -12 + rhs _C493 -13 + rhs _C494 -14 + rhs _C495 -15 + rhs _C496 -1 + rhs _C497 -2 + rhs _C498 -3 + rhs _C499 -4 + rhs _C5 -5 + rhs _C50 -8 + rhs _C500 -5 + rhs _C501 -6 + rhs _C502 -7 + rhs _C503 -8 + rhs _C504 -9 + rhs _C505 -10 + rhs _C506 -11 + rhs _C507 -12 + rhs _C508 -13 + rhs _C509 -14 + rhs _C51 -9 + rhs _C510 -1 + rhs _C511 -2 + rhs _C512 -3 + rhs _C513 -4 + rhs _C514 -5 + rhs _C515 -6 + rhs _C516 -7 + rhs _C517 -8 + rhs _C518 -9 + rhs _C519 -10 + rhs _C52 -10 + rhs _C520 -11 + rhs _C521 -12 + rhs _C522 -13 + rhs _C523 -1 + rhs _C524 -2 + rhs _C525 -3 + rhs _C526 -4 + rhs _C527 -5 + rhs _C528 -6 + rhs _C529 -7 + rhs _C53 -11 + rhs _C530 -8 + rhs _C531 -9 + rhs _C532 -10 + rhs _C533 -11 + rhs _C534 -12 + rhs _C535 -1 + rhs _C536 -2 + rhs _C537 -3 + rhs _C538 -4 + rhs _C539 -5 + rhs _C54 -12 + rhs _C540 -6 + rhs _C541 -7 + rhs _C542 -8 + rhs _C543 -9 + rhs _C544 -10 + rhs _C545 -11 + rhs _C546 -1 + rhs _C547 -2 + rhs _C548 -3 + rhs _C549 -4 + rhs _C55 -1 + rhs _C550 -5 + rhs _C551 -6 + rhs _C552 -7 + rhs _C553 -8 + rhs _C554 -9 + rhs _C555 -10 + rhs _C556 -1 + rhs _C557 -2 + rhs _C558 -3 + rhs _C559 -4 + rhs _C56 -2 + rhs _C560 -5 + rhs _C561 -6 + rhs _C562 -7 + rhs _C563 -8 + rhs _C564 -9 + rhs _C565 -1 + rhs _C566 -2 + rhs _C567 -3 + rhs _C568 -4 + rhs _C569 -5 + rhs _C57 -3 + rhs _C570 -6 + rhs _C571 -7 + rhs _C572 -8 + rhs _C573 -1 + rhs _C574 -2 + rhs _C575 -3 + rhs _C576 -4 + rhs _C577 -5 + rhs _C578 -6 + rhs _C579 -7 + rhs _C58 -4 + rhs _C580 -1 + rhs _C581 -2 + rhs _C582 -3 + rhs _C583 -4 + rhs _C584 -5 + rhs _C585 -6 + rhs _C586 -1 + rhs _C587 -2 + rhs _C588 -3 + rhs _C589 -4 + rhs _C59 -5 + rhs _C590 -5 + rhs _C591 -1 + rhs _C592 -2 + rhs _C593 -3 + rhs _C594 -4 + rhs _C595 -1 + rhs _C596 -2 + rhs _C597 -3 + rhs _C598 -1 + rhs _C599 -2 + rhs _C6 -6 + rhs _C60 -6 + rhs _C600 -1 + rhs _C61 -7 + rhs _C62 -8 + rhs _C63 -9 + rhs _C64 -10 + rhs _C65 -11 + rhs _C66 -1 + rhs _C67 -2 + rhs _C68 -3 + rhs _C69 -4 + rhs _C7 -7 + rhs _C70 -5 + rhs _C71 -6 + rhs _C72 -7 + rhs _C73 -8 + rhs _C74 -9 + rhs _C75 -10 + rhs _C76 -1 + rhs _C77 -2 + rhs _C78 -3 + rhs _C79 -4 + rhs _C8 -8 + rhs _C80 -5 + rhs _C81 -6 + rhs _C82 -7 + rhs _C83 -8 + rhs _C84 -9 + rhs _C85 -1 + rhs _C86 -2 + rhs _C87 -3 + rhs _C88 -4 + rhs _C89 -5 + rhs _C9 -9 + rhs _C90 -6 + rhs _C91 -7 + rhs _C92 -8 + rhs _C93 -1 + rhs _C94 -2 + rhs _C95 -3 + rhs _C96 -4 + rhs _C97 -5 + rhs _C98 -6 + rhs _C99 -7 +BOUNDS + UP bnd possible_seatings_('A',_0) 1 + UP bnd possible_seatings_('B',_0) 1 + UP bnd possible_seatings_('C',_0) 1 + UP bnd possible_seatings_('D',_0) 1 + UP bnd possible_seatings_('E',_0) 1 + UP bnd possible_seatings_('F',_0) 1 + UP bnd possible_seatings_('G',_0) 1 + UP bnd possible_seatings_('H',_0) 1 + UP bnd possible_seatings_('I',_0) 1 + UP bnd possible_seatings_('J',_0) 1 + UP bnd possible_seatings_('K',_0) 1 + UP bnd possible_seatings_('L',_0) 1 + UP bnd possible_seatings_('M',_0) 1 + UP bnd possible_seatings_('N',_0) 1 + UP bnd possible_seatings_('O',_0) 1 + UP bnd possible_seatings_('P',_0) 1 + UP bnd possible_seatings_('A',_1) 1 + UP bnd possible_seatings_('B',_1) 1 + UP bnd possible_seatings_('C',_1) 1 + UP bnd possible_seatings_('D',_1) 1 + UP bnd possible_seatings_('E',_1) 1 + UP bnd possible_seatings_('F',_1) 1 + UP bnd possible_seatings_('G',_1) 1 + UP bnd possible_seatings_('H',_1) 1 + UP bnd possible_seatings_('I',_1) 1 + UP bnd possible_seatings_('J',_1) 1 + UP bnd possible_seatings_('K',_1) 1 + UP bnd possible_seatings_('L',_1) 1 + UP bnd possible_seatings_('M',_1) 1 + UP bnd possible_seatings_('N',_1) 1 + UP bnd possible_seatings_('O',_1) 1 + UP bnd possible_seatings_('P',_1) 1 + UP bnd possible_seatings_('A',_2) 1 + UP bnd possible_seatings_('B',_2) 1 + UP bnd possible_seatings_('C',_2) 1 + UP bnd possible_seatings_('D',_2) 1 + UP bnd possible_seatings_('E',_2) 1 + UP bnd possible_seatings_('F',_2) 1 + UP bnd possible_seatings_('G',_2) 1 + UP bnd possible_seatings_('H',_2) 1 + UP bnd possible_seatings_('I',_2) 1 + UP bnd possible_seatings_('J',_2) 1 + UP bnd possible_seatings_('K',_2) 1 + UP bnd possible_seatings_('L',_2) 1 + UP bnd possible_seatings_('M',_2) 1 + UP bnd possible_seatings_('N',_2) 1 + UP bnd possible_seatings_('O',_2) 1 + UP bnd possible_seatings_('P',_2) 1 + UP bnd possible_seatings_('A',_3) 1 + UP bnd possible_seatings_('B',_3) 1 + UP bnd possible_seatings_('C',_3) 1 + UP bnd possible_seatings_('D',_3) 1 + UP bnd possible_seatings_('E',_3) 1 + UP bnd possible_seatings_('F',_3) 1 + UP bnd possible_seatings_('G',_3) 1 + UP bnd possible_seatings_('H',_3) 1 + UP bnd possible_seatings_('I',_3) 1 + UP bnd possible_seatings_('J',_3) 1 + UP bnd possible_seatings_('K',_3) 1 + UP bnd possible_seatings_('L',_3) 1 + UP bnd possible_seatings_('M',_3) 1 + UP bnd possible_seatings_('N',_3) 1 + UP bnd possible_seatings_('O',_3) 1 + UP bnd possible_seatings_('P',_3) 1 + UP bnd possible_seatings_('A',_4) 1 + UP bnd possible_seatings_('B',_4) 1 + UP bnd possible_seatings_('C',_4) 1 + UP bnd possible_seatings_('D',_4) 1 + UP bnd possible_seatings_('E',_4) 1 + UP bnd possible_seatings_('F',_4) 1 + UP bnd possible_seatings_('G',_4) 1 + UP bnd possible_seatings_('H',_4) 1 + UP bnd possible_seatings_('I',_4) 1 + UP bnd possible_seatings_('J',_4) 1 + UP bnd possible_seatings_('K',_4) 1 + UP bnd possible_seatings_('L',_4) 1 + UP bnd possible_seatings_('M',_4) 1 + UP bnd possible_seatings_('N',_4) 1 + UP bnd possible_seatings_('O',_4) 1 + UP bnd possible_seatings_('P',_4) 1 +ENDATA diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/10teams.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/10teams.gz new file mode 100644 index 000000000..dd91f23ec Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/10teams.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air03.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air03.gz new file mode 100644 index 000000000..0f2795bea Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air03.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air04.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air04.gz new file mode 100644 index 000000000..3fb351162 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air04.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air05.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air05.gz new file mode 100644 index 000000000..00475066d Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/air05.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/arki001.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/arki001.gz new file mode 100644 index 000000000..4ded81ca9 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/arki001.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell3a.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell3a.gz new file mode 100644 index 000000000..4cbde84b8 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell3a.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell5.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell5.gz new file mode 100644 index 000000000..63739d20d Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/bell5.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/blend2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/blend2.gz new file mode 100644 index 000000000..03c528dc7 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/blend2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/cap6000.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/cap6000.gz new file mode 100644 index 000000000..db577acbd Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/cap6000.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dano3mip.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dano3mip.gz new file mode 100644 index 000000000..4b2dd9ef8 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dano3mip.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/danoint.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/danoint.gz new file mode 100644 index 000000000..1222df58a Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/danoint.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dcmulti.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dcmulti.gz new file mode 100644 index 000000000..bdd11d1e3 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dcmulti.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dsbmip.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dsbmip.gz new file mode 100644 index 000000000..c1809ce0c Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/dsbmip.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/egout.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/egout.gz new file mode 100644 index 000000000..132e6f45b Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/egout.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/enigma.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/enigma.gz new file mode 100644 index 000000000..c0de0aca8 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/enigma.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fast0507.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fast0507.gz new file mode 100644 index 000000000..43d461f6a Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fast0507.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fiber.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fiber.gz new file mode 100644 index 000000000..a02ccc200 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fiber.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fixnet6.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fixnet6.gz new file mode 100644 index 000000000..a6c57aff8 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/fixnet6.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/flugpl.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/flugpl.gz new file mode 100644 index 000000000..351b9b3c3 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/flugpl.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gen.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gen.gz new file mode 100644 index 000000000..e38d85c5f Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gen.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2.gz new file mode 100644 index 000000000..b5f79f2c7 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2_o.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2_o.gz new file mode 100644 index 000000000..8155e2545 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa2_o.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3.gz new file mode 100644 index 000000000..ca9c6475b Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3_o.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3_o.gz new file mode 100644 index 000000000..68de10de4 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gesa3_o.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gt2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gt2.gz new file mode 100644 index 000000000..bce013c9e Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/gt2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/harp2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/harp2.gz new file mode 100644 index 000000000..c526a50a4 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/harp2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/khb05250.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/khb05250.gz new file mode 100644 index 000000000..48ff07cd5 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/khb05250.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/l152lav.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/l152lav.gz new file mode 100644 index 000000000..d7e743555 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/l152lav.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/lseu.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/lseu.gz new file mode 100644 index 000000000..b7b175054 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/lseu.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare1.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare1.gz new file mode 100644 index 000000000..a6c13491e Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare1.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare2.gz new file mode 100644 index 000000000..456766880 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/markshare2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas74.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas74.gz new file mode 100644 index 000000000..ca026b672 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas74.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas76.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas76.gz new file mode 100644 index 000000000..2276aa5b8 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mas76.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/miplib3.cat b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/miplib3.cat new file mode 100644 index 000000000..5472c836e --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/miplib3.cat @@ -0,0 +1,332 @@ +This catalogue contains a three-part index of the models contained in +miplib, along with information on how to access the files. The first part +of the index reports statistics for each problem, the second gives +information regarding the origins of each problem, and the third +distinguishes the types of constraints in each problem. Instructions for +accessing the problems, as well as, how to make submissions are given +following the index. + +Please note that at the beginning of each problem file there is a header +section that gives a little more information about that problem than is +contained here. Following the header in each file is the problem data, +stored in MPS format. The file mps_format, which contains more information +on the MPS format, should be consulted before obtaining these problems. A +list of references that make reference to various problems in MIPLIB can +be found in the file references. + +INDEX - PART A : STATISTICS +=========================== + NAME ROWS COLS INT 0/1 CONT INT SOLN LP SOLN + ==== ==== ==== === === ==== ======== ======= + 10teams 230 2025 1800 ALL 225 924 917 + air03 124 10757 10757 ALL 0 340160 338864.25 + air04 823 8904 8904 ALL 0 56137 55535.436 + air05 426 7195 7195 ALL 0 26374 25877.609 + arki001 1048 1388 538 415 850 7580813.0459 7579599.80787 + (not opt) + bell3a 123 133 71 39 62 878430.32 862578.64 + bell5 91 104 58 30 46 8966406.49 8608417.95 + blend2 274 353 264 231 89 7.598985 6.9156751140 + cap6000 2176 6000 6000 ALL 0 -2451377 -2451537.325 + dano3mip 3202 13873 552 ALL 13321 728.1111 576.23162474 + (not opt) + danoint 664 521 56 ALL 465 65.67 62.637280418 + dcmulti 290 548 75 ALL 473 188182 183975.5397 + dsbmip 1182 1886 192 160 1694 -305.19817501 -305.19817501 + egout 98 141 55 ALL 86 568.101 149.589 + enigma 21 100 100 ALL 0 0.0 0.0 + fast0507 507 63009 63009 ALL 0 174 172.14556668 + fiber 363 1298 1254 ALL 44 405935.18000 156082.51759 + fixnet6 478 878 378 ALL 500 3983 1200.88 + flugpl 18 18 11 0 7 1201500 1167185.73 + gen 780 870 150 144 720 112313 112130.0 + gesa2 1392 1224 408 240 816 25779856.372 25476489.678 + gesa2_o 1248 1224 720 384 504 25779856.372 25476489.678 + gesa3 1368 1152 384 216 768 27991042.648 27833632.451 + gesa3_o 1224 1152 672 336 480 27991042.648 27833632.451 + gt2 29 188 188 24 0 21166.000 13460.233074 + harp2 112 2993 2993 ALL 0 -73899798.00 -74353341.502 + khb05250 101 1350 24 ALL 1326 106940226 95919464.0 + l152lav 97 1989 1989 ALL 0 4722 4656.36 + lseu 28 89 89 ALL 0 1120 834.68 +markshare1 6 62 50 ALL 12 1 0 +markshare2 7 74 60 ALL 14 1 0 + mas74 13 151 150 ALL 1 11801.1857 10482.795280 + mas76 12 151 150 ALL 1 4005.1 38893.903641 + misc03 96 160 159 ALL 1 3360 1910.0 + misc06 820 1808 112 ALL 1696 12850.8607 12841.69 + misc07 212 260 259 ALL 1 2810 1415.0 + mitre 2054 10724 10724 ALL 0 115155 114740.51848 + mkc 3411 5325 5323 ALL 2 -553.75 -611.85000000 + (not opt) + mod008 6 319 319 ALL 0 307 290.93 + mod010 146 2655 2655 ALL 0 6548 6532.08 + mod011 4480 10958 96 ALL 10862 -54558535 -62121982.552 + modglob 291 422 98 ALL 324 20740508 20430947.0 + noswot 182 128 100 75 28 -43 -43.0 + nw04 36 87482 87482 ALL 0 16862 16310.66667 + p0033 16 33 33 ALL 0 3089 2520.57 + p0201 133 201 201 ALL 0 7615 6875.0 + p0282 241 282 282 ALL 0 258411 176867.50 + p0548 176 548 548 ALL 0 8691 315.29 + p2756 755 2756 2756 ALL 0 3124 2688.75 + pk1 45 86 55 ALL 31 11.0 0.0 + pp08a 136 240 64 ALL 176 7350.0 2748.3452381 + pp08aCUTS 246 240 64 ALL 176 7350.0 5480.6061563 + qiu 1192 840 48 ALL 792 -132.873137 -931.638857 + qnet1 503 1541 1417 1288 124 16029.692681 14274.102667 + qnet1_o 456 1541 1417 1288 124 16029.692681 12095.571667 + rentacar 6803 9557 55 ALL 9502 30356761 28806137.644 + rgn 24 180 100 ALL 80 82.1999 48.7999 + rout 291 556 315 300 241 1077.56 981.86428571 + set1ch 492 712 240 ALL 472 54537.75 32007.73 + seymour 4944 1372 1372 ALL 0 423 403.84647413 + (not opt) + stein27 118 27 27 ALL 0 18 13.0 + stein45 331 45 45 ALL 0 30 22.0 + swath 884 6805 6724 ALL 81 497.603 334.4968581 + (not opt) + vpm1 234 378 168 ALL 210 20 15.4167 + vpm2 234 378 168 ALL 210 13.75 9.8892645972 + + +Explanation of columns: +NAME - name of the problem +ROWS - number of constraints in the problem, not including free rows +COLS - total number of variables in the problem +INT - number of variables that are integer +0/1 - number of integer variables that are binary +INT SOLUTION - best known integer solution to the problem, along with a + parenthetic qualifier: + (not opt) indicates that the given solution is not integer + optimal + +LP SOLUTION - optimal solution to the linear relaxation of the problem + +INDEX - PART B : ORIGINS +======================== +NAME ORIGINATOR FORMULATOR DONATOR +==== ========== ========== ======= +10teams Dash Associates Bob Daniel +air03 Greg Astfalk +air04 Greg Astfalk +air05 Greg Astfalk +arki001 Avesta-Sheffield, Nils Holmberg Arne Stolbjerg Drud + Sweden +bell3a William Cook William Cook William Cook +bell5 William Cook William Cook William Cook +blend2 Dash Associates Bob Daniel +cap6000 Karla Hoffman, Telecommunications Karla Hoffman + Manfred Padberg Corporation +dano3mip Bell Communications Daniel Bienstock + Research +danoint Columbia's Center for Daniel Bienstock + Telecommunications + Research +dcmulti Jeremy Shapiro Jeremy Shapiro Jonathan Eckstein +dsbmip John J. Forrest +egout Etienne Loute Laurence A. Wolsey Martin Savelsbergh +enigma Harlan Crowder Harlan Crowder E. Andrew Boyd +fast0507 Italian Railway Pier Luigi Guida Sebastian Ceria + Company +fiber US West Youngho Lee Martin Savelsbergh +fixnet6 T. J. Van Roy Martin Savelsbergh +flugpl Harvey M. Wagner John W. Gregory E. Andrew Boyd +gesa2 Spanish Electricity Laurence A. Wolsey Sebastian Ceria +gesa2_o Spanish Electricity GESA (Consulting Sebastian Ceria + Company) +gesa3 Spanish Electricity Laurence A. Wolsey Sebastian Ceria +gesa3_o Spanish Electricity GESA (Consulting Sebastian Ceria + Company) +gen Laurence A. Wolsey Martin Savelsbergh +gt2 Sebastian Ceria +harp2 Martin Savelsbergh +khb05250 Kuhn-Hamburger Laurence A. Wolsey Martin Savelsbergh +l152lav Harlan Crowder Harlan Crowder John W. Gregory +lseu C. E. Lemke, Ellis L. Johnson, John J. Forrest + K. Spielberg Uwe H. Suhl +markshare1 Gerard Cornuejols Gerard Cornuejols Milind Dawande + Milind Dawande Milind Dawande +markshare2 Gerard Cornuejols Gerard Cornuejols Milind Dawande + Milind Dawande Milind Dawande +mas74 Undisclosed Undisclosed Jonathan Eckstein +mas76 Undisclosed Undisclosed Jonathan Eckstein +misc03 Greg Astfalk +misc06 Greg Astfalk +misc07 Greg Astfalk +mitre Martin Savelsbergh +mkc Jayant Kalagnanam Jayant Kalagnanam Jayant Kalagnanam + Milind Dawande Milind Dawande Milind Dawande +mod008 IBM France IBM France John J. Forrest +mod010 IBM Yorktown Hts IBM Yorktown Hts John J. Forrest +mod011 Uwe H. Suhl Uwe H. Suhl John J. Forrest +modglob Y. Smeers Laurence A. Wolsey Martin Savelsbergh +noswot Linus E. Schrage John W. Gregory +nw04 Northwest Airlines Karla Hoffman +p0033 CJP set E. Andrew Boyd +p0201 CJP set E. Andrew Boyd +p0282 CJP set E. Andrew Boyd +p0548 CJP set Ellis L. Johnson E. Andrew Boyd +p2756 CJP set Ellis L. Johnson E. Andrew Boyd +pk1 Pinar Keskinocak Sebastian Ceria +pp08a Martin Savelsbergh +pp08aCUTS Martin Savelsbergh +qiu Yu-Ping Chiu Yu-Ping Chiu Jonathan Eckstein +qnet1 BASF Laurence A. Wolsey Sebastian Ceria +qnet1_o BASF BASF Sebastian Ceria +rentacar John J. Forrest +rgn Linus E. Schrage Laurence A. Wolsey Martin Savelsbergh +rout S. Graves Hernan Abeledo Sebastian Ceria +set1ch Laurence A. Wolsey Martin Savelsbergh +seymour Paul Seymour +stein27 George L. Nemhauser John W. Gregory E. Andrew Boyd +stein45 George L. Nemhauser John W. Gregory E. Andrew Boyd +swath Undisclosed David Panton David Panton +vpm1 Laurence A. Wolsey Martin Savelsbergh +vpm2 Laurence A. Wolsey Martin Savelsbergh + + +Explanation of columns: +NAME - name of the problem +ORIGINATOR - name of the person or institution with whom the problem originated +FORMULATOR - name of the person or institution who formulated the MIP +DONATOR - name of the person who contributed the problem + +NOTE : "CJP set" indicates Crowder-Johnson-Padberg test set + + + + +INDEX - PART C: CCONSTRAINT CLASSIFICATION +=========================================== +NAME | G | K | E | F | I | P | C | S | U | L | +=================================================================== +10teams | 110 | | | | | 40 | | 80| | | +air03 | | | | | | | | 124| | | +air04 | | | | | | | | 823| | | +air05 | | | | | | | | 426| | | +arki001 | 1027 | 13 | | | 6 | 2 | | | | | +bell3a | 101 | | | | | 22 | | | | | +bell5 | 76 | | | | | 15 | | | | | +blend2 | 93 | | | | 79 | | 9 | | 88 | | +cap6000 | | 7 | | | |2046| | 123| | | +------------------------------------------------------------------| +dano3mip | 2518 | | | | | | | | 606| 30 | +danoint | 256 | | | | | | | | 392| | +dcmulti | 165 | | | | | 22 | 10 | | 45 | 45 | +dsbmip | 1142 | | | | | | | 40 | | | +egout | 43 | | | | | | | | 55 | | +enigma | | | 1 | | | | | 20 | | | +fast0507 | | | | | | 3 | 504| | | | +fiber | 44 | | | | | | | 90 | | | +fixnet6 | 100 | | | | | | | | 378| | +flugpl | 18 | | | | | | | | | | +------------------------------------------------------------------| +gen | 318 | 24 | | | | | | | 432| 6 | +gesa2 | 912 | | | | | 14 | | | 288| 144| +gesa2_o | 624 | | | | | 48 | 144| | 288| 144| +gesa3 | 936 | | | | | 48 | | | 264| 120| +gesa3_o | 672 | | | | | 48 | 120| | 264| 120| +gt2 | 27 | | | | | 2 | | | | | +harp2 | | 30 | | 9 | | | | 73 | | | +khb05250 | 77 | | | | | | | | 24 | | +l152lav | | 1 | | | | | | 95 | | | +------------------------------------------------------------------| +lseu | | 11 | | | | 17 | | | | | +markshare1 | 6 | | | | | | | | | | +markshare2 | 7 | | | | | | | | | | +mas74 | 12 | | | | 1 | | | | | | +mas76 | 11 | | | | 1 | | | | | | +misc03 | 1 | 3 | | 2 | 30 | 3 | 31 | 5 | | | +misc06 | 820 | | | | | | | | | | +misc07 | 1 | 3 | | 2 | 42 | 3 | 127| 7 | | | +mitre | | 383| | |1148| | 140| 383| | | +mkc | 2 | | | 24 | 24 |3361| | | | | +mod008 | | 6 | | | | | | | | | +mod010 | | 1 | | | | | | 144| | | +mod011 | 4400 | | | | | | | 16 | 64 | | +modglob | 95 | | | | | | | | 196| | +noswot | 137 | | | | | | | | 20 | 25 | +------------------------------------------------------------------| +nw04 | | | | | | | | 36 | | | +p0033 | | 11 | | | | 4 | | | | | +p0201 | | 33 | | | 54 | 26 | 20 | | | | +p0282 | | 64 | | | | 177| | | | | +p0548 | | 112| | | | 64 | | | | | +p2756 | | 403| | | | 352| | | | | +pk1 | 45 | | | | | | | | | | +pp08a | 72 | | | | | | | | 64 | | +pp08aCUTS | 182 | | | | | | | | 64 | | +qiu | 664 | | | | | | | | 528| | +------------------------------------------------------------------| +qnet1 | 178 | | | 32 | | 4 | 4 | 48 | | 45 | +qnet1_o | 152 | | | 32 | | | | 48 | | 32 | +rentacar | 6674 | | | | | | | | 55 | 55 | +rgn | 20 | | | | | 4 | | | | | +rout | 47 | | | | | 14 | | | 230| | +set1ch | 252 | | | | | | | | 240| | +seymour | | | | | | 285|4659| | | | +stein27 | | | | | 1 | | 117| | | | +stein45 | | | | | 1 | 1 | 329| | | | +swath | 381 | | | | 80 | | |423 | | | +vpm1 | 66 | | | | | | | | 168| | +vpm2 | 66 | | | | | | | | 168| | +------------------------------------------------------------------- + +Explanation of columns: + G-- General + K-- Knapsack + E-- Equality Knapsack + F-- Facility Location + I-- Invariant Knapsack + P-- Packing + C-- Covering + S-- Special Ordered Set + U-- Variable Upper Bound + L-- Variable Lower Bound + +HOW TO ACCESS FILES +=================== +The files are available by anonymous ftp to ftp.caam.rice.edu. Login +as "anonymous" using your e-mail address for the password. Once you are +logged in, switch to the directory "pub/people/bixby/miplib", and +retrieve the files with the "get" command. For example to retrieve a +specific problem from MIPLIB 3.0: + + % ftp ftp.caam.rice.edu + Connected to ftp.caam.rice.edu. + 220 www.caam.rice.edu FTP server + (Version wu-2.4(11) Tue Sep 26 17:27:38 CDT 1995) ready. + Name (ftp.caam:cmoore): anonymous + 331 Guest login ok, send ident as password. + Password: + 230 Guest login ok, access restrictions apply. + ftp> cd pub/people/bixby/miplib/miplib3 + ftp> ls + ftp> get +Again, here denotes the name of the problem whose file you want to +get. + +HOW TO SUBMIT PROBLEMS +====================== +Files can be submitted via anonymous ftp to ftp.caam.rice.edu.Login as +"anonymous" using your e-mail address for the password. Once you are +logged in, switch to the directory "/pub/people/bixby/incoming/bixplex", +and place the files with the "put" command. For example: + + % ftp ftp.caam.rice.edu + Connected to ftp.caam.rice.edu. + 220 www.caam.rice.edu FTP server + (Version wu-2.4(11) Tue Sep 26 17:27:38 CDT 1995) ready. + Name (ftp.caam:cmoore): anonymous + 331 Guest login ok, send ident as password. + Password: + 230 Guest login ok, access restrictions apply. + ftp> cd /pub/people/bixby/incoming/bixplex + ftp> put +Again, here denotes the name of the problem whose file you want to +put. + +The submission should be accompanied by an e-mail message to miplib@rice.edu +containing information about the origin of the instance, the optimal +solution (if known), and the way the optimal solution was obtained. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc03.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc03.gz new file mode 100644 index 000000000..4ead74efa Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc03.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc06.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc06.gz new file mode 100644 index 000000000..95233605d Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc06.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc07.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc07.gz new file mode 100644 index 000000000..436e4684e Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/misc07.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mitre.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mitre.gz new file mode 100644 index 000000000..2b794db96 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mitre.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mkc.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mkc.gz new file mode 100644 index 000000000..6360e1915 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mkc.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod008.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod008.gz new file mode 100644 index 000000000..46d10f63f Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod008.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod010.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod010.gz new file mode 100644 index 000000000..fe01c51c7 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod010.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod011.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod011.gz new file mode 100644 index 000000000..99fea8556 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/mod011.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/modglob.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/modglob.gz new file mode 100644 index 000000000..5dee3f61b Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/modglob.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/noswot.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/noswot.gz new file mode 100644 index 000000000..29db88cbd Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/noswot.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/nw04.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/nw04.gz new file mode 100644 index 000000000..8b35194c9 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/nw04.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0033.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0033.gz new file mode 100644 index 000000000..c2f06a47b Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0033.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0201.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0201.gz new file mode 100644 index 000000000..009c7dfed Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0201.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0282.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0282.gz new file mode 100644 index 000000000..6c46a16af Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0282.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0548.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0548.gz new file mode 100644 index 000000000..45ff59515 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p0548.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p2756.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p2756.gz new file mode 100644 index 000000000..9215805a3 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/p2756.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pk1.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pk1.gz new file mode 100644 index 000000000..edf694d9a Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pk1.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08a.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08a.gz new file mode 100644 index 000000000..8fc3b488d Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08a.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08aCUTS.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08aCUTS.gz new file mode 100644 index 000000000..f7c3467ee Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/pp08aCUTS.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qiu.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qiu.gz new file mode 100644 index 000000000..6afe99b93 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qiu.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1.gz new file mode 100644 index 000000000..e63b4b421 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1_o.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1_o.gz new file mode 100644 index 000000000..9a0fade2e Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/qnet1_o.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rentacar.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rentacar.gz new file mode 100644 index 000000000..6160fb447 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rentacar.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rgn.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rgn.gz new file mode 100644 index 000000000..a7b1b3aed Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rgn.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rout.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rout.gz new file mode 100644 index 000000000..9fc3352ac Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/rout.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/set1ch.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/set1ch.gz new file mode 100644 index 000000000..b6986b974 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/set1ch.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/seymour.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/seymour.gz new file mode 100644 index 000000000..29af24628 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/seymour.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein27.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein27.gz new file mode 100644 index 000000000..18e6fa211 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein27.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein45.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein45.gz new file mode 100644 index 000000000..97b91a52c Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/stein45.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/swath.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/swath.gz new file mode 100644 index 000000000..cb54160fd Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/swath.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm1.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm1.gz new file mode 100644 index 000000000..900d831e3 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm1.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm2.gz b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm2.gz new file mode 100644 index 000000000..deb1c34b2 Binary files /dev/null and b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/Data/miplib3/vpm2.gz differ diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/AUTHORS b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/AUTHORS new file mode 100644 index 000000000..7e02a48dc --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/AUTHORS @@ -0,0 +1,3 @@ +Forrest, John J. +Hafer, Lou +Goncalves, Joao P.: Diving heuristics \ No newline at end of file diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/LICENSE new file mode 100644 index 000000000..744d6f3db --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/LICENSE @@ -0,0 +1,239 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION +OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate + from and are distributed by that particular Contributor. A + Contribution 'originates' from a Contributor if it was added to + the Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to + the Program which: (i) are separate modules of software + distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the + Program. + +"Contributor" means any person or entity that distributes the +Program. + +"Licensed Patents" mean patent claims licensable by a Contributor +which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with +this Agreement. + +"Recipient" means anyone who receives the Program under this +Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright +license to reproduce, prepare derivative works of, publicly display, +publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and +object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent +license under Licensed Patents to make, use, sell, offer to sell, +import and otherwise transfer the Contribution of such Contributor, +if any, in source code and object code form. This patent license +shall apply to the combination of the Contribution and the Program +if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per +se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient for +claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient +hereby assumes sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow Recipient to distribute the Program, it +is Recipient's responsibility to acquire that license before +distributing the Program. + +d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; + and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not by + any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to obtain + it in a reasonable manner on or through a medium customarily + used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and +the like. While this license is intended to facilitate the +commercial use of the Program, the Contributor who includes the +Program in a commercial product offering should do so in a manner +which does not create potential liability for other +Contributors. Therefore, if a Contributor includes the Program in a +commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the +Program in a commercial product offering. The obligations in this +section do not apply to any claims or Losses relating to any actual +or alleged intellectual property infringement. In order to qualify, +an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial +Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any +such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's +responsibility alone. Under this section, the Commercial Contributor +would have to defend claims against the other Contributors related +to those performance claims and warranties, and if a court requires +any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient +is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with +its exercise of rights under this Agreement , including but not +limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, +and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability +of the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that +the Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then +such Recipient's rights granted under Section 2(b) shall terminate +as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably +practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions +(including revisions) of this Agreement from time to time. No one +other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement +Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each +new version of the Agreement will be given a distinguishing version +number. The Program (including Contributions) may always be +distributed subject to the version of the Agreement under which it +was received. In addition, after a new version of the Agreement is +published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly +granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No +party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each +party waives its rights to a jury trial in any resulting litigation. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/cbc_addlibs.txt b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/cbc_addlibs.txt new file mode 100644 index 000000000..60cf79738 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cbc/cbc_addlibs.txt @@ -0,0 +1 @@ +-L/home/runner/work/Cbc/Cbc/dist/lib -lCbcSolver -lCbc -L/usr/lib/ -lnauty -lCgl -lOsiClp -lClpSolver -lClp -lOsi -lCoinUtils -lbz2 -lz -llapack -lgfortran -lquadmath -lblas -lm diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/AUTHORS b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/AUTHORS new file mode 100644 index 000000000..99d13f714 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/AUTHORS @@ -0,0 +1,100 @@ +CglAllDifferrent + John Forrest - contributor & PM + +CglClique & CliqueHelper + JP Fasano + John Forrest + Lazlo Ladanyi - PM + Marta Eso - contributor + +CglCutGenerator + John Forrest - contributor & PM + +CglDuplicateRow + John Forrest - contributor & PM + +CglFlowCover & FlowCoverTest + John Forrest + Laszlo Ladani + Yan Xu - contributor & PM + Jeff Linderoth - contributor + Martin Savelsbergh - contributor + +CglGMI + John Forrest - PM + A more robust Gomory + Giacomo Nannicini - contributor + +CglGomory & GomoryTest + JP Fasano + John Forrest - contributor & PM + Laszlo Ladanyi - contributor + +CglKnapsackCover + John Forrest + Laszlo Ladanyi + Robin Lougee - contributor & PM + +CglLandP + Pierre Bonami - contributor & PM + +CglLiftAndProject + John Forrest + Laszlo Ladanyi + Robin Lougee - contributor & PM + +CglMessage + John Forrest - contributor & PM + +CglMixedIntegerRounding + John Forrest + Laszlo Ladanyi - contributor + Joao Goncalves - contributor & PM + +CglMixedIntegerRounding2 + John Forrest - contributor & PM + +CglOddHole + John Forrest - contributor & PM + Laszlo Ladanyi + +CglPreProcess + John Forrest - contributor & PM + +CglProbing & Probing Test + JP Fasano + John Forrest - contributor & PM + Laszlo Ladanyi + +CglRedSplit + John Forrest + JP Fasano + Francois Margot - contributor & PM + +CglRedSplit2 + John Forrest - PM + Based on CglRedSplit + Giacomo Nannicini - contributor + +CglResidualCapacity + Francisco Barahona - contributor & PM + +CglSimpleRounding + John Forrest + Laszlo Ladanyi + Robin Lougee - contributor & PM + +CglStored + John Forrest - contributor & PM + +CglTwomir + JP Fasano + John Forrest + Oktay Gunluk - contributor & PM + Laszlo Ladanyi + Sanjeeb Dash - contributor + Marcos Goycoolea - contributor + +CglZeroHalf + Alberto Caprara - contributor + John Forrest - PM diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/LICENSE new file mode 100644 index 000000000..744d6f3db --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/LICENSE @@ -0,0 +1,239 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION +OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate + from and are distributed by that particular Contributor. A + Contribution 'originates' from a Contributor if it was added to + the Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to + the Program which: (i) are separate modules of software + distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the + Program. + +"Contributor" means any person or entity that distributes the +Program. + +"Licensed Patents" mean patent claims licensable by a Contributor +which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with +this Agreement. + +"Recipient" means anyone who receives the Program under this +Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright +license to reproduce, prepare derivative works of, publicly display, +publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and +object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent +license under Licensed Patents to make, use, sell, offer to sell, +import and otherwise transfer the Contribution of such Contributor, +if any, in source code and object code form. This patent license +shall apply to the combination of the Contribution and the Program +if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per +se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient for +claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient +hereby assumes sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow Recipient to distribute the Program, it +is Recipient's responsibility to acquire that license before +distributing the Program. + +d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; + and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not by + any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to obtain + it in a reasonable manner on or through a medium customarily + used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and +the like. While this license is intended to facilitate the +commercial use of the Program, the Contributor who includes the +Program in a commercial product offering should do so in a manner +which does not create potential liability for other +Contributors. Therefore, if a Contributor includes the Program in a +commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the +Program in a commercial product offering. The obligations in this +section do not apply to any claims or Losses relating to any actual +or alleged intellectual property infringement. In order to qualify, +an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial +Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any +such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's +responsibility alone. Under this section, the Commercial Contributor +would have to defend claims against the other Contributors related +to those performance claims and warranties, and if a court requires +any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient +is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with +its exercise of rights under this Agreement , including but not +limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, +and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability +of the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that +the Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then +such Recipient's rights granted under Section 2(b) shall terminate +as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably +practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions +(including revisions) of this Agreement from time to time. No one +other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement +Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each +new version of the Agreement will be given a distinguishing version +number. The Program (including Contributions) may always be +distributed subject to the version of the Agreement under which it +was received. In addition, after a new version of the Agreement is +published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly +granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No +party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each +party waives its rights to a jury trial in any resulting litigation. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/cgl_addlibs.txt b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/cgl_addlibs.txt new file mode 100644 index 000000000..425856fbb --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Cgl/cgl_addlibs.txt @@ -0,0 +1 @@ +-L/home/runner/work/Cbc/Cbc/dist/lib -lCgl -lOsiClp -lClpSolver -lClp -lOsi -lCoinUtils -lbz2 -lz -llapack -lgfortran -lquadmath -lblas -lm diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/AUTHORS b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/AUTHORS new file mode 100644 index 000000000..df3361a7a --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/AUTHORS @@ -0,0 +1 @@ +Forrest, John J. \ No newline at end of file diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/LICENSE new file mode 100644 index 000000000..744d6f3db --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/LICENSE @@ -0,0 +1,239 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION +OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate + from and are distributed by that particular Contributor. A + Contribution 'originates' from a Contributor if it was added to + the Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to + the Program which: (i) are separate modules of software + distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the + Program. + +"Contributor" means any person or entity that distributes the +Program. + +"Licensed Patents" mean patent claims licensable by a Contributor +which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with +this Agreement. + +"Recipient" means anyone who receives the Program under this +Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright +license to reproduce, prepare derivative works of, publicly display, +publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and +object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent +license under Licensed Patents to make, use, sell, offer to sell, +import and otherwise transfer the Contribution of such Contributor, +if any, in source code and object code form. This patent license +shall apply to the combination of the Contribution and the Program +if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per +se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient for +claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient +hereby assumes sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow Recipient to distribute the Program, it +is Recipient's responsibility to acquire that license before +distributing the Program. + +d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; + and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not by + any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to obtain + it in a reasonable manner on or through a medium customarily + used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and +the like. While this license is intended to facilitate the +commercial use of the Program, the Contributor who includes the +Program in a commercial product offering should do so in a manner +which does not create potential liability for other +Contributors. Therefore, if a Contributor includes the Program in a +commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the +Program in a commercial product offering. The obligations in this +section do not apply to any claims or Losses relating to any actual +or alleged intellectual property infringement. In order to qualify, +an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial +Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any +such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's +responsibility alone. Under this section, the Commercial Contributor +would have to defend claims against the other Contributors related +to those performance claims and warranties, and if a court requires +any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient +is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with +its exercise of rights under this Agreement , including but not +limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, +and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability +of the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that +the Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then +such Recipient's rights granted under Section 2(b) shall terminate +as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably +practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions +(including revisions) of this Agreement from time to time. No one +other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement +Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each +new version of the Agreement will be given a distinguishing version +number. The Program (including Contributions) may always be +distributed subject to the version of the Agreement under which it +was received. In addition, after a new version of the Agreement is +published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly +granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No +party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each +party waives its rights to a jury trial in any resulting litigation. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/clp_addlibs.txt b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/clp_addlibs.txt new file mode 100644 index 000000000..82ca36ac2 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Clp/clp_addlibs.txt @@ -0,0 +1 @@ +-L/home/runner/work/Cbc/Cbc/dist/lib -lClpSolver -lClp -lCoinUtils -lbz2 -lz -llapack -lgfortran -lquadmath -lblas -lm diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/AUTHORS b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/AUTHORS new file mode 100644 index 000000000..a308b3f61 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/AUTHORS @@ -0,0 +1,8 @@ +This file is last updated on 11/21/2008 +Fasano, J.P. +Forrest, John J. +Hafer, Lou +Ladanyi, Laszlo +Margot, Francois +Tomlin, John +Waechter, Andreas diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/LICENSE new file mode 100644 index 000000000..744d6f3db --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/LICENSE @@ -0,0 +1,239 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION +OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate + from and are distributed by that particular Contributor. A + Contribution 'originates' from a Contributor if it was added to + the Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to + the Program which: (i) are separate modules of software + distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the + Program. + +"Contributor" means any person or entity that distributes the +Program. + +"Licensed Patents" mean patent claims licensable by a Contributor +which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with +this Agreement. + +"Recipient" means anyone who receives the Program under this +Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright +license to reproduce, prepare derivative works of, publicly display, +publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and +object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent +license under Licensed Patents to make, use, sell, offer to sell, +import and otherwise transfer the Contribution of such Contributor, +if any, in source code and object code form. This patent license +shall apply to the combination of the Contribution and the Program +if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per +se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient for +claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient +hereby assumes sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow Recipient to distribute the Program, it +is Recipient's responsibility to acquire that license before +distributing the Program. + +d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; + and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not by + any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to obtain + it in a reasonable manner on or through a medium customarily + used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and +the like. While this license is intended to facilitate the +commercial use of the Program, the Contributor who includes the +Program in a commercial product offering should do so in a manner +which does not create potential liability for other +Contributors. Therefore, if a Contributor includes the Program in a +commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the +Program in a commercial product offering. The obligations in this +section do not apply to any claims or Losses relating to any actual +or alleged intellectual property infringement. In order to qualify, +an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial +Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any +such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's +responsibility alone. Under this section, the Commercial Contributor +would have to defend claims against the other Contributors related +to those performance claims and warranties, and if a court requires +any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient +is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with +its exercise of rights under this Agreement , including but not +limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, +and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability +of the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that +the Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then +such Recipient's rights granted under Section 2(b) shall terminate +as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably +practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions +(including revisions) of this Agreement from time to time. No one +other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement +Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each +new version of the Agreement will be given a distinguishing version +number. The Program (including Contributions) may always be +distributed subject to the version of the Agreement under which it +was received. In addition, after a new version of the Agreement is +published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly +granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No +party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each +party waives its rights to a jury trial in any resulting litigation. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/coinutils_addlibs.txt b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/coinutils_addlibs.txt new file mode 100644 index 000000000..416c7b418 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/CoinUtils/coinutils_addlibs.txt @@ -0,0 +1 @@ +-L/home/runner/work/Cbc/Cbc/dist/lib -lCoinUtils -lbz2 -lz -llapack -lgfortran -lquadmath -lblas -lm diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/AUTHORS b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/AUTHORS new file mode 100644 index 000000000..0495c1f59 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/AUTHORS @@ -0,0 +1,9 @@ +Fasano, J.P. +Forrest, John J. +Hafer, Lou +Ladanyi, Laszlo +Lannez, Sebastien (OsiCuts insert method) +Margot, Francois +Saltzman, Matt +Ralphs, Ted +Walton, Philip (trait specification of OsiCuts) diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/LICENSE b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/LICENSE new file mode 100644 index 000000000..744d6f3db --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/LICENSE @@ -0,0 +1,239 @@ +Eclipse Public License - v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE +PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION +OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + + where such changes and/or additions to the Program originate + from and are distributed by that particular Contributor. A + Contribution 'originates' from a Contributor if it was added to + the Program by such Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include additions to + the Program which: (i) are separate modules of software + distributed in conjunction with the Program under their own + license agreement, and (ii) are not derivative works of the + Program. + +"Contributor" means any person or entity that distributes the +Program. + +"Licensed Patents" mean patent claims licensable by a Contributor +which are necessarily infringed by the use or sale of its +Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with +this Agreement. + +"Recipient" means anyone who receives the Program under this +Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright +license to reproduce, prepare derivative works of, publicly display, +publicly perform, distribute and sublicense the Contribution of such +Contributor, if any, and such derivative works, in source code and +object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent +license under Licensed Patents to make, use, sell, offer to sell, +import and otherwise transfer the Contribution of such Contributor, +if any, in source code and object code form. This patent license +shall apply to the combination of the Contribution and the Program +if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered +by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per +se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are +provided by any Contributor that the Program does not infringe the +patent or other intellectual property rights of any other +entity. Each Contributor disclaims any liability to Recipient for +claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient +hereby assumes sole responsibility to secure any other intellectual +property rights needed, if any. For example, if a third party patent +license is required to allow Recipient to distribute the Program, it +is Recipient's responsibility to acquire that license before +distributing the Program. + +d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant +the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code +form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; + and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, and + implied warranties or conditions of merchantability and + fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, special, + incidental and consequential damages, such as lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not by + any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to obtain + it in a reasonable manner on or through a medium customarily + used for software exchange. + +When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + +Contributors may not remove or alter any copyright notices contained +within the Program. + +Each Contributor must identify itself as the originator of its +Contribution, if any, in a manner that reasonably allows subsequent +Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain +responsibilities with respect to end users, business partners and +the like. While this license is intended to facilitate the +commercial use of the Program, the Contributor who includes the +Program in a commercial product offering should do so in a manner +which does not create potential liability for other +Contributors. Therefore, if a Contributor includes the Program in a +commercial product offering, such Contributor ("Commercial +Contributor") hereby agrees to defend and indemnify every other +Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and +other legal actions brought by a third party against the Indemnified +Contributor to the extent caused by the acts or omissions of such +Commercial Contributor in connection with its distribution of the +Program in a commercial product offering. The obligations in this +section do not apply to any claims or Losses relating to any actual +or alleged intellectual property infringement. In order to qualify, +an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial +Contributor to control, and cooperate with the Commercial +Contributor in, the defense and any related settlement +negotiations. The Indemnified Contributor may participate in any +such claim at its own expense. + +For example, a Contributor might include the Program in a commercial +product offering, Product X. That Contributor is then a Commercial +Contributor. If that Commercial Contributor then makes performance +claims, or offers warranties related to Product X, those performance +claims and warranties are such Commercial Contributor's +responsibility alone. Under this section, the Commercial Contributor +would have to defend claims against the other Contributors related +to those performance claims and warranties, and if a court requires +any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS +PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, +ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, +MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient +is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with +its exercise of rights under this Agreement , including but not +limited to the risks and costs of program errors, compliance with +applicable laws, damage to or loss of data, programs or equipment, +and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT +NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability +of the remainder of the terms of this Agreement, and without further +action by the parties hereto, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +If Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that +the Program itself (excluding combinations of the Program with other +software or hardware) infringes such Recipient's patent(s), then +such Recipient's rights granted under Section 2(b) shall terminate +as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it +fails to comply with any of the material terms or conditions of this +Agreement and does not cure such failure in a reasonable period of +time after becoming aware of such noncompliance. If all Recipient's +rights under this Agreement terminate, Recipient agrees to cease use +and distribution of the Program as soon as reasonably +practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall +continue and survive. + +Everyone is permitted to copy and distribute copies of this +Agreement, but in order to avoid inconsistency the Agreement is +copyrighted and may only be modified in the following manner. The +Agreement Steward reserves the right to publish new versions +(including revisions) of this Agreement from time to time. No one +other than the Agreement Steward has the right to modify this +Agreement. The Eclipse Foundation is the initial Agreement +Steward. The Eclipse Foundation may assign the responsibility to +serve as the Agreement Steward to a suitable separate entity. Each +new version of the Agreement will be given a distinguishing version +number. The Program (including Contributions) may always be +distributed subject to the version of the Agreement under which it +was received. In addition, after a new version of the Agreement is +published, Contributor may elect to distribute the Program +(including its Contributions) under the new version. Except as +expressly stated in Sections 2(a) and 2(b) above, Recipient receives +no rights or licenses to the intellectual property of any +Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly +granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and +the intellectual property laws of the United States of America. No +party to this Agreement will bring a legal action under this +Agreement more than one year after the cause of action arose. Each +party waives its rights to a jury trial in any resulting litigation. diff --git a/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/osi_addlibs.txt b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/osi_addlibs.txt new file mode 100644 index 000000000..64614e7a0 --- /dev/null +++ b/WebAPP/SOLVERs/COIN-OR/Cbc/share/coin/doc/Osi/osi_addlibs.txt @@ -0,0 +1 @@ +-L/home/runner/work/Cbc/Cbc/dist/lib -lOsi -lCoinUtils -lbz2 -lz -llapack -lgfortran -lquadmath -lblas -lm diff --git a/WebAPP/SOLVERs/GLPK/glpk/AUTHORS b/WebAPP/SOLVERs/GLPK/glpk/AUTHORS new file mode 100644 index 000000000..8771f0d86 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/AUTHORS @@ -0,0 +1,33 @@ +The GLPK package was developed and programmed by Andrew Makhorin, +Department for Applied Informatics, Moscow Aviation Institute, Moscow, +Russia. + +E-mail: + +Paper mail: 125871, Russia, Moscow, Volokolamskoye sh., 4, + Moscow Aviation Institute, Andrew O. Makhorin + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.2.2 (MingW32) + +mQGiBD8UdT8RBAC6yWYxoa1b7U973J0jBuQpgZnhXlGJJpMZgAW9efDBD17vhkJm +hPVOQBKRUeOOLcW3/a7NMoNLMdmF1Rgz1FPVy3RgBDsYj4Sp4RBCsX/o0xXh+jxe +gncr4bdN0Ruk03pezVtLi9oYygdxfI51SsjZ2vwYP6BhMwv+xrIgcnc4qwCgoCit +26mTd0FoGOmsQuipo6X5LaUD/1l7NqFIjiGdWthyG3TqsiK5Ew7xF3fLEABXKPjb +PMRTMucX8XXHmW8RUD1vP1uGDnEn6s+fjc3/RtaqKjqGMdLt4XgHQkImaVguNpSS +IxN3LaK600BgAbwSd1bomRqWNlczAM7469VvGG9ASpCBveUUrqwerHZcUbvngL62 +pIcqA/41dO0xYrOTqMRhuguYMgHL2xbwB2Aj2TqRwBm697DIS25B9nE+8UsbjGRx +q3EmeuHeZ5kN5RbESXkGUB8whIcYxvH16HRNmM1ZjmFoBVL2Z6S2gpa2ZUqsq7BZ +s+hriElm3dfOQCt79/o852uKWu5bSjw2yiemVA2T8tG4OoN6DrQjQW5kcmV3IE1h +a2hvcmluIDxtYW9AbWFpMi5yY25ldC5ydT6IWwQTEQIAGwUCPxR1PwYLCQgHAwID +FQIDAxYCAQIeAQIXgAAKCRDRe/IwWYHoGKpHAJ44MmzWKr8OiTc0Bb6/RD56aekp +3wCdGznQMCfWFkehQPbeNaB5yFIs+8a5AQ0EPxR1UBAEAO3U3H5M0iYv06C4kKty +6ReWyYH4CzMAfp2lPVUKzRSjPtoAJ6SkrBSKMT+U+DahxZ4K4HbinvHq3uvlwWax +xw0wKxJl4oY6EGE1Jqn3B//Ak47RaNMnrs9V739WT1YNRpQvh4wOCeMekBzksf43 +hm4dSV4PMQkLmrEeG2+BYaZnAAMFA/4tVHhjGRkxzcTcfHCB+Yo3PXeIQMuIs00c +VKCrNReLni/3BWZC0w9tFzZSdz+URXefPWDGuAC16vLCVOD06NcIQGutPe189dUn +Kf9Bl6qc9DyWsxSTdF/PbLqcLfEe9g7fHhIwdY+w/hSq2n3NEURMzHiMT1U3CvHd +As5IzV/yD4hGBBgRAgAGBQI/FHVQAAoJENF78jBZgegYRZEAmwReJkMSrbs0EQs2 +wjyTCMd5KDh3AKCR2/RvVad9RT3ShYnUiPPYTL2/Nw== +=OfLQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/WebAPP/SOLVERs/GLPK/glpk/COPYING b/WebAPP/SOLVERs/GLPK/glpk/COPYING new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/COPYING @@ -0,0 +1,674 @@ + 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 +. diff --git a/WebAPP/SOLVERs/GLPK/glpk/ChangeLog b/WebAPP/SOLVERs/GLPK/glpk/ChangeLog new file mode 100644 index 000000000..c71214ef6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/ChangeLog @@ -0,0 +1,3454 @@ +Thu Feb 16 10:00:00 2018 Andrew Makhorin + + * GLPK 4.65 (43:0:3) has been released. + + * src/glpk.h, src/api/npp.c + New API routines for LP/MIP preprocessing were added: + glp_npp_alloc_wksp allocate the preprocessor workspace + glp_npp_load_prob load original problem instance + glp_npp_preprocess1 perform basic LP/MIP preprocessing + glp_npp_build_prob build resultant problem instance + glp_npp_postprocess postprocess solution to resultant problem + glp_npp_obtain_sol obtain solution to original problem + glp_npp_free_wksp free the preprocessor workspace + See doc/npp.txt for detailed description of these API routines. + + * examples/nppsamp.c + An example program to demonstrate using of LP/MIP preprocessor + was added. + + The following modules were renamed to simplify maintenance. + * src/draft/glpnpp.h RENAMED -> src/npp/npp.h + * src/draft/glpnpp01.c RENAMED -> src/npp/npp1.c + * src/draft/glpnpp02.c RENAMED -> src/npp/npp2.c + * src/draft/glpnpp03.c RENAMED -> src/npp/npp3.c + * src/draft/glpnpp04.c RENAMED -> src/npp/npp4.c + * src/draft/glpnpp05.c RENAMED -> src/npp/npp5.c + * src/draft/glpnpp06.c RENAMED -> src/npp/npp6.c + * src/bflib/fvs.h RENAMED -> src/misc/fvs.h + * src/bflib/fvs.c RENAMED -> src/misc/fvs.c + * src/draft/glpios.h RENAMED -> src/draft/ios.h + * src/cglib/ RENAMED -> src/intopt/ + * src/draft/glpios10.c RENAMED -> src/intopt/fpump.c + + * src/glpk.h, src/intopt/covgen.c + A new, more robust implementation of locally valid simple cover + cuts was included in the MIP solver. + + * src/draft/ios.h, src/draft/glpios01.c, src/draft/glpios03.c + These modules were changed to use the new cover cut generator. + + * src/misc/ks.c, src/misc/ks.h + Routines to solve 0-1 knapsack problem (used by the new cover + cut generator) were added. + + * src/misc/mt1.c, src/misc/mt1.h, src/misc/mt1.f + Routines to solve 0-1 knapsack problem with Martello & Toth + algorithm (used by the new cover cut generator) were added. + (The original Fortran 77 code mt1.f is included for reference + purposes only.) + + * src/draft/glpapi09.c + The API routine glp_init_iocp was changed to enable long-step + dual simplex by default. + + * src/api/cplex.c + The internal routine col_name routine was changed to construct + a fake column name depending on the column's attributes. + + * examples/glpsol.c + A new option --hide was added. This option removes all symbolic + names from the model being processed. + + * src/env/stdc.h + CDECL macro was added. (This macro is defined by config.h only + on building the GLPK DLL with MSVC.) + The following modules affected by this change were changed: + * src/api/cpxbas.c + * src/draft/glpios11.c + * src/intopt/cfg1.c + * src/intopt/fpump.c + * src/intopt/gmigen.c + * src/intopt/mirgen.c + * src/misc/wclique1.c + * src/simplex/spxchuzr.c + * src/simplex/spychuzc.c + +Sat Dec 02 12:00:00 2017 Andrew Makhorin + + * GLPK 4.64 (42:3:2) has been released. + + * src/simplex/spydual.c + The internal routine play_coef of the dual simplex solver was + changed to perform more aggressive perturbation to prevent dual + degeneracy and avoid stalling even if the current dual basic + solution is strongly feasible (mainly if the objective is zero, + so all reduced costs are always zero). Thanks to David Monniaux + for bug report. + + * src/draft/glpssx.h, glpssx02.c, glpapi07.c + The exact simplex solver routines were changed to perform + terminal output according to the verbosity level (specified by + the control parameter smcp.msg_lev). Thanks to Jeroen Demeyer + for bug report. + + * src/simplex/spxchuzr.c + The directive #include was added. Thanks to Heinrich + Schuchardt for bug report. + + * examples/graceful.mod + An example model in MathProg was added. Thanks to Mike Appleby + for contribution. + + * examples/powpl25h.mod powplant.mod wolfra6d.lp wolfra6d.mod + Three example models in MathProg and one in Cplex LP format + were added. Thanks to Peter Naszvadi for + contribution. + +Tue Jul 25 12:00:00 2017 Andrew Makhorin + + * GLPK 4.63 (42:2:2) has been released. + + * src/simplex/spxchuzr.h, src/simplex/spxchuzr.c + An experimental feature (phase I long-step ratio test) was + included in the primal simplex solver. + + * src/simplex/spxprim.c, src/simplex/spydual.c + An internal scaling of the objective coefficients was added to + the primal and dual simplex solvers. + + * src/simplex/spxprim.c + A minor bug was fixed (correction of flags of fixed non-basic + variables after removing the perturbation). + + * src/glpk.h, src/glpapi06.c + New smcp parameters were added (not documented yet): + int excl (default: GLP_ON) + Internal simplex solver option: + GLP_ON - exclude fixed non-basic variables from the working LP; + GLP_OFF - keep original variables in the working LP. + int shift (default: GLP_ON) + Internal simplex solver option: + GLP_ON - shift bounds of variables in the working LP tow. zero; + GLP_OFF - keep original bounds of variables in the working LP. + int aorn (default: GLP_USE_NT) + Internal simplex solver option: + GLP_USE_AT - use A matrix in sparse row-wise format; + GLP_USE_NT - use N matrix in sparse row-wise format. + Parameter out_frq was changed to specify the output frequency + in milliseconds rather than in simplex iterations. + + src/env/time.c + The Posix version of glp_time was replaced by new one, which + doesn't use gmtime functions to improve portability. Thanks to + Rob Schroeder for bug report. + + src/spv.c, src/spv.h + These files were moved to src/cglib/, since they are used only + in the MIR cuts generator. + + examples/life_goe.mod, examples/tiling.mod, examples/toto.mod + Three new example models in MathProg were added. Thanks to + Peter Naszvadi for contribution. + +Wed Jun 14 12:00:00 2017 Andrew Makhorin + + * GLPK 4.62 (42:1:2) has been released. + + * src/simplex/spxprim.c + An experimental feature (bound perturbation) to improve + numerical stabilty and avoid cycling was included in the primal + simplex solver. Currently it is enabled by default. + + * src/simplex/spxprim.c + Some dense vectors were replaced by sparse ones in full-vector + storage (FVS) format. + + * src/simplex/spxprim.c, src/simplex/spydual.c + Assertions trow[q] != 0.0 and tcol[p] != 0.0 were replaced by + setting an error code to prevent abnormal termination. Thanks + to Chris Matrakidis for patch. + + * src/simplex/spydual.c + Removing perturbation was added if the perturbed problem is + dual infeasible while the original one is dual feasible. Thanks + to Chris Matrakidis for patch. + + * src/api/mps.c + A range bug was fixed. + Thanks to Chris Matrakidis for patch. + + * src/minisat/minisat.c + Changes were made to provide 64-bit portability. Thanks to + Chris Matrakidis for patch. + + * src/api/minisat1.c + Changes related to the minisat solver were made. Thanks to + Chris Matrakidis for patch. + + * src/api/intfeas1.c + Changes were made to skip objective integrality check when + no objective bound is specified. Thanks to Chris Matrakidis + for patch. + + * src/glphbm.c, src/glprgr.c, src/env/stream.c, src/env/time.c, + * src/mpl/mpl5.c, src/mpl/mpl6.c, src/mpl/mplsql.c + Calls to non-thread-safe functions gmtime, strerror, and strtok + were replaced by calls to corresponding thread-safe equivalents + (gmtime_r, strerror_r, and strtok_r for GNU/Linux). + + * w32/*.def, w64/*.def + glp_config symbol was added. Thanks to Heinrich Schuchardt + for bug report. + + * examples/pbn/pbn.mod + A bug was fixed (model didn't work for odd number of rows or + columns). Thanks to Chris Matrakidis for + bug report and patch provided. + +Sun Jan 22 12:00:00 2017 Andrew Makhorin + + * GLPK 4.61 (42:0:2) has been released. + + The following modules were renamed to simplify maintenance. + * src/prob.h RENAMED -> src/api/prob.h + * src/glpapi01.c RENAMED -> src/api/prob1.c + * src/glpapi02.c RENAMED -> src/api/prob2.c + * src/glpapi03.c RENAMED -> src/api/prob3.c + * src/glpapi04.c RENAMED -> src/api/prob4.c + * src/glpapi05.c RENAMED -> src/api/prob5.c + + * src/env/tls.c + TLS (thread local storage class specifier) option was added; + see comments in tls.c for details. + + * configure.ac, config.h.in + Test for TLS was added. + Thanks to David Monniaux for + suggestion and Chris Matrakidis for patch. + + * src/env/tls.c + Dll support was added. + Thanks to Heinrich Schuchardt for + contribution. + + The following modules were changed to add __cdecl specifier + for functions passed to qsort (this is needed only on compiling + GLPK with MSVC to run under MS Windows). + * src/api/cpxbas.c + * src/cglib/cfg1.c + * src/cglib/gmigen.c + * src/cglib/mirgen.c + * src/misc/wclique1.c + * src/simplex/spychuzc.c + * src/glpios10.c + * src/glpios11.c + * examples/glpsol.c + + * src/glpk.h, src/env/env.c + The API routine glp_version was changed to avoid initialization + of the GLPK environment. The new API routine glp_config was + added (but not documented yet). Thanks to Heinrich Schuchardt + for suggestion. + + * INSTALL + Description of the configure option '--with-zlib' was removed. + Thanks to Balaco Baco for bug report. + +Fri Apr 01 12:00:00 2016 Andrew Makhorin + + * GLPK 4.60 (41:0:1) has been released. + + * src/glpk.h + Declarations of all non-documented API routines were hidden by + #ifdef GLP_UNDOC / #endif. + + src/simplex/spydual.c + An experimental feature (objective coefficient perturbation) + to improve numerical stabilty and avoid cycling was included in + the dual simplex solver. + + This release also includes all the changes made in 4.59.2 and + 4.59.1 non-official test releases (see below). + +Fri Mar 18 12:00:00 2016 Andrew Makhorin + + * GLPK 4.59.2 (40:1:0) has been released. + + NOTE: THIS IS A NON-OFFICIAL TEST RELEASE. + + src/simplex/spxprim.c + Improvements were made in the internal routine choose_pivot to + prevent choosing a too small pivot in the primal simplex. + + src/simplex/spydual.c + Improvements were made in the internal routine choose_pivot to + prevent choosing a too small pivot in the dual simplex. + + src/simplex/spychuzc.c + The internal routine spy_eval_bp was added to determine break- + points of the dual objective function. + + src/simplex/spydual.c + An experimental feature (long-step ratio test) was included in + the dual simplex. + + src/glpk.h, src/glpapi06.c + The GLP_RT_FLIP option (long-step ratio test) was added to + the simplex solver. Currently it affects only the dual simplex. + For the primal simplex it is equivalent to GLP_RT_HAR. + + src/examples/glpsol.c + The '--flip' command-line option was added to glpsol (long-step + dual ratio test). + + src/proxy/proxy1.c + Additional check was added to reject wrong solutions somwtimes + reported by the PROXY heuristic. + + src/glpios10.c + A bug (memory leak) was fixed in the FPUMP heuristic routine. + Thanks to for bug report. + +Tue Mar 15 12:00:00 2016 Andrew Makhorin + + * GLPK 4.59.1 (40:1:0) has been released. + + NOTE: THIS IS A NON-OFFICIAL BUG-FIX RELEASE. + + * src/simplex/mpl6.c, src/simplex/sql.c, src/simplex/sql.h + The header sql.h was renamed to avoid conflicts with standard + ODBC headers. Thanks to Noli Sicad for bug + report. + + * src/simplex/spychuzc.c, src/simplex/spychuzc.h + Minor changes were made. + +Fri Mar 11 12:00:00 2016 Andrew Makhorin + + * GLPK 4.59 (40:0:0) has been released. + + * src/sgf.c, src/sgf.h + The routines sgf_reduce_nuc and sgf_factorize were changed to + correctly report structural singularity. + + * src/glpios01.c + The routine ios_solve_node was changed to retry solving node + problem in case of the simplex solver failure. Thanks to Chris + Matrakidis for patch. + + * src/glpios03.c + The routine ios_driver was changed to correctly process the + root node. Thanks to Chris Matrakidis for + patch. + + * src/glpios06.c + Some improvements were made in the MIR cut generation routines. + Thanks to Chris Matrakidis for patch. + + The following source modules were splitted/renamed to simplify + maintenance. + * src/glpios04.c RENAMED -> src/spv.c + * src/glpios05.c glp_gmi_cut (new) -> src/cglib/gmicut.c + * src/glpios05.c glp_gmi_gen (new) -> src/cglib/gmigen.c + * src/glpios05.c REMOVED + * src/glpios06.c glp_mir_init (new) -> src/cglib/mirgen.c + * src/glpios06.c glp_mir_gen (new) -> src/cglib/mirgen.c + * src/glpios06.c glp_mir_free (new) -> src/cglib/mirgen.c + * src/glpios06.c REMOVED + * src/glpios08.c glp_cfg_init (new) -> src/cglib/cfg2.c + * src/glpios08.c glp_cfg_free (new) -> src/cglib/cfg2.c + * src/glpios08.c glp_clq_cut (new) -> src/cglib/clqcut.c + * src/glpios08.c REMOVED + * src/glpmpl.h RENAMED -> src/mpl/mpl.h + * src/glpmpl01.c RENAMED -> src/mpl/mpl1.c + * src/glpmpl02.c RENAMED -> src/mpl/mpl2.c + * src/glpmpl03.c RENAMED -> src/mpl/mpl3.c + * src/glpmpl04.c RENAMED -> src/mpl/mpl4.c + * src/glpmpl05.c RENAMED -> src/mpl/mpl5.c + * src/glpmpl06.c RENAMED -> src/mpl/mpl6.c + * src/glpsql.h RENAMED -> src/mpl/sql.h + * src/glpsql.c RENAMED -> src/mpl/sql.c + + * src/proxy/proxy.c + Minor bug was fixed in the PROXY heuristic routine. Thanks to + Chris Matrakidis for bug report. + + * src/cglib/gmicut.c, src/glpk.h + New API routine glp_gmi_cut was added (not documented yet). + + * src/cglib/gmigen.c, src/glpk.h + New API routine glp_gmi_gen was added (not documented yet). + + * src/cglib/mirgen.c, src/glpk.h + New API routines glp_mir_init, glp_mir_gen, and glp_mir_free + were added (not documented yet). + + * src/cglib/cfg2.c, src/glpk.h + New API routines glp_cfg_init and glp_cfg_free were added (not + documented yet). + + * src/cglib/clqcut.c, src/glpk.h + New API routine glp_clq_cut was added (not documented yet). + + * src/api/rdcc.c, src/api/wrcc.c + API routines glp_read_graph and glp_write_graph were changed + due to changes in the data format. For details see the document + "GLPK: Graph and Network Routines". + + * src/api/rdgr.c, src/api/wrgr.c, src/glpsdf.c, src/glpsdf.h + Old versions of API routines glp_read_graph and glp_write_graph + were removed. + + * doc/gmpl_pt-BR.tex, doc/gmpl_pt-BR.pdf + Translation of the document "Modeling Language GNU MathProg" + to Brazilian Portuguese (pt-BR) was included (in LaTeX and pdf + formats). Thanks to Joao Flavio de Freitas Almeida + for contribution. + +Thu Feb 18 12:00:00 2016 Andrew Makhorin + + * GLPK 4.58 (39:0:0) has been released. + + * src/misc/dimacs.c, src/misc/dimacs.h + Routines to read data files in DIMACS format were implemented + as a separate module. + + The following source modules were splitted/renamed to simplify + maintenance. + * src/glpapi11.c glp_print_sol -> src/api/prsol.c + * src/glpapi11.c glp_read_sol -> src/api/rdsol.c + * src/glpapi11.c glp_write_sol -> src/api/wrsol.c + * src/glpapi11.c glp_print_ipt -> src/api/pript.c + * src/glpapi11.c glp_read_ipt -> src/api/rdipt.c + * src/glpapi11.c glp_write_ipt -> src/api/wript.c + * src/glpapi11.c glp_print_mip -> src/api/prmip.c + * src/glpapi11.c glp_read_mip -> src/api/rdmip.c + * src/glpapi11.c glp_write_mip -> src/api/wrmip.c + * src/glpapi11.c glp_print_ranges -> src/api/prrngs.c + * src/glpapi11.c REMOVED + * src/glpapi14.c RENAMED -> src/api/mpl.c + * src/glpapi15.c glp_read_graph -> src/api/rdgr.c + * src/glpapi15.c glp_write_graph -> src/api/wrgr.c + * src/glpapi15.c REMOVED + * src/glpapi16.c glp_weak_comp -> src/api/weak.c + * src/glpapi16.c glp_strong_comp -> src/api/strong.c + * src/glpapi16.c glp_top_sort -> src/api/topsort.c + * src/glpapi16.c REMOVED + * src/glpapi17.c glp_mincost_lp -> src/api/mcflp.c + * src/glpapi17.c glp_mincost_okalg -> src/api/mcfokalg.c + * src/glpapi17.c glp_mincost_relax4 -> src/api/mcfrelax.c + * src/glpapi17.c glp_maxflow_lp -> src/api/maxflp.c + * src/glpapi17.c glp_maxflow_ffalg -> src/api/maxffalg.c + * src/glpapi17.c glp_check_asnprob -> src/api/ckasn.c + * src/glpapi17.c glp_asnprob_lp -> src/api/asnlp.c + * src/glpapi17.c glp_asnprob_okalg -> src/api/asnokalg.c + * src/glpapi17.c glp_asnprob_hall -> src/api/asnhall.c + * src/glpapi17.c glp_cpp -> src/api/cpp.c + * src/glpapi17.c REMOVED + * src/glpapi18.c glp_wclique_exact -> src/api/wcliqex.c + * src/glpapi18.c REMOVED + * src/glpapi19.c RENAMED -> src/api/minisat1.c + * src/glpapi20.c RENAMED -> src/api/intfeas1.c + * src/glpapi21.c RENAMED -> examples/glpsol.c + * src/glpcpx.c RENAMED -> src/api/cplex.c + * src/glpdmx.c glp_read_mincost -> src/api/rdmcf.c + * src/glpdmx.c glp_write_mincost -> src/api/wrmcf.c + * src/glpdmx.c glp_read_maxflow -> src/api/rdmaxf.c + * src/glpdmx.c glp_write_maxflow -> src/api/wrmaxf.c + * src/glpdmx.c glp_read_asnprob -> src/api/rdasn.c + * src/glpdmx.c glp_write_asnprob -> src/api/wrasn.c + * src/glpdmx.c glp_read_ccdata -> src/api/rdcc.c + * src/glpdmx.c glp_write_ccdata -> src/api/wrcc.c + * src/glpdmx.c glp_read_prob -> src/api/rdprob.c + * src/glpdmx.c glp_write_prob -> src/api/wrprob.c + * src/glpdmx.c glp_read_cnfsat -> src/api/rdcnf.c + * src/glpdmx.c glp_write_cnfsat -> src/api/wrcnf.c + * src/glpdmx.c glp_check_cnfsat -> src/api/ckcnf.c + * src/glpdmx.c REMOVED + * src/glpgmp.c RENAMED -> src/misc/mygmp.c + * src/glpini01.c RENAMED -> src/api/advbas.c + * src/glpini02.c RENAMED -> src/api/cpxbas.c + * src/glpmps.c RENAMED -> src/api/mps.c + * src/glpnet03.c RENAMED -> src/api/netgen.c + * src/glpnet04.c RENAMED -> src/api/gridgen.c + * src/glpnet05.c RENAMED -> src/api/rmfgen.c + + The following source modules were changed due to changes in the + data formats: + * src/api/rdsol.c + * src/api/wrsol.c + * src/api/rdipt.c + * src/api/wript.c + * src/api/rdmip.c + * src/api/wrmip.c + + * src/glpk.h + New API routines were added: glp_mpl_init_rand (not documented + yet), glp_time, glp_difftime. The API routine glp_main (glpsol + main routine) was removed. + + * src/glpmpl.h, src/glpmpl01.c, src/glpmpl03.c + The function tan (trigonometric tangent) was added to MathProg. + Thanks to Chris Matrakidis for patch. + + * src/simplex/spydual.c + A minor typo in dual simplex (GLP_EITLIM instead of GLP_ETMLIM) + was fixed. Thanks to Chris Matrakidis for + patch. + + * src/glpapi09.c, src/glpios01.c, src/glpios03.c + A time limit problem was fixed. Thanks to Chris Matrakidis + for patch. + + * doc/gmpl_es.tex, doc/gmpl_es.pdf + A new version of the document "Modeling Language GNU MathProg" + in Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + + * configure.ac + A check to determine if libtool needs '-no-undefined' flag to + build shared libraries on some platforms was added. + Thanks to Marco Atzeri and Heinrich + Schuchardt for suggestion. + + * autogen.sh + A script to regenerate the configure script and the Makefiles + was added. Thanks to Heinrich Schuchardt . + + * w32/glpk.def, w64/glpk.def + 'glp_at_error' symbol was added to the export list. Thanks to + Heinrich Schuchardt for bug report. + +Sun Nov 08 12:00:00 2015 Andrew Makhorin + + * GLPK 4.57 (38:0:2) has been released. + + * src/simplex/spy*.* + New, more efficient implementation of the dual simplex method + was included in the package. + + * src/simplex/spxprim.c + Incorrect directive #ifdef USE_AT was changed to #if USE_AT. + + * src/simplex/simplex.h + New header for simplex-based drivers was added. + + * src/glpspx02.c + Old implementation of the dual simplex method was removed from + the package. + + * src/glpspx.h + Old header for simplex-based drivers was removed. + + * src/glpapi06.c + Call to spx_dual was changed to spy_dual. + tol_piv = 1e-10 in glp_init_smcp was changed to 1e-9 (this new + tolerance seems to be more adequate for new implementations of + the primal and dual simplex methods). + + * src/glpk.h, src/glpapi09.c, src/glpios03.c + Option iocp.sr_heur to enable/disable simple rounding heuristic + was added. Thanks to Chris Matrakidis for + suggestion. + + * src/env/env.h src/env/error.c + API routine glp_at_error was added and documented. Thanks to + Jeroen Demeyer for suggestion. + + * src/glpapi19.c + Translation of MiniSat solver (src/minisat) from C++ to C is + made by a non-skilled programmer who converts pointers to ints + and vice versa, so MiniSat works on 32-bit platforms only. + Fixing this portability issue would require rewriting the code, + so currently to prevent crashing the API routine glp_minisat1 + was changed just to report failure if 64-bit version of GLPK is + used. Thanks to Heinrich Schuchardt for + bug report. + + * doc/glpk.tex, doc/gmpl.tex + Some material was added according to changes in GLPK API. + Also some minor typos were corrected. Thanks to Anton Voropaev + for typo report. + + * w32/makefiles, w64/makefiles + Option /Zi was added to pass to MSVC compiler. + + examples/tsp/*.* + An example application program TSPSOL was added. This program + is intended to solve the Symmetric Traveling Salesman Problem. + For more details see examples/tsp/README. + +Thu Oct 01 12:00:00 2015 Andrew Makhorin + + * GLPK 4.56 (37:3:1) has been released. + + * src/simplex/*.c, *.h + New, more efficient and robust implementation of the primal + simplex method was included in the package. + + * src/glpspx01.c + Old implementation of the primal simplex method was removed + from the package. + + * src/bflib/sgf.c + A bug was fixed in routine sgf_reduce_nuc. (The bug appeared if + the basis matrix was structurally singular.) Thanks to Martin + Jacob for bug report. + + * w32/*.*, w64/*.* + Scripts to build GLPK with Microsoft Visual Studio 2015 were + added. Thanks to Xypron for contribution + and testing. + +Fri Aug 22 12:00:00 2014 Andrew Makhorin + + * GLPK 4.55 (37:2:1) has been released. + + * src/bflib/luf.c, src/bflib/luf.h + Two routines luf_vt_solve1 and luf_estimate_norm were added to + estimate 1-norm of matrix inverse. + + * src/bflib/btf.c, src/bflib/btf.h + Two routines btf_at_solve1 and btf_estimate_norm were added to + estimate 1-norm of block triangular matrix inverse. + + * src/bflib/fhvint.c, src/bflib/fhvint.h + The routine fhvint_estimate was added to estimate 1-norm of the + basis matrix inverse (FHV-factorization). + + * src/bflib/scfint.c, src/bflib/scfint.h + The routine scfint_estimate was added to estimate 1-norm of the + basis matrix inverse (Schur-complement-based factorization). + + * src/bfd.c, src/bfd.c + The routine bfd_condest was added to estimate the condition of + the basis matrix. + + * src/bflib/scfint.h + The prefix '_glp' was added to keep the namespace clean. + + * src/env/stream.c + Two open modes "a" and "ab" were added. Thanks to Pedro P. Wong + for bug report. + + * src/glpapi21.c (glpsol) + Minor bug was fixed (command-line options --btf, --cbg, --cgr + didn't work properly). + + * src/bflib/sgf.c + A serious bug was fixed in a basis factorization routine used + on the dense phase. (The bug might appear only if the number of + rows exceeded sqrt(2**31) ~= 46,340 and caused access violtaion + exception because of integer overflow.) Thanks to Mark Meketon + for bug report. + + * doc/glpk.tex + Two API routines glp_alloc and glp_realloc were documented. + Thanks to Brian Gladman for suggestion. + + * doc/gmpl_es.tex, doc/gmpl_es.pdf + Translation of the document "Modeling Language GNU MathProg" + to Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + +Fri Mar 28 12:00:00 2014 Andrew Makhorin + + * GLPK 4.54 (37:1:1) has been released. + + * src/bflib/fhvint.h, fhvint.c + Some technical changes were made. + + * src/bflib/btf.h, btf.c, btfint.h, btfint.c + The module BTF was added to the package. It implements sparse + block triangular factorization of a square non-singular matrix + and is based on LU-factorization (see the LUF module). + + * src/bflib/scf.h, scf.c, scfint.h, scfint.c + The module SCF was added to the package. It implements sparse + factorization of a square non-singular matrix based on Schur + complement and LU-factorization (plain or block triangular; see + the LUF and BTF modules). + + * src/bfd.c + LP basis factorization driver was changed to use most recent + versions of the FHV and SCF modules. + + * src/glplpf.h, glplpf.c + Old version of the Schur-complement-based factorization module + was removed from the package. + + * src/glpk.h + New flags GLP_BF_LUF, GLP_BF_BTF were added for glp_bfcp. + + * src/glpapi12.c + The API routines glp_get_bfcp, glp_set_bfcp were replaced due + to new version of the BFD module. + + * src/glpapi21.c + New command-line options --luf, --btf, --ft, --cbg, and --cgr + were added for the glpsol solver. + + * src/* + According to a new version of the GNU Coding Standards in all + messages a grave accent character (`) was replaced by a single + apostrophe character ('). + + * src/glpapi09.c mip status bug was fixed. Thanks to Remy Roy + for bug report. + + * doc/glpk.tex + Some comments about invalidating the basis factorization were + added. Thanks to Xypron for suggestion. + + * configure.ac + "iodbc-config --cflags" was added to detect iodbc flags. Thanks + to Sebastien Villemot for patch. + +Thu Feb 13 12:00:00 2014 Andrew Makhorin + + * GLPK 4.53 (37:0:1) has been released. + + * src/glpmps.c (glp_read_mps) + The code was changed to remove free rows at the end. + + * src/glpcpx.c (glp_read_lp) + A bug was fixed (explicit bounds for binaries not set). Thanks + to Gabriel Hackebeil for bug report. + + * src/glpenv07.c (z_fgetc) + A bug was fixed (Z_STREAM_END -> Z_OK). Thanks to Achim Gaedke + for bug report. + + * src/glpenv07.c + Replaced by src/env/stream.c. + + * src/glpenv08.c + Replaced by src/env/dlsup.c. + + * src/bflib/ifu.h, src/bflib/ifu.c + Re-implemented. + + * src/glpscf.h, src/glpscf.c + Replaced by IFU. + + * src/glplpf.h, src/glplpf.c + Changed due to IFU. + + * src/glpbfd.c + Changed due to LPF. + + * src/glpapi06.c + Two API routines glp_get_it_cnt and glp_set_it_cnt were added. + Thanks to Joey Rios for suggestion. + + * src/glplpx.h, src/glplpx01.c, src/glplpx02.c, src/glplpx03.c + All obsolete API routines were completely removed. + + * examples/oldapi/lpx.h, examples/oldapi/lpx.c + A set of routines that simulate the old GLPK API (as defined + in 4.48) were added. Thanks to Jan Engelhardt + for suggestion. + + * src/zlib/* + zlib 1.2.7 was downgraded to zlib 1.2.5 (from glpk 4.50) due to + bugs detected in zlib 1.2.7 on some 64-bit platforms. Thanks to + Carlo Baldassi for bug report. + + * src/glpsql.c + Alignment bug was fixed. Thanks to Xypron + for suggestion. + + * src/glpsql.c + #include and #include were commented + out to fix a namespace bug on compiling with MariaDB. Thanks to + Xypron for suggestion. + +Sun Jul 28 12:00:00 2013 Andrew Makhorin + + * GLPK 4.52.1 (36:1:0) has been released. + + * src/Makefile.am + Version information bug was fixed. Thanks to Sebastien Villemot + for bug report. + + * src/proxy/proxy.c + A minor bug (incorrect use of glp_term_out) was fixed. + + * src/glpios03.c + The simple rounding heuristic routine was changed to check only + global constraints. + + * src/glpcpx.c + The code was changed to issue the warning message 'lower/upper + bound redefined' only once. + +Thu Jul 18 12:00:00 2013 Andrew Makhorin + + * GLPK 4.52 (36:0:1) has been released. + + * src/misc/wclique1.h, src/misc/wclique1.c + Greedy heuristic to find maximum weight clique was implemented. + + * src/cglib/cfg.h, src/cglib/cfg.c, src/cglib/cfg1.c + Conflict graph routines (used to generate clique cuts) were + implemented. + + * src/glpios08.c + New version of the clique cut generator was implemented. Now it + is able to efficiently process very large and/or dense conflict + graphs. Old rudimentary version was removed from the package. + + * examples/misp1.dat, examples/misp2.dat + Two data files for the maximum independent set problem (MISP) + were added to illustrate efficiency of using the clique cuts. + + * src/glpios03.c + Simple rounding heuristic applied for every node subproblem was + implemented. + + * proxy/proxy.c + Some bugs were fixed in the proximity search heuristic routine. + Thanks to Giorgio Sartor <0gioker0@gmail.com>. + + * src/glpapi21.c + New command-line option '--proxy [nnn]' was added to glpsol to + enable using the proximity search heuristic. + + * src/glpspx02.c + A feature was added to switch to the primal simplex in case of + stalling due to dual degeneracy (for GLP_DUALP only). + + * src/glpmps.c + A bug (incorrect processing of LI column indicator) was fixed + in the mps format reading routine. Thanks to Charles Brixko for + bug report. + +Wed Jun 19 12:00:00 2013 Andrew Makhorin + + * GLPK 4.51 (36:0:0) has been released. + + * src/bflib/sgf.c, src/bflib/sgf.h + Singleton and dense phases of sparse Gaussian factorizer were + implemented. + + * src/bflib/lufint.c, src/bflib/lufint.h + Interface routines to LU-factorization were added. + + * src/bflib/fhvint.c, src/bflib/fhvint.h + Interface routines to FHV-factorization were changed to use + lufint.c routines. + + * src/glplpf.c, src/glplpf.h + Routines implementing Schur-complement version of the LP basis + factorization were changed to use lufint.c routines. + + * src/glpbfd.c, src/glpbfd.h + Interface routines to the LP basis factorization were changed + due to changes in glplpf.c routines. + + * src/glpluf.c, src/glpluf.c + Old version of LU-factorization was removed from the package. + (This old version was used for 10 years since 3.0.6.) + + * src/misc/triang.c, src/misc/triang.h + Routine to find maximal triangular part of rectangular matrix + was added. + + * src/glpini01.c + The API routine glp_adv_basis that constructs advanced initial + LP basis was replaced by an improved version, which (unlike the + old version) takes into account numerical values of constraint + coefficients. + + * src/proxy/* + Routines that implement the proximity search heuristic for MIP + were added. Thanks to Giorgio Sartor <0gioker0@gmail.com> for + contribution. + + * src/glpk.h + iocp.ps_heur was added to enable/disable proxy heuristic. + + * glpsol + --proxy command-line option was added. + + * src/zlib/*.* + zlib general purpose compression library, version 1.2.7, + was ANSIfied and modified according to GLPK requirements and + included in the distribution as an external software module. + This version replaced the old one (1.2.5). For details please + see src/zlib/README. + + * src/glpk.h, src/env/time.c + The API routine glp_time was changed to return double rather + than glp_long. + + * src/glplib02.c + Routines that implement glp_long type (64-bit arithmetic) were + removed from the package. + + * src/glpk.h, src/env/alloc.c + New API routine glp_alloc was added. It makes obsolete two + API routines glp_malloc and glp_calloc which were replaced by + macros to use glp_alloc (hence 36:0:0). + + * src/glpios10.c + A bug was fixed that caused numerical instability in the FPUMP + heuristic (the bug was introduced in glpk 4.40). + +Fri May 24 12:00:00 2013 Andrew Makhorin + + * GLPK 4.50 (35:0:0) has been released + + * src/Makefile.am + Though API was not changed since 4.49, symbols _glp_lpx_* were + removed from the export list, hence 35:0:0. + + * src/glpfhv.h, src/glpfhv.c + Old routines for FHV-factorization were removed. + + * src/bflib/*.h, src/bflib/*.c + New version of basis factorization routines, including routines + for FHV-factorization, were added. + + * src/glpbfd.c + LP basis factorization driver was changed according to the new + routines for FHV-factorization. + + * doc/glpk.tex + Some clarifications about using the name index routines were + added. Thanks to Xypron for suggestion. + + * doc/gmpl.tex + Some typos were corrected. + Thanks to Jeffrey Kantor for report. + + * src/glprlx.c + A serious bug was *tentatively* fixed. This bug is inherited + from the original Fortran version of the RELAX-IV code. + Unfortunately, the code is very intricate, so this bug is still + under investigation. Thanks to Sylvain Fournier for bug report. + + RELAX-IV bug details + -------------------- + In the original RELAX-IV code there are four similar fragments + in subroutines ascnt1 and ascnt2 like this: + + C + C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. + C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH + C THE PRICES. + C + NB = 0 + DO 6 I=1,NSAVE + . . . + IF (RC(ARC).EQ.0) THEN + DELX=DELX+U(ARC) + NB = NB + 1 + PRDCSR(NB) = ARC + END IF + . . . + + On some instances the variable NB becomes greater than N (the + number of nodes) that leads to indexing error, because the + array PRDCSR is declared as array of N elements (more + precisely, as array of MAXNN elements, however, NB becomes even + much greater than MAXNN). + +Tue Apr 16 12:00:00 2013 Andrew Makhorin + + * GLPK 4.49 (34:0:0) has been released + + * glprlx.c, glprlx.h + C version of the Fortran code RELAX-IV (relaxation method of + Bertsekas and Tseng) was added. + + * glpapi17.c + API routine glp_mincost_relax4, which is a driver to RELAX-IV + code, was added and documented. + + * glpnet03.c + API routine glp_netgen_prob (Klingman's standard network + problems) was added and documented. + + * glpapi12.c + A bug (wrong dual feasibility test) was fixed in API routine + glp_warm_up. Thanks to David T. Price + for bug report. + + * glpapi10.c + Obsolete API routine lpx_check_kkt was replaced by API routine + glp_check_kkt. + + * glpk.h + All old API routines whose names begin with 'lpx_' were removed + from API and no more available. + + * glpk.tex, graphs.tex + These documents were essentially reformatted. + +Mon Jan 28 12:00:00 2013 Andrew Makhorin + + * GLPK 4.48 (33:0:0) has been released + + * src/glpmps.c + A bug in glp_write_mps was fixed. Thanks to Raniere Gaia Costa + da Silva for bug report. + + * glpk.h + glp_prob declaration changed (now it is incomplete struct); + glp_tree declaration changed (now it is incomplete struct); + glp_tran declaration changed (now it is incomplete struct); + glp_long declaration removed; + glp_time declaration removed; + glp_difftime removed from API; + glp_data removed from API; + glp_sdf_* removed from API; + glp_mem_usage declaration changed (glp_long -> size_t); + glp_realloc declaration added (not documented yet). + + * glpenv.h, glpenv05.c + Dynamic memory allocation routines were reimplemented. + + * glpk.h, glpnet03.c + Routine glp_netgen_prob was added (not documented yet). + + * configure.ac + Check for gmp.h was added. Thanks to Heinrich Schuchardt for + suggestion. + + * w32/glpk.def, w64/glpk.def + Changes were made to export only API symbols. + +Fri Sep 09 12:00:00 2011 Andrew Makhorin + + * GLPK 4.47 (32:0:32) has been released + + * src/glpapi20.c + New API routine glp_infeas1 to solve 0-1 feasibility problem + was added and documented (see doc/cnfsat.pdf). + + * src/glpnpp06.c + Some new preprocessor routines for SAT-CNF encoding, which are + used by the routine glp_intfeas1, were added. + + * src/glpnpp.h + The header was modified due to additions. + + * src/glpapi21.c + The glpsol solver was modified to bypass model postprocessing + if the solution reported is neither optimal nor feasible. + + * src/glpapi21.c + New glpsol options (--minisat and --objbnd) were added. + + * examples/pbn/*.* + The paint-by-numbers puzzle model (pbn.mod) was modified to + print solution in PostScript format and to check for multiple + solutions. Some benchmark examples from encoded + in MathProg were included in the distribution. For more details + see examples/pbn/README and examples/pbn/pbn.pdf. + + * examples/Makefile.am + A minor bug was fixed to correctly build glpk in a separate + directory. Thanks to Marco Atzeri for + bug report. + +Tue Aug 09 12:00:00 2011 Andrew Makhorin + + * GLPK 4.46 (31:0:31) has been released + + * src/glpk.h, src/Makefile + glpk.h was relocated from 'include' to 'src', and 'include' + subdir was removed; src/Makefile.am was changed appropriately. + + * src/zlib/*.* + zlib general purpose compression library, version 1.2.5, + was ANSIfied and modified according to GLPK requirements and + included in the distribution as an external software module. + + For details see src/zlib/README. + + * src/glpdmx.c + The following new API routines were added: + glp_read_cnfsat - read CNF-SAT problem data in DIMACS format + glp_check_cnfsat - check for CNF-SAT problem instance + glp_write_cnfsat - write CNF-SAT problem data in DIMACS format + + * src/minisat/*.* + MiniSat, a CNF-SAT solver, version 1.14.1, was ANSIfied and + modified according to GLPK requirements and included in the + distribution as an external software module. + + For details see minisat/README and minisat/LICENSE. + + * src/glpapi19.c + The API routine glp_minisat1, which is a driver to the MiniSat + solver, was included in the package. + + * doc/satcnf.* + The document "CNF Satisfiability Problem" was included in the + package. It is a supplement to the GLPK Reference Manual. + + * src/glpapi20.c + New glpsol options (--cnf, --wcnf, and --minisat) was added. + + * glpsql.c + Some bugs were fixed. Thanks to Xypron . + +Sun Dec 05 12:00:00 2010 Andrew Makhorin + + * GLPK 4.45 (30:0:30) has been released + + * glplpx01.c + A bug (it_cnt) in routine reset_parms was fixed. + Thanks to Ali Baharev for report. + + * glpmpl03.c + A bug (print "text\") was fixed. + Thanks to Xypron for report. + + * glpsql.c + A precision bug was fixed. + Thanks to Xypron . + + * glpk.tex + Some typos were corrected. + Thanks to Robbie Morrison . + +Thu Jun 03 12:00:00 2010 Andrew Makhorin + + * GLPK 4.44 (29:0:29) has been released + + * glpapi14.c glpmpl.h glpmpl01.c glpmpl03.c glpmpl04.c + Implemented suffixes for variables and constraints. + + * glpmpl06.c + Made changes to allow comment records in CSV files. + + * glpapi17.c + Added and documented new API routine glp_cpp to solve Critical + Path Problem. + +Sat Feb 20 12:00:00 2010 Andrew Makhorin + + * GLPK 4.43 (28:0:28) has been released + + * glplib.h, glplib.c, glpenv.h, glpenv.c + The module glpenv was split into two modules glpenv and glplib. + + * glpenv01.c, glpenv03.c, glpenv04.c, glpenv06.c + The following new API routines were added and documented: + glp_init_env, glp_free_env, glp_open_tee, glp_close_tee, + glp_error (macro), glp_difftime. + + * glpapi16.c + New API routine glp_top_sort (topological sorting of ayclic + digraph) was added and documented. + + * glpapi17.c + A serious bug was fixed in the routine glp_asn_prob_hall. + + * glpnpp05.c + A bug was fixed in the LP/MIP preprocessor (hidden covering + inequalities). + + * glpsql.c + Some improvements were made in the table driver (NULL data). + Thanks to Xypron for contribution. + + * configure.ac + Changes were made to use .dylib rather than .so under Mac OS. + Thanks to Noli Sicad for testing + +Wed Jan 13 12:00:00 2010 Andrew Makhorin + + * GLPK 4.42 (27:0:27) has been released + + * glpapi01.c, glpapi11.c, glpapi12.c, glpdmx.c + The following new API routines were added and documented: + glp_check_dup (check for duplicate elements in sparse matrix); + glp_sort_matrix (sort elements of the constraint matrix); + glp_read_prob (read problem data in GLPK format); + glp_write_prob (write problem data in GLPK format); + glp_analyze_bound (analyze active bound of non-basic variable); + glp_analyze_coef (analyze obj. coefficient at basic variable); + glp_print_ranges (print sensitivity analysis report; replaces + lpx_print_sens_bnds). + + * glpapi20.c + New command-line options were added to glpsol: + --glp (read problem data in GLPK format); + --wglp (write problem data in GLPK format); + --lp (replaces --cpxlp); + --wlp (replaces --wcpxlp); + --ranges (print sensitivity analysis report). + + * glpapi06.c + In the routine glp_init_smcp default value of the parameter + out_frq was changed to 500 (it was 200). + + * glpipp.h, glpipp01.c, glpipp02.c + The old MIP preprocessor module was removed. + + * glpapi09.c + Now the MIP solver uses the new MIP preprocessor (NPP). + + * glplpx03.c + lpx_write_opb was disabled due to replacing IPP with NPP. + + * glpnet09.c + Kellerman's heuristic to cover edges by cliques was added. + + * glplib08.c + Recognition of special filenames "/dev/stdin", "/dev/stdout", + and "/dev/stderr" was added. + + * glpk.tex + Chapter "Graph and network routines" was carried out from the + reference manual as a separate document. + +Mon Dec 21 12:00:00 2009 Andrew Makhorin + + * GLPK 4.41 (26:0:26) has been released + + * glpapi12.c + The following new API routines were added: + glp_transform_row (replaces lpx_transform_row); + glp_transform_col (replaces lpx_transform_col); + glp_prim_rtest (replaces lpx_prim_ratio_test); + glp_dual_rtest (replaces lpx_dual_ratio_test). + Note that values returned by glp_prim_rtest and glp_dual_rtest + differ from the ones retutned by the deprecated routines. + + * glpnpp*.* + The LP/MIP preprocessor was essentially re-implemented. + + * glpios03.c + The feature to remove inactive cuts from the active subproblem + was implemented. + + * glpios11.c + The feature processing cuts stored in the cut pool was improved + (now it uses estimation of objective degradation). + + * glpscg.* + Obsolete implemetation of the conflict graph was removed. + + * glpmpl.h, glpmpl03.c, glpmpl04.c + FILE was replaced by XFILE to allow using GLPK I/O routines. + + * glpsql.c, examples/sql, doc/tables.tex + The SQL table driver was changed to allow multiple arguments + separated by semicolon in SQL statements. Thanks to Xypron + . + + * glpk.h, glpapi14.c + New API routine glp_time was added (not documented yet). + + * glpapi20.c + Two new options were added to glpsol: --seed value (initialize + pseudo-random number generator used in MathProg model with + specified seed value), and --ini filename (use as initial basis + previously saved with -w option). + + * examples/xyacfs.mod + Thanks to Nigel Galloway for + contribution. + + * examples/dbf/*.* + Thanks to Noli Sicad for contribution. + + * w32/*.*, w64/*.* + Scripts to build GLPK with Microsoft Visual Studio 2010 were + added. Thanks to Xypron for contribution + and testing. + +Tue Nov 03 12:00:00 2009 Andrew Makhorin + + * GLPK 4.40 (25:0:25) has been released + + * glpdmx.c + Two new API routines were added: + glp_read_ccdata (read graph in DIMACS clique/coloring format); + glp_write_ccdata (write graph in DIMACS clique/coloring format). + Also an example file examples/sample.col was added. + + * glpapi19.c, glpnet08.c + New API routine glp_wclique_exact was added. It is intended to + find a maximum weight clique with the exact algorithm developed + by Prof. P. Ostergard. + + * glpnpp02.c + A bug was fixed in the LP preprocessor (routine npp_empty_col). + Thanks to Stefan Vigerske for the + bug report. + + * glpios10.c + A bug was fixed and some improvements were made in the FPUMP + heuristic module. Thanks to Xypron . + + * glpapi12.c + A bug was fixed in the API routine glp_warm_up (dual + feasibility test was incorrect in maximization case). Thanks to + Uday Venkatadri for the bug report. + + * glpapi16.c + Two new API routines were added: + glp_del_vertices (remove vertices from graph); + glp_del_arc (remove arc from graph). + + * glpios09.c + The hybrid pseudocost branching heuristic was included in the + MIP solver. It is available on API level (iocp.br_tech should + be set to GLP_BR_PCH) and in the stand-alone solver glpsol + (via the command-line option --pcost). This heuristic may be + useful on solving hard MIP instances. + + * glpios03.c + The branching heuristic by Driebeck and Tomlin (used in the + MIP solver by default) was changed to switch to branching on + most fractional variable if an lower bound of degradation of + the objective is close to zero for all branching candidates. + +Sun Jul 26 12:00:00 2009 Andrew Makhorin + + * GLPK 4.39 (24:0:24) has been released + + * glpsdf.c + New API routines to read plain data files were added. + + * glpcpx.h, glpini.h, glpscl.h + These headers were removed. + + * glpcpx.c + API routines glp_read_lp and glp_write_lp to read/write files + in CPLEX LP format were re-implemented. Now glp_write_lp + correctly writes double-bounded (ranged) rows by introducing + slack variables rather than by duplicating the rows. The data + structure glp_cpxcp and routine glp_init_cpxcp were added. + + * amd/* + The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to + Niels Klitgord for the bug report. + + * glpapi16.c + New API routines glp_set_vertex_name, glp_create_v_index, + glp_find_vertex, and glp_delete_v_index were added. + + * glpdmx.c + New API routines glp_read_asnprob, glp_write_asnprob, + glp_read_ccformat, and glp_write_ccformat were added (the two + latter routines are not documented yet). + + * glpapi18.c + New API routines glp_check_asnprob, glp_asnprob_lp, + glp_asnprob_okalg, and glp_asnprob_hall were added. + + * glpini01.c, glpini02.c + The message "Crashing..." was changed to "Constructing initial + basis..." due to suggestion by Thomas Kahle . + + * glpapi14.c + New API routines glp_printf, glp_vprintf, glp_malloc, + glp_calloc, glp_free, and glp_assert were added. + + * glplpp.h, glplpp01.c, glplpp02.c + Old LP presolver routines were removed. Now glp_simplex uses + new preprocessing routines (see glpnpp). + + * glpapi12.c + New API routine glp_warm_up was added; it replaces the routine + lpx_warm_up. + +Sat May 02 12:00:00 2009 Andrew Makhorin + + * GLPK 4.38 (23:0:23) has been released + + * glpmps.c + API routines to read/write MPS files were re-implemented. + + * glpspx02.c + Some improvements were made in the dual simplex routine. + + * glpk.h + New structure glp_iptcp was added. + + * glpnpp.h, glpnpp01.c, glpnpp02.c + New LP/MIP preprocessor. Currently it includes only some basic + routines and used only in the interior-point solver. + + * glpapi08.c + API routine glp_interior was replaced by an improved version + (new LP/MIP preprocessor, new ordering algorithms). + + New API routine glp_init_iptcp was added. + + API routine glp_ipt_status may return two new statuses due to + changes in glp_interior. + + * glpsol.c + New command-line options were added (ordering algorithm used in + the interior-point solver). + + * amd/*.*, colamd/*.* + Two external software modules AMD and COLAMD/SYMAMD used in the + interior-point solver were included in the distribution. + + For details see amd/README and colamd/README. + + * glpnet03.c, glpnet04.c, glpnet05.c + A minor bug was fixed (_G => G_). Thanks to Nelson H. F. Beebe + for bug report. + +Sun Mar 29 12:00:00 2009 Andrew Makhorin + + * GLPK 4.37 (22:0:22) has been released + + * glpk.h + iocp.fp_heur was added to enable/disable fpump heuristic. + + * glpios10.c + ios_feas_pump was added (feasibility pump heuristic). + + * glpsol.c + --fpump command-line option was added. + + * glpsds.c + Plain data set routines were added to facilitate reading plain + data in application programs. Currently these routines are not + in API, though declared in glpk.h. + + * glpapi08.c + A bug was fixed in the internal routine restore. (Due to this + bug dual solution components were computed incorrectly if the + problem was scaled.) + + * glpapi10.c, glpapi11.c + The following new API routines were added: + glp_print_sol (replaces lpx_print_sol); + glp_print_ipt (replaces lpx_print_ips); + glp_print_mip (replaces lpx_print_mip); + _glp_check_kkt (replaces lpx_check_kkt, lpx_check_int). + Now the routine lpx_print_prob (deprecated) is equivalent to + the routine glp_write_lp. + + * glpapi18.c, glpapi19.c + The following new API routines were added: + glp_read_graph (read graph from plain text file); + glp_write_graph (write graph to plain text file); + glp_weak_comp (find all weakly connected components); + glp_strong_comp (find all strongly connected components). + + * configure.ac, Makefile.am + Changes were made: (a) to allow using autoreconf/autoheader; + (b) to allow building glpk in a directory other than its source + directory. Thanks to Marco Atzeri for + bug report. + + * examples/shiftcover.mod + An example model in MathProg was added. + Thanks to Larry D'Agostino + for contribution. + +Fri Feb 06 12:00:00 2009 Andrew Makhorin + + * GLPK 4.36 (21:0:21) has been released + + * glpnet06.c, glpnet07.c, glpapi19.c + The following new API routines were added: + glp_mincost_okalg find minimum-cost flow with out-of-kilter + algorithm + glp_maxflow_ffalg find maximal flow with Ford-Fulkerson + algorithm + + * glpsol.c + Two new command-line options were added: + --mincost read min-cost flow data in DIMACS format + --maxflow read maximum flow data in DIMACS format + + * doc/glpk.* + New edition of the reference manual was included. + + * glpk.h + Duplicate symbols were removed to allow using swig. + Thanks to Kelly Westbrooks and + Nigel Galloway for suggestion. + + * glpcpx.c + A minor defect was fixed in the routine glp_write_lp. + Thanks to Sebastien Briais for bug report. + + * glpsql.c + A minor bug was fixed. Thanks to Xypron + for patch. + + * examples/hashi.mod, examples/shikaku.mod + Two example models in MathProg were added. Thanks to Sebastian + Nowozin for contribution. + + * examples/qfit.mod, examples/yacfs.mod + Two example models in MathProg were added. Thanks to Nigel + Galloway for contribution. + +Fri Jan 09 12:00:00 2009 Andrew Makhorin + + * GLPK 4.35 (20:0:20) has been released + + * glpk.h, glpapi.c, glpnet.c + The following new API routines were added: + glp_create_graph create graph + glp_set_graph_name assign (change) graph name + glp_add_vertices add new vertices to graph + glp_add_arc add new arc to graph + glp_erase_graph erase graph content + glp_delete_graph delete graph + glp_read_mincost read minimum cost flow problem data in + DIMACS format + glp_write_mincost write minimum cost flow problem data in + DIMACS format + glp_mincost_lp convert minimum cost flow problem to LP + glp_netgen Klingman's network problem generator + glp_gridgen grid-like network problem generator + glp_read_maxflow read maximum flow problem data in DIMACS + format + glp_write_maxflow write maximum flow problem data in DIMACS + format + glp_maxflow_lp convert maximum flow problem to LP + glp_rmfgen Goldfarb's maximum flow problem generator + + * doc/glpk.* + New edition of the reference manual was included. + + * examples/sample.min, examples/sample.max + Two example data files in DIMACS format were added. + + * glplib04.c + The statement "if (c = '\n') fflush(stdout)" was added to the + internal routine xputc to provide "real-time" terminal output. + Thanks to Luiz Bettoni for + suggestion. + + * glpmpl05.c + A minor bug was fixed in the internal routine mpl_fn_time2str. + Thanks to Stefan Vigerske for bug report. + + * w32/makefile, w64/makefile + The flag -O2 (/O2) was added to some makefiles. + +Thu Dec 04 12:00:00 2008 Andrew Makhorin + + * GLPK 4.34 (19:0:19) has been released + + * src/glpios03.c + A bug was fixed in the internal routine branch_on. Thanks to + Nigel Galloway for bug report. + + * src/glpmpl05.c + Three new MathProg functions were included: + gmtime obtaining current calendar time + str2time converting character string to calendar time + time2str converting calendar time to character string + Thanks to Xypron . + + * doc/glpk.*, doc/gmpl.* + A new edition of the GLPK reference manual and GNU MathProg + language description were included. + +Thu Oct 30 12:00:00 2008 Andrew Makhorin + + * GLPK 4.33 (18:0:18) has been released + + * glpapi*.* + The following new API routines were added: + glp_copy_prob copy problem object content + glp_exact solve LP in exact arithmetic + (makes lpx_exact deprecated) + glp_get_unbnd_ray determine variable causing unboundedness + (makes lpx_get_ray_info deprecated) + glp_interior solve LP with interior-point method + (makes lpx_interior deprecated) + + * glpapi*.* + The following new API routines for processing models written in + the GNU Mathprog language were added to the package: + glp_mpl_alloc_wksp allocate the translator workspace + glp_mpl_read_model read and translate model section + glp_mpl_read_data read and translate data section + glp_mpl_generate generate the model + glp_mpl_build_prob build LP/MIP instance from the model + glp_mpl_postsolve postsolve the model + glp_mpl_free_wksp deallocate the translator workspace + (These routines make lpx_read_model deprecated.) + + * src/glpapi17.c, examples/glpsol.c + The stand-alone solver glpsol was re-implemented with new API + routines. + + * src/glpsql.c + Some bugs were fixed in the SQL table driver. Thanks to Xypron + . + + * examples/cplex/*.* + A crude implementation of CPLEX-like interface to GLPK API was + added to the package. See examples/cplex/README. + +Fri Oct 03 12:00:00 2008 Andrew Makhorin + + * GLPK 4.32 (17:0:17) has been released + + * glpmpl01.c + A bug was fixed. Due to this bug iterated expressions having + an indexing expression whose dummy indices are bound to some + values, i.e. like sum{(i+1,j,k-1) in E} x[i,j,k] are evaluated + incorrectly. Namely, current value of such expressions is not + invalidated when corresponding dummy indices (like i and k in + the example above) are changed, that erroneously results in the + same value evaluated for the first time. + + * glpios03.c + Euclidean reduction of the local objective bound was added in + the routine glpios03.c. + + * glpapi11.c + The following new branch-and-cut API routines were added: + glp_ios_row_attr determine additional row attributes; + glp_ios_pool_size determine current size of the cut pool; + glp_ios_add_row add constraint to the cut pool; + glp_ios_del_row delete constraint from the cut pool; + glp_ios_clear_pool delete all constraints from the cut pool. + + * glpapi08.c + The following new features were included in the branch-and-cut + solver (the API routine glp_intopt): + MIP presolver; + mixed cover cut generator; + clique cut generator. + Due to the MIP presolver glp_intopt may additionally return + GLP_ENOPFS and GLP_ENODFS, if primal or dual infeasibility of + LP relaxation is detected by the presolver. Also the return + code GLP_EMIPGAP was introduced to correctly indicate that the + mip gap tolerance is reached. + + * glplpx01.c + Now the obsolete API routines lpx_integer and lpx_intopt are + completely superseded by the API routine glp_intopt that makes + them deprecated. + + * glpmpl05.c + Now the table driver name "iODBC" can be specified as "ODBC". + + * glpmpl03.c + A bug fixed in the routine free_dca. + Thanks to Xypron . + + * glpsql.c + A bug was fixed in the SQL table driver. + Thanks to Xypron . + + * examples/glpsol.c + Changes were made to allow multiple MathProg data files. + + * doc/glpk.* + A new edition of the GLPK reference manual was included. + + * doc/tables.* + A new edition of the supplement "Using data tables in the GNU + MathProg language" was included. + +Tue Sep 02 12:00:00 2008 Andrew Makhorin + + * GLPK 4.31 (16:0:16) has been released + + * glpspx.h, glpspx01.c, glpspx02.c, glpapi06.c + The dual simplex solver (spx_dual_opt) was replaced by a new + implementation of the two-phase dual simplex method (spx_dual). + Old simplex method routines (spx_prim_opt, spx_prim_feas, and + spx_dual_opt) were removed from the package. + + * glpk.h, glpscl.h, glpscl.c, glpapi04.c + New API routine glp_scale_prob was added. It replaces routine + lpx_scale_prob which is deprecated. + + * glpk.h, glpini.h, glpini01.c, glpini02.c, glpapi05.c + New API routines glp_std_basis, glp_adv_basis, glp_cpx_basis + were added. They replace routines lpx_std_basis, lpx_adv_basis, + lpx_cpx_basis which are deprecated. + + * glpdmp.c + 8-byte data alignment was added to the module (sufficient for + both ILP32 and LP64 environments). + + * glplib07.c + 16-byte data alignment was added to the module to provide + compatibility with LP64 environment (8-byte is not sufficient + due to jmp_buf; thanks to Xypron for investigation). + + * glplpx16.c + New version of the routine lpx_write_pb was added. Thanks to + Oscar Gustafsson for the contribution. + + * w32/VC9, w64/VC9 + Makefiles and batch files were added to build GLPK under 32- + and 64-bit Windows with Microsoft Visual Studio Express 2008. + Thanks to Heinrich Schuchardt for + the contribution and testing. + + * w32/DM, w32/OWC + Makefiles and batch files were added to build GLPK with Digital + Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (32-bit Windows). + +Wed Aug 13 12:00:00 2008 Andrew Makhorin + + * GLPK 4.30 (15:0:15) has been released + + * glpspx.h, glpspx03.c, glpapi06.c + The primal simplex solver (spx_prim_opt, spx_prim_feas) was + replaced by a new implementation (spx_primal), which currently + provides the same features as the old version. + + * glpmpl01.c, glpmpl03.c + Some changes were made in the MathProg translator to allow <, + <=, >=, and > on comparing symbolic values. Thanks to Heinrich + Schuchardt for patches. + + * glplpx10.c + Internal routine set_d_eps in the exact LP solver was changed + to prevent approximation errors in case of integral data. + Thanks to Markus Pilz for bug report. + +XXX XXX XX 12:00:00 2008 Andrew Makhorin + + * GLPK 4.29 (14:0:14) has been released + + * configure.ac + The configure script was changed to disable optional features + by default. For details see file INSTALL. + + * glpipp02.c + A bug was fixed in the internal routine reduce_bounds. Thanks + to Anne-Laurence Putz for + the bug report. + + * glpapi01.c + New API routine glp_erase_prob was added. + + * glpapi13.c + New API routines glp_read_mps and glp_write_mps were added. + They replace API routines lpx_read_mps, lpx_read_freemps, + lpx_write_mps, and lpx_write_freemps, which are deprecated. + + * glpapi14.c + New API routines glp_read_lp and glp_write_lp were added. They + replace API routines lpx_read_cpxlp and lpx_write_cpxlp, which + are deprecated. + + * glpsql.c + Minor bug was fixed. Thanks to Xypron for + the bug report. + +Tue Mar 25 12:00:00 2008 Andrew Makhorin + + * GLPK 4.28 (13:0:13) has been released + + * glplib.h, glplib.c + Three wrapper routines xdlopen, xdlsym, and xdlclose, which + provide the shared library support, were added. A particular + version of these routines depends on the option --enable-dl + passed to the configure script (see file INSTALL for details). + Thanks to Rafael Laboissiere for useful + advices concerning the shared library support. + + * glpsql.c + A static linking to iODBC and MySQL libraries used in the + MathProg table drivers was replaced by a dynamic linking to + corresponding shared libraries. + Many thanks to Heinrich Schuchardt + for the contribution and to Vijay Patil + for testing this feature under Windows XP. + + * glpgmp.h, glpgmp.c + A bug (which appeared only on 64-bit platforms) was fixed. + Thanks to Axel Simon for the bug report. + + * glpapi.c + A bug was fixed in the api routine glp_add_cols. (If the basis + is valid, adding column keeps it valid, however, col->bind was + set to -1 rather to 0.) + Thanks to Cedric[FR] for the bug report. + + * glplib.c + 64-bit unsigned int type glp_ulong and corresponding routines + were replaced by 64-bit signed int type xlong_t. + + * glpk.h, glpapi.c + The type glp_ulong was replaced by glp_long. This affects only + the api routine glp_mem_usage. + + * glplib.c + Compressed data file support was added. This feature requires + the zlib data compression libraries and allows compressing and + decompressing .gz files "on the fly". + + * glpcli.h, glpcli.c + Command-line interface routines were added. (This feature is + incomplete so far.) + +Sun Mar 02 12:00:00 2008 Andrew Makhorin + + * GLPK 4.27 (12:0:12) has been released + + * glpsql.h, glpsql.c + Two MathProg table drivers for iODBC and MySQL contributed by + Heinrich Schuchardt were added to + the package. + + * glpmpl05.c + Mathprog table driver for xBASE was added to the package. + + * glpmpl03.c + A minor was fixed in the MathProg translator (if some field + specified in the table statement is missing in corresponding + input table, the bug causes abnormal termination). Thanks to + Heinrich Schuchardt for the bug + report. + + * glpmpl.h, glpmpl.c + STRING data type was replaced by plain character strings. + +Sun Feb 17 12:00:00 2008 Andrew Makhorin + + * GLPK 4.26 (11:0:11) has been released + + * glpmpl.h, glpmpl01.c, glpmpl03.c, glpmpl05.c + The table statement was implemented. Description of this new + feature is given in file doc/tables.txt. + + * glpios03.c + A bug causing zero divide error on computing euclidean norm of + the cut coefficient vector was fixed. + +Wed Dec 19 12:00:00 2007 Andrew Makhorin + + * GLPK 4.25 (10:0:10) has been released + + * glpapi10.c + Routines lpx_eval_tab_row and lpx_eval_tab_col were replaced by + glp_eval_tab_row and glp_eval_tab_col. + + * glpios03.c, glpios05.c + Gomory's mixed integer cuts were implemented. + + * glpscs.h, glpscs.c + Segmented character string routines are no longer used and were + removed from the package. + +Wed Nov 21 12:00:00 2007 Andrew Makhorin + + * GLPK 4.24 (9:0:9) has been released + + * src/glplpx16.c + A bug was fixed in the routine lpx_write_cpxlp. If a variable + x has upper bound and no lower bound, it should appear in the + bounds section as "-inf <= x <= u", not as "x <= u". Thanks to + Enric Rodriguez for the bug report. + + * src/glpios03.c, src/glpios04.c, src/glpios05.c + MIR (mixed integer rounding) cuts were implemented. + +Sun Oct 28 12:00:00 2007 Andrew Makhorin + + * GLPK 4.23 (8:0:8) has been released + + * src/glplib05.c, configure.ac + Check for vsnprintf was added. + + * include/glppds.h, src/glppds.c + A module to scan plain data was added. + + * src/glpapi09.c + The following new API routines were added: + glp_read_sol read basic solution from text file; + glp_write_sol write basic solution to text file; + glp_read_ipt read interior-point solution from text file; + glp_write_ipt write interior-point solution to text file; + glp_read_mip read MIP solution from text file; + glp_write_mip write MIP solution to text file. + + * src/glpapi12.c + Advanced API routine glp_free_env was added. + + * examples/glpsol.c + The following three command-line options were added: + --mipgap tol set relative MIP gap tolerance + -r filename read solution from filename + -w filename write solution to filename + +Wed Sep 19 12:00:00 2007 Andrew Makhorin + + * GLPK 4.22 (7:0:7) has been released + + * src/glpios02.c + A bug was fixed in the MIP preprocessor (ios_preprocess_node). + Thanks to Roberto Bagnara (Department of + Mathematics, University of Parma, Italy) for the bug report. + + * src/glpios02.c + A bug was fixed in the MIP preprocessor (col_implied_bounds), + due to which constraint coefficients with small magnitude could + lead to wrong implied bounds of structural variables. + + * src/glpipp02.c + A similar bug was fixed in the routine reduce_bounds. + + * src/glpapi01.c + A bug was fixed in the routines glp_set_mat_row and + glp_set_mat_col. (The bug appeared due to incorrect removing + zero elements from the row/column lists.) + + * src/glplpx14.c + A bug was fixed in the API routines lpx_read_mps and + lpx_read_freemps, due to which bounds of type LI specified in + BOUNDS section were incorrectly processed. + + * src/glplib05.c + A call to standard function vsprintf was replaced by a call to + vsnprintf for security reasons. Many thanks to Peter T. Breuer + and Rafael Laboissiere . + +Tue Aug 28 12:00:00 2007 Andrew Makhorin + + * GLPK 4.21 (6:0:6) has been released + + * glpscg.h, glpscg.c + Routines to maintain sparse cliqued graph were added. + + * glpios02.c + MIP preprocessing routines were added. + + * glpk.h, glpios.h, glpios03.c + New reasons for calling the callback routine were introduced + in the MIP solver. + + * glpapi08.c + Default backtracking strategy was changed to best local bound. + + * glpapi11.c + New API routine glp_term_out to enable/disable terminal output + was added. + + * glprng.h, glprng02.c + Two routines to generate uniformly distributed pseudo-random + floating-point numbers were added. + +Thu Jul 26 12:00:00 2007 Andrew Makhorin + + * GLPK 4.20 (5:0:5) has been released + + * glpk.h, glpapi08.c + The routine lpx_integer was replaced by an equivalent routine + glp_intopt. Also new API routine glp_init_iocp was added. + + * glpiet.h, glpiet.c + Routines implementing the implicit enumeration tree are + no longer used and therefore were removed from the package. + + * glpios.h, glpios01.c, glpios02, glpios03 + Routines implementing the integer optimization suite being + replaced by a new version were removed from the package. + + * glpmip.h, glpmip01.c, glpmip02.c + + Routines implementing the B&B method being replaced by a new + version were removed from the package. + + * glpios.h, glpios01.c, glpios02.c + + Routines implementing a new version of the integer optimization + suite (IOS) based on the B&B method were added to the package. + + * glpk.h, glpapi10.c + Branch-and-bound interface routines were added to the package. + + * examples/tspsol.c + The TSP solver based on old version of the integer optimization + suite is no more supported and was removed from the package. + + * glpipp02.c + An error in the routine reduce_bounds was fixed; thanks to + Graham Rockwell for the bug report. + + * glpk.latex + A new edition of the reference manual was included. + +Thu Jul 05 12:00:00 2007 Andrew Makhorin + + * GLPK 4.19 (4:0:4) has been released + + The principal change is upgrading to GPLv3. + + * glpapi01.c + A serious bug in the routine glp_del_cols was fixed; thanks to + Cedric[FR] for the bug report. The bug + appeared because on deleting non-basic columns the basis header + remained valid, however, contained invalid (old) column ordinal + numbers. + + * glpapi10.c + A new advanced API routine glp_mem_limit was added. + + * glplpx01.c + The case GLP_EBOUND was added to the routine lpx_simplex. + Thanks to Cameron Kellough for the + bug report. + + * glplpx19.c + An API routine lpx_write_pb to write the problem instance in + OPB (pseudo boolean) format format was added. Thanks to Oscar + Gustafsson for the contribution. + + * glpsol.c + Two new options --wpb and --wnpb were added to glpsol to write + the problem instance in OPB format. + +Mon Jun 25 12:00:00 2007 Andrew Makhorin + + * GLPK 4.18 (3:0:3) has been released + + * glplib.h + Type names ulong_t and uldiv_t were changed to glp_ulong and + glp_uldiv to avoid conflicts with standard type names on some + platforms. Thanks to Boris Wirtz + for the bug report. + + * glpbfd.*, glpfhv.*, glplpf.* + LP basis factorization routines were made tidy. + + * glpk.h, glpapi04.c + The following API routines were added: + glp_set_rii, glp_set_sjj, glp_get_rii, glp_get_sjj. + + * glpk.h, glpapi06.c + The routine lpx_simplex was replaced by an equivalent routine + glp_simplex. Also new API routine glp_init_smcp was added. + + * glpk.h, glpapi09.c + The following advanced API routines were added: + glp_bf_exists, glp_factorize, glp_bf_updated, glp_get_bfcp, + glp_set_bfcp, glp_get_bhead, glp_get_row_bind, glp_get_col_bind, + glp_ftran, glp_btran. + + * glpk.latex + A new edition of the reference manual was included. + + * examples/dea.mod, examples/food.mod, examples/food2.mod + Three examples in the MathProg language were added. + Thanks to Sebastian Nowozin . + +Sat May 26 12:00:00 2007 Andrew Makhorin + + * GLPK 4.17 (2:0:2) has been released + + * glpdmp.h, glpdmp.c + Memory pool routines were replaced by a new version. + + * glpscs.h, glpscs.c + Segmented string routines were replaced by a new version. + + * glplpx08.c, glplpx09.c + Now the MIP problem may have no integer columns. + + * glpapi01.c + The routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat + were modified to allow zero elements (which are not stored in + the constraint matrix). + + * glpscf.h, glpscf.c + Schur complement factorization routines were implemented. + + * glplpf.h, glplpf.c + LP basis factorization routines based on LU-factorization and + Schur complement were implemented. + + * glplpx02.c, glplpx03.c + New control parameter LPX_K_BFTYPE was introduced to choose the + basis factorization type used by the simplex method routines. + + * glpsol.c + Three new command-line options were added to choose the basis + factorization type used by the simplex method routines: --luf, + --cbg, and --cgr. + + * glpk.latex + A new edition of the reference manual was included. + +Sat May 05 12:00:00 2007 Andrew Makhorin + + * GLPK 4.16 (1:0:1) has been released + + * glpk.h, glpapi.c, glplpx01.c, glplpx02.c + Names of a number basic api routines were changed and now have + the prefix 'glp_'. To keep backward compatibility these routines + are also available via their old names prefixed with 'lpx_'. + + * glplpx19.c + Three new api routines were added: glp_version, glp_term_hook, + and glp_mem_usage. + + * glpk.latex, gmpl.texi + A new edition of the reference manuals was included. + + * lpglpk40.c + This example program is no longer supported and therefore was + removed from the package. + +Sun Feb 18 12:00:00 2007 Andrew Makhorin + + * GLPK 4.15 (0:0:0) has been released + + * configure.ac, Makefile.am + Autotools specification files were changed to use GNU Libtool + that allows building the static as well as shared GLPK library. + Thanks to Rafael Laboissiere . + +Mon Feb 05 08:00:00 2007 Andrew Makhorin + + * GLPK 4.14 has been released + Now GLPK conforms to ILP32, LLP64, and LP64 programming models + (the latter seems to be the ultimate choice regarding 64-bit + architectures). Note that GLPK itself is a 32-bit application, + and the conformity only means that the package works correctly + on all these arenae. Nevertheless, on 64-bit platforms it is + possible to use more than 4GB of memory, if necessary. + + * Makefile + Starting from this release only the header glpk.h is needed to + be installed. + + * glplib01.c + Two routines bigmul and bigdiv which performs multiplication + and division of unsigned integers of arbitrary precision were + added. + + * glplib02.c + A set of 64-bit arithmetic routines were added. + + * glplib04.c + Some low-level library routines were improved and renamed. + + * glpcfg.h + The macro GLP_TM_SPEC were introduced to specify a version of + the time routine depending on the host environment. + +Mon Nov 13 12:00:00 2006 Andrew Makhorin + + * GLPK 4.13 has been released + + * configure.in + '-lm' bug was fixed. + + * glpbfx.h, glpbfx.c + Basis factorization interface routines based on exact (bignum) + arithmetic were implemented. + + * glpssx.h, glpssx1.c, glpssx2.c + Simplex method routines based on exact (bignum) arithmetic were + implemented. + + * glplpx6e.c + The routine lpx_exact, which is an easy-to-use driver to the + exact simplex method, was added. + + * glpsol.c + Two command-line options were added: '--exact' and '--xcheck'. + +Wed Nov 08 12:00:00 2006 Andrew Makhorin + + * GLPK 4.12 has been released + + * glpcfg.h + The package configuration file was added. + + * glplib2.c + Alternative version of the routines umalloc, ucalloc, and ufree + was provided. It does not limit the amount of allocated memory + to INT_MAX bytes and therefore can be used on platforms where + sizeof(void *) > sizeof(int). To enable this version one should + define the preprocessor variable GLP_HUGE_MEM. + + * glprng.c + The routine rng_create_rand was changed to initialize the + generator using seed = 1, not 0, to conform ISO C requirements. + + * glpgmp.h, glpgmp.c + A set of bignum arithmetic routines implementing operations on + integers and rationals was added. These routines are compatible + with the GNU MP library. + + NOTE: To attain a much better performance it is recommended to + use, if possible, the original GNU MP library rather than the + GLPK version, by defining the preprocessor variable GLP_USE_GMP. + + * glplux.h, glplux.c + A tentative implementation of sparse LU-factorization based on + exact (bignum) arithmetic was added. + + * glpssx.h, glpssx.c + A tentative implementation of some simplex method routines based + on exact (bignum) arithmetic was added. + + * glplpx6f.c + A preliminary implementation of the routine lpx_exact_check was + added. This routine checks the current basis for primal and dual + feasibility using exact (bignum) arithmetic. + + * examples/glpsol.c + The command-line option '--xcheck' was introduced to check the + current basis for feasibility using exact (bignum) arithmetic. + +Tue Jul 25 12:00:00 2006 Andrew Makhorin + + * GLPK 4.11 has been released. + + * include/glpbfi.h, src/glpbfi.c + Basis factorization interface routines were added. + + * include/glpluf.h, src/glpluf1.c + Hypersparse solution routines were added. + + * include/glpinv.h, src/glpinv1.c + Hypersparse solution routines (fake version) were added. + + * include/glpmpl.h, src/glpmpl.c + Built-in functions card, length, and substr were implemented. + Output redirection in the printf statement was implemented. + + * examples/graph.mod, examples/crypto.mod + Two example models illustrating new features of the modeling + language were included. + +Thu May 11 12:00:00 2006 Andrew Makhorin + + * GLPK 4.10 has been released. + + * src/glplpx8a.c + A fragment was added to the routines lpx_read_mps and + lpx_read_freemps to accept LI bound type (it is similar to LO, + however, additionally marks the column as integer). + + * include/glpbfi.h, src/glpbfi.c + The module glpbfi which implements the basis factorization + interface (BFI) was added. + + * src/glplpx7a.c + The routine lpx_cover_cut to generate mixed cover cuts was + added. + + * src/glplpx7b.c + The routine lpx_clique_cut to generate clique cuts and related + routines to maintain the conflict graph were added. + + * include/glplpx.h, src/glplpx5.c + The routine lpx_cpx_basis implementing Bixby's algorithm to + construct an initial LP basis was added. + + * examples/glpsol.c + Command-line option '--bib' was added which allows building + an initial LP basis using Bixby's algorithm. + Default command-line option '--mps' was changed to '--freemps'. + + * examples/cf12a.mod, examples/cf12b.mod + Two examples in MathProg (curve fitting problem) were added. + Thanks to Dr. Harley Mackenzie . + +Tue Jan 17 12:00:00 2006 Andrew Makhorin + + * GLPK 4.9 has been released. + + * glpipp.h, glpipp1.c, glpipp2.c + A MIP presolver were implemented (currently incomplete). It is + used internally in the routine lpx_intopt (see below). + + * glplpx6d.c, glplpx7a.c + An advanced branch-and-bound solver (the routine lpx_intopt) + were implemented. + + * glplpx6c.c + The routine lpx_check_int to check MIP feasibility conditions + was added. + + * glplpx8a.c + The routine lpx_print_mip was changed to print MIP feasibility + conditions. + + * glpmpl.h, glpmpl1.c, glpmpl3.c + The built-in functions sin, cos, atan, and atan2 were added to + the MathProg language. + + * doc/lang.* + Some typos were fixed. + Thanks to Minh Ha Duong (CIRED, CNRS). + +Wed Jan 12 12:00:00 2005 Andrew Makhorin + + * GLPK 4.8 has been released. + + * glpspx.h, glpspx1.c, glpspx2.c, glplpx6a.c + Simplex method routines were changed due to a new format of the + constraint matrix. + + * glpmat.h, glpmat.c + Sparse matrix routines were re-implemented using storage-by-rows + format. + + * glpipm.h, glpipm.c, glplpx6b.c + Interior-point method routines were changed due to a new format + of sparse matrices. + + * glpchol.h, glpchol.c + Old version of Cholesky factorization routines being replaced by + a new one (see glpmat.c) was removed from the package. + + * glplpx8c.c + Minor bug was fixed in api routine lpx_read_cpxlp. + +Mon Aug 23 12:00:00 2004 Andrew Makhorin + + * GLPK 4.7 has been released. + + * glplpx.h, glplpx1.c + New core API routines were added (but not documented yet): + lpx_order_matrix, lpx_create_index, lpx_find_row, lpx_find_col, + lpx_delete_index. + + * glplpx8a.c + API routine lpx_read_mps was re-implemented, and two new API + routines lpx_read_freemps and lpx_write_freemps were added to + support free MPS format. + + * glplpx8c.c + Two API routines lpx_read_cpxlp and lpx_write_cpxlp (formerly + named lpx_read_lpt and lpx_write_lpt) were re-implemented. + + * glpmps.h, glpmps.c + This module formerly used in lpx_read_mps was removed from the + package. + + * glplpt.h, glplpt.c + This module formerly used in lpx_read_lpt was removed from the + package. + + * glpmip.h, glpmip1.h, glpmip2.h + New MIP routines mip_best_node and mip_relative_gap were added + due to suggestion of Brady Hunsaker . + + * glpsol.c + The following new command-options were added: + --freemps to read problem data in free MPS format + --wfreemps to write problem data in free MPS format + --cpxlp to read problem data in CPLEX LP format + --wcpxlp to write problem data in CPLEX LP format + --bas to read LP basis from a text file in MPS format + --wbas to write LP basis to a text file in MPS format + --mostf to use "most fractional" branching heuristic + --bestb to use "best bound" backtracking heuristic + + * contrib/deli/*.* + GLPK Delphi interface module was temporarily removed from the + distribution due to licensing problems. + + * contrib/glpkmex/*.* + GLPK Matlab interface module was temporarily removed from the + distribution due to licensing problems. + + * contrib/jni/*.* + GLPK Java interface module was temporarily removed from the + distribution due to licensing problems. + +Wed Aug 04 12:00:00 2004 Andrew Makhorin + + * GLPK 4.6 has been released. + + * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c + Three new statements were implemented in the GNU MathProg + language: solve, printf, and for. Also some bugs were fixed. + + * glplpx.h, glplpx8e.c + Two API routines were added: lpx_read_prob and lpx_write_prob, + which allow reading and writing problem data in GNU LP format. + + * glpsol.c + Three new command-line options were added: --glp (to read + problem data in GNU LP format), --wglp (to write problem data + in GNU LP format), and --name (to change problem name). + + * glprng.h, glprng.c + A portable pseudo-random number generator was implemented as a + separate module. + + * glplib4.c + The old implementation of a pseudo-random number generator was + removed from the package. + + * doc/lang.*, doc/refman.* + New edition of the GLPK documentation was included. + + * contrib/glpkmex/*.* + A new version of GLPKMEX was included in the distribution. For + more details see contrib/glpkmex/ChangeLog. + +Mon Jul 19 12:00:00 2004 Andrew Makhorin + + * GLPK 4.5 has been released. + + * glpmip.h, glpmip1.c, glpmip2.c, glplpx6c.c + New implementation of the branch-and-bound method was added. + It replaces the old implementation, which was removed from the + package. + + * glpies.h, glpies1.c, glpies2.c, glpies3.c + Modules used in the old implementation of the branch-and-bound + method were removed from the package. + + * glplib2.c + Now if the preprocessor variable GLPHUGEMEM is defined, other + version of the routines umalloc, ucalloc, and ufree is used on + compiling the package. This allows avoiding memory allocation + problems on platforms where sizeof(void *) > sizeof(int), for + example, where addresses are 64-bit while integers are 32-bit. + The modification was made due to a bug report provided by Karel + Zimmermann and Christophe Caron + . + +Sat Jan 17 12:00:00 2004 Andrew Makhorin + + * GLPK 4.4 has been released. + + * glplpx.h, glplpx*.c + All API routines were re-implemented using new data structures. + Some new API routines were added and some existing API routines + became obsolete as shown below: + + Obsolete API routine Equivalent new API routine + lpx_check_name (no more supported) + lpx_set_obj_c0 lpx_set_obj_coef + lpx_set_row_coef (no more supported) + lpx_set_col_coef lpx_set_obj_coef + lpx_load_mat (no more supported) + lpx_load_mat3 lpx_load_matrix + lpx_unmark_all (no more supported) + lpx_mark_row (no more supported) + lpx_mark_col (no more supported) + lpx_clear_mat (no more supported) + lpx_del_items lpx_del_rows, lpx_del_cols + lpx_get_row_bnds lpx_get_row_type, lpx_get_row_lb, + lpx_get_row_ub + lpx_get_col_bnds lpx_get_col_type, lpx_get_col_lb, + lpx_get_col_ub + lpx_get_obj_c0 lpx_get_obj_coef + lpx_get_row_coef (no more supported) + lpx_get_col_coef lpx_get_obj_coef + lpx_get_row_mark (no more supported) + lpx_get_col_mark (no more supported) + lpx_get_row_info lpx_get_row_stat, lpx_get_row_prim, + lpx_get_row_dual + lpx_get_col_info lpx_get_col_stat, lpx_get_col_prim, + lpx_get_col_dual + lpx_get_ips_stat lpx_ipt_status + lpx_get_ips_row lpx_ipt_row_prim, lpx_ipt_row_dual + lpx_get_ips_col lpx_ipt_col_prim, lpx_ipt_col_dual + lpx_get_ips_obj lpx_ipt_obj_val + lpx_get_mip_stat lpx_mip_status + lpx_get_mip_row lpx_mip_row_val + lpx_get_mip_col lpx_mip_col_val + lpx_get_mip_obj lpx_mip_obj_val + + Obsolete API routines were kept for backward compatibility, + however, they will be removed in the future. + + * doc/refman.* + New edition of the GLPK reference manual containing description + of all new API routines was included. + + * contrib/glpkmex/*.* + GLPKMEX, a Matlab MEX interface to GLPK package, contributed by + Nicolo Giorgetti was included. + + * doc/GLPK_FAQ.txt + GLPK FAQ contributed by Harley Mackenzie was + included. + +Fri Dec 12 12:00:00 2003 Andrew Makhorin + + * GLPK 4.3 has been released. + + * configure.in + The bug, due to which the standard math library is not linked on + some platforms, was fixed. + + * glpmpl3.c + The bug (0 ** y) was fixed in the routine fp_power. + + * glpmpl.h, glpmpl1.c, glpmpl3.c + Some new built-in functions (round, trunc, Irand224, Uniform01, + Uniform, Normal01, Normal) were added to the MathProg language. + + * glpmpl1.c + The MathProg syntax was changed to allow writing 'subj to'. + + * glplpx.h, glplpx1.c, glplpx2.c + The new api routine lpx_get_ray_info was added. + + * glplpx8a.c + The api routine lpx_print_sol was changed to print the number of + non-basic variable, which causes primal unboundness. + + * glpmps.c + The code was changed to avoid errors on compiling the package on + Mac OS X. Thanks to Andre Girard for + the bug report. + + * doc/lang.*, doc/refman.* + Several typos were fixed and some new material was added in the + glpk documentation. + +Fri Nov 14 12:00:00 2003 Andrew Makhorin + + * GLPK 4.2 has been released. + + * glpiet.h, glpiet.c, glpios.h, glpios1.c, glpios2.c, glpios3.c + A preliminary implementation of the Integer Optimization Suite + (IOS) was included in the package. Eventually IOS will replace + the Implicit Enumeration Suite (IES). + + * glplpx.h, glplpx6d.c + A dummy version of the integer optimization routine lpx_intopt + was included in the package. Later this routine will replace the + routine lpx_integer. + + * examples/glpsol.c + A new command-line option --int-opt was added to the solver to + call lpx_intopt rather than lpx_integer. + + * glpbcs.h, glpbcs1.c, glpbcs2.c + Being replaced by IOS routines (see above) the Branch-and-Cut + Framework (BCS) routines were removed from the package. + + * examples/tspsol.c + Stand-alone Symmetric TSP solver was completely re-programmed + using IOS routines. + + * glplib.h, glplib2.c, glplib4.c + The random-number generator was implemented. It is based on the + module GB_FLIB from the Stanford GraphBase originally developed + by Donald Knuth. + + * glphbsm.c, glplpx8a.c, glpmps.c + All calls to fopen/fclose were replaced by corresponding calls + to ufopen/ufclose due to bug reports provided by Morten Welinder + and . + + * glpmps.c + The code was made re-entrant. + + * glplpx8b.c + API routine lpx_print_sens_bnds for bounds sensitivity analysis + contributed by Brady Hunsaker was added + to the package. This feature is also available in glpsol via the + command-line option --bounds. + + * contrib/jni/*.* + New version of GLPK JNI (Java Native Interface) contributed by + Chris Rosebrugh was added to the package. + + * contrib/deli/*.* + GLPK DELI (Delphi Interface) contributed by Ivo van Baren + was added to the package. + + * glplpx3.c + Default method to scale the problem was changed to equilibration + scaling (lp->scale = 1 in lpx_reset_parms). + + * glplpx6a.c + Two minor (non-critical) typos were fixed due to report provided + by Andrew Hamilton-Wright . + + * glplpp2.c + An untested case (line 941) had been tested due to bug report + provided by Jiri Spitz . + + * w32bc5.mak, w32vc6.mak, w32vc6d.mak, d32dmc.mak + Several makefiles were added to allow building GLPK library for + some non-GNU 32-bit platforms. + +Sat Aug 23 12:00:00 2003 Andrew Makhorin + + * GLPK 4.1 has been released. + + * glpmpl1.c, glpmpl3.c + Some bugs were fixed in the MathProg translator due to the bug + reports provided by Giles Thompson : + conditional set expressions were incorrectly parsed; + dimen attribute was not set by default when a set was used + recursively in its own declaration; + logical expressions ... in if ... then ... else ... did not + work; + displaying set expressions did not free memory allocated for + temporary results. + + * glpmpl3.c (reduce_terms) + Implementation of summation of linear forms over domain was + improved to reduce complexity of that operation from O(n*n) to + O(n*log n). The improvement was made due to a report provided + by Sebastien de Menten . + + * glplpx6a.c (line 1056), glpmip1.c (line 641) + Two minor bugs were fixed due to the bug report provided by + Kendall Demaree . + + * glplpx.h, glplpx6a.c + The method of one artificial variable implemented in the routine + lpx_prim_art and used on the phase I in the glpk simplex solver + has a serious defect: for some lp instances it erroneously + reports that the problem has no primal feasible solution. This + error appears when the column of the artificial variable, which + enters the basis to make it primal feasible, has large + constraint coefficients, that leads to small reduced costs of + non-basic variables and premature termination of the search, + i.e. to wrong conclusion that the problem has no primal feasible + solution. To avoid this defect the routine lpx_prim_feas was + included. It implements the method of implicit artifical + variables (based on minimization of the sum of infeasibilities), + which is a bit slower but much more robust. The routine + lpx_prim_feas having the same functionality now is used instead + the routine lpx_prim_art. + + * glpinv.h, glpinv.c + The test used in the routine inv_update to detect low accuracy + after updating LU-factorization of the basis matrix was replaced + by a new, more robust test. + + * glplpx6c.c + Selecting an active node to be solved next in the routine + btrack_bestp was changed. Now, if any integer feasible solution + has not been found yet, the routine chooses an active node which + has the minimal sum of integer infeasibilities. + + * glpmip.h, glpmip1.c + The additional flag int_obj was included in the structure + MIPTREE used by the branch-and-bound. This flag is set in the + routine mip_create_tree and used in the routine is_better. It + means that the objective is integral, i.e. depends only on + integer variables with integer objective coefficients. The test + used in the routine check_integrality was also replaced by a + new, more reasonable one. + + * glplpx1.c + A minor bug was fixed in the routine lpx_check_name. + + * glpmpl.h, glpmpl4.c, glplpx8d.c + The flag skip_data was added to the parameter list of the + routine mpl_read_model. If this flag is set, the data section + in the model file is ignored. Corresponding change was made in + the routine lpx_read_model. Now, if both model and data files + are specified, the data section in the model file is ignored. + + * glplpx8c.c + A minor bug (wrong format used for writing free columns) in the + routine lpx_write_lpt was fixed due to the bug report provided + by Bernhard Schmidt + + * sample/glpsol.c + The command-line parameter --tmlim, which allows limiting the + solution time, was added. + + * doc/lang.*, doc/refman.* + New edition of the GLPK documentation was included. + + * java-binding/*.* + New version of the GLPK JNI (Java Native Interface) package was + included in the distribution. + + * sample/lpglpk40.c + A non-trivial example was added. It allows using GLPK as a base + LP solver for Concorde, a program for solving Traveling Salesman + Problem (TSP). For details see comments in lpglpk40.c. + + * sample/*.mod + Some examples of LP and MIP models written in GNU MathProg were + added. + +Tue May 06 12:00:00 2003 Andrew Makhorin + + * GLPK 4.0 has been released. + + * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c + The model translator for the GNU MathProg modeling language was + implemented and included in the package. + + * glplpx.h, glplpx8d.c + The api routine lpx_read_model, which is an interface to the + MathProg translator, was included in the package. + + * glplpx.h, glplpx8a.c + The api routine lpx_print_prob for writing LP/MIP problem data + in plain text format was included in the package. + + * sample/glpsol.c + New version of the GLPK stand-alone LP/MIP solver that supports + the GNU MathProg modeling language was implemented. + + * doc/lang.latex, doc/lang.dvi, doc/lang.ps + The document "GLPK: Modeling Language GNU MathProg" was included + in the package. + + * doc/refman.latex, doc/refman.dvi, doc/refman.ps + New edition of the GLPK Reference Manual was included in the + package. + + * glplpx8c.c + A bug in the api routine lpx_write_lpt was fixed. Due to that + bug an addressing error occured in the routine if the objective + function has the non-zero constant term. + + * glplan.h, glplan1.c, glplan2.c, glplan3.c, glplan4.c, + * glplan5.c, glplan6.c, glplan7.c, glplan8.c, glplpx8b.c + All modules of the translator for the GLPK/L modeling language + were removed from the package, because GLPK/L being completely + superseded by GNU MathProg is no more supported. + +Tue Mar 25 12:00:00 2003 Andrew Makhorin + + * GLPK 3.3 has been released. + + * glplpp.h, glplpp1.c, glplpp2.c + An implementation of the built-in LP presolver was added to the + package. + + * glplpx.h + The flag presol was added to the structure LPX. This flag tells + the lpx_simplex whether the built-in LP presolver should be used + or not. By default this flag is off. Also three macros (namely + LPX_E_NOPFS, LPX_E_NODFS, and LPX_K_PRESOL) that concern using + the LP presolver were introduced. + + * glplpx3.c, glplpx6a.c + These modules was changed to use the built-in LP presolver. + + * sample/glpsol.c + Command line options --presol and --nopresol that concern using + the LP presolver were added to the stand-alone LP/MIP solver. + + * glplan1.c + This module was changed to allow declaring sets like A[1:10] in + the models written in the GLPK/L modeling language. + + * doc/refman.latex, doc/lang.latex + New editions of the documents "GLPK User's Guide" and "GLPK/L + Modeling Language" were included in the distribution. + + * java-binding/*.* + The package GLPK JNI (Java Native Interface) implementing Java + binding for GLPK was included in the distribution. This package + was developed and programmed by Yuri Victorovich . + +Tue Feb 18 12:00:00 2003 Andrew Makhorin + + * GLPK 3.2.4 has been released. + + * glplpx6b.c + The code was changed to allow auxiliary variables have non-zero + objective coefficients. + + Also a minor bug was fixed (the constant term was not considered + on displaying the objective function value). + + * sample/glpsol.c + The code was changed to fix a bug (the command-line option 'bfs' + was not recognized). The bug was fixed due to report provided by + Olivier . + + * glplpt.c + The code was changed to fix a bug (binary variables were treated + erroneously as integer ones). + + * glplpx6b.c + The code was changed to fix a bug (variables that have no lower + bounds were incorrectly processed on converting to the standard + formulation). The bug was fixed due to report kindly provided by + Kjell Eikland . + +Mon Nov 11 12:00:00 2002 Andrew Makhorin + + * GLPK 3.2.3 has been released. + + * glpmip.h, glpmip1.c + A preliminary implementation of the branch-and-bound driver + based on the implicit enumeration suite (glpies) was added to + the package. This module is not documented yet. + + * glplpx6c.c + A new implementation of the api routine lpx_integer which now + is based on the b&b driver (see glpmip above) was included in + the package. This new implementation has exactly the same + functionality as the old version and therefore all changes are + transparent to the api user. + + * glpbbm.h, glpbbm.c + * glprsm.h, glprsm1.c, glprsm2.c + * glplp.h, glplp.c + These modules were removed from the package, because they were + used only in the old version of the routine lpx_integer, which + was replaced by the new version (see glplpx6c above). + + * glplpx.h, glplpx6a.c + The api routine lpx_check_kkt was included in the package and + its description was added in the reference manual. This routine + allows checking Karush-Kuhn-Tucker optimality conditions for an + LP solution. + + * glplpx.h, glplpx8a.c + Now the api routine lpx_print_sol also prints information about + "solution quality" obtained via the api routine lpx_check_kkt. + + * glplpx.h, glplpx8a.c + New api routines lpx_read_bas and lpx_write_bas were included + in the package and documented. The routine lpx_write_bas allows + writing a current basis from an LP object to a text file in the + MPS format. The routine lpx_read_bas allows reading a basis + prepared in the MPS format from a text file into an LP object. + + * glplpt.c + The parsing routine which reads LP problem data prepared in the + CPLEX LP format was modified to allow specifying lower bounds + of variables also in the form 'variable >= lower bound' (in the + bounds section). This modification was made due to a notice + provided by Ivan Luzzi . + + * glplpx.h, glplpx8c.c + The api routine lpx_write_lpt which allows writing LP problem + data from an LP object to a text file using the CPLEX LP format + was included in the package and documented. + + * glplpx.h, glplpx3.c + The control parameter LPX_K_LPTORIG that affects the behavior + of the api routine lpx_write_lpt was introduced. + + * glplan6.c + The semantics of the language GLPK/L was changed to allow + selection in case when not all mute letters of a predicate (the + operand that follows the keyword 'where') are presented in a + parameter (the operand that precedes the keyword 'where'), i.e. + to allow writing something like this: + y[j] := sum(i, x[i] where p[i,j]); + The paragraph "Selection" in the langauge description (page 25) + was also correspondingly changed. This change of the language + semantics was undertaken due to a notice provided by Peter Lee + . + + * sample/hwd.lpm + A nice example of LP model written in GLPK/L and contributed by + Peter Lee was included in the package. + + * glplpx6b.c + The api routine lpx_interior was modified: a) to compute dual + values for all structural as well as auxiliary variables; b) to + allow specifying non-zero objective coefficients at auxiliary + variables. + + * sample/glpsol.c + Three new command-line options were added to the solver, which + are: --plain, --orig, and --wrlpt. + +Mon Oct 14 12:00:00 2002 Andrew Makhorin + + * GLPK 3.2.2 has been released. + + * glplpt.h, glplpt.c + A module that reads LP/MIP problem data in CPLEX LP format was + implemented. + + * glplpx8c.c + An api routine lpx_read_lpt that reads LP/MIP problem data in + CPLEX LP format was implemented. + + * sample/glpsol.c, sample/plan.lpt + A new command-line option '--lpt' that allows reading LP/MIP + problem data in CPLEX LP format was added to the solver. + + * doc/refman.latex, doc/refman.dvi, doc/refman.ps + A new edition of the Reference Manual was included. + + * source/*.c + Casting to (unsigned char) was added in some calls to the + classification functions (isalpha, etc.). The bug was fixed due + to report provided by Morten Welinder . + + * glplpx8a.c + The local routine mps_numb used in the routine lpx_write_mps + was modified to correctly format floating-point numbers that + have two digits in the decimal exponent. The bug was fixed due + to report provided by Vlahos Kiriakos . + + * glplan.h, glplan1.c, ..., glplan8.c + Several serious bugs were fixed in the language processor due + to reports provided by : + (a) a static search tree used to find sparse array elements was + sometimes overwritten that caused the message 'assertion failed' + to appear; the bug was fixed by creating separate search trees + in parsing routines; (b) a variable declared using the + predicate-controlled variable declaration statement had wrong + order of domain sets, because the variable array was built as + a copy of the predicate array; the bug was fixed by using the + internal routine transpose that coordinates mute letters (and + therefore domain sets) on copying sparse arrays; (c) sometimes + assignment statements like x[#a,#b,#c] := ... was incorrectly + processed; the bug was fixed by including an appropriate check + into the internal routine assign_stmt. + + * glp_simplex.c + An additional check to see if all lower bounds are not greater + than corresponding upper bounds was included in the routine to + prevent wrong results to appear. Such incorrectness sometimes + was not detected, namely, when variables with such bounds were + non-basic and never entered the basis. + + * glpspx1.c + Maximal number of simplex iterations before reinversion was + decreased from 100 to 50. This allowed to improve accuracy and, + that is more important, to reduce the solution time for many + serial lp problems approximately 1.5--2 times. + + * glpspx2.c + A check to see if all elements in the column chosen to enter + the basis are close to zero in the routine spx_prim_chuzr was + temporarily removed because this check gave wrong conclusion in + case when the corresponding non-basic variable had zero column + in the constraint matrix. An analogous check to see if all + elements in the row chosen to leave the basis are close to zero + in the routine spx_dual_chuzc was also temporarily removed on + the same reason. The bug was fixed due to reports provided by + Flavio Keidi Miyazawa and Vlahos Kiriakos + . + +Mon Aug 12 12:00:00 2002 Andrew Makhorin + + * GLPK 3.2.1 has been released. + + * glpbcs.h, glpbcs1.c, glpbcs2.c + * glpies.h, glpies1.c, glpies2.c, glpies3.c + A preliminary implementation of the branch-and-cut framework + was included in the package. + + * doc/brcut.txt + The document "GLPK: A Preliminary Implementation of the + Branch-And-Cut Framework" was included in the distribution. + + * sample/tspsol.c + An illustrative program for solving symmetric TSP based on the + branch-and-cut method was included in the package. + + * glpdmp.h, glpdmp.c + A new, re-enterable version of routines for managing dynamic + memory pools was included in the package. + + * glpavl.h, glpavl.c + A new, re-enterable version of routines for managing AVL search + trees was included in the package. + + * glplib.h, glplib2.c + Two new low-level routines ufopen and ufclose were included in + the package. + + * glplpx.h, glplpx7.c + The following new api routines were added: lpx_eval_activity, + lpx_eval_red_cost, lpx_reduce_form, lpx_mixed_gomory. + + * glptsp.h, glptsp.c + A module for reading TSP data using TSPLIB format was included + in the package. + +Mon Jul 15 12:00:00 2002 Andrew Makhorin + + * GLPK 3.2 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c + The identifier 'class' (used as a member name in the structure + LPX and as an argument name in the routine lpx_set_class) was + changed to 'clss' in order to avoid conflicts with C++ reserved + words. + + * glpk.h, glplpx.h, glplpx1.c, glplpx2.c, glplpx6a.c, + * glplpx6b.c, glplpx6c.c, glplpx7.c, glplpx8.c + The following new api routines were added: lpx_set_obj_name, + lpx_get_obj_name, lpx_get_row_mark, lpx_get_col_mark, + lpx_transform_row, lpx_transform_col, lpx_prim_ratio_test, + lpx_dual_ratio_test, lpx_interior, lpx_get_ips_stat, + lpx_get_ips_row, lpx_get_ips_col, lpx_get_ips_obj, lpx_read_lpm, + lpx_write_mps, lpx_print_ips. + + * glpsol.c + The solver was completely re-programmed using new api routines. + + * lang.latex, lang.dvi, lang.ps + New edition of the document "GLPK: Modeling Language GLPK/L" + was included in the distribution. + + * refman.latex, refman.dvi, refman.ps + New edition of the document "GLPK: Reference Manual" (which + contains descriptions of all new api routines) was included in + the distribution. + + * glpapi.h, glpapi1.c, glpapi2.c, glpapi3.c, glpapi4.c + These files (which contain old api routines) were removed from + the package. + + * glpipm1.c, glpipm2.c + The file glpipm1.c was renamed to glpipm.c. The file glpipm2.c + was used only by old api routines and therefore was removed from + the package. + + * language.texinfo + Old version of the document "GLPK: Modeling Language GLPK/L" was + removed from the distribution. + +Mon May 27 12:00:00 2002 Andrew Makhorin + + * GLPK 3.1 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, + * glplpx5.c, glplpx6.c, glplpx7.c, glplpx8.c + A preliminary implementation of new API routines was completed. + + * refman.latex, refman.dvi, refman.ps + A draft edition of the document "GLPK Reference Manual", which + describes new API routines, was included. + + * glplib3.c + A bug in measuring long time intervals was fixed up. + + * glprsm3.c + This module contains some obsolete routines not longer used and + therefore it was removed from the package (into the subdirectory + 'oldsrc'). + + * glprsm.h + Some declarations related to the module 'glprsm3.c' (see above) + were removed. + + * guide.texinfo + The document "GLPK User's Guide" describing old API routines was + removed from the package (into the subdirectory 'oldsrc'). + + * newapi.txt + The document "New GLPK API Routines" was removed at all, because + it is superseded by the new reference manual (see above). + +Mon May 13 12:00:00 2002 Andrew Makhorin + + * GLPK 3.0.8 has been released. + + * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, + * glplpx5.c, glplpx6.c, glplpx7.c + A preliminary (currently incomplete) implementation of new api + routines was included. + + * sample/newsamp.c + A sample program for the new api routines was included. + + * newapi.txt + A draft of the document "New GLPK API Routines" was included. + + * glpapi2.c, glpapi5.c, glpapi6.c + These modules (which contain the api routines glp_call_rsm1, + glp_simplex1, glp_pivot_in, glp_pivot_out) were removed from the + package (to the subdirectory 'oldsrc') since these routines are + functionally superseded by the new api routines. + + * glpk.h, glpapi2.c, glpapi3.c, glpapi4.c + The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were + renamed to glp_simplex, glp_interior, glp_integer, respectively. + + * sample/glpsol.c + Some command-line options (which got obsolete due to the recent + changes in api) were excluded. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" was included in + the distribution to reflect the changes in some api routines. + + * doc/libref.texinfo + This document was removed from the package (to the subdirectory + 'oldsrc') since it describes the library routines, most of which + got obsolete and no longer used. + + * Makefile.in + A minor bug was fixed up due to bug report from Hans Schwengeler + . + +Mon Apr 22 12:00:00 2002 Andrew Makhorin + + * GLPK 3.0.7 has been released. + + * glpduff.h, glpduff.c, glpspx.h, glpspx1.c, glpspx2.c, + * glpapi7.c + These modules were replaced by a new implementation of the + simplex method and therefore they were removed from the package + (however they still can be found in the subdirectory 'oldsrc'). + + * glprsm1.c + The routine crash_aa was replaced by a new implementation and + therefore it was removed from the file 'glprsm1.c'. + + * glplpx.h, glplpx.c, glpspx.h, glpspx1.c, glpspx2.c, glpspx3.c, + * glpspx4.c, glpapi7.c + New (currently incomplete) implementation of the simplex method + components was included in the package. + +Thu Mar 28 12:00:00 2002 Andrew Makhorin + + * GLPK 3.0.6 has been released. + + * glpluf.h, glpluf.c, glpinv.h, glpinv.c + New version of LU-factorization and basis maintenance routines + (based on Forrest-Tomlin updating technique) was implemented. + + * glpeta.h, glpeta.c, glpfhv.h, glpfhv.c, glpgel.h, glpgel.c, + * glppfi.h, glppfi.c, glprfi.h, glprfi.c + These routines implement some other forms of the basis matrix. + Now they became obsolete being functionally superseded by the + new version of basis maintenance routines (see above) and were + removed from the package (however they still can be found in the + subdirectory 'oldsrc'). + + * glpbbm.c, glprsm.h, glprsm1.h, glprsm2.h, glpspx.h, glpspx2.c, + * glprsm2.c, glpsol.c + Necessary changes were made in order to use the new version of + basis maintenance routines. + +Tue Jan 29 12:00:00 2002 Andrew Makhorin + + * GLPK 3.0.5 has been released. + Structure of the package was re-organized in order to simplify + its maintenance. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" was included in + the distribution. Now the document includes descriptions of some + additional API routines recently added to the package. + + * doc/newapi.txt + The document "Additional GLPK API Routines" was removed from the + distribution, because the corresponding material was included in + the user's guide (see above). + +Mon Dec 10 12:00:00 2001 Andrew Makhorin + + * GLPK 3.0.4 has been released. + + * glpspx.h, glpspx1.c, glpspx2.c, glpapi/glp_simplex2.h + A new, more efficient version of the two-phase primal simplex + method was implemented (advanced initial basis, projected + steepest edge, recursive computations of solution components). + + * glpapi/glp_call_bbm1.c + Now LP relaxation can be solved either using rsm1_driver(), or + using glp_simplex2(). The choice is controlled by the parameter + 'meth' (a member of struct bbm1). + + * sample/glpsol.c + The new implementation of the simplex method is now used by + default. The old version is available via --old-sim option. + + * glpmat/gm_scaling.c + Now this routine displays only two lines: an initial "quality" + and a final "quality". + + * glplp/prepro_lp.c + Identifiers 'fmin' and 'fmax' renamed to 'f_min' and 'f_max' in + order to avoid conflict with . The bug was fixed due to + report provided by Sami Farin . + +Wed Oct 03 12:00:00 2001 Andrew Makhorin + + * GLPK 3.0.3 has been released. + + * glprsm/harris_row.c, glprsm/harris_col.c + The relative tolerance used on the first pass of the two-pass + ratio test was replaced by the absolute tolerance. + + * glprsm/rsm_primal.c, glprsm/rsm_feas.c, glprsm/rsm_dual.c + The absolute tolerance passed to the two-pass ratio test routine + was decaresed (for both primal and dual simplex). + + These changes were made in order to improve numerical stability + of the simplex method. + + * glprsm/glp_call_rsm1.c, glprsm/glp_call_bbm1.c, + * glprsm/glp_simplex1, glprsm/glp_pivoting.c + Default form of the inverse was changed from RFI to AFI. + +Mon Sep 24 12:00:00 2001 Andrew Makhorin + + * GLPK 3.0.2 has been released. + + * glpfhv.h, glpfhv.c + New version of the basis maintaining routines was implemented. + These routines, which are based on so called FHV-factorization + (a variety of LU-factorization) and Gustavson's data structures, + perform the main operations on the basis matrix faster at the + expense of some worsening numerical accuracy. + + * glprsm.h, glprsm/afi.c + The routines, which implement AFI (Advanced Form of the + Inverse) based on FHV-factorization, were added to the package. + This new form is available via the parameter form = 3 (on API + level) or via the option --afi (in GLPSOL solver). + + * EFI was renamed to PFI + In order to correct terminology the acronym EFI (Elimination + Form of the Inverse) was replaced by PFI (Product Form of the + Inverse) everywhere in the source code and the documentation. + + * glpset/umalloc.c, glpset/ucalloc.c + * glpset/get_atom.c, glpset/get_atomv.c + These memory management routines were changed in order *not* to + clear allocated memory blocks by binary zeros. + +Wed Aug 01 12:00:00 2001 Andrew Makhorin + + * GLPK 3.0.1 has been released. + + * glpapi/old_api.c, glplp/extract_lp.c, store_lpsol.c + Old API routines were deleted from the package. + + * include/glpk.h, include/glpapi.h, include/glplp.h + Specifications of old API routines and data structures were + removed from the headers. + + * sample/glpsol.c + New version of the stand-alone solver GLPSOL that now uses new + API routines was implemented. + + * glpapi/glp_set_row_fctr.c, glpapi/glp_set_col_fctr.c, + * glpapi/glp_get_row_fctr.c, glpapi/glp_get_col_fctr.c, + * glpapi/glp_scale_prob.c + Scaling routines were added. + + * glpapi/glp_write_mps.c + The routine for writing problem data in MPS format was added. + + * glpapi/glp_simplex1.c + Comprehensive driver to the simplex method was added. + + * glpapi/glp_pivoting.c + The routines glp_pivot_in() and glp_pivot_out() intended for + basis maintaining were added. + + * glprsm/create_rsm.c, glprsm/delete_rsm.c, glprsm/scale_rsm.c, + * glprsm/build_basis.c + Additional low level routines related to the simplex method + were added. + + * glpk.h, glpapi.h, glprsm.h + Additional specifications for new routines and data structures + were added. + + * sample/lpglpk30.c + A non-trivial example was added. It allows using GLPK as a base + LP solver for Concorde, a program for solving Traveling Salesman + Problem (TSP). For details see comments in 'lpglpk30.c'. + + * doc/newapi.txt + The document "Additional GLPK API Routines" that describes some + new API routines was included. + +Thu Jul 19 12:00:00 2001 Andrew Makhorin + + * GLPK 3.0 has been released. + + Now GLPK is provided with new API, which is intended for using + the package in more complex algorithmic schemes. + + * glpapi/old_api.c + All routines related to old API were gathered in one file named + 'old_api.c'. + + * glpapi/*.c + These routines that implement new API were added to the package. + + * include/glpk.h, include/glpapi.h + Specifications of new API routines and data structures were + added to these headers. Specifications of old API routines and + data structures were locked by #ifdef GLP_OLD_API directive. + + * doc/guide.texinfo + New edition of the document "GLPK User's Guide" that correspond + to new API was included. + +Thu Jun 14 12:00:00 2001 Andrew Makhorin + + * GLPK 2.4.1 has been released. + + * doc/glpk_ml.texinfo + The new document "Modeling Language GLPK/L" was included. + + * doc/glpk_ug.texinfo + New edition of the document "GLPK User's Guide" was included. + + * doc/language.txt + The preliminary document "GLPK/L Modeling Language: A Brief + description" was removed from the distribution, because it has + been replaced by the new document "Modeling Language GLPK/L". + + * glplang/l_spar.c + The routine comparison() was re-programmed in order to + implement the relation operation as specified in the language + description. + + * glpmip.h, glpmip/*.c + The partition 'glpmip' was renamed to 'glpbbm'. + +Thu May 10 12:00:00 2001 Andrew Makhorin + + * GLPK 2.4 has been released. + + Now GLPK includes an implementation of a preliminary version of + the GLPK/L modeling language. + + * glplang.h, glplang/*.c + The header 'glplang.h' and a set of routines that implements + the GLPK/L language processor (the partition 'glplang') were + added to the package. + + * doc/language.txt + The document "GLPK/L Modeling Language: A Brief Description + (Supplement to GLPK User's Guide)" in plain text format was + included in the package (see the file 'language.txt' in the + subdirectory 'doc' of the distribution). + + * ex/model1.lpm, ex/model2.lpm + Two examples of model descriptions written in GLPK/L were added + to the package. + + * sample/glpsol.c + This program was modified in order: a) to allow processing + model description written in GLPK/L; b) to allow solving pure + LP problem using the interior point method. + + * sample/glpipm.c + This program was removed from the package, because its function + was passed to the GLPSOL solver. + + * Makefile.in + This file was changed in order to install the GLPSOL solver + executable. + +Mon Apr 09 12:00:00 2001 Andrew Makhorin + + * GLPK 2.3 has been released. + + * glpmip.h, glpmip/*.c + These routines (that implement the branch-and-bound method) were + re-programmed in order to improve robustness of implementation. + In particular, heuristic routines were carried out from the main + driver routine. + + Additional GLPK API routines were documented. + + New edition of the document "GLPK User's Guide" was included in + the package. + + The preliminary document "Mixed Integer Programming Using GLPK + Version 2.2 (Supplement to GLPK User's Guide)" was removed from + the package, because this material was included in GLPK User's + Guide. + +Thu Mar 15 12:00:00 2001 Andrew Makhorin + + * GLPK 2.2 has been released. + + Now GLPK includes a tentative implementation of the + branch-and-bound procedure based on the dual simplex method for + mixed integer linear programming (MIP). + + The preliminary document "Mixed Integer Programming Using GLPK + Version 2.2 (Supplement to GLPK User's Guide)" was included into + the package in plain text format (see the file 'mip.txt' in the + subdirectory 'doc' of the distribution). + + * glpmip.h, glpmip/*.c, glpapi/glp_integer.c + These routines (that implement the branch-and-bound method) were + added to the package. + + * sample/glpsol.c + This program was modified in order to allow solving LP and MIP + problems. + + * glprsm/rsm_primal.c, glprsm/rsm_dual.c, glprsm/rsm_feas.c, + * glprsm/rsm1_driver.c + These routines (which are drivers to basic components of the + revised simplex method) were added to the package. + +Mon Feb 19 12:00:00 2001 Andrew Makhorin + + * GLPK 2.1 has been released. + + * glprsm.h, glprsm/*.c + These routines (that implement components of the revised simplex + method) were re-programmed and documented. + + The document "GLPK Implementation of the Revised Simplex Method" + was included into the package. + +Thu Jan 25 12:00:00 2001 Andrew Makhorin + + * GLPK 2.0 has been released. + + Now GLPK includes a tentative implementation of the primal-dual + interior point method for large-scale linear programming (for + more details see the file `NEWS' in the distribution). A number + of routines related to the interior point method were added to + the package. + + * insist.c + The routine `insist' and the macro of the same name were + introduced into the package in order to replace the standard + macro `assert'. Some routines require the expression specified + in the `assert' macro to be evaluated, but compiling the package + with NDEBUG option prevents from that. This bug was fixed due to + bug report provided by Peter A. Huegler . + + * Makefile.in + Minor bug was fixed due to a patch provided by Alexandre Oliva + . + +Wed Jan 10 12:00:00 2001 Andrew Makhorin + + * GLPK 1.1.2 has been released. + + * umalloc.c, ufree.c, create_pool.c, get_atom.c, get_atomv.c + These routines were changed in order to fix a bug due to + report provided by Andrew Hood . Because of + this bug data alignment error occured on the Sparc computer. + +Tue Dec 14 12:00:00 2000 Andrew Makhorin + + * GLPK 1.1.1 has been released. + + Minor bug was fixed in `Makefile.in'. + + GLPK Library Reference was included. + +Mon Nov 27 12:00:00 2000 Andrew Makhorin + + * GLPK 1.1 has been released. + + Minor changes were made in order to co-ordinate GLPK routines + and their descriptions. + + GLPK User's Guide was included. + +Fri Oct 20 12:00:00 2000 Andrew Makhorin + + * GLPK 1.0 has been released. diff --git a/WebAPP/SOLVERs/GLPK/glpk/INSTALL b/WebAPP/SOLVERs/GLPK/glpk/INSTALL new file mode 100644 index 000000000..cf76b2e78 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/INSTALL @@ -0,0 +1,198 @@ +INSTALLING GLPK ON YOUR COMPUTER +******************************** + +Unpacking the distribution file +------------------------------- +The GLPK package (like all other GNU software) is distributed in the +form of a packed archive. It is one file named `glpk-X.Y.tar.gz', where +`X' is the major version number and `Y' is the minor version number; +for example, the archive name might be `glpk-4.15.tar.gz'. + +In order to prepare the distribution for installation you should: + +1. Copy the GLPK distribution file to a working directory. + +2. Unpack the distribution file with the following command: + + gzip -d glpk-X.Y.tar.gz + + After unpacking the distribution file is automatically renamed to + `glpk-X.Y.tar'. + +3. Unarchive the distribution file with the following command: + + tar -x < glpk-X.Y.tar + + It automatically creates the subdirectory `glpk-X.Y' containing the + GLPK distribution. + +Configuring the package +----------------------- +After unpacking and unarchiving the GLPK distribution you should +configure the package, i.e. automatically tune it for your platform. + +Normally, you should just `cd' to the directory `glpk-X.Y' and run the +`configure' script, e.g. + + ./configure + +The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It also creates file `config.h' containing platform-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + +Running `configure' takes about a few seconds. While it is running, it +displays some messages that tell you what it is doing. If you don't want +to see the messages, run `configure' with its standard output redirected +to `dev/null'; for example, `./configure > /dev/null'. + +By default both static and shared versions of the GLPK library will be +compiled. Compilation of the shared librariy can be turned off by +specifying the `--disable-shared' option to `configure', e.g. + + ./configure --disable-shared + +If you encounter problems building the library try using the above +option, because some platforms do not support shared libraries. + +The GLPK package has some optional features listed below. By default +all these features are disabled. To enable a feature the corresponding +option should be passed to the configure script. + +--with-gmp Enable using the GNU MP bignum library + + This feature allows the exact simplex solver to use the GNU MP + bignum library. If it is disabled, the exact simplex solver uses the + GLPK bignum module, which provides the same functionality as GNU MP, + however, it is much less efficient. + + For details about the GNU MP bignum library see its web page at + . + +--enable-dl The same as --enable-dl=ltdl +--enable-dl=ltdl Enable shared library support (GNU) +--enable-dl=dlfcn Enable shared library support (POSIX) + + Currently this feature is only needed to provide dynamic linking to + ODBC and MySQL shared libraries (see below). + + For details about the GNU shared library support see the manual at + . + +--enable-odbc Enable using ODBC table driver (libiodbc) +--enable-odbc=unix Enable using ODBC table driver (libodbc) + + This feature allows transmitting data between MathProg model objects + and relational databases accessed through ODBC. + + For more details about this feature see the supplement "Using Data + Tables in the GNU MathProg Modeling Language" (doc/tables.*). + +--enable-mysql Enable using MySQL table driver (libmysql) + + This feature allows transmitting data between MathProg model objects + and MySQL relational databases. + + For more details about this feature see the supplement "Using Data + Tables in the GNU MathProg Modeling Language" (doc/tables.*). + +Compiling the package +--------------------- +Normally, you can compile (build) the package by typing the command: + + make + +It reads `Makefile' generated by `configure' and performs all necessary +jobs. + +If you want, you can override the `make' variables CFLAGS and LDFLAGS +like this: + + make CFLAGS=-O2 LDFLAGS=-s + +To compile the package in a different directory from the one containing +the source code, you must use a version of `make' that supports `VPATH' +variable, such as GNU `make'. `cd' to the directory where you want the +object files and executables to go and run the `configure' script. +`configure' automatically checks for the source code in the directory +that `configure' is in and in `..'. If for some reason `configure' is +not in the source code directory that you are configuring, then it will +report that it can't find the source code. In that case, run `configure' +with the option `--srcdir=DIR', where DIR is the directory that contains +the source code. + +Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Here are the `make' variables that you might want to override with +environment variables when running `configure'. + +For these variables, any value given in the environment overrides the +value that `configure' would choose: + +CC: C compiler program. The default is `cc'. + +INSTALL: Program used to install files. The default value is `install' + if you have it, otherwise `cp'. + +For these variables, any value given in the environment is added to the +value that `configure' chooses: + +DEFS: Configuration options, in the form `-Dfoo -Dbar ...'. + +LIBS: Libraries to link with, in the form `-lfoo -lbar ...'. + +Checking the package +-------------------- +To check the package, i.e. to run some tests included in the package, +you can use the following command: + + make check + +Installing the package +---------------------- +Normally, to install the GLPK package you should type the following +command: + + make install + +By default, `make install' will install the package's files in +`usr/local/bin', `usr/local/lib', etc. You can specify an installation +prefix other than `/usr/local' by giving `configure' the option +`--prefix=PATH'. Alternately, you can do so by consistently giving a +value for the `prefix' variable when you run `make', e.g. + + make prefix=/usr/gnu + make prefix=/usr/gnu install + +After installing you can remove the program binaries and object files +from the source directory by typing `make clean'. To remove all files +that `configure' created (`Makefile', `config.status', etc.), just type +`make distclean'. + +The file `configure.ac' is used to create `configure' by a program +called `autoconf'. You only need it if you want to remake `configure' +using a newer version of `autoconf'. + +Uninstalling the package +------------------------ +To uninstall the GLPK package, i.e. to remove all the package's files +from the system places, you can use the following command: + + make uninstall + +======================================================================== diff --git a/WebAPP/SOLVERs/GLPK/glpk/Makefile.am b/WebAPP/SOLVERs/GLPK/glpk/Makefile.am new file mode 100644 index 000000000..5a040f49a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/Makefile.am @@ -0,0 +1,7 @@ +## Process this file with automake to produce Makefile.in ## + +ACLOCAL_AMFLAGS=-I m4 + +SUBDIRS = src examples + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/Makefile.in b/WebAPP/SOLVERs/GLPK/glpk/Makefile.in new file mode 100644 index 000000000..7af088a5f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/Makefile.in @@ -0,0 +1,760 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ + THANKS config.guess config.sub install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + cscope distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUNDEFINED = @NOUNDEFINED@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I m4 +SUBDIRS = src examples +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done +cscopelist-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) + +clean-cscope: + -rm -f cscope.files + +cscope.files: clean-cscope cscopelist-recursive cscopelist + +cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr \ + distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + cscopelist-recursive ctags-recursive install-am install-strip \ + tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-cscope \ + clean-generic clean-libtool cscope cscopelist \ + cscopelist-recursive ctags ctags-recursive dist dist-all \ + dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/WebAPP/SOLVERs/GLPK/glpk/NEWS b/WebAPP/SOLVERs/GLPK/glpk/NEWS new file mode 100644 index 000000000..fdef77233 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/NEWS @@ -0,0 +1,2029 @@ +GLPK 4.65 (release date: Feb 16, 2018) + + The following new API routines for LP/MIP preprocessing were + added: + + glp_npp_alloc_wksp allocate the preprocessor workspace + glp_npp_load_prob load original problem instance + glp_npp_preprocess1 perform basic LP/MIP preprocessing + glp_npp_build_prob build resultant problem instance + glp_npp_postprocess postprocess solution to resultant problem + glp_npp_obtain_sol obtain solution to original problem + glp_npp_free_wksp free the preprocessor workspace + + See doc/npp.txt for detailed description of these API routines. + + A new, more robust implementation of locally valid simple cover + cuts was included in the MIP solver. + + The API routine glp_init_iocp was changed to enable long-step + option of the dual simplex by default. + +GLPK 4.64 (release date: Dec 02, 2017) + + The dual simplex solver routine was changed to perform more + aggressive perturbation to prevent dual degeneracy and avoid + stalling even if the current dual basic solution is strongly + feasible (mainly if the objective is zero). Thanks to David + Monniaux for bug report + and example model. + + The exact simplex solver routine was changed to perform + terminal output according to the verbosity level (specified by + the control parameter smcp.msg_lev). Thanks to Jeroen Demeyer + for bug report. + + A minor bug (related to MS Windows version) was fixed. Thanks + to Heinrich Schuchardt for bug report. + + An example model (Graceful Tree Labeling Problem) in MathProg + was added. Thanks to Mike Appleby for + contribution. + + Three example models (Power plant LP scheduler, Neumann CA + grid emulator generator) in MathProg and one in Cplex LP format + were added. Thanks to Peter Naszvadi for + contribution. + +GLPK 4.63 (release date: Jul 25, 2017) + + A "smart" LP perturbation was implemented in the primal and + dual simplex solvers. Now LP is perturbed only if it is + necessary, and by default perturbation is not activated. + The sum of primal infeasibilites that appears in the terminal + output of the primal simplex solver (as "inf = ...") now + corresponds to the original bounds of variables. This allows to + see how much perturbed solution violates the original bounds. + + The long-step technique was implemented for phase I of the + primal simplex solver. This feature can be enabled by + specifying --flip option for glpsol or by specifying + glp_smcp.r_test = GLP_RT_FLIP on api level. For many LP + instances the long-step technique allows reducing the number + of simplex iterations to 30-70%. Please note that unlike the + dual simplex, where this technique can be used on both phase I + and II, for the primal simplex it can be used only on phase I, + where the sum of primal infeasibilities (which is a convex + piecewise linear function) is minimized. + + An internal objective scaling was included in both primal and + dual simplex solvers. For many LP/MIP instances this feature + improves numerical stability (for the dual solver) and prevents + cycling near the optimum (for the primal solver). + + The Posix version of glp_time (glpk/src/env/time.c) was changed + to resolve time_t issue on msys2. Thanks to Rob Schroeder + for bug report. + + Three new example models in MathProg were added: + life_goe.mod (Conway's Game of Life garden of eden checker); + tiling.mod (Rectifiable polyomino tilings generator); + toto.mod (Covering code generator). + Thanks to Peter Naszvadi for contribution. + +GLPK 4.62 (release date: Jun 14, 2017) + + The bound perturbation technique was included in the primal + simplex solver to improve numerical stability and avoid cycling. + Currently this feature is enabled by default. + + A range bug was fixed in the MPS reading routine. Thanks to + Chris Matrakidis for bug report and patch. + + Changes were made to provide 64-bit portability of the Minisat + solver. Thanks to Chris Matrakidis for + patch. + + Calls to non-thread-safe functions gmtime, strerror, and strtok + were replaced by calls to corresponding thread-safe equivalents + (gmtime_r, strerror_r, and strtok_r for GNU/Linux). + +GLPK 4.61 (release date: Jan 22, 2017) + + An option was added to build a re-entrant version of the + package suitable for running in a multi-threaded environment. + This option is enabled by default on configuring the package + if the compiler used supports the thread local storage class + specifier (e.g. _Thread_local or __thread). Thanks to + David Monniaux for suggestion and + Chris Matrakidis for configure.ac patch. + + A re-entrant version of the package allows running multiple + independent instances of glpk in different threads of a multi- + threaded application. Note that glpk is not thread-safe by + design, so if the application calls glpk routines from multiple + threads, no thread may access glpk program objects (glp_prob, + glp_tree, etc.) created by other threads; besides, each thread + before termination should call the API routine glp_free_env to + prevent memory leak. + + A DLL support was added. Thanks to Heinrich Schuchardt + for contribution. + + Some changes were made to allow compiling the package using + stdcall calling convention (this is needed only on compiling + GLPK with MSVC to run under MS Windows). + +GLPK 4.60 (release date: Apr 01, 2016) + + Some improvements were made in the primal and dual simplex + solvers to make the solution process more numerically stable. + + An experimental long-step ratio test feature was added to the + dual simplex. On API level this feature is available thru the + GLP_RT_FLIP option. For glpsol it is available thru the options + --flip (for MIP) or --flip and --dual (for LP). This feature is + not documented yet. + + Additional check was added to reject wrong solutions sometimes + reported by the PROXY heuristic. + + A bug (memory leak) was fixed in the FPUMP heuristic routine. + Thanks to for bug report. + + The header sql.h was renamed to avoid conflicts with standard + ODBC headers. Thanks to Noli Sicad for bug + report. + +GLPK 4.59 (release date: Mar 11, 2016) + + This is a maintainer release. + + Some bugs were fixed and some improvements were made in the MIP + solver. Thanks to Chris Matrakidis for bug + reports and patches. + + The data file format used by API routines glp_read_graph and + glp_write_graph was changed. For more details please see the + document "GLPK: Graph and Network Routines" included in the + distribution. + + Translation of the document "Modeling Language GNU MathProg" + to Brazilian Portuguese (pt-BR) was included (in LaTeX and pdf + formats). Thanks to Joao Flavio de Freitas Almeida + for contribution. + +GLPK 4.58 (release date: Feb 18, 2016) + + The solution file format used by API routines glp_read_sol, + glp_write_sol, glp_read_ipt, glp_write_ipt, glp_read_mip, and + glp_write_mip was changed. For more details please see the GLPK + reference manual included in the distribution. + + The tan function (trigonometric tangent) was added to + GNU MathProg modeling language. Thanks to Chris Matrakidis + for contribution. + + A new version of the document "Modeling Language GNU MathProg" + in Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + + A check to determine if libtool needs '-no-undefined' flag to + build shared libraries on some platforms was added. + Thanks to Marco Atzeri and Heinrich + Schuchardt for suggestion. + + A script to regenerate the configure script and the Makefiles + was added. Thanks to Heinrich Schuchardt . + +GLPK 4.57 (release date: Nov 08, 2015) + + A new, more efficient implementation of the dual simplex method + was included in the package. This new implementation replaces + the old one, which was removed. + + Option sr_heur was added to struct glp_iocp to enable/disable + the simple rounding heuristic used by the MIP solver. Thanks to + Chris Matrakidis for suggestion. + + New API routine glp_at_error was added and documented. Thanks + to Jeroen Demeyer for suggestion. + + Some minor typos were corrected in the GLPK documentation. + Thanks to Anton Voropaev for typo + report. + + An example application program TSPSOL was added. It uses the + GLPK MIP optimizer to solve the Symmetric Traveling Salesman + Problem and illustrates "lazy" constraints generation. For more + details please see glpk/examples/tsp/README. + +GLPK 4.56 (release date: Oct 01, 2015) + + A new, more efficient and more robust implementation of the + primal simplex method was included in the package. This new + implementation replaces the old one, which was removed. + + A bug was fixed in a basis factorization routine. (The bug + appeared if the basis matrix was structurally singular having + duplicate row and/or column singletons.) Thanks to Martin Jacob + for bug report. + + Scripts to build GLPK with Microsoft Visual Studio 2015 were + added. Thanks to Xypron for contribution + and testing. + +GLPK 4.55 (release date: Aug 22, 2014) + + Some internal (non-API) routines to estimate the condition of + the basis matrix were added. These routines are mainly intended + to be used by the simplex-based solvers. + + Two open modes "a" and "ab" were added to GLPK I/O routines. + Thanks to Pedro P. Wong for bug report. + + Minor bug was fixed in the solver glpsol (command-line options + --btf, --cbg, and --cgr didn't work properly). + + A serious bug was fixed in a basis factorization routine used + on the dense phase. (The bug might appear only if the number of + rows exceeded sqrt(2**31) ~= 46,340 and caused access violation + exception because of integer overflow.) Thanks to Mark Meketon + for bug report. + + Two API routines glp_alloc and glp_realloc were documented. + Thanks to Brian Gladman for suggestion. + + Translation of the document "Modeling Language GNU MathProg" + to Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + +GLPK 4.54 (release date: Mar 28, 2014) + + Block-triangular LU-factorization was implemented to be used + on computing an initial factorization of the basis matrix. + + A new version of the Schur-complement-based factorization + module was included in the package. Now it can be used along + with plain as well as with block-triangular LU-factorization. + + Currently the following flags can be used to specify the type + of the basis matrix factorization (glp_bfcp.type): + + GLP_BF_LUF + GLP_BF_FT LUF, Forrest-Tomlin update (default) + GLP_BF_LUF + GLP_BF_BG LUF, Schur complement, Bartels-Golub + update + GLP_BF_LUF + GLP_BF_GR LUF, Schur complement, Givens rotation + update + GLP_BF_BTF + GLP_BF_BG BTF, Schur complement, Bartels-Golub + update + GLP_BF_BTF + GLP_BF_GR BTF, Schur complement, Givens rotation + update + + In case of GLP_BF_FT the update is applied to matrix U, while + in cases of GLP_BF_BG and GLP_BF_GR the update is applied to + the Schur complement. + + Corresponding new options --luf and --btf were added to glpsol. + + For more details please see a new edition of the GLPK reference + manual included in the distribution. + + A minor bug (in reporting the mip solution status) was fixed. + Thanks to Remy Roy for bug report. + + A call to "iodbc-config --cflags" was added in configure.ac + to correctly detect iodbc flags. Thanks to Sebastien Villemot + for patch. + +GLPK 4.53 (release date: Feb 13, 2014) + + The API routine glp_read_mps was changed to remove free rows. + + A bug was fixed in the API routine glp_read_lp. Thanks to + Gabriel Hackebeil for bug report. + + The zlib compression library used by some GLPK routines and + included in the package was downgraded from 1.2.7 to 1.2.5 (as + in GLPK 4.50) because of addressability bugs on some 64-bit + platforms. Thanks to Carlo Baldassi + for bug report. + + A bug was fixed in a routine that reads gzipped files. Thanks + to Achim Gaedke for bug report. + + Two API routines glp_get_it_cnt and glp_set_it_cnt were added. + Thanks to Joey Rios for suggestion. + + All obsolete GLPK API routines (prefixed with lpx) were removed + from the package. + + A set of routines that simulate the old GLPK API (as defined + in 4.48) were added; see examples/oldapi/api/lpx.c. Thanks to + Jan Engelhardt for suggestion. + + A namespace bug was fixed in the SQL table drive module. Thanks + to Dennis Schridde for bug report. + +GLPK 4.52.1 (release date: Jul 28, 2013) + + This is a bug-fix release. + + A version information bug in Makefile.am was fixed. Thanks to + Sebastien Villemot for bug report. + +GLPK 4.52 (release date: Jul 18, 2013) + + The clique cut generator was essentially reimplemented, and now + it is able to process very large and/or dense conflict graphs. + + A simple rounding heuristic was added to the MIP optimizer. + + Some bugs were fixed in the proximity search heuristic routine. + Thanks to Giorgio Sartor <0gioker0@gmail.com>. + + New command-line option '--proxy [nnn]' was added to glpsol to + enable using the proximity search heuristic. + + A bug (incorrect processing of LI column indicator) was fixed + in the mps format reading routine. Thanks to Charles Brixko for + bug report. + +GLPK 4.51 (release date: Jun 19, 2013) + + Singleton and dense phases were implemented on computing + LU-factorization with Gaussian elimination. The singleton phase + is a feature that allows processing row and column singletons + on initial elimination steps more efficiently. The dense phase + is a feature used on final elimination steps when the active + submatrix becomes relatively dense. It significantly reduces + the time needed, especially if the active submatrix fits in CPU + cache, and improves numerical accuracy due to full pivoting. + + The API routine glp_adv_basis that constructs advanced initial + LP basis was replaced by an improved version, which (unlike the + old version) takes into account numerical values of constraint + coefficients. + + The proximity search heuristic for MIP was included in the GLPK + integer optimizer glp_intopt. On API level the heuristic can be + enabled by setting the parameter ps_heur in glp_iocp to GLP_ON. + This feature is also available in the solver glpsol through + command-line option '--proxy'. Many thanks to Giorgio Sartor + <0gioker0@gmail.com> for contribution. + + A bug was fixed that caused numerical instability in the FPUMP + heuristic. + +GLPK 4.50 (release date: May 24, 2013) + + A new version of LU-factorization routines were added. + Currently this version provides the same functionality as the + old one, however, the new version allows further improving. + + Old routines for FHV-factorization used to update the basis + factorization were replaced by a new version conforming to the + new version of LU-factorization. + + Some clarifications about using the name index routines were + added. Thanks to Xypron for suggestion. + + Some typos were corrected in the MathProg language reference. + Thanks to Jeffrey Kantor for report. + + A serious bug (out-of-range indexing error) was *tentatively* + fixed in the routine glp_relax4. Unfortunatly, this bug is + inherited from the original Fortran version of the RELAX-IV + code (for details please see ChangeLog), and since the code is + very intricate, the bug is still under investigation. Thanks to + Sylvain Fournier for bug report. + +GLPK 4.49 (release date: Apr 16, 2013) + + The new API routine glp_mincost_relax4, which is a driver to + relaxation method of Bertsekas and Tseng (RELAX-IV), was added + to the package. RELAX-IV is a code for solving minimum cost + flow problems. On large instances it is 100-1000 times faster + than the standard primal simplex method. Prof. Bertsekas, the + author of the original RELAX-IV Fortran code, kindly permitted + to include a C translation of his code in GLPK under GPLv3. + + A bug (wrong dual feasibility test) was fixed in API routine + glp_warm_up. Thanks to David T. Price + for bug report. + + Obsolete API routine lpx_check_kkt was replaced by new routine + glp_check_kkt. + + IMPORTANT: All old API routines whose names begin with 'lpx_' + were removed from API level and NO MORE AVAILABLE. + +GLPK 4.48 (release date: Jan 28, 2013) + + This is a maintainer release. + + Some minor changes in API (glpk.h) were made. For details + please see ChangeLog. + + Some bugs/typos were fixed. Thanks to + Raniere Gaia Costa da Silva, + Heinrich Schuchardt , and + Robbie Morrison for reports. + +GLPK 4.47 (release date: Sep 09, 2011) + + The new API routine glp_intfeas1 was added to the package. + This routine is a tentative implementation of the integer (0-1) + feasibility solver based on the CNF-SAT solver (which currently + is MiniSat). It may be used in the same way as glp_intopt to + find either any integer feasible solution or a solution, for + which the objective function is not worse than the specified + value. Detailed description of this routine can be found in the + document "CNF Satisfiability Problem", which is included in the + distribution (see doc/cnfsat.pdf). + + The following two options were added to glpsol: + + --minisat translate 0-1 feasibility problem to CNF-SAT + problem and solve it with glp_intfeas1/MiniSat + (if the problem instance is already in CNF-SAT + format, no translation is performed) + + --objbnd bound add inequality obj <= bound (minimization) or + obj >= bound (maximization) to 0-1 feasibility + problem (this option assumes --minisat) + + The paint-by-numbers puzzle model (pbn.mod) included in the + distribution is a nice example of the 0-1 feasibility problem, + which can be efficiently solved with glp_intfeas1/MiniSat. This + model along with a brief instruction (pbn.pdf) and benchmark + examples from encoded in GNU MathProg (*.dat) can + be found in subdirectory examples/pbn/. + + The glpsol lp/mip solver was modified to bypass postprocessing + of MathProg models if the solution reported is neither optimal + nor feasible. + + A minor bug in examples/Makefile.am was fixed to correctly + build glpk in a separate directory. Thanks to Marco Atzeri + for bug report and patch. + +GLPK 4.46 (release date: Aug 09, 2011) + + The following new API routines were added: + + glp_read_cnfsat read CNF-SAT problem data in DIMACS format + glp_check_cnfsat check for CNF-SAT problem instance + glp_write_cnfsat write CNF-SAT problem data in DIMACS format + glp_minisat1 solve CNF-SAT problem instance with MiniSat + + The routine glp_minisat1 is a driver to MiniSat, a CNF-SAT + solver developed by Niklas Een and Niklas Sorensson, Chalmers + University of Technology, Sweden. This routine is similar to + the routine glp_intopt, however, it is intended to solve a 0-1 + programming problem instance, which is the MIP translation of + a CNF-SAT problem instance. + + Detailed description of these new API routines can be found in + the document "CNF Satisfiability Problem", which is included in + the distribution (see files doc/cnfsat.tex and doc/cnfsat.pdf). + + The following new glpsol command-line options were added: + + --cnf filename read CNF-SAT problem instance in DIMACS + format from filename and translate it to MIP + --wcnf filename write CNF-SAT problem instance in DIMACS + format to filename + --minisat solve CNF-SAT problem instance with MiniSat + solver + + The zlib compression library (version 1.2.5) was ANSIfied, + modified according to GLPK requirements and included in the + distribution as an external software module. Thus, now this + feature is platform independent. + + Some bugs were fixed in the SQL table driver. Thanks to Xypron + . + +GLPK 4.45 (release date: Dec 05, 2010) + + This is a bug-fix release. + + Several bugs/typos were fixed. Thanks to + Xypron , + Robbie Morrison , and + Ali Baharev for reports. + + Some glpk documents was re-formatted and merged into a single + document. Now the glpk documentation consists of the following + three main documents (all included in the distribution): + + GLPK: Reference Manual + + GLPK: Graph and Network Routines + + Modeling Language GNU MathProg: Language Reference + +GLPK 4.44 (release date: Jun 03, 2010) + + The following suffixes for variables and constraints were + implemented in the MathProg language: + + .lb (lower bound), + .ub (upper bound), + .status (status in the solution), + .val (primal value), and + .dual (dual value). + + Thanks to Xypron for draft implementation + and testing. + + Now the MathProg language allows comment records (marked by + '#' in the very first position) in CSV data files read with the + table statements. Note that the comment records may appear only + in the beginning of a CSV data file. + + The API routine glp_cpp to solve the Critical Path Problem was + added and documented. + +GLPK 4.43 (release date: Feb 20, 2010) + + This is a maintainer release. + + `configure.ac' was changed to allow building the package under + Mac OS and Darwin with ODBC support. + Thanks to Xypron for suggestions and Noli + Sicad for testing. + + The SQL table driver was improved to process NULL data. Thanks + to Xypron . + + Some bugs were fixed in the LP/MIP preprocessor. + +GLPK 4.42 (release date: Jan 13, 2010) + + The following new API routines were added: + + glp_check_dup check for duplicate elements in sparse + matrix + glp_sort_matrix sort elements of the constraint matrix + glp_read_prob read problem data in GLPK format + glp_write_prob write problem data in GLPK format + glp_analyze_bound analyze active bound of non-basic variable + glp_analyze_coef analyze objective coefficient at basic + variable + glp_print_ranges print sensitivity analysis report (this + routine replaces lpx_print_sens_bnds and + makes it deprecated) + + For description of these new routines and the GLPK LP/MIP + format see a new edition of the reference manual included in + the distribution. (Chapter "Graph and network API routines" was + carried out from the main reference manual and included in the + distribution as a separate document.) + + The following new command-line options were added to the stand- + alone solver glpsol: + --glp filename read problem data in GLPK format + --wglp filename write problem data in GLPK format + --ranges filename print sensitivity analysis report (this + option replaces --bounds) + + Now all GLPK routines performing file I/O support special + filenames "/dev/stdin", "/dev/stdout", and "/dev/stderr", which + can be specified in the same way as regular filenames. This + feature is plaform-independent. + +GLPK 4.41 (release date: Dec 21, 2009) + + The following new API routies were added: + + glp_transform_row transform explicitly specified row + glp_transform_col transform explicitly specified column + glp_prim_rtest perform primal ratio test + glp_dual_rtest perform dual ratio test + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The following API routines are deprecated: lpx_transform_row, + lpx_transform_col, lpx_prim_ratio_test, lpx_dual_ratio_test. + + Some improvements were made in the MIP solver (glp_intopt). + + The SQL table driver used to read/write data in MathProg models + was changed to allow multiple arguments separated by semicolon + in SQL statements. Thanks to Xypron . + + Two new options were added to the glpsol stand-alone solver: + --seed value (to initialize the pseudo-random number generator + used in MathProg models with specified value), and + --ini filename (to use a basis previously saved with -w option + as an initial basis on solving similar LP's). + + Two new MathProg example models were included. Thanks to + Nigel Galloway and Noli Sicad + for contribution. + + Scripts to build GLPK with Microsoft Visual Studio 2010 for + both 32-bit and 64-bit Windows were included. Thanks to Xypron + for contribution and testing. + +GLPK 4.40 (release date: Nov 03, 2009) + + The following new API routines were added: + + glp_del_vertices remove vertices from graph + glp_del_arc remove arc from graph + glp_wclique_exact find maximum weight clique with the exact + algorithm developed by Prof. P. Ostergard + glp_read_ccdata read graph in DIMACS clique/coloring + format + glp_write_ccdata write graph in DIMACS clique/coloring + format + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The hybrid pseudocost branching heuristic was included in the + MIP solver. It is available on API level (iocp.br_tech should + be set to GLP_BR_PCH) and in the stand-alone solver glpsol + (via the command-line option --pcost). This heuristic may be + useful on solving hard MIP instances. + + The branching heuristic by Driebeck and Tomlin (used in the + MIP solver by default) was changed to switch to branching on + most fractional variable if an lower bound of degradation of + the objective is close to zero for all branching candidates. + + A bug was fixed in the LP preprocessor (routine npp_empty_col). + Thanks to Stefan Vigerske for the + bug report. + + A bug was fixed and some improvements were made in the FPUMP + heuristic module. Thanks to Xypron . + + A bug was fixed in the API routine glp_warm_up (dual + feasibility test was incorrect in maximization case). Thanks to + Uday Venkatadri for the bug report. + +GLPK 4.39 (release date: Jul 26, 2009) + + The following new API routines were added: + + glp_warm_up "warm up" LP basis + glp_set_vertex_name assign (change) vertex name + glp_create_v_index create vertex name index + glp_find_vertex find vertex by its name + glp_delete_v_index delete vertex name index + glp_read_asnprob read assignment problem data in DIMACS + format + glp_write_asnprob write assignment problem data in DIMACS + format + glp_check_asnprob check correctness of assignment problem + data + glp_asnprob_lp convert assignment problem to LP + glp_asnprob_okalg solve assignment problem with the + out-of-kilter algorithm + glp_asnprob_hall find bipartite matching of maxumum + cardinality with Hall's algorithm + + Also were added some API routines to read plain data files. + + The API routines glp_read_lp and glp_write_lp to read/write + files in CPLEX LP format were re-implemented. Now glp_write_lp + correctly writes double-bounded (ranged) rows by introducing + slack variables rather than by duplicating the rows. + + For description of these new routines see a new edition of the + reference manual included in the distribution. + + The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to + Niels Klitgord for bug report. + + The message "Crashing..." was changed to "Constructing initial + basis..." due to suggestion by Thomas Kahle . + + Some typos were corrected in glpsol output messages. Thanks to + Xypron for patch. + +GLPK 4.38 (release date: May 02, 2009) + + API routines glp_read_mps and glp_write_mps were improved. + + Some improvements were made in the dual simplex routines. + + Two external software modules AMD and COLAMD were included in + the distribution (for more details please see src/amd/README + and src/colamd/README). Now they are used in the interior-point + solver to reorder the matrix prior to Cholesky factorization. + + API routine glp_ipt_status may return two new statuses due to + changes in the routine glp_interior. For details please see the + reference manual included in the distribution. + + A minor bug was fixed in the graph/network routines. Thanks to + Nelson H. F. Beebe for bug report. + +GLPK 4.37 (release date: Mar 29, 2009) + + The 0-1 Feasibility Pump heuristic was included in the GLPK + integer optimizer glp_intopt. On API level the heuristic can be + enabled by setting the parameter fp_heur in glp_iocp to GLP_ON. + This feature is also available in the solver glpsol through + command-line option '--fpump'. For more details please see the + reference manual included in the distribution. + + The following new API routines were added: + + glp_print_sol write basic solution in printable format + glp_print_ipt write interior-point solution in printable + format + glp_print_mip write MIP solution in printable format + glp_read_graph read (di)graph from plain text file + glp_write_graph write (di)graph to plain text file + glp_weak_comp find all weakly connected components + glp_strong_comp find all strongly connected components + + The following API routines are deprecated: lpx_print_sol, + lpx_print_ips, lpx_print_mip, lpx_print_prob (the latter is + equivalent to glp_write_lp). + + A bug was fixed in the interior-point solver (glp_interior) to + correctly compute dual solution components when the problem is + scaled. + + The files configure.ac and Makefile.am were changed: + (a) to allow using autoreconf/autoheader; + (b) to allow building the package in a directory other than its + source directory. + Thanks to Marco Atzeri for bug report. + + An example model in the GNU MathProg language was added. + Thanks to Larry D'Agostino for + contribution. + +GLPK 4.36 (release date: Feb 06, 2009) + + The following new API routines were added to the package: + + glp_mincost_okalg find minimum-cost flow with out-of-kilter + algorithm + glp_maxflow_ffalg find maximal flow with Ford-Fulkerson + algorithm + + For detailed description of these new routines and related data + structures see chapter "Graph and Network API Routines" in a new + edition of the reference manual included in the distribution. + + The following two new command-line options were added to the + solver glpsol: + + --mincost read min-cost flow data in DIMACS format + --maxflow read maximum flow data in DIMACS format + + Duplicate symbols in the header glpk.h were removed to allow + using swig. + Thanks to Kelly Westbrooks and + Nigel Galloway for suggestion. + + A minor defect was fixed in the routine glp_write_lp. + Thanks to Sebastien Briais for bug report. + + A minor bug was fixed in the SQL module. + Thanks to Xypron for patch. + + Some new example models in the GNU MathProg modeling language + were added. Thanks to Sebastian Nowozin and + Nigel Galloway for contribution. + +GLPK 4.35 (release date: Jan 09, 2009) + + The following new API routines were added to the package: + + glp_create_graph create graph + glp_set_graph_name assign (change) graph name + glp_add_vertices add new vertices to graph + glp_add_arc add new arc to graph + glp_erase_graph erase graph content + glp_delete_graph delete graph + glp_read_mincost read minimum cost flow problem data in + DIMACS format + glp_write_mincost write minimum cost flow problem data in + DIMACS format + glp_mincost_lp convert minimum cost flow problem to LP + glp_netgen Klingman's network problem generator + glp_gridgen grid-like network problem generator + glp_read_maxflow read maximum flow problem data in DIMACS + format + glp_write_maxflow write maximum flow problem data in DIMACS + format + glp_maxflow_lp convert maximum flow problem to LP + glp_rmfgen Goldfarb's maximum flow problem generator + + For detailed description of these new routines and related data + structures see chapter "Graph and Network API Routines" in a new + edition of the reference manual included in the distribution. + + A minor change were made in the internal routine xputc. Thanks + to Luiz Bettoni for suggestion. + + A minor bug was fixed in the internal routine mpl_fn_time2str. + Thanks to Stefan Vigerske for bug report. + +GLPK 4.34 (release date: Dec 04, 2008) + + The GNU MathProg modeling language was supplemented with three + new built-in functions: + + gmtime obtaining current calendar time + str2time converting character string to calendar time + time2str converting calendar time to character string + + (Thanks to Xypron .) + + For detailed description of these functions see Appendix A in + the document "Modeling Language GNU MathProg", a new edition of + which was included in the distribution. + + A bug was fixed in the MIP solver. Thanks to Nigel Galloway + for bug report. + + A new makefile was added to build the GLPK DLL with Microsoft + Visual Studio Express 2008 for 64-bit Windows. Thanks to Xypron + for contribution and testing. + +GLPK 4.33 (release date: Oct 30, 2008) + + The following new API routines were added to the package: + glp_copy_prob copy problem object content + glp_exact solve LP in exact arithmetic + (makes lpx_exact deprecated) + glp_get_unbnd_ray determine variable causing unboundedness + (makes lpx_get_ray_info deprecated) + glp_interior solve LP with interior-point method + (makes lpx_interior deprecated) + + The following new API routines for processing models written in + the GNU Mathprog language were added to the package: + glp_mpl_alloc_wksp allocate the translator workspace + glp_mpl_read_model read and translate model section + glp_mpl_read_data read and translate data section + glp_mpl_generate generate the model + glp_mpl_build_prob build LP/MIP instance from the model + glp_mpl_postsolve postsolve the model + glp_mpl_free_wksp deallocate the translator workspace + (These routines make lpx_read_model deprecated.) + + For description of all these new API routines see the reference + manual included in the distribution. + + A crude implementation of CPLEX-like interface to GLPK API was + added to the package. Currently it allows using GLPK as a core + LP solver for Concorde, a well known computer code for solving + the symmetric TSP. For details see examples/cplex/README. + + Some bugs were fixed in the SQL table driver. Thanks to Xypron + . + +GLPK 4.32 (release date: Oct 03, 2008) + + The following new features were included in the MIP solver + (the API routine glp_intopt): + + * MIP presolver + * mixed cover cut generator + * clique cut generator + * Euclidean reduction of the objective value + + Due to changes the routine glp_intopt may additionally return + GLP_ENOPFS, GLP_ENODFS, and GLP_EMIPGAP. + + The API routines lpx_integer are lpx_intopt are deprecated, + since they are completely superseded by glp_intopt. + + The following new branch-and-cut API routines were added: + glp_ios_row_attr determine additional row attributes + glp_ios_pool_size determine current size of the cut pool + glp_ios_add_row add constraint to the cut pool + glp_ios_del_row delete constraint from the cut pool + glp_ios_clear_pool delete all constraints from the cut pool + + For description of these new routines see the reference manual + included in the distribution. + + The stand-alone solver glpsol was changed to allow multiple + data files. + + A new edition of the supplement "Using Data Tables in the GNU + MathProg Modeling Language" was included. + + As usual, some bugs were fixed (in the MathProg translator). + Thanks to Xypron . + +GLPK 4.31 (release date: Sep 02, 2008) + + The core LP solver based on the dual simplex method was + re-implemented and now it provides both phases I and II. + + The following new API routines were added: + glp_scale_prob automatic scaling of problem data + glp_std_basis construct standard initial LP basis + glp_adv_basis construct advanced initial LP basis + glp_cpx_basis construct Bixby's initial LP basis + + For description of these new routines see the reference manual + included in the distribution. + + The following API routines are deprecated: + lpx_scale_prob, lpx_std_basis, lpx_adv_basis, lpx_cpx_basis. + + Necessary changes were made in memory allocation routines to + resolve portability issues for 64-bit platforms. + + New version of the routine lpx_write_pb to write problem data + in OPB (pseudo boolean format) was added to the package. Thanks + to Oscar Gustafsson for the contribution. + + Two new makefiles were added to build the package for 32- and + 64-bit Windows with Microsoft Visual Studio Express 2008. + Thanks to Heinrich Schuchardt (aka + Xypron) for the contribution and testing. + + Two new makefiles were added to build the package with Digital + Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (for 32-bit Windows). + +GLPK 4.30 (release date: Aug 13, 2008) + + The core LP solver based on the primal simplex method was + re-implemented to allow its further improvements. Currently the + new version provides the same features as the old one, however, + it is a bit faster and more numerically stable. + + Some changes were made in the MathProg translator to allow <, + <=, >=, and > on comparing symbolic values. Thanks to Heinrich + Schuchardt for patches. + + Internal routine set_d_eps in the exact LP solver was changed + to prevent approximation errors in case of integral data. + Thanks to Markus Pilz for bug report. + +GLPK 4.29 (release date: Jul 06, 2008) + + The configure script was changed to disable all optional + features by default. For details please see file INSTALL. + + The following new API routines were added: + glp_erase_prob erase problem object content + glp_read_mps read problem data in MPS format + glp_write_mps write problem data in MPS format + glp_read_lp read problem data in CPLEX LP format + glp_write_lp write problem data in CPLEX LP format + + For description of these new routines see the reference manual + included in the distribution. + + The following API routines are deprecated: + lpx_read_mps, lpx_read_freemps, lpx_write_mps, + lpx_write_freemps, lpx_read_cpxlp, and lpx_write_cpxlp. + + Two bugs were fixed. Thanks to + Anne-Laurence Putz and + Xypron for bug report. + +GLPK 4.28 (release date: Mar 25, 2008) + + The iODBC and MySQL table drivers, which allows transmitting + data between MathProg model objects and relational databases, + were re-implemented to replace a static linking by a dynamic + linking to corresponding shared libraries. + Many thanks to Heinrich Schuchardt + for the contribution, Rafael Laboissiere + for useful advices concerning the shared library support under + GNU/Linux, and Vijay Patil for testing + this feature under Windows XP. + + A new optional feature was added to the package. This feature + is based on the zlib data compression library and allows GLPK + API routines and the stand-alone solver to read and write + compressed data files performing compression/decompression "on + the fly" (compressed data files are recognized by suffix `.gz' + in the file name). It may be useful in case of large MPS files + to save the disk space (up to ten times). + + The `configure' script was re-implemented. Now it supports the + following specific options: + + --with-gmp Enable using the GNU MP bignum library + --without-gmp Disable using the GNU MP bignum library + --with-zlib Enable using the zlib data compression + library + --without-zlib Disable using the zlib data compression + library + --enable-dl Enable shared library support (auto check) + --enable-dl=ltdl Enable shared library support (GNU) + --enable-dl=dlfcn Enable shared library support (POSIX) + --disable-dl Disable shared library support + --enable-odbc Enable using ODBC table driver + --disable-odbc Disable using ODBC table driver + --enable-mysql Enable using MySQL table driver + --disable-mysql Disable using MySQL table driver + + For more details please see file INSTALL. + +GLPK 4.27 (release date: Mar 02, 2008) + + Three new table drivers were added to the MathProg translator: + + xBASE built-in table driver, which allows reading and writing + data in .dbf format (only C and N fields are supported); + + MySQL table driver, which provides connection to a MySQL + database; + + iODBC table driver, which provides connection to a database + through ODBC. + + The MySQL and iODBC table drivers were contributed to GLPK by + Heinrich Schuchardt . + + The table driver is a program module which allows transmitting + data between MathProg model objects and external data tables. + + For detailed description of the table statement and table + drivers see the document "Using Data Tables in the GNU MathProg + Modeling Language" (file doc/tables.txt) included in the + distribution. Some examples which demonstrate using MySQL and + iODBC table drivers can be found in subdirectory examples/sql. + +GLPK 4.26 (release date: Feb 17, 2008) + + The table statement was implemented in the GNU MathProg + modeling language. This new feature allows reading data from + external tables into model objects such as sets and parameters + as well as writing results of computations to external tables. + + A table is a (unordered) set of records, where each record + consists of the same number of fields, and each field is + provided with a unique symbolic name called the field name. + + Currently the GLPK package has the only built-in table driver, + which supports tables in the CSV (comma-separated values) file + format. This format is very simple and supported by almost all + spreadsheets and database management systems. + + Detailed description of the table statement and CSV format can + be found in file doc/tables.txt, included in the distribution. + +GLPK 4.25 (release date: Dec 19, 2007) + + A tentative implementation of Gomory's mixed integer cuts was + included in the branch-and-cut solver. To enable generating + Gomory's cuts the control parameter gmi_cuts passed to the + routine glp_intopt should be set to GLP_ON. This feature is + also available in the solver glpsol through command-line option + '--gomory'. For more details please see the reference manual + included in the distribution. + +GLPK 4.24 (release date: Nov 21, 2007) + + A tentative implementation of MIR (mixed integer rounding) cuts + was included in the MIP solver. To enable generating MIR cuts + the control parameter mir_cuts passed to the routine glp_intopt + should be set to GLP_ON. This feature is also available in the + stand-alone solver glpsol via command-line option '--mir'. For + more details please see the reference manual included in the + distribution. + + The implementation is mainly based on the following two papers: + + 1. H. Marchand and L. A. Wolsey. Aggregation and mixed integer + rounding to solve MIPs. CORE discussion paper 9839, CORE, + Universite catholique de Louvain, June 1998. + + 2. G. Andreello, A. Caprara, and M. Fischetti. Embedding cuts + in a Branch&Cut framework. Preliminary draft, October 2003. + + MIR cuts can be generated on any level of the search tree that + makes the GLPK MIP solver to be a real branch-and-cut solver. + + A bug was fixed in the routine lpx_write_cpxlp. If a variable + x has upper bound and no lower bound, it should appear in the + bounds section as "-inf <= x <= u", not as "x <= u". Thanks to + Enric Rodriguez for the bug report. + +GLPK 4.23 (release date: Oct 28, 2007) + + The following new API routines were added: + + glp_read_sol read basic solution from text file + glp_write_sol write basic solution to text file + glp_read_ipt read interior-point solution from text file + glp_write_ipt write interior-point solution to text file + glp_read_mip read MIP solution from text file + glp_write_mip write MIP solution to text file + + For description of these routines and corresponding file + formats see Chapter "API Routines", Section "Utility routines" + in the reference manual included in the distribution. + + Advanced API routine glp_free_env was added. It may be used by + the application program to free all resources allocated by GLPK + routines. + + The following three new command-line options were added to the + solver glpsol: + + --mipgap tol set relative MIP gap tolerance + -r filename read solution from filename + -w filename write solution to filename + +GLPK 4.22 (release date: Sep 19, 2007) + + This is a maintainer release. + + A bug was fixed in the MIP preprocessor (ios_preprocess_node). + Thanks to Roberto Bagnara (Department of + Mathematics, University of Parma, Italy) for the bug report. + + A bug was fixed in the MIP preprocessor (col_implied_bounds), + due to which constraint coefficients with small magnitude could + lead to wrong implied bounds of structural variables. + + A similar bug was fixed in the routine reduce_bounds. + + A bug was fixed in the routines glp_set_mat_row and + glp_set_mat_col. (The bug appeared due to incorrect removing + zero elements from the row/column lists.) + + A bug was fixed in the API routines lpx_read_mps and + lpx_read_freemps, due to which bounds of type LI specified in + BOUNDS section were incorrectly processed. + + A call to standard function vsprintf was replaced by a call to + vsnprintf for security reasons. Many thanks to Peter T. Breuer + and Rafael Laboissiere . + +GLPK 4.21 (release date: Aug 28, 2007) + + Additional reasons for calling the callback routine used in the + MIP solver (glp_intopt) were introduced. Currently the following + reasons are supported: + + * request for subproblem selection + * request for preprocessing + * request for row generation + * request for heuristic solution + * request for cut generation + * request for branching + * better integer solution found + + A basic preprocessing component used to improve subproblem + formulations by tightening bounds of variables was included in + the MIP solver. Depending on the control parameter pp_tech + passed to the routine glp_intopt the preprocessing can be + performed either on the root level or on all levels (default) + or can be disabled. + + Backtracking heuristic used by default in the MIP solver was + changed to the "best local bound". + + For more details see Chapter "Advanced API routines", Section + "Branch-and-bound interface routines" in a new edition of the + reference manual included in the distribution. + +GLPK 4.20 (release date: Jul 26, 2007) + + API routine lpx_integer was replaced by API routine glp_intopt, + which provides equivalent functionality and additionally allows + the application to control the solution process by means of the + user-written callback routine, which is called by the solver at + various points of the branch-and-bound algorithm. Besides, the + new MIP solver allows generating "lazy" constraints and cutting + planes on all levels of the branch-and-bound tree, not only on + the root level. The routine lpx_integer is also still available + for the backward compatibility. + + The following new advanced API routines, which may be called + from the B&B callback routine, were included in the package: + + glp_ios_reason determine reason for calling callback + routine + glp_ios_get_prob access the problem object + glp_ios_tree_size determine size of the branch-and-bound tree + glp_ios_curr_node determine current active subproblem + glp_ios_next_node determine next active subproblem + glp_ios_prev_node determine previous active subproblem + glp_ios_up_node determine parent subproblem + glp_ios_node_level determine subproblem level + glp_ios_node_bound determine subproblem local bound + glp_ios_mip_gap compute relative MIP gap + glp_ios_heur_sol provide solution found by heuristic + glp_ios_terminate terminate the solution process + + For description of these routines see Chapter "Advanced API + routines", Section "Branch-and-bound interface routines" in a + new edition of the reference manual, which was included in the + distribution. + + Old version of the integer optimization suite (IOS) as well as + TSP solver tspsol based on it are no longer supported and were + removed from the package. + + A minor error in the MIP presolver was fixed; thanks to Graham + Rockwell for the bug report. + +GLPK 4.19 (release date: Jul 05, 2007) + + The principal change is upgrading to GPLv3. + + A serious bug in the routine glp_del_cols was fixed; thanks to + Cedric[FR] for the bug report. The bug + appeared because on deleting non-basic columns the basis header + remained valid, however, contained invalid (old) column ordinal + numbers. + + A new advanced API routine glp_mem_limit was added. + + The case GLP_EBOUND was added to the routine lpx_simplex. + Thanks to Cameron Kellough for the + bug report. + + An API routine lpx_write_pb to write the problem instance in + OPB (pseudo boolean) format format was added. Thanks to Oscar + Gustafsson for the contribution. + + Two new options --wpb and --wnpb were added to glpsol to write + the problem instance in OPB format. + +GLPK 4.18 (release date: Jun 25, 2007) + + The following new API routines were added: + + glp_set_rii set (change) row scale factor + glp_set_sjj set (change) column scale factor + glp_get_rii retrieve row scale factor + glp_get_sjj retrieve column scale factor + glp_simplex solve LP problem with the simplex method + (this routine replaces lpx_simplex, which is + also available for backward compatibility) + glp_init_smcp initialize simplex method control params + glp_bf_exists check if the basis factorization exists + glp_factorize compute the basis factorization + glp_bf_updated check if the basis factorization has been + updated + glp_get_bfcp retrieve basis factorization control params + glp_set_bfcp change basis factorization control params + glp_get_bhead retrieve the basis header information + glp_get_row_bind retrieve row index in the basis header + glp_get_col_bind retrieve column index in the basis header + glp_ftran perform forward transformation + glp_btran perform backward transformation + + For description of all these routines see a new edition of the + reference manual included in the distribution. + + Type names ulong_t and uldiv_t were changed to glp_ulong and + glp_uldiv to avoid conflicts with standard type names on some + platforms. Thanks to Boris Wirtz + for the bug report. + + Some new examples in the MathProg language were added. Thanks + to Sebastian Nowozin . + +GLPK 4.17 (release date: May 26, 2007) + + API routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat + were modified to allow zero constraint coefficients (which are + not stored in the constraint matrix). Note that constraint + coefficients with duplicate row/column indices are not allowed. + + Another form of LP basis factorization was implemented in the + package. It is based on LU-factorization of an initial basis + and Schur complement to reflect changes in the basis. Currently + the implementation is incomplete and provides only updating the + factorization on replacing a column of the basis matrix. On API + level the user can set the control parameter LPX_K_BFTYPE to + choose between the folloiwng forms of LP basis factorization to + be used in the simplex method routines: + 1) LU + Forrest-Tomlin update; + 2) LU + Schur complement + Bartels-Golub update; + 3) LU + Schur complement + Givens rotation update. + The GLPK implementation is similar to LUSOL/LUMOD developed by + Michael A. Saunders. + + The user can choose the form of LP basis factorzation used by + the simplex method routines by specifying the folloiwng options + of glpsol: --luf, --cbg, --cgr. + +GLPK 4.16 (release date: May 05, 2007) + + A number of basic GLPK API routines, which now are in the + stable stable, were renamed to be prefixed with 'glp_'. Note + that all these routines are available via their old names + prefixed with 'lpx_' that keeps the downward compatibility with + older versions of the package. + + Three new GLPK API routines were added to the package: + glp_version, glp_term_hook, and glp_mem_usage; for more details + see a new edition of the GLPK reference manual included in the + distribution. The routine glp_version reports the actual version + of the GLPK library and also can be used (along with the header + glpk.h) in Autotools specification files to check if the GLPK + library has been installed. + + The header glpk.h was changed to conform to C++ environment. + +GLPK 4.15 (release date: Feb 18, 2007) + + Autotools specification files (configure.ac, Makefile.am) were + changed to use GNU Libtool. This allows building the static as + well as shared GLPK library. + +GLPK 4.14 (release date: Feb 05, 2007) + + Now GLPK conforms to ILP32, LLP64, and LP64 programming models + (the latter seems to be the ultimate choice regarding 64-bit + architectures). Note that GLPK itself is a 32-bit application, + and the conformity only means that the package works correctly + on all these arenae. Nevertheless, on 64-bit platforms it is + possible to use more than 4GB of memory, if necessary. + +GLPK 4.13 (release date: Nov 13, 2006) + + A tentative implementation of the "exact" simplex method based + on bignum (rational) arithmetic was included in the package. + + On API level this new feature is available through the routine + lpx_exact, which is similar to the routine lpx_simplex. + + In the solver glpsol this feature is available through two new + command-line options: --exact and --xcheck. If the '--exact' + option is specified, glpsol solves LP instance using the exact + simplex method; in case of MIP it is used to obtain optimal + solution of LP relaxation. If the --xcheck option is specified, + LP instance (or LP relaxation) is solved using the standard + (floating-point) simplex method, however, then glpsol calls the + exact simplex routine to make sure that the final LP basis is + exactly optimal, and if it is not, to perform some additional + simplex iterations in exact arithmetic. + +GLPK 4.12 (release date: Nov 08, 2006) + + A tentative implementation of some simplex method routines + based on exact (bignum) arithmetic was included in the package. + Currently these routines provide computing LU-factorization of + the basis matrix and computing components of basic solution. + + These routines were used to implement a routine, which checks + primal and dual feasibility of basic solution exactly, i.e. in + rational numbers, without round-off errors. In glpsol this + feature is available through the command-line option --xcheck. + + GLPK has its own low-level routines implementing operations on + integer and rational numbers that makes it independent on other + software packages. However, to attain a much better performance + it is highly recommended to install (before configuring GLPK) + the GNU Multiple Precision Arithmetic Library (GMP). Using GMP + makes computations 100-200 times faster. + +GLPK 4.11 (release date: Jul 25, 2006) + + Three new built-in functions in the modeling language were + implemented: card (cardinality of set), length (length of + character string), and substr (substring of character string). + Another improvement concerns the printf statement which now + allows redirecting its output to a specified file. These new + features are illustrated in example models crypto.mod and + graph.mod included in the distribution. For more details see + the document "Modeling Language GNU MathProg". + + Four batch files (along with corresponding makefiles) were + included in the distribution to simplify building GLPK under + MS Windows; see them in subdirectory 'w32'. + +GLPK 4.10 (release date: May 11, 2006) + + Cutting planes of two new classes were implemented: mixed cover + cuts and clique cuts. On API level this feature can be enabled + by setting control parameter LPX_K_USECUTS passed to the routine + lpx_intopt. In glpsol this feature is available through the + command-line options --cover and --clique. For more details see + the reference manual. + + Now the routines lpx_read_mps and lpx_read_freemps support LI + bound type. It is similar to LO, however, indicates the column + as of integer kind. + +GLPK 4.9 (release date: Jan 17, 2006) + + An advanced MIP solver was implemented. It includes: + + - basic presolving technique (removing free, singleton and + redundant rows, improving bounds of columns, removing fixed + columns, reducing constraint coefficents); + + - generating cutting planes to improve LP relaxation (currently + only Gomory's mixed integer cuts are implemented); + + - using the branch-and-bound method to solve resultant MIP; + + - recovering solution of the original MIP. + + The solver is available on API level via the routine lpx_intopt + (see the reference manual). It is similar to the routine + lpx_integer, however, does not require initial solution of LP + relaxation. + + The solver is also available in the command-line utility glpsol + via two options: --intopt (only presolving) and --cuts (assumes + --intopt plus generating cuts). + + Note that efficiency of the MIP solver strongly depends on the + internal structure of the problem to be solved. For some hard + instances it is very efficient, but for other instances it may + be significantly worse than the standard branch-and-bound. + + For some comparative benchmarks see doc/bench1.txt. + + Well, what else... + + Three built-in functions were added to MathProg: sin, cos, and + atan (the latter allows one or two arguments). + + Some bugs were fixed. + + Several new examples in MathProg were included: color.mod + (graph coloring problem), tsp.mod (traveling salesman problem), + and pbn.mod (paint-by-numbers puzzle). + +GLPK 4.8 (release date: Jan 12, 2005) + + Core simplex method and interior-point method routines were + re-implemented and now they use a new, "storage-by-rows" sparse + matrix format (unlike previous versions where linked lists were + used to represent sparse matrices). For details see ChangeLog. + + Also a minor bug was fixed in API routine lpx_read_cpxlp. + +GLPK 4.7 (release date: Aug 23, 2004) + + Now GLPK supports free MPS format. Two new API routines + lpx_read_freemps (to read problem data in free MPS format) and + lpx_write_freemps (to write problem data in free MPS format) + were added. This feature is also available in the solver glpsol + via new command-line options --freemps and --wfreemps. For more + details see the GLPK reference manual. + + API routines lpx_read_cpxlp and lpx_write_cpxlp for reading and + writing problem data in CPLEX LP format were re-implemented to + allow long symbolic names (up to 255 characters). + + The following three modules were temporarily removed from the + GLPK distribution due to licensing problems: DELI (an interface + module to Delphi), GLPKMEX (an interface module to Matlab), and + JNI (an interface module to Java). + +GLPK 4.6 (release date: Aug 04, 2004) + + Three new statements were implemented in the GNU MathProg + language: solve, printf, and for. Their detailed description can + be found in the GLPK documentation included in the distribution. + (See also a sample model, examples/queens.mod, which illustrates + using these new statements.) + + Two new API routines were added to the package: lpx_read_prob + and lpx_write_prob. They allow reading/writing problem data in + GNU LP low-level text format. + + Three new command-line options were implemented in the LP/MIP + solver glpsol: --glp (to read problem data in GNU LP format), + --wglp (to write problem data in GNU LP format), and --name (to + change problem name). Now glpsol also supports processing models + where the new statements (see above) are used. + + A new version of GLPKMEX, a Matlab MEX interface to GLPK, was + included. For more details see contrib/glpkmex/ChangeLog. + +GLPK 4.5 (release date: Jul 19, 2004) + + The branch-and-bound solver was completely re-implemented. + + Some modifications were made in memory allocation routines that + allows using the package on 64-bit platforms. + + For more details see ChangeLog. + +GLPK 4.4 (release date: Jan 17, 2004) + + All API routines were re-implemented using new data structures. + The new implementation provides the same specifications and + functionality of API routines as the old one, however, it has + some important advantages, in particular: + * linked lists are used everywhere that allows creating and + modifying the problem object as efficiently as possible + * all data stored in the problem object are non-scaled (even if + the internal scaling is used) that prevents distortion of the + original problem data + * solution components obtained by the solver remain available + even if the problem object has been modified + * no solver-specific data are used in the new data structures + that allows attaching any external lp/mip solver using GLPK + API as an uniform interface + Note that some API routines became obsolete being replaced by + new, more convenient routines. These obsolete routines are kept + for backward compatibility, however, they will be removed in + the future. For more details please see ChangeLog and the GLPK + Reference Manual. + + New edition of the GLPK Reference Manual was included in the + distribution. + + GLPKMEX, a Matlab MEX interface to GLPK package, contributed by + Nicolo Giorgetti was included in the + distribution. + + GLPK FAQ contributed by Harley Mackenzie was + included in the distribution. + +GLPK 4.3 (release date: Dec 12, 2003) + + The bug, due to which the standard math library is not linked + on building the package on some platforms, was fixed. + + The following new built-in functions were added to the MathProg + language: round, trunc, Irand224, Uniform01, Uniform, Normal01, + Normal. For details see the language description. + + The MathProg syntax was changed to allow writing 'subj to' that + means 'subject to'. + + The new api routine lpx_get_ray_info was added. It is intended + to determine which (non-basic) variable causes unboundness. For + details see the reference manual. + + The module glpmps.c was changed to avoid compilation errors on + building the package on Mac OS X. + + Several typos was fixed and some new material was added to the + GLPK documentation. + +GLPK 4.2 (release date: Nov 14, 2003) + + A preliminary implementation of the Integer Optimization Suite + (IOS) was included in the package. The Branch-and-Cut Framework + being completely superseded by IOS was removed from the package. + + New API routine lpx_print_sens_bnds intended for bounds + sensitivity analysis was contributed to GLPK by Brady Hunsaker + . This function is also available in + the solver glpsol (via command-line option --bounds). + + An improved version of GLPK JNI (Java Native Interface) was + contributed by Chris Rosebrugh . + + GLPK DELI (Delphi Interface) was contributed by Ivo van Baren + . + + Several makefiles were added to allow compiling GLPK on some + non-GNU 32-bit platforms: + * Windows single-threaded static library, Visual C++ 6.0 + * Windows multi-threaded dynamic library, Visual C++ 6.0 + * Windows single-threaded static library, Borland C++ 5.2 + * DOS single-threaded static library, Digital Mars C++ 7.50 + + And, of course, some bugs were fixed. + + For more details see ChangeLog. + +GLPK 4.1 (release date: Aug 23, 2003) + + Some improvements were made in the lp/mip solver routines and + several bugs were fixed in the model translator. + + For more details see ChangeLog. + +GLPK 4.0 (release date: May 06, 2003) + + Now GLPK supports the GNU MathProg modeling language, which is + a subset of the AMPL modeling language. + + The document "GLPK: Modeling Language GNU MathProg" included in + the distribution is a complete description of GNU MathProg. (See + the files lang.latex, lang.dvi, and lang.ps in the subdirectory + 'doc'. See also some examples in the subdirectory 'sample'.) + + New version of the solver glpsol, which supports models written + in GNU MathProg, was implemented. (Brief instructions how to use + glpsol can be found in the GNU MathProg documentation.) + + The GLPK/L modeling language is no more supported. The reason is + that GNU MathProg being much more powerful completely supersedes + all features of GLPK/L. + +GLPK 3.3 (release date: Mar 25, 2003) + + LP PRESOLVER + ------------ + + Now the routine lpx_simplex (which is a driver to the simplex + method for solving LP) is provided with the built-in LP + presolver, which is a program that transforms the original LP + problem to an equivalent LP problem, which may be easier for + solving with the simplex method than the original one. Once the + transformed LP has been solver, the presolver transforms its + basic solution back to a corresponding basic solution of the + original problem. For details about this feature please see the + GLPK reference manual. + + Currently the LP presolver implements the following features: + * removing empty rows; + * removing empty columns; + * removing free rows; + * removing fixed columns; + * removing row singletons, which have the form of equations; + * removing row singletons, which have the form of inequalities; + * removing column singletons, which are implied slack variables; + * fixing and removing column singletons, which are implied free + variables; + * removing forcing rows that involves fixing and removing the + corresponding columns; + * checking for primal and dual infeasibilities. + + The LP presolver is also used by default in the stand-alone + program glpsol. In order *not* to use it, the option --nopresol + should be specified in the command-line. + + CHANGES IN GLPK/L + ----------------- + + The syntax and semantics of the GLPK/L modeling language was + changed to allow declaration of "interval" sets. This means that + now the user can declare a set, for example, as: + + set task = [8:11]; + + that is exactly equivalent to the following declaration: + + set task = (task_8, task_9, task_10, task_11); + + For details see the language description. + + JAVA INTERFACE + -------------- + + Now GLPK includes the package GLPK JNI (Java Native Interface) + that implements Java binding for GLPK. It allows Java programs + to utilize GLPK in solving LP and MIP problems. For details see + a brief user's guide in the subdirectory contrib/java-binding. + This package was developed and programmed by Yuri Victorovich + , who contributed it to GLPK. + +GLPK 3.2.4 (release date: Feb 18, 2003) + + This is a bug-fix release. For details see ChangeLog. + +GLPK 3.2.3 (release date: Nov 11, 2002) + + A new implementation of the api routine lpx_integer which now + is based on the b&b driver (which is based on the implicit + enumeration suite) was included in the package. This new + implementation has exactly the same functionality as the old + version, so all changes are transparent to the api user. + + Four new api routines were included in the package: + lpx_check_kkt checks Karush-Kuhn-Tucker optmality conditions; + lpx_read_bas reads predifined basis in MPS format; + lpx_write_bas writes current basis in MPS format; + lpx_write_lpt writes problem data in CPLEX LP format. + + Also other minor improvements were made (for details see the + file 'ChangeLog'). + +GLPK 3.2.2 (release date: Oct 14, 2002) + + The api routine lpx_read_lpt was included in the package. It + is similar to the routine lpx_read_mps and intended to read + LP/MIP data prepared in CPLEX LP format. Description of this + format is given in the GLPK reference manual, a new edition of + which was also included in the distribution (see the files + 'refman.latex', 'refman.dvi', 'refman.ps' in the subdirectory + 'doc'). In order to use data files in CPLEX LP format with the + solver glpsol the option '--lpt' should be specified in the + command line. + + Several bugs were fixed and some minor improvements were made + (for details see the file 'ChangeLog'). + +GLPK 3.2.1 (release date: Aug 12, 2002) + + Now GLPK includes a preliminary implementation of the + branch-and-cut framework, which is a set of data structures and + routines intended for developing branch-and-cut methods for + solving mixed-integer and combinatorial optimization problems. + + Detailed decsription of the branch-and-cut framework is given in + the document "GLPK: A Preliminary Implementation of the + Branch-And-Cut Framework" included in the distribution (see the + file 'brcut.txt' in the subdirectory 'doc'). + + In order to illustrate how the GLPK branch-and-cut framework + can be used for solving a particular optimization problem there + is an example included in the package. This is a stand-alone + program, TSPSOL, which is intended for solving to optimality the + symmetric Traveling Salesman Problem (TSP), a classical problem + of the combinatorial optimization (see the file 'tspsol.c' in + the subdirectory 'sample'). + +GLPK 3.2 (release date: Jul 15, 2002) + + New edition of the document "GLPK: Reference Manual" was + included (see the files 'refman.latex', 'refman.dvi', and + 'refman.ps' in the subdirectory 'doc'). + + New edition of the document "GLPK: Modeling Language GLPK/L" was + included (see the files 'lang.latex', 'lang.dvi', and 'lang.ps' + in the subdirectory 'doc'). + + The following new API routines were added to the package: + + lpx_transform_row (transform explicitly specified row); + lpx_transform_col (transform explicitly specified column); + lpx_prim_ratio_test (perform primal ratio test); + lpx_dual_ratio_test (perform dual ratio test); + lpx_interior (solve LP problem using interior point method); + lpx_get_ips_stat (query status of interior point solution); + lpx_get_ips_row (obtain row interior point solution); + lpx_get_ips_col (obtain column interior point solution); + lpx_get_ips_obj (obtain interior point value of obj.func.); + lpx_read_lpm (read LP/MIP model written in GLPK/L); + lpx_write_mps (write problem data using MPS format); + lpx_print_ips (print interior point solution). + + Detailed description of all these new API routines are given in + the new edition of the reference manual. + + New version of the stand-alone solver glpsol (which is based on + the new API) was implemented. + + So long as the new API (introduced in glpk 3.0) now provides + all the functions, which were provided by the old API, the old + API routines were removed from the package at all. + +GLPK 3.1 (release date: May 27, 2002) + + A preliminary implementation of new API routines was completed + and included in the package. + + These new API routines provide much more flexible interaction + between the application program, LP/MIP problem instances, and + solver routines. Based on completely changed data structures + they are, however, similar to the API routines and provide the + same functionality. Please note that three routines, namely, + solving LPs using interior point method, reading model written + in the GLPK/L modeling language, and writing problem data in + the MPS format, are not implemented in the new API, however, + these routines are planned to be implemented in the next version + of the package. + + A description of the new API routines is given in the document + "GLPK Reference Manual", a draft edition of which is included + in the package (see the files 'refman.latex', 'refman.dvi', and + 'refman.ps' in the subdirectory 'doc'). + + Although the old API routines are kept in the package, they are + no longer supported and will be removed in the future. + +GLPK 3.0.8 (release date: May 13, 2002) + + A preliminary implementation of new API routines was included + in the package. These new API routines are intended to provide + much more flexible interaction between the application program, + LP/MIP problem and solver routines. See the document "New GLPK + API Routines" (the file 'newapi.txt' in the subdirectory 'doc') + also included in the package. + + The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were + renamed, respectively, to glp_simplex, glp_interior, glp_integer + in order to reflect changes in implementation. The api routines + glp_call_rsm1, glp_simplex1, glp_pivot_in, glp_pivout_out were + removed from the package since they are completely supreseded by + the new API routines (however, these routines still can be found + in the subdirectory 'oldsrc'). Please consult a new edition of + the document "GLPK User's Guide" about all these changes in the + existing api routines. + + The document "GLPK Library Reference" was removed from the + package (into the subdirectory 'oldsrc') since it describes the + obsolete library routines, most of which are no longer used. + +GLPK 3.0.7 (release date: Apr 22, 2002) + + A new, more efficient implementation of the primal/dual simplex + method was included in the package. Due to some improvements the + simplex-based solver allows solving many LP problems faster and + provides more reliable results. Note that the new implementation + is currently incomplete and available only via the api routine + glp_simplex2. + + All the changes are transparent on API level. + +GLPK 3.0.6 (release date: Mar 28, 2002) + + New version of LU-factorization and basis maintenance routines + (based on Forrest-Tomlin updating technique) was implemented. + Since these new routines functionally supersede some routines + (which implement other forms of the basis matrix) and make them + obsolete, the latter were removed from the package (they still + can be found in the subdirectory 'oldsrc'). + + All the changes are transparent on API level. + +GLPK 3.0.5 (release date: Jan 29, 2002) + + New edition of the document "GLPK User's Guide" was included in + the distribution. Now it describes all additional API routines, + which were recently added to the package. + + Structure of the package was re-organized in order to make its + maintenance easier (all small files in the subdurectory 'source' + were merged in bigger units). These changes are transparent for + the user. + +GLPK 3.0.4 (release date: Dec 10, 2001) + + A new, more efficient implementation of the two-phase primal + simplex method was included in the package. Due to some new + features (an advanced initial basis, projected steepest edge, + recursive updating values and reduced costs) the new LP solver + is faster and numerically more stable than the old one. + + The new LP solver is available as API routine glp_simplex2 and + has the same purpose as API routine glp_call_rsm1. For detailed + specification see the file 'newapi.txt' in the directory 'doc'. + + Now the new LP solver is also used by default to solve an + initial LP problem in the branch-and-bound routine glp_call_bbm1 + instead the routine rsm1_driver. Note that the branch-and-bound + procedure itself is still based on rsm1_driver. + + The new LP solver is also used as default solver in GLPSOL for + solving LP and MIP problems. In order to choose the old solver + the option '--old-sim' can be specified in the command line. + +GLPK 3.0.3 (release date: Oct 03, 2001) + + Some minor changes were made in the simplex method routines in + order to improve numerical stability of the method. + +GLPK 3.0.2 (release date: Sep 24, 2001) + + A new implementation of the basis maintaining routines was + included in the package. These routines, which are based on so + called FHV-factorization (a variety of LU-factorization) of the + basis matrix and Gustavson's data structures, allows performing + the main operations faster at the expense of some worsening + numerical accuracy. + + AFI (Advanced Form of the Inverse), which is the form of the + basis matrix based on FHV-factorization, is available via the + parameter form = 3 (on API level) or via the option --afi (in + GLPSOL solver). + +GLPK 3.0.1 (release date: Aug 01, 2001) + + Old GLPK API routines have been removed from the package. + + New GLPK API routines were added: + + - scaling routines; + + - a routine for writing problem data in MPS format; + + - a comprehensive driver to the simplex method; + + - basis maintaining routines. + + A description of the new API routines is given in the document + "Additional GLPK API Routines". This document is included into + the distribution in plain text format (see the file 'newapi.txt' + in the subdirectory 'doc'). + + Now the distribution includes a non-trivial example of using + GLPK as a base LP solver for Concorde, a well known program that + solves Traveling Salesman Problem (TSP). For further details see + comments in the file 'sample/lpglpk30.c'. + +GLPK 3.0 (release date: Jul 19, 2001) + + Now GLPK is provided with new API, which being more flexible + can be used in more complex algorithmic schemes. + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it completely corresponds to the new GLPK + API routines. + + Old API routines are not removed yet from the package, however + they became obsolete and therefore should not be used. Since now + the header glpk.h corresponds to new API, in order to compile + existing programs that use old GLPK API routines the statement + + #define GLP_OLD_API + + should be inserted before the statement + + #include "glpk.h" + +GLPK 2.4.1 (release date: Jun 14, 2001) + + The document "Modeling language GLPK/L" is included into the + distribution in texinfo format. + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it describes all additional API routines + which were recently added to the package. + +GLPK 2.4 (release date: May 10, 2001) + + Now GLPK includes an implementation of a preliminary version + of the GLPK/L modeling language. This language is intended for + writing mathematcal programming models. The name GLPK/L is + derived from GNU Linear Programming Kit Language. + + A brief description of the GLPK/L language is given in the + document "GLPK/L Modeling Language: A Brief Description". This + document is included into the distribution in plain text format + (see the file 'language.txt' in the subdirectory 'doc'). + + The language processor (which is a program that analyzes model + description written in GLPK/L and translates it to internal data + structures) is available as the GLPK API routine. + + The stand-alone solver GLPSOL now is able: a) to process model + descriptions written in the GLPK/L language; b) to solve pure LP + problems using the interior point method (therefore the program + GLPIPM was removed from the package). + +GLPK 2.3 (release date: Apr 09, 2001) + + New edition of the document "GLPK User's Guide" is included in + the distribution. Now it describes all additional API routines + which were recently added to the package. + + The MIP solver was fully re-programmed in order to improve its + robustness and performance. In particular, a basis recovering + procedure was implemented (this procedure allows switching to + the primal simplex method in case when the dual simplex method + fails). + +GLPK 2.2 (release date: Mar 15, 2001) + + Now GLPK includes a tentative implementation of the + branch-and-bound procedure based on the dual simplex method for + mixed integer linear programming (MIP). + + Complete description of this new feature of the package is given + in the preliminary document "Mixed Integer Linear Programming + Using GLPK Version 2.2 (Supplement to GLPK User's Guide)". This + document is included into the distribution in plain text format + (see the file 'mip.txt' in the subdirectory 'doc'). + + The MIP solver (glp_integer) can be used as GLPK API routine in + the same way as the pure LP solver (glp_simplex). + + The stand-alone program 'glpsol' is now able to solve LP as well + as MIP problems. + + Note that the current version of GLPK MIP solver is based on + easiest heuristics for branching and backtrackng. Therefore the + solver is fit mainly for MIP problems which are not very hard + and have few integer variables. + +GLPK 2.1 (release date: Feb 19, 2001) + + The document "GLPK Implementation of the Revised Simplex Method" + is included into the distribution. This document describes most + of routines related to the revised simplex method. + +GLPK 2.0 (release date: Jan 25, 2001) + + Now GLPK includes a tentative implementation of the primal-dual + interior point method for large-scale linear programming. + + The interior point solver can be used as GLPK API routine in the + same manner as the simplex method solver (glp_simplex): + + ret = glp_interior(); + + Note that currently the interior point solver implemented in + GLPK doesn't include many important features, in particular: + + * it can't process dense columns; therefore if the problem has + dense columns, the solving will be extremely inefficient; + + * it has no special features against numerical unstability; + some problems may cause premature termination of the solving + when the matrix A*D*A' becomes ill-conditioned; + + * it computes only values of primal (auxiliary and structural) + variables and doesn't compute values of dual variables (i.e. + reduced costs) which are just set to zero; + + * it doesn't identify optimal basis corresponding to the found + interior point solution; all variables in the found solution + are just marked as basic variables. + + GLPK also includes a stand-alone program 'glpipm' which is a + demo based on the interior point method. It may be used in the + same way as the program 'glpsol' that is based on the simplex + method. diff --git a/WebAPP/SOLVERs/GLPK/glpk/README b/WebAPP/SOLVERs/GLPK/glpk/README new file mode 100644 index 000000000..7d71d65bf --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/README @@ -0,0 +1,39 @@ + Olga K. gewidmet + +GLPK (GNU Linear Programming Kit) Version 4.65 + +Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017, 2018 Andrew Makhorin, +Department for Applied Informatics, Moscow Aviation Institute, Moscow, +Russia. All rights reserved. E-mail: . + +GLPK is part of the GNU Project released under the aegis of GNU. + +GLPK is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation, either version 3 of the License, or (at your +option) any later version. + +See the file COPYING for the GNU General Public License. + +See the file INSTALL for compilation and installation instructions. + +The GLPK package is a set of routines written in ANSI C and organized +in the form of a callable library. This package is intended for solving +large-scale linear programming (LP), mixed integer linear programming +(MIP), and other related problems. + +The GLPK package includes the following main components: + +* primal simplex method; +* dual simplex method; +* exact simplex method based on rational arithmetic; +* primal-dual interior-point method; +* branch-and-cut method; +* application program interface (API); +* GNU MathProg modeling language (a subset of AMPL); +* GLPSOL (stand-alone LP/MIP solver). + +See GLPK webpage . + +Please report bugs to . diff --git a/WebAPP/SOLVERs/GLPK/glpk/THANKS b/WebAPP/SOLVERs/GLPK/glpk/THANKS new file mode 100644 index 000000000..87af37b07 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/THANKS @@ -0,0 +1,245 @@ +Achim Gaedke for bug report. + +Alexandre Oliva for bug report. + +Andre Girard for bug report. + +Andrew Hamilton-Wright for bug report. + +Andrew Hood for bug report. + +Anne-Laurence Putz for bug +report. + +Anton Voropaev for bug and typo report. + +Axel Simon for bug report. + +Balaco Baco for bug report. + +Bernhard Schmidt for bug report. + +Boris Wirtz for bug report. + +Brady Hunsaker for contribution of a routine +for bounds sensitivity analysis. + +Brady Hunsaker for some suggestions concerning +MIP routines. + +Brian Gladman for suggestion. + +Cameron Kellough for bug report. + +Carlo Baldassi for bug report. + +Cedric[FR] for bug report. + +Charles Brixko for bug report. + +Chris Matrakidis for contribution of a patch that +implements the tan function in MathProg. + +Chris Matrakidis for numerous useful suggestions, +contributions, and patches. + +Chris Rosebrugh for contribution of a new version of +GLPK JNI (Java Native Interface). + +Christophe Caron for bug report. + +David Monniaux for some suggestions. + +David Monniaux for bug report. + +David T. Price for bug report. + +Dennis Schridde for bug report. + +Enric Rodriguez for bug report. + +Flavio Keidi Miyazawa for bug report. + +Gabriel Hackebeil for bug report. + +Giles Thompson for bug report. + +Giorgio Sartor <0gioker0@gmail.com> for contribution of routines that +implement the proximity search heuristic for MIP. + +Graham Rockwell for bug report. + +Hans Schwengeler for bug report. + +Harley Mackenzie for contribution of GLPK FAQ. + +Dr. Harley Mackenzie for two example MathProg +models (curve fitting problem). + +Heinrich Schuchardt for contribution of +makefiles and testing the package under 64-bit Windows. + +Heinrich Schuchardt for contribution of +two MathProg table drivers for iODBC and MySQL. + +Heinrich Schuchardt for some patches for +the MathProg translator. + +Heinrich Schuchardt for testing the package on +32- and 64-bit MS Windows platforms. + +Ivan Luzzi for comments concerning CPLEX LP format. + +Ivo van Baren for contribution of GLPK DELI +(Delphi Interface). + +Jan Engelhardt for some suggestions. + +Jeffrey Kantor for reporting typos in the MathProg +language reference. + +Jeroen Demeyer for suggestion. + +Jeroen Demeyer for bug report. + +Jiri Spitz for bug report. + +Joao Flavio de Freitas Almeida for +translation of the document "Modeling Language GNU MathProg" to +Brazilian Portuguese (pt-BR). + +Joey Rios for some suggestions. + +Jonathan Senning for bug report. + +Karel Zimmermann for bug report. + +Kelly Westbrooks for suggestions. + +Kendall Demaree for bug report. + +Kjell Eikland for bug report. + +Larry D'Agostino for example model in +MathProg. + +Luiz Bettoni for some suggestions. + +Marco Atzeri for bug report. + +Marco Atzeri for bug report. + +Mark Meketon for bug report. + +Markus Pilz for bug report. + +Martin Jacob for bug report. + +Mike Appleby for example model in MathProg. + +Minh Ha Duong for fixing doc typos. + +Morten Welinder for bug report. + +Morten Welinder for bug report. + +Nelson H. F. Beebe for bug report. + +Nicolo Giorgetti for contribution of GLPKMEX, +a Matlab MEX interface. + +Niels Klitgord for bug report. + +Nigel Galloway for an example MathProg +model. + +Nigel Galloway for an example program +in C#. + +Nigel Galloway for bug report. + +Nigel Galloway for example models in +MathProg. + +Noli Sicad for testing glpk under Mac OS. + +Noli Sicad for example model in MathProg. + +Olivier for bug report. + +Oscar Gustafsson for contribution of a routine to +write data in OPB (pseudo boolean) format. + +Pablo Yapura for translation of the document +"Modeling Language GNU MathProg" to Spanish. + +Pedro P. Wong for bug report. + +Peter T. Breuer for bug report. + +Peter A. Huegler for bug report. + +Peter Ingerfeld for bug report. + +Peter Lee for example LP model and bug report. + +Peter Naszvadi for example models in MathProg. + +Pietro Scionti for report typos found in +the reference manual. + +Rafael Laboissiere for useful advices concerning +shared library support under GNU/Linux. + +Raniere Gaia Costa da Silva for bug report. + +Remy Roy for bug report. + +Rob Schroeder for bug report. + +Robbie Morrison for correcting the glpk manual. + +Robert Wood for example model in MathProg. + +Roberto Bagnara (Department of Mathematics, +University of Parma, Italy) for bug report. + +Sami Farin for bug report. + +Sebastian Nowozin for example models in MathProg. + +Sebastien Briais for bug report. + +Sebastien de Menten for bug report. + +Sebastien Villemot for bug report. + +Stefan Vigerske for bug report. + +Stefan Vigerske for bug report. + +Sylvain Fournier for bug report. + +Thomas Kahle for some suggestions. + +Uday Venkatadri for bug report. + +Vijay Patil for testing the package under +Windows XP. + +Vlahos Kiriakos for bug report. + +Xypron for bug fixing and some improvments in the +FPUMP module. + +Xypron for bug patch. + +Xypron for contribution and testing batch scripts +to build Glpk with MS Visual Studio 2010. + +Xypron for improving the SQL table driver. + +Xypron for testing GLPK on 64-bit platforms and +for maintaining Windows versions of the package. + +Yuri Victorovich for contribution of GLPK Java binding. diff --git a/WebAPP/SOLVERs/GLPK/glpk/aclocal.m4 b/WebAPP/SOLVERs/GLPK/glpk/aclocal.m4 new file mode 100644 index 000000000..636b7ac2f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/aclocal.m4 @@ -0,0 +1,949 @@ +# generated automatically by aclocal 1.12.5 -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.12' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.12.5], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.12.5])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each '.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], +[$0: two- and three-arguments forms are deprecated. For more info, see: +http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +dnl Support for Objective C++ was only introduced in Autoconf 2.65, +dnl but we still cater to Autoconf 2.62. +m4_ifdef([AC_PROG_OBJCXX], +[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2001-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of '-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([m4/libtool.m4]) +m4_include([m4/ltoptions.m4]) +m4_include([m4/ltsugar.m4]) +m4_include([m4/ltversion.m4]) +m4_include([m4/lt~obsolete.m4]) diff --git a/WebAPP/SOLVERs/GLPK/glpk/autogen.sh b/WebAPP/SOLVERs/GLPK/glpk/autogen.sh new file mode 100755 index 000000000..4dd02fbc1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/autogen.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +######################################################################## +# Run this script on the top level of GLPK directory to regenerate the +# configure script and the Makefiles from templates. +# +# NOTE: You need to have GNU autotools installed. +######################################################################## + +set -e + +test -f configure.ac || { + echo "You should run this script on the top level of GLPK directory." + exit +} + +echo "Executing libtoolize..." +libtoolize -c -f +echo "Executing aclocal..." +aclocal -I m4 +echo "Executing autoconf..." +autoconf +echo "Executing automake..." +automake -c -a +echo "Done." + +echo "See file INSTALL for installation instructions." diff --git a/WebAPP/SOLVERs/GLPK/glpk/config.guess b/WebAPP/SOLVERs/GLPK/glpk/config.guess new file mode 100755 index 000000000..872b96a16 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/config.guess @@ -0,0 +1,1537 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-09-25' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/WebAPP/SOLVERs/GLPK/glpk/config.h.in b/WebAPP/SOLVERs/GLPK/glpk/config.h.in new file mode 100644 index 000000000..794e00c5d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/config.h.in @@ -0,0 +1,30 @@ +/* config.h.in (GLPK configuration template file) */ + +#undef HAVE_SYS_TIME_H +/* defined if the header can be used */ + +#undef HAVE_GETTIMEOFDAY +/* defined if the gettimeofday function can be used */ + +#undef HAVE_GMP +/* defined if the GNU MP bignum library is available */ +/* requires and -lgmp */ + +#undef HAVE_LTDL +/* defined if the GNU Libtool shared library support is enabled */ +/* requires and -lltdl */ + +#undef HAVE_DLFCN +/* defined if the POSIX shared library support is enabled */ +/* requires */ + +#undef ODBC_DLNAME +/* ODBC shared library name if this feature is enabled */ + +#undef MYSQL_DLNAME +/* MySQL shared library name if this feature is enabled */ + +#undef TLS +/* thread local storage-class specifier for re-entrancy (if any) */ + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/config.sub b/WebAPP/SOLVERs/GLPK/glpk/config.sub new file mode 100755 index 000000000..89b128630 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/config.sub @@ -0,0 +1,1789 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. + +timestamp='2012-10-10' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/WebAPP/SOLVERs/GLPK/glpk/configure b/WebAPP/SOLVERs/GLPK/glpk/configure new file mode 100755 index 000000000..c238f864f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/configure @@ -0,0 +1,13911 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for GLPK 4.65. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-glpk@gnu.org +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='GLPK' +PACKAGE_TARNAME='glpk' +PACKAGE_VERSION='4.65' +PACKAGE_STRING='GLPK 4.65' +PACKAGE_BUGREPORT='bug-glpk@gnu.org' +PACKAGE_URL='' + +ac_unique_file="src/glpk.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +NOUNDEFINED +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +LIBTOOL +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_gmp +enable_dl +enable_odbc +enable_mysql +enable_reentrant +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures GLPK 4.65 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/glpk] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of GLPK 4.65:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dl enable shared library support [[default=no]] + --enable-odbc enable MathProg ODBC support [[default=no]] + --enable-mysql enable MathProg MySQL support [[default=no]] + --enable-reentrant enable reentrancy support [[default=yes]] + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gmp use GNU MP bignum library [[default=no]] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +GLPK configure 4.65 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------- ## +## Report this to bug-glpk@gnu.org ## +## ------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by GLPK $as_me 4.65, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + +am__api_version='1.12' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='glpk' + VERSION='4.65' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +ac_config_headers="$ac_config_headers config.h" + + + +# Check whether --with-gmp was given. +if test "${with_gmp+set}" = set; then : + withval=$with_gmp; case $withval in + yes | no) ;; + *) as_fn_error $? "invalid value \`$withval' for --with-gmp" "$LINENO" 5;; + esac +else + with_gmp=no +fi + + +# Check whether --enable-dl was given. +if test "${enable_dl+set}" = set; then : + enableval=$enable_dl; case $enableval in + yes | ltdl | dlfcn | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-dl" "$LINENO" 5;; + esac +else + enable_dl=no +fi + + +# Check whether --enable-odbc was given. +if test "${enable_odbc+set}" = set; then : + enableval=$enable_odbc; case $enableval in + yes | unix | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-odbc" "$LINENO" 5;; + esac +else + enable_odbc=no +fi + + +# Check whether --enable-mysql was given. +if test "${enable_mysql+set}" = set; then : + enableval=$enable_mysql; case $enableval in + yes | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-mysql" "$LINENO" 5;; + esac +else + enable_mysql=no +fi + + +# Check whether --enable-reentrant was given. +if test "${enable_reentrant+set}" = set; then : + enableval=$enable_reentrant; case $enableval in + yes | no) ;; + *) as_fn_error $? "invalid value \`$enableval' for --enable-reentrant" "$LINENO" 5;; + esac +else + enable_reentrant=yes +fi + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from 'make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4' +macro_revision='1.3294' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_FGREP" || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for exp in -lm" >&5 +$as_echo_n "checking for exp in -lm... " >&6; } +if ${ac_cv_lib_m_exp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exp (); +int +main () +{ +return exp (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_exp=yes +else + ac_cv_lib_m_exp=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_exp" >&5 +$as_echo "$ac_cv_lib_m_exp" >&6; } +if test "x$ac_cv_lib_m_exp" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + + +ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_time_h" = xyes; then : + +$as_echo "#define HAVE_SYS_TIME_H 1" >>confdefs.h + +fi + + + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes; then : + +$as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h + +fi + + +if test "$with_gmp" = "yes"; then + ac_fn_c_check_header_mongrel "$LINENO" "gmp.h" "ac_cv_header_gmp_h" "$ac_includes_default" +if test "x$ac_cv_header_gmp_h" = xyes; then : + +else + as_fn_error $? "gmp.h header not found" "$LINENO" 5 +fi + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use GNU MP bignum library" >&5 +$as_echo_n "checking whether to use GNU MP bignum library... " >&6; } +if test "$with_gmp" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GMP 1" >>confdefs.h + + LIBS="-lgmp $LIBS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable shared library support" >&5 +$as_echo_n "checking whether to enable shared library support... " >&6; } +if test "$enable_dl" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 +$as_echo "ltdl" >&6; } + +$as_echo "#define HAVE_LTDL 1" >>confdefs.h + + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "ltdl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 +$as_echo "ltdl" >&6; } + +$as_echo "#define HAVE_LTDL 1" >>confdefs.h + + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "dlfcn"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: dlfcn" >&5 +$as_echo "dlfcn" >&6; } + +$as_echo "#define HAVE_DLFCN 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +case $host_os in + darwin* | macosx*) + LIBIODBC="libiodbc.dylib" + LIBODBC="libodbc.dylib" + LIBMYSQL="libmysqlclient.dylib" + ;; + *) + LIBIODBC="libiodbc.so" + LIBODBC="libodbc.so" + LIBMYSQL="libmysqlclient.so" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg ODBC support" >&5 +$as_echo_n "checking whether to enable MathProg ODBC support... " >&6; } +if test "$enable_odbc" = "yes"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$(iodbc-config --cflags) $CFLAGS" + +cat >>confdefs.h <<_ACEOF +#define ODBC_DLNAME "$LIBIODBC" +_ACEOF + +elif test "$enable_odbc" = "unix"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix" >&5 +$as_echo "unix" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ODBC_DLNAME "$LIBODBC" +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg MySQL support" >&5 +$as_echo_n "checking whether to enable MathProg MySQL support... " >&6; } +if test "$enable_mysql" = "yes"; then + if test "$enable_dl" = "no"; then + as_fn_error $? "--enable-mysql requires --enable-dl" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" + +cat >>confdefs.h <<_ACEOF +#define MYSQL_DLNAME "$LIBMYSQL" +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable reentrancy support" >&5 +$as_echo_n "checking whether to enable reentrancy support... " >&6; } +if test "$enable_reentrant" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread local storage (TLS) class specifier" >&5 +$as_echo_n "checking for thread local storage (TLS) class specifier... " >&6; } + keywords="_Thread_local __thread __declspec(thread)" + tls=none + for tls_keyword in $keywords; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + static void foo(void) + { static $tls_keyword int bar; + exit(1); + } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tls=$tls_keyword; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tls" >&5 +$as_echo "$tls" >&6; } + if test "$tls" != "none"; then + +cat >>confdefs.h <<_ACEOF +#define TLS $tls +_ACEOF + + else + as_fn_error $? "Reentrancy needs complier support for TLS" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool needs -no-undefined flag to build shared libraries" >&5 +$as_echo_n "checking if libtool needs -no-undefined flag to build shared libraries... " >&6; } +case "${host}" in + *-*-cygwin* | *-*-mingw* | *-*-aix*) + ## Add in the -no-undefined flag to LDFLAGS for libtool. + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + NOUNDEFINED=" -no-undefined" + ;; + *) + ## Don't add in anything. + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; +esac + + +ac_config_files="$ac_config_files src/Makefile examples/Makefile Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by GLPK $as_me 4.65, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +GLPK config.status 4.65 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named 'Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running 'make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/WebAPP/SOLVERs/GLPK/glpk/configure.ac b/WebAPP/SOLVERs/GLPK/glpk/configure.ac new file mode 100644 index 000000000..96c4cc547 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/configure.ac @@ -0,0 +1,197 @@ +dnl Process this file with autoconf to produce a configure script + +AC_INIT([GLPK], [4.65], [bug-glpk@gnu.org]) + +AC_CONFIG_SRCDIR([src/glpk.h]) + +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE + +AC_CONFIG_HEADERS([config.h]) + +AC_ARG_WITH(gmp, +AC_HELP_STRING([--with-gmp], + [use GNU MP bignum library [[default=no]]]), + [case $withval in + yes | no) ;; + *) AC_MSG_ERROR([invalid value `$withval' for --with-gmp]);; + esac], + [with_gmp=no]) + +AC_ARG_ENABLE(dl, +AC_HELP_STRING([--enable-dl], + [enable shared library support [[default=no]]]), + [case $enableval in + yes | ltdl | dlfcn | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-dl]);; + esac], + [enable_dl=no]) + +AC_ARG_ENABLE(odbc, +AC_HELP_STRING([--enable-odbc], + [enable MathProg ODBC support [[default=no]]]), + [case $enableval in + yes | unix | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-odbc]);; + esac], + [enable_odbc=no]) + +AC_ARG_ENABLE(mysql, +AC_HELP_STRING([--enable-mysql], + [enable MathProg MySQL support [[default=no]]]), + [case $enableval in + yes | no) ;; + *) AC_MSG_ERROR([invalid value `$enableval' for --enable-mysql]);; + esac], + [enable_mysql=no]) + +AC_ARG_ENABLE(reentrant, +AC_HELP_STRING([--enable-reentrant], + [enable reentrancy support [[default=yes]]]), + [case $enableval in + yes | no) ;; + *) AC_MSG_ERROR( + [invalid value `$enableval' for --enable-reentrant]);; + esac], + [enable_reentrant=yes]) + +dnl Disable unnecessary libtool tests +define([AC_LIBTOOL_LANG_CXX_CONFIG], [:]) +define([AC_LIBTOOL_LANG_F77_CONFIG], [:]) +define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:]) + +dnl Check for programs +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LIBTOOL + +dnl Check for math library +AC_CHECK_LIB([m], [exp]) + +dnl Check for header +AC_CHECK_HEADER([sys/time.h], + AC_DEFINE([HAVE_SYS_TIME_H], [1], [N/A])) + +dnl Check for gettimeofday function +AC_CHECK_FUNC([gettimeofday], + AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [N/A])) + +dnl Check for header +if test "$with_gmp" = "yes"; then + AC_CHECK_HEADER([gmp.h], [], + [AC_MSG_ERROR([gmp.h header not found])]) +fi + +AC_MSG_CHECKING([whether to use GNU MP bignum library]) +if test "$with_gmp" = "yes"; then + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_GMP], [1], [N/A]) + LIBS="-lgmp $LIBS" +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether to enable shared library support]) +if test "$enable_dl" = "yes"; then + AC_MSG_RESULT([ltdl]) + AC_DEFINE([HAVE_LTDL], [1], [N/A]) + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "ltdl"; then + AC_MSG_RESULT([ltdl]) + AC_DEFINE([HAVE_LTDL], [1], [N/A]) + LIBS="-lltdl $LIBS" +elif test "$enable_dl" = "dlfcn"; then + AC_MSG_RESULT([dlfcn]) + AC_DEFINE([HAVE_DLFCN], [1], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +case $host_os in + darwin* | macosx*) + LIBIODBC="libiodbc.dylib" + LIBODBC="libodbc.dylib" + LIBMYSQL="libmysqlclient.dylib" + ;; + *) + LIBIODBC="libiodbc.so" + LIBODBC="libodbc.so" + LIBMYSQL="libmysqlclient.so" + ;; +esac + +AC_MSG_CHECKING([whether to enable MathProg ODBC support]) +if test "$enable_odbc" = "yes"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-odbc requires --enable-dl]) + fi + AC_MSG_RESULT([yes]) + CFLAGS="$(iodbc-config --cflags) $CFLAGS" + AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBIODBC"], [N/A]) +elif test "$enable_odbc" = "unix"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-odbc requires --enable-dl]) + fi + AC_MSG_RESULT([unix]) + AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBODBC"], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether to enable MathProg MySQL support]) +if test "$enable_mysql" = "yes"; then + if test "$enable_dl" = "no"; then + AC_MSG_ERROR([--enable-mysql requires --enable-dl]) + fi + AC_MSG_RESULT([yes]) + CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" + AC_DEFINE_UNQUOTED([MYSQL_DLNAME], ["$LIBMYSQL"], [N/A]) +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING([whether to enable reentrancy support]) +if test "$enable_reentrant" = "yes"; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for thread local storage (TLS) class specifier]) + keywords="_Thread_local __thread __declspec(thread)" + tls=none + for tls_keyword in $keywords; do + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + #include + static void foo(void) + { static ] $tls_keyword [ int bar; + exit(1); + }])], [tls=$tls_keyword; break], []) + done + AC_MSG_RESULT($tls) + if test "$tls" != "none"; then + AC_DEFINE_UNQUOTED([TLS], $tls, [N/A]) + else + AC_MSG_ERROR([Reentrancy needs complier support for TLS]) + fi +else + AC_MSG_RESULT([no]) +fi + +AC_MSG_CHECKING( + [if libtool needs -no-undefined flag to build shared libraries]) +case "${host}" in + *-*-cygwin* | *-*-mingw* | *-*-aix*) + ## Add in the -no-undefined flag to LDFLAGS for libtool. + AC_MSG_RESULT([yes]) + NOUNDEFINED=" -no-undefined" + ;; + *) + ## Don't add in anything. + AC_MSG_RESULT([no]) + ;; +esac +AC_SUBST([NOUNDEFINED]) + +AC_CONFIG_FILES( + [src/Makefile examples/Makefile Makefile]) +AC_OUTPUT + +dnl eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/depcomp b/WebAPP/SOLVERs/GLPK/glpk/depcomp new file mode 100755 index 000000000..e1f51f482 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/depcomp @@ -0,0 +1,787 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2012-07-12.20; # UTC + +# Copyright (C) 1999-2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputting dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Avoid interferences from the environment. +gccflag= dashmflag= + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvisualcpp +fi + +if test "$depmode" = msvc7msys; then + # This is just like msvc7 but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u='sed s,\\\\,/,g' + depmode=msvc7 +fi + +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. +## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. +## (see the conditional assignment to $gccflag above). +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). Also, it might not be +## supported by the other compilers which use the 'gcc' depmode. +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the "deleted header file" problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory +## that the space means something, we add a space to the output as +## well. hp depmode also adds that space, but also prefixes the VPATH +## to the object. Take care to not repeat it in the output. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ + | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like '#:fec' to the end of the + # dependency line. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr "$nl" ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' "$nl" < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts '$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form 'foo.o: dependent.h'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\': + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. + # Do two passes, one to just change these to + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" + rm -f "$tmpdepfile" + ;; + +## The order of this option in the case statement is important, since the +## shell code in configure will try each of these formats in the order +## listed in this file. A plain '-MD' option would be understood by many +## compilers, so we must ensure this comes after the gcc and icc options. +pgcc) + # Portland's C compiler understands '-MD'. + # Will always output deps to 'file.d' where file is the root name of the + # source file under compilation, even if file resides in a subdirectory. + # The object file name does not affect the name of the '.d' file. + # pgcc 10.2 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using '\' : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + # Use the source, not the object, to determine the base name, since + # that's sadly what pgcc will do too. + base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'` + tmpdepfile="$base.d" + + # For projects that build the same source file twice into different object + # files, the pgcc approach of using the *source* file root name can cause + # problems in parallel builds. Use a locking strategy to avoid stomping on + # the same $tmpdepfile. + lockdir="$base.d-lock" + trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15 + numtries=100 + i=$numtries + while test $i -gt 0 ; do + # mkdir is a portable test-and-set. + if mkdir $lockdir 2>/dev/null; then + # This process acquired the lock. + "$@" -MD + stat=$? + # Release the lock. + rm -rf $lockdir + break + else + ## the lock is being held by a different process, + ## wait until the winning process is done or we timeout + while test -d $lockdir && test $i -gt 0; do + sleep 1 + i=`expr $i - 1` + done + fi + i=`expr $i - 1` + done + trap - 1 2 13 15 + if test $i -le 0; then + echo "$0: failed to acquire lock after $numtries attempts" >&2 + echo "$0: check lockdir '$lockdir'" >&2 + exit 1 + fi + + if test $stat -ne 0; then + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add 'dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in 'foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +msvc7) + if test "$libtool" = yes; then + showIncludes=-Wc,-showIncludes + else + showIncludes=-showIncludes + fi + "$@" $showIncludes > "$tmpdepfile" + stat=$? + grep -v '^Note: including file: ' "$tmpdepfile" + if test "$stat" = 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + # The first sed program below extracts the file names and escapes + # backslashes for cygpath. The second sed program outputs the file + # name when reading, but also accumulates all include files in the + # hold buffer in order to output them again at the end. This only + # works with sed implementations that can handle large buffers. + sed < "$tmpdepfile" -n ' +/^Note: including file: *\(.*\)/ { + s//\1/ + s/\\/\\\\/g + p +}' | $cygpath_u | sort -u | sed -n ' +s/ /\\ /g +s/\(.*\)/'"$tab"'\1 \\/p +s/.\(.*\) \\/\1:/ +H +$ { + s/.*/'"$tab"'/ + G + p +}' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvc7msys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for ':' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. + "$@" $dashmflag | + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' "$nl" < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + # makedepend may prepend the VPATH from the source file name to the object. + # No need to regex-escape $object, excess matching of '.' is harmless. + sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove '-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.pdf new file mode 100644 index 000000000..d7ff1932f Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.tex new file mode 100644 index 000000000..4a2c3bbab --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/cnfsat.tex @@ -0,0 +1,413 @@ +%* cnfsat.tex *% + +\documentclass[11pt,draft]{article} +\usepackage{amssymb} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\returns{\para{Returns}} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\title{\bf CNF Satisfiability Problem} + +\author{Andrew Makhorin {\tt}} + +\date{August 2011} + +\maketitle + +\section{Introduction} + +The {\it Satisfiability Problem (SAT)} is a classic combinatorial +problem. Given a Boolean formula of $n$ variables +$$f(x_1,x_2,\dots,x_n),\eqno(1.1)$$ +this problem is to find such values of the variables, on which the +formula takes on the value {\it true}. + +The {\it CNF Satisfiability Problem (CNF-SAT)} is a version of the +Satisfiability Problem, where the Boolean formula (1.1) is specified +in the {\it Conjunctive Normal Form (CNF)}, that means that it is a +conjunction of {\it clauses}, where a clause is a disjunction of +{\it literals}, and a literal is a variable or its negation. +For example: +$$(x_1\vee x_2)\;\&\;(\neg x_2\vee x_3\vee\neg x_4)\;\&\;(\neg +x_1\vee x_4).\eqno(1.2)$$ +Here $x_1$, $x_2$, $x_3$, $x_4$ are Boolean variables to be assigned, +$\neg$ means +negation (logical {\it not}), $\vee$ means disjunction (logical +{\it or}), and $\&$ means conjunction (logical {\it and}). One may +note that the formula (1.2) is {\it satisfiable}, because on +$x_1$ = {\it true}, $x_2$ = {\it false}, $x_3$ = {\it false}, and +$x_4$ = {\it true} it takes on the value {\it true}. If a formula +is not satisfiable, it is called {\it unsatisfiable}, that means that +it takes on the value {\it false} on any values of its variables. + +Any CNF-SAT problem can be easily translated to a 0-1 programming +problem as follows.\linebreak A Boolean variable $x$ can be modeled by +a binary variable in a natural way: $x=1$ means that $x$ takes on the +value {\it true}, and $x=0$ means that $x$ takes on the value +{\it false}. Then, if a literal is a negated variable, i.e. $t=\neg x$, +it can be expressed as $t=1-x$. Since a formula in CNF is a conjunction +of clauses, to provide its satisfiability we should require all its +clauses to take on the value {\it true}. A particular clause is +a disjunction of literals: +$$t\vee t'\vee t''\dots ,\eqno(1.3)$$ +so it takes on the value {\it true} iff at least one of its literals +takes on the value {\it true}, that can be expressed as the following +inequality constraint: +$$t+t'+t''+\dots\geq 1.\eqno(1.4)$$ +Note that no objective function is used in this case, because only +a feasible solution needs to be found. + +For example, the formula (1.2) can be translated to the following +constraints: +$$\begin{array}{c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} +x_1&+&x_2&&&&&\geq&1\\ +&&(1-x_2)&+&x_3&+&(1-x_4)&\geq&1\\ +(1-x_1)&&&&&+&x_4&\geq&1\\ +\end{array}$$ +$$x_1, x_2, x_3, x_4\in\{0,1\}$$ +Carrying out all constant terms to the right-hand side gives +corresponding 0-1 programming problem in the standard format: +$$\begin{array}{r@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }r} +x_1&+&x_2&&&&&\geq&1\\ +&-&x_2&+&x_3&-&x_4&\geq&-1\\ +-x_1&&&&&+&x_4&\geq&0\\ +\end{array}$$ +$$x_1, x_2, x_3, x_4\in\{0,1\}$$ + +In general case translation of a CNF-SAT problem results in the +following 0-1 programming problem: +$$\sum_{j\in J^+_i}x_j-\sum_{j\in J^-_i}x_j\geq 1-|J^-_i|, +\ \ \ i=1,\dots,m\eqno(1.5)$$ +$$x_j\in\{0,1\},\ \ \ j=1,\dots,n\eqno(1.6)$$ +where $n$ is the number of variables, $m$ is the number of clauses +(inequality constraints),\linebreak $J^+_i\subseteq\{1,\dots,n\}$ is +a subset of variables, whose literals in $i$-th clause do not have +negation, and $J^-_i\subseteq\{1,\dots,n\}$ is a subset of variables, +whose literals in $i$-th clause are negations of that variables. It is +assumed that $J^+_i\cap J^-_i=\varnothing$ for all $i$. + +\section{GLPK API Routines} + +\subsection{glp\_read\_cnfsat --- read CNF-SAT problem data in DIMACS +format} + +\synopsis + +\begin{verbatim} + int glp_read_cnfsat(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_cnfsat| reads the CNF-SAT problem data from +a text file in DIMACS format and automatically translates the data to +corresponding 0-1 programming problem instance (1.5)--(1.6). + +The parameter \verb|P| specifies the problem object, to which the +0-1 programming problem instance should be stored. Note that before +reading data the current content of the problem object is completely +erased with the routine \verb|glp_erase_prob|. + +The character string \verb|fname| specifies the name of a text file +to be read in. (If the file name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\newpage + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{DIMACS CNF-SAT problem format}\footnote{This material is based on +the paper ``Satisfiability Suggested Format'', which is publicly +available at {\tt http://dimacs.rutgers.edu/}.} + +The DIMACS input file is a plain ASCII text file. It contains lines of +several types described below. A line is terminated with an end-of-line +character. Fields in each line are separated by at least one blank +space. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any clause lines. It has the following +format: + +\begin{verbatim} + p cnf VARIABLES CLAUSES +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem +line. The three character problem designator \verb|cnf| identifies the +file as containing specification information for the CNF-SAT problem. +The \verb|VARIABLES| field contains an integer value specifying $n$, +the number of variables in the instance. The \verb|CLAUSES| field +contains an integer value specifying $m$, the number of clauses in the +instance. + +\para{Clauses.} The clauses appear immediately after the problem +line. The variables are assumed to be numbered from 1 up to $n$. It is +not necessary that every variable appears in the instance. Each clause +is represented by a sequence of numbers separated by either a space, +tab, or new-line character. The non-negated version of a variable $j$ +is represented by $j$; the negated version is represented by $-j$. Each +clause is terminated by the value 0. Unlike many formats that represent +the end of a clause by a new-line character, this format allows clauses +to be on multiple lines. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the CNF-SAT problem (1.2). + +\begin{footnotesize} +\begin{verbatim} +c sample.cnf +c +c This is an example of the CNF-SAT problem data +c in DIMACS format. +c +p cnf 4 3 +1 2 0 +-4 3 +-2 0 +-1 4 0 +c +c eof +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_check\_cnfsat --- check for CNF-SAT problem instance} + +\synopsis + +\begin{verbatim} + int glp_check_cnfsat(glp\_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_check_cnfsat| checks if the specified problem +object \verb|P| contains a 0-1 programming problem instance in the +format (1.5)--(1.6) and therefore encodes a CNF-SAT problem instance. + +\returns + +If the specified problem object has the format (1.5)--(1.6), the +routine returns zero, otherwise non-zero. + +\subsection{glp\_write\_cnfsat --- write CNF-SAT problem data in DIMACS +format} + +\synopsis + +\begin{verbatim} + int glp_write_cnfsat(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_cnfsat| automatically translates the +specified 0-1 programming problem instance (1.5)--(1.6) to a CNF-SAT +problem instance and writes the problem data to a text file in DIMACS +format. + +The parameter \verb|P| is the problem object, which should specify +a 0-1 programming problem instance in the format (1.5)--(1.6). + +The character string \verb|fname| specifies a name of the output text +file to be written. (If the file name ends with suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +performs automatic compression on writing that file.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\subsection{glp\_minisat1 --- solve CNF-SAT problem instance with +MiniSat solver} + +\synopsis + +\begin{verbatim} + int glp_minisat1(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_minisat1| is a driver to MiniSat, a CNF-SAT +solver developed by Niklas E\'en and Niklas S\"orensson, Chalmers +University of Technology, Sweden.\footnote{The MiniSat software module +is {\it not} part of GLPK, but is used with GLPK and included in the +distribution.} + +\newpage + +It is assumed that the specified problem object \verb|P| contains +a 0-1 programming problem instance in the format (1.5)--(1.6) and +therefore encodes a CNF-SAT problem instance. + +If the problem instance has been successfully solved to the end, the +routine \verb|glp_minisat1| returns 0. In this case the routine +\verb|glp_mip_status| can be used to determine the solution status: + +\begin{itemize} +\item {\tt GLP\_OPT} means that the solver found an integer feasible +solution and therefore the corresponding CNF-SAT instance is +satisfiable; + +\item {\tt GLP\_NOFEAS} means that no integer feasible solution exists +and therefore the corresponding CNF-SAT instance is unsatisfiable. +\end{itemize} + +If an integer feasible solution was found, corresponding values of +binary variables can be retrieved with the routine +\verb|glp_mip_col_val|. + +\returns + +\begin{retlist} +0 & The MIP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found feasible +solution. It only means that the solution process was successful.)\\ + +{\tt GLP\_EDATA} & The specified problem object contains a MIP +instance which does {\it not} have the format (1.5)--(1.6).\\ + +{\tt GLP\_EFAIL} & The solution process was unsuccessful because of +the solver failure.\\ +\end{retlist} + +\subsection{glp\_intfeas1 --- solve integer feasibility problem} + +\synopsis + +\begin{verbatim} + int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); +\end{verbatim} + +\description + +The routine \verb|glp_intfeas1| is a tentative implementation of +an integer feasibility solver based on a CNF-SAT solver (currently +it is MiniSat; see Subsection 2.4). + +If the parameter \verb|use_bound| is zero, the routine searches for +{\it any} integer feasibile solution to the specified integer +programming problem. Note that in this case the objective function is +ignored. + +If the parameter \verb|use_bound| is non-zero, the routine searches for +an integer feasible solution, which provides a value of the objective +function not worse than \verb|obj_bound|. In other word, the parameter +\verb|obj_bound| specifies an upper (in case of minimization) or lower +(in case of maximization) bound to the objective function. + +If the specified problem has been successfully solved to the end, the +routine \verb|glp_intfeas1| returns 0. In this case the routine +\verb|glp_mip_status| can be used to determine the solution status: + +\begin{itemize} +\item {\tt GLP\_FEAS} means that the solver found an integer feasible +solution; + +\item {\tt GLP\_NOFEAS} means that the problem has no integer feasible +solution (if {\tt use\_bound} is zero) or it has no integer feasible +solution, which is not worse than {\tt obj\_bound} (if {\tt use\_bound} +is non-zero). +\end{itemize} + +\newpage + +If an integer feasible solution was found, corresponding values of +variables (columns) can be retrieved with the routine +\verb|glp_mip_col_val|. + +\para{Usage Notes} + +The integer programming problem specified by the parameter \verb|P| +should satisfy to the following requirements: + +\begin{enumerate} +\item All variables (columns) should be either binary ({\tt GLP\_BV}) +or fixed at integer values ({\tt GLP\_FX}). + +\item All constraint and objective coefficients should be integer +numbers in the range\linebreak $[-2^{31},\ +2^{31}-1]$. +\end{enumerate} + +Though there are no special requirements to the constraints, +currently the routine \verb|glp_intfeas1| is efficient mainly for +problems, where most constraints (rows) fall into the following three +classes: + +\begin{enumerate} +\item Covering inequalities +$$\sum_{j}t_j\geq 1,$$ +where $t_j=x_j$ or $t_j=1-x_j$, $x_j$ is a binary variable. + +\item Packing inequalities +$$\sum_{j}t_j\leq 1.$$ + +\item Partitioning equalities (SOS1 constraints) +$$\sum_{j}t_j=1.$$ +\end{enumerate} + +\returns + +\begin{retlist} +0 & The problem has been successfully solved. (This code does +{\it not} necessarily mean that the solver has found an integer +feasible solution. It only means that the solution process was +successful.) \\ + +{\tt GLP\_EDATA} & The specified problem object does not satisfy +to the requirements listed in Paragraph `Usage Notes'. \\ + +{\tt GLP\_ERANGE} & An integer overflow occured on translating the +specified problem to a CNF-SAT problem. \\ + +{\tt GLP\_EFAIL} & The solution process was unsuccessful because of +the solver failure. \\ +\end{retlist} + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.pdf new file mode 100644 index 000000000..34edcb198 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.tex new file mode 100644 index 000000000..e3a8db495 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk.tex @@ -0,0 +1,179 @@ +%* glpk.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017 Andrew Makhorin, +% Department for Applied Informatics, Moscow Aviation Institute, +% Moscow, Russia. All rights reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +% To produce glpk.pdf from glpk.tex run the following two commands: +% latex glpk.tex +% dvipdfm -p letter glpk.dvi +% Note: You need TeX Live 2010 or later version. + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} +\usepackage{lscape} +\usepackage{niceframe} +\usepackage[all]{xy} + +% US Letter = 8.5 x 11 in +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{9in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +%\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +%\setlength{\itemsep}{\parskip} +%\setlength{\parsep}{0pt} +%\setlength{\leftmargini}{\parindent} +%\renewcommand{\labelitemi}{---} + +\newcommand{\Item}[1]{\parbox[t]{\parindent}{#1}} +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\note{\para{Note}} +\def\returns{\para{Returns}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\thispagestyle{empty} + +\artdecoframe{ + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries GNU Linear Programming Kit +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Reference Manual +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.64 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, November 2017) +\end{Large} +\end{center} + +\vspace*{3.8in} +} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016, 2017 Andrew Makhorin, +Department for Applied Informatics, Moscow Aviation Institute, Moscow, +Russia. All rights reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt}\tableofcontents} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\include{glpk01} + +\include{glpk02} + +\include{glpk03} + +\include{glpk04} + +\include{glpk05} + +\include{glpk06} + +\appendix + +\include{glpk07} + +\include{glpk08} + +\include{glpk09} + +\include{glpk10} + +\include{glpk11} + +\include{glpk12} + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk01.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk01.tex new file mode 100644 index 000000000..3ffc587e6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk01.tex @@ -0,0 +1,336 @@ +%* glpk01.tex *% + +\chapter{Introduction} + +GLPK (\underline{G}NU \underline{L}inear \underline{P}rogramming +\underline{K}it) is a set of routines written in the ANSI C programming +language and organized in the form of a callable library. It is +intended for solving linear programming (LP), mixed integer programming +(MIP), and other related problems. + +\section{LP problem} +\label{seclp} + +GLPK assumes the following formulation of the {\it linear programming +(LP)} problem: + +\noindent +\hspace{.5in} minimize (or maximize) +$$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (1.1)$$ +\hspace{.5in} subject to linear constraints +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +x_1&=&a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n} \\ +x_2&=&a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n} \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +x_m&=&a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n} \\ +\end{array} \eqno (1.2) +$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{r@{\:}c@{\:}c@{\:}c@{\:}l} +l_1&\leq&x_1&\leq&u_1 \\ +l_2&\leq&x_2&\leq&u_2 \\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_{m+n}&\leq&x_{m+n}&\leq&u_{m+n} \\ +\end{array} \eqno (1.3) +$$ +where: $x_1, x_2, \dots, x_m$ are auxiliary variables; +$x_{m+1}, x_{m+2}, \dots, x_{m+n}$ are structural variables; +$z$ is the objective function; +$c_1, c_2, \dots, c_n$ are objective coefficients; +$c_0$ is the constant term (``shift'') of the objective function; +$a_{11}, a_{12}, \dots, a_{mn}$ are constraint coefficients; +$l_1, l_2, \dots, l_{m+n}$ are lower bounds of variables; +$u_1, u_2, \dots, u_{m+n}$ are upper bounds of variables. + +Auxiliary variables are also called {\it rows}, because they correspond +to rows of the constraint matrix (i.e. a matrix built of the constraint +coefficients). Similarly, structural variables are also called +{\it columns}, because they correspond to columns of the constraint +matrix. + +Bounds of variables can be finite as well as infinite. Besides, lower +and upper bounds can be equal to each other. Thus, the following types +of variables are possible: + +\begin{center} +\begin{tabular}{r@{}c@{}ll} +\multicolumn{3}{c}{Bounds of variable} & Type of variable \\ +\hline +$-\infty <$ &$\ x_k\ $& $< +\infty$ & Free (unbounded) variable \\ +$l_k \leq$ &$\ x_k\ $& $< +\infty$ & Variable with lower bound \\ +$-\infty <$ &$\ x_k\ $& $\leq u_k$ & Variable with upper bound \\ +$l_k \leq$ &$\ x_k\ $& $\leq u_k$ & Double-bounded variable \\ +$l_k =$ &$\ x_k\ $& $= u_k$ & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +Note that the types of variables shown above are applicable to +structural as well as to auxiliary variables. + +To solve the LP problem (1.1)---(1.3) is to find such values of all +structural and auxiliary variables, which: + +%\vspace*{-10pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}satisfy to all the linear constraints (1.2), and + +\Item{---}are within their bounds (1.3), and + +\Item{---}provide smallest (in case of minimization) or largest (in +case of maximization) value of the objective function (1.1). +%\end{itemize} + +\section{MIP problem} + +{\it Mixed integer linear programming (MIP)} problem is an LP problem +in which some variables are additionally required to be integer. + +GLPK assumes that MIP problem has the same formulation as ordinary +(pure) LP problem (1.1)---(1.3), i.e. includes auxiliary and structural +variables, which may have lower and/or upper bounds. However, in case +of MIP problem some variables may be required to be integer. This +additional constraint means that a value of each {\it integer variable} +must be only integer number. (Should note that GLPK allows only +structural variables to be of integer kind.) + +\section{Using the package} + +\subsection{Brief example} + +In order to understand what GLPK is from the user's standpoint, +consider the following simple LP problem: + +\noindent +\hspace{.5in} maximize +$$z = 10 x_1 + 6 x_2 + 4 x_3$$ +\hspace{.5in} subject to +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +x_1 &+&x_2 &+&x_3 &\leq 100 \\ +10 x_1 &+& 4 x_2 & +&5 x_3 & \leq 600 \\ +2 x_1 &+& 2 x_2 & +& 6 x_3 & \leq 300 \\ +\end{array} +$$ +\hspace{.5in} where all variables are non-negative +$$x_1 \geq 0, \ x_2 \geq 0, \ x_3 \geq 0$$ + +At first, this LP problem should be transformed to the standard form +(1.1)---(1.3). This can be easily done by introducing auxiliary +variables, by one for each original inequality constraint. Thus, the +problem can be reformulated as follows: + +\noindent +\hspace{.5in} maximize +$$z = 10 x_1 + 6 x_2 + 4 x_3$$ +\hspace{.5in} subject to +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +p& = &x_1 &+&x_2 &+&x_3 \\ +q& = &10 x_1 &+& 4 x_2 &+& 5 x_3 \\ +r& = &2 x_1 &+& 2 x_2 &+& 6 x_3 \\ +\end{array} +$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{ccc} +\nonumber -\infty < p \leq 100 && 0 \leq x_1 < +\infty \\ +\nonumber -\infty < q \leq 600 && 0 \leq x_2 < +\infty \\ +\nonumber -\infty < r \leq 300 && 0 \leq x_3 < +\infty \\ +\end{array} +$$ +where $p, q, r$ are auxiliary variables (rows), and $x_1, x_2, x_3$ are +structural variables (columns). + +The example C program shown below uses GLPK API routines in order to +solve this LP problem.\footnote{If you just need to solve LP or MIP +instance, you may write it in MPS or CPLEX LP format and then use the +GLPK stand-alone solver to obtain a solution. This is much less +time-consuming than programming in C with GLPK API routines.} + +\begin{footnotesize} +\begin{verbatim} +/* sample.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], z, x1, x2, x3; +s1: lp = glp_create_prob(); +s2: glp_set_prob_name(lp, "sample"); +s3: glp_set_obj_dir(lp, GLP_MAX); +s4: glp_add_rows(lp, 3); +s5: glp_set_row_name(lp, 1, "p"); +s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); +s7: glp_set_row_name(lp, 2, "q"); +s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); +s9: glp_set_row_name(lp, 3, "r"); +s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); +s11: glp_add_cols(lp, 3); +s12: glp_set_col_name(lp, 1, "x1"); +s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); +s14: glp_set_obj_coef(lp, 1, 10.0); +s15: glp_set_col_name(lp, 2, "x2"); +s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); +s17: glp_set_obj_coef(lp, 2, 6.0); +s18: glp_set_col_name(lp, 3, "x3"); +s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); +s20: glp_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: glp_load_matrix(lp, 9, ia, ja, ar); +s31: glp_simplex(lp, NULL); +s32: z = glp_get_obj_val(lp); +s33: x1 = glp_get_col_prim(lp, 1); +s34: x2 = glp_get_col_prim(lp, 2); +s35: x3 = glp_get_col_prim(lp, 3); +s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", + z, x1, x2, x3); +s37: glp_delete_prob(lp); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +The statement \verb|s1| creates a problem object. Being created the +object is initially empty. The statement \verb|s2| assigns a symbolic +name to the problem object. + +The statement \verb|s3| calls the routine \verb|glp_set_obj_dir| in +order to set the optimization direction flag, where \verb|GLP_MAX| +means maximization. + +The statement \verb|s4| adds three rows to the problem object. + +The statement \verb|s5| assigns the symbolic name `\verb|p|' to the +first row, and the statement \verb|s6| sets the type and bounds of the +first row, where \verb|GLP_UP| means that the row has an upper bound. +The statements \verb|s7|, \verb|s8|, \verb|s9|, \verb|s10| are used in +the same way in order to assign the symbolic names `\verb|q|' and +`\verb|r|' to the second and third rows and set their types and bounds. + +The statement \verb|s11| adds three columns to the problem object. + +The statement \verb|s12| assigns the symbolic name `\verb|x1|' to the +first column, the statement \verb|s13| sets the type and bounds of the +first column, where \verb|GLP_LO| means that the column has an lower +bound, and the statement \verb|s14| sets the objective coefficient for +the first column. The statements \verb|s15|---\verb|s20| are used in +the same way in order to assign the symbolic names `\verb|x2|' and +`\verb|x3|' to the second and third columns and set their types, +bounds, and objective coefficients. + +The statements \verb|s21|---\verb|s29| prepare non-zero elements of the +constraint matrix (i.e. constraint coefficients). Row indices of each +element are stored in the array \verb|ia|, column indices are stored in +the array \verb|ja|, and numerical values of corresponding elements are +stored in the array \verb|ar|. Then the statement \verb|s30| calls +the routine \verb|glp_load_matrix|, which loads information from these +three arrays into the problem object. + +Now all data have been entered into the problem object, and therefore +the statement \verb|s31| calls the routine \verb|glp_simplex|, which is +a driver to the simplex method, in order to solve the LP problem. This +routine finds an optimal solution and stores all relevant information +back into the problem object. + +The statement \verb|s32| obtains a computed value of the objective +function, and the statements \verb|s33|---\verb|s35| obtain computed +values of structural variables (columns), which correspond to the +optimal basic solution found by the solver. + +The statement \verb|s36| writes the optimal solution to the standard +output. The printout may look like follows: + +\newpage + +\begin{footnotesize} +\begin{verbatim} +* 0: objval = 0.000000000e+00 infeas = 0.000000000e+00 (0) +* 2: objval = 7.333333333e+02 infeas = 0.000000000e+00 (0) +OPTIMAL SOLUTION FOUND + +z = 733.333; x1 = 33.3333; x2 = 66.6667; x3 = 0 +\end{verbatim} +\end{footnotesize} + +Finally, the statement \verb|s37| calls the routine +\verb|glp_delete_prob|, which frees all the memory allocated to the +problem object. + +\subsection{Compiling} + +The GLPK package has the only header file \verb|glpk.h|, which should +be available on compiling a C (or C++) program using GLPK API routines. + +If the header file is installed in the default location +\verb|/usr/local/include|, the following typical command may be used to +compile, say, the example C program described above with the GNU C +compiler: + +\begin{verbatim} + $ gcc -c sample.c +\end{verbatim} + +If \verb|glpk.h| is not in the default location, the corresponding +directory containing it should be made known to the C compiler through +\verb|-I| option, for example: + +\begin{verbatim} + $ gcc -I/foo/bar/glpk-4.15/include -c sample.c +\end{verbatim} + +In any case the compilation results in an object file \verb|sample.o|. + +\subsection{Linking} + +The GLPK library is a single file \verb|libglpk.a|. (On systems which +support shared libraries there may be also a shared version of the +library \verb|libglpk.so|.) + +If the library is installed in the default +location \verb|/usr/local/lib|, the following typical command may be +used to link, say, the example C program described above against with +the library: + +\begin{verbatim} + $ gcc sample.o -lglpk -lm +\end{verbatim} + +If the GLPK library is not in the default location, the corresponding +directory containing it should be made known to the linker through +\verb|-L| option, for example: + +\begin{verbatim} + $ gcc -L/foo/bar/glpk-4.15 sample.o -lglpk -lm +\end{verbatim} + +Depending on configuration of the package linking against with the GLPK +library may require optional libraries, in which case these libraries +should be also made known to the linker, for example: + +\begin{verbatim} + $ gcc sample.o -lglpk -lgmp -lm +\end{verbatim} + +For more details about configuration options of the GLPK package see +Appendix \ref{install}, page \pageref{install}. + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk02.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk02.tex new file mode 100644 index 000000000..f49ae75f0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk02.tex @@ -0,0 +1,3480 @@ +%* glpk02.tex *% + +\chapter{Basic API Routines} + +\section{General conventions} + +\subsection{Library header} + +All GLPK API data types and routines are defined in the header file +\verb|glpk.h|. It should be included in all source files which use +GLPK API, either directly or indirectly through some other header file +as follows: + +\begin{verbatim} + #include +\end{verbatim} + +\subsection{Error handling} + +If some GLPK API routine detects erroneous or incorrect data passed by +the application program, it writes appropriate diagnostic messages to +the terminal and then abnormally terminates the application program. +In most practical cases this allows to simplify programming by avoiding +numerous checks of return codes. Thus, in order to prevent crashing the +application program should check all data, which are suspected to be +incorrect, before calling GLPK API routines. + +Should note that this kind of error handling is used only in cases of +incorrect data passed by the application program. If, for example, the +application program calls some GLPK API routine to read data from an +input file and these data are incorrect, the GLPK API routine reports +about error in the usual way by means of the return code. + +\subsection{Thread safety} + +The standard version of GLPK API is {\it not} thread safe and therefore +should not be used in multi-threaded programs. + +\subsection{Array indexing} + +Normally all GLPK API routines start array indexing from 1, not from 0 +(except the specially stipulated cases). This means, for example, that +if some vector $x$ of the length $n$ is passed as an array to some GLPK +API routine, the latter expects vector components to be placed in +locations \verb|x[1]|, \verb|x[2]|, \dots, \verb|x[n]|, and the +location \verb|x[0]| normally is not used. + +To avoid indexing errors it is most convenient and most reliable to +declare the array \verb|x| as follows: + +\begin{verbatim} + double x[1+n]; +\end{verbatim} + +\noindent +or to allocate it as follows: + +\begin{verbatim} + double *x; + . . . + x = calloc(1+n, sizeof(double)); + . . . +\end{verbatim} + +\noindent +In both cases one extra location \verb|x[0]| is reserved that allows +passing the array to GLPK routines in a usual way. + +\section{Problem object} + +All GLPK API routines deal with so called {\it problem object}, which +is a program object of type \verb|glp_prob| and intended to represent +a particular LP or MIP instance. + +The type \verb|glp_prob| is a data structure declared in the header +file \verb|glpk.h| as follows: + +\begin{verbatim} + typedef struct glp_prob glp_prob; +\end{verbatim} + +Problem objects (i.e. program objects of the \verb|glp_prob| type) are +allocated and managed internally by the GLPK API routines. The +application program should never use any members of the \verb|glp_prob| +structure directly and should deal only with pointers to these objects +(that is, \verb|glp_prob *| values). + +The problem object consists of the following segments: + +%\vspace*{-8pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}problem segment, + +\Item{---}basis segment, + +\Item{---}interior-point segment, and + +\Item{---}MIP segment. +%\end{itemize} + +\subsection{Problem segment} + +The {\it problem segment} contains original LP/MIP data, which +corresponds to the problem formulation (1.1)---(1.3) (see Section +\ref{seclp}, page \pageref{seclp}). This segment includes the following +components: + +%\vspace*{-8pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}rows (auxiliary variables), + +\Item{---}columns (structural variables), + +\Item{---}objective function, and + +\Item{---}constraint matrix. +%\end{itemize} + +%\vspace*{-7pt} + +Rows and columns have the same set of the following attributes: + +%\vspace*{-7pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}ordinal number, + +\Item{---}symbolic name (1 up to 255 arbitrary graphic characters), + +\Item{---}type (free, lower bound, upper bound, double bound, fixed), + +\Item{---}numerical values of lower and upper bounds, + +\Item{---}scale factor. +%\end{itemize} + +%\vspace*{-7pt} + +{\it Ordinal numbers} are intended for referencing rows and columns. +Row ordinal numbers are integers $1, 2, \dots, m$, and column ordinal +numbers are integers $1, 2, \dots, n$, where $m$ and $n$ are, +respectively, the current number of rows and columns in the problem +object. + +{\it Symbolic names} are intended for informational purposes. They also +can be used for referencing rows and columns. + +{\it Types and bounds} of rows (auxiliary variables) and columns +(structural variables) are explained above (see Section \ref{seclp}, +page \pageref{seclp}). + +{\it Scale factors} are used internally for scaling rows and columns of +the constraint matrix. + +Information about the {\it objective function} includes numerical +values of objective coefficients and a flag, which defines the +optimization direction (i.e. minimization or maximization). + +The {\it constraint matrix} is a $m \times n$ rectangular matrix built +of constraint coefficients $a_{ij}$, which defines the system of linear +constraints (1.2) (see Section \ref{seclp}, page \pageref{seclp}). This +matrix is stored in the problem object in both row-wise and column-wise +sparse formats. + +Once the problem object has been created, the application program can +access and modify any components of the problem segment in arbitrary +order. + +\subsection{Basis segment} + +The {\it basis segment} of the problem object keeps information related +to the current basic solution. It includes: + +%\vspace*{-8pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}row and column statuses, + +\Item{---}basic solution statuses, + +\Item{---}factorization of the current basis matrix, and + +\Item{---}basic solution components. +%\end{itemize} + +%\vspace*{-8pt} + +The {\it row and column statuses} define which rows and columns are +basic and which are non-basic. These statuses may be assigned either by +the application program of by some API routines. Note that these +statuses are always defined independently on whether the corresponding +basis is valid or not. + +The {\it basic solution statuses} include the {\it primal status} and +the {\it dual status}, which are set by the simplex-based solver once +the problem has been solved. The primal status shows whether a primal +basic solution is feasible, infeasible, or undefined. The dual status +shows the same for a dual basic solution. + +The {\it factorization of the basis matrix} is some factorized form +(like {\it LU}-factorization) of the current basis matrix (defined by +the current row and column statuses). The factorization is used by +simplex-based solvers and kept when the solver terminates the search. +This feature allows efficiently reoptimizing the problem after some +modifications (for example, after changing some bounds or objective +coefficients). It also allows performing the post-optimal analysis (for +example, computing components of the simplex table, etc.). + +The {\it basic solution components} include primal and dual values of +all auxiliary and structural variables for the most recently obtained +basic solution. + +\subsection{Interior-point segment} + +The {\it interior-point segment} contains interior-point solution +components, which include the solution status, and primal and dual +values of all auxiliary and structural variables. + +\subsection{MIP segment} + +The {\it MIP segment} is used only for MIP problems. This segment +includes: + +%\vspace*{-8pt} + +%\begin{itemize}\setlength{\itemsep}{0pt} +\Item{---}column kinds, + +\Item{---}MIP solution status, and + +\Item{---}MIP solution components. +%\end{itemize} + +%\vspace*{-8pt} + +The {\it column kinds} define which columns (i.e. structural variables) +are integer and which are continuous. + +The {\it MIP solution status} is set by the MIP solver and shows whether +a MIP solution is integer optimal, integer feasible (non-optimal), or +undefined. + +The {\it MIP solution components} are computed by the MIP solver and +include primal values of all auxiliary and structural variables for the +most recently obtained MIP solution. + +Note that in case of MIP problem the basis segment corresponds to +the optimal solution of LP relaxation, which is also available to the +application program. + +Currently the search tree is not kept in the MIP segment, so if the +search has been terminated, it cannot be continued. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem creating and modifying routines} + +\subsection{glp\_create\_prob --- create problem object} + +\synopsis + +\begin{verbatim} + glp_prob *glp_create_prob(void); +\end{verbatim} + +\description + +The routine \verb|glp_create_prob| creates a new problem object, which +initially is ``empty'', i.e. has no rows and columns. + +\returns + +The routine returns a pointer to the created object, which should be +used in any subsequent operations on this object. + +\subsection{glp\_set\_prob\_name --- assign (change) problem name} + +\synopsis + +\begin{verbatim} + void glp_set_prob_name(glp_prob *P, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_prob_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing symbolic name of the problem object. + +\subsection{glp\_set\_obj\_name --- assign (change) objective function +name} + +\synopsis + +\begin{verbatim} + void glp_set_obj_name(glp_prob *P, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to the objective function of the +specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing symbolic name of the objective function. + +\newpage + +\subsection{glp\_set\_obj\_dir --- set (change) optimization direction +flag} + +\synopsis + +\begin{verbatim} + void glp_set_obj_dir(glp_prob *P, int dir); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_dir| sets (changes) the optimization +direction flag (i.e. ``sense'' of the objective function) as specified +by the parameter \verb|dir|: + +\verb|GLP_MIN| means minimization; + +\verb|GLP_MAX| means maximization. + +Note that by default the problem is minimization. + +\subsection{glp\_add\_rows --- add new rows to problem object} + +\synopsis + +\begin{verbatim} + int glp_add_rows(glp_prob *P, int nrs); +\end{verbatim} + +\description + +The routine \verb|glp_add_rows| adds \verb|nrs| rows (constraints) to +the specified problem object. New rows are always added to the end of +the row list, so the ordinal numbers of existing rows are not changed. + +Being added each new row is initially free (unbounded) and has empty +list of the constraint coefficients. + +Each new row becomes a non-active (non-binding) constraint, i.e. the +corresponding auxiliary variable is marked as basic. + +If the basis factorization exists, adding row(s) invalidates it. + +\returns + +The routine \verb|glp_add_rows| returns the ordinal number of the first +new row added to the problem object. + +\subsection{glp\_add\_cols --- add new columns to problem object} + +\synopsis + +\begin{verbatim} + int glp_add_cols(glp_prob *P, int ncs); +\end{verbatim} + +\description + +The routine \verb|glp_add_cols| adds \verb|ncs| columns (structural +variables) to the specified problem object. New columns are always +added to the end of the column list, so the ordinal numbers of existing +columns are not changed. + +Being added each new column is initially fixed at zero and has empty +list of the constraint coefficients. + +Each new column is marked as non-basic, i.e. zero value of the +corresponding structural variable becomes an active (binding) bound. + +If the basis factorization exists, it remains valid. + +\returns + +The routine \verb|glp_add_cols| returns the ordinal number of the first +new column added to the problem object. + +\subsection{glp\_set\_row\_name --- assign (change) row name} + +\synopsis + +\begin{verbatim} + void glp_set_row_name(glp_prob *P, int i, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_row_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to \verb|i|-th row (auxiliary +variable) of the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of $i$-th row. + +\subsection{glp\_set\_col\_name --- assign (change) column name} + +\synopsis + +\begin{verbatim} + void glp_set_col_name(glp_prob *P, int j, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_name| assigns a given symbolic +\verb|name| (1 up to 255 characters) to \verb|j|-th column (structural +variable) of the specified problem object. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of $j$-th column. + +\subsection{glp\_set\_row\_bnds --- set (change) row bounds} + +\synopsis + +{\tt void glp\_set\_row\_bnds(glp\_prob *P, int i, int type, +double lb, double ub);} + +\description + +The routine \verb|glp_set_row_bnds| sets (changes) the type and bounds +of \verb|i|-th row (auxiliary variable) of the specified problem +object. + +The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, +lower bound, and upper bound, respectively, as follows: + +\begin{center} +\begin{tabular}{cr@{}c@{}ll} +Type & \multicolumn{3}{c}{Bounds} & Comment \\ +\hline +\verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ + & Free (unbounded) variable \\ +\verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ + & Variable with lower bound \\ +\verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ + & Variable with upper bound \\ +\verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ + & Double-bounded variable \\ +\verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ + & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +where $x$ is the auxiliary variable associated with $i$-th row. + +If the row has no lower bound, the parameter \verb|lb| is ignored. If +the row has no upper bound, the parameter \verb|ub| is ignored. If the +row is an equality constraint (i.e. the corresponding auxiliary +variable is of fixed type), only the parameter \verb|lb| is used while +the parameter \verb|ub| is ignored. + +Being added to the problem object each row is initially free, i.e. its +type is \verb|GLP_FR|. + +\subsection{glp\_set\_col\_bnds --- set (change) column bounds} + +\synopsis + +{\tt void glp\_set\_col\_bnds(glp\_prob *P, int j, int type, +double lb, double ub);} + +\description + +The routine \verb|glp_set_col_bnds| sets (changes) the type and bounds +of \verb|j|-th column (structural variable) of the specified problem +object. + +The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, +lower bound, and upper bound, respectively, as follows: + +\begin{center} +\begin{tabular}{cr@{}c@{}ll} +Type & \multicolumn{3}{c}{Bounds} & Comment \\ +\hline +\verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ + & Free (unbounded) variable \\ +\verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ + & Variable with lower bound \\ +\verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ + & Variable with upper bound \\ +\verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ + & Double-bounded variable \\ +\verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ + & Fixed variable \\ +\end{tabular} +\end{center} + +\noindent +where $x$ is the structural variable associated with $j$-th column. + +If the column has no lower bound, the parameter \verb|lb| is ignored. +If the column has no upper bound, the parameter \verb|ub| is ignored. +If the column is of fixed type, only the parameter \verb|lb| is used +while the parameter \verb|ub| is ignored. + +Being added to the problem object each column is initially fixed at +zero, i.e. its type is \verb|GLP_FX| and both bounds are 0. + +%\newpage + +\subsection{glp\_set\_obj\_coef --- set (change) objective coefficient +or constant term} + +\synopsis + +\begin{verbatim} + void glp_set_obj_coef(glp_prob *P, int j, double coef); +\end{verbatim} + +\description + +The routine \verb|glp_set_obj_coef| sets (changes) the objective +coefficient at \verb|j|-th column (structural variable). A new value of +the objective coefficient is specified by the parameter \verb|coef|. + +If the parameter \verb|j| is 0, the routine sets (changes) the constant +term (``shift'') of the objective function. + +\newpage + +\subsection{glp\_set\_mat\_row --- set (replace) row of the constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], + const double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_set_mat_row| stores (replaces) the contents of +\verb|i|-th row of the constraint matrix of the specified problem +object. + +Column indices and numerical values of new row elements should be +placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +$0 \leq$ \verb|len| $\leq n$ is the new length of $i$-th row, $n$ is +the current number of columns in the problem object. Elements with +identical column indices are not allowed. Zero elements are allowed, +but they are not stored in the constraint matrix. + +If the parameter \verb|len| is 0, the parameters \verb|ind| and/or +\verb|val| can be specified as \verb|NULL|. + +\note + +If the basis factorization exists and changing the row changes +coefficients at basic column(s), the factorization is invalidated. + +\subsection{glp\_set\_mat\_col --- set (replace) column of the +constr\-aint matrix} + +\synopsis + +\begin{verbatim} + void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], + const double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_set_mat_col| stores (replaces) the contents of +\verb|j|-th column of the constraint matrix of the specified problem +object. + +Row indices and numerical values of new column elements should be +placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +$0 \leq$ \verb|len| $\leq m$ is the new length of $j$-th column, $m$ is +the current number of rows in the problem object. Elements with +identical row indices are not allowed. Zero elements are allowed, but +they are not stored in the constraint matrix. + +If the parameter \verb|len| is 0, the parameters \verb|ind| and/or +\verb|val| can be specified as \verb|NULL|. + +\note + +If the basis factorization exists, changing the column corresponding +to a basic structural variable invalidates it. + +\newpage + +\subsection{glp\_load\_matrix --- load (replace) the whole constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_load_matrix(glp_prob *P, int ne, const int ia[], + const int ja[], const double ar[]); +\end{verbatim} + +\description + +The routine \verb|glp_load_matrix| loads the constraint matrix passed +in the arrays \verb|ia|, \verb|ja|, and \verb|ar| into the specified +problem object. Before loading the current contents of the constraint +matrix is destroyed. + +Constraint coefficients (elements of the constraint matrix) should be +specified as triplets (\verb|ia[k]|, \verb|ja[k]|, \verb|ar[k]|) for +$k=1,\dots,ne$, where \verb|ia[k]| is the row index, \verb|ja[k]| is +the column index, and \verb|ar[k]| is a numeric value of corresponding +constraint coefficient. The parameter \verb|ne| specifies the total +number of (non-zero) elements in the matrix to be loaded. Coefficients +with identical indices are not allowed. Zero coefficients are allowed, +however, they are not stored in the constraint matrix. + +If the parameter \verb|ne| is 0, the parameters \verb|ia|, \verb|ja|, +and/or \verb|ar| can be specified as \verb|NULL|. + +\note + +If the basis factorization exists, this operation invalidates it. + +\subsection{glp\_check\_dup --- check for duplicate elements in sparse +matrix} + +\synopsis + +{\tt int glp\_check\_dup(int m, int n, int ne, const int ia[], +const int ja[]);} + +\description + +The routine \verb|glp_check_dup checks| for duplicate elements (that +is, elements with identical indices) in a sparse matrix specified in +the coordinate format. + +The parameters $m$ and $n$ specifies, respectively, the number of rows +and columns in the matrix, $m\geq 0$, $n\geq 0$. + +The parameter {\it ne} specifies the number of (structurally) non-zero +elements in the matrix,\linebreak {\it ne} $\geq 0$. + +Elements of the matrix are specified as doublets $(ia[k],ja[k])$ for +$k=1,\dots,ne$, where $ia[k]$ is a row index, $ja[k]$ is a column +index. + +The routine \verb|glp_check_dup| can be used prior to a call to the +routine \verb|glp_load_matrix| to check that the constraint matrix to +be loaded has no duplicate elements. + +\returns + +\begin{retlist} +0& the matrix representation is correct;\\ +$-k$& indices $ia[k]$ or/and $ja[k]$ are out of range;\\ +$+k$& element $(ia[k],ja[k])$ is duplicate.\\ +\end{retlist} + +\subsection{glp\_sort\_matrix --- sort elements of the constraint +matrix} + +\synopsis + +\begin{verbatim} + void glp_sort_matrix(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_sort_matrix| sorts elements of the constraint +matrix by rebuilding its row and column linked lists. + +On exit from the routine the constraint matrix is not changed, however, +elements in the row linked lists become ordered by ascending column +indices, and the elements in the column linked lists become ordered by +ascending row indices. + +\subsection{glp\_del\_rows --- delete rows from problem object} + +\synopsis + +\begin{verbatim} + void glp_del_rows(glp_prob *P, int nrs, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_rows| deletes rows from the specified problem +object. Ordinal numbers of rows to be deleted should be placed in +locations \verb|num[1]|, \dots, \verb|num[nrs]|, where ${\tt nrs}>0$. + +Note that deleting rows involves changing ordinal numbers of other +rows remaining in the problem object. New ordinal numbers of the +remaining rows are assigned under the assumption that the original +order of rows is not changed. Let, for example, before deletion there +be five rows $a$, $b$, $c$, $d$, $e$ with ordinal numbers 1, 2, 3, 4, +5, and let rows $b$ and $d$ have been deleted. Then after deletion the +remaining rows $a$, $c$, $e$ are assigned new oridinal numbers 1, 2, 3. + +If the basis factorization exists, deleting active (binding) rows, +i.e. whose auxiliary variables are marked as non-basic, invalidates it. + +%\newpage + +\subsection{glp\_del\_cols --- delete columns from problem object} + +\synopsis + +\begin{verbatim} + void glp_del_cols(glp_prob *P, int ncs, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_cols| deletes columns from the specified +problem object. Ordinal numbers of columns to be deleted should be +placed in locations \verb|num[1]|, \dots, \verb|num[ncs]|, where +${\tt ncs}>0$. + +Note that deleting columns involves changing ordinal numbers of other +columns remaining in\linebreak the problem object. New ordinal numbers +of the remaining columns are assigned under the assumption that the +original order of columns is not changed. Let, for example, before +deletion there be six columns $p$, $q$, $r$, $s$, $t$, $u$ with +ordinal numbers 1, 2, 3, 4, 5, 6, and let columns $p$, $q$, $s$ have +been deleted. Then after deletion the remaining columns $r$, $t$, $u$ +are assigned new ordinal numbers 1, 2, 3. + +If the basis factorization exists, deleting basic columns invalidates +it. + +\subsection{glp\_copy\_prob --- copy problem object content} + +\synopsis + +\begin{verbatim} + void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +\end{verbatim} + +\description + +The routine \verb|glp_copy_prob| copies the content of the problem +object \verb|prob| to the problem object \verb|dest|. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, +the routine also copies all symbolic names; otherwise, if it is +\verb|GLP_OFF|, no symbolic names are copied. + +\subsection{glp\_erase\_prob --- erase problem object content} + +\synopsis + +\begin{verbatim} + void glp_erase_prob(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_erase_prob| erases the content of the specified +problem object. The effect of this operation is the same as if the +problem object would be deleted with the routine \verb|glp_delete_prob| +and then created anew with the routine \verb|glp_create_prob|, with the +only exception that the pointer to the problem object remains valid. + +%\newpage + +\subsection{glp\_delete\_prob --- delete problem object} + +\synopsis + +\begin{verbatim} + void glp_delete_prob(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_delete_prob| deletes a problem object, which the +parameter \verb|lp| points to, freeing all the memory allocated to this +object. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem retrieving routines} + +\subsection{glp\_get\_prob\_name --- retrieve problem name} + +\synopsis + +\begin{verbatim} + const char *glp_get_prob_name(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_prob_name| returns a pointer to an internal +buffer, which contains symbolic name of the problem. However, if the +problem has no assigned name, the routine returns \verb|NULL|. + +\subsection{glp\_get\_obj\_name --- retrieve objective function name} + +\synopsis + +\begin{verbatim} + const char *glp_get_obj_name(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_name| returns a pointer to an internal +buffer, which contains symbolic name assigned to the objective +function. However, if the objective function has no assigned name, the +routine returns \verb|NULL|. + +\subsection{glp\_get\_obj\_dir --- retrieve optimization direction +flag} + +\synopsis + +\begin{verbatim} + int glp_get_obj_dir(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_dir| returns the optimization direction +flag (i.e. ``sense'' of the objective function): + +\verb|GLP_MIN| means minimization; + +\verb|GLP_MAX| means maximization. + +\subsection{glp\_get\_num\_rows --- retrieve number of rows} + +\synopsis + +\begin{verbatim} + int glp_get_num_rows(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_rows| returns the current number of rows +in the specified problem object. + +\newpage + +\subsection{glp\_get\_num\_cols --- retrieve number of columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_cols(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_cols| returns the current number of +columns in the specified problem object. + +\subsection{glp\_get\_row\_name --- retrieve row name} + +\synopsis + +\begin{verbatim} + const char *glp_get_row_name(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_name| returns a pointer to an internal +buffer, which contains a symbolic name assigned to \verb|i|-th row. +However, if the row has no assigned name, the routine returns +\verb|NULL|. + +\subsection{glp\_get\_col\_name --- retrieve column name} + +\synopsis + +\begin{verbatim} + const char *glp_get_col_name(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_name| returns a pointer to an internal +buffer, which contains a symbolic name assigned to \verb|j|-th column. +However, if the column has no assigned name, the routine returns +\verb|NULL|. + +\subsection{glp\_get\_row\_type --- retrieve row type} + +\synopsis + +\begin{verbatim} + int glp_get_row_type(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_type| returns the type of \verb|i|-th +row, i.e. the type of corresponding auxiliary variable, as follows: + +\verb|GLP_FR| --- free (unbounded) variable; + +\verb|GLP_LO| --- variable with lower bound; + +\verb|GLP_UP| --- variable with upper bound; + +\verb|GLP_DB| --- double-bounded variable; + +\verb|GLP_FX| --- fixed variable. + +\subsection{glp\_get\_row\_lb --- retrieve row lower bound} + +\synopsis + +\begin{verbatim} + double glp_get_row_lb(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_lb| returns the lower bound of +\verb|i|-th row, i.e. the lower bound of corresponding auxiliary +variable. However, if the row has no lower bound, the routine returns +\verb|-DBL_MAX|. + +\vspace*{-4pt} + +\subsection{glp\_get\_row\_ub --- retrieve row upper bound} + +\synopsis + +\begin{verbatim} + double glp_get_row_ub(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_ub| returns the upper bound of +\verb|i|-th row, i.e. the upper bound of corresponding auxiliary +variable. However, if the row has no upper bound, the routine returns +\verb|+DBL_MAX|. + +\vspace*{-4pt} + +\subsection{glp\_get\_col\_type --- retrieve column type} + +\synopsis + +\begin{verbatim} + int glp_get_col_type(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_type| returns the type of \verb|j|-th +column, i.e. the type of corresponding structural variable, as follows: + +\verb|GLP_FR| --- free (unbounded) variable; + +\verb|GLP_LO| --- variable with lower bound; + +\verb|GLP_UP| --- variable with upper bound; + +\verb|GLP_DB| --- double-bounded variable; + +\verb|GLP_FX| --- fixed variable. + +\vspace*{-4pt} + +\subsection{glp\_get\_col\_lb --- retrieve column lower bound} + +\synopsis + +\begin{verbatim} + double glp_get_col_lb(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_lb| returns the lower bound of +\verb|j|-th column, i.e. the lower bound of corresponding structural +variable. However, if the column has no lower bound, the routine +returns \verb|-DBL_MAX|. + +\subsection{glp\_get\_col\_ub --- retrieve column upper bound} + +\synopsis + +\begin{verbatim} + double glp_get_col_ub(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_ub| returns the upper bound of +\verb|j|-th column, i.e. the upper bound of corresponding structural +variable. However, if the column has no upper bound, the routine +returns \verb|+DBL_MAX|. + +\subsection{glp\_get\_obj\_coef --- retrieve objective coefficient or +constant term} + +\synopsis + +\begin{verbatim} + double glp_get_obj_coef(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_coef| returns the objective coefficient +at \verb|j|-th structural variable (column). + +If the parameter \verb|j| is 0, the routine returns the constant term +(``shift'') of the objective function. + +\subsection{glp\_get\_num\_nz --- retrieve number of constraint +coefficients} + +\synopsis + +\begin{verbatim} + int glp_get_num_nz(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_nz| returns the number of non-zero +elements in the constraint matrix of the specified problem object. + +\subsection{glp\_get\_mat\_row --- retrieve row of the constraint +matrix} + +\synopsis + +\begin{verbatim} + int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_get_mat_row| scans (non-zero) elements of +\verb|i|-th row of the constraint matrix of the specified problem +object and stores their column indices and numeric values to locations +\verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, +\verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is the +number of elements in $i$-th row, $n$ is the number of columns. + +The parameter \verb|ind| and/or \verb|val| can be specified as +\verb|NULL|, in which case corresponding information is not stored. + +%\newpage + +\returns + +The routine \verb|glp_get_mat_row| returns the length \verb|len|, i.e. +the number of (non-zero) elements in \verb|i|-th row. + +\subsection{glp\_get\_mat\_col --- retrieve column of the constraint +matrix} + +\synopsis + +\begin{verbatim} + int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_get_mat_col| scans (non-zero) elements of +\verb|j|-th column of the constraint matrix of the specified problem +object and stores their row indices and numeric values to locations +\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is +the number of elements in $j$-th column, $m$ is the number of rows. + +The parameter \verb|ind| and/or \verb|val| can be specified as +\verb|NULL|, in which case corresponding information is not stored. + +\returns + +The routine \verb|glp_get_mat_col| returns the length \verb|len|, i.e. +the number of (non-zero) elements in \verb|j|-th column. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Row and column searching routines} + +Sometimes it may be necessary to find rows and/or columns by their +names (assigned with the routines \verb|glp_set_row_name| and +\verb|glp_set_col_name|). Though a particular row/column can be found +by its name using simple enumeration of all rows/columns, in case of +large instances such a {\it linear} search may take too long time. + +To significantly reduce the search time the application program may +create the row/column name index, which is an auxiliary data structure +implementing a {\it binary} search. Even in worst cases the search +takes logarithmic time, i.e. the time needed to find a particular row +(or column) by its name is $O(\log_2m)$ (or $O(\log_2n)$), where $m$ +and $n$ are, resp., the number of rows and columns in the problem +object. + +It is important to note that: + +\Item{1.}On creating the problem object with the routine +\verb|glp_create_prob| the name index is {\it not} created. + +\Item{2.}The name index can be created (destroyed) at any time with the +routine \verb|glp_create_index| (\verb|glp_delete_index|). Having been +created the name index becomes part of the corresponding problem +object. + +\Item{3.}The time taken to create the name index is +$O[(m+n)\log_2(m+n)]$, so it is recommended to create the index only +once, for example, just after the problem object was created. + +\Item{4.}If the name index exists, it is automatically updated every +time the name of a row/column is assigned/changed. The update operation +takes logarithmic time. + +\Item{5.}If the name index does not exist, the application should not +call the routines \verb|glp_find_row| and \verb|glp_find_col|. +Otherwise, an error message will be issued and abnormal program +termination will occur. + +\Item{6.}On destroying the problem object with the routine +\verb|glp_delete_prob|, the name index, if exists, is automatically +destroyed. + +\subsection{glp\_create\_index --- create the name index} + +\synopsis + +\begin{verbatim} + void glp_create_index(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_create_index| creates the name index for the +specified problem object. The name index is an auxiliary data +structure, which is intended to quickly (i.e. for logarithmic time) +find rows and columns by their names. + +This routine can be called at any time. If the name index already +exists, the routine does nothing. + +\newpage + +\subsection{glp\_find\_row --- find row by its name} + +\synopsis + +\begin{verbatim} + int glp_find_row(glp_prob *P, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_row| returns the ordinal number of a row, +which is assigned the specified symbolic \verb|name|. If no such row +exists, the routine returns 0. + +\subsection{glp\_find\_col --- find column by its name} + +\synopsis + +\begin{verbatim} + int glp_find_col(glp_prob *P, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_col| returns the ordinal number of a column, +which is assigned the specified symbolic \verb|name|. If no such column +exists, the routine returns 0. + +\subsection{glp\_delete\_index --- delete the name index} + +\synopsis + +\begin{verbatim} + void glp_delete_index(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_delete_index| deletes the name index previously +created by the routine\linebreak \verb|glp_create_index| and frees the +memory allocated to this auxiliary data structure. + +This routine can be called at any time. If the name index does not +exist, the routine does nothing. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem scaling routines} + +\subsection{Background} + +In GLPK the {\it scaling} means a linear transformation applied to the +constraint matrix to improve its numerical properties.\footnote{In many +cases a proper scaling allows making the constraint matrix to be better +conditioned, i.e. decreasing its condition number, that makes +computations numerically more stable.} + +The main equality is the following: +$$\widetilde{A}=RAS,\eqno(2.1)$$ +where $A=(a_{ij})$ is the original constraint matrix, $R=(r_{ii})>0$ is +a diagonal matrix used to scale rows (constraints), $S=(s_{jj})>0$ is a +diagonal matrix used to scale columns (variables), $\widetilde{A}$ is +the scaled constraint matrix. + +From (2.1) it follows that in the {\it scaled} problem instance each +original constraint coefficient $a_{ij}$ is replaced by corresponding +scaled constraint coefficient: +$$\widetilde{a}_{ij}=r_{ii}a_{ij}s_{jj}.\eqno(2.2)$$ + +Note that the scaling is performed internally and therefore +transparently to the user. This means that on API level the user always +deal with unscaled data. + +Scale factors $r_{ii}$ and $s_{jj}$ can be set or changed at any time +either directly by the application program in a problem specific way +(with the routines \verb|glp_set_rii| and \verb|glp_set_sjj|), or by +some API routines intended for automatic scaling. + +\subsection{glp\_set\_rii --- set (change) row scale factor} + +\synopsis + +\begin{verbatim} + void glp_set_rii(glp_prob *P, int i, double rii); +\end{verbatim} + +\description + +The routine \verb|glp_set_rii| sets (changes) the scale factor $r_{ii}$ +for $i$-th row of the specified problem object. + +\subsection{glp\_set\_sjj --- set (change) column scale factor} + +\synopsis + +\begin{verbatim} + void glp_set_sjj(glp_prob *P, int j, double sjj); +\end{verbatim} + +\description + +The routine \verb|glp_set_sjj| sets (changes) the scale factor $s_{jj}$ +for $j$-th column of the specified problem object. + +\newpage + +\subsection{glp\_get\_rii --- retrieve row scale factor} + +\synopsis + +\begin{verbatim} + double glp_get_rii(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_rii| returns current scale factor $r_{ii}$ +for $i$-th row of the specified problem object. + +\vspace*{-6pt} + +\subsection{glp\_get\_sjj --- retrieve column scale factor} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + double glp_get_sjj(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_sjj| returns current scale factor $s_{jj}$ +for $j$-th column of the specified problem object. + +\vspace*{-6pt} + +\subsection{glp\_scale\_prob --- scale problem data} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + void glp_scale_prob(glp_prob *P, int flags); +\end{verbatim} + +\description + +The routine \verb|glp_scale_prob| performs automatic scaling of problem +data for the specified problem object. + +The parameter \verb|flags| specifies scaling options used by the +routine. The options can be combined with the bitwise OR operator and +may be the following: + +\verb|GLP_SF_GM | --- perform geometric mean scaling; + +\verb|GLP_SF_EQ | --- perform equilibration scaling; + +\verb|GLP_SF_2N | --- round scale factors to nearest power of two; + +\verb|GLP_SF_SKIP| --- skip scaling, if the problem is well scaled. + +The parameter \verb|flags| may be also specified as \verb|GLP_SF_AUTO|, +in which case the routine chooses the scaling options automatically. + +\vspace*{-6pt} + +\subsection{glp\_unscale\_prob --- unscale problem data} + +\vspace*{-4pt} + +\synopsis + +\begin{verbatim} + void glp_unscale_prob(glp_prob *P); +\end{verbatim} + +The routine \verb|glp_unscale_prob| performs unscaling of problem data +for the specified problem object. + +``Unscaling'' means replacing the current scaling matrices $R$ and $S$ +by unity matrices that cancels the scaling effect. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{LP basis constructing routines} + +\subsection{Background} + +To start the search the simplex method needs a valid initial basis. +In GLPK the basis is completely defined by a set of {\it statuses} +assigned to {\it all} (auxiliary and structural) variables, where the +status may be one of the following: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable having active lower bound; + +\verb|GLP_NU| --- non-basic variable having active upper bound; + +\verb|GLP_NF| --- non-basic free variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +The basis is {\it valid}, if the basis matrix, which is a matrix built +of columns of the augmented constraint matrix $(I\:|-A)$ corresponding +to basic variables, is non-singular. This, in particular, means that +the number of basic variables must be the same as the number of rows in +the problem object. (For more details see Section \ref{lpbasis}, page +\pageref{lpbasis}.) + +Any initial basis may be constructed (or restored) with the API +routines \verb|glp_set_row_stat| and \verb|glp_set_col_stat| by +assigning appropriate statuses to auxiliary and structural variables. +Another way to construct an initial basis is to use API routines like +\verb|glp_adv_basis|, which implement so called +{\it crashing}.\footnote{This term is from early linear programming +systems and means a heuristic to construct a valid initial basis.} Note +that on normal exit the simplex solver remains the basis valid, so in +case of re-optimization there is no need to construct an initial basis +from scratch. + +\subsection{glp\_set\_row\_stat --- set (change) row status} + +\synopsis + +\begin{verbatim} + void glp_set_row_stat(glp_prob *P, int i, int stat); +\end{verbatim} + +\description + +The routine \verb|glp_set_row_stat| sets (changes) the current status +of \verb|i|-th row (auxiliary variable) as specified by the parameter +\verb|stat|: + +\verb|GLP_BS| --- make the row basic (make the constraint inactive); + +\verb|GLP_NL| --- make the row non-basic (make the constraint active); + +\verb|GLP_NU| --- make the row non-basic and set it to the upper bound; +if the row is not double-bounded, this status is equivalent to +\verb|GLP_NL| (only in case of this routine); + +\verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this +routine); + +\verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this +routine). + +\newpage + +\subsection{glp\_set\_col\_stat --- set (change) column status} + +\synopsis + +\begin{verbatim} + void glp_set_col_stat(glp_prob *P, int j, int stat); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_stat sets| (changes) the current status +of \verb|j|-th column (structural variable) as specified by the +parameter \verb|stat|: + +\verb|GLP_BS| --- make the column basic; + +\verb|GLP_NL| --- make the column non-basic; + +\verb|GLP_NU| --- make the column non-basic and set it to the upper +bound; if the column is not double-bounded, this status is equivalent +to \verb|GLP_NL| (only in case of this routine); + +\verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this +routine); + +\verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this +routine). + +\subsection{glp\_std\_basis --- construct standard initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_std_basis(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_std_basis| constructs the ``standard'' (trivial) +initial LP basis for the specified problem object. + +In the ``standard'' LP basis all auxiliary variables (rows) are basic, +and all structural variables (columns) are non-basic (so the +corresponding basis matrix is unity). + +\subsection{glp\_adv\_basis --- construct advanced initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_adv_basis(glp_prob *P, int flags); +\end{verbatim} + +\description + +The routine \verb|glp_adv_basis| constructs an advanced initial LP +basis for the specified problem object. + +The parameter \verb|flags| is reserved for use in the future and must +be specified as zero. + +In order to construct the advanced initial LP basis the routine does +the following: + +1) includes in the basis all non-fixed auxiliary variables; + +2) includes in the basis as many non-fixed structural variables as +possible keeping the triangular form of the basis matrix; + +3) includes in the basis appropriate (fixed) auxiliary variables to +complete the basis. + +As a result the initial LP basis has as few fixed variables as possible +and the corresponding basis matrix is triangular. + +\subsection{glp\_cpx\_basis --- construct Bixby's initial LP basis} + +\synopsis + +\begin{verbatim} + void glp_cpx_basis(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_cpx_basis| constructs an initial basis for the +specified problem object with the algorithm proposed by +R.~Bixby.\footnote{Robert E. Bixby, ``Implementing the Simplex Method: +The Initial Basis.'' ORSA Journal on Computing, Vol. 4, No. 3, 1992, +pp. 267-84.} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Simplex method routines} + +The {\it simplex method} is a well known efficient numerical procedure +to solve LP problems. + +On each iteration the simplex method transforms the original system of +equaility constraints (1.2) resolving them through different sets of +variables to an equivalent system called {\it the simplex table} (or +sometimes {\it the simplex tableau}), which has the following form: +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} +z&=&d_1(x_N)_1&+&d_2(x_N)_2&+ \dots +&d_n(x_N)_n \\ +(x_B)_1&=&\xi_{11}(x_N)_1& +& \xi_{12}(x_N)_2& + \dots +& + \xi_{1n}(x_N)_n \\ +(x_B)_2&=& \xi_{21}(x_N)_1& +& \xi_{22}(x_N)_2& + \dots +& + \xi_{2n}(x_N)_n \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +(x_B)_m&=&\xi_{m1}(x_N)_1& +& \xi_{m2}(x_N)_2& + \dots +& + \xi_{mn}(x_N)_n \\ +\end{array} \eqno (2.3) +$$ +where: $(x_B)_1, (x_B)_2, \dots, (x_B)_m$ are basic variables; +$(x_N)_1, (x_N)_2, \dots, (x_N)_n$ are non-basic variables; +$d_1, d_2, \dots, d_n$ are reduced costs; +$\xi_{11}, \xi_{12}, \dots, \xi_{mn}$ are coefficients of the +simplex table. (May note that the original LP problem (1.1)---(1.3) +also has the form of a simplex table, where all equalities are resolved +through auxiliary variables.) + +From the linear programming theory it is known that if an optimal +solution of the LP problem (1.1)---(1.3) exists, it can always be +written in the form (2.3), where non-basic variables are set on their +bounds while values of the objective function and basic variables are +determined by the corresponding equalities of the simplex table. + +A set of values of all basic and non-basic variables determined by the +simplex table is called {\it basic solution}. If all basic variables +are within their bounds, the basic solution is called {\it (primal) +feasible}, otherwise it is called {\it (primal) infeasible}. A feasible +basic solution, which provides a smallest (in case of minimization) or +a largest (in case of maximization) value of the objective function is +called {\it optimal}. Therefore, for solving LP problem the simplex +method tries to find its optimal basic solution. + +Primal feasibility of some basic solution may be stated by simple +checking if all basic variables are within their bounds. Basic solution +is optimal if additionally the following optimality conditions are +satisfied for all non-basic variables: +\begin{center} +\begin{tabular}{lcc} +Status of $(x_N)_j$ & Minimization & Maximization \\ +\hline +$(x_N)_j$ is free & $d_j = 0$ & $d_j = 0$ \\ +$(x_N)_j$ is on its lower bound & $d_j \geq 0$ & $d_j \leq 0$ \\ +$(x_N)_j$ is on its upper bound & $d_j \leq 0$ & $d_j \geq 0$ \\ +\end{tabular} +\end{center} +In other words, basic solution is optimal if there is no non-basic +variable, which changing in the feasible direction (i.e. increasing if +it is free or on its lower bound, or decreasing if it is free or on its +upper bound) can improve (i.e. decrease in case of minimization or +increase in case of maximization) the objective function. + +If all non-basic variables satisfy to the optimality conditions shown +above (independently on whether basic variables are within their bounds +or not), the basic solution is called {\it dual feasible}, otherwise it +is called {\it dual infeasible}. + +It may happen that some LP problem has no primal feasible solution due +to incorrect\linebreak formulation --- this means that its constraints +conflict with each other. It also may happen that some LP problem has +unbounded solution again due to incorrect formulation --- this means +that some non-basic variable can improve the objective function, i.e. +the optimality conditions are violated, and at the same time this +variable can infinitely change in the feasible direction meeting +no resistance from basic variables. (May note that in the latter case +the LP problem has no dual feasible solution.) + +\subsection{glp\_simplex --- solve LP problem with the primal or dual +simplex method} + +\synopsis + +\begin{verbatim} + int glp_simplex(glp_prob *P, const glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_simplex| is a driver to the LP solver based on +the simplex method. This routine retrieves problem data from the +specified problem object, calls the solver to solve the problem +instance, and stores results of computations back into the problem +object. + +The simplex solver has a set of control parameters. Values of the +control parameters can be passed in the structure \verb|glp_smcp|, +which the parameter \verb|parm| points to. For detailed description of +this structure see paragraph ``Control parameters'' below. +Before specifying some control parameters the application program +should initialize the structure \verb|glp_smcp| by default values of +all control parameters using the routine \verb|glp_init_smcp| (see the +next subsection). This is needed for backward compatibility, because in +the future there may appear new members in the structure +\verb|glp_smcp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which +case the solver uses default settings. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBADB| & Unable to start the search, because the initial +basis specified in the problem object is invalid---the number of basic +(auxiliary and structural) variables is not the same as the number of +rows in the problem object.\\ + +\verb|GLP_ESING| & Unable to start the search, because the basis matrix +corresponding to the initial basis is singular within the working +precision.\\ + +\verb|GLP_ECOND| & Unable to start the search, because the basis matrix +corresponding to the initial basis is ill-conditioned, i.e. its +condition number is too large.\\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded (auxiliary or structural) variables have incorrect +bounds.\\ + +\verb|GLP_EFAIL| & The search was prematurely terminated due to the +solver failure.\\ + +\verb|GLP_EOBJLL| & The search was prematurely terminated, because the +objective function being maximized has reached its lower limit and +continues decreasing (the dual simplex only).\\ + +\verb|GLP_EOBJUL| & The search was prematurely terminated, because the +objective function being minimized has reached its upper limit and +continues increasing (the dual simplex only).\\ + +\verb|GLP_EITLIM| & The search was prematurely terminated, because the +simplex iteration limit has been exceeded.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ +\end{retlist} + +\begin{retlist} +\verb|GLP_ENOPFS| & The LP problem instance has no primal feasible +solution (only if the LP presolver is used).\\ + +\verb|GLP_ENODFS| & The LP problem instance has no dual feasible +solution (only if the LP presolver is used).\\ +\end{retlist} + +\para{Built-in LP presolver} + +The simplex solver has {\it built-in LP presolver}. It is a subprogram +that transforms the original LP problem specified in the problem object +to an equivalent LP problem, which may be easier for solving with the +simplex method than the original one. This is attained mainly due to +reducing the problem size and improving its numeric properties (for +example, by removing some inactive constraints or by fixing some +non-basic variables). Once the transformed LP problem has been solved, +the presolver transforms its basic solution back to the corresponding +basic solution of the original problem. + +Presolving is an optional feature of the routine \verb|glp_simplex|, +and by default it is disabled. In order to enable the LP presolver the +control parameter \verb|presolve| should be set to \verb|GLP_ON| (see +paragraph ``Control parameters'' below). Presolving may be used when +the problem instance is solved for the first time. However, on +performing re-optimization the presolver should be disabled. + +The presolving procedure is transparent to the API user in the sense +that all necessary processing is performed internally, and a basic +solution of the original problem recovered by the presolver is the same +as if it were computed directly, i.e. without presolving. + +Note that the presolver is able to recover only optimal solutions. If +a computed solution is infeasible or non-optimal, the corresponding +solution of the original problem cannot be recovered and therefore +remains undefined. If you need to know a basic solution even if it is +infeasible or non-optimal, the presolver should be disabled. + +\para{Terminal output} + +Solving large problem instances may take a long time, so the solver +reports some information about the current basic solution, which is +sent to the terminal. This information has the following format: + +\begin{verbatim} + nnn: obj = xxx infeas = yyy (num) cnt +\end{verbatim} + +\noindent +where: `\verb|nnn|' is the iteration number, `\verb|xxx|' is the +current value of the objective function (it is unscaled and has correct +sign); `\verb|yyy|' is the current sum of primal or dual +infeasibilities (it is scaled and therefore may be used only for visual +estimating), `\verb|num|' is the current number of primal or dual +infeasibilities (phase I) or non-optimalities (phase II), `\verb|cnt|' +is the number of basis factorizations since the last terminal output. + +The symbol preceding the iteration number indicates which phase of the +simplex method is in effect: + +{\it Blank} means that the solver is searching for primal feasible +solution using the primal simplex or for dual feasible solution using +the dual simplex; + +{\it Asterisk} (\verb|*|) means that the solver is searching for +optimal solution using the primal simplex; + +{\it Hash} (\verb|#|) means that the solver is searching for optimal +solution using the dual simplex. + +\newpage + +\para{Control parameters} + +This paragraph describes all control parameters currently used in the +simplex solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_smcp|. + +\bigskip + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF| --- no output; + +\verb|GLP_MSG_ERR| --- error and warning messages only; + +\verb|GLP_MSG_ON | --- normal output; + +\verb|GLP_MSG_ALL| --- full output (including informational messages). + +\bigskip + +{\tt int meth} (default: {\tt GLP\_PRIMAL}) + +Simplex method option: + +\verb|GLP_PRIMAL| --- use two-phase primal simplex; + +\verb|GLP_DUAL | --- use two-phase dual simplex; + +\verb|GLP_DUALP | --- use two-phase dual simplex, and if it fails, +switch to the primal simplex. + +\bigskip + +{\tt int pricing} (default: {\tt GLP\_PT\_PSE}) + +Pricing technique: + +\verb|GLP_PT_STD| --- standard (``textbook''); + +\verb|GLP_PT_PSE| --- projected steepest edge. + +\bigskip + +{\tt int r\_test} (default: {\tt GLP\_RT\_HAR}) + +Ratio test technique: + +\verb|GLP_RT_STD| --- standard (``textbook''); + +\verb|GLP_RT_HAR| --- Harris' two-pass ratio test. + +\bigskip + +{\tt double tol\_bnd} (default: {\tt 1e-7}) + +Tolerance used to check if the basic solution is primal feasible. +(Do not change this parameter without detailed understanding its +purpose.) + +%\newpage +\bigskip + +{\tt double tol\_dj} (default: {\tt 1e-7}) + +Tolerance used to check if the basic solution is dual feasible. +(Do not change this parameter without detailed understanding its +purpose.) + +\bigskip + +{\tt double tol\_piv} (default: {\tt 1e-9}) + +Tolerance used to choose eligble pivotal elements of the simplex table. +(Do not change this parameter without detailed understanding its +purpose.) + +%\bigskip +\newpage + +{\tt double obj\_ll} (default: {\tt -DBL\_MAX}) + +Lower limit of the objective function. If the objective function +reaches this limit and continues decreasing, the solver terminates the +search. (Used in the dual simplex only.) + +\bigskip + +{\tt double obj\_ul} (default: {\tt +DBL\_MAX}) + +Upper limit of the objective function. If the objective function +reaches this limit and continues increasing, the solver terminates the +search. (Used in the dual simplex only.) + +\bigskip + +{\tt int it\_lim} (default: {\tt INT\_MAX}) + +Simplex iteration limit. + +\bigskip + +{\tt int tm\_lim} (default: {\tt INT\_MAX}) + +Searching time limit, in milliseconds. + +\bigskip + +{\tt int out\_frq} (default: {\tt 500}) + +Output frequency, in iterations. This parameter specifies how +frequently the solver sends information about the solution process to +the terminal. + +\bigskip + +{\tt int out\_dly} (default: {\tt 0}) + +Output delay, in milliseconds. This parameter specifies how long the +solver should delay sending information about the solution process to +the terminal. + +\bigskip + +{\tt int presolve} (default: {\tt GLP\_OFF}) + +LP presolver option: + +\verb|GLP_ON | --- enable using the LP presolver; + +\verb|GLP_OFF| --- disable using the LP presolver. + +\newpage + +\para{Example 1} + +The following example main program reads LP problem instance in fixed +MPS format from file \verb|25fv47.mps|,\footnote{This instance in fixed +MPS format can be found in the Netlib LP collection; see +{\tt ftp://ftp.netlib.org/lp/data/}.} constructs an advanced initial +basis, solves the instance with the primal simplex method (by default), +and writes the solution to file \verb|25fv47.txt|. + +\begin{footnotesize} +\begin{verbatim} +/* spxsamp1.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_adv_basis(P, 0); + glp_simplex(P, NULL); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from '25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read +One free row was removed +Constructing initial basis... +Size of triangular part is 812 +GLPK Simplex Optimizer, v4.57 +821 rows, 1571 columns, 10400 non-zeros + 0: obj = 7.131703290e+03 inf = 2.145e+05 (204) + 500: obj = 1.886711682e+04 inf = 8.273e+02 (36) 4 + 741: obj = 1.846047936e+04 inf = 5.575e-14 (0) 2 +* 1000: obj = 9.220063473e+03 inf = 2.423e-14 (432) 2 +* 1500: obj = 6.187659664e+03 inf = 1.019e-13 (368) 4 +* 2000: obj = 5.503442062e+03 inf = 0.000e+00 (33) 5 +* 2052: obj = 5.501845888e+03 inf = 0.000e+00 (0) +OPTIMAL LP SOLUTION FOUND +Writing basic solution to '25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\para{Example 2} + +The following example main program solves the same LP problem instance +as in Example 1 above, however, it uses the dual simplex method, which +starts from the standard initial basis. + +\begin{footnotesize} +\begin{verbatim} +/* spxsamp2.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + glp_smcp parm; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + glp_simplex(P, &parm); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from '25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read +One free row was removed +GLPK Simplex Optimizer, v4.57 +821 rows, 1571 columns, 10400 non-zeros + 0: inf = 1.223e+02 (41) + 258: inf = 3.091e-16 (0) 2 +# 500: obj = -5.071287080e+03 inf = 2.947e-15 (292) 2 +# 1000: obj = -1.352843873e+03 inf = 8.452e-15 (302) 5 +# 1500: obj = 7.985859737e+02 inf = 1.127e-14 (263) 5 +# 2000: obj = 3.059023029e+03 inf = 6.290e-11 (197) 4 +# 2500: obj = 5.354770966e+03 inf = 7.172e-13 (130) 5 +# 2673: obj = 5.501845888e+03 inf = 3.802e-16 (0) 2 +OPTIMAL LP SOLUTION FOUND +Writing basic solution to '25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_exact --- solve LP problem in exact arithmetic} + +\synopsis + +\begin{verbatim} + int glp_exact(glp_prob *P, const glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_exact| is a tentative implementation of the +primal two-phase simplex method based on exact (rational) arithmetic. +It is similar to the routine \verb|glp_simplex|, however, for all +internal computations it uses arithmetic of rational numbers, which is +exact in mathematical sense, i.e. free of round-off errors unlike +floating-point arithmetic. + +Note that the routine \verb|glp_exact| uses only three control +parameters passed in the structure \verb|glp_smcp|, namely, +\verb|msg_lev|, \verb|it_lim|, and \verb|tm_lim|. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBADB| & Unable to start the search, because the initial basis +specified in the problem object is invalid---the number of basic +(auxiliary and structural) variables is not the same as the number of +rows in the problem object.\\ + +\verb|GLP_ESING| & Unable to start the search, because the basis matrix +corresponding to the initial basis is exactly singular.\\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded (auxiliary or structural) variables have incorrect +bounds.\\ + +\verb|GLP_EFAIL| & The problem instance has no rows/columns.\\ + +\verb|GLP_EITLIM| & The search was prematurely terminated, because the +simplex iteration limit has been exceeded.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ +\end{retlist} + +\para{Note} + +Computations in exact arithmetic are very time-consuming, so solving +LP problem with the routine \verb|glp_exact| from the very beginning is +not a good idea. It is much better at first to find an optimal basis +with the routine \verb|glp_simplex| and only then to call +\verb|glp_exact|, in which case only a few simplex iterations need to +be performed in exact arithmetic. + +\newpage + +\subsection{glp\_init\_smcp --- initialize simplex solver control +parameters} + +\synopsis + +\begin{verbatim} + int glp_init_smcp(glp_smcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_smcp| initializes control parameters, which +are used by the simplex solver, with default values. + +Default values of the control parameters are stored in +a \verb|glp_smcp| structure, which the parameter \verb|parm| points to. + +\subsection{glp\_get\_status --- determine generic status of basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_status| reports the generic status of the +current basic solution for the specified problem object as follows: + +\verb|GLP_OPT | --- solution is optimal; + +\verb|GLP_FEAS | --- solution is feasible; + +\verb|GLP_INFEAS| --- solution is infeasible; + +\verb|GLP_NOFEAS| --- problem has no feasible solution; + +\verb|GLP_UNBND | --- problem has unbounded solution; + +\verb|GLP_UNDEF | --- solution is undefined. + +More detailed information about the status of basic solution can be +retrieved with the routines \verb|glp_get_prim_stat| and +\verb|glp_get_dual_stat|. + +\subsection{glp\_get\_prim\_stat --- retrieve status of primal basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_prim_stat(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_prim_stat| reports the status of the primal +basic solution for the specified problem object as follows: + +\verb|GLP_UNDEF | --- primal solution is undefined; + +\verb|GLP_FEAS | --- primal solution is feasible; + +\verb|GLP_INFEAS| --- primal solution is infeasible; + +\verb|GLP_NOFEAS| --- no primal feasible solution exists. + +\subsection{glp\_get\_dual\_stat --- retrieve status of dual basic +solution} + +\synopsis + +\begin{verbatim} + int glp_get_dual_stat(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_dual_stat| reports the status of the dual +basic solution for the specified problem object as follows: + +\verb|GLP_UNDEF | --- dual solution is undefined; + +\verb|GLP_FEAS | --- dual solution is feasible; + +\verb|GLP_INFEAS| --- dual solution is infeasible; + +\verb|GLP_NOFEAS| --- no dual feasible solution exists. + +\subsection{glp\_get\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_get_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_obj_val| returns current value of the +objective function. + +\subsection{glp\_get\_row\_stat --- retrieve row status} + +\synopsis + +\begin{verbatim} + int glp_get_row_stat(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_stat| returns current status assigned to +the auxiliary variable associated with \verb|i|-th row as follows: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable on its lower bound; + +\verb|GLP_NU| --- non-basic variable on its upper bound; + +\verb|GLP_NF| --- non-basic free (unbounded) variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +%\newpage + +\subsection{glp\_get\_row\_prim --- retrieve row primal value} + +\synopsis + +\begin{verbatim} + double glp_get_row_prim(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_prim| returns primal value of the +auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_get\_row\_dual --- retrieve row dual value} + +\synopsis + +\begin{verbatim} + double glp_get_row_dual(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_dual| returns dual value (i.e. reduced +cost) of the auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_get\_col\_stat --- retrieve column status} + +\synopsis + +\begin{verbatim} + int glp_get_col_stat(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_stat| returns current status assigned to +the structural variable associated with \verb|j|-th column as follows: + +\verb|GLP_BS| --- basic variable; + +\verb|GLP_NL| --- non-basic variable on its lower bound; + +\verb|GLP_NU| --- non-basic variable on its upper bound; + +\verb|GLP_NF| --- non-basic free (unbounded) variable; + +\verb|GLP_NS| --- non-basic fixed variable. + +\subsection{glp\_get\_col\_prim --- retrieve column primal value} + +\synopsis + +\begin{verbatim} + double glp_get_col_prim(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_prim| returns primal value of the +structural variable associated with \verb|j|-th column. + +%\newpage + +\subsection{glp\_get\_col\_dual --- retrieve column dual value} + +\synopsis + +\begin{verbatim} + double glp_get_col_dual(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_dual| returns dual value (i.e. reduced +cost) of the structural variable associated with \verb|j|-th column. + +\newpage + +\subsection{glp\_get\_unbnd\_ray --- determine variable causing +unboundedness} + +\synopsis + +\begin{verbatim} + int glp_get_unbnd_ray(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_unbnd_ray| returns the number $k$ of +a variable, which causes primal or dual unboundedness. +If $1\leq k\leq m$, it is $k$-th auxiliary variable, and if +$m+1\leq k\leq m+n$, it is $(k-m)$-th structural variable, where $m$ is +the number of rows, $n$ is the number of columns in the problem object. +If such variable is not defined, the routine returns 0. + +\para{Note} + +If it is not exactly known which version of the simplex solver +detected unboundedness, i.e. whether the unboundedness is primal or +dual, it is sufficient to check the status of the variable +with the routine \verb|glp_get_row_stat| or \verb|glp_get_col_stat|. +If the variable is non-basic, the unboundedness is primal, otherwise, +if the variable is basic, the unboundedness is dual (the latter case +means that the problem has no primal feasible dolution). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Interior-point method routines} + +{\it Interior-point methods} (also known as {\it barrier methods}) are +more modern and powerful numerical methods for large-scale linear +programming. Such methods are especially efficient for very sparse LP +problems and allow solving such problems much faster than the simplex +method. + +In brief, the GLPK interior-point solver works as follows. + +At first, the solver transforms the original LP to a {\it working} LP +in the standard format: + +\medskip + +\noindent +\hspace{.5in} minimize +$$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (2.4)$$ +\hspace{.5in} subject to linear constraints +$$ +\begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}l} +a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n}&=&b_1 \\ +a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n}&=&b_2 \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ +a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n}&=&b_m \\ +\end{array} \eqno (2.5) +$$ +\hspace{.5in} and non-negative variables +$$x_1\geq 0,\ \ x_2\geq 0,\ \ \dots,\ \ x_n\geq 0 \eqno(2.6)$$ +where: $z$ is the objective function; $x_1$, \dots, $x_n$ are variables; +$c_1$, \dots, $c_n$ are objective coefficients; $c_0$ is a constant term +of the objective function; $a_{11}$, \dots, $a_{mn}$ are constraint +coefficients; $b_1$, \dots, $b_m$ are right-hand sides. + +Using vector and matrix notations the working LP (2.4)---(2.6) can be +written as follows: +$$z=c^Tx+c_0\ \rightarrow\ \min,\eqno(2.7)$$ +$$Ax=b,\eqno(2.8)$$ +$$x\geq 0,\eqno(2.9)$$ +where: $x=(x_j)$ is $n$-vector of variables, $c=(c_j)$ is $n$-vector of +objective coefficients, $A=(a_{ij})$ is $m\times n$-matrix of +constraint coefficients, and $b=(b_i)$ is $m$-vector of right-hand +sides. + +Karush--Kuhn--Tucker optimality conditions for LP (2.7)---(2.9) are the +following: +$$Ax=b,\eqno(2.10)$$ +$$A^T\pi+\lambda=c,\eqno(2.11)$$ +$$\lambda^Tx=0,\eqno(2.12)$$ +$$x\geq 0,\ \ \lambda\geq 0,\eqno(2.13)$$ +where: +$\pi$ is $m$-vector of Lagrange multipliers (dual variables) for +equality constraints (2.8),\linebreak $\lambda$ is $n$-vector of +Lagrange multipliers (dual variables) for non-negativity constraints +(2.9),\linebreak (2.10) is the primal feasibility condition, (2.11) is +the dual feasibility condition, (2.12) is the primal-dual +complementarity condition, and (2.13) is the non-negativity conditions. + +The main idea of the primal-dual interior-point method is based on +finding a point in the primal-dual space (i.e. in the space of all +primal and dual variables $x$, $\pi$, and $\lambda$), which satisfies +to all optimality conditions (2.10)---(2.13). Obviously, $x$-component +of such point then provides an optimal solution to the working LP +(2.7)---(2.9). + +To find the optimal point $(x^*,\pi^*,\lambda^*)$ the interior-point +method attempts to solve the system of equations (2.10)---(2.12), which +is closed in the sense that the number of variables $x_j$, $\pi_i$, and +$\lambda_j$ and the number equations are the same and equal to $m+2n$. +Due to condition (2.12) this system of equations is non-linear, so it +can be solved with a version of {\it Newton's method} provided with +additional rules to keep the current point within the positive orthant +as required by the non-negativity conditions (2.13). + +Finally, once the optimal point $(x^*,\pi^*,\lambda^*)$ has been found, +the solver performs inverse transformations to recover corresponding +solution to the original LP passed to the solver from the application +program. + +\subsection{glp\_interior --- solve LP problem with the interior-point +method} + +\synopsis + +\begin{verbatim} + int glp_interior(glp_prob *P, const glp_iptcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_interior| is a driver to the LP solver based on +the primal-dual interior-point method. This routine retrieves problem +data from the specified problem object, calls the solver to solve the +problem instance, and stores results of computations back into the +problem object. + +The interior-point solver has a set of control parameters. Values of +the control parameters can be passed in the structure \verb|glp_iptcp|, +which the parameter \verb|parm| points to. For detailed description of +this structure see paragraph ``Control parameters'' below. Before +specifying some control parameters the application program should +initialize the structure \verb|glp_iptcp| by default values of all +control parameters using the routine \verb|glp_init_iptcp| (see the +next subsection). This is needed for backward compatibility, because in +the future there may appear new members in the structure +\verb|glp_iptcp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which +case the solver uses default settings. + +\returns + +\begin{retlist} +0 & The LP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EFAIL| & The problem has no rows/columns.\\ + +\verb|GLP_ENOCVG| & Very slow convergence or divergence.\\ + +\verb|GLP_EITLIM| & Iteration limit exceeded.\\ + +\verb|GLP_EINSTAB| & Numerical instability on solving Newtonian +system.\\ +\end{retlist} + +\newpage + +\para{Comments} + +The routine \verb|glp_interior| implements an easy version of +the primal-dual interior-point method based on Mehrotra's +technique.\footnote{S. Mehrotra. On the implementation of a primal-dual +interior point method. SIAM J. on Optim., 2(4), pp. 575-601, 1992.} + +Note that currently the GLPK interior-point solver does not include +many important features, in particular: + +%\vspace*{-8pt} + +%\begin{itemize} +\Item{---}it is not able to process dense columns. Thus, if the +constraint matrix of the LP problem has dense columns, the solving +process may be inefficient; + +\Item{---}it has no features against numerical instability. For some LP +problems premature termination may happen if the matrix $ADA^T$ becomes +singular or ill-conditioned; + +\Item{---}it is not able to identify the optimal basis, which +corresponds to the interior-point solution found. +%\end{itemize} + +%\vspace*{-8pt} + +\para{Terminal output} + +Solving large LP problems may take a long time, so the solver reports +some information about every interior-point iteration,\footnote{Unlike +the simplex method the interior point method usually needs 30---50 +iterations (independently on the problem size) in order to find an +optimal solution.} which is sent to the terminal. This information has +the following format: + +\begin{verbatim} +nnn: obj = fff; rpi = ppp; rdi = ddd; gap = ggg +\end{verbatim} + +\noindent where: \verb|nnn| is iteration number, \verb|fff| is the +current value of the objective function (in the case of maximization it +has wrong sign), \verb|ppp| is the current relative primal +infeasibility (cf. (2.10)): +$$\frac{\|Ax^{(k)}-b\|}{1+\|b\|},\eqno(2.14)$$ +\verb|ddd| is the current relative dual infeasibility (cf. (2.11)): +$$\frac{\|A^T\pi^{(k)}+\lambda^{(k)}-c\|}{1+\|c\|},\eqno(2.15)$$ +\verb|ggg| is the current primal-dual gap (cf. (2.12)): +$$\frac{|c^Tx^{(k)}-b^T\pi^{(k)}|}{1+|c^Tx^{(k)}|},\eqno(2.16)$$ +and $[x^{(k)},\pi^{(k)},\lambda^{(k)}]$ is the current point on $k$-th +iteration, $k=0,1,2,\dots$\ . Note that all solution components are +internally scaled, so information sent to the terminal is suitable only +for visual inspection. + +\newpage + +\para{Control parameters} + +This paragraph describes all control parameters currently used in the +interior-point solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_iptcp|. + +\bigskip + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF|---no output; + +\verb|GLP_MSG_ERR|---error and warning messages only; + +\verb|GLP_MSG_ON |---normal output; + +\verb|GLP_MSG_ALL|---full output (including informational messages). + +\bigskip + +{\tt int ord\_alg} (default: {\tt GLP\_ORD\_AMD}) + +Ordering algorithm used prior to Cholesky factorization: + +\verb|GLP_ORD_NONE |---use natural (original) ordering; + +\verb|GLP_ORD_QMD |---quotient minimum degree (QMD); + +\verb|GLP_ORD_AMD |---approximate minimum degree (AMD); + +\verb|GLP_ORD_SYMAMD|---approximate minimum degree (SYMAMD). + +\bigskip + +\para{Example} + +The following main program reads LP problem instance in fixed MPS +format from file\linebreak \verb|25fv47.mps|,\footnote{This instance in +fixed MPS format can be found in the Netlib LP collection; see +{\tt ftp://ftp.netlib.org/lp/data/}.} solves it with the interior-point +solver, and writes the solution to file \verb|25fv47.txt|. + +\begin{footnotesize} +\begin{verbatim} +/* iptsamp.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_interior(P, NULL); + glp_print_ipt(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ +\end{verbatim} +\end{footnotesize} + +\newpage + +Below here is shown the terminal output from this example program. + +\begin{footnotesize} +\begin{verbatim} +Reading problem data from `25fv47.mps'... +Problem: 25FV47 +Objective: R0000 +822 rows, 1571 columns, 11127 non-zeros +6919 records were read +Original LP has 822 row(s), 1571 column(s), and 11127 non-zero(s) +Working LP has 821 row(s), 1876 column(s), and 10705 non-zero(s) +Matrix A has 10705 non-zeros +Matrix S = A*A' has 11895 non-zeros (upper triangle) +Minimal degree ordering... +Computing Cholesky factorization S = L'*L... +Matrix L has 35411 non-zeros +Guessing initial point... +Optimization begins... + 0: obj = 1.823377629e+05; rpi = 1.3e+01; rdi = 1.4e+01; gap = 9.3e-01 + 1: obj = 9.260045192e+04; rpi = 5.3e+00; rdi = 5.6e+00; gap = 6.8e+00 + 2: obj = 3.596999742e+04; rpi = 1.5e+00; rdi = 1.2e+00; gap = 1.8e+01 + 3: obj = 1.989627568e+04; rpi = 4.7e-01; rdi = 3.0e-01; gap = 1.9e+01 + 4: obj = 1.430215557e+04; rpi = 1.1e-01; rdi = 8.6e-02; gap = 1.4e+01 + 5: obj = 1.155716505e+04; rpi = 2.3e-02; rdi = 2.4e-02; gap = 6.8e+00 + 6: obj = 9.660273208e+03; rpi = 6.7e-03; rdi = 4.6e-03; gap = 3.9e+00 + 7: obj = 8.694348283e+03; rpi = 3.7e-03; rdi = 1.7e-03; gap = 2.0e+00 + 8: obj = 8.019543639e+03; rpi = 2.4e-03; rdi = 3.9e-04; gap = 1.0e+00 + 9: obj = 7.122676293e+03; rpi = 1.2e-03; rdi = 1.5e-04; gap = 6.6e-01 + 10: obj = 6.514534518e+03; rpi = 6.1e-04; rdi = 4.3e-05; gap = 4.1e-01 + 11: obj = 6.361572203e+03; rpi = 4.8e-04; rdi = 2.2e-05; gap = 3.0e-01 + 12: obj = 6.203355508e+03; rpi = 3.2e-04; rdi = 1.7e-05; gap = 2.6e-01 + 13: obj = 6.032943411e+03; rpi = 2.0e-04; rdi = 9.3e-06; gap = 2.1e-01 + 14: obj = 5.796553021e+03; rpi = 9.8e-05; rdi = 3.2e-06; gap = 1.0e-01 + 15: obj = 5.667032431e+03; rpi = 4.4e-05; rdi = 1.1e-06; gap = 5.6e-02 + 16: obj = 5.613911867e+03; rpi = 2.5e-05; rdi = 4.1e-07; gap = 3.5e-02 + 17: obj = 5.560572626e+03; rpi = 9.9e-06; rdi = 2.3e-07; gap = 2.1e-02 + 18: obj = 5.537276001e+03; rpi = 5.5e-06; rdi = 8.4e-08; gap = 1.1e-02 + 19: obj = 5.522746942e+03; rpi = 2.2e-06; rdi = 4.0e-08; gap = 6.7e-03 + 20: obj = 5.509956679e+03; rpi = 7.5e-07; rdi = 1.8e-08; gap = 2.9e-03 + 21: obj = 5.504571733e+03; rpi = 1.6e-07; rdi = 5.8e-09; gap = 1.1e-03 + 22: obj = 5.502576367e+03; rpi = 3.4e-08; rdi = 1.0e-09; gap = 2.5e-04 + 23: obj = 5.502057119e+03; rpi = 8.1e-09; rdi = 3.0e-10; gap = 7.7e-05 + 24: obj = 5.501885996e+03; rpi = 9.4e-10; rdi = 1.2e-10; gap = 2.4e-05 + 25: obj = 5.501852464e+03; rpi = 1.4e-10; rdi = 1.2e-11; gap = 3.0e-06 + 26: obj = 5.501846549e+03; rpi = 1.4e-11; rdi = 1.2e-12; gap = 3.0e-07 + 27: obj = 5.501845954e+03; rpi = 1.4e-12; rdi = 1.2e-13; gap = 3.0e-08 + 28: obj = 5.501845895e+03; rpi = 1.5e-13; rdi = 1.2e-14; gap = 3.0e-09 +OPTIMAL SOLUTION FOUND +Writing interior-point solution to `25fv47.txt'... +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_init\_iptcp --- initialize interior-point solver +control parameters} + +\synopsis + +\begin{verbatim} + int glp_init_iptcp(glp_iptcp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_iptcp| initializes control parameters, which +are used by the interior-point solver, with default values. + +Default values of the control parameters are stored in the structure +\verb|glp_iptcp|, which the parameter \verb|parm| points to. + +\subsection{glp\_ipt\_status --- determine solution status} + +\synopsis + +\begin{verbatim} + int glp_ipt_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_status| reports the status of a solution +found by the interior-point solver as follows: + +\verb|GLP_UNDEF | --- interior-point solution is undefined; + +\verb|GLP_OPT | --- interior-point solution is optimal; + +\verb|GLP_INFEAS| --- interior-point solution is infeasible; + +\verb|GLP_NOFEAS| --- no feasible primal-dual solution exists. + +\subsection{glp\_ipt\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_ipt_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_obj_val| returns value of the objective +function for interior-point solution. + +\subsection{glp\_ipt\_row\_prim --- retrieve row primal value} + +\synopsis + +\begin{verbatim} + double glp_ipt_row_prim(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_row_prim| returns primal value of the +auxiliary variable associated with \verb|i|-th row. + +\newpage + +\subsection{glp\_ipt\_row\_dual --- retrieve row dual value} + +\synopsis + +\begin{verbatim} + double glp_ipt_row_dual(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_row_dual| returns dual value (i.e. reduced +cost) of the auxiliary variable associated with \verb|i|-th row. + +\subsection{glp\_ipt\_col\_prim --- retrieve column primal value} + +\synopsis + +\begin{verbatim} + double glp_ipt_col_prim(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_col_prim| returns primal value of the +structural variable associated with \verb|j|-th column. + +\subsection{glp\_ipt\_col\_dual --- retrieve column dual value} + +\synopsis + +\begin{verbatim} + double glp_ipt_col_dual(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_ipt_col_dual| returns dual value (i.e. reduced +cost) of the structural variable associated with \verb|j|-th column. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Mixed integer programming routines} + +\subsection{glp\_set\_col\_kind --- set (change) column kind} + +\synopsis + +\begin{verbatim} + void glp_set_col_kind(glp_prob *P, int j, int kind); +\end{verbatim} + +\description + +The routine \verb|glp_set_col_kind| sets (changes) the kind of +\verb|j|-th column (structural variable) as specified by the parameter +\verb|kind|: + +\verb|GLP_CV| --- continuous variable; + +\verb|GLP_IV| --- integer variable; + +\verb|GLP_BV| --- binary variable. + +Setting a column to \verb|GLP_BV| has the same effect as if it were +set to \verb|GLP_IV|, its lower bound were set 0, and its upper bound +were set to 1. + +\subsection{glp\_get\_col\_kind --- retrieve column kind} + +\synopsis + +\begin{verbatim} + int glp_get_col_kind(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_kind| returns the kind of \verb|j|-th +column (structural variable) as follows: + +\verb|GLP_CV| --- continuous variable; + +\verb|GLP_IV| --- integer variable; + +\verb|GLP_BV| --- binary variable. + +\subsection{glp\_get\_num\_int --- retrieve number of integer columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_int(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_int| returns the number of columns +(structural variables), which are marked as integer. Note that this +number {\it does} include binary columns. + +\newpage + +\subsection{glp\_get\_num\_bin --- retrieve number of binary columns} + +\synopsis + +\begin{verbatim} + int glp_get_num_bin(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_get_num_bin| returns the number of columns +(structural variables), which are marked as integer and whose lower +bound is zero and upper bound is one. + +\subsection{glp\_intopt --- solve MIP problem with the branch-and-cut +method} + +\synopsis + +\begin{verbatim} + int glp_intopt(glp_prob *P, const glp_iocp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_intopt| is a driver to the MIP solver based on +the branch-and-cut method, which is a hybrid of branch-and-bound and +cutting plane methods. + +If the presolver is disabled (see paragraph ``Control parameters'' +below), on entry to the routine \verb|glp_intopt| the problem object, +which the parameter \verb|mip| points to, should contain optimal +solution to LP relaxation (it can be obtained, for example, with the +routine \verb|glp_simplex|). Otherwise, if the presolver is enabled, it +is not necessary. + +The MIP solver has a set of control parameters. Values of the control +parameters can be passed in the structure \verb|glp_iocp|, which the +parameter \verb|parm| points to. For detailed description of this +structure see paragraph ``Control parameters'' below. Before specifying +some control parameters the application program should initialize the +structure \verb|glp_iocp| by default values of all control parameters +using the routine \verb|glp_init_iocp| (see the next subsection). This +is needed for backward compatibility, because in the future there may +appear new members in the structure \verb|glp_iocp|. + +The parameter \verb|parm| can be specified as \verb|NULL|, in which case +the solver uses default settings. + +Note that the GLPK branch-and-cut solver is not perfect, so it is +unable to solve hard or very large scale MIP instances for a reasonable +time. + +\returns + +\begin{retlist} +0 & The MIP problem instance has been successfully solved. (This code +does {\it not} necessarily mean that the solver has found optimal +solution. It only means that the solution process was successful.) \\ + +\verb|GLP_EBOUND| & Unable to start the search, because some +double-bounded variables have incorrect bounds or some integer +variables have non-integer (fractional) bounds.\\ + +\verb|GLP_EROOT| & Unable to start the search, because optimal basis +for initial LP relaxation is not provided. (This code may appear only +if the presolver is disabled.)\\ + +\verb|GLP_ENOPFS| & Unable to start the search, because LP relaxation +of the MIP problem instance has no primal feasible solution. (This code +may appear only if the presolver is enabled.)\\ +\end{retlist} + +\newpage + +\begin{retlist} +\verb|GLP_ENODFS| & Unable to start the search, because LP relaxation +of the MIP problem instance has no dual feasible solution. In other +word, this code means that if the LP relaxation has at least one primal +feasible solution, its optimal solution is unbounded, so if the MIP +problem has at least one integer feasible solution, its (integer) +optimal solution is also unbounded. (This code may appear only if the +presolver is enabled.)\\ + +\verb|GLP_EFAIL| & The search was prematurely terminated due to the +solver failure.\\ + +\verb|GLP_EMIPGAP| & The search was prematurely terminated, because the +relative mip gap tolerance has been reached.\\ + +\verb|GLP_ETMLIM| & The search was prematurely terminated, because the +time limit has been exceeded.\\ + +\verb|GLP_ESTOP| & The search was prematurely terminated by application. +(This code may appear only if the advanced solver interface is used.)\\ +\end{retlist} + +\para{Built-in MIP presolver} + +The branch-and-cut solver has {\it built-in MIP presolver}. It is +a subprogram that transforms the original MIP problem specified in the +problem object to an equivalent MIP problem, which may be easier for +solving with the branch-and-cut method than the original one. For +example, the presolver can remove redundant constraints and variables, +whose optimal values are known, perform bound and coefficient reduction, +etc. Once the transformed MIP problem has been solved, the presolver +transforms its solution back to corresponding solution of the original +problem. + +Presolving is an optional feature of the routine \verb|glp_intopt|, and +by default it is disabled. In order to enable the MIP presolver, the +control parameter \verb|presolve| should be set to \verb|GLP_ON| (see +paragraph ``Control parameters'' below). + +\para{Advanced solver interface} + +The routine \verb|glp_intopt| allows the user to control the +branch-and-cut search by passing to the solver a user-defined callback +routine. For more details see Chapter ``Branch-and-Cut API Routines''. + +\para{Terminal output} + +Solving a MIP problem may take a long time, so the solver reports some +information about best known solutions, which is sent to the terminal. +This information has the following format: + +\begin{verbatim} ++nnn: mip = xxx yyy gap (ppp; qqq) +\end{verbatim} + +\noindent +where: `\verb|nnn|' is the simplex iteration number; `\verb|xxx|' is a +value of the objective function for the best known integer feasible +solution (if no integer feasible solution has been found yet, +`\verb|xxx|' is the text `\verb|not found yet|'); `\verb|rho|' is the +string `\verb|>=|' (in case of minimization) or `\verb|<=|' (in case of +maximization); `\verb|yyy|' is a global bound for exact integer optimum +(i.e. the exact integer optimum is always in the range from `\verb|xxx|' +to `\verb|yyy|'); `\verb|gap|' is the relative mip gap, in percents, +computed as $gap=|xxx-yyy|/(|xxx|+{\tt DBL\_EPSILON})\cdot 100\%$ (if +$gap$ is greater than $999.9\%$, it is not printed); `\verb|ppp|' is the +number of subproblems in the active list, `\verb|qqq|' is the number of +subproblems which have been already fathomed and therefore removed from +the branch-and-bound search tree. + +\newpage + +\subsubsection{Control parameters} + +This paragraph describes all control parameters currently used in the +MIP solver. Symbolic names of control parameters are names of +corresponding members in the structure \verb|glp_iocp|. + +\bigskip\vspace*{-2pt} + +{\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) + +Message level for terminal output: + +\verb|GLP_MSG_OFF| --- no output; + +\verb|GLP_MSG_ERR| --- error and warning messages only; + +\verb|GLP_MSG_ON | --- normal output; + +\verb|GLP_MSG_ALL| --- full output (including informational messages). + +\bigskip\vspace*{-2pt} + +{\tt int br\_tech} (default: {\tt GLP\_BR\_DTH}) + +Branching technique option: + +\verb|GLP_BR_FFV| --- first fractional variable; + +\verb|GLP_BR_LFV| --- last fractional variable; + +\verb|GLP_BR_MFV| --- most fractional variable; + +\verb|GLP_BR_DTH| --- heuristic by Driebeck and Tomlin; + +\verb|GLP_BR_PCH| --- hybrid pseudo-cost heuristic. + +\bigskip\vspace*{-2pt} + +{\tt int bt\_tech} (default: {\tt GLP\_BT\_BLB}) + +Backtracking technique option: + +\verb|GLP_BT_DFS| --- depth first search; + +\verb|GLP_BT_BFS| --- breadth first search; + +\verb|GLP_BT_BLB| --- best local bound; + +\verb|GLP_BT_BPH| --- best projection heuristic. + +\bigskip\vspace*{-2pt} + +{\tt int pp\_tech} (default: {\tt GLP\_PP\_ALL}) + +Preprocessing technique option: + +\verb|GLP_PP_NONE| --- disable preprocessing; + +\verb|GLP_PP_ROOT| --- perform preprocessing only on the root level; + +\verb|GLP_PP_ALL | --- perform preprocessing on all levels. + +\bigskip\vspace*{-2pt} + +{\tt int sr\_heur} (default: {\tt GLP\_ON}) + +Simple rounding heuristic option: + +\verb|GLP_ON | --- enable applying the simple rounding heuristic; + +\verb|GLP_OFF| --- disable applying the simple rounding heuristic. + +\newpage + +{\tt int fp\_heur} (default: {\tt GLP\_OFF}) + +Feasibility pump heuristic option: + +\verb|GLP_ON | --- enable applying the feasibility pump heuristic; + +\verb|GLP_OFF| --- disable applying the feasibility pump heuristic. + +\bigskip + +{\tt int ps\_heur} (default: {\tt GLP\_OFF}) + +Proximity search heuristic\footnote{The Fischetti--Monaci Proximity +Search (a.k.a. Proxy) heuristic. This algorithm is often capable of +rapidly improving a feasible solution of a MIP problem with binary +variables. It allows to quickly obtain suboptimal solutions in some +problems which take too long time to be solved to optimality.} option: + +\verb|GLP_ON | --- enable applying the proximity search heuristic; + +\verb|GLP_OFF| --- disable applying the proximity search pump heuristic. + +\bigskip + +{\tt int ps\_tm\_lim} (default: {\tt 60000}) + +Time limit, in milliseconds, for the proximity search heuristic (see +above). + +\bigskip + +{\tt int gmi\_cuts} (default: {\tt GLP\_OFF}) + +Gomory's mixed integer cut option: + +\verb|GLP_ON | --- enable generating Gomory's cuts; + +\verb|GLP_OFF| --- disable generating Gomory's cuts. + +\bigskip + +{\tt int mir\_cuts} (default: {\tt GLP\_OFF}) + +Mixed integer rounding (MIR) cut option: + +\verb|GLP_ON | --- enable generating MIR cuts; + +\verb|GLP_OFF| --- disable generating MIR cuts. + +\bigskip + +{\tt int cov\_cuts} (default: {\tt GLP\_OFF}) + +Mixed cover cut option: + +\verb|GLP_ON | --- enable generating mixed cover cuts; + +\verb|GLP_OFF| --- disable generating mixed cover cuts. + +\bigskip + +{\tt int clq\_cuts} (default: {\tt GLP\_OFF}) + +Clique cut option: + +\verb|GLP_ON | --- enable generating clique cuts; + +\verb|GLP_OFF| --- disable generating clique cuts. + +\newpage + +{\tt double tol\_int} (default: {\tt 1e-5}) + +Absolute tolerance used to check if optimal solution to the current LP +relaxation is integer feasible. (Do not change this parameter without +detailed understanding its purpose.) + +\bigskip + +{\tt double tol\_obj} (default: {\tt 1e-7}) + +Relative tolerance used to check if the objective value in optimal +solution to the current LP relaxation is not better than in the best +known integer feasible solution. (Do not change this parameter without +detailed understanding its purpose.) + +\bigskip + +{\tt double mip\_gap} (default: {\tt 0.0}) + +The relative mip gap tolerance. If the relative mip gap for currently +known best integer feasible solution falls below this tolerance, the +solver terminates the search. This allows obtainig suboptimal integer +feasible solutions if solving the problem to optimality takes too long +time. + +\bigskip + +{\tt int tm\_lim} (default: {\tt INT\_MAX}) + +Searching time limit, in milliseconds. + +\bigskip + +{\tt int out\_frq} (default: {\tt 5000}) + +Output frequency, in milliseconds. This parameter specifies how +frequently the solver sends information about the solution process to +the terminal. + +\bigskip + +{\tt int out\_dly} (default: {\tt 10000}) + +Output delay, in milliseconds. This parameter specifies how long the +solver should delay sending information about solution of the current +LP relaxation with the simplex method to the terminal. + +\bigskip + +{\tt void (*cb\_func)(glp\_tree *tree, void *info)} +(default: {\tt NULL}) + +Entry point to the user-defined callback routine. \verb|NULL| means +the advanced solver interface is not used. For more details see Chapter +``Branch-and-Cut API Routines''. + +\bigskip + +{\tt void *cb\_info} (default: {\tt NULL}) + +Transit pointer passed to the routine \verb|cb_func| (see above). + +\bigskip + +{\tt int cb\_size} (default: {\tt 0}) + +The number of extra (up to 256) bytes allocated for each node of the +branch-and-bound tree to store application-specific data. On creating +a node these bytes are initialized by binary zeros. + +\bigskip + +{\tt int presolve} (default: {\tt GLP\_OFF}) + +MIP presolver option: + +\verb|GLP_ON | --- enable using the MIP presolver; + +\verb|GLP_OFF| --- disable using the MIP presolver. + +\newpage + +{\tt int binarize} (default: {\tt GLP\_OFF}) + +Binarization option (used only if the presolver is enabled): + +\verb|GLP_ON | --- replace general integer variables by binary ones; + +\verb|GLP_OFF| --- do not use binarization. + +\subsection{glp\_init\_iocp --- initialize integer optimizer control +parameters} + +\synopsis + +\begin{verbatim} + void glp_init_iocp(glp_iocp *parm); +\end{verbatim} + +\description + +The routine \verb|glp_init_iocp| initializes control parameters, which +are used by the branch-and-cut solver, with default values. + +Default values of the control parameters are stored in +a \verb|glp_iocp| structure, which the parameter \verb|parm| points to. + +\subsection{glp\_mip\_status --- determine status of MIP solution} + +\synopsis + +\begin{verbatim} + int glp_mip_status(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_status| reports the status of a MIP solution +found by the MIP solver as follows: + +\verb|GLP_UNDEF | --- MIP solution is undefined; + +\verb|GLP_OPT | --- MIP solution is integer optimal; + +\verb|GLP_FEAS | --- MIP solution is integer feasible, however, its +optimality (or non-optimality) has not been proven, perhaps due to +premature termination of the search; + +\verb|GLP_NOFEAS| --- problem has no integer feasible solution (proven +by the solver). + +\subsection{glp\_mip\_obj\_val --- retrieve objective value} + +\synopsis + +\begin{verbatim} + double glp_mip_obj_val(glp_prob *P); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_obj_val| returns value of the objective +function for MIP solution. + +\newpage + +\subsection{glp\_mip\_row\_val --- retrieve row value} + +\synopsis + +\begin{verbatim} + double glp_mip_row_val(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_row_val| returns value of the auxiliary +variable associated with \verb|i|-th row for MIP solution. + +\subsection{glp\_mip\_col\_val --- retrieve column value} + +\synopsis + +\begin{verbatim} + double glp_mip_col_val(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_mip_col_val| returns value of the structural +variable associated with \verb|j|-th column for MIP solution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Additional routines} + +\subsection{glp\_check\_kkt --- check feasibility/optimality +conditions} + +\synopsis + +{\parskip=0pt +\tt void glp\_check\_kkt(glp\_prob *P, int sol, int cond, +double *ae\_max, int *ae\_ind, + +\hspace{105pt}double *re\_max, int *re\_ind);} + +\description + +The routine \verb|glp_check_kkt| allows to check +feasibility/optimality conditions for the current solution stored in +the specified problem object. (For basic and interior-point solutions +these conditions are known as {\it Karush--Kuhn--Tucker optimality +conditions}.) + +The parameter \verb|sol| specifies which solution should be checked: + +\verb|GLP_SOL| --- basic solution; + +\verb|GLP_IPT| --- interior-point solution; + +\verb|GLP_MIP| --- mixed integer solution. + +The parameter \verb|cond| specifies which condition should be checked: + +\verb|GLP_KKT_PE| --- check primal equality constraints (KKT.PE); + +\verb|GLP_KKT_PB| --- check primal bound constraints (KKT.PB); + +\verb|GLP_KKT_DE| --- check dual equality constraints (KKT.DE). This +conditions can be checked only for basic or interior-point solution; + +\verb|GLP_KKT_DB| --- check dual bound constraints (KKT.DB). This +conditions can be checked only for basic or interior-point solution. + +Detailed explanations of these conditions are given below in paragraph +``Background''. + +On exit the routine stores the following information to locations +specified by parameters \verb|ae_max|, \verb|ae_ind|, \verb|re_max|, +and \verb|re_ind| (if some parameter is a null pointer, corresponding +information is not stored): + +\verb|ae_max| --- largest absolute error; + +\verb|ae_ind| --- number of row (KKT.PE), column (KKT.DE), or variable +(KKT.PB, KKT.DB) with the largest absolute error; + +\verb|re_max| --- largest relative error; + +\verb|re_ind| --- number of row (KKT.PE), column (KKT.DE), or variable +(KKT.PB, KKT.DB) with the largest relative error. + +Row (auxiliary variable) numbers are in the range 1 to $m$, where $m$ +is the number of rows in the problem object. Column (structural +variable) numbers are in the range 1 to $n$, where $n$ is the number +of columns in the problem object. Variable numbers are in the range +1 to $m+n$, where variables with numbers 1 to $m$ correspond to rows, +and variables with numbers $m+1$ to $m+n$ correspond to columns. If +the error reported is exact zero, corresponding row, column or variable +number is set to zero. + +\newpage + +\para{Background} + +\def\arraystretch{1.5} + +The first condition checked by the routine is the following: +$$x_R - A x_S = 0, \eqno{\rm (KKT.PE)}$$ +where $x_R$ is the subvector of auxiliary variables (rows), $x_S$ is +the subvector of structural variables (columns), $A$ is the constraint +matrix. This condition expresses the requirement that all primal +variables should satisfy to the system of equality constraints of the +original LP problem. In case of exact arithmetic this condition would +be satisfied for any basic solution; however, in case of inexact +(floating-point) arithmetic, this condition shows how accurate the +primal solution is, that depends on accuracy of a representation of the +basis matrix used by the simplex method, or on accuracy provided by the +interior-point method. + +To check the condition (KKT.PE) the routine computes the vector of +residuals: +$$g = x_R - A x_S,$$ +and determines component of this vector that correspond to largest +absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq i\leq m}|g_i|,$$ +$${\tt re\_max}=\max_{1\leq i\leq m}\frac{|g_i|}{1+|(x_R)_i|}.$$ + +The second condition checked by the routine is the following: +$$l_k \leq x_k \leq u_k {\rm \ \ \ for\ all}\ k=1,\dots,m+n, +\eqno{\rm (KKT.PB)}$$ +where $x_k$ is auxiliary ($1\leq k\leq m$) or structural +($m+1\leq k\leq m+n$) variable, $l_k$ and $u_k$ are, respectively, +lower and upper bounds of the variable $x_k$ (including cases of +infinite bounds). This condition expresses the requirement that all +primal variables shoudl satisfy to bound constraints of the original +LP problem. In case of basic solution all non-basic variables are +placed on their active bounds, so actually the condition (KKT.PB) needs +to be checked for basic variables only. If the primal solution has +sufficient accuracy, this condition shows its primal feasibility. + +To check the condition (KKT.PB) the routine computes a vector of +residuals: +$$ +h_k = \left\{ +\begin{array}{ll} +0, & {\rm if}\ l_k \leq x_k \leq u_k \\ +x_k - l_k, & {\rm if}\ x_k < l_k \\ +x_k - u_k, & {\rm if}\ x_k > u_k \\ +\end{array} +\right. +$$ +for all $k=1,\dots,m+n$, and determines components of this vector that +correspond to largest absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq k \leq m+n}|h_k|,$$ +$${\tt re\_max}=\max_{1\leq k \leq m+n}\frac{|h_k|}{1+|x_k|}.$$ + +\newpage + +The third condition checked by the routine is: +$${\rm grad}\;Z = c = (\tilde{A})^T \pi + d,$$ +where $Z$ is the objective function, $c$ is the vector of objective +coefficients, $(\tilde{A})^T$ is a matrix transposed to the expanded +constraint matrix $\tilde{A} = (I|-A)$, $\pi$ is a vector of Lagrange +multipliers that correspond to equality constraints of the original LP +problem, $d$ is a vector of Lagrange multipliers that correspond to +bound constraints for all (auxiliary and structural) variables of the +original LP problem. Geometrically the third condition expresses the +requirement that the gradient of the objective function should belong +to the orthogonal complement of a linear subspace defined by the +equality and active bound constraints, i.e. that the gradient is +a linear combination of normals to the constraint hyperplanes, where +Lagrange multipliers $\pi$ and $d$ are coefficients of that linear +combination. + +To eliminate the vector $\pi$ rewrite the third condition as: +$$ +\left(\begin{array}{@{}c@{}}I \\ -A^T\end{array}\right) \pi = +\left(\begin{array}{@{}c@{}}d_R \\ d_S\end{array}\right) + +\left(\begin{array}{@{}c@{}}c_R \\ c_S\end{array}\right), +$$ +or, equivalently, +$$ +\left\{ +\begin{array}{r@{}c@{}c} +\pi + d_R&\ =\ &c_R, \\ +-A^T\pi + d_S&\ =\ &c_S. \\ +\end{array} +\right. +$$ + +Then substituting the vector $\pi$ from the first equation into the +second we finally have: +$$A^T (d_R - c_R) + (d_S - c_S) = 0, \eqno{\rm(KKT.DE)}$$ +where $d_R$ is the subvector of reduced costs of auxiliary variables +(rows), $d_S$ is the subvector of reduced costs of structural variables +(columns), $c_R$ and $c_S$ are subvectors of objective coefficients at, +respectively, auxiliary and structural variables, $A^T$ is a matrix +transposed to the constraint matrix of the original LP problem. In case +of exact arithmetic this condition would be satisfied for any basic +solution; however, in case of inexact (floating-point) arithmetic, this +condition shows how accurate the dual solution is, that depends on +accuracy of a representation of the basis matrix used by the simplex +method, or on accuracy provided by the interior-point method. + +To check the condition (KKT.DE) the routine computes a vector of +residuals: +$$u = A^T (d_R - c_R) + (d_S - c_S),$$ +and determines components of this vector that correspond to largest +absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq j\leq n}|u_j|,$$ +$${\tt re\_max}=\max_{1\leq j\leq n}\frac{|u_j|}{1+|(d_S)_j-(c_S)_j|}.$$ + +\newpage + +The fourth condition checked by the routine is the following: +$$ +\left\{ +\begin{array}{l@{\ }r@{\ }c@{\ }c@{\ }c@{\ }l@{\ }c@{\ }c@{\ }c@{\ }l} +{\rm if} & -\infty & < & x_k & < & +\infty, +& {\rm then} & d_k & = & 0 \\ +{\rm if} & l_k & \leq & x_k & < & +\infty, +& {\rm then} & d_k & \geq & 0\ {\rm(minimization)} \\ +&&&&&& & d_k & \leq & 0\ {\rm(maximization)} \\ +{\rm if} & -\infty & < & x_k & \leq & u_k, +& {\rm then} & d_k & \leq & 0\ {\rm(minimization)} \\ +&&&&&& & d_k & \geq & 0\ {\rm(maximization)} \\ +{\rm if} & l_k & \leq & x_k & \leq & u_k, +& {\rm then} & d_k & {\rm is} & {\rm of\ any\ sign} \\ +\end{array}\right.\eqno{\rm(KKT.DB)} +$$ +for all $k=1,\dots,m+n$, where $d_k$ is a reduced cost (Lagrange +multiplier) of auxiliary ($1\leq k\leq m$) or structural +($m+1\leq k\leq m+n$) variable $x_k$. Geometrically this condition +expresses the requirement that constraints of the original problem must +``hold'' the point preventing its movement along the anti-gradient (in +case of minimization) or the gradient (in case of maximization) of the +objective function. In case of basic solution reduced costs of all +basic variables are placed on their active (zero) bounds, so actually +the condition (KKT.DB) needs to be checked for non-basic variables +only. If the dual solution has sufficient accuracy, this condition +shows the dual feasibility of the solution. + +To check the condition (KKT.DB) the routine computes a vector of +residuals: +$$ +v_k = \left\{ +\begin{array}{ll} +0, & {\rm if}\ d_k\ {\rm has\ correct\ sign} \\ +|d_k|, & {\rm if}\ d_k\ {\rm has\ wrong\ sign} \\ +\end{array} +\right. +$$ +for all $k=1,\dots,m+n$, and determines components of this vector that +correspond to largest absolute and relative errors: +$${\tt ae\_max}=\max_{1\leq k\leq m+n}|v_k|,$$ +$${\tt re\_max}=\max_{1\leq k\leq m+n}\frac{|v_k|}{1+|d_k - c_k|}.$$ + +Note that the complete set of Karush-Kuhn-Tucker optimality conditions +also includes the fifth, so called {\it complementary slackness +condition}, which expresses the requirement that at least either +a primal variable $x_k$ or its dual counterpart $d_k$ should be on its +bound for all $k=1,\dots,m+n$. Currently checking this condition is +not implemented yet. + +\def\arraystretch{1} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk03.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk03.tex new file mode 100644 index 000000000..6086c54c1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk03.tex @@ -0,0 +1,1936 @@ +%* glpk03.tex *% + +\chapter{Utility API routines} + +\section{Problem data reading/writing routines} + +\subsection{glp\_read\_mps --- read problem data in MPS format} + +\synopsis + +\begin{verbatim} + int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mps| reads problem data in MPS format from a +text file. (The MPS format is described in Appendix \ref{champs}, page +\pageref{champs}.) + +The parameter \verb|fmt| specifies the MPS format version as follows: + +\verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; + +\verb|GLP_MPS_FILE| --- free (modern) MPS format. + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_mps| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_mps| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\newpage + +\subsection{glp\_write\_mps --- write problem data in MPS format} + +\synopsis + +\begin{verbatim} + int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mps| writes problem data in MPS format to +a text file. (The MPS format is described in Appendix \ref{champs}, +page \pageref{champs}.) + +The parameter \verb|fmt| specifies the MPS format version as follows: + +\verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; + +\verb|GLP_MPS_FILE| --- free (modern) MPS format. + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_write_mps| performs automatic compression on writing it.) + +\returns + +If the operation was successful, the routine \verb|glp_write_mps| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_read\_lp --- read problem data in CPLEX LP format} + +\synopsis + +{\tt int glp\_read\_lp(glp\_prob *P, const glp\_cpxcp *parm, +const char *fname);} + +\description + +The routine \verb|glp_read_lp| reads problem data in CPLEX LP format +from a text file. (The CPLEX LP format is described in Appendix +\ref{chacplex}, page \pageref{chacplex}.) + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_lp| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_lp| returns +zero. Otherwise, it prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_write\_lp --- write problem data in CPLEX LP format} + +\synopsis + +{\tt int glp\_write\_lp(glp\_prob *P, const glp\_cpxcp *parm, +const char *fname);} + +\description + +The routine \verb|glp_write_lp| writes problem data in CPLEX LP format +to a text file. (The CPLEX LP format is described in Appendix +\ref{chacplex}, page \pageref{chacplex}.) + +The parameter \verb|parm| is reserved for use in the future and should +be specified as \verb|NULL|. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_write_lp| performs automatic compression on writing it.) + +\returns + +If the operation was successful, the routine \verb|glp_write_lp| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_read\_prob --- read problem data in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_read_prob(glp_prob *P, int flags, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_prob| reads problem data in the GLPK LP/MIP +format from a text file. (For description of the GLPK LP/MIP format see +below.) + +The parameter \verb|flags| is reserved for use in the future and should +be specified as zero. + +The character string \verb|fname| specifies a name of the text file to +be read in. (If the file name ends with suffix `\verb|.gz|', the file +is assumed to be compressed, in which case the routine +\verb|glp_read_prob| decompresses it ``on the fly''.) + +Note that before reading data the current content of the problem object +is completely erased with the routine \verb|glp_erase_prob|. + +\returns + +If the operation was successful, the routine \verb|glp_read_prob| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +%\newpage + +\para{GLPK LP/MIP format} + +The GLPK LP/MIP format is a DIMACS-like format.\footnote{The DIMACS +formats were developed by the Center for Discrete Mathematics and +Theoretical Computer Science (DIMACS) to facilitate exchange of problem +data. For details see: {\tt }. } +The file in this format is a plain ASCII text file containing lines of +several types described below. A line is terminated with the +end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +\newpage + +The first line of the data file must be the problem line (except +optional comment lines, which may precede the problem line). The last +line of the data file must be the end line. Other lines may follow in +arbitrary order, however, duplicate lines are not allowed. + +\para{Comment lines.} Comment lines give human-readable +information about the data file and are ignored by GLPK routines. +Comment lines can appear anywhere in the data file. Each comment line +begins with the lower-case character \verb|c|. + +\begin{verbatim} + c This is an example of comment line +\end{verbatim} + +\para{Problem line.} There must be exactly one problem line in the +data file. This line must appear before any other lines except comment +lines and has the following format: + +\begin{verbatim} + p CLASS DIR ROWS COLS NONZ +\end{verbatim} + +The lower-case letter \verb|p| specifies that this is the problem line. + +The \verb|CLASS| field defines the problem class and can contain either +the keyword \verb|lp| (that means linear programming problem) or +\verb|mip| (that means mixed integer programming problem). + +The \verb|DIR| field defines the optimization direction (that is, the +objective function sense) and can contain either the keyword \verb|min| +(that means minimization) or \verb|max| (that means maximization). + +The \verb|ROWS|, \verb|COLS|, and \verb|NONZ| fields contain +non-negative integer values specifying, respectively, the number of +rows (constraints), columns (variables), and non-zero constraint +coefficients in the problem instance. Note that \verb|NONZ| value does +not account objective coefficients. + +\para{Row descriptors.} There must be at most one row descriptor line +in the data file for each row (constraint). This line has one of the +following formats: + +\begin{verbatim} + i ROW f + i ROW l RHS + i ROW u RHS + i ROW d RHS1 RHS2 + i ROW s RHS +\end{verbatim} + +The lower-case letter \verb|i| specifies that this is the row +descriptor line. + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The next lower-case letter specifies the row type as follows: + +\verb|f| --- free (unbounded) row: $-\infty<\sum a_jx_j<+\infty$; + +\verb|l| --- inequality constraint of `$\geq$' type: +$\sum a_jx_j\geq b$; + +\verb|u| --- inequality constraint of `$\leq$' type: +$\sum a_jx_j\leq b$; + +\verb|d| --- double-sided inequality constraint: +$b_1\leq\sum a_jx_j\leq b_2$; + +\verb|s| --- equality constraint: $\sum a_jx_j=b$. + +The \verb|RHS| field contains a floaing-point value specifying the +row right-hand side. The \verb|RHS1| and \verb|RHS2| fields contain +floating-point values specifying, respectively, the lower and upper +right-hand sides for the double-sided row. + +If for some row its descriptor line does not appear in the data file, +by default that row is assumed to be an equality constraint with zero +right-hand side. + +\para{Column descriptors.} There must be at most one column descriptor +line in the data file for each column (variable). This line has one of +the following formats depending on the problem class specified in the +problem line: + +\begin{tabular}{@{}l@{\hspace*{40pt}}l} +LP class & MIP class \\ +\hline +\verb|j COL f| & \verb|j COL KIND f| \\ +\verb|j COL l BND| & \verb|j COL KIND l BND| \\ +\verb|j COL u BND| & \verb|j COL KIND u BND| \\ +\verb|j COL d BND1 BND2| & \verb|j COL KIND d BND1 BND2| \\ +\verb|j COL s BND| & \verb|j COL KIND s BND| \\ +\end{tabular} + +The lower-case letter \verb|j| specifies that this is the column +descriptor line. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|KIND| field is used only for MIP problems and specifies the +column kind as follows: + +\verb|c| --- continuous column; + +\verb|i| --- integer column; + +\verb|b| --- binary column (in this case all remaining fields must be +omitted). + +The next lower-case letter specifies the column type as follows: + +\verb|f| --- free (unbounded) column: $-\infty +#include +#include + +int main(void) +{ glp_prob *lp; + glp_tran *tran; + int ret; + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "egypt.mod", 0); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); + if (ret != 0) + fprintf(stderr, "Error on writing MPS file\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + return 0; +} + +/* eof */ +\end{verbatim} +\end{small} + +\newpage + +\subsubsection*{Example 2} + +In this example the program reads model section from file +\verb|sudoku.mod|\footnote{This is an example model which is included +in the GLPK distribution along with alternative data file +{\tt sudoku.dat}.} ignoring data section in this file, reads alternative +data section from file \verb|sudoku.dat|, solves the problem instance +and passes the solution found back to the model. + +\bigskip + +\begin{small} +\begin{verbatim} +/* mplsamp2.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *mip; + glp_tran *tran; + int ret; + mip = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "sudoku.mod", 1); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_read_data(tran, "sudoku.dat"); + if (ret != 0) + { fprintf(stderr, "Error on translating data\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, mip); + glp_simplex(mip, NULL); + glp_intopt(mip, NULL); + ret = glp_mpl_postsolve(tran, mip, GLP_MIP); + if (ret != 0) + fprintf(stderr, "Error on postsolving model\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(mip); + return 0; +} + +/* eof */ +\end{verbatim} +\end{small} + +\newpage + +\subsection{glp\_mpl\_alloc\_wksp --- allocate the translator +workspace} + +\synopsis + +\begin{verbatim} + glp_tran *glp_mpl_alloc_wksp(void); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_alloc_wksp| allocates the MathProg translator +work\-space. (Note that multiple instances of the workspace may be +allocated, if necessary.) + +\returns + +The routine returns a pointer to the workspace, which should be used in +all subsequent operations. + +\subsection{glp\_mpl\_init\_rand --- initialize pseudo-random number +generator} + +\synopsis + +\begin{verbatim} + void glp_mpl_init_rand(glp_tran *tran, int seed); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_init_rand| initializes a pseudo-random number +generator used by the MathProg translator, where the parameter +\verb|seed| may be any integer number. + +A call to the routine \verb|glp_mpl_init_rand| should immediately +follow the call to the routine \verb|glp_mpl_alloc_wksp|. However, +using of this routine is optional. If it is not called, the effect is +the same as if it were called with \verb|seed| equal to 1. + +\subsection{glp\_mpl\_read\_model --- read and translate model section} + +\synopsis + +\begin{verbatim} + int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_read_model| reads model section and, +optionally, data section, which may follow the model section, from a +text file, whose name is the character string \verb|fname|, performs +translation of model statements and data blocks, and stores all the +information in the workspace. + +The parameter \verb|skip| is a flag. If the input file contains the +data section and this flag is non-zero, the data section is not read as +if there were no data section and a warning message is printed. This +allows reading data section(s) from other file(s). + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_mpl\_read\_data --- read and translate data section} + +\synopsis + +\begin{verbatim} + int glp_mpl_read_data(glp_tran *tran, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_read_data| reads data section from a text +file, whose name is the character string \verb|fname|, performs +translation of data blocks, and stores the data read in the translator +workspace. If necessary, this routine may be called more than once. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\subsection{glp\_mpl\_generate --- generate the model} + +\synopsis + +\begin{verbatim} + int glp_mpl_generate(glp_tran *tran, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_generate| generates the model using its +description stored in the translator workspace. This operation means +generating all variables, constraints, and objectives, executing check +and display statements, which precede the solve statement (if it is +presented). + +The character string \verb|fname| specifies the name of an output text +file, to which output produced by display statements should be written. +If \verb|fname| is \verb|NULL|, the output is sent to the terminal. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\vspace*{-6pt} + +\subsection{glp\_mpl\_build\_prob --- build problem instance from the +model} + +\synopsis + +\begin{verbatim} + void glp_mpl_build_prob(glp_tran *tran, glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_build_prob| obtains all necessary information +from the translator work\-space and stores it in the specified problem +object \verb|P|. Note that before building the current content of the +problem object is erased with the routine \verb|glp_erase_prob|. + +\newpage + +\subsection{glp\_mpl\_postsolve --- postsolve the model} + +\synopsis + +\begin{verbatim} + int glp_mpl_postsolve(glp_tran *tran, glp_prob *P, int sol); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_postsolve| copies the solution from the +specified problem object \verb|prob| to the translator workspace and +then executes all the remaining model statements, which follow the +solve statement. + +The parameter \verb|sol| specifies which solution should be copied +from the problem object to the workspace as follows: + +\verb|GLP_SOL| --- basic solution; + +\verb|GLP_IPT| --- interior-point solution; + +\verb|GLP_MIP| --- mixed integer solution. + +\returns + +If the operation is successful, the routine returns zero. Otherwise +the routine prints an error message and returns non-zero. + +\subsection{glp\_mpl\_free\_wksp --- free the translator workspace} + +\synopsis + +\begin{verbatim} + void glp_mpl_free_wksp(glp_tran *tran); +\end{verbatim} + +\description + +The routine \verb|glp_mpl_free_wksp| frees all the memory allocated to +the translator workspace. It also frees all other resources, which are +still used by the translator. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Problem solution reading/writing routines} + +\subsection{glp\_print\_sol --- write basic solution in printable +format} + +\synopsis + +\begin{verbatim} + int glp_print_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_sol writes| the current basic solution to +an LP problem, which is specified by the pointer \verb|P|, to a text +file, whose name is the character string \verb|fname|, in printable +format. + +Information reported by the routine \verb|glp_print_sol| is intended +mainly for visual analysis. + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_sol --- read basic solution in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_read_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_sol| reads basic solution from a text file +in the GLPK format. (For description of the format see below.) + +The character string \verb|fname| specifies the name of the text file +to be read in. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_read_sol| decompresses it "on the fly".) + +\returns + +If the operation was successful, the routine \verb|glp_read_sol| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\para{GLPK basic solution format} + +The GLPK basic solution format is a DIMACS-like format.\footnote{The +DIMACS formats were developed by the Center for Discrete Mathematics +and Theoretical Computer Science (DIMACS) to facilitate exchange of +problem data. +For details see: {\tt }. } +The file in this format is a plain ASCII text file containing lines of +several types described below. A line is terminated with the +end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +The first line of the solution file must be the solution line (except +optional comment lines, which may precede the problem line). The last +line of the data file must be the end line. Other lines may follow in +arbitrary order, however, duplicate lines are not allowed. + +\newpage + +\para{Comment lines.} Comment lines give human-readable information +about the solution file and are ignored by GLPK routines. Comment lines +can appear anywhere in the data file. Each comment line begins with the +lower-case character \verb|c|. + +\begin{verbatim} + c This is an example of comment line +\end{verbatim} + +\para{Solution line.} There must be exactly one solution line in the +solution file. This line must appear before any other lines except +comment lines and has the following format: + +\begin{verbatim} + s bas ROWS COLS PST DST OBJ +\end{verbatim} + +The lower-case letter \verb|s| specifies that this is the solution +line. + +The three-character solution designator \verb|bas| identifies the file +as containing a basic solution to the LP problem instance. + +The \verb|ROWS| and \verb|COLS| fields contain non-negative integer +values that specify the number of rows (constraints) and columns +(variables), resp., in the LP problem instance. + +The \verb|PST| and \verb|DST| fields contain lower-case letters that +specify the primal and dual solution status, resp., as follows: + +\verb|u| --- solution is undefined; + +\verb|f| --- solution is feasible; + +\verb|i| --- solution is infeasible; + +\verb|n| --- no feasible solution exists. + +The \verb|OBJ| field contains a floating-point number that specifies +the objective function value in the basic solution. + +\para{Row solution descriptors.} There must be exactly one row solution +descriptor line in the solution file for each row (constraint). This +line has the following format: + +\begin{verbatim} + i ROW ST PRIM DUAL +\end{verbatim} + +The lower-case letter \verb|i| specifies that this is the row solution +descriptor line. + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The \verb|ST| field contains one of the following lower-case letters +that specifies the row status in the basic solution:\footnote{The row +status is the status of the associated auxiliary variable.} + +\verb|b| --- inactive constraint; + +\verb|l| --- inequality constraint active on its lower bound; + +\verb|u| --- inequality constraint active on its upper bound; + +\verb|f| --- active free (unounded) row; + +\verb|s| --- active equality constraint. + +The \verb|PRIM| field contains a floating-point number that specifies +the row primal value (the value of the corresponding linear form). + +The \verb|DUAL| field contains a floating-point number that specifies +the row dual value (the Lagrangian multiplier for active bound). + +\para{Column solution descriptors.} There must be exactly one column +solution descriptor line in the solution file for each column +(variable). This line has the following format: + +\begin{verbatim} + j COL ST PRIM DUAL +\end{verbatim} + +The lower-case letter \verb|j| specifies that this is the column +solution descriptor line. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|ST| field contains one of the following lower-case letters +that specifies the column status in the basic solution: + +\verb|b| --- basic variable; + +\verb|l| --- non-basic variable having its lower bound active; + +\verb|u| --- non-basic variable having its upper bound active; + +\verb|f| --- non-basic free (unounded) variable; + +\verb|s| --- non-basic fixed variable. + +The \verb|PRIM| field contains a floating-point number that specifies +the column primal value. + +The \verb|DUAL| field contains a floating-point number that specifies +the column dual value (the Lagrangian multiplier for active bound). + +\para{End line.} There must be exactly one end line in the solution +file. This line must appear last in the file and has the following +format: + +\begin{verbatim} + e +\end{verbatim} + +The lower-case letter \verb|e| specifies that this is the end line. +Anything that follows the end line is ignored by GLPK routines. + +\para{Example of solution file in GLPK basic solution format} + +The following example of a solution file in GLPK basic solution format +specifies the optimal basic solution to the LP problem instance from +Subsection ``Example of MPS file''. + +\bigskip + +\begin{center} +\footnotesize\tt +\begin{tabular}{l@{\hspace*{50pt}}} +s bas 7 7 f f 296.216606498195 \\ +i 1 s 2000 -0.0135956678700369 \\ +i 2 u 60 -2.56823104693141 \\ +i 3 b 83.9675090252707 0 \\ +i 4 u 40 -0.544404332129962 \\ +i 5 b 19.9602888086643 0 \\ +i 6 l 1500 0.251985559566788 \\ +i 7 l 250 0.48519855595668 \\ +\end{tabular} +\begin{tabular}{|@{\hspace*{50pt}}l} +j 1 l 0 0.253624548736462 \\ +j 2 b 665.342960288809 0 \\ +j 3 b 490.252707581226 0 \\ +j 4 b 424.187725631769 0 \\ +j 5 l 0 0.0145559566787004 \\ +j 6 b 299.638989169676 0 \\ +j 7 b 120.57761732852 0 \\ +e o f \\ +\end{tabular} +\end{center} + +\newpage + +\subsection{glp\_write\_sol --- write basic solution in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_write_sol(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_sol| writes the current basic solution to +a text file in the GLPK format. (For description of the GLPK basic +solution format see Subsection ``Read basic solution in GLPK format.'') + +The character string \verb|fname| specifies the name of the text file +to be written. (If the file name ends with suffix `\verb|.gz|', the +routine \verb|glp_write_sol| compresses it "on the fly".) + +\returns + +If the operation was successful, the routine \verb|glp_write_sol| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_print\_ipt --- write interior-point solution in +printable format} + +\synopsis + +\begin{verbatim} + int glp_print_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_ipt| writes the current interior point +solution to an LP problem, which the parameter \verb|P| points to, to +a text file, whose name is the character string \verb|fname|, in +printable format. + +Information reported by the routine \verb|glp_print_ipt| is intended +mainly for visual analysis. + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_ipt --- read interior-point solution in GLPK +format} + +\synopsis + +\begin{verbatim} + int glp_read_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_ipt| reads interior-point solution from +a text file in the GLPK format. (For description of the format see +below.) + +The character string \verb|fname| specifies the name of the text file +to be read in. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_read_ipt| decompresses it "on the fly".) + +%\newpage + +\returns + +If the operation was successful, the routine \verb|glp_read_ipt| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\para{GLPK interior-point solution format} + +The GLPK interior-point solution format is a DIMACS-like +format.\footnote{The DIMACS formats were developed by the Center for +Discrete Mathematics and Theoretical Computer Science (DIMACS) to +facilitate exchange of problem data. For details see: +{\tt }. } +The file in this format is a plain ASCII text file containing lines of +several types described below. A line is terminated with the +end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +The first line of the solution file must be the solution line (except +optional comment lines, which may precede the problem line). The last +line of the data file must be the end line. Other lines may follow in +arbitrary order, however, duplicate lines are not allowed. + +\para{Comment lines.} Comment lines give human-readable information +about the solution file and are ignored by GLPK routines. Comment lines +can appear anywhere in the data file. Each comment line begins with the +lower-case character \verb|c|. + +\begin{verbatim} + c This is an example of comment line +\end{verbatim} + +\para{Solution line.} There must be exactly one solution line in the +solution file. This line must appear before any other lines except +comment lines and has the following format: + +\begin{verbatim} + s ipt ROWS COLS SST OBJ +\end{verbatim} + +The lower-case letter \verb|s| specifies that this is the solution +line. + +The three-character solution designator \verb|ipt| identifies the file +as containing an interior-point solution to the LP problem instance. + +The \verb|ROWS| and \verb|COLS| fields contain non-negative integer +values that specify the number of rows (constraints) and columns +(variables), resp., in the LP problem instance. + +The \verb|SST| field contains one of the following lower-case letters +that specifies the solution status: + +\verb|o| --- solution is optimal; + +\verb|i| --- solution is infeasible; + +\verb|n| --- no feasible solution exists; + +\verb|u| --- solution is undefined. + +The \verb|OBJ| field contains a floating-point number that specifies +the objective function value in the interior-point solution. + +\para{Row solution descriptors.} There must be exactly one row solution +descriptor line in the solution file for each row (constraint). This +line has the following format: + +\begin{verbatim} + i ROW PRIM DUAL +\end{verbatim} + +The lower-case letter \verb|i| specifies that this is the row solution +descriptor line. + +%\newpage + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The \verb|PRIM| field contains a floating-point number that specifies +the row primal value (the value of the corresponding linear form). + +The \verb|DUAL| field contains a floating-point number that specifies +the row dual value (the Lagrangian multiplier for active bound). + +\para{Column solution descriptors.} There must be exactly one column +solution descriptor line in the solution file for each column +(variable). This line has the following format: + +\begin{verbatim} + j COL PRIM DUAL +\end{verbatim} + +The lower-case letter \verb|j| specifies that this is the column +solution descriptor line. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|PRIM| field contains a floating-point number that specifies +the column primal value. + +The \verb|DUAL| field contains a floating-point number that specifies +the column dual value (the Lagrangian multiplier for active bound). + +\para{End line.} There must be exactly one end line in the solution +file. This line must appear last in the file and has the following +format: + +\begin{verbatim} + e +\end{verbatim} + +The lower-case letter \verb|e| specifies that this is the end line. +Anything that follows the end line is ignored by GLPK routines. + +\para{Example of solution file in GLPK interior-point solution format} + +The following example of a solution file in GLPK interior-point +solution format specifies the optimal interior-point solution to the LP +problem instance from Subsection ``Example of MPS file''. + +\bigskip + +\begin{center} +\footnotesize\tt +\begin{tabular}{l@{\hspace*{10pt}}} +s ipt 7 7 o 296.216606851403 \\ +i 1 2000.00000290369 -0.0135956757623443 \\ +i 2 60.0000001302903 -2.568231024875 \\ +i 3 83.9675094251819 -8.85591445202383e-10 \\ +i 4 39.9999999985064 -0.544404310443766 \\ +i 5 19.9602886941262 -2.24817803513554e-09 \\ +i 6 1500.00000199013 0.251985567257828 \\ +i 7 250.000000244896 0.48519856304979 \\ +\end{tabular} +\begin{tabular}{|@{\hspace*{10pt}}l} +j 1 3.3482079213784e-07 0.253624547432525 \\ +j 2 665.342955760768 6.04613825351601e-11 \\ +j 3 490.25271366802 5.8488360240978e-10 \\ +j 4 424.187729774275 -2.54144550490434e-11 \\ +j 5 1.46067738492801e-06 0.0145559574770786 \\ +j 6 299.638985053112 1.49359074902927e-10 \\ +j 7 120.577616852015 3.50297708781545e-10 \\ +e o f +\end{tabular} +\end{center} + +\subsection{glp\_write\_ipt --- write interior-point solution in GLPK +format} + +\synopsis + +\begin{verbatim} + int glp_write_ipt(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_ipt| writes the current interior-point +solution to a text file in the GLPK format. (For description of the +GLPK interior-point solution format see Subsection ``Read +interior-point solution in GLPK format.'') + +The character string \verb|fname| specifies the name of the text file +to be written. (If the file name ends with suffix `\verb|.gz|', the +routine \verb|glp_write_ipt| compresses it "on the fly".) + +\returns + +If the operation was successful, the routine \verb|glp_write_ipt| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\subsection{glp\_print\_mip --- write MIP solution in printable format} + +\synopsis + +\begin{verbatim} + int glp_print_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_print_mip| writes the current solution to a MIP +problem, which is specified by the pointer \verb|P|, to a text file, +whose name is the character string \verb|fname|, in printable format. + +Information reported by the routine \verb|glp_print_mip| is intended +mainly for visual analysis. + +\returns + +If no errors occurred, the routine returns zero. Otherwise the routine +prints an error message and returns non-zero. + +\subsection{glp\_read\_mip --- read MIP solution in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_read_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mip| reads MIP solution from a text file in +the GLPK format. (For description of the format see below.) + +The character string \verb|fname| specifies the name of the text file +to be read in. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +\verb|glp_read_mip| decompresses it "on the fly".) + +\returns + +If the operation was successful, the routine \verb|glp_read_mip| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\para{GLPK MIP solution format} + +The GLPK MIP solution format is a DIMACS-like format.\footnote{The +DIMACS formats were developed by the Center for Discrete Mathematics +and Theoretical Computer Science (DIMACS) to facilitate exchange of +problem data. For details see: +{\tt }. } +The file in this format is a plain ASCII text file containing lines of +several types described below. A line is terminated with the +end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +The first line of the solution file must be the solution line (except +optional comment lines, which may precede the problem line). The last +line of the data file must be the end line. Other lines may follow in +arbitrary order, however, duplicate lines are not allowed. + +\para{Comment lines.} Comment lines give human-readable information +about the solution file and are ignored by GLPK routines. Comment lines +can appear anywhere in the data file. Each comment line begins with the +lower-case character \verb|c|. + +\begin{verbatim} + c This is an example of comment line +\end{verbatim} + +\para{Solution line.} There must be exactly one solution line in the +solution file. This line must appear before any other lines except +comment lines and has the following format: + +\begin{verbatim} + s mip ROWS COLS SST OBJ +\end{verbatim} + +The lower-case letter \verb|s| specifies that this is the solution +line. + +The three-character solution designator \verb|mip| identifies the file +as containing a solution to the MIP problem instance. + +The \verb|ROWS| and \verb|COLS| fields contain non-negative integer +values that specify the number of rows (constraints) and columns +(variables), resp., in the LP problem instance. + +The \verb|SST| field contains one of the following lower-case letters +that specifies the solution status: + +\verb|o| --- solution is integer optimal; + +\verb|f| --- solution is integer feasible (non-optimal); + +\verb|n| --- no integer feasible solution exists; + +\verb|u| --- solution is undefined. + +The \verb|OBJ| field contains a floating-point number that specifies +the objective function value in the MIP solution. + +\para{Row solution descriptors.} There must be exactly one row solution +descriptor line in the solution file for each row (constraint). This +line has the following format: + +\begin{verbatim} + i ROW VAL +\end{verbatim} + +The lower-case letter \verb|i| specifies that this is the row solution +descriptor line. + +The \verb|ROW| field specifies the row ordinal number, an integer +between 1 and $m$, where $m$ is the number of rows in the problem +instance. + +The \verb|VAL| field contains a floating-point number that specifies +the row value (the value of the corresponding linear form). + +\para{Column solution descriptors.} There must be exactly one column +solution descriptor line in the solution file for each column +(variable). This line has the following format: + +\begin{verbatim} + j COL VAL +\end{verbatim} + +The lower-case letter \verb|j| specifies that this is the column +solution descriptor line. + +The \verb|COL| field specifies the column ordinal number, an integer +between 1 and $n$, where $n$ is the number of columns in the problem +instance. + +The \verb|VAL| field contains a floating-point number that specifies +the column value. + +\para{End line.} There must be exactly one end line in the solution +file. This line must appear last in the file and has the following +format: + +\begin{verbatim} + e +\end{verbatim} + +The lower-case letter \verb|e| specifies that this is the end line. +Anything that follows the end line is ignored by GLPK routines. + +\para{Example of solution file in GLPK MIP solution format} + +The following example of a solution file in GLPK MIP solution format +specifies an optimal solution to a MIP problem instance. + +\bigskip + +\begin{center} +\footnotesize\tt +\begin{tabular}{l@{\hspace*{50pt}}} +s mip 8 8 o 1201500 \\ +i 1 60 \\ +i 2 8400 \\ +i 3 -1200 \\ +i 4 0 \\ +i 5 9000 \\ +i 6 -600 \\ +i 7 0 \\ +i 8 8000 \\ +\end{tabular} +\begin{tabular}{|@{\hspace*{80pt}}l} +j 1 60 \\ +j 2 6 \\ +j 3 0 \\ +j 4 60 \\ +j 5 6 \\ +j 6 600 \\ +j 7 60 \\ +j 8 16 \\ +e o f \\ +\end{tabular} +\end{center} + +\subsection{glp\_write\_mip --- write MIP solution in GLPK format} + +\synopsis + +\begin{verbatim} + int glp_write_mip(glp_prob *P, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mip| writes the current MIP solution to +a text file in the GLPK format. (For description of the GLPK MIP +solution format see Subsection ``Read MIP solution in GLPK format.'') + +The character string \verb|fname| specifies the name of the text file +to be written. (If the file name ends with suffix `\verb|.gz|', the +routine \verb|glp_write_mip| compresses it "on the fly".) + +\returns + +If the operation was successful, the routine \verb|glp_write_mip| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Post-optimal analysis routines} + +\subsection{glp\_print\_ranges --- print sensitivity analysis report} + +\synopsis + +{\tt int glp\_print\_ranges(glp\_prob *P, int len, const int list[], +int flags,\\ +\hspace*{134pt}const char *fname);} + +\description + +The routine \verb|glp_print_ranges| performs sensitivity analysis of +current optimal basic solution and writes the analysis report in +human-readable format to a text file, whose name is the character +string {\it fname}. (Detailed description of the report structure is +given below.) + +The parameter {\it len} specifies the length of the row/column list. + +The array {\it list} specifies ordinal number of rows and columns to be +analyzed. The ordinal numbers should be passed in locations +{\it list}[1], {\it list}[2], \dots, {\it list}[{\it len}]. Ordinal +numbers from 1 to $m$ refer to rows, and ordinal numbers from $m+1$ to +$m+n$ refer to columns, where $m$ and $n$ are, resp., the total number +of rows and columns in the problem object. Rows and columns appear in +the analysis report in the same order as they follow in the array list. + +It is allowed to specify $len=0$, in which case the array {\it list} is +not used (so it can be specified as \verb|NULL|), and the routine +performs analysis for all rows and columns of the problem object. + +The parameter {\it flags} is reserved for use in the future and must be +specified as zero. + +On entry to the routine \verb|glp_print_ranges| the current basic +solution must be optimal and the basis factorization must exist. +The application program can check that with the routine +\verb|glp_bf_exists|, and if the factorization does +not exist, compute it with the routine \verb|glp_factorize|. Note that +if the LP preprocessor is not used, on normal exit from the simplex +solver routine \verb|glp_simplex| the basis factorization always exists. + +\returns + +If the operation was successful, the routine \verb|glp_print_ranges| +returns zero. Otherwise, it prints an error message and returns +non-zero. + +\para{Analysis report example} + +An example of the sensitivity analysis report is shown on the next two +pages. This example corresponds to the example of LP problem described +in Subsection ``Example of MPS file''. + +\para{Structure of the analysis report} + +For each row and column specified in the array {\it list} the routine +prints two lines containing generic information and analysis +information, which depends on the status of corresponding row or column. + +Note that analysis of a row is analysis of its auxiliary variable, +which is equal to the row linear form $\sum a_jx_j$, and analysis of +a column is analysis of corresponding structural variable. Therefore, +formally, on performing the sensitivity analysis there is no difference +between rows and columns. + +\newpage + +\begin{landscape} +\begin{footnotesize} +\begin{verbatim} + GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 1 + + Problem: PLAN + Objective: VALUE = 296.2166065 (MINimum) + + No. Row name St Activity Slack Lower bound Activity Obj coef Obj value at Limiting + Marginal Upper bound range range break point variable + ------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ + 1 VALUE BS 296.21661 -296.21661 -Inf 299.25255 -1.00000 . MN + . +Inf 296.21661 +Inf +Inf + + 2 YIELD NS 2000.00000 . 2000.00000 1995.06864 -Inf 296.28365 BIN3 + -.01360 2000.00000 2014.03479 +Inf 296.02579 CU + + 3 FE NU 60.00000 . -Inf 55.89016 -Inf 306.77162 BIN4 + -2.56823 60.00000 62.69978 2.56823 289.28294 BIN3 + + 4 CU BS 83.96751 16.03249 -Inf 93.88467 -.30613 270.51157 MN + . 100.00000 79.98213 .21474 314.24798 BIN5 + + 5 MN NU 40.00000 . -Inf 34.42336 -Inf 299.25255 BIN4 + -.54440 40.00000 41.68691 .54440 295.29825 BIN3 + + 6 MG BS 19.96029 10.03971 -Inf 24.74427 -1.79618 260.36433 BIN1 + . 30.00000 9.40292 .28757 301.95652 MN + + 7 AL NL 1500.00000 . 1500.00000 1485.78425 -.25199 292.63444 CU + .25199 +Inf 1504.92126 +Inf 297.45669 BIN3 + + 8 SI NL 250.00000 50.00000 250.00000 235.32871 -.48520 289.09812 CU + .48520 300.00000 255.06073 +Inf 298.67206 BIN3 +\end{verbatim} +\end{footnotesize} +\end{landscape} + +\newpage + +\begin{landscape} +\begin{footnotesize} +\begin{verbatim} + GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 2 + + Problem: PLAN + Objective: VALUE = 296.2166065 (MINimum) + + No. Column name St Activity Obj coef Lower bound Activity Obj coef Obj value at Limiting + Marginal Upper bound range range break point variable + ------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ + 1 BIN1 NL . .03000 . -28.82475 -.22362 288.90594 BIN4 + .25362 200.00000 33.88040 +Inf 304.80951 BIN4 + + 2 BIN2 BS 665.34296 .08000 . 802.22222 .01722 254.44822 BIN1 + . 2500.00000 313.43066 .08863 301.95652 MN + + 3 BIN3 BS 490.25271 .17000 400.00000 788.61314 .15982 291.22807 MN + . 800.00000 -347.42857 .17948 300.86548 BIN5 + + 4 BIN4 BS 424.18773 .12000 100.00000 710.52632 .10899 291.54745 MN + . 700.00000 -256.15524 .14651 307.46010 BIN1 + + 5 BIN5 NL . .15000 . -201.78739 .13544 293.27940 BIN3 + .01456 1500.00000 58.79586 +Inf 297.07244 BIN3 + + 6 ALUM BS 299.63899 .21000 . 358.26772 .18885 289.87879 AL + . +Inf 112.40876 .22622 301.07527 MN + + 7 SILICON BS 120.57762 .38000 . 124.27093 .14828 268.27586 BIN5 + . +Inf 85.54745 .46667 306.66667 MN + + End of report +\end{verbatim} +\end{footnotesize} +\end{landscape} + +\newpage + +\noindent +{\it Generic information} + +{\tt No.} is the row or column ordinal number in the problem object. +Rows are numbered from 1 to $m$, and columns are numbered from 1 to $n$, +where $m$ and $n$ are, resp., the total number of rows and columns in +the problem object. + +{\tt Row name} is the symbolic name assigned to the row. If the row has +no name assigned, this field contains blanks. + +{\tt Column name} is the symbolic name assigned to the column. If the +column has no name assigned, this field contains blanks. + +{\tt St} is the status of the row or column in the optimal solution: + +{\tt BS} --- non-active constraint (row), basic column; + +{\tt NL} --- inequality constraint having its lower right-hand side +active (row), non-basic column having its lower bound active; + +{\tt NU} --- inequality constraint having its upper right-hand side +active (row), non-basic column having its upper bound active; + +{\tt NS} --- active equality constraint (row), non-basic fixed column. + +{\tt NF} --- active free row, non-basic free (unbounded) column. (This +case means that the optimal solution is dual degenerate.) + +{\tt Activity} is the (primal) value of the auxiliary variable (row) or +structural variable (column) in the optimal solution. + +{\tt Slack} is the (primal) value of the row slack variable. + +{\tt Obj coef} is the objective coefficient of the column (structural +variable). + +{\tt Marginal} is the reduced cost (dual activity) of the auxiliary +variable (row) or structural variable (column). + +{\tt Lower bound} is the lower right-hand side (row) or lower bound +(column). If the row or column has no lower bound, this field contains +{\tt -Inf}. + +{\tt Upper bound} is the upper right-hand side (row) or upper bound +(column). If the row or column has no upper bound, this field contains +{\tt +Inf}. + +\noindent +{\it Sensitivity analysis of active bounds} + +The sensitivity analysis of active bounds is performed only for rows, +which are active constraints, and only for non-basic columns, because +inactive constraints and basic columns have no active bounds. + +For every auxiliary (row) or structural (column) non-basic variable the +routine starts changing its active bound in both direction. The first +of the two lines in the report corresponds to decreasing, and the +second line corresponds to increasing of the active bound. Since the +variable being analyzed is non-basic, its activity, which is equal to +its active bound, also starts changing. This changing leads to changing +of basic (auxiliary and structural) variables, which depend on the +non-basic variable. The current basis remains primal feasible and +therefore optimal while values of all basic variables are primal +feasible, i.e. are within their bounds. Therefore, if some basic +variable called the {\it limiting variable} reaches its (lower or +upper) bound first, before any other basic variables, it thereby limits +further changing of the non-basic variable, because otherwise the +current basis would become primal infeasible. The point, at which this +happens, is called the {\it break point}. Note that there are two break +points: the lower break point, which corresponds to decreasing of the +non-basic variable, and the upper break point, which corresponds to +increasing of the non-basic variable. + +In the analysis report values of the non-basic variable (i.e. of its +active bound) being analyzed at both lower and upper break points are +printed in the field `{\tt Activity range}'. Corresponding values of +the objective function are printed in the field `{\tt Obj value at +break point}', and symbolic names of corresponding limiting basic +variables are printed in the field `{\tt Limiting variable}'. +If the active bound can decrease or/and increase unlimitedly, the field +`{\tt Activity range}' contains {\tt -Inf} or/and {\tt +Inf}, resp. + +For example (see the example report above), row SI is a double-sided +constraint, which is active on its lower bound (right-hand side), and +its activity in the optimal solution being equal to the lower bound is +250. The activity range for this row is $[235.32871,255.06073]$. This +means that the basis remains optimal while the lower bound is +increasing up to 255.06073, and further increasing is limited by +(structural) variable BIN3. If the lower bound reaches this upper break +point, the objective value becomes equal to 298.67206. + +Note that if the basis does not change, the objective function depends +on the non-basic variable linearly, and the per-unit change of the +objective function is the reduced cost (marginal value) of the +non-basic variable. + +\noindent +{\it Sensitivity analysis of objective coefficients at non-basic +variables} + +The sensitivity analysis of the objective coefficient at a non-basic +variable is quite simple, because in this case change in the objective +coefficient leads to equivalent change in the reduced cost (marginal +value). + +For every auxiliary (row) or structural (column) non-basic variable the +routine starts changing its objective coefficient in both direction. +(Note that auxiliary variables are not included in the objective +function and therefore always have zero objective coefficients.) The +first of the two lines in the report corresponds to decreasing, and the +second line corresponds to increasing of the objective coefficient. +This changing leads to changing of the reduced cost of the non-basic +variable to be analyzed and does affect reduced costs of all other +non-basic variables. The current basis remains dual feasible and +therefore optimal while the reduced cost keeps its sign. Therefore, if +the reduced cost reaches zero, it limits further changing of the +objective coefficient (if only the non-basic variable is non-fixed). + +In the analysis report minimal and maximal values of the objective +coefficient, on which the basis remains optimal, are printed in the +field `\verb|Obj coef range|'. If the objective coefficient can +decrease or/and increase unlimitedly, this field contains {\tt -Inf} +or/and {\tt +Inf}, resp. + +For example (see the example report above), column BIN5 is non-basic +having its lower bound active. Its objective coefficient is 0.15, and +reduced cost in the optimal solution 0.01456. The column lower bound +remains active while the column reduced cost remains non-negative, +thus, minimal value of the objective coefficient, on which the current +basis still remains optimal, is $0.15-0.01456=0.13644$, that is +indicated in the field `\verb|Obj coef range|'. + +%\newpage + +%{\parskip=0pt +\noindent +{\it Sensitivity analysis of objective coefficients at basic variables} + +%\medskip + +To perform sensitivity analysis for every auxiliary (row) or structural +(column) variable the routine starts changing its objective coefficient +in both direction. (Note that auxiliary variables are not included in +the objective function and therefore always have zero objective +coefficients.) The first of the two lines in the report corresponds to +decreasing, and the second line corresponds to increasing of the +objective coefficient. This changing leads to changing of reduced costs +of non-basic variables. The current basis remains dual feasible and +therefore optimal while reduced costs of all non-basic variables +(except fixed variables) keep their signs. Therefore, if the reduced +cost of some non-basic non-fixed variable called the {\it limiting +variable} reaches zero first, before reduced cost of any other +non-basic non-fixed variable, it thereby limits further changing of the +objective coefficient, because otherwise the current basis would become +dual infeasible (non-optimal). The point, at which this happens, is +called the {\it break point}. Note that there are two break points: the +lower break point, which corresponds to decreasing of the objective +coefficient, and the upper break point, which corresponds to increasing +of the objective coefficient. Let the objective coefficient reach its +limit value and continue changing a bit further in the same direction +that makes the current basis dual infeasible (non-optimal). Then the +reduced cost of the non-basic limiting variable becomes ``a bit'' dual +infeasible that forces the limiting variable to enter the basis +replacing there some basic variable, which leaves the basis to keep its +primal feasibility. It should be understood that if we change the +current basis in this way exactly at the break point, both the current +and adjacent bases will be optimal with the same objective value, +because at the break point the limiting variable has zero reduced cost. +On the other hand, in the adjacent basis the value of the limiting +variable changes, because there it becomes basic, that leads to +changing of the value of the basic variable being analyzed. Note that +on determining the adjacent basis the bounds of the analyzed basic +variable are ignored as if it were a free (unbounded) variable, so it +cannot leave the current basis. + +In the analysis report lower and upper limits of the objective +coefficient at the basic variable being analyzed, when the basis +remains optimal, are printed in the field `{\tt Obj coef range}'. +Corresponding values of the objective function at both lower and upper +break points are printed in the field `{\tt Obj value at break point}', +symbolic names of corresponding non-basic limiting variables are +printed in the field `{\tt Limiting variable}', and values of the basic +variable, which it would take on in the adjacent bases (as was +explained above) are printed in the field `{\tt Activity range}'. +If the objective coefficient can increase or/and decrease unlimitedly, +the field `{\tt Obj coef range}' contains {\tt -Inf} and/or {\tt +Inf}, +resp. It also may happen that no dual feasible adjacent basis exists +(i.e. on entering the basis the limiting variable can increase or +decrease unlimitedly), in which case the field `{\tt Activity range}' +contains {\tt -Inf} and/or {\tt +Inf}. + +For example (see the example report above), structural variable +(column) BIN3 is basic, its optimal value is 490.25271, and its +objective coefficient is 0.17. The objective coefficient range for this +column is $[0.15982,0.17948]$. This means that the basis remains +optimal while the objective coefficient is decreasing down to 0.15982, +and further decreasing is limited by (auxiliary) variable MN. If we +make the objective coefficient a bit less than 0.15982, the limiting +variable MN will enter the basis, and in that adjacent basis the +structural variable BIN3 will take on new optimal value 788.61314. At +the lower break point, where the objective coefficient is exactly +0.15982, the objective function takes on the value 291.22807 in both +the current and adjacent bases. + +Note that if the basis does not change, the objective function depends +on the objective coefficient at the basic variable linearly, and the +per-unit change of the objective function is the value of the basic +variable. +%} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk04.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk04.tex new file mode 100644 index 000000000..0a981befe --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk04.tex @@ -0,0 +1,1392 @@ +%* glpk04.tex *% + +\chapter{Advanced API Routines} + +\section{Background} +\label{basbgd} + +Using vector and matrix notations the LP problem (1.1)---(1.3) (see +Section \ref{seclp}, page \pageref{seclp}) can be stated as follows: + +\noindent +\hspace{.5in} minimize (or maximize) +$$z=c^Tx_S+c_0\eqno(3.1)$$ +\hspace{.5in} subject to linear constraints +$$x_R=Ax_S\eqno(3.2)$$ +\hspace{.5in} and bounds of variables +$$ +\begin{array}{l@{\ }c@{\ }l@{\ }c@{\ }l} +l_R&\leq&x_R&\leq&u_R\\ +l_S&\leq&x_S&\leq&u_S\\ +\end{array}\eqno(3.3) +$$ +where: + +$x_R=(x_1,\dots,x_m)$ is the vector of auxiliary variables; + +$x_S=(x_{m+1},\dots,x_{m+n})$ is the vector of structural variables; + +$z$ is the objective function; + +$c=(c_1,\dots,c_n)$ is the vector of objective coefficients; + +$c_0$ is the constant term (``shift'') of the objective function; + +$A=(a_{11},\dots,a_{mn})$ is the constraint matrix; + +$l_R=(l_1,\dots,l_m)$ is the vector of lower bounds of auxiliary +variables; + +$u_R=(u_1,\dots,u_m)$ is the vector of upper bounds of auxiliary +variables; + +$l_S=(l_{m+1},\dots,l_{m+n})$ is the vector of lower bounds of +structural variables; + +$u_S=(u_{m+1},\dots,u_{m+n})$ is the vector of upper bounds of +structural variables. + +From the simplex method's standpoint there is no difference between +auxiliary and structural variables. This allows combining all these +variables into one vector that leads to the following problem +statement: + +\newpage + +\noindent +\hspace{.5in} minimize (or maximize) +$$z=(0\ |\ c)^Tx+c_0\eqno(3.4)$$ +\hspace{.5in} subject to linear constraints +$$(I\ |-\!A)x=0\eqno(3.5)$$ +\hspace{.5in} and bounds of variables +$$l\leq x\leq u\eqno(3.6)$$ +where: + +$x=(x_R\ |\ x_S)$ is the $(m+n)$-vector of (all) variables; + +$(0\ |\ c)$ is the $(m+n)$-vector of objective +coefficients;\footnote{Subvector 0 corresponds to objective +coefficients at auxiliary variables.} + +$(I\ |-\!A)$ is the {\it augmented} constraint +$m\times(m+n)$-matrix;\footnote{Note that due to auxiliary variables +matrix $(I\ |-\!A)$ contains the unity submatrix and therefore has full +rank. This means, in particular, that the system (3.5) has no linearly +dependent constraints.} + +$l=(l_R\ |\ l_S)$ is the $(m+n)$-vector of lower bounds of (all) +variables; + +$u=(u_R\ |\ u_S)$ is the $(m+n)$-vector of upper bounds of (all) +variables. + +By definition an {\it LP basic solution} geometrically is a point in +the space of all variables, which is the intersection of hyperplanes +corresponding to active constraints\footnote{A constraint is called +{\it active} if at a given point it is satisfied as equality, otherwise +it is called {\it inactive}.}. The space of all variables has the +dimension $m+n$, therefore, to define some basic solution we have to +define $m+n$ active constraints. Note that $m$ constraints (3.5) being +linearly independent equalities are always active, so remaining $n$ +active constraints can be chosen only from bound constraints (3.6). + +A variable is called {\it non-basic}, if its (lower or upper) bound is +active, otherwise it is called {\it basic}. Since, as was said above, +exactly $n$ bound constraints must be active, in any basic solution +there are always $n$ non-basic variables and $m$ basic variables. +(Note that a free variable also can be non-basic. Although such +variable has no bounds, we can think it as the difference between two +non-negative variables, which both are non-basic in this case.) + +Now consider how to determine numeric values of all variables for a +given basic solution. + +Let $\Pi$ be an appropriate permutation matrix of the order $(m+n)$. +Then we can write: +$$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= +\Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)=\Pi x, +\eqno(3.7)$$ +where $x_B$ is the vector of basic variables, $x_N$ is the vector of +non-basic variables, $x=(x_R\ |\ x_S)$ is the vector of all variables +in the original order. In this case the system of linear constraints +(3.5) can be rewritten as follows: +$$(I\ |-\!A)\Pi^T\Pi x=0\ \ \ \Rightarrow\ \ \ (B\ |\ N) +\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)=0,\eqno(3.8)$$ +where +$$(B\ |\ N)=(I\ |-\!A)\Pi^T.\eqno(3.9)$$ + +%\newpage + +Matrix $B$ is a square non-singular $m\times m$-matrix, which is +composed from columns of the augmented constraint matrix corresponding +to basic variables. It is called the {\it basis matrix} or simply the +{\it basis}. Matrix $N$ is a rectangular $m\times n$-matrix, which is +composed from columns of the augmented constraint matrix corresponding +to non-basic variables. + +From (3.8) it follows that: +$$Bx_B+Nx_N=0,\eqno(3.10)$$ +therefore, +$$x_B=-B^{-1}Nx_N.\eqno(3.11)$$ +Thus, the formula (3.11) shows how to determine numeric values of basic +variables $x_B$ assuming that non-basic variables $x_N$ are fixed on +their active bounds. + +The $m\times n$-matrix +$$\Xi=-B^{-1}N,\eqno(3.12)$$ +which appears in (3.11), is called the {\it simplex +tableau}.\footnote{This definition corresponds to the GLPK +implementation.} It shows how basic variables depend on non-basic +variables: +$$x_B=\Xi x_N.\eqno(3.13)$$ + +The system (3.13) is equivalent to the system (3.5) in the sense that +they both define the same set of points in the space of (primal) +variables, which satisfy to these systems. If, moreover, values of all +basic variables satisfy to their bound constraints (3.3), the +corresponding basic solution is called {\it (primal) feasible}, +otherwise {\it (primal) infeasible}. It is understood that any (primal) +feasible basic solution satisfy to all constraints (3.2) and (3.3). + +The LP theory says that if LP has optimal solution, it has (at least +one) basic feasible solution, which corresponds to the optimum. And the +most natural way to determine whether a given basic solution is optimal +or not is to use the Karush---Kuhn---Tucker optimality conditions. + +\def\arraystretch{1.5} + +For the problem statement (3.4)---(3.6) the optimality conditions are +the following:\footnote{These conditions can be appiled to any solution, +not only to a basic solution.} +$$(I\ |-\!A)x=0\eqno(3.14)$$ +$$(I\ |-\!A)^T\pi+\lambda_l+\lambda_u=\nabla z=(0\ |\ c)^T\eqno(3.15)$$ +$$l\leq x\leq u\eqno(3.16)$$ +$$\lambda_l\geq 0,\ \ \lambda_u\leq 0\ \ \mbox{(minimization)} +\eqno(3.17)$$ +$$\lambda_l\leq 0,\ \ \lambda_u\geq 0\ \ \mbox{(maximization)} +\eqno(3.18)$$ +$$(\lambda_l)_k(x_k-l_k)=0,\ \ (\lambda_u)_k(x_k-u_k)=0,\ \ k=1,2,\dots, +m+n\eqno(3.19)$$ +where: + +$\pi=(\pi_1,\dots,\pi_m)$ is a $m$-vector of Lagrange +multipliers for equality constraints (3.5); + +$\lambda_l=[(\lambda_l)_1,\dots,(\lambda_l)_n]$ is a $n$-vector of +Lagrange multipliers for lower bound constraints (3.6); + +$\lambda_u=[(\lambda_u)_1,\dots,(\lambda_u)_n]$ is a $n$-vector of +Lagrange multipliers for upper bound constraints (3.6). + +%\newpage + +Condition (3.14) is the {\it primal} (original) system of equality +constraints (3.5). + +Condition (3.15) is the {\it dual} system of equality constraints. +It requires the gradient of the objective function to be a linear +combination of normals to the planes defined by constraints of the +original problem. + +Condition (3.16) is the primal (original) system of bound constraints +(3.6). + +Condition (3.17) (or (3.18) in case of maximization) is the dual system +of bound constraints. + +Condition (3.19) is the {\it complementary slackness condition}. It +requires, for each original (auxiliary or structural) variable $x_k$, +that either its (lower or upper) bound must be active, or zero bound of +the corresponding Lagrange multiplier ($(\lambda_l)_k$ or +$(\lambda_u)_k$) must be active. + +In GLPK two multipliers $(\lambda_l)_k$ and $(\lambda_u)_k$ for each +primal variable $x_k$, $k=1,\dots,m+n$, are combined into one +multiplier: +$$\lambda_k=(\lambda_l)_k+(\lambda_u)_k,\eqno(3.20)$$ +which is called a {\it dual variable} for $x_k$. This {\it cannot} lead +to an ambiguity, because both lower and upper bounds of $x_k$ cannot be +active at the same time,\footnote{If $x_k$ is a fixed variable, we can +think it as double-bounded variable $l_k\leq x_k\leq u_k$, where +$l_k=u_k.$} so at least one of $(\lambda_l)_k$ and $(\lambda_u)_k$ must +be equal to zero, and because these multipliers have different signs, +the combined multiplier, which is their sum, uniquely defines each of +them. + +\def\arraystretch{1} + +Using dual variables $\lambda_k$ the dual system of bound constraints +(3.17) and (3.18) can be written in the form of so called {\it ``rule of +signs''} as follows: + +\medskip + +\begin{center} +\begin{tabular}{|@{\,}c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}| +@{$\,$}c|c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}|} +\hline +Original bound&\multicolumn{3}{c|}{Minimization}&\multicolumn{3}{c|} +{Maximization}\\ +\cline{2-7} +constraint&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ +(\lambda_u)_k$&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ +(\lambda_u)_k$\\ +\hline +$-\infty= {\tt piv\_tol}\cdot\max|u_{i*}|$, i.e. if it is not very +small in the magnitude among other elements in the same row. Decreasing +this parameter may lead to better sparsity at the expense of numerical +accuracy, and vice versa. + +\medskip + +{\tt int piv\_lim} (default: {\tt 4}) + +This parameter is used on computing $LU$-factorization of the basis +matrix and specifies how many pivot candidates needs to be considered +on choosing a pivot element, \verb|piv_lim| $\geq$ 1. If \verb|piv_lim| +candidates have been considered, the pivoting routine prematurely +terminates the search with the best candidate found. + +\medskip + +{\tt int suhl} (default: {\tt GLP\_ON}) + +This parameter is used on computing $LU$-factorization of the basis +matrix. Being set to {\tt GLP\_ON} it enables applying the following +heuristic proposed by Uwe Suhl: if a column of the active submatrix has +no eligible pivot candidates, it is no more considered until it becomes +a column singleton. In many cases this allows reducing the time needed +for pivot searching. To disable this heuristic the parameter +\verb|suhl| should be set to {\tt GLP\_OFF}. + +\medskip + +{\tt double eps\_tol} (default: {\tt 1e-15}) + +Epsilon tolerance, \verb|eps_tol| $\geq$ 0, used on computing +$LU$-factorization of the basis matrix. If an element of the active +submatrix of factor $U$ is less than \verb|eps_tol| in the magnitude, +it is replaced by exact zero. + +%\medskip +% +%{\tt double max\_gro} (default: {\tt 1e+10}) +% +%Maximal growth of elements of factor $U$, \verb|max_gro| $\geq$ 1, +%allowable on computing $LU$-factorization of the basis matrix. If on +%some elimination step the ratio $u_{big}/b_{max}$ (where $u_{big}$ is +%the largest magnitude of elements of factor $U$ appeared in its active +%submatrix during all the factorization process, $b_{max}$ is the +%largest magnitude of elements of the basis matrix to be factorized), +%the basis matrix is considered as ill-conditioned. + +\medskip + +{\tt int nfs\_max} (default: {\tt 100}) + +Maximal number of additional row-like factors (entries of the eta +file), \verb|nfs_max| $\geq$ 1, which can be added to +$LU$-factorization of the basis matrix on updating it with the +Forrest--Tomlin technique. This parameter is used only once, before +$LU$-factorization is computed for the first time, to allocate working +arrays. As a rule, each update adds one new factor (however, some +updates may need no addition), so this parameter limits the number of +updates between refactorizations. + +\medskip + +{\tt double upd\_tol} (default: {\tt 1e-6}) + +Update tolerance, 0 $<$ \verb|upd_tol| $<$ 1, used on updating +$LU$-factorization of the basis matrix with the Forrest--Tomlin +technique. If after updating the magnitude of some diagonal element +$u_{kk}$ of factor $U$ becomes less than +${\tt upd\_tol}\cdot\max(|u_{k*}|, |u_{*k}|)$, the factorization is +considered as inaccurate. + +\medskip + +{\tt int nrs\_max} (default: {\tt 100}) + +Maximal number of additional rows and columns, \verb|nrs_max| $\geq$ 1, +which can be added to $LU$-factorization of the basis matrix on +updating it with the Schur complement technique. This parameter is used +only once, before $LU$-factorization is computed for the first time, to +allocate working arrays. As a rule, each update adds one new row and +column (however, some updates may need no addition), so this parameter +limits the number of updates between refactorizations. + +%\medskip +% +%{\tt int rs\_size} (default: {\tt 0}) +% +%The initial size of the Sparse Vector Area, in non-zeros, used to +%store non-zero elements of additional rows and columns introduced on +%updating $LU$-factorization of the basis matrix with the Schur +%complement technique. If this parameter is set to 0, the initial SVA +%size is determined automatically. + +\subsection{glp\_get\_bhead --- retrieve the basis header information} + +\synopsis + +\begin{verbatim} + int glp_get_bhead(glp_prob *P, int k); +\end{verbatim} + +\description + +The routine \verb|glp_get_bhead| returns the basis header information +for the current basis associated with the specified problem object. + +\returns + +If basic variable $(x_B)_k$, $1\leq k\leq m$, is $i$-th auxiliary +variable ($1\leq i\leq m$), the routine returns $i$. Otherwise, if +$(x_B)_k$ is $j$-th structural variable ($1\leq j\leq n$), the routine +returns $m+j$. Here $m$ is the number of rows and $n$ is the number of +columns in the problem object. + +\para{Comments} + +Sometimes the application program may need to know which original +(auxiliary and structural) variable correspond to a given basic +variable, or, that is the same, which column of the augmented +constraint matrix $(I\ |-\!A)$ correspond to a given column of the +basis matrix $B$. + +\def\arraystretch{1} + +The correspondence is defined as follows:\footnote{For more details see +Subsection \ref{basbgd}, page \pageref{basbgd}.} +$$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= +\Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right) +\ \ \Leftrightarrow +\ \ \left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)= +\Pi^T\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right),$$ +where $x_B$ is the vector of basic variables, $x_N$ is the vector of +non-basic variables, $x_R$ is the vector of auxiliary variables +following in their original order,\footnote{The original order of +auxiliary and structural variables is defined by the ordinal numbers +of corresponding rows and columns in the problem object.} $x_S$ is the +vector of structural variables following in their original order, $\Pi$ +is a permutation matrix (which is a component of the basis +factorization). + +Thus, if $(x_B)_k=(x_R)_i$ is $i$-th auxiliary variable, the routine +returns $i$, and if $(x_B)_k=(x_S)_j$ is $j$-th structural variable, +the routine returns $m+j$, where $m$ is the number of rows in the +problem object. + +\subsection{glp\_get\_row\_bind --- retrieve row index in the basis +header} + +\synopsis + +\begin{verbatim} + int glp_get_row_bind(glp_prob *P, int i); +\end{verbatim} + +\returns + +The routine \verb|glp_get_row_bind| returns the index $k$ of basic +variable $(x_B)_k$, $1\leq k\leq m$, which is $i$-th auxiliary variable +(that is, the auxiliary variable corresponding to $i$-th row), +$1\leq i\leq m$, in the current basis associated with the specified +problem object, where $m$ is the number of rows. However, if $i$-th +auxiliary variable is non-basic, the routine returns zero. + +\para{Comments} + +The routine \verb|glp_get_row_bind| is an inversion of the routine +\verb|glp_get_bhead|; that is, if \linebreak +\verb|glp_get_bhead|$(P,k)$ returns $i$, +\verb|glp_get_row_bind|$(P,i)$ returns $k$, and vice versa. + +\subsection{glp\_get\_col\_bind --- retrieve column index in the basis +header} + +\synopsis + +\begin{verbatim} + int glp_get_col_bind(glp_prob *P, int j); +\end{verbatim} + +\returns + +The routine \verb|glp_get_col_bind| returns the index $k$ of basic +variable $(x_B)_k$, $1\leq k\leq m$, which is $j$-th structural +variable (that is, the structural variable corresponding to $j$-th +column), $1\leq j\leq n$, in the current basis associated with the +specified problem object, where $m$ is the number of rows, $n$ is the +number of columns. However, if $j$-th structural variable is non-basic, +the routine returns zero. + +\para{Comments} + +The routine \verb|glp_get_col_bind| is an inversion of the routine +\verb|glp_get_bhead|; that is, if \linebreak +\verb|glp_get_bhead|$(P,k)$ returns $m+j$, +\verb|glp_get_col_bind|$(P,j)$ returns $k$, and vice versa. + +\subsection{glp\_ftran --- perform forward transformation} + +\synopsis + +\begin{verbatim} + void glp_ftran(glp_prob *P, double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_ftran| performs forward transformation (FTRAN), +i.e. it solves the system $Bx=b$, where $B$ is the basis matrix +associated with the specified problem object, $x$ is the vector of +unknowns to be computed, $b$ is the vector of right-hand sides. + +On entry to the routine elements of the vector $b$ should be stored in +locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of +rows. On exit the routine stores elements of the vector $x$ in the same +locations. + +\subsection{glp\_btran --- perform backward transformation} + +\synopsis + +\begin{verbatim} + void glp_btran(glp_prob *P, double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_btran| performs backward transformation (BTRAN), +i.e. it solves the system $B^Tx=b$, where $B^T$ is a matrix transposed +to the basis matrix $B$ associated with the specified problem object, +$x$ is the vector of unknowns to be computed, $b$ is the vector of +right-hand sides. + +On entry to the routine elements of the vector $b$ should be stored in +locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of +rows. On exit the routine stores elements of the vector $x$ in the same +locations. + +\subsection{glp\_warm\_up --- ``warm up'' LP basis} + +\synopsis + +\begin{verbatim} + int glp_warm_up(glp_prob *P); +\end{verbatim} + +\description + +The routine \verb|glp_warm_up| ``warms up'' the LP basis for the +specified problem object using current statuses assigned to rows and +columns (that is, to auxiliary and structural variables). + +This operation includes computing factorization of the basis matrix +(if it does not exist), computing primal and dual components of basic +solution, and determining the solution status. + +\returns + +\begin{retlist} +0 & The operation has been successfully performed.\\ + +\verb|GLP_EBADB| & The basis matrix is invalid, because the number of +basic (auxiliary and structural) variables is not the same as the +number of rows in the problem object.\\ + +\verb|GLP_ESING| & The basis matrix is singular within the working +precision.\\ + +\verb|GLP_ECOND| & The basis matrix is ill-conditioned, i.e. its +condition number is too large.\\ +\end{retlist} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Simplex tableau routines} + +\subsection{glp\_eval\_tab\_row --- compute row of the tableau} + +\synopsis + +\begin{verbatim} + int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_eval_tab_row| computes a row of the current +simplex tableau (see Subsection 3.1.1, formula (3.12)), which (row) +corresponds to some basic variable specified by the parameter $k$ as +follows: if $1\leq k\leq m$, the basic variable is $k$-th auxiliary +variable, and if $m+1\leq k\leq m+n$, the basic variable is $(k-m)$-th +structural variable, where $m$ is the number of rows and $n$ is the +number of columns in the specified problem object. The basis +factorization must exist. + +The computed row shows how the specified basic variable depends on +non-basic variables: +$$x_k=(x_B)_i=\xi_{i1}(x_N)_1+\xi_{i2}(x_N)_2+\dots+\xi_{in}(x_N)_n,$$ +where $\xi_{i1}$, $\xi_{i2}$, \dots, $\xi_{in}$ are elements of the +simplex table row, $(x_N)_1$, $(x_N)_2$, \dots, $(x_N)_n$ are non-basic +(auxiliary and structural) variables. + +The routine stores column indices and corresponding numeric values of +non-zero elements of the computed row in unordered sparse format in +locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is +the number of non-zero elements in the row returned on exit. + +Element indices stored in the array \verb|ind| have the same sense as +index $k$, i.e. indices 1 to $m$ denote auxiliary variables while +indices $m+1$ to $m+n$ denote structural variables (all these variables +are obviously non-basic by definition). + +\returns + +The routine \verb|glp_eval_tab_row| returns \verb|len|, which is the +number of non-zero elements in the simplex table row stored in the +arrays \verb|ind| and \verb|val|. + +\para{Comments} + +A row of the simplex table is computed as follows. At first, the +routine checks that the specified variable $x_k$ is basic and uses the +permutation matrix $\Pi$ (3.7) to determine index $i$ of basic variable +$(x_B)_i$, which corresponds to $x_k$. + +The row to be computed is $i$-th row of the matrix $\Xi$ (3.12), +therefore: +$$\xi_i=e_i^T\Xi=-e_i^TB^{-1}N=-(B^{-T}e_i)^TN,$$ +where $e_i$ is $i$-th unity vector. So the routine performs BTRAN to +obtain $i$-th row of the inverse $B^{-1}$: +$$\varrho_i=B^{-T}e_i,$$ +and then computes elements of the simplex table row as inner products: +$$\xi_{ij}=-\varrho_i^TN_j,\ \ j=1,2,\dots,n,$$ +where $N_j$ is $j$-th column of matrix $N$ (3.9), which (column) +corresponds to non-basic variable $(x_N)_j$. The permutation matrix +$\Pi$ is used again to convert indices $j$ of non-basic columns to +original ordinal numbers of auxiliary and structural variables. + +\subsection{glp\_eval\_tab\_col --- compute column of the tableau} + +\synopsis + +\begin{verbatim} + int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_eval_tab_col| computes a column of the current +simplex tableau (see Subsection 3.1.1, formula (3.12)), which (column) +corresponds to some non-basic variable specified by the parameter $k$: +if $1\leq k\leq m$, the non-basic variable is $k$-th auxiliary +variable, and if $m+1\leq k\leq m+n$, the non-basic variable is +$(k-m)$-th structural variable, where $m$ is the number of rows and $n$ +is the number of columns in the specified problem object. The basis +factorization must exist. + +The computed column shows how basic variables depends on the specified +non-basic variable $x_k=(x_N)_j$: +$$ +\begin{array}{r@{\ }c@{\ }l@{\ }l} +(x_B)_1&=&\dots+\xi_{1j}(x_N)_j&+\dots\\ +(x_B)_2&=&\dots+\xi_{2j}(x_N)_j&+\dots\\ +.\ \ .&.&.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\\ +(x_B)_m&=&\dots+\xi_{mj}(x_N)_j&+\dots\\ +\end{array} +$$ +where $\xi_{1j}$, $\xi_{2j}$, \dots, $\xi_{mj}$ are elements of the +simplex table column, $(x_B)_1$, $(x_B)_2$, \dots, $(x_B)_m$ are basic +(auxiliary and structural) variables. + +The routine stores row indices and corresponding numeric values of +non-zero elements of the computed column in unordered sparse format in +locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, +\dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is +the number of non-zero elements in the column returned on exit. + +Element indices stored in the array \verb|ind| have the same sense as +index $k$, i.e. indices 1 to $m$ denote auxiliary variables while +indices $m+1$ to $m+n$ denote structural variables (all these variables +are obviously basic by definition). + +\returns + +The routine \verb|glp_eval_tab_col| returns \verb|len|, which is the +number of non-zero elements in the simplex table column stored in the +arrays \verb|ind| and \verb|val|. + +\para{Comments} + +A column of the simplex table is computed as follows. At first, the +routine checks that the specified variable $x_k$ is non-basic and uses +the permutation matrix $\Pi$ (3.7) to determine index $j$ of non-basic +variable $(x_N)_j$, which corresponds to $x_k$. + +The column to be computed is $j$-th column of the matrix $\Xi$ (3.12), +therefore: +$$\Xi_j=\Xi e_j=-B^{-1}Ne_j=-B^{-1}N_j,$$ +where $e_j$ is $j$-th unity vector, $N_j$ is $j$-th column of matrix +$N$ (3.9). So the routine performs FTRAN to transform $N_j$ to the +simplex table column $\Xi_j=(\xi_{ij})$ and uses the permutation matrix +$\Pi$ to convert row indices $i$ to original ordinal numbers of +auxiliary and structural variables. + +\newpage + +\subsection{glp\_transform\_row --- transform explicitly specified row} + +\synopsis + +\begin{verbatim} + int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_transform_row| performs the same operation as the +routine \verb|glp_eval_tab_row| with exception that the row to be +transformed is specified explicitly as a sparse vector. + +The explicitly specified row may be thought as a linear form: +$$x=a_1x_{m+1}+a_2x_{m+2}+\dots+a_nx_{m+n},$$ +where $x$ is an auxiliary variable for this row, $a_j$ are coefficients +of the linear form, $x_{m+j}$ are structural variables. + +On entry column indices and numerical values of non-zero coefficients +$a_j$ of the specified row should be placed in locations \verb|ind[1]|, +\dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, where +\verb|len| is number of non-zero coefficients. + +This routine uses the system of equality constraints and the current +basis in order to express the auxiliary variable $x$ through the current +non-basic variables (as if the transformed row were added to the problem +object and the auxiliary variable $x$ were basic), i.e. the resultant +row has the form: +$$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n,$$ +where $\xi_j$ are influence coefficients, $(x_N)_j$ are non-basic +(auxiliary and structural) variables, $n$ is the number of columns in +the problem object. + +On exit the routine stores indices and numerical values of non-zero +coefficients $\xi_j$ of the resultant row in locations \verb|ind[1]|, +\dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, +where $0\leq{\tt len'}\leq n$ is the number of non-zero coefficients in +the resultant row returned by the routine. Note that indices of +non-basic variables stored in the array \verb|ind| correspond to +original ordinal numbers of variables: indices 1 to $m$ mean auxiliary +variables and indices $m+1$ to $m+n$ mean structural ones. + +\returns + +The routine \verb|glp_transform_row| returns \verb|len'|, the number of +non-zero coefficients in the resultant row stored in the arrays +\verb|ind| and \verb|val|. + +\newpage + +\subsection{glp\_transform\_col --- transform explicitly specified +column} + +\synopsis + +\begin{verbatim} + int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +\end{verbatim} + +\description + +The routine \verb|glp_transform_col| performs the same operation as the +routine \verb|glp_eval_tab_col| with exception that the column to be +transformed is specified explicitly as a sparse vector. + +The explicitly specified column may be thought as it were added to +the original system of equality constraints: +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +x_1&=&a_{11}x_{m+1}&+\dots+&a_{1n}x_{m+n}&+&a_1x \\ +x_2&=&a_{21}x_{m+1}&+\dots+&a_{2n}x_{m+n}&+&a_2x \\ +\multicolumn{7}{c} +{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +x_m&=&a_{m1}x_{m+1}&+\dots+&a_{mn}x_{m+n}&+&a_mx \\ +\end{array} +$$ +where $x_i$ are auxiliary variables, $x_{m+j}$ are structural variables +(presented in the problem object), $x$ is a structural variable for the +explicitly specified column, $a_i$ are constraint coefficients at $x$. + +On entry row indices and numerical values of non-zero coefficients +$a_i$ of the specified column should be placed in locations +\verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, +\verb|val[len]|, where \verb|len| is number of non-zero coefficients. + +This routine uses the system of equality constraints and the current +basis in order to express the current basic variables through the +structural variable $x$ (as if the transformed column were added to the +problem object and the variable $x$ were non-basic): +$$ +\begin{array}{l@{\ }c@{\ }r} +(x_B)_1&=\dots+&\xi_{1}x\\ +(x_B)_2&=\dots+&\xi_{2}x\\ +\multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +(x_B)_m&=\dots+&\xi_{m}x\\ +\end{array} +$$ +where $\xi_i$ are influence coefficients, $x_B$ are basic (auxiliary +and structural) variables, $m$ is the number of rows in the problem +object. + +On exit the routine stores indices and numerical values of non-zero +coefficients $\xi_i$ of the resultant column in locations \verb|ind[1]|, +\dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, +where $0\leq{\tt len'}\leq m$ is the number of non-zero coefficients in +the resultant column returned by the routine. Note that indices of basic +variables stored in the array \verb|ind| correspond to original ordinal +numbers of variables, i.e. indices 1 to $m$ mean auxiliary variables, +indices $m+1$ to $m+n$ mean structural ones. + +\returns + +The routine \verb|glp_transform_col| returns \verb|len'|, the number of +non-zero coefficients in the resultant column stored in the arrays +\verb|ind| and \verb|val|. + +\newpage + +\subsection{glp\_prim\_rtest --- perform primal ratio test} + +\synopsis + +\begin{verbatim} + int glp_prim_rtest(glp_prob *P, int len, const int ind[], const double val[], + int dir, double eps); +\end{verbatim} + +\description + +The routine \verb|glp_prim_rtest| performs the primal ratio test using +an explicitly specified column of the simplex table. + +The current basic solution associated with the LP problem object must +be primal feasible. + +The explicitly specified column of the simplex table shows how the +basic variables $x_B$ depend on some non-basic variable $x$ (which is +not necessarily presented in the problem object): +$$ +\begin{array}{l@{\ }c@{\ }r} +(x_B)_1&=\dots+&\xi_{1}x\\ +(x_B)_2&=\dots+&\xi_{2}x\\ +\multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +(x_B)_m&=\dots+&\xi_{m}x\\ +\end{array} +$$ + +The column is specifed on entry to the routine in sparse format. +Ordinal numbers of basic variables $(x_B)_i$ should be placed in +locations \verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal number +1 to $m$ denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ +denote structural variables. The corresponding non-zero coefficients +$\xi_i$ should be placed in locations +\verb|val[1]|, \dots, \verb|val[len]|. The arrays \verb|ind| and +\verb|val| are not changed by the routine. + +The parameter \verb|dir| specifies direction in which the variable $x$ +changes on entering the basis: $+1$ means increasing, $-1$ means +decreasing. + +The parameter \verb|eps| is an absolute tolerance (small positive +number, say, $10^{-9}$) used by the routine to skip $\xi_i$'s whose +magnitude is less than \verb|eps|. + +The routine determines which basic variable (among those specified in +\verb|ind[1]|, \dots, \verb|ind[len]|) reaches its (lower or upper) +bound first before any other basic variables do, and which, therefore, +should leave the basis in order to keep primal feasibility. + +\returns + +The routine \verb|glp_prim_rtest| returns the index, \verb|piv|, in the +arrays \verb|ind| and \verb|val| corresponding to the pivot element +chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic +solution is primal unbounded, and therefore the choice cannot be made, +the routine returns zero. + +\para{Comments} + +If the non-basic variable $x$ is presented in the LP problem object, +the input column can be computed with the routine +\verb|glp_eval_tab_col|; otherwise, it can be computed with the routine +\verb|glp_transform_col|. + +\newpage + +\subsection{glp\_dual\_rtest --- perform dual ratio test} + +\synopsis + +\begin{verbatim} + int glp_dual_rtest(glp_prob *P, int len, const int ind[], const double val[], + int dir, double eps); +\end{verbatim} + +\description + +The routine \verb|glp_dual_rtest| performs the dual ratio test using +an explicitly specified row of the simplex table. + +The current basic solution associated with the LP problem object must +be dual feasible. + +The explicitly specified row of the simplex table is a linear form +that shows how some basic variable $x$ (which is not necessarily +presented in the problem object) depends on non-basic variables $x_N$: +$$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n.$$ + +The row is specified on entry to the routine in sparse format. Ordinal +numbers of non-basic variables $(x_N)_j$ should be placed in locations +\verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal numbers 1 to $m$ +denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ denote +structural variables. The corresponding non-zero coefficients $\xi_j$ +should be placed in locations \verb|val[1]|, \dots, \verb|val[len]|. +The arrays \verb|ind| and \verb|val| are not changed by the routine. + +The parameter \verb|dir| specifies direction in which the variable $x$ +changes on leaving the basis: $+1$ means that $x$ goes on its lower +bound, so its reduced cost (dual variable) is increasing (minimization) +or decreasing (maximization); $-1$ means that $x$ goes on its upper +bound, so its reduced cost is decreasing (minimization) or increasing +(maximization). + +The parameter \verb|eps| is an absolute tolerance (small positive +number, say, $10^{-9}$) used by the routine to skip $\xi_j$'s whose +magnitude is less than \verb|eps|. + +The routine determines which non-basic variable (among those specified +in \verb|ind[1]|, \dots,\linebreak \verb|ind[len]|) should enter the +basis in order to keep dual feasibility, because its reduced cost +reaches the (zero) bound first before this occurs for any other +non-basic variables. + +\returns + +The routine \verb|glp_dual_rtest| returns the index, \verb|piv|, in the +arrays \verb|ind| and \verb|val| corresponding to the pivot element +chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic +solution is dual unbounded, and therefore the choice cannot be made, +the routine returns zero. + +\para{Comments} + +If the basic variable $x$ is presented in the LP problem object, the +input row can be computed\linebreak with the routine +\verb|glp_eval_tab_row|; otherwise, it can be computed with the routine +\linebreak \verb|glp_transform_row|. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Post-optimal analysis routines} + +\subsection{glp\_analyze\_bound --- analyze active bound of non-basic +variable} + +\synopsis + +\begin{verbatim} + void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, + double *limit2, int *var2); +\end{verbatim} + +\description + +The routine \verb|glp_analyze_bound| analyzes the effect of varying the +active bound of specified non-basic variable. + +The non-basic variable is specified by the parameter $k$, where +$1\leq k\leq m$ means auxiliary variable of corresponding row, and +$m+1\leq k\leq m+n$ means structural variable (column). + +Note that the current basic solution must be optimal, and the basis +factorization must exist. + +Results of the analysis have the following meaning. + +\verb|value1| is the minimal value of the active bound, at which the +basis still remains primal feasible and thus optimal. \verb|-DBL_MAX| +means that the active bound has no lower limit. + +\verb|var1| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) basic variable, which reaches its bound +first and thereby limits further decreasing the active bound being +analyzed. if \verb|value1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. + +\verb|value2| is the maximal value of the active bound, at which the +basis still remains primal feasible and thus optimal. \verb|+DBL_MAX| +means that the active bound has no upper limit. + +\verb|var2| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) basic variable, which reaches its bound +first and thereby limits further increasing the active bound being +analyzed. if \verb|value2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. + +The parameters \verb|value1|, \verb|var1|, \verb|value2|, \verb|var2| +can be specified as \verb|NULL|, in which case corresponding information +is not stored. + +\subsection{glp\_analyze\_coef --- analyze objective coefficient at +basic variable} + +\synopsis + +\begin{verbatim} + void glp_analyze_coef(glp_prob *P, int k, + double *coef1, int *var1, double *value1, + double *coef2, int *var2, double *value2); +\end{verbatim} + +\description + +The routine \verb|glp_analyze_coef| analyzes the effect of varying the +objective coefficient at specified basic variable. + +The basic variable is specified by the parameter $k$, where +$1\leq k\leq m$ means auxiliary variable of corresponding row, and +$m+1\leq k\leq m+n$ means structural variable (column). + +Note that the current basic solution must be optimal, and the basis +factorization must exist. + +Results of the analysis have the following meaning. + +\verb|coef1| is the minimal value of the objective coefficient, at +which the basis still remains dual feasible and thus optimal. +\verb|-DBL_MAX| means that the objective coefficient has no lower +limit. + +\verb|var1| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost +reaches its zero bound first and thereby limits further decreasing the +objective coefficient being analyzed. +If \verb|coef1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. + +\verb|value1| is value of the basic variable being analyzed in an +adjacent basis, which is defined as follows. Let the objective +coefficient reach its minimal value (\verb|coef1|) and continue +decreasing. Then the reduced cost of the limiting non-basic variable +(\verb|var1|) becomes dual infeasible and the current basis becomes +non-optimal that forces the limiting non-basic variable to enter the +basis replacing there some basic variable that leaves the basis to keep +primal feasibility. Should note that on determining the adjacent basis +current bounds of the basic variable being analyzed are ignored as if +it were free (unbounded) variable, so it cannot leave the basis. It may +happen that no dual feasible adjacent basis exists, in which case +\verb|value1| is set to \verb|-DBL_MAX| or \verb|+DBL_MAX|. + +\verb|coef2| is the maximal value of the objective coefficient, at +which the basis still remains dual feasible and thus optimal. +\verb|+DBL_MAX| means that the objective coefficient has no upper +limit. + +\verb|var2| is the ordinal number of an auxiliary (1 to $m$) or +structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost +reaches its zero bound first and thereby limits further increasing the +objective coefficient being analyzed. +If \verb|coef2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. + +\verb|value2| is value of the basic variable being analyzed in an +adjacent basis, which is defined exactly in the same way as +\verb|value1| above with exception that now the objective coefficient +is increasing. + +The parameters \verb|coef1|, \verb|var1|, \verb|value1|, \verb|coef2|, +\verb|var2|, \verb|value2| can be specified as \verb|NULL|, in which +case corresponding information is not stored. + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk05.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk05.tex new file mode 100644 index 000000000..66e3c40a7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk05.tex @@ -0,0 +1,1098 @@ +%* glpk05.tex *% + +\chapter{Branch-and-Cut API Routines} + +\section{Introduction} + +\subsection{Using the callback routine} + +The GLPK MIP solver based on the branch-and-cut method allows the +application program to control the solution process. This is attained +by means of the user-defined callback routine, which is called by the +solver at various points of the branch-and-cut algorithm. + +The callback routine passed to the MIP solver should be written by the +user and has the following specification:\footnote{The name +{\tt foo\_bar} used here is a placeholder for the callback routine +name.} + +\begin{verbatim} + void foo_bar(glp_tree *T, void *info); +\end{verbatim} + +\noindent +where \verb|tree| is a pointer to the data structure \verb|glp_tree|, +which should be used on subsequent calls to branch-and-cut interface +routines, and \verb|info| is a transit pointer passed to the routine +\verb|glp_intopt|, which may be used by the application program to pass +some external data to the callback routine. + +The callback routine is passed to the MIP solver through the control +parameter structure \verb|glp_iocp| (see Chapter ``Basic API +Routines'', Section ``Mixed integer programming routines'', Subsection +``Solve MIP problem with the branch-and-cut method'') as follows: + +\begin{verbatim} + glp_prob *mip; + glp_iocp parm; + . . . + glp_init_iocp(&parm); + . . . + parm.cb_func = foo_bar; + parm.cb_info = ... ; + ret = glp_intopt(mip, &parm); + . . . +\end{verbatim} + +To determine why it is being called by the MIP solver the callback +routine should use the routine \verb|glp_ios_reason| (described in this +section below), which returns a code indicating the reason for calling. +Depending on the reason the callback routine may perform necessary +actions to control the solution process. + +The reason codes, which correspond to various point of the +branch-and-cut algorithm implemented in the MIP solver, are described +in Subsection ``Reasons for calling the callback routine'' below. + +To ignore calls for reasons, which are not processed by the callback +routine, it should simply return to the MIP solver doing nothing. For +example: + +\begin{verbatim} +void foo_bar(glp_tree *T, void *info) +{ . . . + switch (glp_ios_reason(T)) + { case GLP_IBRANCH: + . . . + break; + case GLP_ISELECT: + . . . + break; + default: + /* ignore call for other reasons */ + break; + } + return; +} +\end{verbatim} + +To control the solution process as well as to obtain necessary +information the callback routine may use the branch-and-cut API +routines described in this chapter. Names of all these routines begin +with `\verb|glp_ios_|'. + +\subsection{Branch-and-cut algorithm} + +This section gives a schematic description of the branch-and-cut +algorithm as it is implemented in the GLPK MIP solver. + +{\it 1. Initialization} + +Set $L:=\{P_0\}$, where $L$ is the {\it active list} (i.e. the list of +active subproblems), $P_0$ is the original MIP problem to be solved. + +Set $z^{\it best}:=+\infty$ (in case of minimization) or +$z^{\it best}:=-\infty$ (in case of maximization), where $z^{\it best}$ +is {\it incumbent value}, i.e. an upper (minimization) or lower +(maximization) global bound for $z^{\it opt}$, the optimal objective +value for $P^0$. + +{\it 2. Subproblem selection} + +If $L=\varnothing$ then GO TO 9. + +Select $P\in L$, i.e. make active subproblem $P$ current. + +%\newpage + +{\it 3. Solving LP relaxation} + +Solve $P^{\it LP}$, which is LP relaxation of $P$. + +If $P^{\it LP}$ has no primal feasible solution then GO TO 8. + +Let $z^{\it LP}$ be the optimal objective value for $P^{\it LP}$. + +If $z^{\it LP}\geq z^{\it best}$ (minimization) or +$z^{\it LP}\leq z^{\rm best}$ (), GO TO 8. + +{\it 4. Adding ``lazy'' constraints} + +Let $x^{\it LP}$ be the optimal solution to $P^{\it LP}$. + +If there are ``lazy'' constraints (i.e. essential constraints not +included in the original MIP problem $P_0$), which are violated at the +optimal point $x^{\it LP}$, add them to $P$, and GO TO 3. + +{\it 5. Check for integrality} + +Let $x_j$ be a variable, which is required to be integer, and let +$x^{\it LP}_j\in x^{\it LP}$ be its value in the optimal solution to +$P^{\it LP}$. + +If $x^{\it LP}_j$ are integral for all integer variables, then a better +integer feasible solution is found. Store its components, set +$z^{\it best}:=z^{\it LP}$, and GO TO 8. + +{\it 6. Adding cutting planes} + +If there are cutting planes (i.e. valid constraints for $P$), +which are violated at the optimal point $x^{\it LP}$, add them to $P$, +and GO TO 3. + +{\it 7. Branching} + +Select {\it branching variable} $x_j$, i.e. a variable, which is +required to be integer, and whose value $x^{\it LP}_j\in x^{\it LP}$ is +fractional in the optimal solution to $P^{\it LP}$. + +Create new subproblem $P^D$ (so called {\it down branch}), which is +identical to the current subproblem $P$ with exception that the upper +bound of $x_j$ is replaced by $\lfloor x^{\it LP}_j\rfloor$. (For +example, if $x^{\it LP}_j=3.14$, the new upper bound of $x_j$ in the +down branch will be $\lfloor 3.14\rfloor=3$.) + +Create new subproblem $P^U$ (so called {\it up branch}), which is +identical to the current subproblem $P$ with exception that the lower +bound of $x_j$ is replaced by $\lceil x^{\it LP}_j\rceil$. (For example, +if $x^{\it LP}_j=3.14$, the new lower bound of $x_j$ in the up branch +will be $\lceil 3.14\rceil=4$.) + +Set $L:=(L\backslash\{P\})\cup\{P^D,P^U\}$, i.e. remove the current +subproblem $P$ from the active list $L$ and add two new subproblems +$P^D$ and $P^U$ to it. Then GO TO 2. + +{\it 8. Pruning} + +Remove from the active list $L$ all subproblems (including the current +one), whose local bound $\widetilde{z}$ is not better than the global +bound $z^{\it best}$, i.e. set $L:=L\backslash\{P\}$ for all $P$, where +$\widetilde{z}\geq z^{\it best}$ (in case of minimization) or +$\widetilde{z}\leq z^{\it best}$ (in case of maximization), and then +GO TO 2. + +The local bound $\widetilde{z}$ for subproblem $P$ is an lower +(minimization) or upper (maximization) bound for integer optimal +solution to {\it this} subproblem (not to the original problem). This +bound is local in the sense that only subproblems in the subtree rooted +at node $P$ cannot have better integer feasible solutions. Note that +the local bound is not necessarily the optimal objective value to LP +relaxation $P^{\it LP}$. + +{\it 9. Termination} + +If $z^{\it best}=+\infty$ (in case of minimization) or +$z^{\it best}=-\infty$ (in case of maximization), the original problem +$P_0$ has no integer feasible solution. Otherwise, the last integer +feasible solution stored on step 5 is the integer optimal solution to +the original problem $P_0$ with $z^{\it opt}=z^{\it best}$. STOP. + +\subsection{The search tree} + +On the branching step of the branch-and-cut algorithm the current +subproblem is divided into two\footnote{In more general cases the +current subproblem may be divided into more than two subproblems. +However, currently such feature is not used in GLPK.} new subproblems, +so the set of all subproblems can be represented in the form of a rooted +tree, which is called the {\it search} or {\it branch-and-bound} tree. +An example of the search tree is shown on Fig.~1. Each node of the +search tree corresponds to a subproblem, so the terms `node' and +`subproblem' may be used synonymously. + +\begin{figure}[t] +\noindent\hfil +\xymatrix @R=20pt @C=10pt +{&&&&&&*+<14pt>[o][F=]{A}\ar@{-}[dllll]\ar@{-}[dr]\ar@{-}[drrrr]&&&&\\ +&&*+<14pt>[o][F=]{B}\ar@{-}[dl]\ar@{-}[dr]&&&&&*+<14pt>[o][F=]{C} +\ar@{-}[dll]\ar@{-}[dr]\ar@{-}[drrr]&&&*+<14pt>[o][F-]{\times}\\ +&*+<14pt>[o][F-]{\times}\ar@{-}[dl]\ar@{-}[d]\ar@{-}[dr]&& +*+<14pt>[o][F-]{D}&&*+<14pt>[o][F=]{E}\ar@{-}[dl]\ar@{-}[dr]&&& +*+<14pt>[o][F=]{F}\ar@{-}[dl]\ar@{-}[dr]&&*+<14pt>[o][F-]{G}\\ +*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times} +&&*+<14pt>[][F-]{H}&&*+<14pt>[o][F-]{I}&*+<14pt>[o][F-]{\times}&& +*+<14pt>[o][F-]{J}&\\} + +\bigskip + +\noindent\hspace{.8in} +\xymatrix @R=11pt +{*+<20pt>[][F-]{}&*\txt{\makebox[1in][l]{Current}}&& +*+<20pt>[o][F-]{}&*\txt{\makebox[1in][l]{Active}}\\ +*+<20pt>[o][F=]{}&*\txt{\makebox[1in][l]{Non-active}}&& +*+<14pt>[o][F-]{\times}&*\txt{\makebox[1in][l]{Fathomed}}\\ +} + +\bigskip + +\begin{center} +Fig. 1. An example of the search tree. +\end{center} +\end{figure} + +In GLPK each node may have one of the following four statuses: + +%\vspace*{-8pt} + +%\begin{itemize} +\Item{---}{\it current node} is the active node currently being +processed; + +\Item{---}{\it active node} is a leaf node, which still has to be +processed; + +\Item{---}{\it non-active node} is a node, which has been processed, +but not fathomed; + +\Item{---}{\it fathomed node} is a node, which has been processed and +fathomed. +%\end{itemize} + +%\vspace*{-8pt} + +In the data structure representing the search tree GLPK keeps only +current, active, and non-active nodes. Once a node has been fathomed, +it is removed from the tree data structure. + +Being created each node of the search tree is assigned a distinct +positive integer called the {\it subproblem reference number}, which +may be used by the application program to specify a particular node of +the tree. The root node corresponding to the original problem to be +solved is always assigned the reference number 1. + +\subsection{Current subproblem} + +The current subproblem is a MIP problem corresponding to the current +node of the search tree. It is represented as the GLPK problem object +(\verb|glp_prob|) that allows the application program using API +routines to access its content in the standard way. If the MIP +presolver is not used, it is the original problem object passed to the +routine \verb|glp_intopt|; otherwise, it is an internal problem object +built by the MIP presolver. + +Note that the problem object is used by the MIP solver itself during +the solution process for various purposes (to solve LP relaxations, to +perfom branching, etc.), and even if the MIP presolver is not used, the +current content of the problem object may differ from its original +content. For example, it may have additional rows, bounds of some rows +and columns may be changed, etc. In particular, LP segment of the +problem object corresponds to LP relaxation of the current subproblem. +However, on exit from the MIP solver the content of the problem object +is restored to its original state. + +To obtain information from the problem object the application program +may use any API routines, which do not change the object. Using API +routines, which change the problem object, is restricted to stipulated +cases. + +\subsection{The cut pool} + +The {\it cut pool} is a set of cutting plane constraints maintained by +the MIP solver. It is used by the GLPK cut generation routines and may +be used by the application program in the same way, i.e. rather than +to add cutting plane constraints directly to the problem object the +application program may store them to the cut pool. In the latter case +the solver looks through the cut pool, selects efficient constraints, +and adds them to the problem object. + +\subsection{Reasons for calling the callback routine} + +The callback routine may be called by the MIP solver for the following +reasons. + +\para{Request for subproblem selection} + +The callback routine is called with the reason code \verb|GLP_ISELECT| +if the current subproblem has been fathomed and therefore there is no +current subproblem. + +In response the callback routine may select some subproblem from the +active list and pass its reference number to the solver using the +routine \verb|glp_ios_select_node|, in which case the solver continues +the search from the specified active subproblem. If no selection is +made by the callback routine, the solver uses a backtracking technique +specified by the control parameter \verb|bt_tech|. + +To explore the active list (i.e. active nodes of the branch-and-bound +tree) the callback routine may use the routines \verb|glp_ios_next_node| +and \verb|glp_ios_prev_node|. + +\para{Request for preprocessing} + +The callback routine is called with the reason code \verb|GLP_IPREPRO| +if the current subproblem has just been selected from the active list +and its LP relaxation is not solved yet. + +In response the callback routine may perform some preprocessing of the +current subproblem like tightening bounds of some variables or removing +bounds of some redundant constraints. + +\para{Request for row generation} + +The callback routine is called with the reason code \verb|GLP_IROWGEN| +if LP relaxation of the current subproblem has just been solved to +optimality and its objective value is better than the best known +integer feasible solution. + +In response the callback routine may add one or more ``lazy'' +constraints (rows), which are violated by the current optimal solution +of LP relaxation, using API routines \verb|glp_add_rows|, +\verb|glp_set_row_name|, \verb|glp_set_row_bnds|, and +\verb|glp_set_mat_row|, in which case the solver will perform +re-optimization of LP relaxation. If there are no violated constraints, +the callback routine should just return. + +Note that components of optimal solution to LP relaxation can be +obtained with API\linebreak routines \verb|glp_get_obj_val|, +\verb|glp_get_row_prim|, \verb|glp_get_row_dual|, +\verb|glp_get_col_prim|, and\linebreak \verb|glp_get_col_dual|. + +\para{Request for heuristic solution} + +The callback routine is called with the reason code \verb|GLP_IHEUR| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may try applying a primal heuristic +to find an integer feasible solution,\footnote{Integer feasible to the +original MIP problem, not to the current subproblem.} which is better +than the best known one. In case of success the callback routine may +store such better solution in the problem object using the routine +\verb|glp_ios_heur_sol|. + +\para{Request for cut generation} + +The callback routine is called with the reason code \verb|GLP_ICUTGEN| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may reformulate the {\it current} +subproblem (before it will be splitted up due to branching) by adding +to the problem object one or more {\it cutting plane constraints}, +which cut off the fractional optimal point from the MIP +polytope.\footnote{Since these constraints are added to the current +subproblem, they may be globally as well as locally valid.} + +Adding cutting plane constraints may be performed in two ways. +One way is the same as for the reason code \verb|GLP_IROWGEN| (see +above), in which case the callback routine adds new rows corresponding +to cutting plane constraints directly to the current subproblem. + +The other way is to add cutting plane constraints to the +{\it cut pool}, a set of cutting plane constraints maintained by the +solver, rather than directly to the current subproblem. In this case +after return from the callback routine the solver looks through the +cut pool, selects efficient cutting plane constraints, adds them to the +current subproblem, drops other constraints, and then performs +re-optimization. + +\para{Request for branching} + +The callback routine is called with the reason code \verb|GLP_IBRANCH| +if LP relaxation of the current subproblem being solved to optimality +is integer infeasible (i.e. values of some structural variables of +integer kind are fractional), though its objective value is better than +the best known integer feasible solution. + +In response the callback routine may choose some variable suitable for +branching (i.e. integer variable, whose value in optimal solution to +LP relaxation of the current subproblem is fractional) and pass its +ordinal number to the solver using the routine +\verb|glp_ios_branch_upon|, in which case the solver splits the current +subproblem in two new subproblems and continues the search. +If no choice is made by the callback routine, the solver uses +a branching technique specified by the control parameter \verb|br_tech|. + +\para{Better integer solution found} + +The callback routine is called with the reason code \verb|GLP_IBINGO| +if LP relaxation of the current subproblem being solved to optimality +is integer feasible (i.e. values of all structural variables of integer +kind are integral within the working precision) and its objective value +is better than the best known integer feasible solution. + +Optimal solution components for LP relaxation can be obtained in the +same way as for the reason code \verb|GLP_IROWGEN| (see above). + +Components of the new MIP solution can be obtained with API routines +\verb|glp_mip_obj_val|, \verb|glp_mip_row_val|, and +\verb|glp_mip_col_val|. Note, however, that due to row/cut generation +there may be additional rows in the problem object. + +The difference between optimal solution to LP relaxation and +corresponding MIP solution is that in the former case some structural +variables of integer kind (namely, basic variables) may have values, +which are close to nearest integers within the working precision, while +in the latter case all such variables have exact integral values. + +The reason \verb|GLP_IBINGO| is intended only for informational +purposes, so the callback routine should not modify the problem object +in this case. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Basic routines} + +\subsection{glp\_ios\_reason --- determine reason for calling the +callback routine} + +\synopsis + +\begin{verbatim} + int glp_ios_reason(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_reason| returns a code, which indicates why +the user-defined callback routine is being called: + +\verb|GLP_ISELECT| --- request for subproblem selection; + +\verb|GLP_IPREPRO| --- request for preprocessing; + +\verb|GLP_IROWGEN| --- request for row generation; + +\verb|GLP_IHEUR | --- request for heuristic solution; + +\verb|GLP_ICUTGEN| --- request for cut generation; + +\verb|GLP_IBRANCH| --- request for branching; + +\verb|GLP_IBINGO | --- better integer solution found. + +\subsection{glp\_ios\_get\_prob --- access the problem object} + +\synopsis + +\begin{verbatim} + glp_prob *glp_ios_get_prob(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_get_prob| can be called from the user-defined +callback routine to access the problem object, which is used by the MIP +solver. It is the original problem object passed to the routine +\verb|glp_intopt| if the MIP presolver is not used; otherwise it is an +internal problem object built by the presolver. + +\returns + +The routine \verb|glp_ios_get_prob| returns a pointer to the problem +object used by the MIP solver. + +\para{Comments} + +To obtain various information about the problem instance the callback +routine can access the problem object (i.e. the object of type +\verb|glp_prob|) using the routine \verb|glp_ios_get_prob|. It is the +original problem object passed to the routine \verb|glp_intopt| if the +MIP presolver is not used; otherwise it is an internal problem object +built by the presolver. + +\newpage + +\subsection{glp\_ios\_row\_attr --- determine additional row +attributes} + +\synopsis + +\begin{verbatim} + void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); +\end{verbatim} + +\description + +The routine \verb|glp_ios_row_attr| retrieves additional attributes of +$i$-th row of the current subproblem and stores them in the structure +\verb|glp_attr|, which the parameter \verb|attr| points to. + +The structure \verb|glp_attr| has the following fields: + +\medskip + +{\tt int level} + +Subproblem level at which the row was created. (If \verb|level| = 0, +the row was added either to the original problem object passed to the +routine \verb|glp_intopt| or to the root subproblem on generating +``lazy'' or/and cutting plane constraints.) + +\medskip + +{\tt int origin} + +The row origin flag: + +\verb|GLP_RF_REG | --- regular constraint; + +\verb|GLP_RF_LAZY| --- ``lazy'' constraint; + +\verb|GLP_RF_CUT | --- cutting plane constraint. + +\medskip + +{\tt int klass} + +The row class descriptor, which is a number passed to the routine +\verb|glp_ios_add_row| as its third parameter. If the row is a cutting +plane constraint generated by the solver, its class may be the +following: + +\verb|GLP_RF_GMI | --- Gomory's mixed integer cut; + +\verb|GLP_RF_MIR | --- mixed integer rounding cut; + +\verb|GLP_RF_COV | --- mixed cover cut; + +\verb|GLP_RF_CLQ | --- clique cut. + +\subsection{glp\_ios\_mip\_gap --- compute relative MIP gap} + +\synopsis + +\begin{verbatim} + double glp_ios_mip_gap(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_mip_gap| computes the relative MIP gap (also +called {\it duality gap}) with the following formula: +$${\tt gap} = \frac{|{\tt best\_mip} - {\tt best\_bnd}|} +{|{\tt best\_mip}| + {\tt DBL\_EPSILON}}$$ +where \verb|best_mip| is the best integer feasible solution found so +far, \verb|best_bnd| is the best (global) bound. If no integer feasible +solution has been found yet, \verb|gap| is set to \verb|DBL_MAX|. + +\newpage + +\returns + +The routine \verb|glp_ios_mip_gap| returns the relative MIP gap. + +\para{Comments} + +The relative MIP gap is used to measure the quality of the best integer +feasible solution found so far, because the optimal solution value +$z^*$ for the original MIP problem always lies in the range +$${\tt best\_bnd}\leq z^*\leq{\tt best\_mip}$$ +in case of minimization, or in the range +$${\tt best\_mip}\leq z^*\leq{\tt best\_bnd}$$ +in case of maximization. + +To express the relative MIP gap in percents the value returned by the +routine \verb|glp_ios_mip_gap| should be multiplied by 100\%. + +\subsection{glp\_ios\_node\_data --- access application-specific data} + +\synopsis + +\begin{verbatim} + void *glp_ios_node_data(glp_tree *T, int p); +\end{verbatim} + +\description + +The routine \verb|glp_ios_node_data| allows the application accessing +a memory block allocated for the subproblem (which may be active or +inactive), whose reference number is $p$. + +The size of the block is defined by the control parameter +\verb|cb_size| passed to the routine \verb|glp_intopt|. The block is +initialized by binary zeros on creating corresponding subproblem, and +its contents is kept until the subproblem will be removed from the +tree. + +The application may use these memory blocks to store specific data for +each subproblem. + +\returns + +The routine \verb|glp_ios_node_data| returns a pointer to the memory +block for the specified subproblem. Note that if \verb|cb_size| = 0, +the routine returns a null pointer. + +\subsection{glp\_ios\_select\_node --- select subproblem to continue +the search} + +\synopsis + +\begin{verbatim} + void glp_ios_select_node(glp_tree *T, int p); +\end{verbatim} + +\description + +The routine \verb|glp_ios_select_node| can be called from the +user-defined callback routine in response to the reason +\verb|GLP_ISELECT| to select an active subproblem, whose reference +number\linebreak is $p$. The search will be continued from the +subproblem selected. + +\newpage + +\subsection{glp\_ios\_heur\_sol --- provide solution found by +heuristic} + +\synopsis + +\begin{verbatim} + int glp_ios_heur_sol(glp_tree *T, const double x[]); +\end{verbatim} + +\description + +The routine \verb|glp_ios_heur_sol| can be called from the user-defined +callback routine in response to the reason \verb|GLP_IHEUR| to provide +an integer feasible solution found by a primal heuristic. + +Primal values of {\it all} variables (columns) found by the heuristic +should be placed in locations $x[1]$, \dots, $x[n]$, where $n$ is the +number of columns in the original problem object. Note that the routine +\verb|glp_ios_heur_sol| does {\it not} check primal feasibility of the +solution provided. + +Using the solution passed in the array $x$ the routine computes value +of the objective function. If the objective value is better than the +best known integer feasible solution, the routine computes values of +auxiliary variables (rows) and stores all solution components in the +problem object. + +\returns + +If the provided solution is accepted, the routine +\verb|glp_ios_heur_sol| returns zero. Otherwise, if the provided +solution is rejected, the routine returns non-zero. + +\vspace*{-5pt} + +\subsection{glp\_ios\_can\_branch --- check if can branch upon +specified variable} + +\synopsis + +\begin{verbatim} + int glp_ios_can_branch(glp_tree *T, int j); +\end{verbatim} + +\returns + +If $j$-th variable (column) can be used to branch upon, the routine +returns non-zero, otherwise zero. + +\vspace*{-5pt} + +\subsection{glp\_ios\_branch\_upon --- choose variable to branch upon} + +\synopsis + +\begin{verbatim} + void glp_ios_branch_upon(glp_tree *T, int j, int sel); +\end{verbatim} + +\description + +The routine \verb|glp_ios_branch_upon| can be called from the +user-defined callback routine in response to the reason +\verb|GLP_IBRANCH| to choose a branching variable, whose ordinal number +\linebreak is $j$. Should note that only variables, for which the +routine \verb|glp_ios_can_branch| returns non-zero, can be used to +branch upon. + +The parameter \verb|sel| is a flag that indicates which branch +(subproblem) should be selected next to continue the search: + +\verb|GLP_DN_BRNCH| --- select down-branch; + +\verb|GLP_UP_BRNCH| --- select up-branch; + +\verb|GLP_NO_BRNCH| --- use general selection technique. + +\newpage + +\para{Comments} + +On branching the solver removes the current active subproblem from the +active list and creates two new subproblems ({\it down-} and {\it +up-branches}), which are added to the end of the active list. Note that +the down-branch is created before the up-branch, so the last active +subproblem will be the up-branch. + +The down- and up-branches are identical to the current subproblem with +exception that in the down-branch the upper bound of $x_j$, the variable +chosen to branch upon, is replaced by $\lfloor x_j^*\rfloor$, while in +the up-branch the lower bound of $x_j$ is replaced by +$\lceil x_j^*\rceil$, where $x_j^*$ is the value of $x_j$ in optimal +solution to LP relaxation of the current subproblem. For example, if +$x_j^*=3.14$, the new upper bound of $x_j$ in the down-branch is +$\lfloor 3.14\rfloor=3$, and the new lower bound in the up-branch is +$\lceil 3.14\rceil=4$.) + +Additionally the callback routine may select either down- or up-branch, +from which the solver will continue the search. If none of the branches +is selected, a general selection technique will be used. + +\subsection{glp\_ios\_terminate --- terminate the solution process} + +\synopsis + +\begin{verbatim} + void glp_ios_terminate(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_terminate| sets a flag indicating that the +MIP solver should prematurely terminate the search. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{The search tree exploring routines} + +\subsection{glp\_ios\_tree\_size --- determine size of the search tree} + +\synopsis + +\begin{verbatim} + void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, int *t_cnt); +\end{verbatim} + +\description + +The routine \verb|glp_ios_tree_size| stores the following three counts +which characterize the current size of the search tree: + +\verb|a_cnt| is the current number of active nodes, i.e. the current +size of the active list; + +\verb|n_cnt| is the current number of all (active and inactive) nodes; + +\verb|t_cnt| is the total number of nodes including those which have +been already removed from the tree. This count is increased whenever +a new node appears in the tree and never decreased. + +If some of the parameters \verb|a_cnt|, \verb|n_cnt|, \verb|t_cnt| is +a null pointer, the corresponding count is not stored. + +\subsection{glp\_ios\_curr\_node --- determine current active +subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_curr_node(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_curr_node| returns the reference number of +the current active subproblem. However, if the current subproblem does +not exist, the routine returns zero. + +\subsection{glp\_ios\_next\_node --- determine next active subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_next_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +If the parameter $p$ is zero, the routine \verb|glp_ios_next_node| +returns the reference number of the first active subproblem. However, +if the tree is empty, zero is returned. + +If the parameter $p$ is not zero, it must specify the reference number +of some active subproblem, in which case the routine returns the +reference number of the next active subproblem. However, if there is +no next active subproblem in the list, zero is returned. + +All subproblems in the active list are ordered chronologically, i.e. +subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. + +\newpage + +\subsection{glp\_ios\_prev\_node --- determine previous active +subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_prev_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +If the parameter $p$ is zero, the routine \verb|glp_ios_prev_node| +returns the reference number of the last active subproblem. However, if +the tree is empty, zero is returned. + +If the parameter $p$ is not zero, it must specify the reference number +of some active subproblem, in which case the routine returns the +reference number of the previous active subproblem. However, if there +is no previous active subproblem in the list, zero is returned. + +All subproblems in the active list are ordered chronologically, i.e. +subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. + +\subsection{glp\_ios\_up\_node --- determine parent subproblem} + +\synopsis + +\begin{verbatim} + int glp_ios_up_node(glp_tree *T, int p); +\end{verbatim} + +\returns + +The parameter $p$ must specify the reference number of some (active or +inactive) subproblem, in which case the routine \verb|iet_get_up_node| +returns the reference number of its parent subproblem. However, if the +specified subproblem is the root of the tree and, therefore, has +no parent, the routine returns zero. + +\subsection{glp\_ios\_node\_level --- determine subproblem level} + +\synopsis + +\begin{verbatim} + int glp_ios_node_level(glp_tree *T, int p); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_node_level| returns the level of the +subproblem, whose reference number is $p$, in the branch-and-bound +tree. (The root subproblem has level 0, and the level of any other +subproblem is the level of its parent plus one.) + +\subsection{glp\_ios\_node\_bound --- determine subproblem local bound} + +\synopsis + +\begin{verbatim} + double glp_ios_node_bound(glp_tree *T, int p); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_node_bound| returns the local bound for +(active or inactive) subproblem, whose reference number is $p$. + +\newpage + +\para{Comments} + +The local bound for subproblem $p$ is an lower (minimization) or upper +(maximization) bound for integer optimal solution to {\it this} +subproblem (not to the original problem). This bound is local in the +sense that only subproblems in the subtree rooted at node $p$ cannot +have better integer feasible solutions. + +On creating a subproblem (due to the branching step) its local bound is +inherited from its parent and then may get only stronger (never weaker). +For the root subproblem its local bound is initially set to +\verb|-DBL_MAX| (minimization) or \verb|+DBL_MAX| (maximization) and +then improved as the root LP relaxation has been solved. + +Note that the local bound is not necessarily the optimal objective +value to corresponding LP relaxation. + +\subsection{glp\_ios\_best\_node --- find active subproblem with best +local bound} + +\synopsis + +\begin{verbatim} + int glp_ios_best_node(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_best_node| returns the reference number of +the active subproblem, whose local bound is best (i.e. smallest in case +of minimization or largest in case of maximization). However, if the +tree is empty, the routine returns zero. + +\para{Comments} + +The best local bound is an lower (minimization) or upper (maximization) +bound for integer optimal solution to the original MIP problem. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{The cut pool routines} + +\subsection{glp\_ios\_pool\_size --- determine current size of the cut +pool} + +\synopsis + +\begin{verbatim} + int glp_ios_pool_size(glp_tree *T); +\end{verbatim} + +\returns + +The routine \verb|glp_ios_pool_size| returns the current size of the +cut pool, that is, the number of cutting plane constraints currently +added to it. + +\subsection{glp\_ios\_add\_row --- add constraint to the cut pool} + +\synopsis + +\begin{verbatim} + int glp_ios_add_row(glp_tree *T, const char *name, int klass, int flags, + int len, const int ind[], const double val[], int type, double rhs); +\end{verbatim} + +\description + +The routine \verb|glp_ios_add_row| adds specified row (cutting plane +constraint) to the cut pool. + +The cutting plane constraint should have the following format: +$$\sum_{j\in J}a_jx_j\left\{\begin{array}{@{}c@{}}\geq\\\leq\\ +\end{array}\right\}b,$$ +where $J$ is a set of indices (ordinal numbers) of structural +variables, $a_j$ are constraint coefficients, $x_j$ are structural +variables, $b$ is the right-hand side. + +The parameter \verb|name| specifies a symbolic name assigned to the +constraint (1 up to 255 characters). If it is \verb|NULL| or an empty +string, no name is assigned. + +The parameter \verb|klass| specifies the constraint class, which must +be either zero or a number in the range from 101 to 200. +The application may use this attribute to distinguish between cutting +plane constraints of different classes.\footnote{Constraint classes +numbered from 1 to 100 are reserved for GLPK cutting plane generators.} + +The parameter \verb|flags| currently is not used and must be zero. + +Ordinal numbers of structural variables (i.e. column indices) $j\in J$ +and numerical values of corresponding constraint coefficients $a_j$ +should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and +\verb|val[1]|, \dots, \verb|val[len]|, respectively, where +${\tt len}=|J|$ is the number of constraint coefficients, +$0\leq{\tt len}\leq n$, and $n$ is the number of columns in the problem +object. Coefficients with identical column indices are not allowed. +Zero coefficients are allowed, however, they are ignored. + +The parameter \verb|type| specifies the constraint type as follows: + +\verb|GLP_LO| means inequality constraint $\Sigma a_jx_j\geq b$; + +\verb|GLP_UP| means inequality constraint $\Sigma a_jx_j\leq b$; + +\newpage + +The parameter \verb|rhs| specifies the right-hand side $b$. + +All cutting plane constraints in the cut pool are identified by their +ordinal numbers 1, 2, \dots, $size$, where $size$ is the current size +of the cut pool. New constraints are always added to the end of the cut +pool, thus, ordinal numbers of previously added constraints are not +changed. + +\returns + +The routine \verb|glp_ios_add_row| returns the ordinal number of the +cutting plane constraint added, which is the new size of the cut pool. + +\para{Example} + +\begin{verbatim} +/* generate triangle cutting plane: + x[i] + x[j] + x[k] <= 1 */ +. . . +/* add the constraint to the cut pool */ +ind[1] = i, val[1] = 1.0; +ind[2] = j, val[2] = 1.0; +ind[3] = k, val[3] = 1.0; +glp_ios_add_row(tree, NULL, TRIANGLE_CUT, 0, 3, ind, val, GLP_UP, 1.0); +\end{verbatim} + +\para{Comments} + +Cutting plane constraints added to the cut pool are intended to be then +added only to the {\it current} subproblem, so these constraints can be +globally as well as locally valid. However, adding a constraint to the +cut pool does not mean that it will be added to the current +subproblem---it depends on the solver's decision: if the constraint +seems to be efficient, it is moved from the pool to the current +subproblem, otherwise it is simply dropped.\footnote{Globally valid +constraints could be saved and then re-used for other subproblems, but +currently such feature is not implemented.} + +Normally, every time the callback routine is called for cut generation, +the cut pool is empty. On the other hand, the solver itself can +generate cutting plane constraints (like Gomory's or mixed integer +rounding cuts), in which case the cut pool may be non-empty. + +\subsection{glp\_ios\_del\_row --- remove constraint from the cut pool} + +\synopsis + +\begin{verbatim} + void glp_ios_del_row(glp_tree *T, int i); +\end{verbatim} + +\description + +The routine \verb|glp_ios_del_row| deletes $i$-th row (cutting plane +constraint) from the cut pool, where $1\leq i\leq size$ is the ordinal +number of the constraint in the pool, $size$ is the current size of the +cut pool. + +Note that deleting a constraint from the cut pool leads to changing +ordinal numbers of other constraints remaining in the pool. New ordinal +numbers of the remaining constraints are assigned under assumption that +the original order of constraints is not changed. Let, for example, +there be four constraints $a$, $b$, $c$ and $d$ in the cut pool, which +have ordinal numbers 1, 2, 3 and 4, respectively, and let constraint +$b$ have been deleted. Then after deletion the remaining constraint $a$, +$c$ and $d$ are assigned new ordinal numbers 1, 2 and 3, respectively. + +To find the constraint to be deleted the routine \verb|glp_ios_del_row| +uses ``smart'' linear search, so it is recommended to remove +constraints in a natural or reverse order and avoid removing them in +a random order. + +\para{Example} + +\begin{verbatim} +/* keep first 10 constraints in the cut pool and remove other + constraints */ +while (glp_ios_pool_size(tree) > 10) + glp_ios_del_row(tree, glp_ios_pool_size(tree)); +\end{verbatim} + +\subsection{glp\_ios\_clear\_pool --- remove all constraints from the +cut pool} + +\synopsis + +\begin{verbatim} + void glp_ios_clear_pool(glp_tree *T); +\end{verbatim} + +\description + +The routine \verb|glp_ios_clear_pool| makes the cut pool empty deleting +all existing rows (cutting plane constraints) from it. + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk06.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk06.tex new file mode 100644 index 000000000..51bec189b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk06.tex @@ -0,0 +1,464 @@ +%* glpk06.tex *% + +\chapter{Miscellaneous API Routines} + +\section{GLPK environment routines} + +\subsection{glp\_init\_env --- initialize GLPK environment} + +\synopsis + +\begin{verbatim} + int glp_init_env(void); +\end{verbatim} + +\description + +The routine \verb|glp_init_env| initializes the GLPK environment. +Normally the application program does not need to call this routine, +because it is called automatically on the first call to any API +routine. + +\returns + +\begin{retlist} +0 & initialization successful;\\ +1 & environment is already initialized;\\ +2 & initialization failed (insufficient memory);\\ +3 & initialization failed (unsupported programming model).\\ +\end{retlist} + +\subsection{glp\_version --- determine library version} + +\synopsis + +\begin{verbatim} + const char *glp_version(void); +\end{verbatim} + +\returns + +The routine \verb|glp_version| returns a pointer to a null-terminated +character string, which specifies the version of the GLPK library in +the form \verb|"X.Y"|, where `\verb|X|' is the major version number, +and `\verb|Y|' is the minor version number, for example, \verb|"4.16"|. + +\newpage + +\subsection{glp\_free\_env --- free GLPK environment} + +\synopsis + +\begin{verbatim} + int glp_free_env(void); +\end{verbatim} + +\description + +The routine \verb|glp_free_env| frees all resources used by GLPK +routines (memory blocks, etc.) which are currently still in use. + +Normally the application program does not need to call this routine, +because GLPK routines always free all unused resources. However, if +the application program even has deleted all problem objects, there +will be several memory blocks still allocated for the internal library +needs. For some reasons the application program may want GLPK to free +this memory, in which case it should call \verb|glp_free_env|. + +Note that a call to \verb|glp_free_env| invalidates all problem objects +which still exist. + +\returns + +\begin{retlist} +0 & termination successful;\\ +1 & environment is inactive (was not initialized).\\ +\end{retlist} + +\subsection{glp\_printf --- write formatted output to terminal} + +\synopsis + +\begin{verbatim} + void glp_printf(const char *fmt, ...); +\end{verbatim} + +\description + +The routine \verb|glp_printf| uses the format control string +\verb|fmt| to format its parameters and writes the formatted output to +the terminal. + +This routine is a replacement of the standard C function +\verb|printf| and used by all GLPK routines to perform terminal +output. The application program may use \verb|glp_printf| for the same +purpose that allows controlling its terminal output with the routines +\verb|glp_term_out| and \verb|glp_term_hook|. + +\subsection{glp\_vprintf --- write formatted output to terminal} + +\synopsis + +\begin{verbatim} + void glp_vprintf(const char *fmt, va_list arg); +\end{verbatim} + +\description + +The routine \verb|glp_vprintf| uses the format control string +\verb|fmt| to format its parameters specified by the list \verb|arg| +and writes the formatted output to the terminal. + +This routine is a replacement of the standard C function +\verb|vprintf| and used by all GLPK routines to perform terminal +output. The application program may use \verb|glp_vprintf| for the same +purpose that allows controlling its terminal output with the routines +\verb|glp_term_out| and \verb|glp_term_hook|. + +\newpage + +\subsection{glp\_term\_out --- enable/disable terminal output} + +\synopsis + +\begin{verbatim} + int glp_term_out(int flag); +\end{verbatim} + +\description + +Depending on the parameter flag the routine \verb|glp_term_out| enables +or disables terminal output performed by glpk routines: + +\verb|GLP_ON | --- enable terminal output; + +\verb|GLP_OFF| --- disable terminal output. + +\returns + +The routine \verb|glp_term_out| returns the previous value of the +terminal output flag. + +\subsection{glp\_term\_hook --- intercept terminal output} + +\synopsis + +\begin{verbatim} + void glp_term_hook(int (*func)(void *info, const char *s), void *info); +\end{verbatim} + +\description + +The routine \verb|glp_term_hook| installs the user-defined hook routine +to intercept all terminal output performed by GLPK routines. + +%This feature can be used to redirect the terminal output to other +%destination, for example, to a file or a text window. + +The parameter {\it func} specifies the user-defined hook routine. It is +called from an internal printing routine, which passes to it two +parameters: {\it info} and {\it s}. The parameter {\it info} is a +transit pointer specified in corresponding call to the routine +\verb|glp_term_hook|; it may be used to pass some additional information +to the hook routine. The parameter {\it s} is a pointer to the null +terminated character string, which is intended to be written to the +terminal. If the hook routine returns zero, the printing routine writes +the string {\it s} to the terminal in a usual way; otherwise, if the +hook routine returns non-zero, no terminal output is performed. + +To uninstall the hook routine both parameters {\it func} and {\it info} +should be specified as \verb|NULL|. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +static int hook(void *info, const char *s) +{ FILE *foo = info; + fputs(s, foo); + return 1; +} + +int main(void) +{ FILE *foo; + . . . + glp_term_hook(hook, foo); /* redirect terminal output */ + . . . + glp_term_hook(NULL, NULL); /* resume terminal output */ + . . . +} +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_open\_tee --- start copying terminal output} + +\synopsis + +\begin{verbatim} + int glp_open_tee(const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_open_tee| starts copying all the terminal output +to an output text file, whose name is specified by the character string +\verb|fname|. + +\returns + +\begin{retlist} +0 & operation successful;\\ +1 & copying terminal output is already active;\\ +2 & unable to create output file.\\ +\end{retlist} + +\subsection{glp\_close\_tee --- stop copying terminal output} + +\synopsis + +\begin{verbatim} + int glp_close_tee(void); +\end{verbatim} + +\description + +The routine \verb|glp_close_tee| stops copying the terminal output to +the output text file previously open by the routine \verb|glp_open_tee| +closing that file. + +\returns + +\begin{retlist} +0 & operation successful;\\ +1 & copying terminal output was not started.\\ +\end{retlist} + +\subsection{glp\_error --- display error message and terminate +execution} + +\synopsis + +\begin{verbatim} + void glp_error(const char *fmt, ...); +\end{verbatim} + +\description + +The routine \verb|glp_error| (implemented as a macro) formats its +parameters using the format control string \verb|fmt|, writes the +formatted message to the terminal, and then abnormally terminates the +program. + +\newpage + +\subsection{glp\_at\_error --- check for error state} + +\synopsis + +\begin{verbatim} + int glp_at_error(void); +\end{verbatim} + +\description + +The routine \verb|glp_at_error| checks if the GLPK environment is at +error state, i.~e.~if the call to the routine is (indirectly) made from +the \verb|glp_error| routine via an user-defined hook routine. + +This routine can be used, for example, by a custom output handler +(installed with the routine \verb|glp_term_hook|) to determine whether +or not the message to be displayed is an error message. + +\returns + +If the GLPK environment is at error state, the routine returns +non-zero, otherwise zero. + +\subsection{glp\_assert --- check logical condition} + +\synopsis + +\begin{verbatim} + void glp_assert(int expr); +\end{verbatim} + +\description + +The routine \verb|glp_assert| (implemented as a macro) checks +a logical condition specified by the expression \verb|expr|. If the +condition is true (non-zero), the routine does nothing; otherwise, if +the condition is false (zero), the routine prints an error message and +abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|assert| +and used by all GLPK routines to check program logic. The application +program may use \verb|glp_assert| for the same purpose. + +\subsection{glp\_error\_hook --- install hook to intercept abnormal +termination} + +\synopsis + +\begin{verbatim} + void glp_error_hook(void (*func)(void *info), void *info); +\end{verbatim} + +\description + +The routine \verb|glp_error_hook| installs a user-defined hook routine +to intercept abnormal termination. + +The parameter \verb|func| specifies the user-defined hook routine. It +is called from the routine \verb|glp_error| before the latter calls the +abort function to abnormally terminate the application program because +of fatal error. The parameter \verb|info| is a transit pointer, +specified in the corresponding call to the routine +\verb|glp_error_hook|; it may be used to pass some information to the +hook routine. + +To uninstall the hook routine the parameters \verb|func| and \verb|info| +should be specified as \verb|NULL|. + +If the hook routine returns, the application program is abnormally +terminated. To prevent abnormal termnation the hook routine may perform +a global jump using the standard function \verb|longjmp|, in which case +the application program {\it must} call the routine \verb|glp_free_env|. + +\subsection{glp\_alloc --- allocate memory block} + +\synopsis + +\begin{verbatim} + void *glp_alloc(int n, int size); +\end{verbatim} + +\description + +The routine \verb|glp_alloc| dynamically allocates a memory block of +\verb|n|$\times$\verb|size| bytes long. Note that: + +1) the parameters \verb|n| and \verb|size| must be positive; + +2) having been allocated the memory block contains arbitrary data, that +is, it is {\it not} initialized by binary zeros; + +3) if the block cannot be allocated due to insufficient memory, the +routine prints an error message and abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|malloc| +and used by GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_alloc| for the same purpose. + +\returns + +The routine \verb|glp_alloc| returns a pointer to the memory block +allocated. To free this block the routine \verb|glp_free| (not the +standard C function \verb|free|!) should be used. + +\subsection{glp\_realloc --- reallocate memory block} + +\synopsis + +\begin{verbatim} + void *glp_realloc(void *ptr, int n, int size); +\end{verbatim} + +\description + +The routine \verb|glp_realloc| dynamically reallocates a memory block +pointed to by \verb|ptr|, which was previously allocated by the routine +\verb|glp_alloc| or reallocated by this routine. Note that the pointer +\verb|ptr| must be valid and must not be \verb|NULL|. The new size of +the memory block is \verb|n|$\times$\verb|size| bytes long. Note that: + +1) both parameters \verb|n| and \verb|size| must be positive; + +2) if the block cannot be reallocated due to insufficient memory, the +routine prints an error message and abnormally terminates the program. + +This routine is a replacement of the standard C function \verb|realloc| +and used by GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_realloc| for the same purpose. + +\returns + +The routine \verb|glp_realloc| returns a pointer to the memory block +reallocated. To free this block the routine \verb|glp_free| (not the +standard C function \verb|free|!) should be used. + +\newpage + +\subsection{glp\_free --- free memory block} + +\synopsis + +\begin{verbatim} + void glp_free(void *ptr); +\end{verbatim} + +\description + +The routine \verb|glp_free| deallocates a memory block pointed to by +\verb|ptr|, which was previously allocated by the routine +\verb|glp_malloc| or reallocated by the routine \verb|glp_realloc|. +Note that the pointer \verb|ptr| must be valid and must not be +\verb|NULL|. + +This routine is a replacement of the standard C function \verb|free| +and used by GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_free| for the same purpose. + +\subsection{glp\_mem\_usage --- get memory usage information} + +\synopsis + +\begin{verbatim} + void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak); +\end{verbatim} + +\description + +The routine \verb|glp_mem_usage| reports some information about +utilization of the memory by the routines \verb|glp_malloc|, +\verb|glp_calloc|, and \verb|glp_free|. Information is stored to +locations specified by corresponding parameters (see below). Any +parameter can be specified as \verb|NULL|, in which case corresponding +information is not stored. + +\verb|*count| is the number of currently allocated memory blocks. + +\verb|*cpeak| is the peak value of \verb|*count| reached since the +initialization of the GLPK library environment. + +\verb|*total| is the total amount, in bytes, of currently allocated +memory blocks. + +\verb|*tpeak| is the peak value of \verb|*total| reached since the +initialization of the GLPK library envirionment. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +glp_mem_usage(&count, NULL, NULL, NULL); +printf("%d memory block(s) are still allocated\n", count); +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_mem\_limit --- set memory usage limit} + +\synopsis + +\begin{verbatim} + void glp_mem_limit(int limit); +\end{verbatim} + +\description + +The routine \verb|glp_mem_limit| limits the amount of memory available +for dynamic allocation (with the routines \verb|glp_malloc| and +\verb|glp_calloc|) to \verb|limit| megabytes. + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk07.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk07.tex new file mode 100644 index 000000000..004fe2ec8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk07.tex @@ -0,0 +1,258 @@ +%* glpk07.tex *% + +\chapter{Installing GLPK on Your Computer} +\label{install} + +\section{Downloading the distribution tarball} + +The distribution tarball of the most recent version of the GLPK +package can be found on \url{http://ftp.gnu.org/gnu/glpk/} [via http] +and \url{ftp://ftp.gnu.org/gnu/glpk/} [via FTP]. It can also be found +on one of the FTP mirrors; see \url{http://www.gnu.org/prep/ftp.html}. +Please use a mirror if possible. + +To make sure that the GLPK distribution tarball you have downloaded is +intact you need to download the corresponding `\verb|.sig|' file and +run a command like this: + +\begin{verbatim} + gpg --verify glpk-4.38.tar.gz.sig +\end{verbatim} + +\noindent +If that command fails because you do not have the required public key, +run the following command to import it: + +\begin{verbatim} + gpg --keyserver keys.gnupg.net --recv-keys 5981E818 +\end{verbatim} + +\noindent +and then re-run the previous command. + +\section{Unpacking the distribution tarball} + +The GLPK package (like all other GNU software) is distributed in the +form of packed archive. This is one file named \verb|glpk-X.Y.tar.gz|, +where {\it X} is the major version number and {\it Y} is the minor +version number. + +In order to prepare the distribution for installation you need to copy +the GLPK distribution file to a working subdirectory and then unpack +and unarchive the distribution file with the following command: + +\begin{verbatim} + tar zx < glpk-X.Y.tar +\end{verbatim} + +\newpage + +\section{Configuring the package} + +After unpacking and unarchiving the GLPK distribution you should +configure the package,\linebreak i.e. automatically tune it for your +platform. + +Normally, you should just \verb|cd| to the subdirectory \verb|glpk-X.Y| +and run the configure script, e.g. + +\begin{verbatim} + ./configure +\end{verbatim} + +The `\verb|configure|' shell script attempts to guess correct values +for various system-dependent variables used during compilation. It uses +those values to create a `\verb|Makefile|' in each directory of the +package. It also creates file `\verb|config.h|' containing +platform-dependent definitions. Finally, it creates a shell script +`\verb|config.status|' that you can run in the future to recreate the +current configuration, a file `\verb|config.cache|' that saves the +results of its tests to speed up reconfiguring, and a file +`\verb|config.log|' containing compiler output (useful mainly for +debugging `\verb|configure|'). + +Running `\verb|configure|' takes about a minute. While it is running, +it displays some informational messages that tell you what it +is doing. If you don't want to see these messages, run +`\verb|configure|' with its standard output redirected to +`\verb|dev/null|'; for example, `\verb|./configure > /dev/null|'. + +By default both static and shared versions of the GLPK library will be +compiled. Compilation of the shared librariy can be turned off by +specifying the `\verb|--disable-shared|' option to `\verb|configure|': + +\begin{verbatim} + ./configure --disable-shared +\end{verbatim} + +\noindent +If you encounter problems building the library try using the above +option, because some platforms do not support shared libraries. + +The GLPK package has some optional features listed below. By default +all these features are disabled. To enable a feature the corresponding +option should be passed to the configure script. + +\verb|--with-gmp | Enable using the GNU MP bignum library + +This feature allows the exact simplex solver to use the GNU MP bignum +library. If it is disabled, the exact simplex solver uses the GLPK +bignum module, which provides the same functionality as GNU MP, however, +it is much less efficient. + +For details about the GNU MP bignum library see its web page at +\url{http://gmplib.org/}. + +\verb|--enable-dl | The same as `\verb|--enable-dl=ltdl|' + +\verb|--enable-dl=ltdl | Enable shared library support (GNU) + +\verb|--enable-dl=dlfcn | Enable shared library support (POSIX) + +Currently this feature is only needed to provide dynamic linking to +ODBC and MySQL shared libraries (see below). + +For details about the GNU shared library support see the manual at +\url{http://www.gnu.org/software/libtool/manual/}. + +\verb|--enable-odbc | +Enable using ODBC table driver (\verb|libiodbc|) + +\verb|--enable-odbc=unix | +Enable using ODBC table driver (\verb|libodbc|) + +This feature allows transmitting data between MathProg model objects +and relational databases accessed through ODBC. + +For more details about this feature see the supplement ``Using Data +Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). + +\verb|--enable-mysql | +Enable using MySQL table driver (\verb|libmysql|) + +This feature allows transmitting data between MathProg model objects +and MySQL relational databases. + +For more details about this feature see the supplement ``Using Data +Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). + +\section{Compiling the package} + +Normally, you can compile (build) the package by typing the command: + +\begin{verbatim} + make +\end{verbatim} + +\noindent +It reads `\verb|Makefile|' generated by `\verb|configure|' and performs +all necessary jobs. + +If you want, you can override the `\verb|make|' variables \verb|CFLAGS| +and \verb|LDFLAGS| like this: + +\begin{verbatim} + make CFLAGS=-O2 LDFLAGS=-s +\end{verbatim} + +To compile the package in a different directory from the one containing +the source code, you must use a version of `\verb|make|' that supports +`\verb|VPATH|' variable, such as GNU `\verb|make|'. `\verb|cd|' to the +directory where you want the object files and executables to go and run +the `\verb|configure|' script. `\verb|configure|' automatically checks +for the source code in the directory that `\verb|configure|' is in and +in `\verb|..|'. If for some reason `\verb|configure|' is not in the +source code directory that you are configuring, then it will report +that it can't find the source code. In that case, run `\verb|configure|' +with the option `\verb|--srcdir=DIR|', where \verb|DIR| is the +directory that contains the source code. + +Some systems require unusual options for compilation or linking that +the `\verb|configure|' script does not know about. You can give +`\verb|configure|' initial values for variables by setting them in the +environment. Using a Bourne-compatible shell, you can do that on the +command line like this: + +\begin{verbatim} + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure +\end{verbatim} + +\noindent +Or on systems that have the `\verb|env|' program, you can do it like +this: + +\begin{verbatim} + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure +\end{verbatim} + +Here are the `\verb|make|' variables that you might want to override +with environment variables when running `\verb|configure|'. + +For these variables, any value given in the environment overrides the +value that `\verb|configure|' would choose: + +\verb|CC | C compiler program. The default is `\verb|cc|'. + +\verb|INSTALL | Program used to install files. The default value is +`\verb|install|' if you have it,\\ +\verb| | otherwise `\verb|cp|'. + +For these variables, any value given in the environment is added to the +value that `\verb|configure|' chooses: + +\verb|DEFS | Configuration options, in the form +`\verb|-Dfoo -Dbar| \dots'. + +\verb|LIBS | Libraries to link with, in the form +`\verb|-lfoo -lbar| \dots'. + +\section{Checking the package} + +To check the package, i.e. to run some tests included in the package, +you can use the following command: + +\begin{verbatim} + make check +\end{verbatim} + +\section{Installing the package} + +Normally, to install the GLPK package you should type the following +command: + +\begin{verbatim} + make install +\end{verbatim} + +\noindent +By default, `\verb|make install|' will install the package's files in +`\verb|usr/local/bin|', `\verb|usr/local/lib|', etc. You can specify an +installation prefix other than `\verb|/usr/local|' by giving +`\verb|configure|' the option `\verb|--prefix=PATH|'. Alternately, you +can do so by consistently giving a value for the `\verb|prefix|' +variable when you run `\verb|make|', e.g. + +\begin{verbatim} + make prefix=/usr/gnu + make prefix=/usr/gnu install +\end{verbatim} + +After installing you can remove the program binaries and object files +from the source directory by typing `\verb|make clean|'. To remove all +files that `\verb|configure|' created (`\verb|Makefile|', +`\verb|config.status|', etc.), just type `\verb|make distclean|'. + +The file `\verb|configure.ac|' is used to create `\verb|configure|' by +a program called `\verb|autoconf|'. You only need it if you want to +remake `\verb|configure|' using a newer version of `\verb|autoconf|'. + +\section{Uninstalling the package} + +To uninstall the GLPK package, i.e. to remove all the package's files +from the system places, you can use the following command: + +\begin{verbatim} + make uninstall +\end{verbatim} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk08.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk08.tex new file mode 100644 index 000000000..2636cb3c8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk08.tex @@ -0,0 +1,740 @@ +%* glpk08.tex *% + +\chapter{MPS Format} +\label{champs} + +\section{Fixed MPS Format} +\label{secmps} + +The MPS format\footnote{The MPS format was developed in 1960's by IBM +as input format for their mathematical programming system MPS/360. +Today the MPS format is a most widely used format understood by most +mathematical programming packages. This appendix describes only the +features of the MPS format, which are implemented in the GLPK package.} +is intended for coding LP/MIP problem data. This format assumes the +formulation of LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, +page \pageref{seclp}). + +{\it MPS file} is a text file, which contains two types of +cards\footnote{In 1960's MPS file was a deck of 80-column punched +cards, so the author decided to keep the word ``card'', which may be +understood as ``line of text file''.}: indicator cards and data cards. + +Indicator cards determine a kind of succeeding data. Each indicator +card has one word in uppercase letters beginning in column 1. + +Data cards contain problem data. Each data card is divided into six +fixed fields: + +\begin{center} +\begin{tabular}{lcccccc} +& Field 1 & Field 2 & Field 3 & Field 4 & Field 5 & Field 6 \\ +\hline +Columns & 2---3 & 5---12 & 15---22 & 25---36 & 40---47 & 50---61 \\ +Contents & Code & Name & Name & Number & Name & Number \\ +\end{tabular} +\end{center} + +On a particular data card some fields may be optional. + +Names are used to identify rows, columns, and some vectors (see below). + +Aligning the indicator code in the field 1 to the left margin is +optional. + +All names specified in the fields 2, 3, and 5 should contain from 1 up +to 8 arbitrary characters (except control characters). If a name is +placed in the field 3 or 5, its first character should not be the dollar +sign `\verb|$|'. If a name contains spaces, the spaces are ignored. + +All numerical values in the fields 4 and 6 should be coded in the form +$sxx$\verb|E|$syy$, where $s$ is the plus `\verb|+|' or the minus +`\verb|-|' sign, $xx$ is a real number with optional decimal point, +$yy$ is an integer decimal exponent. Any number should contain up to 12 +characters. If the sign $s$ is omitted, the plus sign is assumed. The +exponent part is optional. If a number contains spaces, the spaces are +ignored. + +%\newpage + +If a card has the asterisk `\verb|*|' in the column 1, this card is +considered as a comment and ignored. Besides, if the first character in +the field 3 or 5 is the dollar sign `\verb|$|', all characters from the +dollar sign to the end of card are considered as a comment and ignored. + +MPS file should contain cards in the following order: + +%\vspace*{-8pt} + +%\begin{itemize} +\Item{---}NAME indicator card; + +\Item{---}ROWS indicator card; + +\Item{---}data cards specifying rows (constraints); + +\Item{---}COLUMNS indicator card; + +\Item{---}data cards specifying columns (structural variables) and +constraint coefficients; + +\Item{---}RHS indicator card; + +\Item{---}data cards specifying right-hand sides of constraints; + +\Item{---}RANGES indicator card; + +\Item{---}data cards specifying ranges for double-bounded constraints; + +\Item{---}BOUNDS indicator card; + +\Item{---}data cards specifying types and bounds of structural +variables; + +\Item{---}ENDATA indicator card. +%\end{itemize} + +%\vspace*{-8pt} + +{\it Section} is a group of cards consisting of an indicator card and +data cards succeeding this indicator card. For example, the ROWS section +consists of the ROWS indicator card and data cards specifying rows. + +The sections RHS, RANGES, and BOUNDS are optional and may be omitted. + +\section{Free MPS Format} + +{\it Free MPS format} is an improved version of the standard (fixed) +MPS format described above.\footnote{This format was developed in the +beginning of 1990's by IBM as an alternative to the standard fixed MPS +format for Optimization Subroutine Library (OSL).} Note that all +changes in free MPS format concern only the coding of data while the +structure of data is the same for both fixed and free versions of the +MPS format. + +In free MPS format indicator and data records\footnote{{\it Record} in +free MPS format has the same meaning as {\it card} in fixed MPS format.} +may have arbitrary length not limited to 80 characters. Fields of data +records have no predefined positions, i.e. the fields may begin in any +position, except position 1, which must be blank, and must be separated +from each other by one or more blanks. However, the fields must appear +in the same order as in fixed MPS format. + +%\newpage + +Symbolic names in fields 2, 3, and 5 may be longer than 8 +characters\footnote{GLPK allows symbolic names having up to 255 +characters.} and must not contain embedded blanks. + +Numeric values in fields 4 and 6 are limited to 12 characters and must +not contain embedded blanks. + +Only six fields on each data record are used. Any other fields are +ignored. + +If the first character of any field (not necessarily fields 3 and 5) +is the dollar sign (\$), all characters from the dollar sign to the end +of record are considered as a comment and ignored. + +\newpage + +\section{NAME indicator card} + +The NAME indicator card should be the first card in the MPS file +(except optional comment cards, which may precede the NAME card). This +card should contain the word \verb|NAME| in the columns 1---4 and the +problem name in the field 3. The problem name is optional and may be +omitted. + +\section{ROWS section} +\label{secrows} + +The ROWS section should start with the indicator card, which contains +the word \verb|ROWS| in the columns 1---4. + +Each data card in the ROWS section specifies one row (constraint) of +the problem. All these data cards have the following format. + +`\verb|N|' in the field 1 means that the row is free (unbounded): +$$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +< +\infty;$$ + +`\verb|L|' in the field 1 means that the row is of ``less than or equal +to'' type: +$$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +\leq b_i;$$ + +`\verb|G|' in the field 1 means that the row is of ``greater than or +equal to'' type: +$$b_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +< +\infty;$$ + +`\verb|E|' in the field 1 means that the row is of ``equal to'' type: +$$x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} \leq +b_i,$$ +where $b_i$ is a right-hand side. Note that each constraint has a +corresponding implictly defined auxiliary variable ($x_i$ above), whose +value is a value of the corresponding linear form, therefore row bounds +can be considered as bounds of such auxiliary variable. + +The filed 2 specifies a row name (which is considered as the name of +the corresponding auxiliary variable). + +%\newpage + +The fields 3, 4, 5, and 6 are not used and should be empty. + +Numerical values of all non-zero right-hand sides $b_i$ should be +specified in the RHS section (see below). All double-bounded (ranged) +constraints should be specified in the RANGES section (see below). + +\section{COLUMNS section} + +The COLUMNS section should start with the indicator card, which +contains the word \verb|COLUMNS| in the columns 1---7. + +Each data card in the COLUMNS section specifies one or two constraint +coefficients $a_{ij}$ and also introduces names of columns, i.e. names +of structural variables. All these data cards have the following +format. + +The field 1 is not used and should be empty. + +The field 2 specifies a column name. If this field is empty, the column +name from the immediately preceeding data card is assumed. + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a numerical value of the constraint coefficient +$a_{ij}$, which is placed in the corresponding row and column. + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---constraint coefficient'' for the same column. + +Elements of the constraint matrix (i.e. constraint coefficients) should +be enumerated in the column wise manner: all elements for the current +column should be specified before elements for the next column. However, +the order of rows in the COLUMNS section may differ from the order of +rows in the ROWS section. + +Constraint coefficients not specified in the COLUMNS section are +considered as zeros. Therefore zero coefficients may be omitted, +although it is allowed to explicitly specify them. + +\section{RHS section} + +The RHS section should start with the indicator card, which contains the +word \verb|RHS| in the columns 1---3. + +Each data card in the RHS section specifies one or two right-hand sides +$b_i$ (see Section \ref{secrows}, page \pageref{secrows}). All these +data cards have the following format. + +The field 1 is not used and should be empty. + +The field 2 specifies a name of the right-hand side (RHS) +vector\footnote{This feature allows the user to specify several RHS +vectors in the same MPS file. However, before solving the problem a +particular RHS vector should be chosen.}. If this field is empty, the +RHS vector name from the immediately preceeding data card is assumed. + +%\newpage + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a right-hand side $b_i$ for the row, whose name is +specified in the field 3. Depending on the row type $b_i$ is a lower +bound (for the row of \verb|G| type), an upper bound (for the row of +\verb|L| type), or a fixed value (for the row of \verb|E| +type).\footnote{If the row is of {\tt N} type, $b_i$ is considered as +a constant term of the corresponding linear form. Should note, however, +this convention is non-standard.} + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---right-hand side'' for the same RHS vector. + +All right-hand sides for the current RHS vector should be specified +before right-hand sides for the next RHS vector. However, the order of +rows in the RHS section may differ from the order of rows in the ROWS +section. + +Right-hand sides not specified in the RHS section are considered as +zeros. Therefore zero right-hand sides may be omitted, although it is +allowed to explicitly specify them. + +\newpage + +\section{RANGES section} + +The RANGES section should start with the indicator card, which contains +the word \verb|RANGES| in the columns 1---6. + +Each data card in the RANGES section specifies one or two ranges for +double-side constraints, i.e. for constraints that are of the types +\verb|L| and \verb|G| at the same time: +$$l_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} +\leq u_i,$$ +where $l_i$ is a lower bound, $u_i$ is an upper bound. All these data +cards have the following format. + +The field 1 is not used and should be empty. + +The field 2 specifies a name of the range vector\footnote{This feature +allows the user to specify several range vectors in the same MPS file. +However, before solving the problem a particular range vector should be +chosen.}. If this field is empty, the range vector name from the +immediately preceeding data card is assumed. + +The field 3 specifies a row name defined in the ROWS section. + +The field 4 specifies a range value $r_i$ (see the table below) for the +row, whose name is specified in the field 3. + +The fields 5 and 6 are optional. If they are used, they should contain +a second pair ``row name---range value'' for the same range vector. + +All range values for the current range vector should be specified before +range values for the next range vector. However, the order of rows in +the RANGES section may differ from the order of rows in the ROWS +section. + +For each double-side constraint specified in the RANGES section its +lower and upper bounds are determined as follows: + +%\newpage + +\begin{center} +\begin{tabular}{cccc} +Row type & Sign of $r_i$ & Lower bound & Upper bound \\ +\hline +{\tt G} & $+$ or $-$ & $b_i$ & $b_i + |r_i|$ \\ +{\tt L} & $+$ or $-$ & $b_i - |r_i|$ & $b_i$ \\ +{\tt E} & $+$ & $b_i$ & $b_i + |r_i|$ \\ +{\tt E} & $-$ & $b_i - |r_i|$ & $b_i$ \\ +\end{tabular} +\end{center} + +\noindent +where $b_i$ is a right-hand side specified in the RHS section (if $b_i$ +is not specified, it is considered as zero), $r_i$ is a range value +specified in the RANGES section. + +\section{BOUNDS section} +\label{secbounds} + +The BOUNDS section should start with the indicator card, which contains +the word \verb|BOUNDS| in the columns 1---6. + +Each data card in the BOUNDS section specifies one (lower or upper) +bound for one structural variable (column). All these data cards have +the following format. + +The indicator in the field 1 specifies the bound type: + +\verb|LO| --- lower bound; + +\verb|UP| --- upper bound; + +\verb|FX| --- fixed variable (lower and upper bounds are equal); + +\verb|FR| --- free variable (no bounds); + +\verb|MI| --- no lower bound (lower bound is ``minus infinity''); + +\verb|PL| --- no upper bound (upper bound is ``plus infinity''). + +The field 2 specifies a name of the bound vector\footnote{This feature +allows the user to specify several bound vectors in the same MPS file. +However, before solving the problem a particular bound vector should be +chosen.}. If this field is empty, the bound vector name from the +immediately preceeding data card is assumed. + +The field 3 specifies a column name defined in the COLUMNS section. + +The field 4 specifies a bound value. If the bound type in the field 1 +differs from \verb|LO|, \verb|UP|, and \verb|FX|, the value in the field +4 is ignored and may be omitted. + +The fields 5 and 6 are not used and should be empty. + +All bound values for the current bound vector should be specified before +bound values for the next bound vector. However, the order of columns in +the BOUNDS section may differ from the order of columns in the COLUMNS +section. Specification of a lower bound should precede specification of +an upper bound for the same column (if both the lower and upper bounds +are explicitly specified). + +By default, all columns (structural variables) are non-negative, i.e. +have zero lower bound and no upper bound. Lower ($l_j$) and upper +($u_j$) bounds of some column (structural variable $x_j$) are set in the +following way, where $s_j$ is a corresponding bound value explicitly +specified in the BOUNDS section: + +%\newpage + +\verb|LO| sets $l_j$ to $s_j$; + +\verb|UP| sets $u_j$ to $s_j$; + +\verb|FX| sets both $l_j$ and $u_j$ to $s_j$; + +\verb|FR| sets $l_j$ to $-\infty$ and $u_j$ to $+\infty$; + +\verb|MI| sets $l_j$ to $-\infty$; + +\verb|PL| sets $u_j$ to $+\infty$. + +\section{ENDATA indicator card} + +The ENDATA indicator card should be the last card of MPS file (except +optional comment cards, which may follow the ENDATA card). This card +should contain the word \verb|ENDATA| in the columns 1---6. + +\section{Specifying objective function} + +It is impossible to explicitly specify the objective function and +optimization direction in the MPS file. However, the following implicit +rule is used by default: the first row of \verb|N| type is considered +as a row of the objective function (i.e. the objective function is the +corresponding auxiliary variable), which should be {\it minimized}. + +GLPK also allows specifying a constant term of the objective function +as a right-hand side of the corresponding row in the RHS section. + +\section{Example of MPS file} +\label{secmpsex} + +To illustrate what the MPS format is, consider the following example of +LP problem: + +\def\arraystretch{1.2} + +\noindent\hspace{.5in}minimize +$$ +value = .03\ bin_1 + .08\ bin_2 + .17\ bin_3 + .12\ bin_4 + .15\ bin_5 ++ .21\ al + .38\ si +$$ +\noindent\hspace{.5in}subject to linear constraints +$$ +\begin{array}{@{}l@{\:}l@{}} +yield &= \ \ \ \ \;bin_1 + \ \ \ \ \;bin_2 + \ \ \ \ \;bin_3 + + \ \ \ \ \;bin_4 + \ \ \ \ \;bin_5 + \ \ \ \ \;al + + \ \ \ \ \;si \\ +FE &= .15\ bin_1 + .04\ bin_2 + .02\ bin_3 + .04\ bin_4 + .02\ bin_5 + + .01\ al + .03\ si \\ +CU &= .03\ bin_1 + .05\ bin_2 + .08\ bin_3 + .02\ bin_4 + .06\ bin_5 + + .01\ al \\ +MN &= .02\ bin_1 + .04\ bin_2 + .01\ bin_3 + .02\ bin_4 + .02\ bin_5 + \\ +MG &= .02\ bin_1 + .03\ bin_2 +\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ + .01\ bin_5 \\ +AL &= .70\ bin_1 + .75\ bin_2 + .80\ bin_3 + .75\ bin_4 + .80\ bin_5 + + .97\ al \\ +SI &= .02\ bin_1 + .06\ bin_2 + .08\ bin_3 + .12\ bin_4 + .02\ bin_5 + + .01\ al + .97\ si \\ +\end{array} +$$ +\noindent\hspace{.5in}and bounds of (auxiliary and structural) +variables +$$ +\begin{array}{r@{\ }l@{\ }l@{\ }l@{\ }rcr@{\ }l@{\ }l@{\ }l@{\ }r} +&&yield&=&2000&&0&\leq&bin_1&\leq&200\\ +-\infty&<&FE&\leq&60&&0&\leq&bin_2&\leq&2500\\ +-\infty&<&CU&\leq&100&&400&\leq&bin_3&\leq&800\\ +-\infty&<&MN&\leq&40&&100&\leq&bin_4&\leq&700\\ +-\infty&<&MG&\leq&30&&0&\leq&bin_5&\leq&1500\\ +1500&\leq&AL&<&+\infty&&0&\leq&al&<&+\infty\\ +250&\leq&SI&\leq&300&&0&\leq&si&<&+\infty\\ +\end{array} +$$ + +\def\arraystretch{1} + +A complete MPS file which specifies data for this example is shown +below (the first two comment lines show card positions). + +\newpage + +\begin{footnotesize} +\begin{verbatim} +*000000001111111111222222222233333333334444444444555555555566 +*234567890123456789012345678901234567890123456789012345678901 +NAME PLAN +ROWS + N VALUE + E YIELD + L FE + L CU + L MN + L MG + G AL + L SI +COLUMNS + BIN1 VALUE .03000 YIELD 1.00000 + FE .15000 CU .03000 + MN .02000 MG .02000 + AL .70000 SI .02000 + BIN2 VALUE .08000 YIELD 1.00000 + FE .04000 CU .05000 + MN .04000 MG .03000 + AL .75000 SI .06000 + BIN3 VALUE .17000 YIELD 1.00000 + FE .02000 CU .08000 + MN .01000 AL .80000 + SI .08000 + BIN4 VALUE .12000 YIELD 1.00000 + FE .04000 CU .02000 + MN .02000 AL .75000 + SI .12000 + BIN5 VALUE .15000 YIELD 1.00000 + FE .02000 CU .06000 + MN .02000 MG .01000 + AL .80000 SI .02000 + ALUM VALUE .21000 YIELD 1.00000 + FE .01000 CU .01000 + AL .97000 SI .01000 + SILICON VALUE .38000 YIELD 1.00000 + FE .03000 SI .97000 +RHS + RHS1 YIELD 2000.00000 FE 60.00000 + CU 100.00000 MN 40.00000 + SI 300.00000 + MG 30.00000 AL 1500.00000 +RANGES + RNG1 SI 50.00000 +BOUNDS + UP BND1 BIN1 200.00000 + UP BIN2 2500.00000 + LO BIN3 400.00000 + UP BIN3 800.00000 + LO BIN4 100.00000 + UP BIN4 700.00000 + UP BIN5 1500.00000 +ENDATA +\end{verbatim} +\end{footnotesize} + +%\vspace*{-6pt} + +\section{MIP features} + +%\vspace*{-4pt} + +The MPS format provides two ways for introducing integer variables into +the problem. + +The first way is most general and based on using special marker cards +INTORG and INTEND. These marker cards are placed in the COLUMNS section. +The INTORG card indicates the start of a group of integer variables +(columns), and the card INTEND indicates the end of the group. The MPS +file may contain arbitrary number of the marker cards. + +The marker cards have the same format as the data cards (see Section +\ref{secmps}, page \pageref{secmps}). + +The fields 1, 2, and 6 are not used and should be empty. + +The field 2 should contain a marker name. This name may be arbitrary. + +The field 3 should contain the word \verb|'MARKER'| (including +apostrophes). + +The field 5 should contain either the word \verb|'INTORG'| (including +apostrophes) for the marker card, which begins a group of integer +columns, or the word \verb|'INTEND'| (including apostrophes) for the +marker card, which ends the group. + +The second way is less general but more convenient in some cases. It +allows the user declaring integer columns using three additional types +of bounds, which are specified in the field 1 of data cards in the +BOUNDS section (see Section \ref{secbounds}, page \pageref{secbounds}): + +\verb|LI| --- lower integer. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +field 3, is of integer kind. In this case an lower bound of the +column should be specified in field 4 (like in the case of \verb|LO| +bound type). + +\verb|UI| --- upper integer. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +field 3, is of integer kind. In this case an upper bound of the +column should be specified in field 4 (like in the case of \verb|UP| +bound type). + +\verb|BV| --- binary variable. This bound type specifies that the +corresponding column (structural variable), whose name is specified in +the field 3, is of integer kind, its lower bound is zero, and its upper +bound is one (thus, such variable being of integer kind can have only +two values zero and one). In this case a numeric value specified in the +field 4 is ignored and may be omitted. + +Consider the following example of MIP problem: + +\noindent +\hspace{1in} minimize +$$Z = 3 x_1 + 7 x_2 - x_3 + x4$$ +\hspace{1in} subject to linear constraints +$$ +\begin{array}{c} +\nonumber r_1 = 2 x_1 - \ \ x_2 + \ \ x_3 - \ \;x_4 \\ +\nonumber r_2 = \ \;x_1 - \ \;x_2 - 6 x_3 + 4 x_4 \\ +\nonumber r_3 = 5 x_1 + 3 x_2 \ \ \ \ \ \ \ \ \ + \ \ x_4 \\ +\end{array} +$$ +\hspace{1in} and bound of variables +$$ +\begin{array}{cccl} +\nonumber 1 \leq r_1 < +\infty && 0 \leq x_1 \leq 4 &{\rm(continuous)}\\ +\nonumber 8 \leq r_2 < +\infty && 2 \leq x_2 \leq 5 &{\rm(integer)} \\ +\nonumber 5 \leq r_3 < +\infty && 0 \leq x_3 \leq 1 &{\rm(integer)} \\ +\nonumber && 3 \leq x_4 \leq 8 &{\rm(continuous)}\\ +\end{array} +$$ + +The corresponding MPS file may look like follows: + +\newpage + +\begin{footnotesize} +\begin{verbatim} +NAME SAMP1 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + MARK0001 'MARKER' 'INTORG' + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + MARK0002 'MARKER' 'INTEND' + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UP BND1 X2 5.0 + UP BND1 X3 1.0 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA +\end{verbatim} +\end{footnotesize} + +%\newpage +\vspace{-3pt} + +The same example may be coded without INTORG/INTEND markers using the +bound type UI for the variable $x_2$ and the bound type BV for the +variable $x_3$: + +%\medskip + +\begin{footnotesize} +\begin{verbatim} +NAME SAMP2 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UI BND1 X2 5.0 + BV BND1 X3 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA +\end{verbatim} +\end{footnotesize} + +%\section{Specifying predefined basis} +%\label{secbas} +% +%The MPS format can also be used to specify some predefined basis for an +%LP problem, i.e. to specify which rows and columns are basic and which +%are non-basic. +% +%The order of a basis file in the MPS format is: +% +%$\bullet$ NAME indicator card; +% +%$\bullet$ data cards (can appear in arbitrary order); +% +%$\bullet$ ENDATA indicator card. +% +%Each data card specifies either a pair "basic column---non-basic row" +%or a non-basic column. All the data cards have the following format. +% +%`\verb|XL|' in the field 1 means that a column, whose name is given in +%the field 2, is basic, and a row, whose name is given in the field 3, +%is non-basic and placed on its lower bound. +% +%`\verb|XU|' in the field 1 means that a column, whose name is given in +%the field 2, is basic, and a row, whose name is given in the field 3, +%is non-basic and placed on its upper bound. +% +%`\verb|LL|' in the field 1 means that a column, whose name is given in +%the field 3, is non-basic and placed on its lower bound. +% +%`\verb|UL|' in the field 1 means that a column, whose name is given in +%the field 3, is non-basic and placed on its upper bound. +% +%The field 2 contains a column name. +% +%If the indicator given in the field 1 is `\verb|XL|' or `\verb|XU|', +%the field 3 contains a row name. Otherwise, if the indicator is +%`\verb|LL|' or `\verb|UL|', the field 3 is not used and should be +%empty. +% +%The field 4, 5, and 6 are not used and should be empty. +% +%A basis file in the MPS format acts like a patch: it doesn't specify +%a basis completely, instead that it is just shows in what a given basis +%differs from the "standard" basis, where all rows (auxiliary variables) +%are assumed to be basic and all columns (structural variables) are +%assumed to be non-basic. +% +%As an example here is a basis file that specifies an optimal basis +%for the example LP problem given in Section \ref{secmpsex}, +%Page \pageref{secmpsex}: +% +%\pagebreak +% +%\begin{verbatim} +%*000000001111111111222222222233333333334444444444555555555566 +%*234567890123456789012345678901234567890123456789012345678901 +%NAME PLAN +% XL BIN2 YIELD +% XL BIN3 FE +% XL BIN4 MN +% XL ALUM AL +% XL SILICON SI +% LL BIN1 +% LL BIN5 +%ENDATA +%\end{verbatim} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk09.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk09.tex new file mode 100644 index 000000000..a78e9878e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk09.tex @@ -0,0 +1,423 @@ +%* glpk09.tex *% + +\chapter{CPLEX LP Format} +\label{chacplex} + +\section{Prelude} + +The CPLEX LP format\footnote{The CPLEX LP format was developed in +the end of 1980's by CPLEX Optimization, Inc. as an input format for +the CPLEX linear programming system. Although the CPLEX LP format is +not as widely used as the MPS format, being row-oriented it is more +convenient for coding mathematical programming models by human. This +appendix describes only the features of the CPLEX LP format which are +implemented in the GLPK package.} is intended for coding LP/MIP problem +data. It is a row-oriented format that assumes the formulation of +LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, page +\pageref{seclp}). + +CPLEX LP file is a plain text file written in CPLEX LP format. Each +text line of this file may contain up to 255 characters\footnote{GLPK +allows text lines of arbitrary length.}. Blank lines are ignored. +If a line contains the backslash character ($\backslash$), this +character and everything that follows it until the end of line are +considered as a comment and also ignored. + +An LP file is coded by the user using the following elements: keywords, +symbolic names, numeric constants, delimiters, and blanks. + +{\it Keywords} which may be used in the LP file are the following: + +\begin{verbatim} + minimize minimum min + maximize maximum max + subject to such that s.t. st. st + bounds bound + general generals gen + integer integers int + binary binaries bin + infinity inf + free + end +\end{verbatim} + +\noindent +All the keywords are case insensitive. Keywords given above on the same +line are equivalent. Any keyword (except \verb|infinity|, \verb|inf|, +and \verb|free|) being used in the LP file must start at the beginning +of a text line. + +\newpage + +{\it Symbolic names} are used to identify the objective function, +constraints (rows), and variables (columns). All symbolic names are case +sensitive and may contain up to 16 alphanumeric characters\footnote{GLPK +allows symbolic names having up to 255 characters.} (\verb|a|, \dots, +\verb|z|, \verb|A|, \dots, \verb|Z|, \verb|0|, \dots, \verb|9|) as well +as the following characters: + +\begin{verbatim} + ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~ +\end{verbatim} + +\noindent +with exception that no symbolic name can begin with a digit or +a period. + +{\it Numeric constants} are used to denote constraint and objective +coefficients, right-hand sides of constraints, and bounds of variables. +They are coded in the standard form $xx$\verb|E|$syy$, where $xx$ is +a real number with optional decimal point, $s$ is a sign (\verb|+| or +\verb|-|), $yy$ is an integer decimal exponent. Numeric constants may +contain arbitrary number of characters. The exponent part is optional. +The letter `\verb|E|' can be coded as `\verb|e|'. If the sign $s$ is +omitted, plus is assumed. + +{\it Delimiters} that may be used in the LP file are the following: + +\begin{verbatim} + : + + + - + < <= =< + > >= => + = +\end{verbatim} + +\noindent +Delimiters given above on the same line are equivalent. The meaning of +the delimiters will be explained below. + +{\it Blanks} are non-significant characters. They may be used freely to +improve readability of the LP file. Besides, blanks should be used to +separate elements from each other if there is no other way to do that +(for example, to separate a keyword from a following symbolic name). + +The order of an LP file is the following: + +%\vspace*{-8pt} + +%\begin{itemize} +\Item{---}objective function definition; + +\Item{---}constraints section; + +\Item{---}bounds section; + +\Item{---}general, integer, and binary sections (can appear in +arbitrary order); + +\Item{---}end keyword. +%\end{itemize} + +%\vspace*{-8pt} + +These components are discussed in following sections. + +\section{Objective function definition} + +The objective function definition must appear first in the LP file. +It defines the objective function and specifies the optimization +direction. + +The objective function definition has the following form: +$$ +\left\{ +\begin{array}{@{}c@{}} +{\tt minimize} \\ {\tt maximize} +\end{array} +\right\}\ f\ {\tt :}\ s\ c\ x\ \dots\ s\ c\ x +$$ +where $f$ is a symbolic name of the objective function, $s$ is a sign +\verb|+| or \verb|-|, $c$ is a numeric constant that denotes an +objective coefficient, $x$ is a symbolic name of a variable. + +If necessary, the objective function definition can be continued on as +many text lines as desired. + +The name of the objective function is optional and may be omitted +(together with the semicolon that follows it). In this case the default +name `\verb|obj|' is assigned to the objective function. + +If the very first sign $s$ is omitted, the sign plus is assumed. Other +signs cannot be omitted. + +If some objective coefficient $c$ is omitted, 1 is assumed. + +Symbolic names $x$ used to denote variables are recognized by context +and therefore needn't to be declared somewhere else. + +Here is an example of the objective function definition: + +\begin{verbatim} + Minimize Z : - x1 + 2 x2 - 3.5 x3 + 4.997e3x(4) + x5 + x6 + + x7 - .01x8 +\end{verbatim} + +\section{Constraints section} + +The constraints section must follow the objective function definition. +It defines a system of equality and/or inequality constraints. + +The constraint section has the following form: + +\begin{center} +\begin{tabular}{l} +\verb|subject to| \\ +{\it constraint}$_1$ \\ +\hspace{20pt}\dots \\ +{\it constraint}$_m$ \\ +\end{tabular} +\end{center} + +\noindent where {\it constraint}$_i, i=1,\dots,m,$ is a particular +constraint definition. + +Each constraint definition can be continued on as many text lines as +desired. However, each constraint definition must begin on a new line +except the very first constraint definition which can begin on the same +line as the keyword `\verb|subject to|'. + +Constraint definitions have the following form: +$$ +r\ {\tt:}\ s\ c\ x\ \dots\ s\ c\ x +\ \left\{ +\begin{array}{@{}c@{}} +\mbox{\tt<=} \\ \mbox{\tt>=} \\ \mbox{\tt=} +\end{array} +\right\}\ b +$$ +where $r$ is a symbolic name of a constraint, $s$ is a sign \verb|+| or +\verb|-|, $c$ is a numeric constant that denotes a constraint +coefficient, $x$ is a symbolic name of a variable, $b$ is a right-hand +side. + +The name $r$ of a constraint (which is the name of the corresponding +auxiliary variable) is optional and may be omitted together with the +semicolon that follows it. In the latter case the default names like +`\verb|r.nnn|' are assigned to unnamed constraints. + +The linear form $s\ c\ x\ \dots\ s\ c\ x$ in the left-hand side of +a constraint definition has exactly the same meaning as in the case of +the objective function definition (see above). + +After the linear form one of the following delimiters that indicates +the constraint sense must be specified: + +\verb|<=| \ means `less than or equal to' + +\verb|>=| \ means `greater than or equal to' + +\verb|= | \ means `equal to' + +The right hand side $b$ is a numeric constant with an optional sign. + +Here is an example of the constraints section: + +\begin{verbatim} + Subject To + one: y1 + 3 a1 - a2 - b >= 1.5 + y2 + 2 a3 + 2 + a4 - b >= -1.5 + two : y4 + 3 a1 + 4 a5 - b <= +1 + .20y5 + 5 a2 - b = 0 + 1.7 y6 - a6 + 5 a777 - b >= 1 +\end{verbatim} + +Should note that it is impossible to express ranged constraints in the +CPLEX LP format. Each a ranged constraint can be coded as two +constraints with identical linear forms in the left-hand side, one of +which specifies a lower bound and other does an upper one of the +original ranged constraint. Another way is to introduce a slack +double-bounded variable; for example, the +constraint +$$10\leq x+2y+3z\leq 50$$ +can be written as follows: +$$x+2y+3z+t=50,$$ +where $0\leq t\leq 40$ is a slack variable. + +\section{Bounds section} + +The bounds section is intended to define bounds of variables. This +section is optional; if it is specified, it must follow the constraints +section. If the bound section is omitted, all variables are assumed to +be non-negative (i.e. that they have zero lower bound and no upper +bound). + +The bounds section has the following form: + +\begin{center} +\begin{tabular}{l} +\verb|bounds| \\ +{\it definition}$_1$ \\ +\hspace{20pt}\dots \\ +{\it definition}$_p$ \\ +\end{tabular} +\end{center} + +\noindent +where {\it definition}$_k, k=1,\dots,p,$ is a particular bound +definition. + +Each bound definition must begin on a new line\footnote{The GLPK +implementation allows several bound definitions to be placed on the +same line.} except the very first bound definition which can begin on +the same line as the keyword `\verb|bounds|'. + +%\newpage + +Syntactically constraint definitions can have one of the following six +forms: + +\begin{center} +\begin{tabular}{ll} +$x$ \verb|>=| $l$ & specifies a lower bound \\ +$l$ \verb|<=| $x$ & specifies a lower bound \\ +$x$ \verb|<=| $u$ & specifies an upper bound \\ +$l$ \verb|<=| $x$ \verb|<=| $u$ &specifies both lower and upper bounds\\ +$x$ \verb|=| $t$ &specifies a fixed value \\ +$x$ \verb|free| &specifies free variable +\end{tabular} +\end{center} + +\noindent +where $x$ is a symbolic name of a variable, $l$ is a numeric constant +with an optional sign that defines a lower bound of the variable or +\verb|-inf| that means that the variable has no lower bound, $u$ is +a~numeric constant with an optional sign that defines an upper bound of +the variable or \verb|+inf| that means that the variable has no upper +bound, $t$ is a numeric constant with an optional sign that defines a +fixed value of the variable. + +By default all variables are non-negative, i.e. have zero lower bound +and no upper bound. Therefore definitions of these default bounds can +be omitted in the bounds section. + +Here is an example of the bounds section: + +\begin{verbatim} + Bounds + -inf <= a1 <= 100 + -100 <= a2 + b <= 100 + x2 = +123.456 + x3 free +\end{verbatim} + +\section{General, integer, and binary sections} + +The general, integer, and binary sections are intended to define +some variables as integer or binary. All these sections are optional +and needed only in case of MIP problems. If they are specified, they +must follow the bounds section or, if the latter is omitted, the +constraints section. + +All the general, integer, and binary sections have the same form as +follows: + +\begin{center} +\begin{tabular}{l} +$ +\left\{ +\begin{array}{@{}l@{}} +\verb|general| \\ +\verb|integer| \\ +\verb|binary | \\ +\end{array} +\right\} +$ \\ +\hspace{10pt}$x_1$ \\ +\hspace{10pt}\dots \\ +\hspace{10pt}$x_q$ \\ +\end{tabular} +\end{center} + +\noindent +where $x_k$ is a symbolic name of variable, $k=1,\dots,q$. + +Each symbolic name must begin on a new line\footnote{The GLPK +implementation allows several symbolic names to be placed on the same +line.} except the very first symbolic name which can begin on the same +line as the keyword `\verb|general|', `\verb|integer|', or +`\verb|binary|'. + +%\newpage + +If a variable appears in the general or the integer section, it is +assumed to be general integer variable. If a variable appears in the +binary section, it is assumed to be binary variable, i.e. an integer +variable whose lower bound is zero and upper bound is one. (Note that +if bounds of a variable are specified in the bounds section and then +the variable appears in the binary section, its previously specified +bounds are ignored.) + +Here is an example of the integer section: + +\begin{verbatim} + Integer + z12 + z22 + z35 +\end{verbatim} + +\newpage + +\section{End keyword} + +The keyword `\verb|end|' is intended to end the LP file. It must begin +on a separate line and no other elements (except comments and blank +lines) must follow it. Although this keyword is optional, it is strongly +recommended to include it in the LP file. + +\section{Example of CPLEX LP file} + +Here is a complete example of CPLEX LP file that corresponds to the +example given in Section \ref{secmpsex}, page \pageref{secmpsex}. + +\medskip + +\begin{footnotesize} +\begin{verbatim} +\* plan.lp *\ + +Minimize + value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + + .21 alum + .38 silicon + +Subject To + yield: bin1 + bin2 + bin3 + bin4 + bin5 + + alum + silicon = 2000 + + fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + + .01 alum + .03 silicon <= 60 + + cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + + .01 alum <= 100 + + mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 + + mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 + + al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + + .97 alum >= 1500 + + si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon >= 250 + + si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon <= 300 + +Bounds + bin1 <= 200 + bin2 <= 2500 + 400 <= bin3 <= 800 + 100 <= bin4 <= 700 + bin5 <= 1500 + +End + +\* eof *\ +\end{verbatim} +\end{footnotesize} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk10.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk10.tex new file mode 100644 index 000000000..1943ef02e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk10.tex @@ -0,0 +1,160 @@ +%* glpk10.tex *% + +\chapter{Stand-alone LP/MIP Solver} +\label{chaglpsol} + +The GLPK package includes the program \verb|glpsol|, which is a +stand-alone LP/MIP solver. This program can be invoked from the command +line to read LP/MIP problem data in any format supported by GLPK, solve +the problem, and write its solution to an output text file. + +\para{Usage} + +\verb|glpsol| [{\it options\dots}] [{\it filename}] + +\para{General options} + +\begin{verbatim} + --mps read LP/MIP problem in fixed MPS format + --freemps read LP/MIP problem in free MPS format (default) + --lp read LP/MIP problem in CPLEX LP format + --glp read LP/MIP problem in GLPK format + --math read LP/MIP model written in GNU MathProg modeling + language + -m filename, --model filename + read model section and optional data section from + filename (same as --math) + -d filename, --data filename + read data section from filename (for --math only); + if model file also has data section, it is ignored + -y filename, --display filename + send display output to filename (for --math only); + by default the output is sent to terminal + --seed value initialize pseudo-random number generator used in + MathProg model with specified seed (any integer); + if seed value is ?, some random seed will be used + --mincost read min-cost flow problem in DIMACS format + --maxflow read maximum flow problem in DIMACS format + --cnf read CNF-SAT problem in DIMACS format + --simplex use simplex method (default) + --interior use interior point method (LP only) + -r filename, --read filename + read solution from filename rather to find it with + the solver + --min minimization + --max maximization + --scale scale problem (default) + --noscale do not scale problem + -o filename, --output filename + write solution to filename in printable format + -w filename, --write filename + write solution to filename in plain text format + --ranges filename + write sensitivity analysis report to filename in + printable format (simplex only) + --tmlim nnn limit solution time to nnn seconds + --memlim nnn limit available memory to nnn megabytes + --check do not solve problem, check input data only + --name probname change problem name to probname + --wmps filename write problem to filename in fixed MPS format + --wfreemps filename + write problem to filename in free MPS format + --wlp filename write problem to filename in CPLEX LP format + --wglp filename write problem to filename in GLPK format + --wcnf filename write problem to filename in DIMACS CNF-SAT format + --log filename write copy of terminal output to filename + -h, --help display this help information and exit + -v, --version display program version and exit +\end{verbatim} + +\para{LP basis factorization options} + +\begin{verbatim} + --luf plain LU factorization (default) + --btf block triangular LU factorization + --ft Forrest-Tomlin update (requires --luf; default) + --cbg Schur complement + Bartels-Golub update + --cgr Schur complement + Givens rotation update +\end{verbatim} + +\para{Options specific to the simplex solver} + +\begin{verbatim} + --primal use primal simplex (default) + --dual use dual simplex + --std use standard initial basis of all slacks + --adv use advanced initial basis (default) + --bib use Bixby's initial basis + --ini filename use as initial basis previously saved with -w + (disables LP presolver) + --steep use steepest edge technique (default) + --nosteep use standard "textbook" pricing + --relax use Harris' two-pass ratio test (default) + --norelax use standard "textbook" ratio test + --presol use presolver (default; assumes --scale and --adv) + --nopresol do not use presolver + --exact use simplex method based on exact arithmetic + --xcheck check final basis using exact arithmetic +\end{verbatim} + +\para{Options specific to the interior-point solver} + +\begin{verbatim} + --nord use natural (original) ordering + --qmd use quotient minimum degree ordering + --amd use approximate minimum degree ordering (default) + --symamd use approximate minimum degree ordering +\end{verbatim} + +\para{Options specific to the MIP solver} + +\begin{verbatim} + --nomip consider all integer variables as continuous + (allows solving MIP as pure LP) + --first branch on first integer variable + --last branch on last integer variable + --mostf branch on most fractional variable + --drtom branch using heuristic by Driebeck and Tomlin + (default) + --pcost branch using hybrid pseudocost heuristic (may be + useful for hard instances) + --dfs backtrack using depth first search + --bfs backtrack using breadth first search + --bestp backtrack using the best projection heuristic + --bestb backtrack using node with best local bound + (default) + --intopt use MIP presolver (default) + --nointopt do not use MIP presolver + --binarize replace general integer variables by binary ones + (assumes --intopt) + --fpump apply feasibility pump heuristic + --proxy [nnn] apply proximity search heuristic (nnn is time limit + in seconds; default is 60) + --gomory generate Gomory's mixed integer cuts + --mir generate MIR (mixed integer rounding) cuts + --cover generate mixed cover cuts + --clique generate clique cuts + --cuts generate all cuts above + --mipgap tol set relative mip gap tolerance to tol + --minisat translate integer feasibility problem to CNF-SAT + and solve it with MiniSat solver + --objbnd bound add inequality obj <= bound (minimization) or + obj >= bound (maximization) to integer feasibility + problem (assumes --minisat) +\end{verbatim} + +For description of the MPS format see Appendix \ref{champs}, page +\pageref{champs}. + +For description of the CPLEX LP format see Appendix \ref{chacplex}, +page \pageref{chacplex}. + +For description of the modeling language see the document ``Modeling +Language GNU MathProg: Language Reference'' included in the GLPK +distribution. + +For description of the DIMACS min-cost flow problem format and DIMACS +maximum flow problem format see the document ``GLPK: Graph and Network +Routines'' included in the GLPK distribution. + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk11.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk11.tex new file mode 100644 index 000000000..ff731fb56 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk11.tex @@ -0,0 +1,207 @@ +%* glpk11.tex *% + +\chapter{External Software Used In GLPK} + +In the GLPK package there are used some external software listed in +this Appendix. Note that these software are {\it not} part of GLPK, but +are used with GLPK and included in the distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{AMD} + +\noindent +AMD Version 2.2, Copyright {\copyright} 2007 by Timothy A. Davis, +Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +\para{Description} + +AMD is a set of routines for pre-ordering sparse matrices prior to +Cholesky or LU factorization, using the approximate minimum degree +ordering algorithm. + +\para{License} + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License +as published by the Free Software Foundation; either version 2.1 of +the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA. + +Permission is hereby granted to use or copy this program under the +terms of the GNU LGPL, provided that the Copyright, this License, +and the Availability of the original version is retained on all +copies. User documentation of any code that uses this code or any +modified version of this code must cite the Copyright, this License, +the Availability note, and ``Used by permission.'' Permission to +modify the code and to distribute modified code is granted, provided +the Copyright, this License, and the Availability note are retained, +and a notice that the code was modified is included. + +AMD is available under alternate licences; contact T. Davis for +details. + +\para{Availability} + +\noindent +\url{http://www.cise.ufl.edu/research/sparse/amd} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{COLAMD/SYMAMD} + +\noindent +COLAMD/SYMAMD Version 2.7, Copyright {\copyright} 1998-2007, Timothy A. +Davis, All Rights Reserved. + +\para{Description} + +colamd: an approximate minimum degree column ordering algorithm, for +LU factorization of symmetric or unsymmetric matrices, QR factorization, +least squares, interior point methods for linear programming problems, +and other related problems. + +symamd: an approximate minimum degree ordering algorithm for Cholesky +factorization of symmetric matrices. + +\para{Authors} + +The authors of the code itself are Stefan I. Larimore and Timothy A. +Davis (davis at cise.ufl.edu), University of Florida. The algorithm +was developed in collaboration with John Gilbert, Xerox PARC, and +Esmond Ng, Oak Ridge National Laboratory. + +\para{License} + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License +as published by the Free Software Foundation; either version 2.1 of +the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA. + +Permission is hereby granted to use or copy this program under the +terms of the GNU LGPL, provided that the Copyright, this License, +and the Availability of the original version is retained on all +copies. User documentation of any code that uses this code or any +modified version of this code must cite the Copyright, this License, +the Availability note, and ``Used by permission.'' Permission to +modify the code and to distribute modified code is granted, provided +the Copyright, this License, and the Availability note are retained, +and a notice that the code was modified is included. + +COLAMD is also available under alternate licenses, contact T. Davis for +details. + +\para{Availability} + +\noindent +\url{http://www.cise.ufl.edu/research/sparse/colamd} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%\newpage + +\section{MiniSat} + +\noindent +MiniSat-C v1.14.1, Copyright {\copyright} 2005, Niklas Sorensson. + +\para{Description} + +MiniSat is a minimalistic implementation of a Chaff-like SAT solver +based on the two-literal watch scheme for fast BCP and clause learning +by conflict analysis. + +\newpage + +\para{License} + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +\para{Availability} + +\noindent +\url{http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\section{zlib} + +\noindent +zlib version 1.2.5, Copyright {\copyright} 1995--2010 Jean-loup Gailly +and Mark Adler. + +\para{Description} + +zlib is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by +RFCs (Request for Comments) 1950 to 1952 in the files +\verb|rfc1950.txt| (zlib format), \verb|rfc1951.txt| (deflate format) +and \verb|rfc1952.txt| (gzip format). + +\para{License} + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +\hfill Jean-loup Gailly + +\hfill Mark Adler + +\para{Availability} + +\noindent +\url{http://www.zlib.net/} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/glpk12.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk12.tex new file mode 100644 index 000000000..ea69587a0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/glpk12.tex @@ -0,0 +1,710 @@ +%* glpk12.tex *% + +\begin{footnotesize} + +\chapter*{\sf\bfseries GNU General Public License} +\addcontentsline{toc}{chapter}{GNU General Public License} + +\begin{center} +{\bf Version 3, 29 June 2007} +\end{center} + +\begin{quotation} +\noindent +Copyright {\copyright} 2007 Free Software Foundation, Inc. +\verb|| +\end{quotation} + +\begin{quotation} +\noindent +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +\end{quotation} + +\medskip\para{\normalsize 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. + +\newpage + +\medskip\para{\normalsize TERMS AND CONDITIONS} + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize 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. + +\medskip\para{\normalsize END OF TERMS AND CONDITIONS} + +\newpage + +\medskip\para{\normalsize How to Apply These Terms to Your New Programs} + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the ``copyright'' line and a pointer to where the full notice is found. + +\begin{verbatim} + + 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 . +\end{verbatim} + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +\begin{verbatim} + 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. +\end{verbatim} + +\noindent +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, your +program's commands might be different; for a GUI interface, you would +use an ``about box''. + + You should also get your employer (if you work as a programmer) or +school, if any, to sign a ``copyright disclaimer'' for the program, if +necessary. For more information on this, and how to apply and follow the +GNU GPL, see \verb||. + + The GNU General Public License does not permit incorporating your +program into proprietary programs. If your program is a subroutine +library, you may consider it more useful to permit linking proprietary +applications with the library. If this is what you want to do, use the +GNU Lesser General Public License instead of this License. But first, +please read \verb||. + +\end{footnotesize} + +%* eof *% diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.pdf new file mode 100644 index 000000000..110b92455 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.tex new file mode 100644 index 000000000..41e92e913 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl.tex @@ -0,0 +1,4301 @@ +%* gmpl.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013, 2014, 2015, 2016 Andrew Makhorin, Department +% for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. +% All rights reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +% To produce gmpl.pdf from gmpl.tex run the following two commands: +% latex gmpl.tex +% dvipdfm -p letter gmpl.dvi +% Note: You need TeX Live 2010 or later version. + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries Modeling Language GNU MathProg +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Language Reference +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.58 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, February 2016) +\end{Large} + +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016 Andrew Makhorin, +Department for Applied Informatics, Moscow Aviation Institute, Moscow, +Russia. All rights reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that +the entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Introduction} + +{\it GNU MathProg} is a modeling language intended for describing +linear mathematical programming models.\footnote{The GNU MathProg +language is a subset of the AMPL language. Its GLPK implementation is +mainly based on the paper: {\it Robert Fourer}, {\it David M. Gay}, and +{\it Brian W. Kernighan}, ``A Modeling Language for Mathematical +Programming.'' {\it Management Science} 36 (1990), pp.~519-54.} + +Model descriptions written in the GNU MathProg language consist of +a set of statements and data blocks constructed by the user from the +language elements described in this document. + +In a process called {\it translation}, a program called the {\it model +translator} analyzes the model description and translates it into +internal data structures, which may be then used either for generating +mathematical programming problem instance or directly by a program +called the {\it solver} to obtain numeric solution of the problem. + +\section{Linear programming problem} +\label{problem} + +In MathProg the linear programming (LP) problem is stated as follows: + +\medskip + +\noindent\hspace{1in}minimize (or maximize) +$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ +\noindent\hspace{1in}subject to linear constraints +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} +L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ +L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ +\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ +\end{array}\eqno(1.2) +$$ +\noindent\hspace{1in}and bounds of variables +$$ +\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} +l_1&\leq&x_1&\leq&u_1\\ +l_2&\leq&x_2&\leq&u_2\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_n&\leq&x_n&\leq&u_n\\ +\end{array}\eqno(1.3) +$$ + +\newpage + +\noindent +where $x_1$, $x_2$, \dots, $x_n$ are variables; $z$ is the objective +function; $c_1$, $c_2$, \dots, $c_n$ are objective coefficients; $c_0$ +is the constant term (``shift'') of the objective function; $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are constraint coefficients; $L_1$, $L_2$, +\dots, $L_m$ are lower constraint bounds; $U_1$, $U_2$, \dots, $U_m$ +are upper constraint bounds; $l_1$, $l_2$, \dots, $l_n$ are lower +bounds of variables; $u_1$, $u_2$, \dots, $u_n$ are upper bounds of +variables. + +Bounds of variables and constraint bounds can be finite as well as +infinite. Besides, lower bounds can be equal to corresponding upper +bounds. Thus, the following types of variables and constraints are +allowed: + +\medskip + +{\def\arraystretch{1.4} +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +$-\infty$&$<$&$x$&$<$&$+\infty$&Free (unbounded) variable\\ +$l$&$\leq$&$x$&$<$&$+\infty$&Variable with lower bound\\ +$-\infty$&$<$&$x$&$\leq$&$u$&Variable with upper bound\\ +$l$&$\leq$&$x$&$\leq$&$u$&Double-bounded variable\\ +$l$&$=$&$x$&=&$u$&Fixed variable\\ +\end{tabular} + +\noindent\hfil +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Free (unbounded) linear +form\\ +$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Inequality constraint ``greater +than or equal to''\\ +$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Inequality constraint ``less +than or equal to''\\ +$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Double-bounded inequality +constraint\\ +$L$&$=$&$\sum a_jx_j$&=&$U$&Equality constraint\\ +\end{tabular} +} + +\medskip + +In addition to pure LP problems MathProg also allows mixed integer +linear programming (MIP) problems, where some or all variables are +restricted to be integer or binary. + +\section{Model objects} + +In MathProg the model is described in terms of sets, parameters, +variables, constraints, and objectives, which are called {\it model +objects}. + +The user introduces particular model objects using the language +statements. Each model object is provided with a symbolic name which +uniquely identifies the object and is intended for referencing +purposes. + +Model objects, including sets, can be multidimensional arrays built +over indexing sets. Formally, $n$-dimensional array $A$ is the mapping: +$$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ +where $\Delta\subseteq S_1\times\dots\times S_n$ is a subset of the +Cartesian product of indexing sets, $\Xi$ is a set of array members. +In MathProg the set $\Delta$ is called the {\it subscript domain}. Its +members are $n$-tuples $(i_1,\dots,i_n)$, where $i_1\in S_1$, \dots, +$i_n\in S_n$. + +If $n=0$, the Cartesian product above has exactly one member (namely, +0-tuple), so it is convenient to think scalar objects as 0-dimensional +arrays having one member. + +\newpage + +The type of array members is determined by the type of corresponding +model object as follows: + +\medskip + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Model object&Array member\\ +\hline +Set&Elemental plain set\\ +Parameter&Number or symbol\\ +Variable&Elemental variable\\ +Constraint&Elemental constraint\\ +Objective&Elemental objective\\ +\end{tabular} + +\medskip + +In order to refer to a particular object member the object should be +provided with {\it subscripts}. For example, if $a$ is a 2-dimensional +parameter defined over $I\times J$, a reference to its particular +member can be written as $a[i,j]$, where $i\in I$ and $j\in J$. It is +understood that scalar objects being 0-dimensional need no subscripts. + +\section{Structure of model description} + +It is sometimes desirable to write a model which, at various points, +may require different data for each problem instance to be solved using +that model. For this reason in MathProg the model description consists +of two parts: the {\it model section} and the {\it data section}. + +The model section is a main part of the model description that contains +declarations of model objects and is common for all problems based on +the corresponding model. + +The data section is an optional part of the model description that +contains data specific for a particular problem instance. + +Depending on what is more convenient the model and data sections can be +placed either in one file or in two separate files. The latter feature +allows having arbitrary number of different data sections to be used +with the same model section. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Coding model description} +\label{coding} + +The model description is coded in a plain text format using ASCII +character set. Characters valid in the model description are the +following: + +\begin{itemize} +\item alphabetic characters:\\ +\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ +\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| +\item numeric characters:\\ +\verb|0 1 2 3 4 5 6 7 8 9| +\item special characters:\\ +\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? +\item white-space characters:\\ +\verb|SP HT CR NL VT FF| +\end{itemize} + +Within string literals and comments any ASCII characters (except +control characters) are valid. + +White-space characters are non-significant. They can be used freely +between lexical units to improve readability of the model description. +They are also used to separate lexical units from each other if there +is no other way to do that. + +Syntactically model description is a sequence of lexical units in the +following categories: + +\begin{itemize} +\item symbolic names; +\item numeric literals; +\item string literals; +\item keywords; +\item delimiters; +\item comments. +\end{itemize} + +The lexical units of the language are discussed below. + +\newpage + +\section{Symbolic names} + +A {\it symbolic name} consists of alphabetic and numeric characters, +the first of which should be alphabetic. All symbolic names are +distinct (case sensitive). + +\para{Examples} + +\begin{verbatim} +alpha123 +This_is_a_name +_P123_abc_321 +\end{verbatim} + +Symbolic names are used to identify model objects (sets, parameters, +variables, constraints, objectives) and dummy indices. + +All symbolic names (except names of dummy indices) should be unique, +i.e. the model description should have no objects with identical names. +Symbolic names of dummy indices should be unique within the scope, +where they are valid. + +\section{Numeric literals} + +A {\it numeric literal} has the form {\it xx}{\tt E}{\it syy}, where +{\it xx} is a number with optional decimal point, {\it s} is the sign +{\tt+} or {\tt-}, {\it yy} is a decimal exponent. The letter {\tt E} is +case insensitive and can be coded as {\tt e}. + +\para{Examples} + +\begin{verbatim} +123 +3.14159 +56.E+5 +.78 +123.456e-7 +\end{verbatim} + +Numeric literals are used to represent numeric quantities. They have +obvious fixed meaning. + +\section{String literals} + +A {\it string literal} is a sequence of arbitrary characters enclosed +either in single quotes or in double quotes. Both these forms are +equivalent. + +If a single quote is part of a string literal enclosed in single +quotes, it should be coded twice. Analogously, if a double quote is +part of a string literal enclosed in double quotes, it should be coded +twice. + +\para{Examples} + +\begin{verbatim} +'This is a string' +"This is another string" +'That''s all' +"""Hello there,"" said the captain." +\end{verbatim} + +String literals are used to represent symbolic quantities. + +\section{Keywords} + +A {\it keyword} is a sequence of alphabetic characters and possibly +some special characters. + +All keywords fall into two categories: {\it reserved keywords}, which +cannot be used as symbolic names, and {\it non-reserved keywords}, +which are recognized by context and therefore can be used as symbolic +names. + +The reserved keywords are the following: + +\noindent\hfil +\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} +{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ +{\tt by}&{\tt if}&{\tt not}&{\tt within}\\ +{\tt cross}&{\tt in}&{\tt or}\\ +{\tt diff}&{\tt inter}&{\tt symdiff}\\ +{\tt div}&{\tt less}&{\tt then}\\ +\end{tabular} + +Non-reserved keywords are described in following sections. + +All the keywords have fixed meaning, which will be explained on +discussion of corresponding syntactic constructions, where the keywords +are used. + +\section{Delimiters} + +A {\it delimiter} is either a single special character or a sequence of +two special characters as follows: + +\noindent\hfil +\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} +p{.3in}p{.3in}@{}} +{\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}& +{\tt>>}\\ +{\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}& +{\tt\char126}&{\tt]}&{\tt<-}\\ +{\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ +{\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ +\end{tabular} + +If the delimiter consists of two characters, there should be no spaces +between the characters. + +All the delimiters have fixed meaning, which will be explained on +discussion corresponding syntactic constructions, where the delimiters +are used. + +\section{Comments} + +For documenting purposes the model description can be provided with +{\it comments}, which may have two different forms. The first form is +a {\it single-line comment}, which begins with the character {\tt\#} +and extends until end of line. The second form is a {\it comment +sequence}, which is a sequence of any characters enclosed within +{\tt/*} and {\tt*/}. + +\para{Examples} + +\begin{verbatim} +param n := 10; # This is a comment +/* This is another comment */ +\end{verbatim} + +Comments are ignored by the model translator and can appear anywhere in +the model description, where white-space characters are allowed. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Expressions} + +An {\it expression} is a rule for computing a value. In model +description expressions are used as constituents of certain statements. + +In general case expressions consist of operands and operators. + +Depending on the type of the resultant value all expressions fall into +the following categories: + +\vspace*{-8pt} + +\begin{itemize} +\item numeric expressions; +\item symbolic expressions; +\item indexing expressions; +\item set expressions; +\item logical expressions; +\item linear expressions. +\end{itemize} + +\vspace*{-8pt} + +\section{Numeric expressions} + +A {\it numeric expression} is a rule for computing a single numeric +value represented as a floating-point number. + +The primary numeric expression may be a numeric literal, dummy index, +unsubscripted parameter, subscripted parameter, built-in function +reference, iterated numeric expression, conditional numeric expression, +or another numeric expression enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|1.23 |&(numeric literal)\\ +\verb|j|&(dummy index)\\ +\verb|time|&(unsubscripted parameter)\\ +\verb|a['May 2003',j+1]|&(subscripted parameter)\\ +\verb|abs(b[i,j])|&(function reference)\\ +\end{tabular} + +\newpage + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|sum{i in S diff T} alpha[i] * b[i,j]|&(iterated expression)\\ +\verb|if i in I then 2 * p else q[i+1]|&(conditional expression)\\ +\verb|(b[i,j] + .5 * c)|&(parenthesized expression)\\ +\end{tabular} + +More general numeric expressions containing two or more primary numeric +expressions may be constructed by using certain arithmetic operators. + +\para{Examples} + +\begin{verbatim} +j+1 +2 * a[i-1,j+1] - b[i,j] +sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] +(if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) +\end{verbatim} + +\subsection{Numeric literals} + +If the primary numeric expression is a numeric literal, the resultant +value is obvious. + +\subsection{Dummy indices} + +If the primary numeric expression is a dummy index, the resultant value +is current value assigned to that dummy index. + +\subsection{Unsubscripted parameters} + +If the primary numeric expression is an unsubscripted parameter (which +should be 0-dimen\-sional), the resultant value is the value of that +parameter. + +\subsection{Subscripted parameters} + +The primary numeric expression, which refers to a subscripted +parameter, has the following syntactic form: +$$ +\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} +$$ +where {\it name} is the symbolic name of the parameter, $i_1$, $i_2$, +\dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the parameter with which the subscript list is associated. + +Actual values of subscript expressions are used to identify +a particular member of the parameter that determines the resultant +value of the primary expression. + +\newpage + +\subsection{Function references} + +In MathProg there exist the following built-in functions which may be +used in numeric expressions: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt abs(}$x${\tt)}&$|x|$, absolute value of $x$\\ +{\tt atan(}$x${\tt)}&$\arctan x$, principal value of the arc tangent of +$x$ (in radians)\\ +{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, principal value of the +arc tangent of $y/x$ (in radians). In this case the signs of both +arguments $y$ and $x$ are used to determine the quadrant of the +resultant value\\ +{\tt card(}$X${\tt)}&$|X|$, cardinality (the number of elements) of +set $X$\\ +{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, smallest integer not less than +$x$ (``ceiling of $x$'')\\ +{\tt cos(}$x${\tt)}&$\cos x$, cosine of $x$ (in radians)\\ +{\tt exp(}$x${\tt)}&$e^x$, base-$e$ exponential of $x$\\ +{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, largest integer not greater +than $x$ (``floor of $x$'')\\ +{\tt gmtime()}&the number of seconds elapsed since 00:00:00~Jan~1, 1970, +Coordinated Universal Time (for details see Section \ref{gmtime}, +page \pageref{gmtime})\\ +{\tt length(}$s${\tt)}&$|s|$, length of character string $s$\\ +{\tt log(}$x${\tt)}&$\log x$, natural logarithm of $x$\\ +{\tt log10(}$x${\tt)}&$\log_{10}x$, common (decimal) logarithm of $x$\\ +{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the largest +of values $x_1$, $x_2$, \dots, $x_n$\\ +{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the smallest +of values $x_1$, $x_2$, \dots, $x_n$\\ +{\tt round(}$x${\tt)}&rounding $x$ to nearest integer\\ +{\tt round(}$x${\tt,} $n${\tt)}&rounding $x$ to $n$ fractional decimal +digits\\ +{\tt sin(}$x${\tt)}&$\sin x$, sine of $x$ (in radians)\\ +{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, non-negative square root of $x$\\ +{\tt str2time(}$s${\tt,} $f${\tt)}&converting character string $s$ to +calendar time (for details see Section \ref{str2time}, page +\pageref{str2time})\\ +{\tt tan(}$x${\tt)}&$\tan x$, tangent of $x$ (in radians)\\ +{\tt trunc(}$x${\tt)}&truncating $x$ to nearest integer\\ +{\tt trunc(}$x${\tt,} $n${\tt)}&truncating $x$ to $n$ fractional +decimal digits\\ +{\tt Irand224()}&generating pseudo-random integer uniformly distributed +in $[0,2^{24})$\\ +{\tt Uniform01()}&generating pseudo-random number uniformly distributed +in $[0,1)$\\ +{\tt Uniform(}$a${\tt,} $b${\tt)}&generating pseudo-random number +uniformly distributed in $[a,b)$\\ +{\tt Normal01()}&generating Gaussian pseudo-random variate with +$\mu=0$ and $\sigma=1$\\ +{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generating Gaussian +pseudo-random variate with given $\mu$ and $\sigma$\\ +\end{tabular} + +Arguments of all built-in functions, except {\tt card}, {\tt length}, +and {\tt str2time}, should be numeric expressions. The argument of +{\tt card} should be a set expression. The argument of {\tt length} and +both arguments of {\tt str2time} should be symbolic expressions. + +The resultant value of the numeric expression, which is a function +reference, is the result of applying the function to its argument(s). + +Note that each pseudo-random generator function has a latent argument +(i.e. some internal state), which is changed whenever the function has +been applied. Thus, if the function is applied repeatedly even to +identical arguments, due to the side effect different resultant values +are always produced. + +\newpage + +\subsection{Iterated expressions} +\label{itexpr} + +An {\it iterated numeric expression} is a primary numeric expression, +which has the following syntactic form: +$$\mbox{\it iterated-operator indexing-expression integrand}$$ +where {\it iterated-operator} is the symbolic name of the iterated +operator to be performed (see below), {\it indexing-expression} is an +indexing expression which introduces dummy indices and controls +iterating, {\it integrand} is a numeric expression that participates in +the operation. + +In MathProg there exist four iterated operators, which may be used in +numeric expressions: + +{\def\arraystretch{2} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt sum}&summation&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt prod}&production&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt min}&minimum&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt max}&maximum&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +\end{tabular} +} + +\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +specified by the indexing expression which defines particular values +assigned to the dummy indices on performing the iterated operation, +$f(i_1,\dots,i_n)$ is the integrand, a numeric expression whose +resultant value depends on the dummy indices. + +The resultant value of an iterated numeric expression is the result of +applying of the iterated operator to its integrand over all $n$-tuples +contained in the domain. + +\subsection{Conditional expressions} +\label{ifthen} + +A {\it conditional numeric expression} is a primary numeric expression, +which has one of the following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ +\mbox{{\tt if} $b$ {\tt then} $x$}\\ +\end{array} +} +$$ +where $b$ is an logical expression, $x$ and $y$ are numeric +expressions. + +The resultant value of the conditional expression depends on the value +of the logical expression that follows the keyword {\tt if}. If it +takes on the value {\it true}, the value of the conditional expression +is the value of the expression that follows the keyword {\tt then}. +Otherwise, if the logical expression takes on the value {\it false}, +the value of the conditional expression is the value of the expression +that follows the keyword {\it else}. If the second, reduced form of the +conditional expression is used and the logical expression takes on the +value {\it false}, the resultant value of the conditional expression is +zero. + +\newpage + +\subsection{Parenthesized expressions} + +Any numeric expression may be enclosed in parentheses that +syntactically makes it a primary numeric expression. + +Parentheses may be used in numeric expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\subsection{Arithmetic operators} + +In MathProg there exist the following arithmetic operators, which may +be used in numeric expressions: + +\begin{tabular}{@{}ll@{}} +{\tt +} $x$&unary plus\\ +{\tt -} $x$&unary minus\\ +$x$ {\tt +} $y$&addition\\ +$x$ {\tt -} $y$&subtraction\\ +$x$ {\tt less} $y$&positive difference (if $x1$, the second form should be used. + +If the first form of the indexing entry is used, the index $i$ can be +a dummy index only (see below). If the second form is used, the indices +$i_1$, $i_2$, \dots, $i_n$ can be either dummy indices or some numeric +or symbolic expressions, where at least one index should be a dummy +index. The third, reduced form of the indexing entry has the same +effect as if there were $i$ (if $S$ is 1-dimensional) or +$i_1$, $i_2$, \dots, $i_n$ (if $S$ is $n$-dimensional) all specified as +dummy indices. + +A {\it dummy index} is an auxiliary model object, which acts like an +individual variable. Values assigned to dummy indices are components of +$n$-tuples from basic sets, i.e. some numeric and symbolic quantities. + +For referencing purposes dummy indices can be provided with symbolic +names. However, unlike other model objects (sets, parameters, etc.) +dummy indices need not be explicitly declared. Each {\it undeclared} +symbolic name being used in the indexing position of an indexing entry +is recognized as the symbolic name of corresponding dummy index. + +Symbolic names of dummy indices are valid only within the scope of the +indexing expression, where the dummy indices were introduced. Beyond +the scope the dummy indices are completely inaccessible, so the same +symbolic names may be used for other purposes, in particular, to +represent dummy indices in other indexing expressions. + +The scope of indexing expression, where implicit declarations of dummy +indices are valid, depends on the context, in which the indexing +expression is used: + +\vspace*{-8pt} + +\begin{itemize} +\item If the indexing expression is used in iterated operator, its +scope extends until the end of the integrand. +\item If the indexing expression is used as a primary set expression, +its scope extends until the end of that indexing expression. +\item If the indexing expression is used to define the subscript domain +in declarations of some model objects, its scope extends until the end +of the corresponding statement. +\end{itemize} + +\vspace*{-8pt} + +The indexing mechanism implemented by means of indexing expressions is +best explained by some examples discussed below. + +Let there be given three sets: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +A=\{4,7,9\},\\ +B=\{(1,Jan),(1,Feb),(2,Mar),(2,Apr),(3,May),(3,Jun)\},\\ +C=\{a,b,c\},\\ +\end{array} +} +$$ +where $A$ and $C$ consist of 1-tuples (singlets), $B$ consists of +2-tuples (doublets). Consider the following indexing expression: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +where {\tt i}, {\tt j}, {\tt k}, and {\tt l} are dummy indices. + +\newpage + +Although MathProg is not a procedural language, for any indexing +expression an equivalent algorithmic description can be given. In +particular, the algorithmic description of the indexing expression +above could look like follows: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\it action};\\ +\end{tabular} + +\noindent where the dummy indices $i$, $j$, $k$, $l$ are consecutively +assigned corresponding components of $n$-tuples from the basic sets $A$, +$B$, $C$, and {\it action} is some action that depends on the context, +where the indexing expression is used. For example, if the action were +printing current values of dummy indices, the printout would look like +follows: + +\noindent\hfil +\begin{tabular}{@{}llll@{}} +$i=4$&$j=1$&$k=Jan$&$l=a$\\ +$i=4$&$j=1$&$k=Jan$&$l=b$\\ +$i=4$&$j=1$&$k=Jan$&$l=c$\\ +$i=4$&$j=1$&$k=Feb$&$l=a$\\ +$i=4$&$j=1$&$k=Feb$&$l=b$\\ +\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +$i=9$&$j=3$&$k=Jun$&$l=b$\\ +$i=9$&$j=3$&$k=Jun$&$l=c$\\ +\end{tabular} + +Let the example indexing expression be used in the following iterated +operation: +$$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +where {\tt p} is a 4-dimensional numeric parameter or some numeric +expression whose resultant value depends on {\tt i}, {\tt j}, {\tt k}, +and {\tt l}. In this case the action is summation, so the resultant +value of the primary numeric expression is: +$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +Now let the example indexing expression be used as a primary set +expression. In this case the action is gathering all 4-tuples +(quadruplets) of the form $(i,j,k,l)$ in one set, so the resultant +value of such operation is simply the Cartesian product of the basic +sets: +$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +Note that in this case the same indexing expression might be written in +the reduced form: +$$\mbox{{\tt\{A, B, C\}}}$$ +because the dummy indices $i$, $j$, $k$, and $l$ are not referenced and +therefore their symbolic names need not be specified. + +\newpage + +Finally, let the example indexing expression be used as the subscript +domain in the declaration of a 4-dimensional model object, say, +a numeric parameter: +$$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ + +\noindent In this case the action is generating the parameter members, +where each member has the form $p[i,j,k,l]$. + +As was said above, some indices in the second form of indexing entries +may be numeric or symbolic expressions, not only dummy indices. In this +case resultant values of such expressions play role of some logical +conditions to select only that $n$-tuples from the Cartesian product of +basic sets that satisfy these conditions. + +Consider, for example, the following indexing expression: +$$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +where {\tt i}, {\tt k}, {\tt l} are dummy indices, and {\tt i-1} is +a numeric expression. The algorithmic decsription of this indexing +expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf and} $j=i-1$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\it action};\\ +\end{tabular} + +\noindent Thus, if this indexing expression were used as a primary set +expression, the resultant set would be the following: +$$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +Should note that in this case the resultant set consists of 3-tuples, +not of 4-tuples, because in the indexing expression there is no dummy +index that corresponds to the first component of 2-tuples from the set +$B$. + +The general rule is: the number of components of $n$-tuples defined by +an indexing expression is the same as the number of dummy indices in +that expression, where the correspondence between dummy indices and +components on $n$-tuples in the resultant set is positional, i.e. the +first dummy index corresponds to the first component, the second dummy +index corresponds to the second component, etc. + +In some cases it is needed to select a subset from the Cartesian +product of some sets. This may be attained by using an optional logical +predicate, which is specified in the indexing expression. + +Consider, for example, the following indexing expression: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +where the logical expression following the colon is a predicate. The +algorithmic description of this indexing expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf for all} $i\in A$ {\bf do}\\ +\hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +\hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +\hspace{48pt}{\bf if} $i\leq 5$ {\bf and} $k\neq`Mar'$ {\bf then}\\ +\hspace{64pt}{\it action};\\ +\end{tabular} + +\noindent Thus, if this indexing expression were used as a primary set +expression, the resultant set would be the following: +$$\{(4,1,Jan,a),(4,1,Feb,a),(4,2,Apr,a),\dots,(4,3,Jun,c)\}.$$ + +If no predicate is specified in the indexing expression, one, which +takes on the value {\it true}, is assumed. + +\section{Set expressions} + +A {\it set expression} is a rule for computing an elemental set, i.e. +a collection of $n$-tuples, where components of $n$-tuples are numeric +and symbolic quantities. + +The primary set expression may be a literal set, unsubscripted set, +subscripted set, ``arithmetic'' set, indexing expression, iterated set +expression, conditional set expression, or another set expression +enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(literal set)\\ +\verb|I| &(unsubscripted set)\\ +\verb|S[i-1,j+1]| &(subscripted set)\\ +\verb|1..t-1 by 2| &(``arithmetic'' set)\\ +\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(indexing expression)\\ +\verb|setof{i in I, j in J}(i+1,j-1)| &(iterated set expression)\\ +\verb|if i < j then S[i,j] else F diff S[i,j]| &(conditional set +expression)\\ +\verb|(1..10 union 21..30)| &(parenthesized set expression)\\ +\end{tabular} + +More general set expressions containing two or more primary set +expressions may be constructed by using certain set operators. + +\para{Examples} + +\begin{verbatim} +(A union B) inter (I cross J) +1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) +\end{verbatim} + +\subsection{Literal sets} + +A {\it literal set} is a primary set expression, which has the +following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +\mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +\end{array} +} +$$ +where $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ are numeric or +symbolic expressions. + +If the first form is used, the resultant set consists of 1-tuples +(singlets) enumerated within the curly braces. It is allowed to specify +an empty set as {\tt\{\ \}}, which has no 1-tuples. If the second form +is used, the resultant set consists of $n$-tuples enumerated within the +curly braces, where a particular $n$-tuple consists of corresponding +components enumerated within the parentheses. All $n$-tuples should +have the same number of components. + +\subsection{Unsubscripted sets} + +If the primary set expression is an unsubscripted set (which should be +0-dimen\-sional), the resultant set is an elemental set associated with +the corresponding set object. + +\subsection{Subscripted sets} + +The primary set expression, which refers to a subscripted set, has the +following syntactic form: +$$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +where {\it name} is the symbolic name of the set object, $i_1$, $i_2$, +\dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the set object with which the subscript list is associated. + +Actual values of subscript expressions are used to identify a +particular member of the set object that determines the resultant set. + +\subsection{``Arithmetic'' sets} + +The primary set expression, which is an ``arithmetic'' set, has the +following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +\mbox{$t_0$ {\tt..} $t_1$}\\ +\end{array} +} +$$ +where $t_0$, $t_1$, and $\delta t$ are numeric expressions (the value +of $\delta t$ should not be zero). The second form is equivalent to the +first form, where $\delta t=1$. + +If $\delta t>0$, the resultant set is determined as follows: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +Otherwise, if $\delta t<0$, the resultant set is determined as follows: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ + +\subsection{Indexing expressions} + +If the primary set expression is an indexing expression, the resultant +set is determined as described above in Section \ref{indexing}, page +\pageref{indexing}. + +\newpage + +\subsection{Iterated expressions} + +An {\it iterated set expression} is a primary set expression, which has +the following syntactic form: +$$\mbox{{\tt setof} {\it indexing-expression} {\it integrand}}$$ +where {\it indexing-expression} is an indexing expression, which +introduces dummy indices and controls iterating, {\it integrand} is +either a single numeric or symbolic expression or a list of numeric and +symbolic expressions separated by commae and enclosed in parentheses. + +If the integrand is a single numeric or symbolic expression, the +resultant set consists of 1-tuples and is determined as follows: +$$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +\noindent where $x$ is a value of the integrand, $i_1$, \dots, $i_n$ +are dummy indices introduced in the indexing expression, $\Delta$ is +the domain, a set of $n$-tuples specified by the indexing expression, +which defines particular values assigned to the dummy indices on +performing the iterated operation. + +If the integrand is a list containing $m$ numeric and symbolic +expressions, the resultant set consists of $m$-tuples and is determined +as follows: +$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +where $x_1$, \dots, $x_m$ are values of the expressions in the +integrand list, $i_1$, \dots, $i_n$ and $\Delta$ have the same meaning +as above. + +\subsection{Conditional expressions} + +A {\it conditional set expression} is a primary set expression that has +the following syntactic form: +$$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +where $b$ is an logical expression, $X$ and $Y$ are set expressions, +which should define sets of the same dimension. + +The resultant value of the conditional expression depends on the value +of the logical expression that follows the keyword {\tt if}. If it +takes on the value {\it true}, the resultant set is the value of the +expression that follows the keyword {\tt then}. Otherwise, if the +logical expression takes on the value {\it false}, the resultant set is +the value of the expression that follows the keyword {\tt else}. + +\subsection{Parenthesized expressions} + +Any set expression may be enclosed in parentheses that syntactically +makes it a primary set expression. + +Parentheses may be used in set expressions, as in algebra, to specify +the desired order in which operations are to be performed. Where +parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\newpage + +\subsection{Set operators} + +In MathProg there exist the following set operators, which may be used +in set expressions: + +\begin{tabular}{@{}ll@{}} +$X$ {\tt union} $Y$&union $X\cup Y$\\ +$X$ {\tt diff} $Y$&difference $X\backslash Y$\\ +$X$ {\tt symdiff} $Y$&symmetric difference +$X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +$X$ {\tt inter} $Y$&intersection $X\cap Y$\\ +$X$ {\tt cross} $Y$&cross (Cartesian) product $X\times Y$\\ +\end{tabular} + +\noindent where $X$ and Y are set expressions, which should define sets +of identical dimension (except the Cartesian product). + +If the expression includes more than one set operator, all operators +are performed from left to right according to the hierarchy of +operations (see below). + +The resultant value of the expression, which contains set operators, is +the result of applying the operators to their operands. + +The dimension of the resultant set, i.e. the dimension of $n$-tuples, +of which the resultant set consists of, is the same as the dimension of +the operands, except the Cartesian product, where the dimension of the +resultant set is the sum of the dimensions of its operands. + +\subsection{Hierarchy of operations} + +The following list shows the hierarchy of operations in set +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of numeric operations&1st-7th\\ +Evaluation of symbolic operations&8th-9th\\ +Evaluation of iterated or ``arithmetic'' set ({\tt setof}, {\tt..})& +10th\\ +Cartesian product ({\tt cross})&11th\\ +Intersection ({\tt inter})&12th\\ +Union and difference ({\tt union}, {\tt diff}, {\tt symdiff})&13th\\ +Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& +14th\\ +\end{tabular} + +This hierarchy has the same meaning as was explained above for numeric +expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\newpage + +\section{Logical expressions} + +A {\it logical expression} is a rule for computing a single logical +value, which can be either {\it true} or {\it false}. + +The primary logical expression may be a numeric expression, relational +expression, iterated logical expression, or another logical expression +enclosed in parentheses. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|i+1| &(numeric expression)\\ +\verb|a[i,j] < 1.5| &(relational expression)\\ +\verb|s[i+1,j-1] <> 'Mar' & year | &(relational expression)\\ +\verb|(i+1,'Jan') not in I cross J| &(relational expression)\\ +\verb|S union T within A[i] inter B[j]| &(relational expression)\\ +\verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(iterated logical +expression)\\ +\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(parenthesized logical +expression)\\ +\end{tabular} + +More general logical expressions containing two or more primary logical +expressions may be constructed by using certain logical operators. + +\para{Examples} + +\begin{verbatim} +not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +(i,j) in S or (i,j) not in T diff U +\end{verbatim} + +\vspace*{-8pt} + +\subsection{Numeric expressions} + +The resultant value of the primary logical expression, which is a +numeric expression, is {\it true}, if the resultant value of the +numeric expression is non-zero. Otherwise the resultant value of the +logical expression is {\it false}. + +\vspace*{-8pt} + +\subsection{Relational operators} + +In MathProg there exist the following relational operators, which may +be used in logical expressions: + +\begin{tabular}{@{}ll@{}} +$x$ {\tt<} $y$&test on $x=} $y$&test on $x\geq y$\\ +$x$ {\tt>} $y$&test on $x>y$\\ +$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&test on $x\neq y$\\ +$x$ {\tt in} $Y$&test on $x\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&test on +$(x_1,\dots,x_n)\in Y$\\ +$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&test on $x\not\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&test on +$(x_1,\dots,x_n)\not\in Y$\\ +$X$ {\tt within} $Y$&test on $X\subseteq Y$\\ +$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&test on +$X\not\subseteq Y$\\ +\end{tabular} + +\noindent where $x$, $x_1$, \dots, $x_n$, $y$ are numeric or symbolic +expressions, $X$ and $Y$ are set expression. + +\newpage + +1. In the operations {\tt in}, {\tt not in}, and {\tt !in} the +number of components in the first operands should be the same as the +dimension of the second operand. + +2. In the operations {\tt within}, {\tt not within}, and {\tt !within} +both operands should have identical dimension. + +All the relational operators listed above have their conventional +mathematical meaning. The resultant value is {\it true}, if +corresponding relation is satisfied for its operands, otherwise +{\it false}. (Note that symbolic values are ordered lexicographically, +and any numeric value precedes any symbolic value.) + +\subsection{Iterated expressions} + +An {\it iterated logical expression} is a primary logical expression, +which has the following syntactic form: +$$\mbox{{\it iterated-operator} {\it indexing-expression} +{\it integrand}}$$ +where {\it iterated-operator} is the symbolic name of the iterated +operator to be performed (see below), {\it indexing-expression} is an +indexing expression which introduces dummy indices and controls +iterating, {\it integrand} is a numeric expression that participates in +the operation. + +In MathProg there exist two iterated operators, which may be used in +logical expressions: + +{\def\arraystretch{1.4} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt forall}&$\forall$-quantification&$\displaystyle +\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +{\tt exists}&$\exists$-quantification&$\displaystyle +\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +\end{tabular} +} + +\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +specified by the indexing expression which defines particular values +assigned to the dummy indices on performing the iterated operation, +$f(i_1,\dots,i_n)$ is the integrand, a logical expression whose +resultant value depends on the dummy indices. + +For $\forall$-quantification the resultant value of the iterated +logical expression is {\it true}, if the value of the integrand is +{\it true} for all $n$-tuples contained in the domain, otherwise +{\it false}. + +For $\exists$-quantification the resultant value of the iterated +logical expression is {\it false}, if the value of the integrand is +{\it false} for all $n$-tuples contained in the domain, otherwise +{\it true}. + +\subsection{Parenthesized expressions} + +Any logical expression may be enclosed in parentheses that +syntactically makes it a primary logical expression. + +Parentheses may be used in logical expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant value is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\newpage + +\subsection{Logical operators} + +In MathProg there exist the following logical operators, which may be +used in logical expressions: + +\begin{tabular}{@{}ll@{}} +{\tt not} $x$, {\tt!}$x$&negation $\neg\ x$\\ +$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunction (logical ``and'') +$x\;\&\;y$\\ +$x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunction (logical ``or'') +$x\vee y$\\ +\end{tabular} + +\noindent where $x$ and $y$ are logical expressions. + +If the expression includes more than one logical operator, all +operators are performed from left to right according to the hierarchy +of the operations (see below). The resultant value of the expression, +which contains logical operators, is the result of applying the +operators to their operands. + +\subsection{Hierarchy of operations} + +The following list shows the hierarchy of operations in logical +expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Evaluation of numeric operations&1st-7th\\ +Evaluation of symbolic operations&8th-9th\\ +Evaluation of set operations&10th-14th\\ +Relational operations ({\tt<}, {\tt<=}, etc.)&15th\\ +Negation ({\tt not}, {\tt!})&16th\\ +Conjunction ({\tt and}, {\tt\&\&})&17th\\ +$\forall$- and $\exists$-quantification ({\tt forall}, {\tt exists})& +18th\\ +Disjunction ({\tt or}, {\tt||})&19th\\ +\end{tabular} + +This hierarchy has the same meaning as was explained above for numeric +expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\section{Linear expressions} + +A {\it linear expression} is a rule for computing so called +a {\it linear form} or simply a {\it formula}, which is a linear (or +affine) function of elemental variables. + +The primary linear expression may be an unsubscripted variable, +subscripted variable, iterated linear expression, conditional linear +expression, or another linear expression enclosed in parentheses. + +It is also allowed to use a numeric expression as the primary linear +expression, in which case the resultant value of the numeric expression +is automatically converted to a formula that includes the constant term +only. + +\para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|z| &(unsubscripted variable)\\ +\verb|x[i,j]| &(subscripted variable)\\ +\verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +(iterated linear expression)\\ +\verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +(conditional linear expression)\\ +\verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +(parenthesized linear expression)\\ +\end{tabular} + +More general linear expressions containing two or more primary linear +expressions may be constructed by using certain arithmetic operators. + +\para{Examples} + +\begin{verbatim} +2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z +(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) +\end{verbatim} + +\vspace*{-5pt} + +\subsection{Unsubscripted variables} + +If the primary linear expression is an unsubscripted variable (which +should be 0-dimensional), the resultant formula is that unsubscripted +variable. + +\vspace*{-5pt} + +\subsection{Subscripted variables} + +The primary linear expression, which refers to a subscripted variable, +has the following syntactic form: +$$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +where {\it name} is the symbolic name of the model variable, $i_1$, +$i_2$, \dots, $i_n$ are subscripts. + +Each subscript should be a numeric or symbolic expression. The number +of subscripts in the subscript list should be the same as the dimension +of the model variable with which the subscript list is associated. + +Actual values of the subscript expressions are used to identify a +particular member of the model variable that determines the resultant +formula, which is an elemental variable associated with corresponding +member. + +\vspace*{-5pt} + +\subsection{Iterated expressions} + +An {\it iterated linear expression} is a primary linear expression, +which has the following syntactic form: +$$\mbox{{\tt sum} {\it indexing-expression} {\it integrand}}$$ +where {\it indexing-expression} is an indexing expression, which +introduces dummy indices and controls iterating, {\it integrand} is +a linear expression that participates in the operation. + +The iterated linear expression is evaluated exactly in the same way as +the iterated numeric expression (see Subection \ref{itexpr}, page +\pageref{itexpr}) with exception that the integrand participated in the +summation is a formula, not a numeric value. + +\vspace*{-5pt} + +\subsection{Conditional expressions} + +A {\it conditional linear expression} is a primary linear expression, +which has one of the following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +\mbox{{\tt if} $b$ {\tt then} $f$}\\ +\end{array} +} +$$ +where $b$ is an logical expression, $f$ and $g$ are linear expressions. + +\newpage + +The conditional linear expression is evaluated exactly in the same way +as the conditional numeric expression (see Subsection \ref{ifthen}, +page \pageref{ifthen}) with exception that operands participated in the +operation are formulae, not numeric values. + +\subsection{Parenthesized expressions} + +Any linear expression may be enclosed in parentheses that syntactically +makes it a primary linear expression. + +Parentheses may be used in linear expressions, as in algebra, to +specify the desired order in which operations are to be performed. +Where parentheses are used, the expression within the parentheses is +evaluated before the resultant formula is used. + +The resultant value of the parenthesized expression is the same as the +value of the expression enclosed within parentheses. + +\subsection{Arithmetic operators} + +In MathProg there exists the following arithmetic operators, which may +be used in linear expressions: + +\begin{tabular}{@{}ll@{}} +{\tt+} $f$&unary plus\\ +{\tt-} $f$&unary minus\\ +$f$ {\tt+} $g$&addition\\ +$f$ {\tt-} $g$&subtraction\\ +$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplication\\ +$f$ {\tt/} $x$&division +\end{tabular} + +\noindent where $f$ and $g$ are linear expressions, $x$ is a numeric +expression (more precisely, a linear expression containing only the +constant term). + +If the expression includes more than one arithmetic operator, all +operators are performed from left to right according to the hierarchy +of operations (see below). The resultant value of the expression, which +contains arithmetic operators, is the result of applying the operators +to their operands. + +\subsection{Hierarchy of operations} + +The hierarchy of arithmetic operations used in linear expressions is +the same as for numeric expressions (see Subsection \ref{hierarchy}, +page \pageref{hierarchy}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Statements} + +{\it Statements} are basic units of the model description. In MathProg +all statements are divided into two categories: declaration statements +and functional statements. + +{\it Declaration statements} (set statement, parameter statement, +variable statement, constraint statement, objective statement) are used +to declare model objects of certain kinds and define certain properties +of such objects. + +{\it Functional statements} (solve statement, check statement, display +statement, printf statement, loop statement, table statement) are +intended for performing some specific actions. + +Note that declaration statements may follow in arbitrary order, which +does not affect the result of translation. However, any model object +should be declared before it is referenced in other statements. + +\section{Set statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt set} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the set; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the set; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the set; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the set. +(Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt dimen} $n$]\hspace*{0pt}\\ +specifies the dimension of $n$-tuples which the set consists of; +\item[{\tt within} {\it expression}]\hspace*{0pt}\\ +specifies a superset which restricts the set or all its members +(elemental sets) to be within that superset; +\item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +specifies an elemental set assigned to the set or its members; +\item[{\tt default} {\it expression}]\hspace*{0pt}\\ +specifies an elemental set assigned to the set or its members whenever +no appropriate data are available in the data section. +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +set nodes; +set arcs within nodes cross nodes; +set step{s in 1..maxiter} dimen 2 := if s = 1 then arcs else step[s-1] + union setof{k in nodes, (i,k) in step[s-1], (k,j) in step[s-1]}(i,j); +set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, + default {('abc',123), (321,'cba')}; +\end{verbatim} + +The set statement declares a set. If the subscript domain is not +specified, the set is a simple set, otherwise it is an array of +elemental sets. + +The {\tt dimen} attribute specifies the dimension of $n$-tuples, which +the set (if it is a simple set) or its members (if the set is an array +of elemental sets) consist of, where $n$ should be an unsigned integer +from 1 to 20. At most one {\tt dimen} attribute can be specified. If +the {\tt dimen} attribute is not specified, the dimension of $n$-tuples +is implicitly determined by other attributes (for example, if there is +a set expression that follows {\tt:=} or the keyword {\tt default}, the +dimension of $n$-tuples of corresponding elemental set is used). +If no dimension information is available, {\tt dimen 1} is assumed. + +The {\tt within} attribute specifies a set expression whose resultant +value is a superset used to restrict the set (if it is a simple set) or +its members (if the set is an array of elemental sets) to be within +that superset. Arbitrary number of {\tt within} attributes may be +specified in the same set statement. + +The assign ({\tt:=}) attribute specifies a set expression used to +evaluate elemental set(s) assigned to the set (if it is a simple set) +or its members (if the set is an array of elemental sets). If the +assign attribute is specified, the set is {\it computable} and +therefore needs no data to be provided in the data section. If the +assign attribute is not specified, the set should be provided with data +in the data section. At most one assign or default attribute can be +specified for the same set. + +The {\tt default} attribute specifies a set expression used to evaluate +elemental set(s) assigned to the set (if it is a simple set) or its +members (if the set is an array of elemental sets) whenever +no appropriate data are available in the data section. If neither +assign nor default attribute is specified, missing data will cause an +error. + +\newpage + +\section{Parameter statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt param} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the parameter; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the parameter; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the parameter; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the +parameter. (Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +specifies that the parameter is integer; +\item[{\tt binary}]\hspace*{0pt}\\ +specifies that the parameter is binary; +\item[{\tt symbolic}]\hspace*{0pt}\\ +specifies that the parameter is symbolic; +\item[{\it relation expression}]\hspace*{0pt}\\ +(where {\it relation} is one of: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +specifies a condition that restricts the parameter or its members to +satisfy that condition; +\item[{\tt in} {\it expression}]\hspace*{0pt}\\ +specifies a superset that restricts the parameter or its members to be +in that superset; +\item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +specifies a value assigned to the parameter or its members; +\item[{\tt default} {\it expression}]\hspace*{0pt}\\ +specifies a value assigned to the parameter or its members whenever +no appropriate data are available in the data section. +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +param units{raw, prd} >= 0; +param profit{prd, 1..T+1}; +param N := 20 integer >= 0 <= 100; +param comb 'n choose k' {n in 0..N, k in 0..n} := + if k = 0 or k = n then 1 else comb[n-1,k-1] + comb[n-1,k]; +param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], + in C[i,j], default 0.5 * (i + j); +param month symbolic default 'May' in {'Mar', 'Apr', 'May'}; +\end{verbatim} + +The parameter statement declares a parameter. If a subscript domain is +not specified, the parameter is a simple (scalar) parameter, otherwise +it is a $n$-dimensional array. + +The type attributes {\tt integer}, {\tt binary}, and {\tt symbolic} +qualify the type of values that can be assigned to the parameter as +shown below: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Type attribute&Assigned values\\ +\hline +(not specified)&Any numeric values\\ +{\tt integer}&Only integer numeric values\\ +{\tt binary}&Either 0 or 1\\ +{\tt symbolic}&Any numeric and symbolic values\\ +\end{tabular} + +The {\tt symbolic} attribute cannot be specified along with other type +attributes. Being specified it should precede all other attributes. + +The condition attribute specifies an optional condition that restricts +values assigned to the parameter to satisfy that condition. This +attribute has the following syntactic forms: + +\begin{tabular}{@{}ll@{}} +{\tt<} $v$&check for $x=} $v$&check for $x\geq v$\\ +{\tt>} $v$&check for $x\geq v$\\ +{\tt<>} $v$, {\tt!=} $v$&check for $x\neq v$\\ +\end{tabular} + +\noindent where $x$ is a value assigned to the parameter, $v$ is the +resultant value of a numeric or symbolic expression specified in the +condition attribute. Arbitrary number of condition attributes can be +specified for the same parameter. If a value being assigned to the +parameter during model evaluation violates at least one of specified +conditions, an error is raised. (Note that symbolic values are ordered +lexicographically, and any numeric value precedes any symbolic value.) + +The {\tt in} attribute is similar to the condition attribute and +specifies a set expression whose resultant value is a superset used to +restrict numeric or symbolic values assigned to the parameter to be in +that superset. Arbitrary number of the {\tt in} attributes can be +specified for the same parameter. If a value being assigned to the +parameter during model evaluation is not in at least one of specified +supersets, an error is raised. + +The assign ({\tt:=}) attribute specifies a numeric or symbolic +expression used to compute a value assigned to the parameter (if it is +a simple parameter) or its member (if the parameter is an array). If +the assign attribute is specified, the parameter is {\it computable} +and therefore needs no data to be provided in the data section. If the +assign attribute is not specified, the parameter should be provided +with data in the data section. At most one assign or {\tt default} +attribute can be specified for the same parameter. + +The {\tt default} attribute specifies a numeric or symbolic expression +used to compute a value assigned to the parameter or its member +whenever no appropriate data are available in the data section. If +neither assign nor {\tt default} attribute is specified, missing data +will cause an error. + +\newpage + +\section{Variable statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt var} {\it name} {\it alias} {\it domain} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the variable; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the variable; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the variable; + +\noindent +{\it attrib}, \dots, {\it attrib} are optional attributes of the +variable. (Commae preceding attributes may be omitted.) + +\para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +restricts the variable to be integer; +\item[{\tt binary}]\hspace*{0pt}\\ +restricts the variable to be binary; +\item[{\tt>=} {\it expression}]\hspace*{0pt}\\ +specifies an lower bound of the variable; +\item[{\tt<=} {\it expression}]\hspace*{0pt}\\ +specifies an upper bound of the variable; +\item[{\tt=} {\it expression}]\hspace*{0pt}\\ +specifies a fixed value of the variable; +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +var x >= 0; +var y{I,J}; +var make{p in prd}, integer, >= commit[p], <= market[p]; +var store{raw, 1..T+1} >= 0; +var z{i in I, j in J} >= i+j; +\end{verbatim} + +The variable statement declares a variable. If a subscript domain is +not specified, the variable is a simple (scalar) variable, otherwise it +is a $n$-dimensional array of elemental variables. + +Elemental variable(s) associated with the model variable (if it is a +simple variable) or its members (if it is an array) correspond to the +variables in the LP/MIP problem formulation (see Section \ref{problem}, +page \pageref{problem}). Note that only elemental variables actually +referenced in some constraints and/or objectives are included in the +LP/MIP problem instance to be generated. + +The type attributes {\tt integer} and {\tt binary} restrict the +variable to be integer or binary, respectively. If no type attribute is +specified, the variable is continuous. If all variables in the model +are continuous, the corresponding problem is of LP class. If there is +at least one integer or binary variable, the problem is of MIP class. + +The lower bound ({\tt>=}) attribute specifies a numeric expression for +computing an lower bound of the variable. At most one lower bound can +be specified. By default all variables (except binary ones) have no +lower bound, so if a variable is required to be non-negative, its zero +lower bound should be explicitly specified. + +The upper bound ({\tt<=}) attribute specifies a numeric expression for +computing an upper bound of the variable. At most one upper bound +attribute can be specified. + +The fixed value ({\tt=}) attribute specifies a numeric expression for +computing a value, at which the variable is fixed. This attribute +cannot be specified along with the bound attributes. + +\section{Constraint statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][106pt]{468pt}{ +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt<=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt>=} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt<=} {\it expression} {\tt,} {\tt<=} +{\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt,} {\tt>=} {\it expression} {\tt,} {\tt>=} +{\it expression} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the constraint; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the constraint; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the constraint; + +\noindent +{\it expression} is a linear expression used to compute a component of +the constraint. (Commae following expressions may be omitted.) + +\noindent +(The keyword {\tt s.t.} may be written as {\tt subject to} or as +{\tt subj to}, or may be omitted at all.) + +\para{Examples} + +\begin{verbatim} +s.t. r: x + y + z, >= 0, <= 1; +limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd; +subject to balance{i in raw, t in 1..T}: + store[i,t+1] = store[i,t] - sum{j in prd} units[i,j] * make[j,t]; +subject to rlim 'regular-time limit' {t in time}: + sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t]; +\end{verbatim} + +The constraint statement declares a constraint. If a subscript domain +is not specified, the\linebreak constraint is a simple (scalar) +constraint, otherwise it is a $n$-dimensional array of elemental +constraints. + +Elemental constraint(s) associated with the model constraint (if it is +a simple constraint) or its members (if it is an array) correspond to +the linear constraints in the LP/MIP problem formulation (see +Section \ref{problem}, page \pageref{problem}). + +If the constraint has the form of equality or single inequality, i.e. +includes two expressions, one of which follows the colon and other +follows the relation sign {\tt=}, {\tt<=}, or {\tt>=}, both expressions +in the statement can be linear expressions. If the constraint has the +form of double inequality,\linebreak i.e. includes three expressions, +the middle expression can be a linear expression while the leftmost and +rightmost ones can be only numeric expressions. + +Generating the model is, roughly speaking, generating its constraints, +which are always evaluated for the entire subscript domain. Evaluation +of the constraints leads, in turn, to evaluation of other model objects +such as sets, parameters, and variables. + +Constructing an actual linear constraint included in the problem +instance, which (constraint) corresponds to a particular elemental +constraint, is performed as follows. + +If the constraint has the form of equality or single inequality, +evaluation of both linear expressions gives two resultant linear forms: +$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +g&=&b_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&b_0,\\ +\end{array}$$ +where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, +\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ are numeric coefficients; +$a_0$ and $b_0$ are constant terms. Then all linear terms of $f$ and +$g$ are carried to the left-hand side, and the constant terms are +carried to the right-hand side, that gives the final elemental +constraint in the standard form: +$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ + +If the constraint has the form of double inequality, evaluation of the +middle linear expression gives the resultant linear form: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +and evaluation of the leftmost and rightmost numeric expressions gives +two numeric values $l$ and $u$, respectively. Then the constant term of +the linear form is carried to both left-hand and right-handsides that +gives the final elemental constraint in the standard form: +$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + +\section{Objective statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt minimize} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt maximize} {\it name} {\it alias} {\it domain} {\tt:} +{\it expression} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the objective; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the objective; + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the objective; + +\noindent +{\it expression} is a linear expression used to compute the linear form +of the objective. + +\newpage + +\para{Examples} + +\begin{verbatim} +minimize obj: x + 1.5 * (y + z); +maximize total_profit: sum{p in prd} profit[p] * make[p]; +\end{verbatim} + +The objective statement declares an objective. If a subscript domain is +not specified, the objective is a simple (scalar) objective. Otherwise +it is a $n$-dimensional array of elemental objectives. + +Elemental objective(s) associated with the model objective (if it is a +simple objective) or its members (if it is an array) correspond to +general linear constraints in the LP/MIP problem formulation (see +Section \ref{problem}, page \pageref{problem}). However, unlike +constraints the corresponding linear forms are free (unbounded). + +Constructing an actual linear constraint included in the problem +instance, which (constraint) corresponds to a particular elemental +constraint, is performed as follows. The linear expression specified in +the objective statement is evaluated that, gives the resultant linear +form: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, +\dots, $a_n$ are numeric coefficients; $a_0$ is the constant term. Then +the linear form is used to construct the final elemental constraint in +the standard form: +$$-\infty= 0 and y >= 0; +check sum{i in ORIG} supply[i] = sum{j in DEST} demand[j]; +check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +\end{verbatim} + +The check statement allows checking the resultant value of an logical +expression specified in the statement. If the value is {\it false}, an +error is reported. + +If the subscript domain is not specified, the check is performed only +once. Specifying the subscript domain allows performing multiple check +for every $n$-tuple in the domain set. In the latter case the logical +expression may include dummy indices introduced in corresponding +indexing expression. + +\section{Display statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt display} {\it domain} {\tt:} {\it item} {\tt,} +\dots {\tt,} {\it item} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the display statement; + +\noindent +{\it item}, \dots, {\it item} are items to be displayed. (The colon +preceding the first item may be omitted.) + +\para{Examples} + +\begin{verbatim} +display: 'x =', x, 'y =', y, 'z =', z; +display sqrt(x ** 2 + y ** 2 + z ** 2); +display{i in I, j in J}: i, j, a[i,j], b[i,j]; +\end{verbatim} + +The display statement evaluates all items specified in the statement +and writes their values on the standard output (terminal) in plain text +format. + +If a subscript domain is not specified, items are evaluated and then +displayed only once. Specifying the subscript domain causes items to be +evaluated and displayed for every $n$-tuple in the domain set. In the +latter case items may include dummy indices introduced in corresponding +indexing expression. + +An item to be displayed can be a model object (set, parameter, +variable, constraint, objective) or an expression. + +If the item is a computable object (i.e. a set or parameter provided +with the assign attribute), the object is evaluated over the entire +domain and then its content (i.e. the content of the object array) is +displayed. Otherwise, if the item is not a computable object, only its +current content (i.e. members actually generated during the model +evaluation) is displayed. + +If the item is an expression, the expression is evaluated and its +resultant value is displayed. + +\section{Printf statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][64pt]{468pt}{ +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>} +{\it filename} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>>} +{\it filename} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an optional indexing expression, which specifies +a subscript domain of the printf statement; + +\noindent +{\it format} is a symbolic expression whose value specifies a format +control string. (The colon preceding the format expression may be +omitted.) + +\noindent +{\it expression}, \dots, {\it expression} are zero or more expressions +whose values have to be formatted and printed. Each expression should +be of numeric, symbolic, or logical type. + +\noindent +{\it filename} is a symbolic expression whose value specifies a name +of a text file, to which the output is redirected. The flag {\tt>} +means creating a new empty file while the flag {\tt>>} means appending +the output to an existing file. If no file name is specified, the +output is written on the standard output (terminal). + +\para{Examples} + +\begin{verbatim} +printf 'Hello, world!\n'; +printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "result.txt"; +printf{i in I, j in J}: "flow from %s to %s is %d\n", i, j, x[i,j] + >> result_file & ".txt"; +printf{i in I} 'total flow from %s is %g\n', i, sum{j in J} x[i,j]; +printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), + k, x[k]; +\end{verbatim} + +The printf statement is similar to the display statement, however, it +allows formatting data to be written. + +If a subscript domain is not specified, the printf statement is +executed only once. Specifying a subscript domain causes executing the +printf statement for every $n$-tuple in the domain set. In the latter +case the format and expression may include dummy indices introduced in +corresponding indexing expression. + +The format control string is a value of the symbolic expression +{\it format} specified in the printf statement. It is composed of zero +or more directives as follows: ordinary characters (not {\tt\%}), which +are copied unchanged to the output stream, and conversion +specifications, each of which causes evaluating corresponding +expression specified in the printf statement, formatting it, and +writing its resultant value to the output stream. + +Conversion specifications that may be used in the format control string +are the following:\linebreak {\tt d}, {\tt i}, {\tt f}, {\tt F}, +{\tt e}, {\tt E}, {\tt g}, {\tt G}, and {\tt s}. These specifications +have the same syntax and semantics as in the C programming language. + +\section{For statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt for} {\it domain} {\tt:} {\it statement} {\tt;} + +\medskip + +\hspace{6pt} {\tt for} {\it domain} {\tt:} {\tt\{} {\it statement} +\dots {\it statement} {\tt\}} {\tt;} +}} + +\medskip + +\noindent +{\it domain} is an indexing expression which specifies a subscript +domain of the for statement. (The colon following the indexing +expression may be omitted.) + +\noindent +{\it statement} is a statement, which should be executed under control +of the for statement; + +\noindent +{\it statement}, \dots, {\it statement} is a sequence of statements +(enclosed in curly braces), which should be executed under control of +the for statement. + +Only the following statements can be used within the for statement: +check, display, printf, and another for. + +\para{Examples} + +\begin{verbatim} +for {(i,j) in E: i != j} +{ printf "flow from %s to %s is %g\n", i, j, x[i,j]; + check x[i,j] >= 0; +} +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} +for {1..72} printf("*"); +\end{verbatim} + +The for statement causes a statement or a sequence of statements +specified as part of the for statement to be executed for every +$n$-tuple in the domain set. Thus, statements within the for statement +may include dummy indices introduced in corresponding indexing +expression. + +\newpage + +\section{Table statement} + +\noindent +\framebox[468pt][l]{ +\parbox[c][80pt]{468pt}{ +\hspace{6pt} {\tt table} {\it name} {\it alias} {\tt IN} {\it driver} +{\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it set} {\tt<-} {\tt[} {\it fld} {\tt,} +\dots {\tt,} {\it fld} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +{\it fld} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it fld} +{\tt;} + +\medskip + +\hspace{6pt} {\tt table} {\it name} {\it alias} {\it domain} {\tt OUT} +{\it driver} {\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it fld} +{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it fld} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the table; + +\noindent +{\it alias} is an optional string literal, which specifies an alias of +the table; + +\noindent +{\it domain} is an indexing expression, which specifies a subscript +domain of the (output) table; + +\noindent +{\tt IN} means reading data from the input table; + +\noindent +{\tt OUT} means writing data to the output table; + +\noindent +{\it driver} is a symbolic expression, which specifies the driver used +to access the table (for details see Appendix \ref{drivers}, page +\pageref{drivers}); + +\noindent +{\it arg} is an optional symbolic expression, which is an argument +pass\-ed to the table driver. This symbolic expression should not +include dummy indices specified in the domain; + +\noindent +{\it set} is the name of an optional simple set called {\it control +set}. It can be omitted along with the delimiter {\tt<-}; + +\noindent +{\it fld} is a field name. Within square brackets at least one field +should be specified. The field name following a parameter name or +expression is optional and can be omitted along with the +delimiter~{\tt\textasciitilde}, in which case the name of corresponding +model object is used as the field name; + +\noindent +{\it par} is a symbolic name of a model parameter; + +\noindent +{\it expr} is a numeric or symbolic expression. + +\para{Examples} + +\begin{verbatim} +table data IN "CSV" "data.csv": S <- [FROM,TO], d~DISTANCE, + c~COST; +table result{(f,t) in S} OUT "CSV" "result.csv": f~FROM, t~TO, + x[f,t]~FLOW; +\end{verbatim} + +The table statement allows reading data from a table into model +objects such as sets and (non-scalar) parameters as well as writing +data from the model to a table. + +\newpage + +\subsection{Table structure} + +A {\it data table} is an (unordered) set of {\it records}, where each +record consists of the same number of {\it fields}, and each field is +provided with a unique symbolic name called the {\it field name}. For +example: + +\bigskip + +\begin{tabular}{@{\hspace*{42mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c +@{\hspace*{9mm}}c} +First&Second&&Last\\ +field&field&.\ \ .\ \ .&field\\ +$\downarrow$&$\downarrow$&&$\downarrow$\\ +\end{tabular} + +\begin{tabular}{ll@{}} +Table header&$\rightarrow$\\ +First record&$\rightarrow$\\ +Second record&$\rightarrow$\\ +\\ +\hfil .\ \ .\ \ .\\ +\\ +Last record&$\rightarrow$\\ +\end{tabular} +\begin{tabular}{|l|l|c|c|} +\hline +{\tt FROM}&{\tt TO}&{\tt DISTANCE}&{\tt COST}\\ +\hline +{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +\hline +\end{tabular} + +\subsection{Reading data from input table} + +The input table statement causes reading data from the specified table +record by record. + +Once a next record has been read, numeric or symbolic values of fields, +whose names are enclosed in square brackets in the table statement, are +gathered into $n$-tuple, and if the control set is specified in the +table statement, this $n$-tuple is added to it. Besides, a numeric or +symbolic value of each field associated with a model parameter is +assigned to the parameter member identified by subscripts, which are +components of the $n$-tuple just read. + +For example, the following input table statement: + +\noindent\hfil +\verb|table data IN "...": S <- [FROM,TO], d~DISTANCE, c~COST;| + +\noindent +causes reading values of four fields named {\tt FROM}, {\tt TO}, +{\tt DISTANCE}, and {\tt COST} from each record of the specified table. +Values of fields {\tt FROM} and {\tt TO} give a pair $(f,t)$, which is +added to the control set {\tt S}. The value of field {\tt DISTANCE} is +assigned to parameter member ${\tt d}[f,t]$, and the value of field +{\tt COST} is assigned to parameter member ${\tt c}[f,t]$. + +Note that the input table may contain extra fields whose names are not +specified in the table statement, in which case values of these fields +on reading the table are ignored. + +\subsection{Writing data to output table} + +The output table statement causes writing data to the specified table. +Note that some drivers (namely, CSV and xBASE) destroy the output table +before writing data, i.e. delete all its existing records. + +Each $n$-tuple in the specified domain set generates one record written +to the output table. Values of fields are numeric or symbolic values of +corresponding expressions specified in the table statement. These +expressions are evaluated for each $n$-tuple in the domain set and, +thus, may include dummy indices introduced in the corresponding indexing +expression. + +For example, the following output table statement: + +\noindent\hfil +\verb|table result{(f,t) in S} OUT "...": f~FROM, t~TO, x[f,t]~FLOW;| + +\noindent +causes writing records, by one record for each pair $(f,t)$ in set +{\tt S}, to the output table, where each record consists of three +fields named {\tt FROM}, {\tt TO}, and {\tt FLOW}. The values written +to fields {\tt FROM} and {\tt TO} are current values of dummy indices +{\tt f} and {\tt t}, and the value written to field {\tt FLOW} is +a value of member ${\tt x}[f,t]$ of corresponding subscripted parameter +or variable. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Model data} + +{\it Model data} include elemental sets, which are ``values'' of model +sets, and numeric and symbolic values of model parameters. + +In MathProg there are two different ways to saturate model sets and +parameters with data. One way is simply providing necessary data using +the assign attribute. However, in many cases it is more practical to +separate the model itself and particular data needed for the model. For +the latter reason in MathProg there is another way, when the model +description is divided into two parts: model section and data section. + +A {\it model section} is a main part of the model description that +contains declarations of all model objects and is common for all +problems based on that model. + +A {\it data section} is an optional part of the model description that +contains model data specific for a particular problem. + +In MathProg model and data sections can be placed either in one text +file or in two separate text files. + +1. If both model and data sections are placed in one file, the file is +composed as follows: + +\bigskip + +\noindent\hfil +\framebox{\begin{tabular}{l} +{\it statement}{\tt;}\\ +{\it statement}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it statement}{\tt;}\\ +{\tt data;}\\ +{\it data block}{\tt;}\\ +{\it data block}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it data block}{\tt;}\\ +{\tt end;} +\end{tabular}} + +\newpage + +2. If the model and data sections are placed in two separate files, the +files are composed as follows: + +\bigskip + +\noindent\hfil +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\it statement}{\tt;}\\ +{\it statement}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it statement}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\\\Model file\\ +\end{tabular} +\hspace{32pt} +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\tt data;}\\ +{\it data block}{\tt;}\\ +{\it data block}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it data block}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\Data file\\ +\end{tabular} + +\bigskip + +Note: If the data section is placed in a separate file, the keyword +{\tt data} is optional and may be omitted along with the semicolon that +follows it. + +\section{Coding data section} + +The {\it data section} is a sequence of data blocks in various formats, +which are discussed in following sections. The order, in which data +blocks follow in the data section, may be arbitrary, not necessarily +the same, in which corresponding model objects follow in the model +section. + +The rules of coding the data section are commonly the same as the rules +of coding the model description (see Section \ref{coding}, page +\pageref{coding}), i.e. data blocks are composed from basic lexical +units such as symbolic names, numeric and string literals, keywords, +delimiters, and comments. However, for the sake of convenience and for +improving readability there is one deviation from the common rule: if +a string literal consists of only alphanumeric characters (including +the underscore character), the signs {\tt+} and {\tt-}, and/or the +decimal point, it may be coded without bordering by (single or double) +quotes. + +All numeric and symbolic material provided in the data section is coded +in the form of numbers and symbols, i.e. unlike the model section +no expressions are allowed in the data section. Nevertheless, the signs +{\tt+} and {\tt-} can precede numeric literals to allow coding signed +numeric quantities, in which case there should be no white-space +characters between the sign and following numeric literal (if there is +at least one white-space, the sign and following numeric literal are +recognized as two different lexical units). + +\newpage + +\section{Set data block} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt set} {\it name} {\tt,} {\it record} {\tt,} \dots +{\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt set} {\it name} {\tt[} {\it symbol} {\tt,} \dots +{\tt,} {\it symbol} {\tt]} {\tt,} {\it record} {\tt,} \dots {\tt,} +{\it record} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the set; + +\noindent +{\it symbol}, \dots, {\it symbol} are subscripts, which specify +a particular member of the set (if the set is an array, i.e. a set of +sets); + +\noindent +{\it record}, \dots, {\it record} are data records. + +\noindent +Commae preceding data records may be omitted. + +\para{Data records} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +is a non-significant data record, which may be used freely to improve +readability; +\item[{\tt(} {\it slice} {\tt)}]\hspace*{0pt}\\ +specifies a slice; +\item[{\it simple-data}]\hspace*{0pt}\\ +specifies set data in the simple format; +\item[{\tt:} {\it matrix-data}]\hspace*{0pt}\\ +specifies set data in the matrix format; +\item[{\tt(tr)} {\tt:} {\it matrix-data}]\hspace*{0pt}\\ +specifies set data in the transposed matrix format. (In this case the +colon following the keyword {\tt(tr)} may be omitted.) +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +set month := Jan Feb Mar Apr May Jun; +set month "Jan", "Feb", "Mar", "Apr", "May", "Jun"; +set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; +set A[3,'Mar'] : 1 2 3 4 := + 1 - + - - + 2 - + + - + 3 + - - + + 4 - + - + ; +set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +set B := (1,*,*) : 1 2 3 := + 1 + - - + 2 - + + + 3 - + - + (2,*,*) : 1 2 3 := + 1 + - + + 2 - - - + 3 + - - ; +\end{verbatim} + +\noindent(In these examples {\tt month} is a simple set of singlets, +{\tt A} is a 2-dimensional array of doublets, and {\tt B} is a simple +set of triplets. Data blocks for the same set are equivalent in the +sense that they specify the same data in different formats.) + +The {\it set data block} is used to specify a complete elemental set, +which is assigned to a set (if it is a simple set) or one of its +members (if the set is an array of sets).\footnote{There is another way +to specify data for a simple set along with data for parameters. This +feature is discussed in the next section.} + +Data blocks can be specified only for non-computable sets, i.e. for +sets, which have no assign attribute ({\tt:=}) in the corresponding set +statements. + +If the set is a simple set, only its symbolic name should be specified +in the header of the data block. Otherwise, if the set is a +$n$-dimensional array, its symbolic name should be provided with a +complete list of subscripts separated by commae and enclosed in square +brackets to specify a particular member of the set array. The number of +subscripts should be the same as the dimension of the set array, where +each subscript should be a number or symbol. + +An elemental set defined in the set data block is coded as a sequence +of data records described below.\footnote{{\it Data record} is simply a +technical term. It does not mean that data records have any special +formatting.} + +\subsection{Assign data record} + +The {\it assign data record} ({\tt:=}) is a non-signficant element. +It may be used for improving readability of data blocks. + +\subsection{Slice data record} + +The {\it slice data record} is a control record, which specifies a +{\it slice} of the elemental set defined in the data block. It has the +following syntactic form: +$$\mbox{{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}}$$ +where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. + +Each component of the slice can be a number or symbol or the asterisk +({\tt*}). The number of components in the slice should be the same as +the dimension of $n$-tuples in the elemental set to be defined. For +instance, if the elemental set contains 4-tuples (quadruplets), the +slice should have four components. The number of asterisks in the slice +is called the {\it slice dimension}. + +The effect of using slices is the following. If a $m$-dimensional slice +(i.e. a slice having $m$ asterisks) is specified in the data block, all +subsequent data records should specify tuples of the dimension~$m$. +Whenever a $m$-tuple is encountered, each asterisk in the slice is +replaced by corresponding components of the $m$-tuple that gives the +resultant $n$-tuple, which is included in the elemental set to be +defined. For example, if the slice $(a,*,1,2,*)$ is in effect, and +2-tuple $(3,b)$ is encountered in a subsequent data record, the +resultant 5-tuple included in the elemental set is $(a,3,1,2,b)$. + +The slice having no asterisks itself defines a complete $n$-tuple, +which is included in the elemental set. + +Being once specified the slice effects until either a new slice or the +end of data block is encountered. Note that if no slice is specified in +the data block, one, components of which are all asterisks, is assumed. + +\subsection{Simple data record} + +The {\it simple data record} defines one $n$-tuple in a simple format +and has the following syntactic form: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +where $t_1$, $t_2$, \dots, $t_n$ are components of the $n$-tuple. Each +component can be a number or symbol. Commae between components are +optional and may be omitted. + +\subsection{Matrix data record} + +The {\it matrix data record} defines several 2-tuples (doublets) in +a matrix format and has the following syntactic form: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols +corresponding to rows of the matrix; $c_1$, $c_2$, \dots, $c_n$ are +numbers and/or symbols corresponding to columns of the matrix, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are matrix elements, which can be either +{\tt+} or {\tt-}. (In this data record the delimiter {\tt:} preceding +the column list and the delimiter {\tt:=} following the column list +cannot be omitted.) + +Each element $a_{ij}$ of the matrix data block (where $1\leq i\leq m$, +$1\leq j\leq n$) corresponds to 2-tuple $(r_i,c_j)$. If $a_{ij}$ is the +plus sign ({\tt+}), that 2-tuple (or a longer $n$-tuple, if a slice is +used) is included in the elemental set. Otherwise, if $a_{ij}$ is the +minus sign ({\tt-}), that 2-tuple is not included in the elemental set. + +Since the matrix data record defines 2-tuples, either the elemental set +should consist of 2-tuples or the slice currently used should be +2-dimensional. + +\newpage + +\subsection{Transposed matrix data record} + +The {\it transposed matrix data record} has the following syntactic +form: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +optional and may be omitted.) + +This data record is completely analogous to the matrix data record (see +above) with only exception that in this case each element $a_{ij}$ of +the matrix corresponds to 2-tuple $(c_j,r_i)$ rather than $(r_i,c_j)$. + +Being once specified the {\tt(tr)} indicator affects all subsequent +data records until either a slice or the end of data block is +encountered. + +\section{Parameter data block} + +\noindent +\framebox[468pt][l]{ +\parbox[c][88pt]{468pt}{ +\hspace{6pt} {\tt param} {\it name} {\tt,} {\it record} {\tt,} \dots +{\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\it name} {\tt default} {\it value} {\tt,} +{\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt:} {\it tabbing-data} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt default} {\it value} {\tt:} +{\it tabbing-data} {\tt;} +}} + +\medskip + +\noindent +{\it name} is a symbolic name of the parameter; + +\noindent +{\it value} is an optional default value of the parameter; + +\noindent +{\it record}, \dots, {\it record} are data records; + +\noindent +{\it tabbing-data} specifies parameter data in the tabbing format. + +\noindent +Commae preceding data records may be omitted. + +\para{Data records} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +is a non-significant data record, which may be used freely to improve +readability; +\item[{\tt[} {\it slice} {\tt]}]\hspace*{0pt}\\ +specifies a slice; +\item[{\it plain-data}]\hspace*{0pt}\\ +specifies parameter data in the plain format; +\item[{\tt:} {\it tabular-data}]\hspace*{0pt}\\ +specifies parameter data in the tabular format; +\item[{\tt(tr)} {\tt:} {\it tabular-data}]\hspace*{0pt}\\ +specifies set data in the transposed tabular format. (In this case the +colon following the keyword {\tt(tr)} may be omitted.) +\end{description} + +\vspace*{-8pt} + +\para{Examples} + +\begin{verbatim} +param T := 4; +param month := 1 Jan 2 Feb 3 Mar 4 Apr 5 May; +param month := [1] 'Jan', [2] 'Feb', [3] 'Mar', [4] 'Apr', [5] 'May'; +param init_stock := iron 7.32 nickel 35.8; +param init_stock [*] iron 7.32, nickel 35.8; +param cost [iron] .025 [nickel] .03; +param value := iron -.1, nickel .02; +param : init_stock cost value := + iron 7.32 .025 -.1 + nickel 35.8 .03 .02 ; +param : raw : init stock cost value := + iron 7.32 .025 -.1 + nickel 35.8 .03 .02 ; +param demand default 0 (tr) + : FRA DET LAN WIN STL FRE LAF := + bands 300 . 100 75 . 225 250 + coils 500 750 400 250 . 850 500 + plate 100 . . 50 200 . 250 ; +param trans_cost := + [*,*,bands]: FRA DET LAN WIN STL FRE LAF := + GARY 30 10 8 10 11 71 6 + CLEV 22 7 10 7 21 82 13 + PITT 19 11 12 10 25 83 15 + [*,*,coils]: FRA DET LAN WIN STL FRE LAF := + GARY 39 14 11 14 16 82 8 + CLEV 27 9 12 9 26 95 17 + PITT 24 14 17 13 28 99 20 + [*,*,plate]: FRA DET LAN WIN STL FRE LAF := + GARY 41 15 12 16 17 86 8 + CLEV 29 9 13 9 28 99 18 + PITT 26 14 17 13 31 104 20 ; +\end{verbatim} + +The {\it parameter data block} is used to specify complete data for a +parameter (or parameters, if data are specified in the tabbing format). + +Data blocks can be specified only for non-computable parameters, i.e. +for parameters, which have no assign attribute ({\tt:=}) in the +corresponding parameter statements. + +Data defined in the parameter data block are coded as a sequence of +data records described below. Additionally the data block can be +provided with the optional {\tt default} attribute, which specifies a +default numeric or symbolic value of the parameter (parameters). This +default value is assigned to the parameter or its members when +no appropriate value is defined in the parameter data block. The +{\tt default} attribute cannot be used, if it is already specified in +the corresponding parameter statement. + +\subsection{Assign data record} + +The {\it assign data record} ({\tt:=}) is a non-signficant element. +It may be used for improving readability of data blocks. + +\subsection{Slice data record} + +The {\it slice data record} is a control record, which specifies a +{\it slice} of the parameter array. It has the following syntactic +form: +$$\mbox{{\tt[} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt]}}$$ +where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. + +Each component of the slice can be a number or symbol or the asterisk +({\tt*}). The number of components in the slice should be the same as +the dimension of the parameter. For instance, if the parameter is a +4-dimensional array, the slice should have four components. The number +of asterisks in the slice is called the {\it slice dimension}. + +The effect of using slices is the following. If a $m$-dimensional slice +(i.e. a slice having $m$ asterisks) is specified in the data block, all +subsequent data records should specify subscripts of the parameter +members as if the parameter were $m$-dimensional, not $n$-dimensional. + +Whenever $m$ subscripts are encountered, each asterisk in the slice is +replaced by corresponding subscript that gives $n$ subscripts, which +define the actual parameter member. For example, if the slice +$[a,*,1,2,*]$ is in effect, and subscripts 3 and $b$ are encountered in +a subsequent data record, the complete subscript list used to choose a +parameter member is $[a,3,1,2,b]$. + +It is allowed to specify a slice having no asterisks. Such slice itself +defines a complete subscript list, in which case the next data record +should define only a single value of corresponding parameter member. + +Being once specified the slice effects until either a new slice or the +end of data block is encountered. Note that if no slice is specified in +the data block, one, components of which are all asterisks, is assumed. + +\subsection{Plain data record} + +The {\it plain data record} defines a subscript list and a single value +in the plain format. This record has the following syntactic form: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +where $t_1$, $t_2$, \dots, $t_n$ are subscripts, and $v$ is a value. +Each subscript as well as the value can be a number or symbol. Commae +following subscripts are optional and may be omitted. + +In case of 0-dimensional parameter or slice the plain data record has +no subscripts and consists of a single value only. + +\subsection{Tabular data record} + +The {\it tabular data record} defines several values, where each value +is provided with two subscripts. This record has the following +syntactic form: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols +corresponding to rows of the table; $c_1$, $c_2$, \dots, $c_n$ are +numbers and/or symbols corresponding to columns of the table, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ are table elements. Each element can be a +number or symbol or the single decimal point ({\tt.}). (In this data +record the delimiter {\tt:} preceding the column list and the delimiter +{\tt:=} following the column list cannot be omitted.) + +Each element $a_{ij}$ of the tabular data block ($1\leq i\leq m$, +$1\leq j\leq n$) defines two subscripts, where the first subscript is +$r_i$, and the second one is $c_j$. These subscripts are used in +conjunction with the current slice to form the complete subscript list +that identifies a particular member of the parameter array. If $a_{ij}$ +is a number or symbol, this value is assigned to the parameter member. +However, if $a_{ij}$ is the single decimal point, the member is +assigned a default value specified either in the parameter data block +or in the parameter statement, or, if no default value is specified, +the member remains undefined. + +Since the tabular data record provides two subscripts for each value, +either the parameter or the slice currently used should be +2-dimensional. + +\subsection{Transposed tabular data record} + +The {\it transposed tabular data record} has the following syntactic +form: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +optional and may be omitted.) + +This data record is completely analogous to the tabular data record +(see above) with only exception that the first subscript defined by +element $a_{ij}$ is $c_j$ while the second one is $r_i$. + +Being once specified the {\tt(tr)} indicator affects all subsequent +data records until either a slice or the end of data block is +encountered. + +\newpage + +\subsection{Tabbing data format} + +The parameter data block in the {\it tabbing format} has the following +syntactic form: +$$ +\begin{array}{*{8}{l}} +\multicolumn{4}{l} +{{\tt param}\ {\tt default}\ value\ {\tt :}\ s\ {\tt :}}& +p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_r\ \ \verb|:=|\\ +r_{11}\ \verb|,|& r_{12}\ \verb|,|& \dots\ \verb|,|& r_{1n}\ \verb|,|& +a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1r}\ \verb|,|\\ +r_{21}\ \verb|,|& r_{22}\ \verb|,|& \dots\ \verb|,|& r_{2n}\ \verb|,|& +a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2r}\ \verb|,|\\ +\dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +r_{m1}\ \verb|,|& r_{m2}\ \verb|,|& \dots\ \verb|,|& r_{mn}\ \verb|,|& +a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mr}\ \verb|;|\\ +\end{array} +$$ + +1. The keyword {\tt default} may be omitted along with a value +following it. + +2. Symbolic name $s$ may be omitted along with the colon following it. + +3. All commae are optional and may be omitted. + +The data block in the tabbing format shown above is exactly equivalent +to the following data blocks: + +\verb|set| $s$\ \verb|:=|\ $ +\verb|(|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|) | +\verb|(|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|) | +\dots +\verb| (|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|);|$ + +\verb|param| $p_1$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{11} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{21} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m1} +\verb|;| +$ + +\verb|param| $p_2$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{12} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{22} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m2} +\verb|;| +$ + +\verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . + +\verb|param| $p_r$\ \verb|default|\ $value$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{1r} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{2r} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{mr} +\verb|;| +$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\chapter{Using suffixes} + +\vspace*{-12pt} + +Suffixes can be used to retrieve additional values associated with +model variables, constraints, and objectives. + +A {\it suffix} consists of a period ({\tt.}) followed by a non-reserved +keyword. For example, if {\tt x} is a two-dimensional variable, +{\tt x[i,j].lb} is a numeric value equal to the lower bound of +elemental variable {\tt x[i,j]}, which (value) can be used everywhere +in expressions like a numeric parameter. + +For model variables suffixes have the following meaning: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&lower bound\\ +{\tt.ub}&upper bound\\ +{\tt.status}&status in the solution:\\ +&0 --- undefined\\ +&1 --- basic\\ +&2 --- non-basic on lower bound\\ +&3 --- non-basic on upper bound\\ +&4 --- non-basic free (unbounded) variable\\ +&5 --- non-basic fixed variable\\ +{\tt.val}&primal value in the solution\\ +{\tt.dual}&dual value (reduced cost) in the solution\\ +\end{tabular} + +For model constraints and objectives suffixes have the following +meaning: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&lower bound of the linear form\\ +{\tt.ub}&upper bound of the linear form\\ +{\tt.status}&status in the solution:\\ +&0 --- undefined\\ +&1 --- non-active\\ +&2 --- active on lower bound\\ +&3 --- active on upper bound\\ +&4 --- active free (unbounded) row\\ +&5 --- active equality constraint\\ +{\tt.val}&primal value of the linear form in the solution\\ +{\tt.dual}&dual value (reduced cost) of the linear form in the +solution\\ +\end{tabular} + +Note that suffixes {\tt.status}, {\tt.val}, and {\tt.dual} can be used +only below the solve statement. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Date and time functions} + +\noindent\hfil +\begin{tabular}{c} +by Andrew Makhorin \verb||\\ +and Heinrich Schuchardt \verb||\\ +\end{tabular} + +\section{Obtaining current calendar time} +\label{gmtime} + +To obtain the current calendar time in MathProg there exists the +function {\tt gmtime}. It has no arguments and returns the number of +seconds elapsed since 00:00:00 on January 1, 1970, Coordinated +Universal Time (UTC). For example: + +\begin{verbatim} + param utc := gmtime(); +\end{verbatim} + +MathProg has no function to convert UTC time returned by the function +{\tt gmtime} to {\it local} calendar times. Thus, if you need to +determine the current local calendar time, you have to add to the UTC +time returned the time offset from UTC expressed in seconds. For +example, the time in Berlin during the winter is one hour ahead of UTC +that corresponds to the time offset +1~hour~= +3600~secs, so the +current winter calendar time in Berlin may be determined as follows: + +\begin{verbatim} + param now := gmtime() + 3600; +\end{verbatim} + +\noindent Similarly, the summer time in Chicago (Central Daylight Time) +is five hours behind UTC, so the corresponding current local calendar +time may be determined as follows: + +\begin{verbatim} + param now := gmtime() - 5 * 3600; +\end{verbatim} + +Note that the value returned by {\tt gmtime} is volatile, i.e. being +called several times this function may return different values. + +\section{Converting character string to calendar time} +\label{str2time} + +The function {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converts a +character string (timestamp) specified by its first argument {\it s}, +which should be a symbolic expression, to the calendar time suitable +for arithmetic calculations. The conversion is controlled by the +specified format string {\it f} (the second argument), which also +should be a symbolic expression. + +\newpage + +The result of conversion returned by {\tt str2time} has the same +meaning as values returned by the function {\tt gmtime} (see Subsection +\ref{gmtime}, page \pageref{gmtime}). Note that {\tt str2time} does +{\tt not} correct the calendar time returned for the local timezone, +i.e. being applied to 00:00:00 on January 1, 1970 it always returns 0. + +For example, the model statements: + +\begin{verbatim} + param s, symbolic, := "07/14/98 13:47"; + param t := str2time(s, "%m/%d/%y %H:%M"); + display t; +\end{verbatim} + +\noindent produce the following printout: + +\begin{verbatim} + t = 900424020 +\end{verbatim} + +\noindent where the calendar time printed corresponds to 13:47:00 on +July 14, 1998. + +The format string passed to the function {\tt str2time} consists of +conversion specifiers and ordinary characters. Each conversion +specifier begins with a percent ({\tt\%}) character followed by a +letter. + +The following conversion specifiers may be used in the format string: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&The abbreviated month name (case insensitive). At least three +first letters of the month name should appear in the input string.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&The day of the month as a decimal number (range 1 to 31). +Leading zero is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&The same as {\tt\%b}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 0 +to 23). Leading zero is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&The month as a decimal number (range 1 to 12). Leading zero is +permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&The minute as a decimal number (range 0 to 59). Leading zero +is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&The second as a decimal number (range 0 to 60). Leading zero +is permitted, but not required.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&The year without a century as a decimal number (range 0 to 99). +Leading zero is permitted, but not required. Input values in the range +0 to 68 are considered as the years 2000 to 2068 while the values 69 to +99 as the years 1969 to 1999.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%z}&The offset from GMT in ISO 8601 format.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&A literal {\tt\%} character.\\ +\end{tabular} + +All other (ordinary) characters in the format string should have a +matching character in the input string to be converted. Exceptions are +spaces in the input string which can match zero or more space +characters in the format string. + +\newpage + +If some date and/or time component(s) are missing in the format and, +therefore, in the input string, the function {\tt str2time} uses their +default values corresponding to 00:00:00 on January 1, 1970, that is, +the default value of the year is 1970, the default value of the month +is January, etc. + +The function {\tt str2time} is applicable to all calendar times in the +range 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of +the Gregorian calendar. + +\section{Converting calendar time to character string} +\label{time2str} + +The function {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converts the +calendar time specified by its first argument {\it t}, which should be +a numeric expression, to a character string (symbolic value). The +conversion is controlled by the specified format string {\it f} (the +second argument), which should be a symbolic expression. + +The calendar time passed to {\tt time2str} has the same meaning as +values returned by the function {\tt gmtime} (see Subsection +\ref{gmtime}, page \pageref{gmtime}). Note that {\tt time2str} does +{\it not} correct the specified calendar time for the local timezone, +i.e. the calendar time 0 always corresponds to 00:00:00 on January 1, +1970. + +For example, the model statements: + +\begin{verbatim} + param s, symbolic, := time2str(gmtime(), "%FT%TZ"); + display s; +\end{verbatim} + +\noindent may produce the following printout: + +\begin{verbatim} + s = '2008-12-04T00:23:45Z' +\end{verbatim} + +\noindent which is a timestamp in the ISO format. + +The format string passed to the function {\tt time2str} consists of +conversion specifiers and ordinary characters. Each conversion +specifier begins with a percent ({\tt\%}) character followed by a +letter. + +The following conversion specifiers may be used in the format string: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%a}&The abbreviated (2-character) weekday name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%A}&The full weekday name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&The abbreviated (3-character) month name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%B}&The full month name.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%C}&The century of the year, that is the greatest integer not +greater than the year divided by~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&The day of the month as a decimal number (range 01 to 31).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%D}&The date using the format \verb|%m/%d/%y|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%e}&The day of the month like with \verb|%d|, but padded with +blank rather than zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%F}&The date using the format \verb|%Y-%m-%d|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%g}&The year corresponding to the ISO week number, but without the +century (range 00 to~99). This has the same format and value as +\verb|%y|, except that if the ISO week number (see \verb|%V|) belongs +to the previous or next year, that year is used instead.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%G}&The year corresponding to the ISO week number. This has the +same format and value as \verb|%Y|, except that if the ISO week number +(see \verb|%V|) belongs to the previous or next year, that year is used +instead. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&The same as \verb|%b|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 00 +to 23).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%I}&The hour as a decimal number, using a 12-hour clock (range 01 +to 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%j}&The day of the year as a decimal number (range 001 to 366).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%k}&The hour as a decimal number, using a 24-hour clock like +\verb|%H|, but padded with blank rather than zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%l}&The hour as a decimal number, using a 12-hour clock like +\verb|%I|, but padded with blank rather than zero. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&The month as a decimal number (range 01 to 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&The minute as a decimal number (range 00 to 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%p}&Either {\tt AM} or {\tt PM}, according to the given time value. +Midnight is treated as {\tt AM} and noon as {\tt PM}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%P}&Either {\tt am} or {\tt pm}, according to the given time value. +Midnight is treated as {\tt am} and noon as {\tt pm}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%R}&The hour and minute in decimal numbers using the format +\verb|%H:%M|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&The second as a decimal number (range 00 to 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%T}&The time of day in decimal numbers using the format +\verb|%H:%M:%S|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%u}&The day of the week as a decimal number (range 1 to 7), Monday +being 1.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%U}&The week number of the current year as a decimal number (range +00 to 53), starting with the first Sunday as the first day of the first +week. Days preceding the first Sunday in the year are considered to be +in week 00. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%V}&The ISO week number as a decimal number (range 01 to 53). ISO +weeks start with Monday and end with Sunday. Week 01 of a year is the +first week which has the majority of its days in that year; this is +equivalent to the week containing January 4. Week 01 of a year can +contain days from the previous year. The week before week 01 of a year +is the last week (52 or 53) of the previous year even if it contains +days from the new year. In other word, if 1 January is Monday, Tuesday, +Wednesday or Thursday, it is in week 01; if 1 January is Friday, +Saturday or Sunday, it is in week 52 or 53 of the previous year.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%w}&The day of the week as a decimal number (range 0 to 6), Sunday +being 0.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%W}&The week number of the current year as a decimal number (range +00 to 53), starting with the first Monday as the first day of the first +week. Days preceding the first Monday in the year are considered to be +in week 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&The year without a century as a decimal number (range 00 to +99), that is the year modulo~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%Y}&The year as a decimal number, using the Gregorian calendar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&A literal \verb|%| character.\\ +\end{tabular} + +All other (ordinary) characters in the format string are simply copied +to the resultant string. + +The first argument (calendar time) passed to the function {\tt time2str} +should be in the range from $-62135596800$ to $+64092211199$ that +corresponds to the period from 00:00:00 on January 1, 0001 to 23:59:59 +on December 31, 4000 of the Gregorian calendar. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Table drivers} +\label{drivers} + +\noindent\hfil +\begin{tabular}{c} +by Andrew Makhorin \verb||\\ +and Heinrich Schuchardt \verb||\\ +\end{tabular} + +\bigskip\bigskip + +The {\it table driver} is a program module which provides transmitting +data between MathProg model objects and data tables. + +Currently the GLPK package has four table drivers: + +\vspace*{-8pt} + +\begin{itemize} +\item built-in CSV table driver; +\item built-in xBASE table driver; +\item ODBC table driver; +\item MySQL table driver. +\end{itemize} + +\vspace*{-8pt} + +\section{CSV table driver} + +The CSV table driver assumes that the data table is represented in the +form of a plain text file in the CSV (comma-separated values) file +format as described below. + +To choose the CSV table driver its name in the table statement should +be specified as \verb|"CSV"|, and the only argument should specify the +name of a plain text file containing the table. For example: + +\begin{verbatim} + table data IN "CSV" "data.csv": ... ; +\end{verbatim} + +The filename suffix may be arbitrary, however, it is recommended to use +the suffix `\verb|.csv|'. + +On reading input tables the CSV table driver provides an implicit field +named \verb|RECNO|, which contains the current record number. This +field can be specified in the input table statement as if there were +the actual field named \verb|RECNO| in the CSV file. For example: + +\begin{verbatim} + table list IN "CSV" "list.csv": num <- [RECNO], ... ; +\end{verbatim} + +\newpage + +\subsection*{CSV format\footnote{This material is based on the RFC +document 4180.}} + +The CSV (comma-separated values) format is a plain text file format +defined as follows. + +1. Each record is located on a separate line, delimited by a line +break. For example: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +\noindent +where \verb|\n| means the control character \verb|LF| ({\tt 0x0A}). + +2. The last record in the file may or may not have an ending line +break. For example: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz +\end{verbatim} + +3. There should be a header line appearing as the first line of the +file in the same format as normal record lines. This header should +contain names corresponding to the fields in the file. The number of +field names in the header line should be the same as the number of +fields in the records of the file. For example: + +\begin{verbatim} + name1,name2,name3\n + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +4. Within the header and each record there may be one or more fields +separated by commas. Each line should contain the same number of fields +throughout the file. Spaces are considered as part of a field and +therefore not ignored. The last field in the record should not be +followed by a comma. For example: + +\begin{verbatim} + aaa,bbb,ccc\n +\end{verbatim} + +5. Fields may or may not be enclosed in double quotes. For example: + +\begin{verbatim} + "aaa","bbb","ccc"\n + zzz,yyy,xxx\n +\end{verbatim} + +6. If a field is enclosed in double quotes, each double quote which is +part of the field should be coded twice. For example: + +\begin{verbatim} + "aaa","b""bb","ccc"\n +\end{verbatim} + +\para{Example} + +\begin{verbatim} +FROM,TO,DISTANCE,COST +Seattle,New-York,2.5,0.12 +Seattle,Chicago,1.7,0.08 +Seattle,Topeka,1.8,0.09 +San-Diego,New-York,2.5,0.15 +San-Diego,Chicago,1.8,0.10 +San-Diego,Topeka,1.4,0.07 +\end{verbatim} + +\newpage + +\section{xBASE table driver} + +The xBASE table driver assumes that the data table is stored in the +.dbf file format. + +To choose the xBASE table driver its name in the table statement should +be specified as \verb|"xBASE"|, and the first argument should specify +the name of a .dbf file containing the table. For the output table there +should be the second argument defining the table format in the form +\verb|"FF...F"|, where \verb|F| is either {\tt C({\it n})}, +which specifies a character field of length $n$, or +{\tt N({\it n}{\rm [},{\it p}{\rm ]})}, which specifies a numeric field +of length $n$ and precision $p$ (by default $p$ is 0). + +The following is a simple example which illustrates creating and +reading a .dbf file: + +\begin{verbatim} +table tab1{i in 1..10} OUT "xBASE" "foo.dbf" + "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, + "?" ~ FOO, "[" & i & "]" ~ C; +set S, dimen 4; +table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A]; +display S; +end; +\end{verbatim} + +\section{ODBC table driver} + +The ODBC table driver allows connecting to SQL databases using an +implementation of the ODBC interface based on the Call Level Interface +(CLI).\footnote{The corresponding software standard is defined in +ISO/IEC 9075-3:2003.} + +\para{Debian GNU/Linux.} +Under Debian GNU/Linux the ODBC table driver uses the iODBC +package,\footnote{See {\tt}.} which should be +installed before building the GLPK package. The installation can be +effected with the following command: + +\begin{verbatim} + sudo apt-get install libiodbc2-dev +\end{verbatim} + +Note that on configuring the GLPK package to enable using the iODBC +library the option `\verb|--enable-odbc|' should be passed to the +configure script. + +The individual databases should be entered for systemwide usage in +\verb|/etc/odbc.ini| and\linebreak \verb|/etc/odbcinst.ini|. Database +connections to be used by a single user are specified by files in the +home directory (\verb|.odbc.ini| and \verb|.odbcinst.ini|). + +\para{Microsoft Windows.} +Under Microsoft Windows the ODBC table driver uses the Microsoft ODBC +library. To enable this feature the symbol: + +\begin{verbatim} + #define ODBC_DLNAME "odbc32.dll" +\end{verbatim} + +\noindent +should be defined in the GLPK configuration file `\verb|config.h|'. + +Data sources can be created via the Administrative Tools from the +Control Panel. + +To choose the ODBC table driver its name in the table statement should +be specified as \verb|'ODBC'| or \verb|'iODBC'|. + +\newpage + +The argument list is specified as follows. + +The first argument is the connection string passed to the ODBC library, +for example: + +\verb|'DSN=glpk;UID=user;PWD=password'|, or + +\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. + +Different parts of the string are separated by semicolons. Each part +consists of a pair {\it fieldname} and {\it value} separated by the +equal sign. Allowable fieldnames depend on the ODBC library. Typically +the following fieldnames are allowed: + +\verb|DATABASE | database; + +\verb|DRIVER | ODBC driver; + +\verb|DSN | name of a data source; + +\verb|FILEDSN | name of a file data source; + +\verb|PWD | user password; + +\verb|SERVER | database; + +\verb|UID | user name. + +The second argument and all following are considered to be SQL +statements + +SQL statements may be spread over multiple arguments. If the last +character of an argument is a semicolon this indicates the end of +a SQL statement. + +The arguments of a SQL statement are concatenated separated by space. +The eventual trailing semicolon will be removed. + +All but the last SQL statement will be executed directly. + +For IN-table the last SQL statement can be a SELECT command starting +with the capitalized letters \verb|'SELECT '|. If the string does not +start with \verb|'SELECT '| it is considered to be a table name and a +SELECT statement is automatically generated. + +For OUT-table the last SQL statement can contain one or multiple +question marks. If it contains a question mark it is considered a +template for the write routine. Otherwise the string is considered a +table name and an INSERT template is automatically generated. + +The writing routine uses the template with the question marks and +replaces the first question mark by the first output parameter, the +second question mark by the second output parameter and so forth. Then +the SQL command is issued. + +The following is an example of the output table statement: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO result 'VALUES ( 4, ?, ? )' : + l ~ LOC, quantity[l] ~ QUAN; +\end{verbatim} + +\newpage + +\noindent +Alternatively it could be written as follows: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'result' : + l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +Using templates with `\verb|?|' supports not only INSERT, but also +UPDATE, DELETE, etc. For example: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' + 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantity[l], l; +\end{verbatim} + +\section{MySQL table driver} + +The MySQL table driver allows connecting to MySQL databases. + +\para{Debian GNU/Linux.} +Under Debian GNU/Linux the MySQL table driver uses the MySQL +package,\footnote{For download development files see +{\tt}.} which should be +installed before building the GLPK package. The installation can be +effected with the following command: + +\begin{verbatim} + sudo apt-get install libmysqlclient15-dev +\end{verbatim} + +Note that on configuring the GLPK package to enable using the MySQL +library the option `\verb|--enable-mysql|' should be passed to the +configure script. + +\para{Microsoft Windows.} +Under Microsoft Windows the MySQL table driver also uses the MySQL +library. To enable this feature the symbol: + +\begin{verbatim} + #define MYSQL_DLNAME "libmysql.dll" +\end{verbatim} + +\noindent +should be defined in the GLPK configuration file `\verb|config.h|'. + +To choose the MySQL table driver its name in the table statement should +be specified as \verb|'MySQL'|. + +The argument list is specified as follows. + +The first argument specifies how to connect the data base in the DSN +style, for example: + +\verb|'Database=glpk;UID=glpk;PWD=gnu'|. + +Different parts of the string are separated by semicolons. Each part +consists of a pair {\it fieldname} and {\it value} separated by the +equal sign. The following fieldnames are allowed: + +\newpage + +\verb|Server | server running the database (defaulting to localhost); + +\verb|Database | name of the database; + +\verb|UID | user name; + +\verb|PWD | user password; + +\verb|Port | port used by the server (defaulting to 3306). + +The second argument and all following are considered to be SQL +statements. + +SQL statements may be spread over multiple arguments. If the last +character of an argument is a semicolon this indicates the end of +a SQL statement. + +The arguments of a SQL statement are concatenated separated by space. +The eventual trailing semicolon will be removed. + +All but the last SQL statement will be executed directly. + +For IN-table the last SQL statement can be a SELECT command starting +with the capitalized letters \verb|'SELECT '|. If the string does not +start with \verb|'SELECT '| it is considered to be a table name and a +SELECT statement is automatically generated. + +For OUT-table the last SQL statement can contain one or multiple +question marks. If it contains a question mark it is considered a +template for the write routine. Otherwise the string is considered a +table name and an INSERT template is automatically generated. + +The writing routine uses the template with the question marks and +replaces the first question mark by the first output parameter, the +second question mark by the second output parameter and so forth. Then +the SQL command is issued. + +The following is an example of the output table statement: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO result VALUES ( 4, ?, ? )' : + l ~ LOC, quantity[l] ~ QUAN; +\end{verbatim} + +\noindent +Alternatively it could be written as follows: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS result;' + 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'result' : + l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +\newpage + +Using templates with `\verb|?|' supports not only INSERT, but also +UPDATE, DELETE, etc. For example: + +\begin{verbatim} +table ta { l in LOCATIONS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' + 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantity[l], l; +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Solving models with glpsol} + +The GLPK package\footnote{{\tt http://www.gnu.org/software/glpk/}} +includes the program {\tt glpsol}, a stand-alone LP/MIP solver. This +program can be launched from the command line or from the shell to +solve models written in the GNU MathProg modeling language. + +To tell the solver that the input file contains a model description you +need to specify the option \verb|--model| in the command line. +For example: + +\begin{verbatim} + glpsol --model foo.mod +\end{verbatim} + +Sometimes it is necessary to use the data section placed in a separate +file, in which case you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --data foo.dat +\end{verbatim} + +\noindent Note that if the model file also contains the data section, +that section is ignored. + +It is also allowed to specify more than one file containing the data +section, for example: + +\begin{verbatim} + glpsol --model foo.mod --data foo1.dat --data foo2.dat +\end{verbatim} + +If the model description contains some display and/or printf +statements, by default the output is sent to the terminal. If you need +to redirect the output to a file, you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --display foo.out +\end{verbatim} + +If you need to look at the problem, which has been generated by the +model translator, you may use the option \verb|--wlp| as follows: + +\begin{verbatim} + glpsol --model foo.mod --wlp foo.lp +\end{verbatim} + +\noindent In this case the problem data is written to file +\verb|foo.lp| in CPLEX LP format suitable for visual analysis. + +Sometimes it is needed merely to check the model description not +solving the generated problem instance. In this case you may specify +the option \verb|--check|, for example: + +\begin{verbatim} + glpsol --check --model foo.mod --wlp foo.lp +\end{verbatim} + +\newpage + +If you need to write a numeric solution obtained by the solver to +a file, you may use the following command: + +\begin{verbatim} + glpsol --model foo.mod --output foo.sol +\end{verbatim} + +\noindent in which case the solution is written to file \verb|foo.sol| +in a plain text format suitable for visual analysis. + +The complete list of the \verb|glpsol| options can be found in the +GLPK reference manual included in the GLPK distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Example model description} + +\section{Model description written in MathProg} + +Below here is a complete example of the model description written in +the GNU MathProg modeling language. + +\bigskip + +\begin{verbatim} +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; +\end{verbatim} + +\newpage + +\section{Generated LP problem instance} + +Below here is the result of the translation of the example model +produced by the solver \verb|glpsol| and written in CPLEX LP format +with the option \verb|--wlp|. + +\medskip + +\begin{verbatim} +\* Problem: transp *\ + +Minimize + cost: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) + +Subject To + supply(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + + x(Seattle,Topeka) <= 350 + supply(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + + x(San~Diego,Topeka) <= 600 + demand(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 + demand(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 + demand(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 + +End +\end{verbatim} + +\section{Optimal LP solution} + +Below here is the optimal solution of the generated LP problem instance +found by the solver \verb|glpsol| and written in plain text format +with the option \verb|--output|. + +\medskip + +\begin{footnotesize} +\begin{verbatim} +Problem: transp +Rows: 6 +Columns: 6 +Non-zeros: 18 +Status: OPTIMAL +Objective: cost = 153.675 (MINimum) + + No. Row name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 cost B 153.675 + 2 supply[Seattle] + NU 350 350 < eps + 3 supply[San-Diego] + B 550 600 + 4 demand[New-York] + NL 325 325 0.225 + 5 demand[Chicago] + NL 300 300 0.153 + 6 demand[Topeka] + NL 275 275 0.126 + + No. Column name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 x[Seattle,New-York] + B 50 0 + 2 x[Seattle,Chicago] + B 300 0 + 3 x[Seattle,Topeka] + NL 0 0 0.036 + 4 x[San-Diego,New-York] + B 275 0 + 5 x[San-Diego,Chicago] + NL 0 0 0.009 + 6 x[San-Diego,Topeka] + B 275 0 + +End of output +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section*{Acknowledgements} +\addcontentsline{toc}{chapter}{Acknowledgements} + +The authors would like to thank the following people, who kindly read, +commented, and corrected the draft of this document: + +\noindent Juan Carlos Borras \verb|| + +\noindent Harley Mackenzie \verb|| + +\noindent Robbie Morrison \verb|| + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.pdf new file mode 100644 index 000000000..126f9e876 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.tex new file mode 100644 index 000000000..7a61125a2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_es.tex @@ -0,0 +1,3231 @@ +%* gmpl_es.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +% Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +% rights reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +\documentclass[11pt,spanish]{report} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} + +\renewcommand\contentsname{\sf\bfseries Contenidos} +\renewcommand\chaptername{\sf\bfseries Capítulo} +\renewcommand\appendixname{\sf\bfseries Apéndice} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries Lenguaje de Modelado GNU MathProg +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Referencia del Lenguaje +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf para GLPK Versión 4.57 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (BORRADOR, octubre del 2015) +\end{Large} + +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +El paquete GLPK es parte del Proyecto GNU distribuido bajo la égida de GNU + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. Todos los derechos reservados. + +\noindent +Título original en inglés: Modeling Language GNU MathProg - Language Reference for GLPK Version 4.50 + +\noindent +Traducción: Pablo Yapura, Facultad de Ciencias Agrarias y Forestales, Universidad Nacional de La Plata, La Plata, Argentina. + +\noindent +Copyright \copyright{} 2013, 2014, 2015 Pablo Yapura, para esta traducción. Todos los derechos reservados. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +\noindent +Se permite realizar y distribuir copias textuales de este manual siempre que se preserve este aviso de permiso y el aviso del copyright en todas las copias. + +\noindent +Se permite copiar y distribuir versiones modificadas de este manual bajo las condiciones de copias textuales, siempre que también se distribuya íntegro el trabajo derivado resultante bajo los términos de un aviso de permiso idéntico al presente. + +\noindent +Se permite copiar y distribuir traducciones de este manual en otro idioma bajo las condiciones establecidas arriba para versiones modificadas. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Introducción} + +{\it GNU MathProg} es un lenguaje de modelado diseñado para describir modelos lineales de programación matemática.\footnote{El lenguaje GNU MathProg es un subconjunto del lenguaje AMPL. Su implementación en GLPK está basada principalmente en el paper: {\it Robert Fourer}, {\it David M. Gay} \& {\it Brian W. Kernighan}, ``A Modeling Language for Mathematical Programming.'' {\it Management Science} 36 (1990), pp.~519-554.} + +La descripción del modelo escrita en el lenguaje GNU MathProg consiste en un conjunto de sentencias y bloques de datos construidos por el usuario a partir de los elementos del lenguaje que se describen en este documento. + +En un proceso que se denomina {\it traducción}, un programa denominado {\it traductor del modelo} analiza la descripción del modelo y la traduce en una estructura interna de datos, la que puede ser usada tanto para generar una instancia de un problema de programación matemática, como para obtener directamente una solución numérica del problema mediante un programa denominado {\it solver}. + +\section{El problema de la programación lineal} +\label{problem} + +En MathProg el problema de la programación lineal (PL) se expresa como sigue: + +\medskip + +\noindent\hspace{1in}minimizar (o maximizar) +$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ +\noindent\hspace{1in}sujeto a las restricciones lineales +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} +L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ +L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ +\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ +\end{array}\eqno(1.2) +$$ +\noindent\hspace{1in}y a las cotas de las variables +$$ +\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} +l_1&\leq&x_1&\leq&u_1\\ +l_2&\leq&x_2&\leq&u_2\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_n&\leq&x_n&\leq&u_n\\ +\end{array}\eqno(1.3) +$$ + +\noindent +donde $x_1$, $x_2$, \dots, $x_n$ son variables; $z$ es la función objetivo; $c_1$, $c_2$, \dots, $c_n$ son coeficientes de la función objetivo; $c_0$ es el término constante (``de traslación'') de la función objetivo; $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ son coeficientes de las restricciones; $L_1$, $L_2$, +\dots, $L_m$ son cotas inferiores de las restricciones; $U_1$, $U_2$, \dots, $U_m$ son cotas superiores de las restricciones; $l_1$, $l_2$, \dots, $l_n$ son cotas inferiores de las variables y $u_1$, $u_2$, \dots, $u_n$ son cotas superiores de las variables. + +Las cotas de las variables y las cotas de las restricciones pueden ser tanto finitas como infinitas. Además, las cotas inferiores pueden ser iguales a las correspondientes cotas superiores. Entonces, están permitidos los siguientes tipos de variables y restricciones: + +\medskip + +{\def\arraystretch{1.4} +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +$-\infty$&$<$&$x$&$<$&$+\infty$&Variable libre (no acotada)\\ +$l$&$\leq$&$x$&$<$&$+\infty$&Variable con cota inferior\\ +$-\infty$&$<$&$x$&$\leq$&$u$&Variable con cota superior\\ +$l$&$\leq$&$x$&$\leq$&$u$&Variable doblemente acotada\\ +$l$&$=$&$x$&=&$u$&Variable fija\\ +\end{tabular} + +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Forma lineal libre (no acotada)\\ +$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Restricción de inecuación ``mayor o igual que''\\ +$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Restricción de inecuación ``menor o igual que''\\ +$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Restricción de inecuación doblemente acotada\\ +$L$&$=$&$\sum a_jx_j$&=&$U$&Restricción de igualdad\\ +\end{tabular} +} + +\medskip + +Además de problemas puros de PL, MathProg también permite problemas de programación entera lineal mixta (PEM), en los que algunas o todas las variables se han restringido a ser enteras o binarias. + +\section{Objetos del modelo} + +En MathProg el modelo se describe mediante conjuntos, parámetros, variables, restricciones y objetivos, los que se denominan {\it objetos del modelo}. + +El usuario introduce objetos particulares del modelo usando las sentencias del lenguaje. Cada objeto del modelo está provisto de un nombre simbólico que lo identifica de manera única y está pensado con propósitos de referencia. + +\newpage + +Los objetos del modelo, incluyendo los conjuntos, pueden ser arreglos multidimensionales construidos sobre conjuntos indizantes. Formalmente, el arreglo $n$-dimensional $A$ es el mapeo $$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ donde $\Delta\subseteq C_1\times\dots\times C_n$ es el subconjunto del producto cartesiano de los conjuntos indizantes, $\Xi$ es el conjunto de los miembros del arreglo. En MathProg, el conjunto $\Delta$ se denomina {\it dominio del subíndice}. Sus miembros son los $n$-tuplos $(i_1,\dots,i_n)$, donde +$i_1\in C_1$, \dots, $i_n\in C_n$. + +Si $n=0$, el producto cartesiano tiene exactamente un miembro (específicamente, un 0-tuplo), de forma tal que es conveniente pensar en los objetos escalares como arreglos 0-dimensionales que tienen un solo miembro. + +El tipo de los miembros del arreglo se determina por el tipo del objeto del modelo correspondiente como sigue: + +\medskip + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Objeto del modelo&Miembro del arreglo\\ +\hline +Conjunto&Conjunto plano elemental\\ +Parámetro&Número o símbolo\\ +Variable&Variable elemental\\ +Restricción&Restricción elemental\\ +Objetivo&Objetivo elemental\\ +\end{tabular} + +\medskip + +Para referir al miembro particular de un objeto, el mismo debe estar provisto de {\it subíndices}. Por ejemplo, si $a$ es un parámetro 2-dimensional definido sobre $I\times J$, una referencia a sus miembros particulares se puede escribir como $a[i,j]$, donde $i\in I$ y $j\in J$. Se sobreentiende que los objetos escalares no necesitan subíndices por ser 0-dimensionales. + +\section{Estructura de la descripción del modelo} + +A veces es deseable escribir un modelo que, en distintos momentos, puede requerir diferentes datos para solucionar cada instancia del problema usando el modelo. Por esta razón, en MathProg la descripción del modelo consta de dos partes: la {\it sección del modelo} y la {\it sección de los datos}. + +La sección del modelo es la parte principal de la descripción del modelo que contiene las declaraciones de los objetos del modelo; es común a todos los problemas basados en el modelo correspondiente. + +La sección de los datos es una parte opcional de la descripción del modelo que contiene los datos específicos para una instancia particular del problema. + +Dependiendo de lo que sea más conveniente, las secciones del modelo y de los datos pueden disponerse en el mismo archivo o en dos archivos separados. Esta última característica permite tener un número arbitrario de secciones con datos diferentes para ser usadas con la misma sección del modelo. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Codificación de la descripción del modelo} +\label{coding} + +La descripción del modelo se codifica en formato de texto plano usando el juego de caracteres ASCII. Los caracteres válidos en la descripción del modelo son los siguientes: + +\begin{itemize} +\item caracteres alfabéticos:\\ +\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ +\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| +\item caracteres numéricos:\\ +\verb|0 1 2 3 4 5 6 7 8 9| +\item caracteres especiales:\\ +\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? +\item caracteres no imprimibles:\\ +\verb|SP HT CR NL VT FF| +\end{itemize} + +Dentro de los literales de cadena y de los comentarios, cualquier carácter ASCII (excepto los caracteres de control) son válidos. + +Los caracteres no imprimibles no son significativos. Se pueden usar libremente entre las unidades léxicas para mejorar la legibilidad de la descripción del modelo. También se usan para separar unidades léxicas entre sí, en caso de no existir otra forma de hacerlo. + +Sintácticamente, la descripción del modelo es una secuencia de unidades léxicas de las siguientes categorías: + +\begin{itemize} +\item nombres simbólicos; +\item literales numéricos; +\item literales de cadena; +\item palabras clave; +\item delimitadores; +\item comentarios. +\end{itemize} + +Las unidades léxicas del lenguaje se discuten a continuación. + +\section{Nombres simbólicos} + +Un {\it nombre simbólico} consiste de caracteres alfabéticos y numéricos, el primero de los cuales debe ser alfabético. Todos los nombres simbólicos deben ser distintos (sensibilidad a las mayúsculas). + +\para{Ejemplos} + +\begin{verbatim} +alfa123 +Esto_es_un_nombre +_P123_abc_321 +\end{verbatim} + +Los nombres simbólicos se usan para identificar los objetos del modelo (conjuntos, parámetros, variables, restricciones y objetivos) y los índices. + +Todos los nombres simbólicos (exceptuando los nombres de los índices) deben ser únicos, {\it i.e.} la descripción del modelo no debe tener objetos distintos con el mismo nombre. Los nombres simbólicos de los índices deben ser únicos dentro del alcance en el que son válidos. + +\section{Literales numéricos} + +Un {\it literal numérico} sigue la forma {\it xx}{\tt E}{\it syy}, donde {\it xx} es un número con punto decimal optativo, {\it s} es el signo {\tt+} o {\tt-} e {\it yy} es un exponente decimal. La letra {\tt E} es insensible a las mayúsculas y se puede codificar como {\tt e}. + +\para{Ejemplos} + +\begin{verbatim} +123 +3.14159 +56.E+5 +.78 +123.456e-7 +\end{verbatim} + +Los literales numéricos se usan para representar cantidades numéricas y tienen significado fijo obvio. + +\section{Literales de cadena} + +Un {\it literal de cadena} es una secuencia arbitraria de caracteres encerrados entre comillas, tanto simples como dobles. Ambas formas son equivalentes. + +Si una comilla simple es parte de un literal de cadena encerrado entre comillas simples, se debe codificar dos veces. Análogamente, si una comilla doble es parte de un literal de cadena encerrado entre comillas dobles, se debe codificar dos veces. + +\para{Ejemplos} + +\begin{verbatim} +'Esta es una cadena' +"Esta es otra cadena" +'No debe usarse los 20''s' +"""Hola, che"" cantaba Favio." +\end{verbatim} + +Los literales de cadena se usan para representar cantidades simbólicas. + +\section{Palabras clave} + +Una {\it palabra clave} es una secuencia de caracteres alfabéticos y posiblemente algunos caracteres especiales. + +Todas la palabras clave caen en alguna de dos categorías: las {\it palabras clave reservadas}, que no pueden usarse como nombres simbólicos, y las {\it palabras clave no reservadas}, que son reconocidas por el contexto y entonces pueden usarse como nombres simbólicos. + +Las palabras clave reservadas son las siguientes: + +\noindent\hfil +\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} +{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ +{\tt by}&{\tt if}&{\tt not}&{\tt within}\\ +{\tt cross}&{\tt in}&{\tt or}\\ +{\tt diff}&{\tt inter}&{\tt symdiff}\\ +{\tt div}&{\tt less}&{\tt then}\\ +\end{tabular} + +Las palabras clave no reservadas se describen en secciones posteriores. + +Todas las palabras clave tienen un significado fijo, el que se explicará en las discusiones de las correspondientes construcciones sintácticas donde las palabras claves sean usadas. + +\section{Delimitadores} + +Un {\it delimitador} es tanto un carácter especial individual como una secuencia de dos caracteres especiales, como sigue: + +\noindent\hfil +\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} +p{.3in}p{.3in}@{}} +{\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}&{\tt>}{\tt>}\\ +{\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}&{\tt\char126} +&{\tt]}&{\tt<-}\\ +{\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ +{\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ +\end{tabular} + +Si el delimitador está compuesto por dos caracteres, no debe haber espacios entre ellos. + +Todos los delimitadores tienen un significado fijo, el que se explicará en las discusiones de las correspondientes construcciones sintácticas donde los delimitadores sean usados. + +\section{Comentarios} + +Con propósitos de documentación, la descripción del modelo puede ser provista de {\it comentarios}, los que pueden ser de dos formas diferentes. La primera es un {\it comentario de una línea individual}, el que debe comenzar con el carácter {\tt\#} y se extiende hasta el final de la línea. La segunda forma es un {\it comentario en secuencia}, el que consiste en una secuencia de caracteres cualesquiera encerrados entre {\tt/*} y {\tt*/}. + +\para{Ejemplos} + +\begin{verbatim} +param n := 10; # Esto es un comentario +/* Esto es otro comentario */ +\end{verbatim} + +Los comentarios son ignorados por el traductor del modelo y pueden aparecer en cualquier sitio de la descripción del modelo en la que que se permitan caracteres no imprimibles. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Expresiones} + +Una {\it expresión} es una regla para calcular un valor. En la descripción de un modelo, las expresiones se usan como constituyentes de ciertas sentencias. + +En general, las expresiones están compuestas por operandos y operadores. + +Dependiendo del tipo del valor resultante, todas las expresiones pertenecen a alguna de las siguientes categorías: + +\vspace*{-8pt} + +\begin{itemize} +\item expresiones numéricas; +\item expresiones simbólicas; +\item expresiones indizantes; +\item expresiones de conjuntos; +\item expresiones lógicas; +\item expresiones lineales. +\end{itemize} + +\vspace*{-8pt} + +\section{Expresiones numéricas} + +Una {\it expresión numérica} es una regla para calcular un valor numérico individual representado como un número de punto flotante. + +La expresión numérica primaria puede ser un literal numérico, un índice, un parámetro no-indizado, un parámetro indizado, una función interna de referencia, una expresión numérica iterada, una expresión numérica condicional u otra expresión numérica encerrada entre paréntesis. + +\newpage + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|1.23|&(literal numérico)\\ +\verb|j|&(índice)\\ +\verb|tiempo|&(parámetro no-indizado)\\ +\verb|a['Mayo de 2003',j+1]|&(parámetro indizado)\\ +\verb|abs(b[i,j])|&(función de referencia)\\ +\verb|sum{i in S diff T} alfa[i] * b[i,j]|&(expresión iterada)\\ +\verb|if i in I then 2 * p else q[i+1]|&(expresión condicional)\\ +\verb|(b[i,j] + .5 * c)|&(expresión parentética)\\ +\end{tabular} + +Empleando ciertos operadores aritméticos se pueden construir expresiones numéricas más generales conteniendo dos o más expresiones numéricas primarias. + +\para{Ejemplos} + +\begin{verbatim} +j+1 +2 * a[i-1,j+1] - b[i,j] +sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] +(if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) +\end{verbatim} + +\subsection{Literales numéricos} + +Si la expresión numérica primaria es un literal numérico, el valor resultante es obvio. + +\subsection{Índices} + +Si la expresión numérica primaria es un índice, el valor resultante es el valor corriente asignado al índice. + +\subsection{Parámetros no-indizados} + +Si la expresión numérica primaria es un parámetro no-indizado (el que debe ser 0-dimensional), el valor resultante es el valor del parámetro. + +\subsection{Parámetros indizados} + +La expresión numérica primaria que se refiere a parámetros indizados tiene la siguiente forma sintáctica: +$$ +\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} +$$ +donde {\it nombre} es el nombre simbólico del parámetro e $i_1$, $i_2$, +\dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe ser igual a la dimensión del parámetro con el cual está asociada la lista de subíndices. + +Los valores reales de las expresiones de subíndices se usan para identificar al miembro particular del parámetro que determina el valor resultante de la expresión primaria. + +\subsection{Funciones de referencia} + +En MathProg existen las siguientes funciones internas, las que se pueden usar en expresiones numéricas: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt abs(}$x${\tt)}&$|x|$, valor absoluto de $x$\\ +{\tt atan(}$x${\tt)}&$\arctan x$, valor principal del arcotangente de +$x$ (en radianes)\\ +{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, valor principal del arcotangente de $y/x$ (en radianes). En este caso, los signos de ambos argumentos, $y$ y $x$, se usan para determinar el cuadrante del valor resultante\\ +{\tt card(}$X${\tt)}&$|X|$, el cardinal (número de elementos) del conjunto $X$\\ +{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, el menor entero no menor que $x$ (``techo de $x$'')\\ +{\tt cos(}$x${\tt)}&$\cos x$, coseno de $x$ (en radianes)\\ +{\tt exp(}$x${\tt)}&$e^x$, exponencial en base $e$ de $x$\\ +{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, el mayor entero no mayor que $x$ (``piso de $x$'')\\ +{\tt gmtime()}&el número de segundos transcurridos desde las 00:00:00 del 1 de enero de 1970, Tiempo Universal Coordinado (para los detalles ver la Sección \ref{gmtime}, página \pageref{gmtime})\\ +{\tt length(}$c${\tt)}&$|c|$, longitud de la cadena de caracteres $c$\\ +{\tt log(}$x${\tt)}&$\log x$, logaritmo natural de $x$\\ +{\tt log10(}$x${\tt)}&$\log_{10}x$, logaritmo común (decimal) de $x$\\ +{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&el mayor de los valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&el menor de los valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt round(}$x${\tt)}&redondeo de $x$ al entero más próximo\\ +{\tt round(}$x${\tt,} $n${\tt)}&redondeo de $x$ a $n$ dígitos decimales\\ +{\tt sin(}$x${\tt)}&$\sin x$, seno de $x$ (en radianes)\\ +{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, raíz cuadrada no-negativa de $x$\\ +{\tt str2time(}$c${\tt,} $f${\tt)}&conversión de la cadena de caracteres $c$ a tiempo calendario (para los detalles ver la Sección \ref{str2time}, página \pageref{str2time})\\ +{\tt trunc(}$x${\tt)}&truncado de $x$ al entero más próximo\\ +{\tt trunc(}$x${\tt,} $n${\tt)}&truncado de $x$ a $n$ dígitos decimales\\ +{\tt Irand224()}&generación de un entero pseudo-aleatorio uniformemente distribuido en $[0,2^{24})$\\ +{\tt Uniform01()}&generación de un número pseudo-aleatorio uniformemente distribuido en $[0,1)$\\ +{\tt Uniform(}$a${\tt,} $b${\tt)}&generación de un número pseudo-aleatorio uniformemente distribuido en $[a,b)$\\ +{\tt Normal01()}&generación de una variable gaussiana pseudo-aleatoria con $\mu=0$ y $\sigma=1$\\ +{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generación de una variable gaussiana pseudo-aleatoria con $\mu$ y $\sigma$ dadas\\ +\end{tabular} + +Los argumentos de todas la funciones internas, excepto {\tt card}, {\tt length} y {\tt str2time}, deben ser expresiones numéricas. El argumento de {\tt card} debe ser una expresión de conjunto. El argumento de {\tt length} y ambos argumentos de {\tt str2time} deben ser expresiones simbólicas. + +El valor resultante de una expresión numérica que es una función de referencia es el resultado de aplicar la función a sus argumentos. + +Se debe notar que cada función generadora pseudo-aleatoria tiene un argumento latente ({\it i.e.} algún estado interno) que cambia cada vez que se aplica la función. Así, si la función se aplica repetidamente, aún con argumentos idénticos, debido al efecto colateral siempre se producirán valores resultantes diferentes. + +\subsection{Expresiones iteradas} +\label{itexpr} + +Una {\it expresión numérica iterada} es una expresión numérica primaria que tiene la siguiente forma sintáctica: +$$\mbox{\it operador-iterado expresión-indizante integrando}$$ +donde {\it operador-iterado} es el nombre simbólico del operador iterado que se ejecutará (ver más adelante), {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión numérica que participa en la operación. + +En MathProg existen cuatro operadores iterados que se pueden usar en expresiones numéricas: + +{\def\arraystretch{2} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt sum}&sumatoria&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt prod}&multiplicatoria&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt min}&mínimo&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt max}&máximo&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +\end{tabular} +} + +\noindent donde $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante, $\Delta$ es el dominio, el conjunto de los $n$-tuplos especificados en la expresión indizante que define valores particulares asignados a los índices para ejecutar la operación iterada y $f(i_1,\dots,i_n)$ es el integrando, una expresión numérica cuyo valor resultante depende de los índices. + +El valor resultante de una expresión numérica iterada es el resultado de aplicar el operador iterado a sus integrandos a través de todos los $n$-tuplos contenidos en el dominio. + +\subsection{Expresiones condicionales} +\label{ifthen} + +Una {\it expresión numérica condicional} es una expresión numérica primaria que tiene una de las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ +\mbox{{\tt if} $b$ {\tt then} $x$}\\ +\end{array} +} +$$ +donde $b$ es una expresión lógica, mientras que $x$ e $y$ son expresiones numéricas. + +El valor resultante de un expresión condicional depende del valor de la expresión lógica que sigue a la palabra clave {\tt if}. Si toma el valor {\it verdadero}, el valor de la expresión condicional es el valor de la expresión que sigue a la palabra clave {\tt then}. De otro modo, si la expresión lógica toma el valor {\it falso}, el valor de la expresión condicional es el valor de la expresión que sigue a la palabra clave {\tt else}. Si se usa la segunda forma sintáctica, la reducida, y la expresión lógica toma el valor {\it falso}, el valor resultante de la expresión condicional será cero. + +\subsection{Expresiones parentéticas} + +Cualquier expresión numérica puede ser encerrada entre paréntesis, lo que las torna sintácticamente en una expresión numérica primaria. + +Los paréntesis pueden usarse en expresiones numéricas, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores aritméticos} + +En MathProg existen los siguientes operadores aritméticos, los que se pueden usar en expresiones numéricas: + +\begin{tabular}{@{}ll@{}} +{\tt +} $x$&más unario\\ +{\tt -} $x$&menos unario\\ +$x$ {\tt +} $y$&adición\\ +$x$ {\tt -} $y$&sustracción\\ +$x$ {\tt less} $y$&diferencia positiva (si $x1$, la segunda forma es la que debe usarse. + +Si se usa la primera forma de la entrada indizante, el índice $i$ sólo puede ser un índice (ver más adelante). Si se usa la segunda forma, los índices $i_1$, $i_2$, \dots, $i_n$ pueden ser indistintamente índices o alguna expresión numérica o simbólica, siempre que al menos uno de los índices sea un índice. La tercera forma, reducida, de la entrada indizante tiene el mismo efecto que si +$i$ (si $C$ es 1-dimensional) o $i_1$, $i_2$, \dots, $i_n$ (si $C$ es $n$-dimensional) se hubieran especificado todos como índices. + +Un {\it índice} es un objeto auxiliar del modelo que actúa como una variable individual. Los valores asignados a los índices son componentes de los $n$-tuplos de conjuntos básicos, {\it i.e.} algunas cantidades numéricas y simbólicas. + +Para referenciarlos, los índices pueden ser provistos con nombres simbólicos. Sin embargo, a diferencia de otros objetos del modelo (conjuntos, parámetros, etc.), los índices no necesitan ser declarados explícitamente. Cada nombre simbólico {\it no-declarado} que se usa en una posición indizante de alguna entrada indizante es reconocido como el nombre simbólico correspondiente al índice. + +Los nombre simbólicos de los índices son válidos solamente dentro del alcance de la expresión indizante en la que se introdujo el índice. Más allá del alcance, estos índices son completamente inaccesibles, de modo que los mismos nombres simbólicos se pueden usar para diferentes propósitos, en particular para representar índices en otras expresiones indizantes. + +El alcance de la expresión indizante, en el que las declaraciones implícitas de los índices son válidas, depende del contexto en que se usa la expresión indizante: + +\vspace*{-8pt} + +\begin{itemize} +\item Si la expresión indizante se usa en un operador-iterado, su alcance se extiende hasta el final del integrando; +\item Si la expresión indizante se usa como una expresión de conjunto primaria, su alcance se extiende hasta el final de esta expresión indizante; +\item Si la expresión indizante se usa para definir el dominio del subíndice en la declaración de algún objeto del modelo, su alcance se extiende hasta el final de la correspondiente sentencia. +\end{itemize} + +\vspace*{-8pt} + +El mecanismo de indización implementado mediante las expresiones indizantes se explica mejor con algunos ejemplos que se discuten a continuación. + +Sean tres conjuntos: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +A=\{4,7,9\},\\ +B=\{(1,Ene),(1,Feb),(2,Mar),(2,Abr),(3,May),(3,Jun)\},\\ +C=\{a,b,c\},\\ +\end{array} +} +$$ +donde $A$ y $C$ consisten de 1-tuplos (singletones) y $B$ consiste de +2-tuplos (duplos). Considérese la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +donde {\tt i}, {\tt j}, {\tt k} y {\tt l} son índices. + +Aunque MathProg no es un lenguaje de programación por procedimientos, para cualquier expresión indizante se puede dar una descripción algorítmica equivalente. En particular, la descripción algorítmica de la expresión indizante anterior se vería como sigue: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\it acción};\\ +\end{tabular} + +\noindent donde los índices $i$, $j$, $k$ y $l$ son asignados consecutivamente a los correspondientes componentes de los $n$-tuplos a partir de los conjuntos básicos $A$, $B$ y $C$ y {\it acción} es alguna acción que depende del contexto en el que se esté usando la expresión indizante. Por ejemplo, si la acción fuese imprimir los valores corrientes de los índices, la impresión se vería como sigue: + +\noindent\hfil +\begin{tabular}{@{}llll@{}} +$i=4$&$j=1$&$k=Ene$&$l=a$\\ +$i=4$&$j=1$&$k=Ene$&$l=b$\\ +$i=4$&$j=1$&$k=Ene$&$l=c$\\ +$i=4$&$j=1$&$k=Feb$&$l=a$\\ +$i=4$&$j=1$&$k=Feb$&$l=b$\\ +\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +$i=9$&$j=3$&$k=Jun$&$l=b$\\ +$i=9$&$j=3$&$k=Jun$&$l=c$\\ +\end{tabular} + +Sea la expresión indizante del ejemplo usada en la siguiente operación iterada: +$$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +donde {\tt p} es un parámetro numérico 4-dimensional o alguna expresión numérica cuyos valores resultantes dependan de {\tt i}, {\tt j}, {\tt k} y {\tt l}. En este caso la acción es la sumatoria, de modo que el valor resultante de la expresión numérica primaria es: +$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +Ahora, sea la expresión indizante del ejemplo usada como una expresión de conjunto primaria. En este caso, la acción es reunir a todos los 4-tuplos (cuádruplos) de la forma $(i,j,k,l)$ en un conjunto, de modo que el valor resultante de tal operación es simplemente el producto cartesiano de los conjuntos básicos: +$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +Se debe notar que, en este caso, la misma expresión indizante podría escribirse en la forma reducida: +$$\mbox{{\tt\{A, B, C\}}}$$ +ya que los índices $i$, $j$, $k$ y $l$ no son referenciados y, consecuentemente, sus nombres simbólicos no necesitan ser especificados. + +Finalmente, sea la expresión indizante del ejemplo usada como el dominio del subíndice en la declaración de algún objeto 4-dimensional del modelo, por ejemplo un parámetro numérico: +$$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ + +\noindent En este caso la acción es generar los miembros del parámetro, donde cada uno de los cuales tiene la forma $p[i,j,k,l]$. + +Como se dijo anteriormente, algunos índices en la segunda forma de las entradas indizantes pueden ser expresiones numéricas o simbólicas, no solamente índices. En este caso, los valores resultantes de tales expresiones desempeñan el papel de algunas condiciones lógicas para seleccionar, solamente, aquellos $n$-tuplos del producto cartesiano de los conjuntos básicos que satisfacen estas condiciones. + +Considérese, por ejemplo, la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +donde {\tt i}, {\tt k} y {\tt l} son índices e {\tt i-1} es una expresión numérica. La descripción algorítmica de esta expresión indizante sería la siguiente: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf y} $j=i-1$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\it acción};\\ +\end{tabular} + +\noindent Así, si la expresión indizante se usara como una expresión de conjunto primaria, el conjunto resultante sería el siguiente: +$$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +Debe notarse que, en este caso, el conjunto resultante consistirá de 3-tuplos y no de 4-tuplos, puesto que en la expresión indizante no hay un índice que corresponda al primer componente de los 2-tuplos del conjunto $B$. + +La regla general es: el número de componentes de los $n$-tuplos definido por una expresión indizante es igual al número de índices de tal expresión, en la que la correspondencia entre los índices y los componentes de los $n$-tuplos en el conjunto resultante es posicional, {\it i.e.} el primer índice se corresponde con el primer componente, el segundo índice se corresponde con el segundo componente, etc. + +En algunos casos es necesario seleccionar un subconjunto del producto cartesiano de algunos conjuntos. Esto se puede lograr mediante el empleo de un predicado lógico opcional, el que se especifica en la expresión indizante. + +Considérese, por ejemplo, la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +donde la expresión lógica que sigue a los dos puntos es un predicado. La descripción algorítmica de tal expresión indizante sería la siguiente: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\bf si} $i\leq 5$ {\bf y} $k\neq`Mar'$ {\bf entonces}\\ +\hspace{64pt}{\it acción};\\ +\end{tabular} + +\noindent Así, si esta expresión indizante se usara como una expresión de conjunto primaria, el conjunto resultante sería el siguiente: +$$\{(4,1,Ene,a),(4,1,Feb,a),(4,2,Abr,a),\dots,(4,3,Jun,c)\}.$$ + +Si no se especifica un predicado en la expresión indizante, se asume uno que toma el valor {\it verdadero}. + +\section{Expresiones de conjunto} + +Una {\it expresión de conjunto} es una regla para calcular un conjunto elemental, {\it i.e.} una colección de $n$-tuplos cuyos componentes son cantidades numéricas y simbólicas. + +La expresión de conjunto primaria puede ser un conjunto de literales, un conjunto no-indizado, un conjunto indizado, un conjunto ``aritmético'', una expresión indizante, una expresión de conjunto iterada, una expresión de conjunto condicional u otra expresión de conjunto encerrada entre paréntesis. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(conjunto de literales)\\ +\verb|I| &(conjunto no-indizado)\\ +\verb|S[i-1,j+1]| &(conjunto indizado)\\ +\verb|1..t-1 by 2| &(conjunto ``aritmético'')\\ +\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(expresión indizante)\\ +\verb|setof{i in I, j in J}(i+1,j-1)| &(expresión de conjunto iterada)\\ +\verb|if i < j then S[i,j] else F diff S[i,j]| &(expresión de conjunto condicional)\\ +\verb|(1..10 union 21..30)| &(expresión de conjunto parentética)\\ +\end{tabular} + +Empleando ciertos operadores de conjunto se pueden construir expresiones de conjunto más generales conteniendo dos o más expresiones de conjunto primarias. + +\newpage + +\para{Ejemplos} + +\begin{verbatim} +(A union B) inter (I cross J) +1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) +\end{verbatim} + +\subsection{Conjuntos de literales} + +Un {\it conjunto de literales} es una expresión de conjunto primaria que tiene las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +\mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +\end{array} +} +$$ +donde $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ son expresiones numéricas o simbólicas. + +Si se usa la primera forma, el conjunto resultante consiste de 1-tuplos (singletones), enumerados entre las llaves. Se permite especificar un conjunto vacío como {\tt\{\ \}}, el que no tiene 1-tuplos. Si se usa la segunda forma, el conjunto resultante consiste de $n$-tuplos enumerados entre las llaves, donde cada $n$-tuplo particular está compuesto por los correspondientes componentes enumerados entre los paréntesis. Todos los $n$-tuplos deben tener el mismo número de componentes. + +\subsection{Conjuntos no-indizados} + +Si la expresión de conjunto primaria es un conjunto no-indizado (el que debe ser 0-dimensional), el conjunto resultante es un conjunto elemental asociado con el objeto conjunto correspondiente. + +\subsection{Conjuntos indizados} + +La expresión de conjunto primaria que se refiere a un conjunto indizado tiene la siguiente forma sintáctica: +$$\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +donde {\it nombre} es el nombre simbólico del objeto conjunto e $i_1$, $i_2$, +\dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe coincidir con la dimensión del objeto conjunto al cual está asociada la lista de subíndices. + +Los valores corrientes de las expresiones de los subíndices se usan para identificar un miembro particular del objeto conjunto que determina el conjunto resultante. + +\subsection{Conjuntos ``aritméticos''} + +La expresión de conjunto primaria que constituye un conjunto ``aritmético'' tiene las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +\mbox{$t_0$ {\tt..} $t_1$}\\ +\end{array} +} +$$ +donde $t_0$, $t_1$ y $\delta t$ son expresiones numéricas (el valor de +$\delta t$ no debe ser cero). La segunda forma es equivalente a la primera con $\delta t=1$. + +Si $\delta t>0$, el conjunto resultante se determina como sigue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +De otro modo, si $\delta t<0$, el conjunto resultante se determina como sigue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ + +\subsection{Expresiones de indización} + +Si la expresión de conjunto primaria es una expresión indizante, el conjunto resultante se determina como se ha descripto anteriormente en la Sección \ref{indexing}, página \pageref{indexing}. + +\subsection{Expresiones iteradas} + +Una {\it expresión de conjunto iterada} es una expresión de conjunto primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt setof} {\it expresión-indizante} {\it integrando}}$$ +donde {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es tanto una expresión numérica o simbólica individual como una lista de expresiones numéricas o simbólicas separadas por coma y encerradas entre paréntesis. + +Si el integrando es una expresión numérica o simbólica individual, el conjunto resultante está compuesto por 1-tuplos y se determina como sigue: +$$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +\noindent donde $x$ es un valor del integrando, $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante y $\Delta$ es el dominio, un conjunto de $n$-tuplos especificados por la expresión indizante que define los valores particulares asignados a los índices para realizar la operación iterada. + +Si el integrando es una lista conteniendo $m$ expresiones numéricas y simbólicas, el conjunto resultante está compuesto por $m$-tuplos y se determina como sigue: +$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +donde $x_1$, \dots, $x_m$ son valores de las expresiones en la lista de integrandos e $i_1$, \dots, $i_n$ y $\Delta$ tienen el mismo significado anterior. + +\subsection{Expresiones condicionales} + +Una {\it expresión de conjunto condicional} es una expresión de conjunto primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +donde $b$ es una expresión lógica y $X$ e $Y$ son expresiones de conjunto que deben definir conjuntos de igual dimensión. + +El valor resultante de la expresión condicional depende del valor de la expresión lógica que sigue a la palabra clave {\tt if}. Si toma el valor {\it verdadero}, el conjunto resultante es el valor de la expresión que sigue a la palabra clave {\tt then}. De otro modo, si la expresión lógica toma el valor {\it falso}, el conjunto resultante es el valor de la expresión que sigue a la palabra clave {\tt else}. + +\subsection{Expresiones parentéticas} + +Cualquier expresión de conjunto puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión de conjunto primaria. + +Los paréntesis pueden usarse en expresiones de conjunto, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores de conjunto} + +En MathProg existen los siguientes operadores de conjunto, los que se pueden usar en expresiones de conjunto: + +\begin{tabular}{@{}ll@{}} +$X$ {\tt union} $Y$&union $X\cup Y$\\ +$X$ {\tt diff} $Y$&diferencia $X\backslash Y$\\ +$X$ {\tt symdiff} $Y$&diferencia simétrica $X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +$X$ {\tt inter} $Y$&intersección $X\cap Y$\\ +$X$ {\tt cross} $Y$&producto cartesiano (``cruzado'') $X\times Y$\\ +\end{tabular} + +\noindent donde $X$ e $Y$ son expresiones de conjunto que deben definir conjuntos de la misma dimensión (excepto para el producto cartesiano). + +Si la expresión incluye más de un operador de conjunto, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). + +El valor resultante de la expresión que contiene operadores de conjunto es el resultado de aplicar los operadores a sus operandos. + +La dimensión del conjunto resultante, {\it i.e.} la dimensión de los $n$-tuplos de los que consiste el conjunto resultante, es la dimensión de los operandos, excepto en el producto cartesiano, en la que la dimensión del conjunto resultante es la suma de las dimensiones de sus operandos. + +\subsection{Jerarquía de las operaciones} + +La siguiente lista muestra la jerarquía de las operaciones en expresiones de conjunto: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operación&Jerarquía\\ +\hline +Evaluación de operaciones numéricas& +1.{\textsuperscript{\b{a}}}-7.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones simbólicas& +8.{\textsuperscript{\b{a}}}-9.{\textsuperscript{\b{a}}}\\ +Evaluación de conjuntos iterados o ``aritméticos'' ({\tt setof}, {\tt..})& +10.{\textsuperscript{\b{a}}}\\ +Producto cartesiano ({\tt cross})& +11.{\textsuperscript{\b{a}}}\\ +Intersección ({\tt inter})& +12.{\textsuperscript{\b{a}}}\\ +Unión y diferencia ({\tt union}, {\tt diff}, {\tt symdiff})& +13.{\textsuperscript{\b{a}}}\\ +Evaluación condicional ({\tt if} \dots {\tt then} \dots {\tt else})& +14.{\textsuperscript{\b{a}}}\\ +\end{tabular} + +Esta jerarquía tiene el mismo significado que se explicó anteriormente para expresiones numéricas (ver Subsección \ref{hierarchy}, página \pageref{hierarchy}). + +\section{Expresiones lógicas} + +Una {\it expresión lógica} es una regla para calcular un valor lógico individual, el que puede ser tanto {\it verdadero} como {\it falso}. + +La expresión lógica primaria puede ser una expresión numérica, una expresión relacional, una expresión lógica iterada u otra expresión lógica encerrada entre paréntesis. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|i+1| &(expresión numérica)\\ +\verb|a[i,j] < 1.5| &(expresión relacional)\\ +\verb|s[i+1,j-1] <> 'Mar' & anho | &(expresión relacional)\\ +\verb|(i+1,'Ene') not in I cross J| &(expresión relacional)\\ +\verb|S union T within A[i] inter B[j]| &(expresión relacional)\\ +\verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(expresión lógica iterada)\\ +\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(expresión lógica parentética)\\ +\end{tabular} + +Empleando ciertos operadores lógicos se pueden construir expresiones lógicas más generales conteniendo dos o más expresiones lógicas primarias. + +\para{Ejemplos} + +\begin{verbatim} +not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +(i,j) in S or (i,j) not in T diff U +\end{verbatim} + +\vspace*{-8pt} + +\subsection{Expresiones numéricas} + +El valor resultante de una expresión lógica primaria, cuando es una expresión numérica, es {\it verdadero} si el valor resultante de la expresión numérica es distinto de cero. De otro modo, el valor resultante de la expresión lógica es {\it falso}. + +\vspace*{-8pt} + +\subsection{Operadores relacionales} + +En MathProg existen los siguientes operadores relacionales, los que se pueden usar en expresiones lógicas: + +\begin{tabular}{@{}ll@{}} +$x$ {\tt<} $y$&comprueba si $x=} $y$&comprueba si $x\geq y$\\ +$x$ {\tt>} $y$&comprueba si $x>y$\\ +$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&comprueba si $x\neq y$\\ +$x$ {\tt in} $Y$&comprueba si $x\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&comprueba si +$(x_1,\dots,x_n)\in Y$\\ +$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&comprueba si $x\not\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&comprueba si +$(x_1,\dots,x_n)\not\in Y$\\ +$X$ {\tt within} $Y$&comprueba si $X\subseteq Y$\\ +$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&comprueba si +$X\not\subseteq Y$\\ +\end{tabular} + +\noindent donde $x$, $x_1$, \dots, $x_n$ e $y$ son expresiones numéricas o simbólicas, mientras que $X$ e $Y$ son expresiones de conjunto. + +Notas: + +1. En las operaciones {\tt in}, {\tt not in} y {\tt !in} el número de componentes del primer operando debe ser igual a la dimensión del segundo operando. + +2. En las operaciones {\tt within}, {\tt not within} y {\tt !within} ambos operandos deben tener la misma dimensión. + +Todos los operadores relacionales listados anteriormente tienen su significado matemático convencional. El valor resultante es {\it verdadero} si los operandos satisfacen la correspondiente relación, o es {\it falso} en caso contrario. (Debe notarse que los valores simbólicos se ordenan lexicográficamente y que cualquier valor numérico precede a cualquier valor simbólico.) + +\subsection{Expresiones iteradas} + +Una {\it expresión lógica iterada} es una expresión lógica primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\it operador-iterado} {\it expresión-indizante} +{\it integrando}}$$ +donde {\it operador-iterado} es el nombre simbólico del operador iterado que se ejecutará (ver más adelante), {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión lógica que participa en la operación. + +En MathProg existen dos operadores iterados que se pueden usar en expresiones lógicas: + +{\def\arraystretch{1.4} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt forall}&cuantificador-$\forall$&$\displaystyle +\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +{\tt exists}&cuantificador-$\exists$&$\displaystyle +\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +\end{tabular} +} + +\noindent donde $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante, $\Delta$ es el dominio, un conjunto de $n$-tuplos especificados por la expresión indizante que define los valores particulares asignados a los índices para ejecutar la operación iterada y $f(i_1,\dots,i_n)$ es el integrando, una expresión lógica cuyo valor resultante depende de los índices. + +Para el cuantificador-$\forall$, el valor resultante de la expresión lógica iterada es {\it verdadero} si el valor del integrando es {\it verdadero} para todos los $n$-tuplos contenidos en el dominio, de otro modo es {\it falso}. + +Para el cuantificador-$\exists$, el valor resultante de la expresión lógica iterada es {\it falso} si el valor del integrando es {\it falso} para todos los $n$-tuplos contenidos en el dominio, de otro modo es {\it verdadero}. + +\subsection{Expresiones parentéticas} + +Cualquier expresión lógica puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión lógica primaria. + +Los paréntesis pueden usarse en expresiones lógicas, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores lógicos} + +En MathProg existen los siguientes operadores lógicos, los que se pueden usar en expresiones lógicas: + +\begin{tabular}{@{}ll@{}} +{\tt not} $x$, {\tt!}$x$&negación $\neg\ x$\\ +$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunción (``y'' lógico) +$x\;\&\;y$\\ +$x$ {\tt or} $y$, $x$ {\tt||} $y$&disyunción (``o'' lógico) +$x\vee y$\\ +\end{tabular} + +\noindent donde $x$ e $y$ son expresiones lógicas. + +Si la expresión incluye más de un operador lógico, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). El valor resultante de la expresión que contiene operadores lógicos es el resultado de aplicar los operadores a sus operandos. + +\subsection{Jerarquía de las operaciones} + +La siguiente lista muestra la jerarquía de las operaciones en expresiones lógicas: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operación&Jerarquía\\ +\hline +Evaluación de operaciones numéricas& +1.{\textsuperscript{\b{a}}}-7.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones simbólicas& +8.{\textsuperscript{\b{a}}}-9.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones de conjuntos& +10.{\textsuperscript{\b{a}}}-14.{\textsuperscript{\b{a}}}\\ +Operaciones relacionales ({\tt<}, {\tt<=}, etc.)& +15.{\textsuperscript{\b{a}}}\\ +Negación ({\tt not}, {\tt!})& +16.{\textsuperscript{\b{a}}}\\ +Conjunción ({\tt and}, {\tt\&\&})& +17.{\textsuperscript{\b{a}}}\\ +Cuantificación-$\forall$ y -$\exists$ ({\tt forall}, {\tt exists})& +18.{\textsuperscript{\b{a}}}\\ +Disyunción ({\tt or}, {\tt||})& +19.{\textsuperscript{\b{a}}}\\ +\end{tabular} + +Esta jerarquía tiene el mismo significado que se explicó anteriormente para expresiones numéricas (ver Subsección \ref{hierarchy}, página \pageref{hierarchy}). + +\section{Expresiones lineales} + +Una {\it expresión lineal} es una regla para calcular la denominada {\it forma lineal}, que es una función lineal (o afín) de variables elementales. + +La expresión lineal primaria puede ser una variable no-indizada, una variable indizada, una expresión lineal iterada, una expresión lineal condicional u otra expresión lineal encerrada entre paréntesis. + +También está permitido usar una expresión numérica como una expresión lineal primaria, en cuyo caso el valor resultante de la expresión numérica se convierte automáticamente a una forma lineal que incluye el término constante solamente. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|z| &(variable no-indizada)\\ +\verb|x[i,j]| &(variable indizada)\\ +\verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +(expresión lineal iterada)\\ +\verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +(expresión lineal condicional)\\ +\verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +(expresión lineal parentética)\\ +\end{tabular} + +Empleando ciertos operadores aritméticos se pueden construir expresiones lineales más generales conteniendo dos o más expresiones lineales primarias. + +\para{Ejemplos} + +\begin{verbatim} +2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z +(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) +\end{verbatim} + +\vspace*{-5pt} + +\subsection{Variables no-indizadas} + +Si la expresión lineal primaria es una variable no-indizada (que debe ser 0-dimensional), la forma lineal resultante es aquella variable no-indizada. + +\vspace*{-5pt} + +\subsection{Variables indizadas} + +La expresión lineal primaria que se refiere a una variable indizada tiene la siguiente forma sintáctica: +$$\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +donde {\it nombre} es el nombre simbólico de la variable del modelo e $i_1$, +$i_2$, \dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe ser igual a la dimensión de la variable del modelo con la cual está asociada la lista de subíndices. + +Los valores corrientes de las expresiones de los subíndices se usan para identificar un miembro particular de la variable del modelo que determina la forma lineal resultante, la cual es una variable elemental asociada con el miembro correspondiente. + +\vspace*{-5pt} + +\subsection{Expresiones iteradas} + +Una {\it expresión lineal iterada} es una expresión lineal primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt sum} {\it expresión-indizante} {\it integrando}}$$ +donde {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión lineal que participa en la operación. + +La expresión lineal iterada se evalúa exactamente de la misma manera que la expresión numérica iterada (ver Subsección \ref{itexpr}, página +\pageref{itexpr}), excepto que el integrando participante en la sumatoria es una forma lineal y no un valor numérico. + +\vspace*{-5pt} + +\subsection{Expresiones condicionales} + +Una {\it expresión lineal condicional} es una expresión lineal primaria que tiene alguna de las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +\mbox{{\tt if} $b$ {\tt then} $f$}\\ +\end{array} +} +$$ +donde $b$ es una expresión lógica, mientras que $f$ y $g$ son expresiones lineales. + +La expresión lineal condicional se evalúa exactamente de la misma manera que la expresión numérica condicional (ver Subsección \ref{ifthen}, página \pageref{ifthen}), excepto que los operandos participantes en la operación son formas lineales y no valores numéricos. + +\subsection{Expresiones parentéticas} + +Cualquier expresión lineal puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión lineal primaria. + +Los paréntesis pueden usarse en expresiones lineales, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores aritméticos} + +En MathProg existen los siguientes operadores aritméticos, los que se pueden usar en expresiones lineales: + +\begin{tabular}{@{}ll@{}} +{\tt+} $f$&más unario\\ +{\tt-} $f$&menos unario\\ +$f$ {\tt+} $g$&adición\\ +$f$ {\tt-} $g$&sustracción\\ +$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplicación\\ +$f$ {\tt/} $x$&división +\end{tabular} + +\noindent donde $f$ y $g$ son expresiones lineales, mientras que $x$ es una expresión numérica (más precisamente, una expresión lineal conteniendo únicamente el término constante). + +Si la expresión incluye más de un operador aritmético, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). El valor resultante de la expresión que contiene operadores aritméticos es el resultado de aplicar los operadores a sus operandos. + +\subsection{Jerarquía de las operaciones} + +La jerarquía de las operaciones aritméticas usadas en las expresiones lineales es la misma que en las expresiones numéricas (ver Subsección \ref{hierarchy}, +página \pageref{hierarchy}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Sentencias} + +Las {\it sentencias} son unidades básicas de la descripción del modelo. En MathProg todas las sentencias se clasifican en dos categorías: sentencias declarativas y sentencias funcionales. + +Las {\it sentencias declarativas} (sentencia {\it set}, sentencia {\it parameter}, sentencia {\it variable}, sentencia {\it constraint} y sentencia {\it objective}) se usan para declarar objetos de cierto tipo del modelo y definir ciertas propiedades de tales objetos. + +Las {\it sentencias funcionales} (sentencia {\it solve}, sentencia {\it check}, sentencia {\it display}, sentencia {\it printf}, sentencia {\it loop} y sentencia {\it table}) están ideadas para ejecutar ciertas acciones específicas. + +Debe notarse que las sentencias declarativas pueden seguir cualquier orden arbitrario, lo cual no afecta el resultado de la traducción. Sin embargo, todos los objetos del modelo deben ser declarados antes de ser referenciados en otras sentencias. + +\section{Sentencia set} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del conjunto; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el conjunto; + +\noindent +{\it dominio} es una expresión-indizante opcional que especifica el dominio del subíndice del conjunto; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales del conjunto (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt dimen} $n$]\hspace*{0pt}\\ +especifica la dimensión de los $n$-tuplos de los que consiste el conjunto; +\item[{\tt within} {\it expresión}]\hspace*{0pt}\\ +especifica un superconjunto que restringe al conjunto o a todos sus miembros (conjuntos elementales) a estar incluido en aquel superconjunto; +\item[{\tt:=} {\it expresión}]\hspace*{0pt}\\ +especifica un conjunto elemental asignado al conjunto o sus miembros; +\item[{\tt default} {\it expresión}]\hspace*{0pt}\\ +especifica un conjunto elemental asignado al conjunto o sus miembros cuando no haya datos apropiados disponibles en la sección de datos. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +set nodos; +set arcos within nodos cross nodos; +set paso{p in 1..maxiter} dimen 2 := if p = 1 then arcos else paso[p-1] + union setof{k in nodos, (i,k) in paso[p-1], (k,j) in paso[p-1]}(i,j); +set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, + default {('abc',123), (321,'cba')}; +\end{verbatim} + +La sentencia set declara un conjunto. Si no se especifica el dominio del subíndice, el conjunto será simple, de otro modo será un arreglo de conjuntos elementales. + +El atributo {\tt dimen} especifica la dimensión de los $n$-tuplos de los que consiste el conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales), en la que $n$ debe ser un entero sin signo desde 1 hasta 20. Como mucho se puede especificar un atributo {\tt dimen}. Si no se especifica el atributo {\tt dimen}, la dimensión de los $n$-tuplos se determina implícitamente por otros atributos (por ejemplo, si hay una expresión de conjunto que sigue a {\tt :=} o a la palabra clave {\tt default}, se usará la dimensión de los $n$-tuplos del correspondiente conjunto elemental). Si no hay información disponible sobre la dimensión, se asume {\tt dimen 1}. + +El atributo {\tt within} especifica una expresión de conjunto cuyo valor resultante es un superconjunto usado para restringir al conjunto (si es un conjunto simple) o a sus miembros (si el conjunto es un arreglo de conjuntos elementales) a estar incluido en aquel superconjunto. Se puede especificar un número arbitrario de atributos {\tt within} en la misma sentencia set. + +El atributo de asignación ({\tt :=}) especifica una expresión de conjunto usada para evaluar conjuntos elementales asignados al conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales). Si se especifica el atributo de asignación, el conjunto es {\it calculable} y consecuentemente no es necesario proveerle datos en la sección de datos. Si no se especifica el atributo de asignación, entonces se deben proveer datos para el conjunto en la sección de datos. Como mucho, se puede especificar una asignación o un atributo {\tt default} para el mismo conjunto. + +El atributo {\tt default} especifica una expresión de conjunto usada para evaluar conjuntos elementales asignados al conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales) toda vez que no haya datos apropiados disponibles en la sección de datos. Si no se especifica una asignación o un atributo {\tt default}, la carencia de datos causará un error. + +\newpage + +\section{Sentencia parameter} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del parámetro; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el parámetro; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice del parámetro; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales del parámetro (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +especifica que el parámetro es entero; +\item[{\tt binary}]\hspace*{0pt}\\ +especifica que el parámetro es binario; +\item[{\tt symbolic}]\hspace*{0pt}\\ +especifica que el parámetro es simbólico; +\item[{\it relación expresión}]\hspace*{0pt}\\ +(donde {\it relación} es alguno de: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +especifica una condición que restringe al parámetro o a sus miembros a satisfacer aquella condición; +\item[{\tt in} {\it expresión}]\hspace*{0pt}\\ +especifica un superconjunto que restringe al parámetro o a sus miembros a estar incluidos en aquel superconjunto; +\item[{\tt:=} {\it expresión}]\hspace*{0pt}\\ +especifica un valor asignado al parámetro o a sus miembros; +\item[{\tt default} {\it expresión}]\hspace*{0pt}\\ +especifica un valor asignado al parámetro o a sus miembros cuando no haya datos apropiados disponibles en la sección de datos. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +param unidades{insumo,producto} >= 0; +param ganancia{producto, 1..T+1}; +param N := 20 integer >= 0 <= 100; +param combinacion 'n elige k' {n in 0..N, k in 0..n} := + if k = 0 or k = n then 1 else combinacion[n-1,k-1] + combinacion[n-1,k]; +param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], + in C[i,j], default 0.5 * (i + j); +param mes symbolic default 'May' in {'Mar', 'Abr', 'May'}; +\end{verbatim} + +La sentencia parameter declara un parámetro. Si el dominio del subíndice no se especifica, el parámetro es un parámetro simple (escalar); de otro modo es un arreglo $n$-dimensional. + +Los atributos de tipo {\tt integer}, {\tt binary} y {\tt symbolic} califican el tipo de valores que se le puede asignar al parámetro como se muestra a continuación: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Atributo de tipo&Valores asignado\\ +\hline +(no especificado)&Cualquier valor numérico\\ +{\tt integer}&Solamente valores numéricos enteros\\ +{\tt binary}&Tanto 0 como 1\\ +{\tt symbolic}&Cualquier valor numérico y simbólico\\ +\end{tabular} + +El atributo {\tt symbolic} no se puede especificar junto con otros atributos de tipo. Cuando se especifica debe preceder a todos los demás atributos. + +El atributo de condición especifica una condición opcional que restringe los valores asignados al parámetro a satisfacer esta condición. Este atributo tiene las siguientes formas sintácticas: + +\begin{tabular}{@{}ll@{}} +{\tt<} $v$&comprueba si $x=} $v$&comprueba si $x\geq v$\\ +{\tt>} $v$&comprueba si $x\geq v$\\ +{\tt<>} $v$, {\tt!=} $v$&comprueba si $x\neq v$\\ +\end{tabular} + +\noindent donde $x$ es un valor asignado al parámetro y $v$ es el valor resultante de una expresión numérica o simbólica especificada en el atributo de condición. Se puede especificar un número arbitrario de atributos de condición para el mismo parámetro. Si el valor que se está asignando al parámetro durante la evaluación del modelo viola al menos una de las condiciones especificadas, se producirá un error. (Debe notarse que los valores simbólicos se ordenan lexicográficamente y que cualquier valor numérico precede a cualquier valor simbólico.) + +El atributo {\tt in} es semejante al atributo de condición y especifica una expresión de conjunto cuyo valor resultante es un superconjunto usado para restringir los valores numéricos o simbólicos asignados al parámetro a estar incluidos en aquel superconjunto. Se puede especificar un número arbitrario de atributos {\tt in} para el mismo parámetro. Si el valor que se está asignando al parámetro durante la evaluación del modelo no pertenece al menos a uno de los superconjuntos especificados, se producirá un error. + +El atributo de asignación ({\tt:=}) especifica una expresión numérica o simbólica usada para calcular un valor asignado al parámetro (si es un parámetro simple) o a sus miembros (si el parámetro es un arreglo). Si se especifica el atributo de asignación, el parámetro es {\it calculable} y consecuentemente no es necesario proveer datos en la sección de datos. Si no se especifica el atributo de asignación, entonces se deben proveer datos para el parámetro en la sección de datos. Como mucho, se puede especificar una asignación o un atributo {\tt default} para el mismo conjunto. + +El atributo {\tt default} especifica una expresión numérica o simbólica que se usa para calcular un valor asignado al parámetro o a sus miembros, toda vez que no haya datos apropiados disponibles en la sección de datos. Si no se especifica una asignación ni un atributo {\tt default}, la carencia de datos causará un error. + +\section{Sentencia variable} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt var} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la variable; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la variable; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la variable; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales de la variable (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +restringe la variable a ser entera; +\item[{\tt binary}]\hspace*{0pt}\\ +restringe la variable a ser binaria; +\item[{\tt>=} {\it expresión}]\hspace*{0pt}\\ +especifica una cota inferior para la variable; +\item[{\tt<=} {\it expresión}]\hspace*{0pt}\\ +especifica una cota superior para la variable; +\item[{\tt=} {\it expresión}]\hspace*{0pt}\\ +especifica un valor fijo para la variable. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +var x >= 0; +var y{I,J}; +var elaborar{p in producto}, integer, >= compromiso[p], <= mercado[p]; +var almacenar{insumo, 1..T+1} >= 0; +var z{i in I, j in J} >= i+j; +\end{verbatim} + +La sentencia variable declara una variable. Si no se especifica el dominio del subíndice, la variable es una variable simple (escalar); de otro modo es un arreglo $n$-dimensional de variables elementales. + +Las variables elementales asociadas con una variable del modelo (si es una variable simple) o sus miembros (si es un arreglo) corresponde a las variables en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). Debe notarse que sólo variables elementales realmente referenciadas en algunas restricciones y/u objetivos se incluirán en la instancia del problema de PL/PEM que se generará. + +Los atributos de tipo {\tt integer} y {\tt binary} restringen la variable a ser entera o binaria, respectivamente. Si no se especifica un atributo de tipo, la variable será continua. Si todas las variables en el modelo son continuas, el problema correspondiente será de la clase PL. Si hay al menos una variable entera o binaria, el problema será de la clase PEM. + +El atributo de cota inferior ({\tt>=}) especifica una expresión numérica para calcular la cota inferior de la variable. Se puede especificar una cota inferior como máximo. Por defecto, todas las variables no tienen cota inferior (excepto las binarias), de modo que si se requiere que sea no-negativa, su cota inferior cero debe especificarse explícitamente. + +El atributo de cota superior ({\tt<=}) especifica una expresión numérica para calcular la cota superior de la variable. Se puede especificar una cota superior como máximo. + +El atributo de valor fijo ({\tt=}) especifica una expresión numérica para calcular el valor en el cual se fijará la variable. Este atributo no puede especificarse junto con los atributos de cota. + +\section{Sentencia constraint} + +\noindent +\framebox[468pt][l]{ +\parbox[c][106pt]{468pt}{ +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt<=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt>=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt<=} {\it expresión} {\tt,} {\tt<=} +{\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt>=} {\it expresión} {\tt,} {\tt>=} +{\it expresión} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la restricción; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la restricción; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la restricción; + +\noindent +{\it expresión} es una expresión lineal usada para calcular un componente de la restricción (las comas que siguen a las expresiones pueden omitirse). + +\noindent +(La palabra clave {\tt s.t.} se puede escribir como {\tt subject to}, o como {\tt subj to} o ser completamente omitida.) + +\para{Ejemplos} + +\begin{verbatim} +s.t. r: x + y + z, >= 0, <= 1; +limite{t in 1..T}: sum{j in producto} elaborar[j,t] <= max_producto; +subject to balance{i in insumo, t in 1..T}: + almacenar[i,t+1] = almacenar[i,t] - + sum{j in producto} unidades[i,j] * elaborar[j,t]; +subject to ltn 'limite tiempo normal' {t in tiempo}: + sum{p in producto} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * brigadas[t]; +\end{verbatim} + +La sentencia constraint declara una restricción. Si no se especifica el dominio del subíndice, la restricción es una restricción simple (escalar); de otro modo, es un arreglo $n$-dimensional de restricciones elementales. + +Las restricciones elementales asociadas con la restricción del modelo (si es una restricción simple) o sus miembros (si es un arreglo) corresponde a las restricciones lineales en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). + +Si la restricción tiene la forma de una igualdad o desigualdad simple, {\it i.e.} incluye dos expresiones, una de las cuales está a continuación de los dos puntos y la otra está a continuación del signo relacional {\tt=}, {\tt<=} o {\tt>=}, ambas expresiones de la sentencia pueden ser expresiones lineales. Si la restricción tiene la forma de una doble desigualdad, {\it i.e.} incluye tres expresiones, la expresión del medio puede ser una expresión lineal mientras que la de la izquierda y la de la derecha sólo pueden ser expresiones numéricas. + +Generar el modelo es, groseramente hablando, generar sus restricciones, las que son siempre evaluadas para todo el dominio del subíndice. A su vez, la evaluación de las restricciones lleva a la evaluación de otros objetos del modelo tales como los conjuntos, los parámetros y las variables. + +La construcción de una restricción lineal real incluida en la instancia del problema, la cual corresponde a una restricción elemental particular, se realiza como sigue. + +Si la restricción tiene la forma de una igualdad o desigualdad simple, la evaluación de ambas expresiones lineales resulta en dos formas lineales: +$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +g&=&b_1x_1&+&b_2x_2&+\dots+&b_nx_n&+&b_0,\\ +\end{array}$$ +donde $x_1$, $x_2$, \dots, $x_n$ son variables elementales; $a_1$, $a_2$, +\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ son coeficientes numéricos y +$a_0$ y $b_0$ son términos constantes. Luego, todos los términos lineales de $f$ y $g$ se llevan al lado izquierdo y los términos constantes se llevan al lado derecho, para dar la restricción elemental final en forma estándar: +$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ + +Si la restricción tiene la forma de una doble desigualdad, la evaluación de la expresión lineal del medio resulta en una forma lineal: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +y la evaluación de las expresiones numéricas de la izquierda y de la derecha dará dos valores numéricos $l$ y $u$, respectivamente. Luego, el término constante de la forma lineal se lleva tanto a la izquierda como a la derecha para dar la restricción elemental final en forma estándar: +$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + +\section{Sentencia objective} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt minimize} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt maximize} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del objetivo; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el objetivo; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice del objetivo; + +\noindent +{\it expresión} es una expresión lineal usada para calcular la forma lineal del objetivo. + +\para{Ejemplos} + +\begin{verbatim} +minimize objetivo: x + 1.5 * (y + z); +maximize ganancia_total: sum{p in producto} ganancia[p] * elaborar[p]; +\end{verbatim} + +La sentencia objective declara un objetivo. Si no se especifica el dominio del subíndice, el objetivo es un objetivo simple (escalar); de otro modo, es un arreglo $n$-dimensional de objetivos elementales. + +Los objetivos elementales asociados con el objetivo del modelo (si es un objetivo simple) o sus miembros (si es un arreglo) corresponden a restricciones lineales generales en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). Sin embargo, a diferencia de las restricciones, las correspondientes formas lineales son libres (no tienen cota). + +La construcción de una restricción lineal real incluida en la instancia del problema, la cual corresponde a una restricción elemental particular, se realiza como sigue. La expresión lineal especificada en la sentencia objective se evalúa para resultar en una forma lineal: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +donde $x_1$, $x_2$, \dots, $x_n$ son variables elementales; $a_1$, $a_2$, +\dots, $a_n$ son coeficientes numéricos y $a_0$ es el término constante. Luego se usa la forma lineal para construir la restricción elemental final en forma estándar: +$$-\infty= 0 and y >= 0; +check sum{i in ORIGEN} oferta[i] = sum{j in DESTINO} demanda[j]; +check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +\end{verbatim} + +El sentencia check permite comprobar el valor resultante de una expresión lógica especificada en la sentencia. Si el valor es {\it falso} se reporta un error. + +Si el dominio del subíndice no se especifica, la comprobación se ejecuta solamente una vez. Especificar el dominio del subíndice permite ejecutar múltiples comprobaciones para cada $n$-tuplo en el conjunto dominio. En este último caso, la expresión lógica puede incluir índices introducidos en la correspondiente expresión indizante. + +\section{Sentencia display} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt display} {\it dominio} {\tt:} {\it ítem} {\tt,} +\dots {\tt,} {\it ítem} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia display; + +\noindent +{\it ítem}, \dots, {\it ítem} son ítems que se mostrarán (los dos puntos que preceden al primer ítem pueden omitirse). + +\para{Ejemplos} + +\begin{verbatim} +display: 'x =', x, 'y =', y, 'z =', z; +display sqrt(x ** 2 + y ** 2 + z ** 2); +display{i in I, j in J}: i, j, a[i,j], b[i,j]; +\end{verbatim} + +La sentencia display evalúa todos los ítems especificados en la sentencia y escribe sus valores en la salida estándar (terminal) en formato de texto plano. + +Si el dominio del subíndice no se especifica, los ítems son evaluados y mostrados solamente una vez. Especificar el dominio del subíndice produce que los ítems sean evaluados y mostrados para cada $n$-tuplo en el conjunto dominio. En este último caso, los ítems pueden incluir índices introducidos en la correspondiente expresión indizante. + +Un ítem a ser mostrado puede ser un objeto del modelo (conjunto, parámetro, variable, restricción u objetivo) o una expresión. + +Si el ítem es un objeto calculable ({\it i.e.} un conjunto o parámetro provisto con el atributo de asignación), el mismo es evaluado a través de todo su dominio y luego se muestra su contenido ({\it i.e.} el contenido del arreglo de objetos). De otro modo, si el ítem no es un objeto calculable, solamente se muestra su contenido corriente ({\it i.e.} los miembros realmente generados durante la evaluación del modelo). + +Si el ítem es una expresión, la misma se evalúa y se muestra su valor resultante. + +\section{Sentencia printf} + +\noindent +\framebox[468pt][l]{ +\parbox[c][64pt]{468pt}{ +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt>} +{\it archivo} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt>}{\tt>} +{\it archivo} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia printf; + +\noindent +{\it formato} es una expresión simbólica cuyo valor especifica una cadena de control de formato (los dos puntos que preceden a la expresión de formato pueden omitirse). + +\noindent +{\it expresión}, \dots, {\it expresión} son cero o más expresiones cuyos valores deben ser formateados e impresos. Cada expresión debe ser de tipo numérico, simbólico o lógico. + +\noindent +{\it archivo} es una expresión simbólica cuyo valor especifica el nombre de un archivo de texto al cual se redirigirá la salida. La señal {\tt>} significa la creación de un archivo nuevo y vacío, mientras que la señal {\tt>}{\tt>} significa anexar la salida a un archivo existente. Si no se especifica un nombre de archivo, la salida se escribe en la salida estándar (terminal). + +\para{Ejemplos} + +\begin{verbatim} +printf 'Hola, mundo!\n'; +printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "resultado.txt"; +printf{i in I, j in J}: "el flujo desde %s hacia %s es %d\n", i, j, x[i,j] + >> archivo_resultados & ".txt"; +printf{i in I} 'el flujo total de %s es %g\n', i, sum{j in J} x[i,j]; +printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), + k, x[k]; +\end{verbatim} + +La sentencia printf es semejante a la sentencia display; sin embargo, la misma permite formatear los datos que se escribirán. + +Si el dominio del subíndice no se especifica, la sentencia printf es ejecutada solamente una vez. Especificar el dominio del subíndice produce que la sentencia printf sea ejecutada para cada $n$-tuplo en el conjunto dominio. En este último caso, el formato y la expresión pueden incluir índices introducidos en la correspondiente expresión indizante. + +La cadena de control de formato es el valor de la expresión simbólica {\it formato} especificado en la sentencia printf. Se compone con cero o más directivas como sigue: caracteres ordinarios (no {\tt\%}), que son copiados sin modificación al flujo de salida, y especificaciones de conversión, cada una de las cuales provoca la evaluación de la expresión correspondiente especificada en la sentencia printf, su formateo y la escritura del valor resultante en el flujo de salida. + +Las especificaciones de conversión que se pueden usar en la cadena de control de formato son las siguientes: {\tt d}, {\tt i}, {\tt f}, {\tt F}, {\tt e}, {\tt E}, {\tt g}, {\tt G} y {\tt s}. Estas especificaciones tienen la misma semántica y sintaxis que en el lenguaje de programación C. + +\section{Sentencia for} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt for} {\it dominio} {\tt:} {\it sentencia} {\tt;} + +\medskip + +\hspace{6pt} {\tt for} {\it dominio} {\tt:} {\tt\{} {\it sentencia} +\dots {\it sentencia} {\tt\}} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia for (los dos puntos a continuación de la expresión indizante pueden omitirse); + +\noindent +{\it sentencia} es una sentencia que será ejecutada bajo el control de la sentencia for; + +\noindent +{\it sentencia}, \dots, {\it sentencia} es una secuencia de sentencias (encerrada entre llaves) que serán ejecutadas bajo el control de la sentencia for. + +Solamente se pueden usar las siguientes sentencias dentro de la sentencia for: check, display, printf y otra sentencia for. + +\para{Ejemplos} + +\begin{verbatim} +for {(i,j) in E: i != j} +{ printf "el flujo desde %s hacia %s es %g\n", i, j, x[i,j]; + check x[i,j] >= 0; +} +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} +for {1..72} printf("*"); +\end{verbatim} + +La sentencia for provoca que la sentencia o secuencia de sentencias especificadas como parte de la sentencia for sea ejecutada para cada $n$-tuplo en el conjunto dominio. De modo que las sentencias dentro de la sentencia for pueden incluir índices introducidos en la correspondiente expresión indizante. + +\section{Sentencia table} + +\noindent +\framebox[468pt][l]{ +\parbox[c][80pt]{468pt}{ +\hspace{6pt} {\tt table} {\it nombre} {\it alias} {\tt IN} {\it controlador} +{\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it conjunto} {\tt<-} {\tt[} {\it cmp} {\tt,} +\dots {\tt,} {\it cmp} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +{\it cmp} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it cmp} +{\tt;} + +\medskip + +\hspace{6pt} {\tt table} {\it nombre} {\it alias} {\it dominio} {\tt OUT} +{\it controlador} {\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it cmp} +{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it cmp} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la tabla; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la tabla; + +\noindent +{\it dominio} es una expresión indizante que especifica el dominio del subíndice de la tabla (de salida); + +\noindent +{\tt IN} significa leer datos desde la tabla de entrada; + +\noindent +{\tt OUT} significa escribir datos en la tabla de salida; + +\noindent +{\it controlador} es una expresión simbólica que especifica el controlador usado para acceder a la tabla (para más detalles, ver Apéndice \ref{drivers}, página \pageref{drivers}); + +\noindent +{\it arg} es una expresión simbólica opcional que es un argumento pasado al controlador de la tabla. Esta expresión simbólica no debe incluir índices especificados en el dominio; + +\noindent +{\it conjunto} es el nombre de un conjunto simple opcional llamado {\it conjunto de control}. Puede ser omitido junto con el delimitador {\tt<-}; + +\noindent +{\it cmp} es un nombre de campo. Entre corchetes se debe especificar al menos un campo. El nombre de campo a continuación de un nombre de parámetro o de una expresión es opcional y puede ser omitido junto con el delimitador~{\tt\textasciitilde}, en cuyo caso el nombre del objeto del modelo que corresponda se usará como el nombre de campo; + +\noindent +{\it par} es el nombre simbólico de un parámetro del modelo; + +\noindent +{\it expr} es una expresión numérica o simbólica. + +\para{Ejemplos} + +\begin{verbatim} +table datos IN "CSV" "datos.csv": M <- [DESDE,HACIA], d~DISTANCIA, + c~COSTO; +table resultado{(s,h) in M} OUT "CSV" "resultado.csv": s~DESDE, h~HACIA, + x[s,h]~FLUJO; +\end{verbatim} + +La sentencia table permite leer datos desde una tabla y asignarlos a objetos del modelo tales como conjuntos y parámetros (no escalares), al igual que escribir datos del modelo en una tabla. + +\subsection{Estructura de tablas} + +Una {\it tabla de datos} es un conjunto (desordenado) de {\it registros}, en el que cada registro consiste del mismo número de {\it campos}, y cada campo está provisto de un nombre simbólico único denominado {\it nombre de campo}. Por ejemplo: + +\bigskip + +\begin{tabular}{@{\hspace*{51mm}}c@{\hspace*{9mm}}c@{\hspace*{10mm}}c +@{\hspace*{7mm}}c} +Primer&Segundo&&Último\\ +campo&campo&.\ \ .\ \ .&campo\\ +$\downarrow$&$\downarrow$&&$\downarrow$\\ +\end{tabular} + +\begin{tabular}{ll@{}} +Encabezado de tabla&$\rightarrow$\\ +Primer registro&$\rightarrow$\\ +Segundo registro&$\rightarrow$\\ +\\ +\hfil .\ \ .\ \ .\\ +\\ +Último registro&$\rightarrow$\\ +\end{tabular} +\begin{tabular}{|l|l|c|c|} +\hline +{\tt DESDE}&{\tt HACIA}&{\tt DISTANCIA}&{\tt COSTO}\\ +\hline +{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +\hline +\end{tabular} + +\subsection{Lectura de datos desde una tabla de entrada} + +La sentencia table de entrada produce la lectura de los datos desde la tabla especificada, registro por registro. + +Una vez que se ha leído el próximo registro, los valores numéricos o simbólicos de los campos cuyos nombres se han encerrado entre corchetes en la sentencia table se reúnen en un $n$-tuplo y, si se ha especificado el conjunto de control en la sentencia table, este $n$-tuplo es agregado al mismo. Además, un valor numérico o simbólico de cada campo asociado con un parámetro del modelo se asigna al miembro del parámetro identificado por subíndices, los cuales son componentes del $n$-tuplo que se acaba de leer. + +Por ejemplo, la siguiente sentencia table de entrada: + +\noindent\hfil +\verb|table datos IN "...": M <- [DESDE,HACIA], d~DISTANCIA, c~COSTO;| + +\noindent +produce la lectura de valores de cuatro campos llamados {\tt DESDE}, {\tt HACIA}, {\tt DISTANCIA} y {\tt COSTO} de cada registro de la tabla especificada. Los valores de los campos {\tt DESDE} y {\tt HACIA} proveen un par $(s,h)$ que se agrega al conjunto de control {\tt M}. El valor del campo {\tt DISTANCIA} se asigna al miembro del parámetro ${\tt d}[s,h]$ y el valor del campo {\tt COSTO} se asigna al miembro del parámetro ${\tt c}[s,h]$. + +Debe notarse que la tabla de entrada puede contener campos adicionales cuyos nombres no sean especificados en la sentencia table, en cuyo caso los valores de estos campos serán ignorados al leer la tabla. + +\subsection{Escritura de datos en una tabla de salida} + +La sentencia table de salida produce la escritura de datos en la tabla especificada. Debe notarse que algunos controladores (concretamente CSV y xBASE) destruyen la tabla de salida antes de escribir los datos, {\it i.e.} borran todos sus registros existentes. + +Cada $n$-tuplo en el conjunto dominio especificado genera un registro escrito en la tabla de salida. Los valores de los campos son valores numéricos o simbólicos de las correspondientes expresiones especificadas en la sentencia table. Estas expresiones se evalúan para cada $n$-tuplo en el conjunto dominio y, de este modo, puede incluir índices que se introdujeron en la correspondiente expresión indizante. + +Por ejemplo, la siguiente sentencia table de salida: + +\noindent\hfil +\verb|table resultado{(s,h) in M} OUT "...": s~DESDE, h~HACIA, x[s,h]~FLUJO;| + +\noindent +produce la escritura de registros en la tabla de salida, a razón de un registro por cada par $(s,h)$ en el conjunto {\tt M}, en el que cada registro consiste de tres campos llamados {\tt DESDE}, {\tt HACIA} y {\tt FLUJO}. Los valores escritos en los campos {\tt DESDE} y {\tt HACIA} son los valores corrientes de los índices {\tt s} y {\tt h}, y el valor escrito en el campo {\tt FLUJO} es un valor del miembro ${\tt x}[s,h]$ del correspondiente parámetro o variable indexada. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Datos del modelo} + +Los {\it datos del modelo} incluyen conjuntos elementales, los cuales son ``valores'' de los conjuntos del modelo, y valores simbólicos y numéricos de los parámetros del modelo. + +En MathProg hay dos maneras diferentes de proveer valores para los conjuntos y parámetros del modelo. Una manera es simplemente proveyendo los datos necesarios mediante el atributo de asignación. Sin embargo, en muchos casos es más práctico separar el modelo en sí mismo de los datos particulares necesarios para el modelo. Por esta última razón, en MathProg hay otra manera que consiste en separar la descripción del modelo en dos partes: la sección del modelo y la sección de los datos. + +La {\it sección del modelo} es la parte principal de la descripción del modelo que contiene las declaraciones de todos los objetos del modelo y es común a todos los problemas basados en tal modelo. + +La {\it sección de los datos} es una parte opcional de la descripción del modelo que contiene datos específicos para un problema particular. + +En MathProg las secciones del modelo y de los datos se pueden ubicar tanto en un único archivo de texto, como en dos archivos de texto separados. + +1. Si ambas secciones se ubican en un archivo, este debe componerse como sigue: + +\bigskip + +\noindent\hfil +\framebox{\begin{tabular}{l} +{\it sentencia}{\tt;}\\ +{\it sentencia}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentencia}{\tt;}\\ +{\tt data;}\\ +{\it bloque de datos}{\tt;}\\ +{\it bloque de datos}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloque de datos}{\tt;}\\ +{\tt end;} +\end{tabular}} + +\newpage + +2. Si ambas secciones se ubican en dos archivos separados, los archivos se componen como sigue: + +\bigskip + +\noindent\hfil +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\it sentencia}{\tt;}\\ +{\it sentencia}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentencia}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\\\Archivo del modelo\\ +\end{tabular} +\hspace{32pt} +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\tt data;}\\ +{\it bloque de datos}{\tt;}\\ +{\it bloque de datos}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloque de datos}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\Archivo de datos\\ +\end{tabular} + +\bigskip + +Nota: si la sección de datos se ubica en un archivo separado, la palabra clave {\tt data} es opcional y puede omitirse, al igual que el punto y coma que le sigue. + +\section{Codificación de la sección de los datos} + +La {\it sección de los datos} es una secuencia de bloques de datos en varios formatos que se discuten en las siguientes secciones. El orden que siguen los bloques de datos en la sección de los datos puede ser arbitrario, no necesariamente el mismo que se siguió en la sección del modelo para sus correspondientes objetos. + +Las reglas para codificar la sección de los datos comúnmente son las mismas reglas que para codificar la descripción del modelo (ver Sección \ref{coding}, página \pageref{coding}), {\it i.e.} los bloques de datos se componen con unidades léxicas básicas como nombres simbólicos, literales numéricos y de cadena, palabras clave, delimitadores y comentarios. Sin embargo, por conveniencia y para mejorar la legibilidad hay una desviación de la regla común: si un literal de cadena consiste únicamente de caracteres alfanuméricos (incluyendo el carácter de subrayado), los signos {\tt+} y {\tt-} y/o el punto decimal, el mismo puede codificarse sin comillas delimitadoras (simples o dobles). + +Todo el material numérico y simbólico provisto en la sección de los datos se codifica en la forma de números y símbolos, {\it i.e.} a diferencia de la sección del modelo, en la sección de los datos no se permiten expresiones. Sin embargo, los signos {\tt+} y {\tt-} pueden preceder a literales numéricos para permitir la codificación de cantidades numéricas con signo, en cuyo caso no debe haber caracteres de espacio en blanco entre el signo y el literal numérico que le sigue (si hay al menos un espacio en blanco, el signo y el literal numérico que le sigue serán reconocidos como dos unidades léxicas diferentes). + +\newpage + +\section{Bloque de datos de conjunto} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nombre} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt set} {\it nombre} {\tt[} {\it símbolo} {\tt,} \dots +{\tt,} {\it símbolo} {\tt]} {\tt,} {\it registro} {\tt,} \dots {\tt,} +{\it registro} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del conjunto; + +\noindent +{\it símbolo}, \dots, {\it símbolo} son subíndices que especifican un miembro particular del conjunto (si el conjunto es un arreglo, {\it i.e.} un conjunto de conjuntos); + +\noindent +{\it registro}, \dots, {\it registro} son registros. + +\noindent +Las comas que preceden a los registros pueden omitirse. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +es un elemento de asignación de registro no-significativo que puede ser usado libremente para mejorar la legibilidad; +\item[{\tt(} {\it porción} {\tt)}]\hspace*{0pt}\\ +especifica una porción; +\item[{\it datos-simples}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato simple; +\item[{\tt:} {\it datos-matriciales}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato matricial; +\item[{\tt(tr)} {\tt:} {\it datos-matriciales}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato matricial traspuesto (en este caso, los dos puntos que siguen a la palabra clave {\tt(tr)} pueden omitirse). +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +set mes := Ene Feb Mar Abr May Jun; +set mes "Ene", "Feb", "Mar", "Abr", "May", "Jun"; +set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; +set A[3,'Mar'] : 1 2 3 4 := + 1 - + - - + 2 - + + - + 3 + - - + + 4 - + - + ; +set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +set B := (1,*,*) : 1 2 3 := + 1 + - - + 2 - + + + 3 - + - + (2,*,*) : 1 2 3 := + 1 + - + + 2 - - - + 3 + - - ; +\end{verbatim} + +\noindent(En estos ejemplos, {\tt mes} es un conjunto simple de singletones, {\tt A} es un arreglo 2-dimensional de duplos y {\tt B} es un conjunto simple de triplos. Los bloques de datos para el mismo conjunto son equivalentes en el sentido de que especifican los mismos datos en formatos distintos. + +El {\it bloque de datos del conjunto} se usa para especificar un conjunto elemental completo, el que se asigna a un conjunto (si es un conjunto simple) o a uno de sus miembros (si el conjunto es un arreglo de conjuntos).\footnote{Hay otra forma de especificar datos para un conjunto simple junto con los datos para los parámetros. Esta característica se discute en la próxima sección.} + +Los bloques de datos sólo pueden ser especificados para conjuntos no-calculables, {\it i.e.} para conjuntos que no tienen el atributo de asignación ({\tt:=}) en la correspondiente sentencia set. + +Si el conjunto es un conjunto simple, sólo se debe especificar su nombre simbólico en el encabezado del bloque de datos. De otro modo, si el conjunto es un arreglo $n$-dimensional, su nombre simbólico debe proveerse con una lista completa de subíndices separados por coma y encerrados entre corchetes para especificar un miembro particular del arreglo de conjuntos. El número de subíndices debe ser igual a la dimensión del arreglo de conjuntos, en el que cada subíndice deben ser un número o símbolo. + +Un conjunto elemental definido en el bloque de datos del conjunto se codifica como una secuencia de registros según se describe luego.\footnote{{Registro} es simplemente un término técnico. No significa que los mismos presenten algún formateo especial.} + +\subsection{Asignación de registro} + +La {\it asignación de registro} ({\tt:=}) es un elemento no-significativo. Se puede usar para mejorar la legibilidad de los bloques de datos. + +\subsection{Registro en porción} + +El {\it registro en porción} es un registro de control que especifica una {\it porción} del conjunto elemental definido en el bloque de datos. Tiene la siguiente forma sintáctica: +$$\mbox{{\tt(} $p_1$ {\tt,} $p_2$ {\tt,} \dots {\tt,} $p_n$ {\tt)}}$$ +donde $p_1$, $p_2$, \dots, $p_n$ son componentes de la porción. + +Cada componente de la porción puede ser un número o un símbolo o el asterisco ({\tt*}). El número de componentes de la porción debe coincidir con la dimensión de los $n$-tuplos del conjunto elemental que se define. Por ejemplo, si el conjunto elemental contiene 4-tuplos (cuádruplos), la porción debe tener cuatro componentes. El número de asteriscos en la porción se denomina la {\it dimensión de la porción}. + +El efecto de usar las porciones es como sigue: si se especifica una porción $m$-dimensional ({\it i.e.} una porción que tiene $m$ asteriscos) en el bloque de datos, todos los registros subsecuentes deben especificar tuplos de dimensión $m$. Cuando se encuentra un $m$-tuplo, cada asterisco en la porción se reemplaza por los correspondientes componentes del $m$-tuplo para dar el $n$-tuplo resultante, el que es incluido en el conjunto elemental que se define. Por ejemplo, si está vigente la porción $(a,*,1,2,*)$ y se encuentra el duplo $(3,b)$ en el registro subsecuente, el 5-tuplo resultante que se incluye en el conjunto elemental es $(a,3,1,2,b)$. + +Las porciones que no tienen asteriscos en si mismas, definen un $n$-tuplo completo que se incluye en el conjunto elemental. + +Una vez especificada una porción, la misma está vigente hasta que aparezca una nueva porción o bien hasta que se encuentra el final del bloque de datos. Debe notarse que si no se especifica una porción en el bloque de datos, se asume una cuyos componentes son asteriscos en todas las posiciones. + +\subsection{Registro simple} + +El {\it registro simple} define un $n$-tuplo en formato simple y tiene la siguiente forma sintáctica: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +donde $t_1$, $t_2$, \dots, $t_n$ son componentes del $n$-tuplo. Cada componente puede ser un número o símbolo. Las comas entre componentes son opcionales y pueden omitirse. + +\subsection{Registro matricial} + +El {\it registro matricial} define varios 2-tuplos (duplos) en formato matricial y tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +donde $f_1$, $f_2$, \dots, $f_m$ son números y/o símbolos que corresponden a filas de la matriz; $c_1$, $c_2$, \dots, $c_n$ son números y/o símbolos que corresponden a columnas de la matriz, mientras que $a_{11}$, $a_{12}$, \dots, $a_{mn}$ son los elementos de la matriz, los cuales pueden ser tanto {\tt+} como {\tt-}. (En este registro, el delimitador {\tt:} que precede a la lista de columnas y el delimitador {\tt:=} a continuación de la lista de columnas, no pueden ser omitidos.) + +Cada elemento $a_{ij}$ del bloque de datos matricial (donde $1\leq i\leq m$, +$1\leq j\leq n$) corresponde a 2-tuplos $(f_i,c_j)$. Si en $a_{ij}$ se indica el signo más ({\tt+}), el correspondiente 2-tuplo (o un $n$-tuplo más largo si se usa una porción) se incluye en el conjunto elemental. De otro modo, si en $a_{ij}$ se indica el signo menos ({\tt-}) el 2-tuplo no se incluye en el conjunto elemental. + +Puesto que el registro matricial define 2-tuplos, ya sea el conjunto elemental o bien la porción vigente en uso deben ser 2-dimensionales. + +\subsection{Registro matricial traspuesto} + +El {\it registro matricial traspuesto} tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(En este caso el delimitador {\tt:} a continuación de la palabra clave {\tt (tr)} es opcional y puede omitirse.) + +Este registro es completamente análogo al registro matricial (ver anteriormente) con la única excepción, en este caso, de que cada elemento $a_{ij}$ de la matriz corresponde al 2-tuplo $(c_j,f_i)$ en vez de a $(f_i,c_j)$. + +Una vez especificado, el indicador {\tt(tr)} tiene alcance en todos los registros subsecuentes hasta que se encuentra otra porción o bien el fin del bloque de datos. + +\section{Bloque de datos de parámetro} + +\noindent +\framebox[468pt][l]{ +\parbox[c][88pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nombre} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\it nombre} {\tt default} {\it valor} {\tt,} +{\it registro} {\tt,} \dots {\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt:} {\it datos-tabulación} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt default} {\it valor} {\tt:} +{\it datos-tabulación} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del parámetro; + +\noindent +{\it valor} es un valor por defecto opcional del parámetro; + +\noindent +{\it registro}, \dots, {\it registro} son registros. + +\noindent +{\it datos-tabulación} especifica los datos del parámetro en el formato tabulación. + +\noindent +Las comas que preceden a los registros pueden omitirse. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +es un elemento de asignación de registro no-significativo que puede ser usado libremente para mejorar la legibilidad; +\item[{\tt[} {\it porción} {\tt]}]\hspace*{0pt}\\ +especifica una porción; +\item[{\it datos-planos}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato plano; +\item[{\tt:} {\it datos-tabulares}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato tabular; +\item[{\tt(tr)} {\tt:} {\it datos-tabulares}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato matricial traspuesto (en este caso, los dos puntos que siguen a la palabra clave {\tt(tr)} pueden omitirse). +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +param T := 4; +param mes := 1 Ene 2 Feb 3 Mar 4 Abr 5 May; +param mes := [1] 'Ene', [2] 'Feb', [3] 'Mar', [4] 'Abr', [5] 'May'; +param stock_inicial := hierro 7.32 niquel 35.8; +param stock_inicial [*] hierro 7.32, niquel 35.8; +param costo [hierro] .025 [niquel] .03; +param valor := hierro -.1, niquel .02; +param : stock_inicial costo valor := + hierro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param : insumo : stock_inicial costo valor := + hierro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param demanda default 0 (tr) + : FRA DET LAN WIN STL FRE LAF := + laminas 300 . 100 75 . 225 250 + rollos 500 750 400 250 . 850 500 + cintas 100 . . 50 200 . 250 ; +param costo_transporte := + [*,*,laminas]: FRA DET LAN WIN STL FRE LAF := + GARY 30 10 8 10 11 71 6 + CLEV 22 7 10 7 21 82 13 + PITT 19 11 12 10 25 83 15 + [*,*,rollos]: FRA DET LAN WIN STL FRE LAF := + GARY 39 14 11 14 16 82 8 + CLEV 27 9 12 9 26 95 17 + PITT 24 14 17 13 28 99 20 + [*,*,cintas]: FRA DET LAN WIN STL FRE LAF := + GARY 41 15 12 16 17 86 8 + CLEV 29 9 13 9 28 99 18 + PITT 26 14 17 13 31 104 20 ; +\end{verbatim} + +El {\it bloque de datos del parámetro} se usa para especificar datos completos a un parámetro (o a varios parámetros si los datos se especifican en el formato tabulaciones) + +Los bloques de datos sólo pueden ser especificados para parámetros no-calculables, {\it i.e.} para parámetros que no tienen el atributo de asignación({\tt:=}) en la correspondiente sentencia parameter. + +Los datos definidos en el bloque de datos del parámetro se codifican como una secuencia de registros descriptos luego. Adicionalmente, el bloque de datos puede ser provisto con el atributo opcional {\tt default}, el cual especifica un valor numérico o simbólico por defecto para el parámetro (parámetros). Este valor por defecto se asigna al parámetro, o a sus miembros, cuando no se definen valores apropiados en el bloque de datos del parámetro. El atributo {\tt default} no se puede usar si ya se ha especificado en la correspondiente sentencia parameter. + +\subsection{Asignación de registro} + +La {\it asignación de registro} ({\tt:=}) es un elemento no-significativo. Se puede usar para mejorar la legibilidad de los bloques de datos. + +\subsection{Registro en porción} + +El {\it registro en porción} es un registro de control que especifica una {\it porción} del arreglo de parámetros. Tiene la siguiente forma sintáctica: +$$\mbox{{\tt[} $p_1$ {\tt,} $p_2$ {\tt,} \dots {\tt,} $p_n$ {\tt]}}$$ +donde $p_1$, $p_2$, \dots, $p_n$ son componentes de la porción. + +Cada componente de la porción puede ser un número o un símbolo o el asterisco ({\tt*}). El número de componentes de la porción debe coincidir con la dimensión del parámetro. Por ejemplo, si el parámetro es un arreglo 4-dimensional, la porción debe tener cuatro componentes. El número de asteriscos en la porción se denomina la {\it dimensión de la porción}. + +El efecto de usar las porciones es como sigue: si se especifica una porción $m$-dimensional ({\it i.e.} una porción que tiene $m$ asteriscos) en el bloque de datos, todos los registros subsecuentes deben especificar los subíndices de los miembros del parámetro como si el parámetro fuese $m$-dimensional y no $n$-dimensional. + +Cuando se encuentran los $m$ subíndices, cada asterisco en la porción se reemplaza por el correspondiente subíndice para dar los $n$ subíndices, los cuales definen al miembro corriente del parámetro. Por ejemplo, si está vigente la porción $(a,*,1,2,*)$ y se encuentran los subíndices 3 y $b$ en el registro subsecuente, la lista completa de subíndices que se usa para elegir un miembro del parámetro es $(a,3,1,2,b)$. + +Se permite especificar una porción que no tenga asteriscos. Tal porción, en sí misma define una lista completa de subíndices, en cuyo caso el próximo registro debe definir solamente un valor individual del correspondiente miembro del parámetro. + +Una vez especificada una porción, la misma está vigente hasta que aparezca una nueva porción o bien hasta que se encuentra el final del bloque de datos. Debe notarse que si no se especifica una porción en el bloque de datos, se asume una cuyos componentes son todos asteriscos. + +\subsection{Registro plano} + +El {\it registro plano} define la lista de subíndices y un valor individual en el formato plano. Este registro tiene la siguiente forma sintáctica: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +donde $t_1$, $t_2$, \dots, $t_n$ son subíndices y $v$ es un valor. Cada subíndice, al igual que el valor, puede ser un número o un símbolo. Las comas que siguen a los subíndices son opcionales y pueden omitirse. + +En el caso de parámetros o porciones 0-dimensionales, el registro plano no tiene subíndice y consiste solamente de un valor individual. + +\subsection{Registro tabular} + +El {\it registro tabular} define varios valores, cada uno de los cuales viene provisto con dos subíndices. Este registro tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +donde los $f_1$, $f_2$, \dots, $f_m$ son números y/o símbolos que corresponden a filas de la tabla; $c_1$, $c_2$, \dots, $c_n$ son números y/o símbolos que corresponden a columnas de la tabla; mientras que $a_{11}$, $a_{12}$, \dots, $a_{mn}$ son elementos de la tabla. Cada elemento puede ser un número o símbolo o el punto decimal ({\tt.}) solo (en este registro, el delimitador {\tt:} que precede a la lista de columnas y el delimitador {\tt:=} a continuación de la lista de columnas, no pueden ser omitidos.). + +Cada elemento $a_{ij}$ del bloque de datos tabulares ($1\leq i\leq m$, +$1\leq j\leq n$) define dos subíndices, siendo el primero $f_i$ y el segundo $c_j$. Estos subíndices se usan junto con la porción vigente para formar la lista completa de subíndices que identifica a un miembro particular del arreglo de parámetros. Si $a_{ij}$ es un número o símbolo, tal valor se asigna al miembro del parámetro. Sin embargo, si $a_{ij}$ es un punto decimal solo, el miembro recibe el valor por defecto especificado ya sea en el bloque de datos del parámetro o en la sentencia parameter, o si no hay un valor por defecto especificado, el miembro permanece indefinido. + +Puesto que el registro tabular provee dos subíndices para cada valor, ya sea el parámetro o bien la porción vigente en uso deben ser 2-dimensionales. + +\subsection{Registro tabular traspuesto} + +El {\it registro tabular traspuesto} tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(En este caso el delimitador {\tt:} a continuación de la palabra clave {\tt (tr)} es opcional y puede omitirse.) + +Este registro es completamente análogo al registro tabular (ver anteriormente), con la única excepción de que el primer subíndice definido por el elemento $a_{ij}$ es $c_j$ mientras que el segundo es $f_i$. + +Una vez especificado, el indicador {\tt(tr)} tiene alcance en todos los registros subsecuentes hasta que se encuentre otra porción o bien el fin del bloque de datos. + +\subsection{Formato de datos tabulación} + +El bloque de datos del parámetro en el {\it formato tabulación} tiene la siguiente forma sintáctica: +$$ +\begin{array}{*{8}{l}} +\multicolumn{4}{l} +{{\tt param}\ {\tt default}\ valor\ {\tt :}\ c\ {\tt :}}& +p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_f\ \ \verb|:=|\\ +f_{11}\ \verb|,|& f_{12}\ \verb|,|& \dots\ \verb|,|& f_{1n}\ \verb|,|& +a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1f}\ \verb|,|\\ +f_{21}\ \verb|,|& f_{22}\ \verb|,|& \dots\ \verb|,|& f_{2n}\ \verb|,|& +a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2f}\ \verb|,|\\ +\dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +f_{m1}\ \verb|,|& f_{m2}\ \verb|,|& \dots\ \verb|,|& f_{mn}\ \verb|,|& +a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mf}\ \verb|;|\\ +\end{array} +$$ + +1. La palabra clave {\tt default} puede omitirse junto con el valor que le sigue. + +2. El nombre simbólico $c$ puede omitirse junto con los dos puntos que le siguen. + +3. Todas las comas son opcionales y pueden omitirse. + +El bloque de datos en el formato tabulación mostrado arriba es exactamente equivalente a los siguientes bloques de datos: + +\verb|set| $c$\ \verb|:=|\ $ +\verb|(|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|) | +\verb|(|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|) | +\dots +\verb| (|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|);|$ + +\verb|param| $p_1$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{11} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{21} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{m1} +\verb|;| +$ + +\verb|param| $p_2$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{12} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{22} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{m2} +\verb|;| +$ + +\verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . + +\verb|param| $p_f$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{1f} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{2f} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{mf} +\verb|;| +$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\chapter{Uso de sufijos} + +\vspace*{-12pt} + +Se pueden usar sufijos para recuperar valores adicionales relacionados con las variables, restricciones y objetivos del modelo. + +Un {\it sufijo} consiste de un punto ({\tt.}) seguido de una palabra clave no-reservada. Por ejemplo, si {\tt x} es una variable bidimensional, {\tt x[i,j].lb} es un valor numérico igual a la cota inferior de la variable elemental {\tt x[i,j]} que se puede usar como un parámetro numérico dondequiera que sea en expresiones. + +Para las variables del modelo, los sufijos tienen los siguientes significados: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&cota inferior\\ +{\tt.ub}&cota superior\\ +{\tt.status}&estatus en la solución:\\ +&0 --- indefinida\\ +&1 --- básica\\ +&2 --- no-básica en la cota inferior\\ +&3 --- no-básica en la cota superior\\ +&4 --- variable no-básica libre (no acotada)\\ +&5 --- variable no-básica fija\\ +{\tt.val}&valor primal en la solución\\ +{\tt.dual}&valor dual (costo reducido) en la solución\\ +\end{tabular} + +Para las restricciones y objetivos del modelo, los sufijos tienen los siguientes significados: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&cota inferior de la forma lineal\\ +{\tt.ub}&cota superior de la forma lineal\\ +{\tt.status}&estatus en la solución:\\ +&0 --- indefinida\\ +&1 --- no-limitante\\ +&2 --- limitante en la cota inferior\\ +&3 --- limitante en la cota superior\\ +&4 --- fila limitante libre (no-acotada)\\ +&5 --- restricción de igualdad limitante\\ +{\tt.val}&valor primal de la forma lineal en la solución\\ +{\tt.dual}&valor dual (costo reducido) de la forma lineal en la solución\\ +\end{tabular} + +Debe notarse que los sufijos {\tt.status}, {\tt.val} y {\tt.dual} solamente pueden usarse luego de la sentencia solve. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Funciones de fecha y hora} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +y Heinrich Schuchardt \verb||\\ +\end{tabular} + +\section{Obtención del tiempo calendario corriente} +\label{gmtime} + +Para obtener el tiempo calendario\footnote{N. del T.: el tiempo calendario es un punto en el {\it continuum} del tiempo, por ejemplo 4 de noviembre de 1990 a las 18:02.5 UTC. A veces se lo llama ``tiempo absoluto''. La definición está tomada de {\it Sandra Loosemore}, {\it Richard M. Stallman}, {\it Roland McGrath}, {\it Andrew Oram} \& {\it Ulrich Drepper}, ``The GNU C Library Reference Manual - for version 2.17'', Free Software Foundation, Inc, 2012.} corriente en MathProg existe la función {\tt gmtime}. No tiene argumentos y devuelve el número de segundos transcurridos desde las 00:00:00 del 1 de enero de 1970, Tiempo Universal Coordinado (UTC). Por ejemplo: + +\begin{verbatim} + param utc := gmtime(); +\end{verbatim} + +MathPro no tiene una función para convertir el tiempo UTC devuelto por la función {\tt gmtime} a tiempo calendario {\it local}. Entonces, si se necesita determinar el tiempo calendario local corriente, se debe agregar al tiempo UTC devuelto la diferencia horaria con respecto al UTC expresada en segundos. Por ejemplo, la hora en Berlín durante el invierno está una hora adelante del UTC, lo que corresponde una diferencia horaria de +1~hora~= +3600~segundos, de modo que el tiempo calendario corriente del invierno en Berlín se puede determinar como sigue: + +\begin{verbatim} + param ahora := gmtime() + 3600; +\end{verbatim} + +\noindent Análogamente, el horario de verano en Chicago (Zona Horaria Central) está cinco horas por detrás del UTC, de modo que el correspondiente tiempo calendario local corriente se puede determinar como sigue: + +\begin{verbatim} + param ahora := gmtime() - 5 * 3600; +\end{verbatim} + +Debe notarse que el valor devuelto por {\tt gmtime} es volátil, {\it i.e.} si se la invoca varias veces, esta función devolverá valores diferentes. + +\section{Conversión de una cadena de caracteres a un tiempo calendario} +\label{str2time} + +La función {\tt str2time(}{\it c}{\tt,} {\it f}{\tt)} convierte una cadena de caracteres (una {\it estampa de la fecha y hora}) especificada por su primer argumento {\it c}, la que debe ser una expresión simbólica, a un tiempo calendario apropiado para cálculos aritméticos. La conversión se controla mediante la especificación de una cadena de formato {\it f} (el segundo argumento), la que también debe ser una expresión simbólica. + +El resultado de la conversión devuelto por {\tt str2time} tiene el mismo significado que los valores devueltos por la función {\tt gmtime} (ver Subsección \ref{gmtime}, página \pageref{gmtime}). Debe notarse que {\tt str2time} {\it no corrige} el tiempo calendario devuelto para considerar la zona horaria local, {\it i.e.} si se aplica a las 00:00:00 del 1 de enero de 1970, siempre devolverá 0. + +Por ejemplo, las sentencias del modelo + +\begin{verbatim} + param c, symbolic, := "07/14/98 13:47"; + param t := str2time(c, "%m/%d/%y %H:%M"); + display t; +\end{verbatim} + +\noindent imprime lo siguiente en la salida estándar: + +\begin{verbatim} + t = 900424020 +\end{verbatim} + +\noindent donde el tiempo calendario mostrado corresponde a las 13:47:00 del 14 de julio de 1998. + +La cadena de formato que se pasa a la función {\tt str2time} consiste de especificadores de conversión y caracteres ordinarios. Cada especificador de conversión empieza con un carácter de porcentaje ({\tt\%}) seguido por una letra. + +Los siguientes especificadores de conversión se pueden usar en la cadena de formato\footnote{N. del T.: en todas las funciones de fecha y hora, nombre del mes y del día de la semana refiere a su denominación en inglés, {\it e.g.}: {\tt August}, {\tt Aug}, {\tt Wednesday}, {\tt We}.}: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&El nombre del mes abreviado (insensible a mayúsculas). Al menos las tres primeras letras del nombre del mes deben aparecer en la cadena de entrada.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&El día del mes como un número decimal (rango de 1 a 31). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&Lo mismo que {\tt\%b}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&La hora como un número decimal, empleando un reloj de 24 horas (rango de 0 a 23). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&El mes como un número decimal (rango de 1 a 12). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&El minuto como número decimal (rango de 0 a 59). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&El segundo como un número decimal (rango de 0 a 59). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&El año sin un siglo como un número decimal (rango de 0 a 99). Se permite el cero como primer dígito, aunque no es requerido. Los valores de entrada en el rango de 0 a 68 se consideran como los años 2000 al 2068, mientras que los valores del 69 al 99 como los años 1969 a 1999.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%z}&La diferencia horaria con respecto a GMT en formato ISO 8601.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&Un carácter {\tt\%} literal.\\ +\end{tabular} + +Todos los demás caracteres (ordinarios) en la cadena de formato deben tener un carácter de coincidencia con la cadena de entrada a ser convertida. Las excepciones son los espacios en la cadena de entrada, la cual puede coincidir con cero o más caracteres de espacio en la cadena de formato. + +Si algún componente de la fecha y/u hora están ausentes en el formato y, consecuentemente, en la cadena de entrada, la función {\tt str2time} usa sus valores por defecto de las 00:00:00 del 1 de enero de 1970, es decir que el valor por defecto para el año es 1970, el valor por defecto para el mes es enero, etc. + +La función {} es aplicable a todos los tiempos calendarios en el rango desde las 00:00:00 del 1 de enero del 0001 hasta las 23:59:59 del 31 de diciembre del 4000 del calendario gregoriano. + +\section{Conversión de un tiempo calendario a una cadena de caracteres} +\label{time2str} + +La función {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} convierte el tiempo calendario especificado por su primer argumento {\it t}, el que debe ser una expresión numérica, a una cadena de caracteres (valor simbólico). La conversión se controla con la cadena de formato {\it f} especificada (el segundo argumento), la que debe ser una expresión simbólica. + +El tiempo calendario que se le pasa a {\tt time2str} tiene el mismo significado que el valor devuelto por la función {\tt gmtime} (ver Subsección \ref{gmtime}, página \pageref{gmtime}). Debe notarse que {\tt time2str} {\it no corrige} el tiempo calendario especificado para considerar la zona horaria local, {\it i.e.} el tiempo calendario 0 siempre corresponde a las 00:00:00 del 1 de enero de 1970. + +Por ejemplo, las sentencias del modelo + +\begin{verbatim} + param c, symbolic, := time2str(gmtime(), "%FT%TZ"); + display c; +\end{verbatim} + +\noindent puede producir la siguiente impresión: + +\begin{verbatim} + c = '2008-12-04T00:23:45Z' +\end{verbatim} + +\noindent que es una estampa de una fecha y hora en el formato ISO. + +La cadena de formato que se pasa a la función {\tt time2str} consiste de especificadores de conversión y caracteres ordinarios. Cada especificador de conversión empieza con un carácter de porcentaje ({\tt\%}) seguido por una letra. + +Los siguientes especificadores de conversión se pueden usar en la cadena de formato: + +\newpage + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%a}&El nombre del día de la semana abreviado (2 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%A}&El nombre del día de la semana completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&El nombre del mes abreviado (3 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%B}&El nombre del mes completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%C}&El siglo del año, es decir el mayor entero no mayor que el año dividido por~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&El día del mes como un número decimal (rango de 01 a 31).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%D}&La fecha, usando el formato \verb|%m/%d/%y|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%e}&El día del mes, como con \verb|%d|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%F}&La fecha, usando el formato \verb|%Y-%m-%d|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%g}&El año correspondiente al número de semana ISO, pero sin el siglo (rango de 00 a 99). Tiene el mismo formato y valor que \verb|%y|, excepto que si el número de semana ISO (ver \verb|%V|) pertenece al año previo o siguiente, se usa aquel año en su lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%G}&El año correspondiente al número de semana ISO. Tiene el mismo formato y valor que \verb|%Y|, excepto que si el número de semana ISO (ver \verb|%V|) pertenece al año previo o siguiente, se usa aquel año en su lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&Lo mismo que \verb|%b|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&La hora como un número decimal, empleando un reloj de 24 horas (rango de 00 a 23).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%I}&La hora como un número decimal, empleando un reloj de 12 horas (rango de 01 a 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%j}&El día del año como un número decimal (rango de 001 a 366).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%k}&La hora como un número decimal, empleando un reloj de 24 horas como con \verb|%H|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%l}&La hora como un número decimal, empleando un reloj de 12 horas como con \verb|%I|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&El mes como un número decimal (rango de 01 a 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&El minuto como un número decimal (rango de 00 a 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%p}&Tanto {\tt AM} como {\tt PM}, de acuerdo con el valor horario dado. La medianoche es tratada como {\tt AM} y el mediodía como {\tt PM}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%P}&Tanto {\tt am} como {\tt pm}, de acuerdo con el valor horario dado. La medianoche es tratada como {\tt am} y el mediodía como {\tt pm}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%R}&La hora y los minutos en números decimales, usando el formato \verb|%H:%M|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&Los segundos como un número decimal (rango de 00 a 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%T}&La hora del día en números decimales, usando el formato \verb|%H:%M:%S|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%u}&El día de la semana como un número decimal (rango de 1 a 7), siendo 1 el lunes.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%U}&El número de semana del año corriente como un número decimal (rango de 00 a 53), empezando con el primer domingo como el primer día de la primer semana. Se considera que los días del año anteriores al primer domingo son parte de la semana 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%V}&El número de semana ISO como un número decimal (rango 01 a 53). Las semanas de ISO empiezan los lunes y terminan los domingos. La semana 01 de un año es la primer semana que tiene la mayoría de sus días en ese año, lo cual es equivalente a la semana que contiene al 4 de enero. La semana 01 de un año puede contener días del año previo. La semana anterior a la semana 01 de un año es la última semana (52 o 53) del año previo, aún si esta contiene días del nuevo año. En otras palabras, si el 1 de enero cae en lunes, martes, miércoles o jueves, está en la semana 01; si el 1 de enero cae en viernes, sábado o domingo, está en la semana 52 o 53 del año previo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%w}&El día de la semana como un número decimal (rango de 0 a 6), siendo 0 el domingo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%W}&El número de semana del año corriente como un número decimal (rango de 00 a 53), empezando con el primer lunes como el primer día de la primer semana. Se considera que los días del año anteriores al primer lunes son parte de la semana 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&El año sin el siglo como un número decimal (rango de 00 a 99), es decir año {\tt mod} 100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%Y}&El año como un número decimal, usando el calendario gregoriano.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}& Un carácter \verb|%| literal.\\ +\end{tabular} + +Todos los demás caracteres (ordinarios) en la cadena de formato simplemente se copian a la cadena resultante. + +El primer argumento (tiempo calendario) que se le pasa a la función {\tt time2str} debe están en el rango entre $-62135596800$ y $+64092211199$, lo que corresponde al período desde las 00:00:00 del 1 de enero del 0001 hasta las 23:59:59 del 31 de diciembre del 4000 del calendario gregoriano. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Controladores de tablas} +\label{drivers} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +y Heinrich Schuchardt \verb||\\ +\end{tabular} + +\bigskip\bigskip + +El {\it controlador de tablas} es un módulo del programa que permite la trasmisión de datos entre objetos de un modelo MathProg y tablas de datos. + +Actualmente, el paquete GLPK tiene cuatro controladores de tablas: + +\vspace*{-8pt} + +\begin{itemize} +\item controlador interno de tablas CSV; +\item controlador interno de tablas xBASE; +\item controlador de tablas ODBC; +\item controlador de tablas MySQL. +\end{itemize} + +\vspace*{-8pt} + +\section{Controlador de tablas CSV} + +El controlador de tablas CSV asume que la tabla de datos está representada en la forma de un archivo de texto plano, en el formato de archivo CSV (valores separados por coma) como se describe más adelante. + +Para elegir el controlador de tablas CSV, su nombre en la sentencia table debe especificarse como \verb|"CSV"| y el único argumento debe especificar el nombre de un archivo de texto plano conteniendo la tabla. Por ejemplo: + +\begin{verbatim} + table datos IN "CSV" "datos.csv": ... ; +\end{verbatim} + +El sufijo del nombre de archivo puede ser arbitrario; sin embargo, se recomienda usar el sufijo `\verb|.csv|'. + +\newpage + +Al leer tablas de entrada, el controlador de tablas CSV provee un campo implícito llamado \verb|RECNO|, el cual contiene el número del registro corriente. Este campo puede especificarse en la sentencia table de entrada, como si existiera un verdadero campo llamado \verb|RECNO| en el archivo CSV. Por ejemplo: + +\begin{verbatim} + table lista IN "CSV" "lista.csv": num <- [RECNO], ... ; +\end{verbatim} + +\subsection*{Formato CSV\footnote{Este material está basado en el documento RFC 4180.}} + +El formato CSV (valores separados por coma) es un formato de archivo de texto plano definido como sigue: + +1. Cada registro se ubica en una línea separada, delimitada por un salto de línea. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +\noindent +donde \verb|\n| significa el carácter de control \verb|LF| ({\tt 0x0A}). + +2. El último registro en el archivo puede tener un salto de línea final o no. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz +\end{verbatim} + +3. Debería haber una línea de encabezado que aparezca en la primera línea del archivo, en el mismo formato que las líneas de registro normales. Este encabezado debería contener nombres que correspondan a los campos en el archivo. El número de nombres de campo en la línea de encabezado debe ser igual al número de campos de los registros en el archivo. Por ejemplo: + +\begin{verbatim} + nombre1,nombre2,nombre3\n + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +4. Dentro del encabezado y de cada registro puede haber uno o más campos separados por comas. Cada línea debe contener el mismo número de campos a través de todo el archivo. Los espacios se consideran parte del campo y, consecuentemente, no son ignorados. El último campo en el registro no debe estar seguido de una coma. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n +\end{verbatim} + +5. Los campos pueden estar encerrados entre comillas dobles o no. Por ejemplo: + +\begin{verbatim} + "aaa","bbb","ccc"\n + zzz,yyy,xxx\n +\end{verbatim} + +6. Si el campo se encierra entre comillas dobles, cada comilla doble que sea parte del campo debe codificarse dos veces. Por ejemplo: + +\begin{verbatim} + "aaa","b""bb","ccc"\n +\end{verbatim} + +\newpage + +\para{Ejemplo} + +\begin{verbatim} +DESDE,HACIA,DISTANCIA,COSTO +Seattle,New-York,2.5,0.12 +Seattle,Chicago,1.7,0.08 +Seattle,Topeka,1.8,0.09 +San-Diego,New-York,2.5,0.15 +San-Diego,Chicago,1.8,0.10 +San-Diego,Topeka,1.4,0.07 +\end{verbatim} + +\section{Controlador de tablas xBASE} + +El controlador de tablas xBASE asume que la tabla de datos se almacenó en formato de archivo .dbf. + +Para elegir el controlador de tablas xBASE, su nombre en la sentencia table debe especificarse como \verb|"xBASE"| y el primer argumento debe especificar el nombre de un archivo .dbf que contenga la tabla. Para la tabla de salida, debe haber un segundo argumento definiendo el formato de la tabla en la forma \verb|"FF...F"|, donde \verb|F| es tanto {\tt C({\it n})}, el cual especifica un campo de caracteres de longitud $n$, como + {\tt N({\it n}{\rm [},{\it p}{\rm ]})}, el cual especifica un campo numérico de longitud $n$ y precisión $p$ (por defecto, $p$ es 0). + +El siguiente es un ejemplo simple que ilustra la creación y lectura de un archivo .dbf: + +\begin{verbatim} +table tab1{i in 1..10} OUT "xBASE" "foo.dbf" + "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, + "?" ~ FOO, "[" & i & "]" ~ C; +set M, dimen 4; +table tab2 IN "xBASE" "foo.dbf": M <- [B, C, RECNO, A]; +display M; +end; +\end{verbatim} + +\section{Controlador de tablas ODBC} + +El controlador de tablas ODBC permite conexiones con bases de datos SQL usando una implementación de la interfaz ODBC basada en la Call Level Interface (CLI).\footnote{La norma de software correspondiente se define en ISO/IEC 9075-3:2003.} + +\para{Debian GNU/Linux.} +Bajo Debian GNU/Linux, el controlador de tablas ODBC usa el paquete iODBC,\footnote{Ver {\tt}.} el cual debe estar instalado antes de compilar el paquete GLPK. La instalación se puede efectuar con el siguiente comando: + +\begin{verbatim} + sudo apt-get install libiodbc2-dev +\end{verbatim} + +Debe notarse que para la configuración del paquete GLPK para activar el uso de la librería iODBC, se debe pasar la opción `\verb|--enable-odbc|' al script de configuración. + +Para su uso en todo el sistema, las bases de datos individuales deben ingresarse en \verb|/etc/odbc.ini| y \verb|/etc/odbcinst.ini|. Las conexiones de las bases de datos usadas por un usuario individual se especifican mediante archivos en el directorio home (\verb|.odbc.ini| y \verb|.odbcinst.ini|). + +\para{Microsoft Windows.} +Bajo Microsoft Windows, el controlador de tablas ODBC usa la librería ODBC de Microsoft. Para activar esta característica, el símbolo: + +\begin{verbatim} + #define ODBC_DLNAME "odbc32.dll" +\end{verbatim} + +\noindent +debe definirse en el archivo de configuración de GLPK `\verb|config.h|'. + +Las fuentes de datos pueden crearse por intermedio de las Herramientas Administrativas del Panel de Control. + +Para elegir el controlador de tablas ODBC, su nombre en la sentencia table debe especificarse como \verb|'ODBC'| o \verb|'iODBC'|. + +La lista de argumentos se especifica como sigue. + +El primer argumento es la cadena de conexión que se pasa a la librería ODBC, por ejemplo: + +\verb|'DSN=glpk;UID=user;PWD=password'|, o + +\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. + +Las diferentes partes de la cadena se separan con punto y coma. Cada parte consiste de un par {\it nombre de campo} y {\it valor} separados por el signo igual. Los nombres de campo permitidos dependen de la librería ODBC. Típicamente, se permiten los siguientes nombres de campo: + +\verb|DATABASE | base de datos; + +\verb|DRIVER | controlador ODBC; + +\verb|DSN | nombre de una fuente de datos; + +\verb|FILEDSN | nombre de un archivo de fuente de datos; + +\verb|PWD | clave de usuario; + +\verb|SERVER | base de datos; + +\verb|UID | nombre de usuario. + +El segundo argumento, y todos los siguientes, son considerados como sentencias SQL. + +Las sentencias SQL se pueden extender sobre múltiples argumentos. Si el último carácter de un argumento es un punto y coma, este indica el final de una sentencia SQL. + +Los argumentos de una sentencia SQL se concatenan separados por espacios. El eventual punto y coma final será removido. + +Todas las sentencias SQL, excepto la última, se ejecutarán directamente. + +Para table-IN, la última sentencia SQL puede ser un comando SELECT que empieza con \verb|'SELECT '| en letras mayúsculas. Si la cadena no se inicia con \verb|'SELECT '|, se considera que es un nombre de tabla y automáticamente se genera una sentencia SELECT. + +Para table-OUT, la última sentencia SQL puede contener uno o múltiples signos de interrogación. Si contiene un signo de interrogación, se considera como una plantilla para la rutina de escritura. De otro modo, la cadena es considerada un nombre de tabla y se genera automáticamente una plantilla INSERT. + +La rutina de escritura usa la plantilla con el signo de interrogación y reemplaza al primer signo de interrogación con el primer parámetro de salida, el segundo signo de interrogación con el segundo parámetro de salida, y así sucesivamente. Luego se emite el comando SQL. + +El siguiente es un ejemplo de la sentencia table de salida: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'INSERT INTO resultados 'VALUES ( 4, ?, ? )' : + l ~ LOC, cantidad[l] ~ CANT; +\end{verbatim} + +\noindent +Alternativamente, se puede escribir como sigue: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'resultados' : + l ~ LOC, cantidad[l] ~ CANT, 4 ~ ID; +\end{verbatim} + +El uso de plantillas con `\verb|?|' no sólo permite INSERT, sino también UPDATE, DELETE, etc. Por ejemplo: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultados SET FECHA = ' & fecha & ' WHERE ID = 4;' + 'UPDATE resultados SET CANT = ? WHERE LOC = ? AND ID = 4' : + cantidad[l], l; +\end{verbatim} + +\section{Controlador de tablas MySQL} + +El controlador de tablas permite conexiones con bases de datos MySQL. + +\para{Debian GNU/Linux.} +Bajo Debian GNU/Linux, el controlador de tablas MySQL usa el paquete MySQL,\footnote{Para descargar los archivos de desarrollo, ver +{\tt}.} el cual debe estar instalado antes de compilar el paquete GLPK. La instalación se puede efectuar con el siguiente comando: + +\begin{verbatim} + sudo apt-get install libmysqlclient15-dev +\end{verbatim} + +Debe notarse que para la configuración del paquete GLPK para activar el uso de la librería MySQL, se debe pasar la opción `\verb|--enable-mysql|' al script de configuración. + +\para{Microsoft Windows.} +Bajo Microsoft Windows, el controlador de tablas MySQL también usa la librería MySQL. Para activar esta característica, el símbolo: + +\begin{verbatim} + #define MYSQL_DLNAME "libmysql.dll" +\end{verbatim} + +\noindent +debe definirse en el archivo de configuración de GLPK `\verb|config.h|'. + +Para elegir el controlador de tablas MySQL, su nombre en la sentencia table debe especificarse como \verb|'MySQL'|. + +La lista de argumentos se especifica como sigue. + +El primer argumento especifica como conectar la base de datos en el estilo DSN, por ejemplo: + +\verb|'Database=glpk;UID=glpk;PWD=gnu'|. + +Las diferentes partes de la cadena se separan con punto y coma. Cada parte consiste de un par {\it nombre de campo} y {\it valor} separados por el signo igual. Se permiten los siguientes nombres de campo: + +\verb|Server | servidor corriendo la base de datos (localhost por defecto); + +\verb|Database | nombre de la base de datos; + +\verb|UID | nombre de usuario; + +\verb|PWD | clave de usuario; + +\verb|Port | puerto usado por el servidor (3306 por defecto). + +El segundo argumento, y todos los siguientes, son considerados como sentencias SQL. + +Las sentencias SQL se pueden extender sobre múltiples argumentos. Si el último carácter de un argumento es un punto y coma, este indica el final de una sentencia SQL. + +Los argumentos de una sentencia SQL se concatenan separados por espacios. El eventual punto y coma final será removido. + +Todas las sentencias SQL, excepto la última, se ejecutarán directamente. + +Para table-IN, la última sentencia SQL puede ser un comando SELECT que empieza con \verb|'SELECT '| en letras mayúsculas. Si la cadena no se inicia con \verb|'SELECT '|, se considera que es un nombre de tabla y automáticamente se genera una sentencia SELECT. + +Para table-OUT, la última sentencia SQL puede contener uno o múltiples signos de interrogación. Si contiene un signo de interrogación, se considera como una plantilla para la rutina de escritura. De otro modo, la cadena es considerada un nombre de tabla y se genera automáticamente una plantilla INSERT. + +La rutina de escritura usa la plantilla con el signo de interrogación y reemplaza al primer signo de interrogación con el primer parámetro de salida, el segundo signo de interrogación con el segundo parámetro de salida y así sucesivamente. Luego se emite el comando SQL. + +El siguiente es un ejemplo de la sentencia table de salida: + +\newpage + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'INSERT INTO resultados VALUES ( 4, ?, ? )' : + l ~ LOC, cantidad[l] ~ CANT; +\end{verbatim} + +\noindent +Alternativamente, se puede escribir como sigue: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'resultados' : + l ~ LOC, cantidad[l] ~ CANT, 4 ~ ID; +\end{verbatim} + +El uso de plantillas con `\verb|?|' no sólo permite INSERT, sino también UPDATE, DELETE, etc. Por ejemplo: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultados SET FECHA = ' & fecha & ' WHERE ID = 4;' + 'UPDATE resultados SET CANT = ? WHERE LOC = ? AND ID = 4' : + cantidad[l], l; +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Solución de modelos con glpsol} + +El paquete GLPK\footnote{{\tt http://www.gnu.org/software/glpk/}} incluye el programa {\tt glpsol}, un {\it solver} autónomo de PL/PEM. Este programa puede ser invocado desde la línea de comando o desde el {\it shell} para resolver modelos escritos en el lenguaje de modelado GNU MathProg. + +Para comunicarle al solver que el archivo de entrada contiene una descripción del modelo, es necesario especificar la opción \verb|--model| en la línea de comando. Por ejemplo: + +\begin{verbatim} + glpsol --model foo.mod +\end{verbatim} + +A veces es necesario usar la sección de datos colocada en un archivo separado, en cuyo caso se debe usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --data foo.dat +\end{verbatim} + +\noindent Debe notarse que, si el archivo del modelo también contiene una sección de datos, esta sección será ignorada. + +También se permite especificar más de un archivo conteniendo la sección de datos, por ejemplo: + +\begin{verbatim} + glpsol --model foo.mod --data foo1.dat --data foo2.dat +\end{verbatim} + +Si la descripción del modelo contiene algunas sentencias display y/o printf, por defecto la salida es enviada a la terminal. Si se necesita redirigir la salida a un archivo, se puede usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --display foo.out +\end{verbatim} + +Si se necesita inspeccionar el problema, el cual ha sido generado por el traductor del modelo, se puede usar la opción \verb|--wlp| como sigue: + +\begin{verbatim} + glpsol --model foo.mod --wlp foo.lp +\end{verbatim} + +\noindent En este caso el problema se escribe en el archivo \verb|foo.lp|, en formato CPLEX LP apropiado para el análisis visual. + +\newpage + +A veces sólo se necesita chequear la descripción del modelo, sin resolver la instancia generada del problema. En este caso, se debe especificar la opción \verb|--check|, por ejemplo: + +\begin{verbatim} + glpsol --check --model foo.mod --wlp foo.lp +\end{verbatim} + +Si se necesita escribir una solución numérica obtenida por el solver en un archivo, se puede usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --output foo.sol +\end{verbatim} + +\noindent en cuyo caso la solución se escribe en el archivo \verb|foo.sol| en formato de texto plano apropiado para el análisis visual. + +La lista completa de opciones de \verb|glpsol| se puede encontrar en el manual de referencia de GLPK incluido en la distribución de GLPK. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Ejemplo de descripción del modelo} + +\section{Descripción del modelo escrita en MathProg} + +Abajo hay un ejemplo completo de la descripción de un modelo escrito en el lenguaje de modelado GNU MathProg. + +\bigskip + +\begin{verbatim} +# UN PROBLEMA DE TRANSPORTE +# +# Este problema determina la logística de costo mínimo de flete +# que cumple los requerimientos en los mercados y en las fábricas +# de suministro. +# +# Referencia: +# Dantzig G B. 1963. Linear Programming and Extensions. +# Princeton University Press, Princeton, New Jersey. +# Sección 3-3. + +set I; +/* plantas de enlatado */ + +set J; +/* mercados */ + +param a{i in I}; +/* producción de la planta i, en cajas */ + +param b{j in J}; +/* demanda en el mercado j, en cajas */ + +param d{i in I, j in J}; +/* distancia, en miles de millas */ + +param f; +/* flete, en dólares por caja cada mil millas */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* costo de transporte, en miles de dólares por caja */ + +var x{i in I, j in J} >= 0; +/* cantidades despachadas, en cajas */ + +minimize costo: sum{i in I, j in J} c[i,j] * x[i,j]; +/* costo total de transporte, en miles de dólares */ + +s.t. suministro{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observar el límite de suministro de la planta i */ + +s.t. demanda{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfacer la demanda del mercado j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; +\end{verbatim} + +%\newpage + +\section{Instancia generada del problema de PL} + +Abajo está el resultado de la traducción del modelo de ejemplo producido por el solver \verb|glpsol|, con la opción \verb|--wlp| y escrita en el formato CPLEX LP. + +\medskip + +\begin{verbatim} +\* Problem: transporte *\ + +Minimize + costo: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) + +Subject To + suministro(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + + x(Seattle,Topeka) <= 350 + suministro(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + + x(San~Diego,Topeka) <= 600 + demanda(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 + demanda(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 + demanda(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 + +End +\end{verbatim} + +\section{Solución óptima del problema de PL} + +Abajo está la solución óptima de la instancia generada del problema de PL encontrada por el solver \verb|glpsol|, con la opción \verb|--output| y escrita en formato de texto plano. + +\medskip + +%\begin{footnotesize} +\begin{verbatim} +Problem: transporte +Rows: 6 +Columns: 6 +Non-zeros: 18 +Status: OPTIMAL +Objective: costo = 153.675 (MINimum) + + No. Row name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 costo B 153.675 + 2 suministro[Seattle] + NU 350 350 < eps + 3 suministro[San-Diego] + B 550 600 + 4 demanda[New-York] + NL 325 325 0.225 + 5 demanda[Chicago] + NL 300 300 0.153 + 6 demanda[Topeka] + NL 275 275 0.126 + + No. Column name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 x[Seattle,New-York] + B 50 0 + 2 x[Seattle,Chicago] + B 300 0 + 3 x[Seattle,Topeka] + NL 0 0 0.036 + 4 x[San-Diego,New-York] + B 275 0 + 5 x[San-Diego,Chicago] + NL 0 0 0.009 + 6 x[San-Diego,Topeka] + B 275 0 + +End of output +\end{verbatim} +%\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section*{Reconocimientos} +\addcontentsline{toc}{chapter}{Reconocimientos} + +Los autores desean agradecer a las siguientes personas, quienes amablemente leyeron, comentaron y corrigieron el borrador de este documento: + +\noindent Juan Carlos Borrás \verb|| + +\noindent Harley Mackenzie \verb|| + +\noindent Robbie Morrison \verb|| + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.pdf new file mode 100644 index 000000000..a2f25cb6d Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.tex new file mode 100644 index 000000000..ee5723b71 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/gmpl_pt-BR.tex @@ -0,0 +1,7893 @@ +%* gmpl.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +% Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +% rights reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +\documentclass[11pt, brazil]{report} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} + +\renewcommand\contentsname{\sf\bfseries Conteúdo} +\renewcommand\chaptername{\sf\bfseries Capítulo} +\renewcommand\appendixname{\sf\bfseries Apêndice} + +% \renewcommand\contentsname{\sf\bfseries Contents} +% \renewcommand\chaptername{\sf\bfseries Chapter} +% \renewcommand\appendixname{\sf\bfseries Appendix} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries Linguagem de Modelagem GNU MathProg +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Linguagem de Referência % Language Reference +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf para o GLPK Versão 4.57 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (RASCUNHO, Fevereiro 2016) +\end{Large} + +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +% The GLPK package is part of the GNU Project released under the aegis of GNU. +O pacote GLPK é parte do Projeto GNU distribuído sob a égide do GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013, 2014, 2015, 2016 Andrew Makhorin, Department +for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. +% All rights reserved. +Todos os direitos reservados. + +\noindent +Título original: Modeling Language GNU MathProg - Language Reference for GLPK Version 4.57 + +\noindent +Tradução: João Flávio de Freitas Almeida, Departamento de Engenharia de Produção, Universidade Federal de Minas Gerais, +Minas Gerais, Brasil. + +\noindent +Copyright \copyright{} 2015 João Flávio de Freitas Almeida, para esta tradução. Todos os direitos reservados. + +\noindent +Free Software Foundation, Inc., Rua Franklin, 51, 5$^{o}$ andar, Boston, +MA 02110-1301, USA. + +\noindent +É permitido realizar e distribuir cópias textuais deste manual +mantendo o aviso de copyright e preservando este aviso de permissão +em todas as cópias. +% Permission is granted to make and distribute verbatim copies of this +% manual provided the copyright notice and this permission notice are +% preserved on all copies. + +\noindent +É concedida a permissão para copiar e distribuir versões modificadas deste manual sob +as condições de cópias textuais, desde que o resultado completo derivado +do trabalho resultante seja distribuído sob os termos de uma notificação +de permissão idêntica a esta. + +% Permission is granted to copy and distribute modified versions of this +% manual under the conditions for verbatim copying, provided also that +% the entire resulting derived work is distributed under the terms of +% a permission notice identical to this one. + +\noindent +É concedida a permissão para copiar e distribuir traduções deste manual +em outra linguagem, sob as condições acima para as versões modificadas. + +% Permission is granted to copy and distribute translations of this +% manual into another language, under the above conditions for modified +% versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Introdução} + +{\it GNU MathProg} é uma linguagem de modelagem projetada para descrever +modelos lineares de programação matemática. +\footnote{A linguagem GNU MathProg é um subconjunto da linguagem AMPL. +A implementação do GLPK é \linebreak principalmente baseada no artigo: +{\it Robert Fourer}, {\it David M. Gay}, and +{\it Brian W. Kernighan}, ``A Modeling Language for Mathematical +Programming.'' {\it Management Science} 36 (1990), pp.~519-54.} + +% {\it GNU MathProg} is a modeling language intended for describing +% linear mathematical programming models.\footnote{The GNU MathProg +% language is a subset of the AMPL language. Its GLPK implementation is +% mainly based on the paper: {\it Robert Fourer}, {\it David M. Gay}, and +% {\it Brian W. Kernighan}, ``A Modeling Language for Mathematical +% Programming.'' {\it Management Science} 36 (1990), pp.~519-54.} + +A descrição de um modelo escrito na linguagem GNU MathProg consiste +em um conjunto de sentenças e blocos de dados construído pelo +usuário a partir dos elementos de linguagem descritos neste documento. + + +% Model descriptions written in the GNU MathProg language consist of +% a set of statements and data blocks constructed by the user from the +% language elements described in this document. + +Em um processo denominado {\it tradução}, um programa denominado +{\it tradutor do modelo} analisa a descrição do modelo e o traduz +para uma estrutura de dados interna, que pode ser usado tanto para gerar +instância de um problema de programação matemática ou obter diretamente +a solução numérica do problema por meio de um programa chamado {\it solver}. + +% In a process called {\it translation}, a program called the {\it model +% translator} analyzes the model description and translates it into +% internal data structures, which may be then used either for generating +% mathematical programming problem instance or directly by a program +% called the {\it solver} to obtain numeric solution of the problem. + +\section{Problema de programação linear} +\label{problem} + +Em MathProg o problema de programação linear (PL) é expresso da seguinte forma: + +% In MathProg the linear programming (LP) problem is stated as follows: + +\medskip + +\noindent\hspace{1in}minimizar (ou maximizar) +$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ +\noindent\hspace{1in}subjeito às restrições lineares +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} +L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ +L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ +\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ +\end{array}\eqno(1.2) +$$ +\noindent\hspace{1in}e os limites das variáveis +$$ +\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} +l_1&\leq&x_1&\leq&u_1\\ +l_2&\leq&x_2&\leq&u_2\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_n&\leq&x_n&\leq&u_n\\ +\end{array}\eqno(1.3) +$$ + +% \newpage + +\noindent +onde $x_1$, $x_2$, \dots, $x_n$ são variáveis; $z$ é a função objetivo +; $c_1$, $c_2$, \dots, $c_n$ são coeficientes da função objetivo; $c_0$ +é o termo constante da função objetivo; $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ são coeficientes das restrições; $L_1$, $L_2$, +\dots, $L_m$ são limites inferiores das restrições; $U_1$, $U_2$, \dots, $U_m$ +são limites superiores das restrições; $l_1$, $l_2$, \dots, $l_n$ são limites +inferiores das variáveis; $u_1$, $u_2$, \dots, $u_n$ são limites superiores das +variáveis. + +Os limites das variáveis e das restrições podem ser tanto finitos quanto +infinitos. Além disso, os limites inferiores podem ser igual aos limites +superiores correspondentes. Logo, os seguintes tipos de variáveis e +restrições são permitidos: + + +% where $x_1$, $x_2$, \dots, $x_n$ are variables; $z$ is the objective +% function; $c_1$, $c_2$, \dots, $c_n$ are objective coefficients; $c_0$ +% is the constant term (``shift'') of the objective function; $a_{11}$, +% $a_{12}$, \dots, $a_{mn}$ are constraint coefficients; $L_1$, $L_2$, +% \dots, $L_m$ are lower constraint bounds; $U_1$, $U_2$, \dots, $U_m$ +% are upper constraint bounds; $l_1$, $l_2$, \dots, $l_n$ are lower +% bounds of variables; $u_1$, $u_2$, \dots, $u_n$ are upper bounds of +% variables. +% +% Bounds of variables and constraint bounds can be finite as well as +% infinite. Besides, lower bounds can be equal to corresponding upper +% bounds. Thus, the following types of variables and constraints are +% allowed: + +\medskip + +{\def\arraystretch{1.4} +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +$-\infty$&$<$&$x$&$<$&$+\infty$&Variável livre (ilimitada)\\ +$l$&$\leq$&$x$&$<$&$+\infty$&Variável com limite inferior\\ +$-\infty$&$<$&$x$&$\leq$&$u$&Variável com limite superior\\ +$l$&$\leq$&$x$&$\leq$&$u$&Variável duplamente limitada\\ +$l$&$=$&$x$&=&$u$&Variável fixa\\ +\end{tabular} +% \begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +% $-\infty$&$<$&$x$&$<$&$+\infty$&Free (unbounded) variable\\ +% $l$&$\leq$&$x$&$<$&$+\infty$&Variable with lower bound\\ +% $-\infty$&$<$&$x$&$\leq$&$u$&Variable with upper bound\\ +% $l$&$\leq$&$x$&$\leq$&$u$&Double-bounded variable\\ +% $l$&$=$&$x$&=&$u$&Fixed variable\\ +% \end{tabular} + +\noindent\hfil +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Forma linear livre (ilimitada)\\ +$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Restrição de desigualdade ``maior ou igual a''\\ +$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Restrição de desigualdade ``menor ou igual a''\\ +$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Restrição de desigualdade duplamente limitada\\ +$L$&$=$&$\sum a_jx_j$&=&$U$&Restrição de igualdade\\ +\end{tabular} +% \begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +% $-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Free (unbounded) linear +% form\\ +% $L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Inequality constraint ``greater +% than or equal to''\\ +% $-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Inequality constraint ``less +% than or equal to''\\ +% $L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Double-bounded inequality +% constraint\\ +% $L$&$=$&$\sum a_jx_j$&=&$U$&Equality constraint\\ +% \end{tabular} +} + +\medskip + +Além de problemas puramente PL, MathProg também permite +problemas de programação inteira mista (PIM), onde algumas ou +todas as variáveis são restritas a serem inteiras ou binárias. + +% In addition to pure LP problems MathProg also allows mixed integer +% linear programming (MIP) problems, where some or all variables are +% restricted to be integer or binary. + +\section{Objetos do modelo} + +Em MathProg o modelo é descrito em termos de conjuntos, parâmetros, +variáveis, restrições e objetivos, que se denominam {\it objetos +do modelo}. + +O usuário introduz objetos particulares do modelo usando as sentenças +da linguagem. Cada objeto do modelo possui um nome simbólico que o identifica +de maneira única sendo projetado para propósitos de referenciação. + +% In MathProg the model is described in terms of sets, parameters, +% variables, constraints, and objectives, which are called {\it model +% objects}. +% +% The user introduces particular model objects using the language +% statements. Each model object is provided with a symbolic name which +% uniquely identifies the object and is intended for referencing +% purposes. + +Objetos do modelo, incluindo conjuntos, podem ser matrizes multidimensionais +construídos sobre conjuntos indexantes. Formalmente, uma matriz $n$-dimensional $A$ +é o mapeamento: +% Model objects, including sets, can be multidimensional arrays built +% over indexing sets. Formally, $n$-dimensional array $A$ is the mapping: +$$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ +onde $\Delta\subseteq S_1\times\dots\times S_n$ é um subconjunto do +produto Cartesiano de conjuntos indexantes, $\Xi$ é um conjunto dos +membros da matriz. Em MathProg o conjunto $\Delta$ é chamado o {\it domínio do subíndice}. % REVISAR +Seus membros são $n$-tuplas $(i_1,\dots,i_n)$, onde $i_1\in S_1$, \dots, +$i_n\in S_n$. +% where $\Delta\subseteq S_1\times\dots\times S_n$ is a subset of the +% Cartesian product of indexing sets, $\Xi$ is a set of array members. +% In MathProg the set $\Delta$ is called the {\it subscript domain}. Its +% members are $n$-tuples $(i_1,\dots,i_n)$, where $i_1\in S_1$, \dots, +% $i_n\in S_n$. + +Se $n=0$, o produto Cartesiano acima possui exatamente um membro (denominado +0-tupla), portanto, é conveniente pensar nos objetos escalares como sendo +matrizes 0-dimensionais que \linebreak possuem apenas um membro. +% If $n=0$, the Cartesian product above has exactly one member (namely, +% 0-tuple), so it is convenient to think scalar objects as 0-dimensional +% arrays having one member. + +% \newpage + +O tipo dos membros da matriz é determinado pelo tipo de objeto do modelo +correspondente, como segue: +% The type of array members is determined by the type of corresponding +% model object as follows: + +\medskip + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Objeto do modelo&Membro da matriz\\ +\hline +Conjunto&Conjunto plano elementar\\ +Parâmetro&Número ou símbolo\\ +Variável&Variável elementar\\ +Restrição&Restrição elementar\\ +Objetivo&Objetivo elementar\\ +\end{tabular} +% \begin{tabular}{@{}ll@{}} +% Model object&Array member\\ +% \hline +% Set&Elemental plain set\\ +% Parameter&Number or symbol\\ +% Variable&Elemental variable\\ +% Constraint&Elemental constraint\\ +% Objective&Elemental objective\\ +% \end{tabular} + +\medskip + +Para referir a um membro particular de um objeto, este deve possuir +{\it subíndices}. Por exemplo, se $a$ é um parâmetro 2-dimensional +definido sobre $I\times J$, uma referência a seus membros particulares +pode ser escrito como $a[i,j]$, onde $i\in I$ e $j\in J$. Entende-se +que objetos escalares não necessitam de subíndices por serem 0-dimensionais. + +% In order to refer to a particular object member the object should be +% provided with {\it subscripts}. For example, if $a$ is a 2-dimensional +% parameter defined over $I\times J$, a reference to its particular +% member can be written as $a[i,j]$, where $i\in I$ and $j\in J$. It is +% understood that scalar objects being 0-dimensional need no subscripts. + +\section{Estrutura da descrição do modelo} + +Às vezes é desejável escrever um modelo que, por diferentes motivos, +tenha que requerer diferentes dados para resolver cada instância do problema +usando o mesmo modelo. +Por esta razão, em MathProg a descrição do modelo consiste em duas partes: +a {\it seção de modelo} e a {\it seção de dados}. + +% It is sometimes desirable to write a model which, at various points, +% may require different data for each problem instance to be solved using +% that model. For this reason in MathProg the model description consists +% of two parts: the {\it model section} and the {\it data section}. + +A seção de modelo é a principal parte da descrição do modelo, pois ela contém +as declarações dos objetos do modelo. Ela também é comum a todos os problemas +baseados no modelo correspondente. + +% The model section is a main part of the model description that contains +% declarations of model objects and is common for all problems based on +% the corresponding model. + +A seção de dados é uma parte opcional da descrição do modelo que +contém dados específicos para uma instância particular do problema. + +% The data section is an optional part of the model description that +% contains data specific for a particular problem instance. + +Dependendo do que seja mais conveniente, as seções de modelo e de dados +podem ser dispostas em um arquivo único ou em dois arquivos separados. +Esta última funcionalidade permite que se tenha um quantidade arbitrária +de seções de dados diferentes a serem usadas com a mesma seção de modelo. + +% Depending on what is more convenient the model and data sections can be +% placed either in one file or in two separate files. The latter feature +% allows having arbitrary number of different data sections to be used +% with the same model section. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Codificação da descrição do modelo} +\label{coding} + +A descrição do modelo é codificada em um formato de arquivo plano de +texto usando o conjunto de caracteres ASCII. +Os caracteres válidos na descrição do modelo são os seguintes: + +% The model description is coded in a plain text format using ASCII +% character set. Characters valid in the model description are the +% following: + +\begin{itemize} +\item Caracteres alfabéticos:\\ +\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ +\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| +\item caracteres numéricos:\\ +\verb|0 1 2 3 4 5 6 7 8 9| +\item caracteres especiais:\\ +\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? +\item caracteres de espaço em branco:\\ +\verb|SP HT CR NL VT FF| +\end{itemize} + +Dentro de literais de cadeia e comentários quaisquer +caracteres ASCII (exceto caracteres de controle) são válidos. + +% Within string literals and comments any ASCII characters (except +% control characters) are valid. + + +Caracteres de espaço-em-branco não são significativos. Eles podem ser +usados livremente entre unidades léxicas para melhorar a legibilidade da +descrição do modelo. Eles também são usados para separar unidades léxicas +entre si, no caso de não existir outra forma de fazê-lo. + +% White-space characters are non-significant. They can be used freely +% between lexical units to improve readability of the model description. +% They are also used to separate lexical units from each other if there +% is no other way to do that. + +Sintaticamente a descrição do modelo é uma sequência de unidades léxicas +nas seguintes \linebreak categorias: + +% Syntactically model description is a sequence of lexical units in the +% following categories: + +\begin{itemize} +\item nomes simbólicos; +\item literais numéricos; +\item literais de cadeia; +\item palavras-chave; +\item delimitadores; +\item comentários. +\end{itemize} + +% \begin{itemize} +% \item symbolic names; +% \item numeric literals; +% \item string literals; +% \item keywords; +% \item delimiters; +% \item comments. +% \end{itemize} + +As unidades léxicas da linguagem são discutidas abaixo. + +% \newpage + +\section{Nomes simbólicos} + +Um {\it nome simbólico} consiste de caracteres alfabéticos e numéricos, +em que o primeiro deste deve ser alfabético. Todos os nomes simbólicos +devem ser distintos (sensibilidade às maiúsculas: case-sensitive). + +% A {\it symbolic name} consists of alphabetic and numeric characters, +% the first of which should be alphabetic. All symbolic names are +% distinct (case sensitive). + +\para{Exemplos} + +\begin{verbatim} +alfa123 +Este_eh_um_nome +_P123_abc_321 +\end{verbatim} + +Nomes simbólicos são usados para identificar objetos do modelo +(conjuntos, parâmetros, \linebreak variáveis, restrições, objetivos) +e os índices. + +% Symbolic names are used to identify model objects (sets, parameters, +% variables, constraints, objectives) and dummy indices. + +Todos os nomes simbólicos (exceto os nomes dos índices) devem ser únicos, +i.e., a descrição do modelo não pode ter objetos com nomes idênticos. +Nomes simbólicos de índices devem ser únicos dentro do escopo em que são válidos. + +% All symbolic names (except names of dummy indices) should be unique, +% i.e. the model description should have no objects with identical names. +% Symbolic names of dummy indices should be unique within the scope, +% where they are valid. + +\section{Literais numéricos} + +Um {\it literal numérico} possui a forma {\it xx}{\tt E}{\it syy}, onde +{\it xx} é um número com ponto decimal opcional, {\it s} é o sinal +{\tt+} ou {\tt-}, {\it yy} é um expoente decimal. A letra {\tt E} é +insensível à maiúsculas (case-insensitive) e pode ser codificada como {\tt e}. + +% A {\it numeric literal} has the form {\it xx}{\tt E}{\it syy}, where +% {\it xx} is a number with optional decimal point, {\it s} is the sign +% {\tt+} or {\tt-}, {\it yy} is a decimal exponent. The letter {\tt E} is +% case insensitive and can be coded as {\tt e}. + +\para{Exemplos} + +\begin{verbatim} +123 +3.14159 +56.E+5 +.78 +123.456e-7 +\end{verbatim} + +Literais numéricos são usados para representar quantidades numéricas. Eles +possuem significado fixo óbvio. + +% Numeric literals are used to represent numeric quantities. They have +% obvious fixed meaning. + +\section{Literais de cadeia} + +Uma {\it literal de cadeia} é uma sequência arbitrária de caracteres cercada +por aspas tanto simples como duplas. Ambas formas são equivalentes. + +% A {\it string literal} is a sequence of arbitrary characters enclosed +% either in single quotes or in double quotes. Both these forms are +% equivalent. + +Se uma aspa simples é parte de uma literal de cadeia cercada por +aspas simples, ela deve ser codificada duas vezes. De forma análoga, +se uma aspa dupla é parte de um literal de cadeia cercada por aspas duplas, +ela deve ser codificada duas vezes. + +% If a single quote is part of a string literal enclosed in single +% quotes, it should be coded twice. Analogously, if a double quote is +% part of a string literal enclosed in double quotes, it should be coded +% twice. + +\para{Exemplos} + +\begin{verbatim} +'Esta eh uma string' +"Esta eh outra string" +'Copo d''agua' +"""Beleza"" disse o capitao." +\end{verbatim} + +Literais de cadeia são usadas para representar quantidades simbólicas. +% String literals are used to represent symbolic quantities. + +\section{Palavras-chave} + +Uma {\it palavra-chave} é uma sequência de caracteres alfabéticos e +possivelmente alguns caracteres especiais. + +% A {\it keyword} is a sequence of alphabetic characters and possibly +% some special characters. + +Todas as palavras-chave caem em algumas das duas categorias: +{\it palavras-chave reservadas}, que não podem ser usadas como nomes simbólicos, +e {\it palavras-chave não-reservadas}, que são reconhecidas pelo contexto, +portanto, podem ser usadas como nomes simbólicos. + + +As palavras-chave reservadas são as seguintes: + +% All keywords fall into two categories: {\it reserved keywords}, which +% cannot be used as symbolic names, and {\it non-reserved keywords}, +% which are recognized by context and therefore can be used as symbolic +% names. +% +% The reserved keywords are the following: + +\noindent\hfil +\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} +{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ +{\tt by}&{\tt if}&{\tt not}&{\tt within}\\ +{\tt cross}&{\tt in}&{\tt or}\\ +{\tt diff}&{\tt inter}&{\tt symdiff}\\ +{\tt div}&{\tt less}&{\tt then}\\ +\end{tabular} + +Palavras-chave não-reservadas são descritas nas seções posteriores. + +Todas as palavras-chave possuem um significado fixo, a ser +explicado nas discussões das \linebreak construções sintáticas correspondentes, +onde as palavras-chave são usadas. + +% Non-reserved keywords are described in following sections. +% +% All the keywords have fixed meaning, which will be explained on +% discussion of corresponding syntactic constructions, where the keywords +% are used. + +\section{Delimitadores} + +Um {\it delimitador} é tanto um caractere especial único quanto uma sequência +de dois caracteres especiais, como segue: + +% A {\it delimiter} is either a single special character or a sequence of +% two special characters as follows: + +\noindent\hfil +\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} +p{.3in}p{.3in}@{}} +{\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}& +{\tt>>}\\ +{\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}& +{\tt\char126}&{\tt]}&{\tt<-}\\ +{\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ +{\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ +\end{tabular} + +Se um delimitador consiste de dois caracteres, não deve haver espaços +entre os eles. + +Todos os delimitadores possuem um significado fixo, a ser +explicado nas discussões das \linebreak construções sintáticas correspondentes, +onde os delimitadores são usados. + +% If the delimiter consists of two characters, there should be no spaces +% between the characters. +% +% All the delimiters have fixed meaning, which will be explained on +% discussion corresponding syntactic constructions, where the delimiters +% are used. + +\section{Comentários} + +Com propósitos de documentação, a descrição do modelo pode conter +{\it comentários}, que podem ter duas formas diferentes. A primeira forma é +um {\it comentário de linha-única}, que começa com o caractere {\tt\#} +e se estende até o final da linha. A segunda forma é uma {\it sequência de +comentários}, que é uma sequência de quaisquer caracteres cercados por +{\tt/*} e {\tt*/}. + +% For documenting purposes the model description can be provided with +% {\it comments}, which may have two different forms. The first form is +% a {\it single-line comment}, which begins with the character {\tt\#} +% and extends until end of line. The second form is a {\it comment +% sequence}, which is a sequence of any characters enclosed within +% {\tt/*} and {\tt*/}. + +\para{Exemplos} + +\begin{verbatim} +param n := 10; # Este é um comentario +/* Este é outro comentário */ +\end{verbatim} + +Comentários e caracteres de espaço-em-branco são ignorados pelo tradutor +do modelo e podem aparecer em qualquer local da descrição do modelo. + +% Comments are ignored by the model translator and can appear anywhere in +% the model description, where white-space characters are allowed. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Expressões} + +Uma {\it expressão} é uma regra para calcular um valor. Na descrição +de um modelo, expressões são usadas como constituintes de certas sentenças. + +No geral, expressões são constituídas de operandos e operadores. + +Dependendo do tipo de valor resultante, todas expressões se enquadram nas +seguintes categorias: + +% An {\it expression} is a rule for computing a value. In model +% description expressions are used as constituents of certain statements. +% +% In general case expressions consist of operands and operators. +% +% Depending on the type of the resultant value all expressions fall into +% the following categories: + +\vspace*{-8pt} + +\begin{itemize} +\item expressões numéricas; +\item expressões simbólicas; +\item expressões indexantes; +\item expressões de conjuntos; +\item expressões lógicas; +\item expressões lineares. +\end{itemize} + +% \begin{itemize} +% \item numeric expressions; +% \item symbolic expressions; +% \item indexing expressions; +% \item set expressions; +% \item logical expressions; +% \item linear expressions. +% \end{itemize} + +\vspace*{-8pt} + +\section{Expressões numéricas} + +Uma {\it expressão numérica} é uma regra para calcular um valor numérico individual +representado como um número de ponto-flutuante. + +A expressão numérica primária pode ser um literal numérico, um índice, +um parâmetro não-indexado, um parâmetro indexado, uma função interna de +referência, uma expressão numérica iterada, uma expressão numérica condicional +ou outra expressão cercada por parênteses. + +% A {\it numeric expression} is a rule for computing a single numeric +% value represented as a floating-point number. +% +% The primary numeric expression may be a numeric literal, dummy index, +% unsubscripted parameter, subscripted parameter, built-in function +% reference, iterated numeric expression, conditional numeric expression, +% or another numeric expression enclosed in parentheses. + +\para{Exemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|1.23 |&(literal numérico)\\ +\verb|j|&(índice)\\ +\verb|time|&(parâmetro não-indexado)\\ +\verb|a['May 2003',j+1]|&(parâmetro indexado)\\ +\verb|abs(b[i,j])|&(função de referência)\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% \verb|1.23 |&(numeric literal)\\ +% \verb|j|&(dummy index)\\ +% \verb|time|&(unsubscripted parameter)\\ +% \verb|a['May 2003',j+1]|&(subscripted parameter)\\ +% \verb|abs(b[i,j])|&(function reference)\\ +% \end{tabular} + +\newpage + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|sum{i in S diff T} alpha[i] * b[i,j]|&(expressão iterada)\\ +\verb|if i in I then 2 * p else q[i+1]|&(expressão condicional)\\ +\verb|(b[i,j] + .5 * c)|&(expressão entre parênteses)\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% \verb|sum{i in S diff T} alpha[i] * b[i,j]|&(iterated expression)\\ +% \verb|if i in I then 2 * p else q[i+1]|&(conditional expression)\\ +% \verb|(b[i,j] + .5 * c)|&(parenthesized expression)\\ +% \end{tabular} + +Expressões numéricas mais genéricas, contendo duas ou mais +expressões numéricas primárias, podem ser construídas usando +determinados operadores aritméticos. + +% More general numeric expressions containing two or more primary numeric +% expressions may be constructed by using certain arithmetic operators. + +\para{Exemplos} + +\begin{verbatim} +j+1 +2 * a[i-1,j+1] - b[i,j] +sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] +(if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) +\end{verbatim} + +\subsection{Literais numéricos} + +Se a expressão numérica primária é um literal numérico, +o valor resultante é óbvio. + +% If the primary numeric expression is a numeric literal, the resultant +% value is obvious. + +\subsection{Índices} + +Se a expressão numérica primária é um índice, +o valor resultante é o valor corrente atribuído àquele índice. + +% If the primary numeric expression is a dummy index, the resultant value +% is current value assigned to that dummy index. + +\subsection{Parâmetros não-indexados} + +Se a expressão numérica primária é um parâmetro não-indexado +(que deve ser 0-dimensional), o valor resultante é o valor +do parâmetro. + +% If the primary numeric expression is an unsubscripted parameter (which +% should be 0-dimen\-sional), the resultant value is the value of that +% parameter. + +\subsection{Parâmetros indexados} + +A expressão numérica primária, que se refere ao parâmetro indexado, +possui a seguinte forma sintática: +% The primary numeric expression, which refers to a subscripted +% parameter, has the following syntactic form: +$$ +\mbox{{\it nome}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} +$$ +onde {\it nome} é o nome simbólico do parâmetro e $i_1$, $i_2$, +\dots, $i_n$ são subíndices. + +Cada subíndice deve ser uma expressão numérica ou simbólica. O número +de subíndices na lista de subíndices deve ser o mesmo da dimensão +do parâmetro com o qual a lista de subíndices está associada. + +Os valores reais das expressões de subíndice são usadas para identificar +um membro particular do parâmetro que determina o valor resultante +da expressão primária. + +% where {\it name} is the symbolic name of the parameter, $i_1$, $i_2$, +% \dots, $i_n$ are subscripts. +% +% Each subscript should be a numeric or symbolic expression. The number +% of subscripts in the subscript list should be the same as the dimension +% of the parameter with which the subscript list is associated. +% +% Actual values of subscript expressions are used to identify +% a particular member of the parameter that determines the resultant +% value of the primary expression. + +\newpage + +\subsection{Funções de referência} + +Em MathProg existem as seguintes funções internas, que podem ser +usadas como expressões numéricas: + +% In MathProg there exist the following built-in functions which may be +% used in numeric expressions: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt abs(}$x${\tt)}&$|x|$, valor absoluto de $x$\\ +{\tt atan(}$x${\tt)}&$\arctan x$, valor principal do arco tangente de +$x$ (em radianos)\\ +{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, valor principal do +arco tangente de $y/x$ (em radianos). Neste caso, os sinais de ambos +argumentos $y$ e $x$ são usados para determinar o quadrante do valor +resultante\\ +{\tt card(}$X${\tt)}&$|X|$, cardinalidade (o número de elementos) do +conjunto $X$\\ +{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, menor inteiro não menor que +$x$ (``teto de $x$'')\\ +{\tt cos(}$x${\tt)}&$\cos x$, cosseno de $x$ (em radianos)\\ +{\tt exp(}$x${\tt)}&$e^x$, exponencial de $x$ na base-$e$\\ +{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, maior inteiro não maior +que $x$ (``piso de $x$'')\\ +{\tt gmtime()}&o número de segundos decorridos deste 00:00:00 de~01~de~Jan de 1970, +Tempo Universal Coordenado (detalhes na Seção \ref{gmtime}, +página \pageref{gmtime})\\ +{\tt length(}$s${\tt)}&$|s|$, comprimento da cadeia de caracteres $s$\\ +{\tt log(}$x${\tt)}&$\log x$, logaritmo natural de $x$\\ +{\tt log10(}$x${\tt)}&$\log_{10}x$, logaritmo comum (decimal) de $x$\\ +{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&o maior +dos valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&o menor +dos valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt round(}$x${\tt)}&arrendondamento de $x$ ao inteiro mais próximo\\ +{\tt round(}$x${\tt,} $n${\tt)}&arrendondamento de $x$ a $n$ dígitos decimais\\ +{\tt sin(}$x${\tt)}&$\sin x$, seno de $x$ (em radianos)\\ +{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, raiz quadrada não-negativa de $x$\\ +{\tt str2time(}$s${\tt,} $f${\tt)}&conversão de uma cadeia de caracteres $s$ ao +tempo calendário (detalhes na Seção \ref{str2time}, página +\pageref{str2time})\\ +{\tt trunc(}$x${\tt)}&truncado de $x$ ao inteiro mais próximo\\ +{\tt trunc(}$x${\tt,} $n${\tt)}&truncado de $x$ a $n$ dígitos decimais\\ +{\tt Irand224()}&gera inteiro pseudo-aleatório uniformemente distribuído +em $[0,2^{24})$\\ +{\tt Uniform01()}&gera número pseudo-aleatório uniformemente distribuído +em $[0,1)$\\ +{\tt Uniform(}$a${\tt,} $b${\tt)}&gera número pseudo-aleatório uniformemente +distribuído em $[a,b)$\\ +{\tt Normal01()}&gera variável Gaussiana pseudo-aleatória com +$\mu=0$ e $\sigma=1$\\ +{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&gera variável Gaussiana pseudo-aleatória +com $\mu$ e $\sigma$ dados\\ +\end{tabular} + +% \begin{tabular}{@{}p{112pt}p{328pt}@{}} +% {\tt abs(}$x${\tt)}&$|x|$, absolute value of $x$\\ +% {\tt atan(}$x${\tt)}&$\arctan x$, principal value of the arc tangent of +% $x$ (in radians)\\ +% {\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, principal value of the +% arc tangent of $y/x$ (in radians). In this case the signs of both +% arguments $y$ and $x$ are used to determine the quadrant of the +% resultant value\\ +% {\tt card(}$X${\tt)}&$|X|$, cardinality (the number of elements) of +% set $X$\\ +% {\tt ceil(}$x${\tt)}&$\lceil x\rceil$, smallest integer not less than +% $x$ (``ceiling of $x$'')\\ +% {\tt cos(}$x${\tt)}&$\cos x$, cosine of $x$ (in radians)\\ +% {\tt exp(}$x${\tt)}&$e^x$, base-$e$ exponential of $x$\\ +% {\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, largest integer not greater +% than $x$ (``floor of $x$'')\\ +% {\tt gmtime()}&the number of seconds elapsed since 00:00:00~Jan~1, 1970, +% Coordinated Universal Time (for details see Section \ref{gmtime}, +% page \pageref{gmtime})\\ +% {\tt length(}$s${\tt)}&$|s|$, length of character string $s$\\ +% {\tt log(}$x${\tt)}&$\log x$, natural logarithm of $x$\\ +% {\tt log10(}$x${\tt)}&$\log_{10}x$, common (decimal) logarithm of $x$\\ +% {\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the largest +% of values $x_1$, $x_2$, \dots, $x_n$\\ +% {\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the smallest +% of values $x_1$, $x_2$, \dots, $x_n$\\ +% {\tt round(}$x${\tt)}&rounding $x$ to nearest integer\\ +% {\tt round(}$x${\tt,} $n${\tt)}&rounding $x$ to $n$ fractional decimal +% digits\\ +% {\tt sin(}$x${\tt)}&$\sin x$, sine of $x$ (in radians)\\ +% {\tt sqrt(}$x${\tt)}&$\sqrt{x}$, non-negative square root of $x$\\ +% {\tt str2time(}$s${\tt,} $f${\tt)}&converting character string $s$ to +% calendar time (for details see Section \ref{str2time}, page +% \pageref{str2time})\\ +% {\tt trunc(}$x${\tt)}&truncating $x$ to nearest integer\\ +% {\tt trunc(}$x${\tt,} $n${\tt)}&truncating $x$ to $n$ fractional +% decimal digits\\ +% {\tt Irand224()}&generating pseudo-random integer uniformly distributed +% in $[0,2^{24})$\\ +% {\tt Uniform01()}&generating pseudo-random number uniformly distributed +% in $[0,1)$\\ +% {\tt Uniform(}$a${\tt,} $b${\tt)}&generating pseudo-random number +% uniformly distributed in $[a,b)$\\ +% {\tt Normal01()}&generating Gaussian pseudo-random variate with +% $\mu=0$ and $\sigma=1$\\ +% {\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generating Gaussian +% pseudo-random variate with given $\mu$ and $\sigma$\\ +% \end{tabular} + +Os argumentos de todas as funções internas, exceto {\tt card}, {\tt length}, +e {\tt str2time}, devem ser \linebreak expressões numéricas. O argumento de +{\tt card} deve ser uma expressão de conjunto. O argumento de {\tt length} e +ambos argumentos de {\tt str2time} devem ser expressões simbólicas. + +O valor resultante da expressão numérica, que é uma função de referência, +é o resultado da aplicação da função ao(s) seu(s) argumento(s). + +Note que cada função geradora de números pseudo-aleatórios possui um argumento +latente (i.e., algum estado interno), que é alterado sempre que função é aplicada. +Assim, se a função é aplicada repetidamente mesmos aos argumentos idênticos, +devido ao efeito secundário, sempre se produzirão valores resultantes diferentes. + +% Arguments of all built-in functions, except {\tt card}, {\tt length}, +% and {\tt str2time}, should be numeric expressions. The argument of +% {\tt card} should be a set expression. The argument of {\tt length} and +% both arguments of {\tt str2time} should be symbolic expressions. +% +% The resultant value of the numeric expression, which is a function +% reference, is the result of applying the function to its argument(s). +% +% Note that each pseudo-random generator function has a latent argument +% (i.e. some internal state), which is changed whenever the function has +% been applied. Thus, if the function is applied repeatedly even to +% identical arguments, due to the side effect different resultant values +% are always produced. +\newpage + +\subsection{Expressões iteradas} +\label{itexpr} + +Uma {\it expressão numérica iterada} é uma expressão numérica primária, +que possui a seguinte forma sintática: +$$\mbox{\it operador-iterado expressão-indexada integrando}$$ +onde o {\it operador-iterado} é o nome simbólico do operador de iteração +a ser executado (veja abaixo), {\it expressão-indexada} é uma +expressão indexada que introduz índices e controla a iteração e +{\it integrando} é uma expressão numérica que participa da operação. + +\noindent +Em MathProg existem quatro operadores iterados, que podem ser usados +em expressões numéricas: + +% An {\it iterated numeric expression} is a primary numeric expression, +% which has the following syntactic form: +% $$\mbox{\it iterated-operator indexing-expression integrand}$$ +% where {\it iterated-operator} is the symbolic name of the iterated +% operator to be performed (see below), {\it indexing-expression} is an +% indexing expression which introduces dummy indices and controls +% iterating, {\it integrand} is a numeric expression that participates in +% the operation. +% +% In MathProg there exist four iterated operators, which may be used in +% numeric expressions: + +{\def\arraystretch{2} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt sum}&somatório&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt prod}&produtório&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt min}&mínimo&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt max}&máximo&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +\end{tabular} +} + +% {\def\arraystretch{2} +% \noindent\hfil +% \begin{tabular}{@{}lll@{}} +% {\tt sum}&summation&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +% f(i_1,\dots,i_n)$\\ +% {\tt prod}&production&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +% f(i_1,\dots,i_n)$\\ +% {\tt min}&minimum&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +% f(i_1,\dots,i_n)$\\ +% {\tt max}&maximum&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +% f(i_1,\dots,i_n)$\\ +% \end{tabular} +% } + +\noindent onde $i_1$, \dots, $i_n$ são índices introduzidos nas +expressões indexadas, $\Delta$ é o domínio, um conjunto de $n$-tuplas +especificado pela expressão indexada que define valores particulares +atribuído aos índices ao executar a operação iterada e +$f(i_1,\dots,i_n)$ é o integrando, uma expressão numérica cujo valor +resultante depende dos índices. + +O valor resultante de uma expressão numérica iterada é o resultado da aplicação +do operador iterado ao seu integrando por todas as $n$-tuplas +contidas no domínio. + +% \noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +% the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +% specified by the indexing expression which defines particular values +% assigned to the dummy indices on performing the iterated operation, +% $f(i_1,\dots,i_n)$ is the integrand, a numeric expression whose +% resultant value depends on the dummy indices. +% +% The resultant value of an iterated numeric expression is the result of +% applying of the iterated operator to its integrand over all $n$-tuples +% contained in the domain. + +\subsection{Expressões condicionais} +\label{ifthen} + +Uma {\it expressão numérica condicional} é uma expressão numérica primária +que possui uma das seguintes formas sintáticas: +% A {\it conditional numeric expression} is a primary numeric expression, +% which has one of the following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ +\mbox{{\tt if} $b$ {\tt then} $x$}\\ +\end{array} +} +$$ +onde $b$ é uma expressão lógica, enquanto que $x$ e $y$ são expressões numéricas. + +% where $b$ is an logical expression, $x$ and $y$ are numeric +% expressions. + + +O valor resultante da expressão condicional depende do valor da +expressão lógica que segue a palavra-chave {\tt if}. Se ela recebe +o valor {\it verdadeiro}, o valor da expressão condicional é o valor +da expressão que segue a palavra-chave {\tt then}. +Caso contrário, se a expressão lógica recebe o valor {\it falso}, +o valor da expressão condicional é o valor da expressão que segue +a palavra-chave {\it else}. Se ocorre a segunda forma sintática +da expressão condicional, a reduzida, e a expressão lógica recebe o valor +{\it falso}, então o valor resultante da expressão condicional é zero. + +% The resultant value of the conditional expression depends on the value +% of the logical expression that follows the keyword {\tt if}. If it +% takes on the value {\it true}, the value of the conditional expression +% is the value of the expression that follows the keyword {\tt then}. +% Otherwise, if the logical expression takes on the value {\it false}, +% the value of the conditional expression is the value of the expression +% that follows the keyword {\it else}. If the second, reduced form of the +% conditional expression is used and the logical expression takes on the +% value {\it false}, the resultant value of the conditional expression is +% zero. + +\newpage + +\subsection{Expressões parentizadas} + +Qualquer expressão numérica pode ser cercada por parênteses, o que as +torna sintaticamente uma expressão numérica primária. + +Parênteses podem ser usados em expressões numéricas, como em álgebra, para +especificar a ordem desejada na qual as operações devem ser realizadas. +Quando se usam parênteses, a expressão entre parênteses é avaliada +antes e seu o valor resultante é usado. + +O valor resultante de uma expressão parentizada é o mesmo +valor de uma expressão cercada entre parênteses. + +% Any numeric expression may be enclosed in parentheses that +% syntactically makes it a primary numeric expression. +% +% Parentheses may be used in numeric expressions, as in algebra, to +% specify the desired order in which operations are to be performed. +% Where parentheses are used, the expression within the parentheses is +% evaluated before the resultant value is used. +% +% The resultant value of the parenthesized expression is the same as the +% value of the expression enclosed within parentheses. + +\subsection{Operadores aritméticos} + +Em MathProg exitem os seguintes operadores aritméticos, que podem ser +usados em expressões numéricas: + +% In MathProg there exist the following arithmetic operators, which may +% be used in numeric expressions: + +\begin{tabular}{@{}ll@{}} +{\tt +} $x$&mais unário\\ +{\tt -} $x$&menos unário\\ +$x$ {\tt +} $y$&adição\\ +$x$ {\tt -} $y$&subtração\\ +$x$ {\tt less} $y$&diferença positiva (se $x1$, a segunda forma deve ser usada. + +% The number of indices in the indexing entry should be the same as the +% dimension of the basic set $S$, i.e. if $S$ consists of 1-tuples, the +% first form should be used, and if $S$ consists of $n$-tuples, where +% $n>1$, the second form should be used. + +Se a primeira forma da entrada indexante é usada, o índice $i$ pode ser +apenas um índice (veja mais adiante). Se a segunda forma é utilizada, os índices +$i_1$, $i_2$, \dots, $i_n$ podem ser tanto índices como alguma expressão numérica +ou simbólica, em que pelo menos um dos índices deve ser um índice. +Na terceira, a forma reduzida da entrada indexante possui o mesmo efeito +se houver $i$ (se $S$ é 1-dimensional) ou +$i_1$, $i_2$, \dots, $i_n$ (se $S$ é $n$-dimensional) onde todos são especificados +como índices. + +% If the first form of the indexing entry is used, the index $i$ can be +% a dummy index only (see below). If the second form is used, the indices +% $i_1$, $i_2$, \dots, $i_n$ can be either dummy indices or some numeric +% or symbolic expressions, where at least one index should be a dummy +% index. The third, reduced form of the indexing entry has the same +% effect as if there were $i$ (if $S$ is 1-dimensional) or +% $i_1$, $i_2$, \dots, $i_n$ (if $S$ is $n$-dimensional) all specified as +% dummy indices. + +Um {\it índice} é um objeto auxiliar do modelo, que atua como uma +variável individual. Os valores atribuídos aos índices são componentes +das $n$-tuplas dos conjuntos básicos, i.e., algumas quantidades +numéricas e simbólicas. + +% A {\it dummy index} is an auxiliary model object, which acts like an +% individual variable. Values assigned to dummy indices are components of +% $n$-tuples from basic sets, i.e. some numeric and symbolic quantities. + +Com propósitos de referência, índices podem ter nomes simbólicos. +No entanto, diferentemente de outros objetos de modelo (conjuntos, +parâmetros, etc.) índices não precisam ser \linebreak explicitamente declarados. +Cada nome simbólico {\it não-declarado} usado na posição indexante de +uma entrada indexante é reconhecida como o nome simbólico do índice +correspondente. + +% For referencing purposes dummy indices can be provided with symbolic +% names. However, unlike other model objects (sets, parameters, etc.) +% dummy indices need not be explicitly declared. Each {\it undeclared} +% symbolic name being used in the indexing position of an indexing entry +% is recognized as the symbolic name of corresponding dummy index. + +Os nomes simbólicos dos índices são válidos somente dentro do escopo +da expressão indexante, onde o índice foi inserido. Além do escopo, +os índices são completamente inacessíveis, de modo que os mesmos +nomes simbólicos podem ser usados para outros propósitos, em particular, +para representar índices em outras expressões indexantes. + +% Symbolic names of dummy indices are valid only within the scope of the +% indexing expression, where the dummy indices were introduced. Beyond +% the scope the dummy indices are completely inaccessible, so the same +% symbolic names may be used for other purposes, in particular, to +% represent dummy indices in other indexing expressions. + +O escopo da expressão indexante, em que declarações implícitas de índices +são válidas, depende do contexto em que a expressão indexante é usada: + +% The scope of indexing expression, where implicit declarations of dummy +% indices are valid, depends on the context, in which the indexing +% expression is used: + +\vspace*{-8pt} + +\begin{itemize} +\item Se a expressão indexante é usada em um operador-iterado, seu +escopo se estende até o final do integrando. +\item Se a expressão indexante é usada como uma expressão de conjunto +primária, seu escopo de estende até o final desta expressão indexante. +\item Se a expressão indexante é usada para definir o domínio do subíndice +na declaração de alguns objetos de modelo, seu escopo se estende até o +final da declaração correspondente. +\end{itemize} + +% \begin{itemize} +% \item If the indexing expression is used in iterated operator, its +% scope extends until the end of the integrand. +% \item If the indexing expression is used as a primary set expression, +% its scope extends until the end of that indexing expression. +% \item If the indexing expression is used to define the subscript domain +% in declarations of some model objects, its scope extends until the end +% of the corresponding statement. +% \end{itemize} + +\vspace*{-8pt} + +O mecanismo de indexação implementado para indexar expressões é melhor +explicado por alguns exemplos discutidos abaixo. + +Sejam três conjuntos: +% The indexing mechanism implemented by means of indexing expressions is +% best explained by some examples discussed below. +% +% Let there be given three sets: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +A=\{4,7,9\},\\ +B=\{(1,Jan),(1,Fev),(2,Mar),(2,Abr),(3,Mai),(3,Jun)\},\\ +C=\{a,b,c\},\\ +\end{array} +} +$$ +% $$ +% {\def\arraystretch{1.4} +% \begin{array}{l} +% A=\{4,7,9\},\\ +% B=\{(1,Jan),(1,Feb),(2,Mar),(2,Apr),(3,May),(3,Jun)\},\\ +% C=\{a,b,c\},\\ +% \end{array} +% } +% $$ +onde $A$ e $C$ consistem de 1-tuplas (singletos), $B$ consiste de +2-tuplas (dobletes). Considere a seguinte expressão indexante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +onde {\tt i}, {\tt j}, {\tt k}, e {\tt l} são índices. + +% where $A$ and $C$ consist of 1-tuples (singlets), $B$ consists of +% 2-tuples (doublets). Consider the following indexing expression: +% $$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +% where {\tt i}, {\tt j}, {\tt k}, and {\tt l} are dummy indices. + +\newpage + +Embora MathProg não seja uma linguagem procedural, para qualquer +expressão indexante uma descrição algorítmica equivalente pode ser dada. +Em particular, a descrição algorítmica da expressão indexante acima +poderia ser vista como segue: + +% Although MathProg is not a procedural language, for any indexing +% expression an equivalent algorithmic description can be given. In +% particular, the algorithmic description of the indexing expression +% above could look like follows: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf faça}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf faça}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf faça}\\ +\hspace{48pt}{\it ação};\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}l@{}} +% {\bf for all} $i\in A$ {\bf do}\\ +% \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +% \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +% \hspace{48pt}{\it action};\\ +% \end{tabular} + +\noindent onde os índices $i$, $j$, $k$, $l$ são consecutivamente +atribuídos aos componentes correspondentes das $n$-tuplas dos conjuntos +básicos $A$, $B$, $C$, e {\it ação} é alguma ação que dependa do contexto +no qual a expressão indexante é usada. Por exemplo, se a ação fosse +imprimir os valores atuais dos índices, a impressão seria vista como segue: + +% \noindent where the dummy indices $i$, $j$, $k$, $l$ are consecutively +% assigned corresponding components of $n$-tuples from the basic sets $A$, +% $B$, $C$, and {\it action} is some action that depends on the context, +% where the indexing expression is used. For example, if the action were +% printing current values of dummy indices, the printout would look like +% follows: + +\noindent\hfil +\begin{tabular}{@{}llll@{}} +$i=4$&$j=1$&$k=Jan$&$l=a$\\ +$i=4$&$j=1$&$k=Jan$&$l=b$\\ +$i=4$&$j=1$&$k=Jan$&$l=c$\\ +$i=4$&$j=1$&$k=Fev$&$l=a$\\ +$i=4$&$j=1$&$k=Fev$&$l=b$\\ +\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +$i=9$&$j=3$&$k=Jun$&$l=b$\\ +$i=9$&$j=3$&$k=Jun$&$l=c$\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}llll@{}} +% $i=4$&$j=1$&$k=Jan$&$l=a$\\ +% $i=4$&$j=1$&$k=Jan$&$l=b$\\ +% $i=4$&$j=1$&$k=Jan$&$l=c$\\ +% $i=4$&$j=1$&$k=Feb$&$l=a$\\ +% $i=4$&$j=1$&$k=Feb$&$l=b$\\ +% \multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +% $i=9$&$j=3$&$k=Jun$&$l=b$\\ +% $i=9$&$j=3$&$k=Jun$&$l=c$\\ +% \end{tabular} + +Seja o exemplo da expressão indexante usado na seguinte +operação iterada: +$$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +onde {\tt p} é uma parâmetro numérico 4-dimensional ou alguma +expressão numérica cujo valor resultante dependa de +{\tt i}, {\tt j}, {\tt k} e {\tt l}. Neste caso, a ação é o somatório, +de forma que o valor resultante da expressão numérica primária é: +$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +% Let the example indexing expression be used in the following iterated +% operation: +% $$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +% where {\tt p} is a 4-dimensional numeric parameter or some numeric +% expression whose resultant value depends on {\tt i}, {\tt j}, {\tt k}, +% and {\tt l}. In this case the action is summation, so the resultant +% value of the primary numeric expression is: +% $$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +Agora seja a expressão indexante do exemplo usada como uma expressão +de conjunto primária. Neste caso, a ação é reunir todas as 4-tuplas +(quádruplas) da forma $(i,j,k,l)$ em um conjunto, de forma que o +valor resultante de tal operação é simplesmente o produto +Cartesiano dos conjuntos básicos: +$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +Note que neste caso, a mesma expressão indexante pode ser escrita +na forma reduzida: +$$\mbox{{\tt\{A, B, C\}}}$$ +pois os índices $i$, $j$, $k$ e $l$ não são referenciados, portanto, +seus nomes simbólicos não precisam ser especificados. + +% Now let the example indexing expression be used as a primary set +% expression. In this case the action is gathering all 4-tuples +% (quadruplets) of the form $(i,j,k,l)$ in one set, so the resultant +% value of such operation is simply the Cartesian product of the basic +% sets: +% $$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +% Note that in this case the same indexing expression might be written in +% the reduced form: +% $$\mbox{{\tt\{A, B, C\}}}$$ +% because the dummy indices $i$, $j$, $k$, and $l$ are not referenced and +% therefore their symbolic names need not be specified. + +\newpage + +Finalmente, seja a expressão indexante do exemplo usada como o domínio do +subíndice na declaração de um objeto de modelo 4-dimensional, por exemplo, +um parâmetro numérico: +% Finally, let the example indexing expression be used as the subscript +% domain in the declaration of a 4-dimensional model object, say, +% a numeric parameter: +$$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ + +\noindent Neste caso, a ação é gerar os membros do parâmetro, +onde cada membro possui a forma $p[i,j,k,l]$. + +% \noindent In this case the action is generating the parameter members, +% where each member has the form $p[i,j,k,l]$. + +Como mencionado anteriormente, alguns índices da segunda forma das entradas +indexantes podem ser expressões numéricas ou simbólicas, não apenas índices. +Neste caso, os valores resultantes destas expressões desempenham o papel +de algumas condições lógicas para selecionar apenas aquelas $n$-tuplas +do produto Cartesiano dos conjuntos básicos que satisfaçam estas +condições. + +% As was said above, some indices in the second form of indexing entries +% may be numeric or symbolic expressions, not only dummy indices. In this +% case resultant values of such expressions play role of some logical +% conditions to select only that $n$-tuples from the Cartesian product of +% basic sets that satisfy these conditions. + +Considere, por exemplo, a seguinte expressão indexante: +$$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +onde {\tt i}, {\tt k} e {\tt l} são índices, e {\tt i-1} é uma +expressão numérica. A descrição algorítmica desta expressão +indexante é a seguinte: + +% Consider, for example, the following indexing expression: +% $$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +% where {\tt i}, {\tt k}, {\tt l} are dummy indices, and {\tt i-1} is +% a numeric expression. The algorithmic decsription of this indexing +% expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf faça}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf e} $j=i-1$ {\bf faça}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf faça}\\ +\hspace{48pt}{\it ação};\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}l@{}} +% {\bf for all} $i\in A$ {\bf do}\\ +% \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf and} $j=i-1$ {\bf do}\\ +% \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +% \hspace{48pt}{\it action};\\ +% \end{tabular} + +\noindent Assim, se esta expressão indexante fosse usada como uma expressão de conjunto +primária, o conjunto resultante seira o seguinte: +$$\{(4,Mai,a),(4,Mai,b),(4,Mai,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +Deve-se notar que neste caso o conjunto resultante consiste em 3-tuplas, +e não de 4-tuplas, porque na expressão indexante não há índice que +corresponda ao primeiro componente das 2-tuplas do conjunto $B$. + +% \noindent Thus, if this indexing expression were used as a primary set +% expression, the resultant set would be the following: +% $$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +% Should note that in this case the resultant set consists of 3-tuples, +% not of 4-tuples, because in the indexing expression there is no dummy +% index that corresponds to the first component of 2-tuples from the set +% $B$. + +A regra geral é: o número de componentes de $n$-tuplas definido por +uma expressão indexante é o mesmo do número de índices naquela expressão, +onde a correspondência entre índices e componentes nas $n$-tuplas no +conjunto resultante é posicional, i.e., o primeiro índice corresponde +ao primeiro componente, o segundo índice corresponde ao segundo +componente, etc. + +% The general rule is: the number of components of $n$-tuples defined by +% an indexing expression is the same as the number of dummy indices in +% that expression, where the correspondence between dummy indices and +% components on $n$-tuples in the resultant set is positional, i.e. the +% first dummy index corresponds to the first component, the second dummy +% index corresponds to the second component, etc. + +Em alguns casos é necessário selecionar um subconjunto do produto +Cartesiano de alguns \linebreak conjuntos. Isto pode ser alcançado mediante o +emprego de um predicado lógico opcional, que é especificado na +expressão indexante. + +% In some cases it is needed to select a subset from the Cartesian +% product of some sets. This may be attained by using an optional logical +% predicate, which is specified in the indexing expression. + +Considere, por exemplo, a seguinte expressão indexante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +onde a expressão lógica após os dois pontos é um predicado. A +descrição algorítmica desta expressão indexante é a seguinte: + +% Consider, for example, the following indexing expression: +% $$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +% where the logical expression following the colon is a predicate. The +% algorithmic description of this indexing expression is the following: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf faça}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf faça}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf faça}\\ +\hspace{48pt}{\bf se} $i\leq 5$ {\bf e} $k\neq`Mar'$ {\bf então}\\ +\hspace{64pt}{\it ação};\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}l@{}} +% {\bf for all} $i\in A$ {\bf do}\\ +% \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ +% \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ +% \hspace{48pt}{\bf if} $i\leq 5$ {\bf and} $k\neq`Mar'$ {\bf then}\\ +% \hspace{64pt}{\it action};\\ +% \end{tabular} + +\noindent Assim, se a expressão indexante fosse usada como uma +expressão de conjunto primária, o conjunto resultante seria o seguinte: +$$\{(4,1,Jan,a),(4,1,Fev,a),(4,2,Abr,a),\dots,(4,3,Jun,c)\}.$$ + +Se o predicado não é especificado na expressão indexante assume-se um, +que recebe o valor {\it verdadeiro}. + +% \noindent Thus, if this indexing expression were used as a primary set +% expression, the resultant set would be the following: +% $$\{(4,1,Jan,a),(4,1,Feb,a),(4,2,Apr,a),\dots,(4,3,Jun,c)\}.$$ +% +% If no predicate is specified in the indexing expression, one, which +% takes on the value {\it true}, is assumed. + +\section{Expressões de conjunto} + +Uma {\it expressão de conjunto} é uma regra para calcular um conjunto +elementar, i.e., uma coleção de $n$-tuplas, onde os componentes das +$n$-tuplas são quantidades numéricas e simbólicas. + +% A {\it set expression} is a rule for computing an elemental set, i.e. +% a collection of $n$-tuples, where components of $n$-tuples are numeric +% and symbolic quantities. + +A expressão de conjunto primária pode ser um conjunto de literais, um conjunto +não-indexado, um conjunto indexado, um conjunto ``aritmético'', uma expressão +indexante, uma expressão de \linebreak conjunto iterada, uma expressão de conjunto +condicional ou outra expressão cercada por \linebreak parênteses. + +\para{Exemplos} + +% The primary set expression may be a literal set, unsubscripted set, +% subscripted set, ``arithmetic'' set, indexing expression, iterated set +% expression, conditional set expression, or another set expression +% enclosed in parentheses. +% +% \para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(conjunto de literais)\\ +\verb|I| &(conjunto não-indexado)\\ +\verb|S[i-1,j+1]| &(conjunto indexado)\\ +\verb|1..t-1 by 2| &(conjunto ``aritmético'')\\ +\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(expressão indexante)\\ +\verb|setof{i in I, j in J}(i+1,j-1)| &(expressão de conjunto iterado)\\ +\verb|if i < j then S[i,j] else F diff S[i,j]| &(expressão de conjunto +condicional)\\ +\verb|(1..10 union 21..30)| &(expressão de conjunto parentizado)\\ +\end{tabular} + +% \noindent +% \begin{tabular}{@{}ll@{}} +% \verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(literal set)\\ +% \verb|I| &(unsubscripted set)\\ +% \verb|S[i-1,j+1]| &(subscripted set)\\ +% \verb|1..t-1 by 2| &(``arithmetic'' set)\\ +% \verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(indexing expression)\\ +% \verb|setof{i in I, j in J}(i+1,j-1)| &(iterated set expression)\\ +% \verb|if i < j then S[i,j] else F diff S[i,j]| &(conditional set +% expression)\\ +% \verb|(1..10 union 21..30)| &(parenthesized set expression)\\ +% \end{tabular} + +Expressões de conjuntos mais genéricas contendo duas ou mais expressões +de conjunto primárias podem ser construídas usando operadores +específicos de conjunto . + +\para{Exemplos} + +% More general set expressions containing two or more primary set +% expressions may be constructed by using certain set operators. +% +% \para{Examples} + +\begin{verbatim} +(A union B) inter (I cross J) +1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) +\end{verbatim} + +\subsection{Conjuntos de literais} + +Um {\it conjunto de literais} é uma expressão de conjunto primária +que possui as duas formas \linebreak sintáticas seguintes: +% A {\it literal set} is a primary set expression, which has the +% following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +\mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +\end{array} +} +$$ +% $$ +% {\def\arraystretch{1.4} +% \begin{array}{l} +% \mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +% \mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +% {\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +% {\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +% \end{array} +% } +% $$ +onde $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ são expressões +numéricas ou simbólicas. + +Se a primeira forma é adotada, o conjunto resultante consiste +de 1-tuplas (singletos) enumerados entre as chaves. +É permitido especificar um conjunto vazio como {\tt\{\ \}}, +que não possui 1-tuplas. Se a segunda forma é adotada, +o conjunto resultante consiste de $n$-tuplas enumeradas entre as chaves, +onde uma $n$-tupla particular consiste nos componentes correspondentes +enumerados entre parênteses. Todas as $n$-tuplas devem ter o mesmo +número de componentes. + +% where $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ are numeric or +% symbolic expressions. +% +% If the first form is used, the resultant set consists of 1-tuples +% (singlets) enumerated within the curly braces. It is allowed to specify +% an empty set as {\tt\{\ \}}, which has no 1-tuples. If the second form +% is used, the resultant set consists of $n$-tuples enumerated within the +% curly braces, where a particular $n$-tuple consists of corresponding +% components enumerated within the parentheses. All $n$-tuples should +% have the same number of components. + +\subsection{Conjuntos não-indexados} + +Se a expressão de conjunto primária é um conjunto não-indexado +(que deve ser 0-dimensional), o conjunto resultante é um conjunto +elementar associado com o objeto conjunto correspondente. + +% If the primary set expression is an unsubscripted set (which should be +% 0-dimen\-sional), the resultant set is an elemental set associated with +% the corresponding set object. + +\subsection{Conjuntos indexados} + +A expressão de conjunto primária, que se refere a um conjunto indexado, +tem a seguinte forma sintática: +$$\mbox{{\it nome}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +onde {\it nome} é o nome simbólico do objeto conjunto e $i_1$, $i_2$, +\dots, $i_n$ são subíndices. + +% The primary set expression, which refers to a subscripted set, has the +% following syntactic form: +% $$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +% $i_n${\tt]}}$$ +% where {\it name} is the symbolic name of the set object, $i_1$, $i_2$, +% \dots, $i_n$ are subscripts. + +Cada subíndice deve ser uma expressão numérica ou simbólica. O número de +subíndices nas lista de subíndices deve ser o mesmo da dimensão do objeto +conjunto com o qual as lista de subíndice está associada. + +Os valores correntes das expressões de subíndices são usados para identificar +um membro \linebreak particular do objeto conjunto que determina o conjunto resultante. + +% Each subscript should be a numeric or symbolic expression. The number +% of subscripts in the subscript list should be the same as the dimension +% of the set object with which the subscript list is associated. +% +% Actual values of subscript expressions are used to identify a +% particular member of the set object that determines the resultant set. + +\subsection{Conjuntos ``aritméticos''} + +A expressão de conjunto primária que constitui um conjunto ``aritmético'', +possui as duas formas sintáticas seguintes: +% The primary set expression, which is an ``arithmetic'' set, has the +% following two syntactic forms: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +\mbox{$t_0$ {\tt..} $t_1$}\\ +\end{array} +} +$$ +onde $t_0$, $t_1$, e $\delta t$ são expressões numéricas (o valor de +$\delta t$ não deve ser zero). A segunda forma é equivalente a primeira +forma, onde $\delta t=1$. + +Se $\delta t>0$, o conjunto resultante é determinado como segue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +Caso contrário, se $\delta t<0$, o conjunto resultante é determinado como segue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ +% $$ +% {\def\arraystretch{1.4} +% \begin{array}{l} +% \mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +% \mbox{$t_0$ {\tt..} $t_1$}\\ +% \end{array} +% } +% $$ +% where $t_0$, $t_1$, and $\delta t$ are numeric expressions (the value +% of $\delta t$ should not be zero). The second form is equivalent to the +% first form, where $\delta t=1$. +% +% If $\delta t>0$, the resultant set is determined as follows: +% $$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +% Otherwise, if $\delta t<0$, the resultant set is determined as follows: +% $$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ + +\subsection{Expressões indexantes} + +Se a expressão primária é uma expressão indexante, o conjunto resultante +é determinado como descrito anteriormente, na Seção \ref{indexing}, página +\pageref{indexing}. + +% If the primary set expression is an indexing expression, the resultant +% set is determined as described above in Section \ref{indexing}, page +% \pageref{indexing}. + +\newpage + +\subsection{Expressões iteradas} + +Uma {\it expressão de conjunto iterada} é uma expressão de conjunto +primária, que possui a seguinte forma sintática: +$$\mbox{{\tt setof} {\it expressão-indexante} {\it integrando}}$$ +onde {\it expressão-indexante} é uma expressão indexante, que +introduz índices e controla a iteração, {\it integrando} é +tanto uma expressão numérica ou simbólica individual, como uma +lista de expressões numéricas ou simbólicas separadas por vírgula +e cercadas entre parênteses. + +% An {\it iterated set expression} is a primary set expression, which has +% the following syntactic form: +% $$\mbox{{\tt setof} {\it indexing-expression} {\it integrand}}$$ +% where {\it indexing-expression} is an indexing expression, which +% introduces dummy indices and controls iterating, {\it integrand} is +% either a single numeric or symbolic expression or a list of numeric and +% symbolic expressions separated by commae and enclosed in parentheses. + +Se o integrando é uma expressão numérica ou simbólica individual, o +conjunto resultante consiste de 1-tuplas, sendo determinado como segue: +$$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +\noindent onde $x$ é um valor do integrando, $i_1$, \dots, $i_n$ +são índices introduzidos na expressão indexante, $\Delta$ é +o domínio, um conjunto de $n$-tuplas especificado pela expressão +indexante que define valores particulares atribuídos aos índices ao +realizar a operação de iteração. + +% If the integrand is a single numeric or symbolic expression, the +% resultant set consists of 1-tuples and is determined as follows: +% $$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +% \noindent where $x$ is a value of the integrand, $i_1$, \dots, $i_n$ +% are dummy indices introduced in the indexing expression, $\Delta$ is +% the domain, a set of $n$-tuples specified by the indexing expression, +% which defines particular values assigned to the dummy indices on +% performing the iterated operation. + +Se o integrando é uma lista contendo $m$ expressões numéricas e simbólicas, +o conjunto resultante consiste de $m$-tuplas, sendo determinado +como segue: +$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +onde $x_1$, \dots, $x_m$ são valores das expressões na lista +de integrandos, $i_1$, \dots, $i_n$ e $\Delta$ possuem o mesmo significado +anterior. + +% If the integrand is a list containing $m$ numeric and symbolic +% expressions, the resultant set consists of $m$-tuples and is determined +% as follows: +% $$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +% where $x_1$, \dots, $x_m$ are values of the expressions in the +% integrand list, $i_1$, \dots, $i_n$ and $\Delta$ have the same meaning +% as above. + +\subsection{Expressões condicionais} + +Uma {\it expressão de conjunto condicional} é uma expressão de conjunto +primária que possui a seguinte forma sintática: +$$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +onde $b$ é uma expressão lógica, $X$ e $Y$ são expressões de conjunto, +que devem definir conjuntos da mesma dimensão. + +% A {\it conditional set expression} is a primary set expression that has +% the following syntactic form: +% $$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +% where $b$ is an logical expression, $X$ and $Y$ are set expressions, +% which should define sets of the same dimension. + +O valor resultante da expressão condicional depende do valor da +expressão lógica que segue a palavra-chave {\tt if}. Se ela recebe +o valor {\it verdadeiro}, o conjunto resultante é o valor da expressão +que segue a palavra-chave {\tt then}. Caso contrário, se a +expressão lógica recebe o valor {\it falso}, o conjunto resultante é +o valor da expressão que segue a palavra-chave {\tt else}. + +% The resultant value of the conditional expression depends on the value +% of the logical expression that follows the keyword {\tt if}. If it +% takes on the value {\it true}, the resultant set is the value of the +% expression that follows the keyword {\tt then}. Otherwise, if the +% logical expression takes on the value {\it false}, the resultant set is +% the value of the expression that follows the keyword {\tt else}. + +\subsection{Expressões parentizadas} + +Qualquer expressão de conjunto pode ser cercada entre parênteses, o que as tornam +\linebreak sintaticamente uma expressão de conjunto primária. +Parênteses podem ser usados em expressões de conjunto, como em álgebra, para +especificar a ordem desejada nas quais as operações devem ser executadas. +Quando se usam parênteses, a expressão entre parênteses é avaliada +antes que o valor resultante seja usado. +O valor resultante de uma expressão parentizada é idêntico ao valor da expressão +cercada entre parênteses. + +% Any set expression may be enclosed in parentheses that syntactically +% makes it a primary set expression. +% +% Parentheses may be used in set expressions, as in algebra, to specify +% the desired order in which operations are to be performed. Where +% parentheses are used, the expression within the parentheses is +% evaluated before the resultant value is used. +% +% The resultant value of the parenthesized expression is the same as the +% value of the expression enclosed within parentheses. + +\newpage + +\subsection{Operadores de conjunto} + +Em MathProg existem os seguintes operadores de conjunto, que podem ser +usados em expressões de conjunto: + +% In MathProg there exist the following set operators, which may be used +% in set expressions: + +\begin{tabular}{@{}ll@{}} +$X$ {\tt union} $Y$&união $X\cup Y$\\ +$X$ {\tt diff} $Y$&diferença $X\backslash Y$\\ +$X$ {\tt symdiff} $Y$&diferença simétrica +$X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +$X$ {\tt inter} $Y$&interseção $X\cap Y$\\ +$X$ {\tt cross} $Y$&produto Cartesiano (cruzado) $X\times Y$\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% $X$ {\tt union} $Y$&union $X\cup Y$\\ +% $X$ {\tt diff} $Y$&difference $X\backslash Y$\\ +% $X$ {\tt symdiff} $Y$&symmetric difference +% $X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +% $X$ {\tt inter} $Y$&intersection $X\cap Y$\\ +% $X$ {\tt cross} $Y$&cross (Cartesian) product $X\times Y$\\ +% \end{tabular} + +\noindent onde $X$ e Y são expressões de conjunto, que devem definir conjuntos +de dimensões idênticas (exceto o produto Cartesiano). + +Se a expressão inclui mais de um operador de conjunto, todos operadores +são executados da esquerda para a direita de acordo com a hierarquia das +operações (veja adiante). + +O valor resultante da expressão, que contém operadores de conjunto, é +o resultado da aplicação dos operadores aos seus operandos. + +A dimensão do conjunto resultante, i.e., a dimensão das $n$-tuplas, +dos quais consistem o conjunto resultante, é a mesma da dimensão dos +operandos, exceto o produto Cartesiano, onde a dimensão do conjunto +resultante é a soma das dimensões dos seus operandos. + +% \noindent where $X$ and Y are set expressions, which should define sets +% of identical dimension (except the Cartesian product). +% +% If the expression includes more than one set operator, all operators +% are performed from left to right according to the hierarchy of +% operations (see below). +% +% The resultant value of the expression, which contains set operators, is +% the result of applying the operators to their operands. +% +% The dimension of the resultant set, i.e. the dimension of $n$-tuples, +% of which the resultant set consists of, is the same as the dimension of +% the operands, except the Cartesian product, where the dimension of the +% resultant set is the sum of the dimensions of its operands. + +\subsection{Hierarquia das operações} + +A lista seguinte mostra a hierarquia das operações em expressões de conjunto: + +% The following list shows the hierarchy of operations in set +% expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operação&Hierarquia\\ +\hline +Avaliação de operações numéricas& +1{\textsuperscript{\b{a}}}-7{\textsuperscript{\b{a}}}\\ +Avaliação de operações simbólicas& +8{\textsuperscript{\b{a}}}-9{\textsuperscript{\b{a}}}\\ +Avaliação de conjuntos iterados ou ``aritméticos'' ({\tt setof}, {\tt..})& +10{\textsuperscript{\b{a}}}\\ +Produto Cartesiano ({\tt cross})& +11{\textsuperscript{\b{a}}}\\ +Interseção ({\tt inter})& +12{\textsuperscript{\b{a}}}\\ +União e diferença ({\tt union}, {\tt diff}, {\tt symdiff})& +13{\textsuperscript{\b{a}}}\\ +Avaliação condicional ({\tt if} \dots {\tt then} \dots {\tt else})& +14{\textsuperscript{\b{a}}}\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}ll@{}} +% Operation&Hierarchy\\ +% \hline +% Evaluation of numeric operations&1st-7th\\ +% Evaluation of symbolic operations&8th-9th\\ +% Evaluation of iterated or ``arithmetic'' set ({\tt setof}, {\tt..})& +% 10th\\ +% Cartesian product ({\tt cross})&11th\\ +% Intersection ({\tt inter})&12th\\ +% Union and difference ({\tt union}, {\tt diff}, {\tt symdiff})&13th\\ +% Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& +% 14th\\ +% \end{tabular} + +Esta hierarquia possui o mesmo significado como explicado anteriormente +para expressões \linebreak numéricas (ver Subseção \ref{hierarchy}, página \pageref{hierarchy}). + +% This hierarchy has the same meaning as was explained above for numeric +% expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\newpage + +\section{Expressões lógicas} + +Uma {\it expressão lógica} é uma regra para calcular um valor lógico +individual, que pode ser {\it verdadeiro} ou {\it falso}. + +A expressão lógica primária pode ser uma expressão numérica, +uma expressão relacional, uma expressão lógica iterada ou +outra expressão lógica cercada entre parênteses. + +\para{Exemplos} + +% A {\it logical expression} is a rule for computing a single logical +% value, which can be either {\it true} or {\it false}. +% +% The primary logical expression may be a numeric expression, relational +% expression, iterated logical expression, or another logical expression +% enclosed in parentheses. +% +% \para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|i+1| &(expressão numérica)\\ +\verb|a[i,j] < 1.5| &(expressão relacional)\\ +\verb|s[i+1,j-1] <> 'Mar' & year | &(expressão relacional)\\ +\verb|(i+1,'Jan') not in I cross J| &(expressão relacional)\\ +\verb|S union T within A[i] inter B[j]| &(expressão relacional)\\ +\verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(expressão lógica iterada)\\ +\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(expressão lógica parentizada)\\ +\end{tabular} + +% \noindent +% \begin{tabular}{@{}ll@{}} +% \verb|i+1| &(numeric expression)\\ +% \verb|a[i,j] < 1.5| &(relational expression)\\ +% \verb|s[i+1,j-1] <> 'Mar' & year | &(relational expression)\\ +% \verb|(i+1,'Jan') not in I cross J| &(relational expression)\\ +% \verb|S union T within A[i] inter B[j]| &(relational expression)\\ +% \verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(iterated logical +% expression)\\ +% \verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(parenthesized logical +% expression)\\ +% \end{tabular} + +Expressões lógicas mais genéricas, contendo duas ou mais +expressões lógicas primárias, podem ser construídas usando +determinados operadores lógicos. + +\para{Exemplos} + +\begin{verbatim} +not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +(i,j) in S or (i,j) not in T diff U +\end{verbatim} + +% More general logical expressions containing two or more primary logical +% expressions may be constructed by using certain logical operators. +% +% \para{Examples} +% +% \begin{verbatim} +% not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +% (i,j) in S or (i,j) not in T diff U +% \end{verbatim} +\vspace*{-8pt} + +\subsection{Expressões numéricas} + +O valor resultante da expressão lógica primária, que é uma +expressão numérica, é {\it verdadeiro}, se o valor resultante da +expressão numérica é diferente de zero. Caso contrário o valor resultante +da expressão lógica é {\it falso}. + +% The resultant value of the primary logical expression, which is a +% numeric expression, is {\it true}, if the resultant value of the +% numeric expression is non-zero. Otherwise the resultant value of the +% logical expression is {\it false}. + +\vspace*{-8pt} + +\subsection{Operadores relacionais} + +Em MathProg existem os seguintes operadores relacionais, que podem +ser usados em expressões lógicas: + +% In MathProg there exist the following relational operators, which may +% be used in logical expressions: + +\begin{tabular}{@{}ll@{}} +$x$ {\tt<} $y$&verifica se $x=} $y$&verifica se $x\geq y$\\ +$x$ {\tt>} $y$&verifica se $x>y$\\ +$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&verifica se $x\neq y$\\ +$x$ {\tt in} $Y$&verifica se $x\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&verifica se +$(x_1,\dots,x_n)\in Y$\\ +$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&verifica se $x\not\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&verifica se +$(x_1,\dots,x_n)\not\in Y$\\ +$X$ {\tt within} $Y$&verifica se $X\subseteq Y$\\ +$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&verifica se +$X\not\subseteq Y$\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% $x$ {\tt<} $y$&test on $x=} $y$&test on $x\geq y$\\ +% $x$ {\tt>} $y$&test on $x>y$\\ +% $x$ {\tt<>} $y$, $x$ {\tt!=} $y$&test on $x\neq y$\\ +% $x$ {\tt in} $Y$&test on $x\in Y$\\ +% {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&test on +% $(x_1,\dots,x_n)\in Y$\\ +% $x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&test on $x\not\in Y$\\ +% {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +% {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&test on +% $(x_1,\dots,x_n)\not\in Y$\\ +% $X$ {\tt within} $Y$&test on $X\subseteq Y$\\ +% $X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&test on +% $X\not\subseteq Y$\\ +% \end{tabular} + +\noindent onde $x$, $x_1$, \dots, $x_n$, $y$ são expressões numéricas ou +simbólicas, $X$ e $Y$ são expressões de conjunto. + +% \noindent where $x$, $x_1$, \dots, $x_n$, $y$ are numeric or symbolic +% expressions, $X$ and $Y$ are set expression. + +\newpage + +1. Nas operações {\tt in}, {\tt not in} e {\tt !in} o número +de componentes nos primeiros operandos deve ser igual a +dimensão do segundo operando. + +2. Nas operações {\tt within}, {\tt not within} e {\tt !within} +ambos operandos devem ter a mesma dimensão. + +Todos operadores relacionais listados acima têm seus significados +matemáticos convencionais. O valor resultante é {\it verdadeiro}, se +a relação correspondente é satisfeita para seus operandos, caso contrário +é {\it falso}. (Note que valores simbólicos são ordenados de forma +lexicográfica e qualquer valor numérico precede qualquer valor simbólico.) + +% 1. In the operations {\tt in}, {\tt not in}, and {\tt !in} the +% number of components in the first operands should be the same as the +% dimension of the second operand. +% +% 2. In the operations {\tt within}, {\tt not within}, and {\tt !within} +% both operands should have identical dimension. +% +% All the relational operators listed above have their conventional +% mathematical meaning. The resultant value is {\it true}, if +% corresponding relation is satisfied for its operands, otherwise +% {\it false}. (Note that symbolic values are ordered lexicographically, +% and any numeric value precedes any symbolic value.) + +\subsection{Expressões iteradas} + +Uma {\it expressão lógica iterada} é uma expressão lógica primária +com a seguinte forma sintática: +$$\mbox{{\it operador-iterado} {\it expressão-indexante} +{\it integrando}}$$ +onde {\it operador-iterado} é o nome simbólico do operador iterado +a ser executado (veja adiante), {\it expressão-indexante} é uma +expressão indexante que introduz índices e controla a iteração, \linebreak +{\it integrando} é uma expressão numérica que participa da operação. + +Em MathProg existem dois operadores iterados que podem ser usados +em expressões lógicas: + +% An {\it iterated logical expression} is a primary logical expression, +% which has the following syntactic form: +% $$\mbox{{\it iterated-operator} {\it indexing-expression} +% {\it integrand}}$$ +% where {\it iterated-operator} is the symbolic name of the iterated +% operator to be performed (see below), {\it indexing-expression} is an +% indexing expression which introduces dummy indices and controls +% iterating, {\it integrand} is a numeric expression that participates in +% the operation. +% +% In MathProg there exist two iterated operators, which may be used in +% logical expressions: + +{\def\arraystretch{1.4} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt forall}&quantificador-$\forall$&$\displaystyle +\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +{\tt exists}&quantificador-$\exists$&$\displaystyle +\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +\end{tabular} +} + +% {\def\arraystretch{1.4} +% \noindent\hfil +% \begin{tabular}{@{}lll@{}} +% {\tt forall}&$\forall$-quantification&$\displaystyle +% \forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +% {\tt exists}&$\exists$-quantification&$\displaystyle +% \exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +% \end{tabular} +% } + +\noindent onde $i_1$, \dots, $i_n$ são índices introduzidos na +expressão indexante, $\Delta$ é o domínio, um conjunto de $n$-tuplas +especificado pela expressão indexante que define valores específicos +atribuídos aos índices ao executar a operação iterada, e +$f(i_1,\dots,i_n)$ é o integrando, uma expressão lógica cujo +valor resultante depende dos índices. + +Para o quantificador $\forall$, o valor resultante da expressão +lógica iterada é {\it verdadeiro}, se o valor do integrando é +{\it verdadeiro} para todas as $n$-tuplas contidas no domínio, +caso contrário, é {\it falso}. + +Para o quantificador $\exists$ o valor resultante da expressão +lógica iterada é {\it falso}, se o valor do integrando é +{\it falso} para todas as $n$-tuplas contidas no domínio, +caso contrário, é {\it verdadeiro}. + +% \noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in +% the indexing expression, $\Delta$ is the domain, a set of $n$-tuples +% specified by the indexing expression which defines particular values +% assigned to the dummy indices on performing the iterated operation, +% $f(i_1,\dots,i_n)$ is the integrand, a logical expression whose +% resultant value depends on the dummy indices. +% +% For $\forall$-quantification the resultant value of the iterated +% logical expression is {\it true}, if the value of the integrand is +% {\it true} for all $n$-tuples contained in the domain, otherwise +% {\it false}. +% +% For $\exists$-quantification the resultant value of the iterated +% logical expression is {\it false}, if the value of the integrand is +% {\it false} for all $n$-tuples contained in the domain, otherwise +% {\it true}. + +\subsection{Expressões parentizadas} + +Qualquer expressão lógica pode ser cercada entre parênteses, o que a +converte sintaticamente em uma expressão lógica primária. + +Parênteses podem ser usados em expressões lógicas, como em álgebra, para +especificar a ordem desejada na qual as operações devem ser executadas. +Quando se usam parênteses, a expressão entre parênteses é avaliada antes +que o valor resultante seja usado. + +O valor resultante da expressão parentizada é idêntico ao valor da expressão +cercada entre parênteses. + +% Any logical expression may be enclosed in parentheses that +% syntactically makes it a primary logical expression. +% +% Parentheses may be used in logical expressions, as in algebra, to +% specify the desired order in which operations are to be performed. +% Where parentheses are used, the expression within the parentheses is +% evaluated before the resultant value is used. +% +% The resultant value of the parenthesized expression is the same as the +% value of the expression enclosed within parentheses. + +\newpage + +\subsection{Operadores lógicos} + +Em MathProg existem os seguintes operadores lógicos, que podem ser usados em +expressões lógicas: + +% In MathProg there exist the following logical operators, which may be +% used in logical expressions: + +\begin{tabular}{@{}ll@{}} +{\tt not} $x$, {\tt!}$x$&negação $\neg\ x$\\ +$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunção (``e'' lógico) +$x\;\&\;y$\\ +$x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunção (``ou'' lógico) +$x\vee y$\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% {\tt not} $x$, {\tt!}$x$&negation $\neg\ x$\\ +% $x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunction (logical ``and'') +% $x\;\&\;y$\\ +% $x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunction (logical ``or'') +% $x\vee y$\\ +% \end{tabular} + +\noindent onde $x$ e $y$ são expressões lógicas. + +Se a expressão inclui mais de um operador lógico, todos operadores +são executados da esquerda para a direita de acordo com a hierarquia +das operações (veja adiante). O valor resultante da \linebreak expressão +que contém operadores lógicos é o resultado da aplicação dos +operadores aos seus \linebreak operandos. + +% \noindent where $x$ and $y$ are logical expressions. +% +% If the expression includes more than one logical operator, all +% operators are performed from left to right according to the hierarchy +% of the operations (see below). The resultant value of the expression, +% which contains logical operators, is the result of applying the +% operators to their operands. + +\subsection{Hierarquia das operações} + +A lista seguinte mostra a hierarquia das operações em expressões +lógicas: + +% The following list shows the hierarchy of operations in logical +% expressions: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operation&Hierarchy\\ +\hline +Avaliação de operações numéricas& +1{\textsuperscript{\b{a}}}-7{\textsuperscript{\b{a}}}\\ +Avaliação de operações simbólicas& +8{\textsuperscript{\b{a}}}-9{\textsuperscript{\b{a}}}\\ +Avaliação de operações de conjunto& +10{\textsuperscript{\b{a}}}-14{\textsuperscript{\b{a}}}\\ +Operações relacionais ({\tt<}, {\tt<=}, etc.)& +15{\textsuperscript{\b{a}}}\\ +negação ({\tt not}, {\tt!})& +16{\textsuperscript{\b{a}}}\\ +Conjunção({\tt and}, {\tt\&\&})& +17{\textsuperscript{\b{a}}}\\ +Quantificação-$\forall$ e -$\exists$ ({\tt forall}, {\tt exists})& +18{\textsuperscript{\b{a}}}\\ +Disjunção ({\tt or}, {\tt||})& +19{\textsuperscript{\b{a}}}\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}ll@{}} +% Operation&Hierarchy\\ +% \hline +% Evaluation of numeric operations&1st-7th\\ +% Evaluation of symbolic operations&8th-9th\\ +% Evaluation of set operations&10th-14th\\ +% Relational operations ({\tt<}, {\tt<=}, etc.)&15th\\ +% Negation ({\tt not}, {\tt!})&16th\\ +% Conjunction ({\tt and}, {\tt\&\&})&17th\\ +% $\forall$- and $\exists$-quantification ({\tt forall}, {\tt exists})& +% 18th\\ +% Disjunction ({\tt or}, {\tt||})&19th\\ +% \end{tabular} + +Esta hierarquia possui o mesmo significado como explicado anteriormente +para expressões \linebreak numéricas (ver Subseção \ref{hierarchy}, página \pageref{hierarchy}). + +% This hierarchy has the same meaning as was explained above for numeric +% expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). + +\newpage + +\section{Expressões lineares} + +Uma {\it expressão linear} é uma regra para calcular a chamada +{\it forma linear} ou simplesmente {\it fórmula}, que é uma função linear (ou +afim) de variáveis elementares. + +A expressão linear primária pode ser uma variável não-indexada, uma +variável indexada, uma expressão linear iterada, uma expressão linear condicional +ou outra expressão linear cercada entre parênteses. + +Também e permitido usar uma expressão numérica como a expressão linear +primária, neste caso, o valor resultante da expressão numérica +é automaticamente convertido para uma fórmula que inclui o +termo constante apenas. + +\para{Exemplos} + +% A {\it linear expression} is a rule for computing so called +% a {\it linear form} or simply a {\it formula}, which is a linear (or +% affine) function of elemental variables. +% +% The primary linear expression may be an unsubscripted variable, +% subscripted variable, iterated linear expression, conditional linear +% expression, or another linear expression enclosed in parentheses. +% +% It is also allowed to use a numeric expression as the primary linear +% expression, in which case the resultant value of the numeric expression +% is automatically converted to a formula that includes the constant term +% only. +% +% \para{Examples} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|z| &(variável não-indexada)\\ +\verb|x[i,j]| &(variável indexada)\\ +\verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +(expressão linear iterada)\\ +\verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +(expressão linear condicional)\\ +\verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +(expressão linear parentizada)\\ +\end{tabular} + +% \noindent +% \begin{tabular}{@{}ll@{}} +% \verb|z| &(unsubscripted variable)\\ +% \verb|x[i,j]| &(subscripted variable)\\ +% \verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +% (iterated linear expression)\\ +% \verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +% (conditional linear expression)\\ +% \verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +% (parenthesized linear expression)\\ +% \end{tabular} + +Expressões lineares mais genéricas, contendo duas ou mais +expressões lineares primárias, podem ser construídas usando +determinados operadores aritméticos. + +\para{Exemplos} + +% More general linear expressions containing two or more primary linear +% expressions may be constructed by using certain arithmetic operators. +% +% \para{Examples} + +\begin{verbatim} +2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z +(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) +\end{verbatim} + +\vspace*{-5pt} + +\subsection{Variáveis não-indexadas} + +Se a expressão linear primária é uma variável não-indexada (que deve +se 0-dimensional), a fórmula resultante formula é aquela variável +não-indexada. + +% If the primary linear expression is an unsubscripted variable (which +% should be 0-dimensional), the resultant formula is that unsubscripted +% variable. + +\vspace*{-5pt} + +\subsection{Variáveis indexadas} + +A expressão linear primária que se refere a uma variável indexada possui +a seguinte forma sintática: +$$\mbox{{\it nome}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +onde {\it nome} é o nome simbólico da variável do modelo, $i_1$, +$i_2$, \dots, $i_n$ são subíndices. + +Cada subíndice deve ser uma expressão numérica ou simbólica. O número +de subíndices na lista de subíndices deve ser igual ao da dimensão da +variável do modelo com a qual está associada a lista de subíndices. + +Os valores correntes das expressões dos subíndices são usados para identificar +um membro \linebreak particular da variável do modelo que determina a fórmula resultante, +que é uma variável elementar associada com o membro correspondente. + +% The primary linear expression, which refers to a subscripted variable, +% has the following syntactic form: +% $$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +% $i_n${\tt]}}$$ +% where {\it name} is the symbolic name of the model variable, $i_1$, +% $i_2$, \dots, $i_n$ are subscripts. +% +% Each subscript should be a numeric or symbolic expression. The number +% of subscripts in the subscript list should be the same as the dimension +% of the model variable with which the subscript list is associated. +% +% Actual values of the subscript expressions are used to identify a +% particular member of the model variable that determines the resultant +% formula, which is an elemental variable associated with corresponding +% member. + +\vspace*{-5pt} + +\subsection{Expressões iteradas} + +Uma {\it expressão linear iterada} é uma expressão linear primária, +que tem a seguinte forma sintática: +$$\mbox{{\tt sum} {\it expressão-indexante} {\it integrando}}$$ +onde {\it expressão-indexante} é uma expressão indexante, que +introduz índices e controla iterações, {\it integrando} é +uma expressão linear que participa da operação. + +A expressão linear iterada é avaliada exatamente da mesma forma que a +expressão numérica iterada (ver Subseção \ref{itexpr}, página +\pageref{itexpr}), exceto que o integrando participante do +somatório é uma fórmula e não um valor numérico. + +% An {\it iterated linear expression} is a primary linear expression, +% which has the following syntactic form: +% $$\mbox{{\tt sum} {\it indexing-expression} {\it integrand}}$$ +% where {\it indexing-expression} is an indexing expression, which +% introduces dummy indices and controls iterating, {\it integrand} is +% a linear expression that participates in the operation. +% +% The iterated linear expression is evaluated exactly in the same way as +% the iterated numeric expression (see Subection \ref{itexpr}, page +% \pageref{itexpr}) with exception that the integrand participated in the +% summation is a formula, not a numeric value. + +\vspace*{-5pt} + +\subsection{Expressões condicionais} + +Uma {\it expressão linear condicional} é uma expressão linear primária, +que possui uma das duas formas sintáticas seguintes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +\mbox{{\tt if} $b$ {\tt then} $f$}\\ +\end{array} +} +$$ +onde $b$ é uma expressão lógica, $f$ e $g$ são expressões lineares. + + +% A {\it conditional linear expression} is a primary linear expression, +% which has one of the following two syntactic forms: +% $$ +% {\def\arraystretch{1.4} +% \begin{array}{l} +% \mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +% \mbox{{\tt if} $b$ {\tt then} $f$}\\ +% \end{array} +% } +% $$ +% where $b$ is an logical expression, $f$ and $g$ are linear expressions. + +% \newpage + +A expressão linear condicional é avaliada exatamente da mesma forma +que a expressão \linebreak condicional numérica (ver Subseção \ref{ifthen}, +página \pageref{ifthen}), exceto que os operandos que participam da operação +são fórmulas e não valores numéricos. + +% The conditional linear expression is evaluated exactly in the same way +% as the conditional numeric expression (see Subsection \ref{ifthen}, +% page \pageref{ifthen}) with exception that operands participated in the +% operation are formulae, not numeric values. + +\subsection{Expressões parentizadas} + +Qualquer expressão linear pode ser cercada entre parênteses, o que a +converte sintaticamente em uma expressão linear primária. + +Parênteses podem ser usados em expressões lineares, como em álgebra, para +especificar a ordem desejada na qual as operações devem ser executadas. +Quando se usam parênteses, a expressão entre parênteses é avaliada antes +que a fórmula resultante seja usada. + +O valor resultante da expressão parentizada é idêntico ao valor da +expressão cercada entre parênteses. + +% Any linear expression may be enclosed in parentheses that syntactically +% makes it a primary linear expression. +% +% Parentheses may be used in linear expressions, as in algebra, to +% specify the desired order in which operations are to be performed. +% Where parentheses are used, the expression within the parentheses is +% evaluated before the resultant formula is used. +% +% The resultant value of the parenthesized expression is the same as the +% value of the expression enclosed within parentheses. + +\subsection{Operadores aritméticos} + +Em MathProg existem os seguintes operadores aritméticos, que podem ser +usados em expressões lineares: + +% In MathProg there exists the following arithmetic operators, which may +% be used in linear expressions: + +\begin{tabular}{@{}ll@{}} +{\tt+} $f$&mais unário\\ +{\tt-} $f$&menos unário\\ +$f$ {\tt+} $g$&adição\\ +$f$ {\tt-} $g$&subtração\\ +$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplicação\\ +$f$ {\tt/} $x$&divisão +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% {\tt+} $f$&unary plus\\ +% {\tt-} $f$&unary minus\\ +% $f$ {\tt+} $g$&addition\\ +% $f$ {\tt-} $g$&subtraction\\ +% $x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplication\\ +% $f$ {\tt/} $x$&division +% \end{tabular} + +\noindent onde $f$ e $g$ são expressões lineares, $x$ é uma expressão +numérica (mais precisamente, uma expressão linear contendo apenas o termo +constante). + +Se a expressão inclui mais de um operador aritmético, todos +operadores são executados da esquerda para a direita de acordo com a hierarquia +das operações (veja adiante). O valor resultante da expressão, que +contém operadores aritméticos, é o resultado de aplicar os operadores aos +seus operandos. + +% \noindent where $f$ and $g$ are linear expressions, $x$ is a numeric +% expression (more precisely, a linear expression containing only the +% constant term). +% +% If the expression includes more than one arithmetic operator, all +% operators are performed from left to right according to the hierarchy +% of operations (see below). The resultant value of the expression, which +% contains arithmetic operators, is the result of applying the operators +% to their operands. + +\subsection{Hierarquia das operações} + +A hierarquia de operações aritméticas usada em expressões lineares é a mesma +para expressões numéricas (ver Subseção \ref{hierarchy}, página \pageref{hierarchy}). + +% The hierarchy of arithmetic operations used in linear expressions is +% the same as for numeric expressions (see Subsection \ref{hierarchy}, +% page \pageref{hierarchy}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Sentenças} + +{\it Sentenças} são unidades básicas da descrição do modelo. Em MathProg +todas as sentenças são divididas em duas categorias: sentenças de declaração +e sentenças funcionais. + +{\it Sentenças de declaração} (sentença {\it set}, sentença {\it parameter}, +sentença {\it variable}, sentença \linebreak {\it constraint}, sentença {\it objective}) são +usados para declarar objetos de certo tipo do modelo e definir certas propriedades +de tais objetos. + +{\it Sentenças funcionais} (sentença {\it solve}, sentença {\it check}, +sentença {\it display}, sentença {\it printf}, sentença {\it loop}, sentença +{\it table}) são projetadas para executar ações específicas. + +Note que sentenças de declaração podem seguir em qualquer ordem arbitrária, +o que não afeta o resultado da tradução. Entretanto, qualquer objeto de modelo +deve ser declarado antes de ser referenciado por outras sentenças. + +% {\it Statements} are basic units of the model description. In MathProg +% all statements are divided into two categories: declaration statements +% and functional statements. +% +% {\it Declaration statements} (set statement, parameter statement, +% variable statement, constraint statement, objective statement) are used +% to declare model objects of certain kinds and define certain properties +% of such objects. +% +% {\it Functional statements} (solve statement, check statement, display +% statement, printf statement, loop statement, table statement) are +% intended for performing some specific actions. +% +% Note that declaration statements may follow in arbitrary order, which +% does not affect the result of translation. However, any model object +% should be declared before it is referenced in other statements. + +\section{Sentença set} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nome} {\it alias} {\it domínio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][24pt]{468pt}{ +% \hspace{6pt} {\tt set} {\it name} {\it alias} {\it domain} {\tt,} +% {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +% }} + +\medskip + +\noindent +{\it nome} é um nome simbólico do conjunto; + +\noindent +{\it alias} é um literal de cadeia opcional que especifica um pseudônimo +para o conjunto; + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica o domínio +do subíndice do conjunto; + +\noindent +{\it atributo}, \dots, {\it atributo} são atributos opcionais do conjunto +(as vírgulas que precedem os atributos podem ser omitidas.) + +\para{Atributos opcionais} + +% \noindent +% {\it name} is a symbolic name of the set; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the set; +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the set; +% +% \noindent +% {\it attrib}, \dots, {\it attrib} are optional attributes of the set. +% (Commae preceding attributes may be omitted.) +% +% \para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt dimen} $n$]\hspace*{0pt}\\ +especifica a dimensão de $n$-tuplas das quais o conjunto é consistido; +\item[{\tt within} {\it expressão}]\hspace*{0pt}\\ +especifica um superconjunto que restringe ao conjunto ou a todos seus +membros (conjuntos elementares) a estarem incluídos naquele superconjunto; +\item[{\tt:=} {\it expressão}]\hspace*{0pt}\\ +especifica um conjunto elementar atribuído ao conjunto ou aos seus membros; +\item[{\tt default} {\it expressão}]\hspace*{0pt}\\ +especifica um conjunto elementar atribuído ao conjunto ou aos seus membros +sempre que não há dados apropriados disponíveis na seção de dados. +\end{description} + +% \begin{description} +% \item[{\tt dimen} $n$]\hspace*{0pt}\\ +% specifies the dimension of $n$-tuples which the set consists of; +% \item[{\tt within} {\it expression}]\hspace*{0pt}\\ +% specifies a superset which restricts the set or all its members +% (elemental sets) to be within that superset; +% \item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +% specifies an elemental set assigned to the set or its members; +% \item[{\tt default} {\it expression}]\hspace*{0pt}\\ +% specifies an elemental set assigned to the set or its members whenever +% no appropriate data are available in the data section. +% \end{description} + +\vspace*{-8pt} + +\para{Exemplos} + +% \para{Examples} + +\begin{verbatim} +set nos; +set arcos within nos cross nos; +set passo{s in 1..maxiter} dimen 2 := if s = 1 then arcos else passo[s-1] + union setof{k in nos, (i,k) in passo[s-1], (k,j) in passo[s-1]}(i,j); +set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, + default {('abc',123), (321,'cba')}; +\end{verbatim} + +% \begin{verbatim} +% set nodes; +% set arcs within nodes cross nodes; +% set step{s in 1..maxiter} dimen 2 := if s = 1 then arcs else step[s-1] +% union setof{k in nodes, (i,k) in step[s-1], (k,j) in step[s-1]}(i,j); +% set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, +% default {('abc',123), (321,'cba')}; +% \end{verbatim} + +A sentença set declara um conjunto. Se o domínio do subíndice não é +especificado, o conjunto é um conjunto simples, caso contrário será +uma matriz de conjuntos elementares. + +O atributo {\tt dimen} especifica a dimensão de $n$-tuplas da qual é +consistida o conjunto (se o conjunto é simples) ou seus membros +(se o conjunto é uma matriz de conjuntos elementares), +em que $n$ deve ser um inteiro de 1 a 20. Pode-se especificar +no máximo um atributo {\tt dimen}. Se o atributo {\tt dimen} não é +especificado, a dimensão das $n$-tuplas é implicitamente determinada +por outros atributos (por exemplo, se há uma expressão que segue +{\tt:=} ou a palavra-chave {\tt default}, usa-se a dimensão das $n$-tuplas +do conjunto elementar correspondente). +Se nenhuma informação de dimensão é fornecida, assume-se +{\tt dimen 1}. + +O atributo {\tt within} especifica uma expressão de conjunto cujo +valor resultante é um superconjunto usado para restringir o conjunto +(se o conjunto é simples) ou seus membros (se o conjunto é uma matriz +de conjuntos elementares) a estar incluído naquele superconjunto. +Um número arbitrário de atributos {\tt within} podem ser especificados +na mesma sentença set. + +O atributo de atribuição ({\tt:=}) especifica uma expressão de conjunto +usada para avaliar conjunto(s) \linebreak elementar(es) atribuído(s) ao conjunto +(se o conjunto é simples) ou seus membros (se o conjunto é uma matriz +de conjuntos elementares). Se o atributo de atribuição é especificado, +o conjunto é {\it calculável}, portanto, não há a necessidade de fornecer +dados na seção de dados. Se o atributo de atribuição não é especificado, +deve-se fornecer os dados na seção de dados. Pode-se especificar no +máximo um atributo de atribuição ou {\tt default} para o mesmo conjunto. + +O atributo {\tt default} especifica uma expressão de conjunto usado para +avaliar conjunto(s) \linebreak elementar(es) atribuído(s) ao conjunto +(se o conjunto é simples) ou seus membros (se o conjunto é uma matriz +de conjuntos elementares) sempre que não houver dados apropriados +disponíveis na seção de dados. Se não se especifica nem o atributo de +atribuição nem o atributo {\tt default}, a falta de dados causará um erro. + +% The set statement declares a set. If the subscript domain is not +% specified, the set is a simple set, otherwise it is an array of +% elemental sets. +% +% The {\tt dimen} attribute specifies the dimension of $n$-tuples, which +% the set (if it is a simple set) or its members (if the set is an array +% of elemental sets) consist of, where $n$ should be an unsigned integer +% from 1 to 20. At most one {\tt dimen} attribute can be specified. If +% the {\tt dimen} attribute is not specified, the dimension of $n$-tuples +% is implicitly determined by other attributes (for example, if there is +% a set expression that follows {\tt:=} or the keyword {\tt default}, the +% dimension of $n$-tuples of corresponding elemental set is used). +% If no dimension information is available, {\tt dimen 1} is assumed. +% +% The {\tt within} attribute specifies a set expression whose resultant +% value is a superset used to restrict the set (if it is a simple set) or +% its members (if the set is an array of elemental sets) to be within +% that superset. Arbitrary number of {\tt within} attributes may be +% specified in the same set statement. +% +% The assign ({\tt:=}) attribute specifies a set expression used to +% evaluate elemental set(s) assigned to the set (if it is a simple set) +% or its members (if the set is an array of elemental sets). If the +% assign attribute is specified, the set is {\it computable} and +% therefore needs no data to be provided in the data section. If the +% assign attribute is not specified, the set should be provided with data +% in the data section. At most one assign or default attribute can be +% specified for the same set. +% +% The {\tt default} attribute specifies a set expression used to evaluate +% elemental set(s) assigned to the set (if it is a simple set) or its +% members (if the set is an array of elemental sets) whenever +% no appropriate data are available in the data section. If neither +% assign nor default attribute is specified, missing data will cause an +% error. + +\newpage + +\section{Sentença parameter} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nome} {\it alias} {\it domínio} {\tt,} +{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +}} + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][24pt]{468pt}{ +% \hspace{6pt} {\tt param} {\it name} {\it alias} {\it domain} {\tt,} +% {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +% }} + +\medskip + +\noindent +{\it nome} é um nome simbólico do parâmetro; + +\noindent +{\it alias} é um literal de cadeia opcional que especifica um pseudônimo +para o parâmetro; + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica o domínio +do subíndice do parâmetro; + +\noindent +{\it atributo}, \dots, {\it atributo} são atributos opcionais do parâmetro +(as vírgulas que precedem os atributos podem ser omitidas.) + +\para{Atributos opcionais} + +% \noindent +% {\it name} is a symbolic name of the parameter; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the parameter; +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the parameter; +% +% \noindent +% {\it attrib}, \dots, {\it attrib} are optional attributes of the +% parameter. (Commae preceding attributes may be omitted.) +% +% \para{Optional attributes} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +especifica que o parâmetro é inteiro; +\item[{\tt binary}]\hspace*{0pt}\\ +especifica que o parâmetro é binário; +\item[{\tt symbolic}]\hspace*{0pt}\\ +especifica que o parâmetro é simbólico; +\item[{\it expressão de relação}]\hspace*{0pt}\\ +(onde {\it relação} é algum de: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +especifica uma condição que restringe o parâmetro ou seus membros a +satisfazer aquela condição; +\item[{\tt in} {\it expressão}]\hspace*{0pt}\\ +especifica um superconjunto que restringe o parâmetro ou seus membros +a estarem inseridos naquele superconjunto; +\item[{\tt:=} {\it expressão}]\hspace*{0pt}\\ +especifica um valor atribuído ao parâmetro ou a seus membros; +\item[{\tt default} {\it expressão}]\hspace*{0pt}\\ +especifica um valor atribuído ao parâmetro ou aos seus membros sempre +que não houverem dados disponíveis na seção de dados. +\end{description} + +% \begin{description} +% \item[{\tt integer}]\hspace*{0pt}\\ +% specifies that the parameter is integer; +% \item[{\tt binary}]\hspace*{0pt}\\ +% specifies that the parameter is binary; +% \item[{\tt symbolic}]\hspace*{0pt}\\ +% specifies that the parameter is symbolic; +% \item[{\it relation expression}]\hspace*{0pt}\\ +% (where {\it relation} is one of: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +% {\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +% specifies a condition that restricts the parameter or its members to +% satisfy that condition; +% \item[{\tt in} {\it expression}]\hspace*{0pt}\\ +% specifies a superset that restricts the parameter or its members to be +% in that superset; +% \item[{\tt:=} {\it expression}]\hspace*{0pt}\\ +% specifies a value assigned to the parameter or its members; +% \item[{\tt default} {\it expression}]\hspace*{0pt}\\ +% specifies a value assigned to the parameter or its members whenever +% no appropriate data are available in the data section. +% \end{description} + +\vspace*{-8pt} + +\para{Exemplos} + +% \para{Examples} + +\begin{verbatim} +param unidades{insumo, produto} >= 0; +param lucro{produto, 1..T+1}; +param N := 20 integer >= 0 <= 100; +param combinacao 'n escolhe k' {n in 0..N, k in 0..n} := + if k = 0 or k = n then 1 else combinacao[n-1,k-1] + combinacao[n-1,k]; +param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], + in C[i,j], default 0.5 * (i + j); +param mes symbolic default 'Mai' in {'Mar', 'Abr', 'Mai'}; +\end{verbatim} + +% \begin{verbatim} +% param units{raw, prd} >= 0; +% param profit{prd, 1..T+1}; +% param N := 20 integer >= 0 <= 100; +% param comb 'n choose k' {n in 0..N, k in 0..n} := +% if k = 0 or k = n then 1 else comb[n-1,k-1] + comb[n-1,k]; +% param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], +% in C[i,j], default 0.5 * (i + j); +% param month symbolic default 'May' in {'Mar', 'Apr', 'May'}; +% \end{verbatim} + +A sentença parameter declara um parâmetro. Se o domínio de subíndice não +é especificado, o parâmetro é simples (escalar), caso contrário, +é uma matriz $n$-dimensional. + +Os atributos de tipo {\tt integer}, {\tt binary} e {\tt symbolic} +qualificam os tipos de valores que podem ser atribuídos ao parâmetro, conforme +demonstrado: + +% The parameter statement declares a parameter. If a subscript domain is +% not specified, the parameter is a simple (scalar) parameter, otherwise +% it is a $n$-dimensional array. +% +% The type attributes {\tt integer}, {\tt binary}, and {\tt symbolic} +% qualify the type of values that can be assigned to the parameter as +% shown below: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Tipo de atributo&Valores atribuídos\\ +\hline +(não especificado)&Qualquer valor numérico\\ +{\tt integer}&Apenas valores numéricos inteiros\\ +{\tt binary}&Tanto 0 quanto 1\\ +{\tt symbolic}&Qualquer valor numérico e simbólico\\ +\end{tabular} + +% \noindent\hfil +% \begin{tabular}{@{}ll@{}} +% Type attribute&Assigned values\\ +% \hline +% (not specified)&Any numeric values\\ +% {\tt integer}&Only integer numeric values\\ +% {\tt binary}&Either 0 or 1\\ +% {\tt symbolic}&Any numeric and symbolic values\\ +% \end{tabular} + +O atributo {\tt symbolic} não pode ser especificado juntamente com outros tipos +de atributos. Uma vez especificado, ele deve preceder todos os outros atributos. + +O atributo de condição especifica uma condição opcional que restringe +os valores atribuídos ao parâmetro para satisfazer aquela condição. +Este atributo tem as seguintes formas sintáticas: + +% The {\tt symbolic} attribute cannot be specified along with other type +% attributes. Being specified it should precede all other attributes. +% +% The condition attribute specifies an optional condition that restricts +% values assigned to the parameter to satisfy that condition. This +% attribute has the following syntactic forms: + +\begin{tabular}{@{}ll@{}} +{\tt<} $v$&verifica se $x=} $v$&verifica se $x\geq v$\\ +{\tt>} $v$&verifica se $x\geq v$\\ +{\tt<>} $v$, {\tt!=} $v$&verifica se $x\neq v$\\ +\end{tabular} + +% \begin{tabular}{@{}ll@{}} +% {\tt<} $v$&check for $x=} $v$&check for $x\geq v$\\ +% {\tt>} $v$&check for $x\geq v$\\ +% {\tt<>} $v$, {\tt!=} $v$&check for $x\neq v$\\ +% \end{tabular} + +\noindent onde $x$ é um valor atribuído ao parâmetro, $v$ é o +valor resultante de uma expressão numérica ou simbólica especificado +no atributo de condição. Um número arbitrário de atributos de condição +pode ser especificado para o mesmo parâmetro. Se, durante a avaliação do +modelo, um valor atribuído ao parâmetro viola pelo menos uma das +condições especificadas, ocorrerá um erro. (Note que valores simbólicos +são ordenados de forma lexicográfica e qualquer valor numérico precede +qualquer valor simbólico.) + +O atributo {\tt in} é similar ao atributo de condição e especifica +uma expressão de conjunto cujo valor resultante é um superconjunto usado +para restringir valores numéricos ou simbólicos atribuídos ao parâmetro +a estarem incluídos naquele superconjunto. Pode-se especificar um número +arbitrário de atributos {\tt in} para o mesmo parâmetro. Se, durante a avaliação do +modelo, o valor atribuído ao parâmetro não pertence a pelo menos um dos +superconjuntos especificados, ocorrerá um erro. + +O atributo de atribuição ({\tt:=}) especifica uma expressão numérica +ou simbólica usada para \linebreak computar um valor atribuído ao parâmetro +(se é um parâmetro simples) ou seus membros (se o parâmetro é uma matriz). +Se o atributo de atribuição é especificado, +o parâmetro é {\it calculável}, \linebreak portanto, não há a necessidade de fornecer +dados na seção de dados. Se o atributo de atribuição não é especificado, +deve-se fornecer os dados para o parâmetro na seção de dados. Pode-se especificar no +máximo um atributo de atribuição ou {\tt default} para o mesmo parâmetro. + +O atributo {\tt default} especifica uma expressão numérica ou simbólica +usada para computar um valor atribuído ao parâmetro ou seus membros +sempre que não houver dados apropriados disponíveis na seção de dados. +Se não se especifica nem o atributo de atribuição nem o atributo +{\tt default}, a falta de dados causará um erro. + +% \noindent where $x$ is a value assigned to the parameter, $v$ is the +% resultant value of a numeric or symbolic expression specified in the +% condition attribute. Arbitrary number of condition attributes can be +% specified for the same parameter. If a value being assigned to the +% parameter during model evaluation violates at least one of specified +% conditions, an error is raised. (Note that symbolic values are ordered +% lexicographically, and any numeric value precedes any symbolic value.) +% +% The {\tt in} attribute is similar to the condition attribute and +% specifies a set expression whose resultant value is a superset used to +% restrict numeric or symbolic values assigned to the parameter to be in +% that superset. Arbitrary number of the {\tt in} attributes can be +% specified for the same parameter. If a value being assigned to the +% parameter during model evaluation is not in at least one of specified +% supersets, an error is raised. +% +% The assign ({\tt:=}) attribute specifies a numeric or symbolic +% expression used to compute a value assigned to the parameter (if it is +% a simple parameter) or its member (if the parameter is an array). If +% the assign attribute is specified, the parameter is {\it computable} +% and therefore needs no data to be provided in the data section. If the +% assign attribute is not specified, the parameter should be provided +% with data in the data section. At most one assign or {\tt default} +% attribute can be specified for the same parameter. +% +% The {\tt default} attribute specifies a numeric or symbolic expression +% used to compute a value assigned to the parameter or its member +% whenever no appropriate data are available in the data section. If +% neither assign nor {\tt default} attribute is specified, missing data +% will cause an error. + +\newpage + +\section{Sentença variable} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt var} {\it nome} {\it alias} {\it domínio} {\tt,} +{\it atrib} {\tt,} \dots {\tt,} {\it atrib} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico da variável; + +\noindent +{\it alias} é um literal de cadeia opcional que especifica um pseudônimo +para a variável; + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica o domínio +do subíndice da variável; + +\noindent +{\it atrib}, \dots, {\it atrib} são atributos opcionais da variável +(as vírgulas que precedem os atributos podem ser omitidas.) + +\para{Atributos opcionais} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +restringe a variável a ser inteira; +\item[{\tt binary}]\hspace*{0pt}\\ +restringe a variável a ser binária; +\item[{\tt>=} {\it expressão}]\hspace*{0pt}\\ +especifica um limite inferior para a variável; +\item[{\tt<=} {\it expressão}]\hspace*{0pt}\\ +especifica um limite superior para a variável; +\item[{\tt=} {\it expressão}]\hspace*{0pt}\\ +especifica um valor fixo para a variável; +\end{description} + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][24pt]{468pt}{ +% \hspace{6pt} {\tt var} {\it name} {\it alias} {\it domain} {\tt,} +% {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the variable; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the variable; +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the variable; +% +% \noindent +% {\it attrib}, \dots, {\it attrib} are optional attributes of the +% variable. (Commae preceding attributes may be omitted.) +% +% \para{Optional attributes} +% +% \vspace*{-8pt} +% +% \begin{description} +% \item[{\tt integer}]\hspace*{0pt}\\ +% restricts the variable to be integer; +% \item[{\tt binary}]\hspace*{0pt}\\ +% restricts the variable to be binary; +% \item[{\tt>=} {\it expression}]\hspace*{0pt}\\ +% specifies an lower bound of the variable; +% \item[{\tt<=} {\it expression}]\hspace*{0pt}\\ +% specifies an upper bound of the variable; +% \item[{\tt=} {\it expression}]\hspace*{0pt}\\ +% specifies a fixed value of the variable; +% \end{description} + +\vspace*{-8pt} + +\para{Exemplos} + +% \para{Examples} + +\begin{verbatim} +var x >= 0; +var y{I,J}; +var produzir{p in prod}, integer, >= comprometido[p], <= mercado[p]; +var armazenar{insumo, 1..T+1} >= 0; +var z{i in I, j in J} >= i+j; +\end{verbatim} + +% \begin{verbatim} +% var x >= 0; +% var y{I,J}; +% var make{p in prd}, integer, >= commit[p], <= market[p]; +% var store{raw, 1..T+1} >= 0; +% var z{i in I, j in J} >= i+j; +% \end{verbatim} + +A sentença variable declara uma variável. Se não se especifica o +domínio do subíndice, a variável e uma variável simples (escalar), +caso contrário é uma matriz $n$-dimensional de variáveis elementares. + +As variáveis elementares associadas com a variável do modelo +(se é uma variável simples) ou seus membros (se é uma matriz) corresponde +às variáveis na formulação do problema PL/PIM (ver Seção \ref{problem}, +página \pageref{problem}). Note que somente variáveis elementares +realmente referenciadas em algumas restrições e/ou objetivos serão +incluídas na instância do problema PL/PIM a ser gerado. + +Os atributos de tipo {\tt integer} e {\tt binary} restringem a variável +a ser inteira ou binária, \linebreak respectivamente. Se nenhum atributo de tipo +é especificado, a variável é contínua. Se todas as variáveis no modelo +são contínuas, o problema correspondente é da classe PL. Se há pelo +menos uma variável inteira ou binária, o problema é da classe PIM. + +\newpage + +O atributo de limite inferior ({\tt>=}) especifica uma expressão numérica +para calcular um limite inferior da variável. No máximo um limite inferior +pode ser especificado. Por padrão, todas as variáveis (exceto as binárias) +não tem limite inferior, assim, se há a necessidade de uma variável ser +não-negativa, seu limite inferior zero deve ser explicitamente especificado. + +O atributo de limite superior ({\tt<=}) especifica uma expressão numérica +para calcular um limite superior da variável. No máximo um limite superior +pode ser especificado. + +O atributo de valor fixo ({\tt=}) especifica uma expressão numérica para +calcular um valor no qual a variável é fixada. Este atributo não pode +ser especificado junto com os atributos de limite. + + +% The variable statement declares a variable. If a subscript domain is +% not specified, the variable is a simple (scalar) variable, otherwise it +% is a $n$-dimensional array of elemental variables. +% +% Elemental variable(s) associated with the model variable (if it is a +% simple variable) or its members (if it is an array) correspond to the +% variables in the LP/MIP problem formulation (see Section \ref{problem}, +% page \pageref{problem}). Note that only elemental variables actually +% referenced in some constraints and/or objectives are included in the +% LP/MIP problem instance to be generated. +% +% The type attributes {\tt integer} and {\tt binary} restrict the +% variable to be integer or binary, respectively. If no type attribute is +% specified, the variable is continuous. If all variables in the model +% are continuous, the corresponding problem is of LP class. If there is +% at least one integer or binary variable, the problem is of MIP class. +% +% The lower bound ({\tt>=}) attribute specifies a numeric expression for +% computing an lower bound of the variable. At most one lower bound can +% be specified. By default all variables (except binary ones) have no +% lower bound, so if a variable is required to be non-negative, its zero +% lower bound should be explicitly specified. +% +% The upper bound ({\tt<=}) attribute specifies a numeric expression for +% computing an upper bound of the variable. At most one upper bound +% attribute can be specified. +% +% The fixed value ({\tt=}) attribute specifies a numeric expression for +% computing a value, at which the variable is fixed. This attribute +% cannot be specified along with the bound attributes. + + +\section{Sentença constraint} + +\noindent +\framebox[468pt][l]{ +\parbox[c][106pt]{468pt}{ +\hspace{6pt} {\tt s.t.} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt,} {\tt=} {\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt,} {\tt<=} {\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt,} {\tt>=} {\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt,} {\tt<=} {\it expressão} {\tt,} {\tt<=} +{\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt,} {\tt>=} {\it expressão} {\tt,} {\tt>=} +{\it expressão} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico da restrição; + +\noindent +{\it alias} é um literal de cadeia opcional que especifica um pseudônimo +da restrição; + +\noindent +{\it domínio} é uma expressão indexante opcional, que especifica +o domínio do subíndice da restrição; + +\noindent +{\it expressão} é uma expressão linear usada para calcular um componente +da restrição (as vírgulas que precedem os atributos podem ser omitidas). + +\noindent +(A palavra-chave {\tt s.t.} pode ser escrita como {\tt subject to}, como +{\tt subj to} ou pode ser omitido por completo). + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][106pt]{468pt}{ +% \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt,} {\tt=} {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt,} {\tt<=} {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt,} {\tt>=} {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt,} {\tt<=} {\it expression} {\tt,} {\tt<=} +% {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt,} {\tt>=} {\it expression} {\tt,} {\tt>=} +% {\it expression} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the constraint; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the constraint; +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the constraint; +% +% \noindent +% {\it expression} is a linear expression used to compute a component of +% the constraint. (Commae following expressions may be omitted.) +% +% \noindent +% (The keyword {\tt s.t.} may be written as {\tt subject to} or as +% {\tt subj to}, or may be omitted at all.) + + +\para{Exemplos} + +% \para{Examples} + +\begin{verbatim} +s.t. r: x + y + z, >= 0, <= 1; +limite{t in 1..T}: sum{j in produto} produzir[j,t] <= max_prod; +subject to balanco{i in insumo, t in 1..T}: + estoque[i,t+1] = estoque[i,t] - sum{j in produto} unidades[i,j] * produzir[j,t]; +subject to rlim 'limite tempo-regular' {t in tempo}: + sum{p in produto} pt[p] * rprod[p,t] <= 1.3 * dpp[t] * equipes[t]; +\end{verbatim} + +% \begin{verbatim} +% s.t. r: x + y + z, >= 0, <= 1; +% limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd; +% subject to balance{i in raw, t in 1..T}: +% store[i,t+1] = store[i,t] - sum{j in prd} units[i,j] * make[j,t]; +% subject to rlim 'regular-time limit' {t in time}: +% sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t]; +% \end{verbatim} + +A sentença de restrição declara uma restrição. Se o domínio do subíndice +não é especificado, a restrição é uma restrição simples (escalar), +caso contrário, é uma matriz $n$-dimensional de restrições elementares. + +Restrições elementares associadas com a restrição do modelo (se é +uma restrição simples) ou seus membros (se é uma matriz) correspondem +a restrições lineares na formulação do problema de PL/PIM (ver +Seção \ref{problem}, página \pageref{problem}). + +Se a restrição possui a forma de igualdade ou desigualdade simples, i.e., +inclui duas expressões, uma segue depois dos dois pontos e a outra +segue depois do sinal de relação {\tt=}, {\tt<=} ou {\tt>=}, \linebreak ambas +expressões na sentença podem ser expressões lineares. Se a restrição +possui a forma de uma \linebreak desigualdade dupla, i.e., inclui três expressões, +a expressão do meio pode ser uma expressão linear, enquanto a da +esquerda e a da direita podem ser apenas expressões numéricas. + +Gerar o modelo é, a grosso modo, gerar suas restrições, que são sempre +avaliadas para todo domínio do subíndice. Avaliar as restrições, +por sua vez, leva a avaliação de outros objetos de modelo tais como +conjuntos, parâmetros e variáveis. + +A construção de uma restrição linear incluída na instância do problema, +que corresponde a uma restrição elementar particular, é realizada +como segue. + + +% The constraint statement declares a constraint. If a subscript domain +% is not specified, the\linebreak constraint is a simple (scalar) +% constraint, otherwise it is a $n$-dimensional array of elemental +% constraints. +% +% Elemental constraint(s) associated with the model constraint (if it is +% a simple constraint) or its members (if it is an array) correspond to +% the linear constraints in the LP/MIP problem formulation (see +% Section \ref{problem}, page \pageref{problem}). +% +% If the constraint has the form of equality or single inequality, i.e. +% includes two expressions, one of which follows the colon and other +% follows the relation sign {\tt=}, {\tt<=}, or {\tt>=}, both expressions +% in the statement can be linear expressions. If the constraint has the +% form of double inequality,\linebreak i.e. includes three expressions, +% the middle expression can be a linear expression while the leftmost and +% rightmost ones can be only numeric expressions. +% +% Generating the model is, roughly speaking, generating its constraints, +% which are always evaluated for the entire subscript domain. Evaluation +% of the constraints leads, in turn, to evaluation of other model objects +% such as sets, parameters, and variables. +% +% Constructing an actual linear constraint included in the problem +% instance, which (constraint) corresponds to a particular elemental +% constraint, is performed as follows. + + +Se a restrição possui a forma de igualdade ou desigualdade simples, +a avaliação de ambas \linebreak expressões lineares resultam em duas formas lineares: +$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +g&=&b_1x_1&+&b_2x_2&+\dots+&b_nx_n&+&b_0,\\ +\end{array}$$ +onde $x_1$, $x_2$, \dots, $x_n$ são variáveis elementares; $a_1$, $a_2$, +\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ são coeficientes numéricos; +$a_0$ e $b_0$ são termos constantes. Em seguida, todos os termos lineares +de $f$ e $g$ são levados ao lado esquerdo, enquanto que os termos constantes +são levados ao lado direito, resultando na restrição elementar +final na forma padrão: +$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ + +Se a restrição possui a forma de desigualdade dupla, a avaliação da +expressão linear do meio resulta na seguinte forma linear: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +e a avaliação das expressões numéricas da esquerda e da direita dão +dois valores numéricos $l$ e $u$, respectivamente. Logo, +o termo constante da forma linear é levado tanto à esquerda como +à direita para gerar a restrição elementar final na forma padrão: +$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + + +% If the constraint has the form of equality or single inequality, +% evaluation of both linear expressions gives two resultant linear forms: +% $$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +% f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +% g&=&b_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&b_0,\\ +% \end{array}$$ +% where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, +% \dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ are numeric coefficients; +% $a_0$ and $b_0$ are constant terms. Then all linear terms of $f$ and +% $g$ are carried to the left-hand side, and the constant terms are +% carried to the right-hand side, that gives the final elemental +% constraint in the standard form: +% $$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +% \begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ +% +% If the constraint has the form of double inequality, evaluation of the +% middle linear expression gives the resultant linear form: +% $$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +% and evaluation of the leftmost and rightmost numeric expressions gives +% two numeric values $l$ and $u$, respectively. Then the constant term of +% the linear form is carried to both left-hand and right-handsides that +% gives the final elemental constraint in the standard form: +% $$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + + +\section{Sentença objective} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt minimize} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt maximize} {\it nome} {\it alias} {\it domínio} {\tt:} +{\it expressão} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico do objetivo; + +\noindent +{\it alias} é uma literal de cadeia opcional que especifica um +pseudônimo do objetivo; + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica +um domínio do subíndice do objetivo; + +\noindent +{\it expressão} é uma expressão linear usada pra calcular a forma +linear do objetivo. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][44pt]{468pt}{ +% \hspace{6pt} {\tt minimize} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt maximize} {\it name} {\it alias} {\it domain} {\tt:} +% {\it expression} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the objective; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the objective; +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the objective; +% +% \noindent +% {\it expression} is a linear expression used to compute the linear form +% of the objective. + +\newpage + +\para{Exemplos} + +% \para{Examples} + +\begin{verbatim} +minimize obj: x + 1.5 * (y + z); +maximize lucro_total: sum{p in produto} lucro[p] * produzir[p]; +\end{verbatim} + +% \begin{verbatim} +% minimize obj: x + 1.5 * (y + z); +% maximize total_profit: sum{p in prd} profit[p] * make[p]; +% \end{verbatim} + +A sentença objective declara um objetivo. Se o domínio do subíndice +não é especificado, o objetivo é um objetivo simples (escalar). Caso contrário, +é uma matriz $n$-dimensional de objetivos elementares. + +Objetivos elementares associados com o objetivo do modelo (se é um +objetivo simples) ou seus membros (se é uma matriz) correspondem +a restrições lineares genéricas na formulação do problema PL/PIM +(ver Seção \ref{problem}, página \pageref{problem}). No entanto, +diferentemente das restrições, estas formas lineares são livres +(ilimitadas). + +A construção de uma forma linear incluída na instância do problema, +a qual corresponde a uma restrição elementar particular, +é realizada como segue. A expressão linear especificada da na +sentença objective é avaliada para resultar na seguinte forma linear: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +onde $x_1$, $x_2$, \dots, $x_n$ são variáveis elementares; $a_1$, $a_2$, +\dots, $a_n$ são coeficientes numéricos; $a_0$ é o termo constante. Logo, +a forma linear é usada para construir a restrição final elementar na +forma padrão: +$$-\infty= 0 and y >= 0; +check sum{i in ORIG} suprimento[i] = sum{j in DEST} demanda[j]; +check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +\end{verbatim} + +A sentença check permite a verificação do valor resultante +de uma expressão lógica especificada na sentença. Se o valor +é {\it falso}, um erro é reportado. + +Se o domínio do subíndice não é especificado, a verificação é realizada +apenas uma vez. \linebreak Especificar o domínio do subíndice +permite a execução de verificações múltiplas para cada $n$-tupla +no conjunto domínio. Neste último caso, a expressão lógica pode +incluir índices introduzidos na expressão indexante correspondente. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][24pt]{468pt}{ +% \hspace{6pt} {\tt check} {\it domain} {\tt:} {\it expression} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the check statement; +% +% \noindent +% {\it expression} is an logical expression which specifies the logical +% condition to be checked. (The colon preceding {\it expression} may be +% omitted.) +% +% \para{Examples} +% +% \begin{verbatim} +% check: x + y <= 1 and x >= 0 and y >= 0; +% check sum{i in ORIG} supply[i] = sum{j in DEST} demand[j]; +% check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +% \end{verbatim} +% +% The check statement allows checking the resultant value of an logical +% expression specified in the statement. If the value is {\it false}, an +% error is reported. +% +% If the subscript domain is not specified, the check is performed only +% once. Specifying the subscript domain allows performing multiple check +% for every $n$-tuple in the domain set. In the latter case the logical +% expression may include dummy indices introduced in corresponding +% indexing expression. + +\section{Sentença display} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt display} {\it domínio} {\tt:} {\it item} {\tt,} +\dots {\tt,} {\it item} {\tt;} +}} + +\medskip + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica +um domínio do subíndice da sentença display; + +\noindent +{\it item}, \dots, {\it item} são itens a serem mostrados (os dois pontos +que precedem o primeiro item podem ser omitidos). + +\para{Exemplos} + +\begin{verbatim} +display: 'x =', x, 'y =', y, 'z =', z; +display sqrt(x ** 2 + y ** 2 + z ** 2); +display{i in I, j in J}: i, j, a[i,j], b[i,j]; +\end{verbatim} + +A sentença display avalia todos itens especificados na sentença +e escreve seus valores em saída padrão (terminal) em formato de +texto plano. + +Se um domínio de subíndice não é especificado, os itens são avaliados e +mostrados apenas uma vez. Ao especificar o domínio do subíndice, itens +são avaliados e mostrados para cada $n$-tupla no conjunto do domínio. No +último caso, os itens podem incluir índices introduzidos na expressão +indexante correspondente. + +Um item a ser mostrado pode ser um objeto de modelo (conjunto, parâmetro, +variável, restrição, objetivo) ou uma expressão. + +Se um item é um objeto calculável (i.e., um conjunto ou parâmetro com +o atributo de atribuição), o objeto é avaliado por todo domínio +e em seguida, seu conteúdo (i.e., o conteúdo da matriz de objetos) é +mostrado. Caso contrário, se o item não é um objeto calculável, somente seu +seu conteúdo corrente (i.e., os membros realmente gerados durante a +avaliação do modelo) é mostrado. + +Se o item é uma expressão, a expressão é avaliada e seu valor +resultante é mostrado. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][24pt]{468pt}{ +% \hspace{6pt} {\tt display} {\it domain} {\tt:} {\it item} {\tt,} +% \dots {\tt,} {\it item} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the display statement; +% +% \noindent +% {\it item}, \dots, {\it item} are items to be displayed. (The colon +% preceding the first item may be omitted.) +% +% \para{Examples} +% +% \begin{verbatim} +% display: 'x =', x, 'y =', y, 'z =', z; +% display sqrt(x ** 2 + y ** 2 + z ** 2); +% display{i in I, j in J}: i, j, a[i,j], b[i,j]; +% \end{verbatim} +% +% The display statement evaluates all items specified in the statement +% and writes their values on the standard output (terminal) in plain text +% format. +% +% If a subscript domain is not specified, items are evaluated and then +% displayed only once. Specifying the subscript domain causes items to be +% evaluated and displayed for every $n$-tuple in the domain set. In the +% latter case items may include dummy indices introduced in corresponding +% indexing expression. +% +% An item to be displayed can be a model object (set, parameter, +% variable, constraint, objective) or an expression. +% +% If the item is a computable object (i.e. a set or parameter provided +% with the assign attribute), the object is evaluated over the entire +% domain and then its content (i.e. the content of the object array) is +% displayed. Otherwise, if the item is not a computable object, only its +% current content (i.e. members actually generated during the model +% evaluation) is displayed. +% +% If the item is an expression, the expression is evaluated and its +% resultant value is displayed. + +\section{Sentença printf} + +\noindent +\framebox[468pt][l]{ +\parbox[c][64pt]{468pt}{ +\hspace{6pt} {\tt printf} {\it domínio} {\tt:} {\it formato} {\tt,} +{\it expressão} {\tt,} \dots {\tt,} {\it expressão} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domínio} {\tt:} {\it formato} {\tt,} +{\it expressão} {\tt,} \dots {\tt,} {\it expressão} {\tt>} +{\it nome-do-arquivo} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it domínio} {\tt:} {\it formato} {\tt,} +{\it expressão} {\tt,} \dots {\tt,} {\it expressão} {\tt>>} +{\it nome-do-arquivo} {\tt;} +}} + +\medskip + +\noindent +{\it domínio} é uma expressão indexante opcional que especifica o domínio +do subíndice da sentença printf; + +\noindent +{\it formato} é uma expressão simbólica cujo valor especifica uma cadeia de +controle de formato (os dois pontos que precedem a expressão de formato +podem ser omitidos). + +\noindent +{\it expressão}, \dots, {\it expressão} são zero ou mais expressões +cujos valores devem ser formatados e impressos. Cada expressão deve +ser de tipo numérico, simbólico ou lógico. + +\noindent +{\it nome-do-arquivo} é uma expressão simbólica cujo valor especifica um nome +de um arquivo de texto para onde a saída é redirecionada. O sinal {\tt>} +significa criar um novo aquivo vazio, enquanto o sinal {\tt>>} significa +acrescentar a saída a um arquivo existente. Se o nome do arquivo não é especificado, +a saída é escrita na saída padrão (terminal). + +\para{Exemplos} + +\begin{verbatim} +printf 'Ola, mundo!\n'; +printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "resultado.txt"; +printf{i in I, j in J}: "fluxo de %s para %s eh %d\n", i, j, x[i,j] + >> arquivo_resultado & ".txt"; +printf{i in I} 'fluxo total de %s eh %g\n', i, sum{j in J} x[i,j]; +printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), + k, x[k]; +\end{verbatim} + +A sentença printf é similar a sentença display, no entanto, ela +permite formatar os dados a serem escritos. + +Se um domínio do subíndice não é especificado, a sentença printf +é executada apenas uma vez. Especificar um domínio do subíndice gera +a execução da sentença printf para cada $n$-tupla no conjunto do domínio. +No último caso, o formato e a expressão podem incluir índices introduzidos +nas expressões indexantes correspondentes. + +A cadeia de controle de formato é valor da expressão simbólica +{\it formato} especificada na sentença printf. Ela é composta de zero +ou mais diretivas, como segue: tanto caracteres ordinários (exceto {\tt\%}), que +são copiados sem modificação ao fluxo de saída, quanto especificações de conversão, +provocam a avaliação da expressão correspondente especificada na sentença +printf, do seu formato e da escrita do valor resultante no fluxo de saída. + +As especificações de conversão que podem ser usadas na cadeia de controle +de formato são as seguintes: {\tt d}, {\tt i}, {\tt f}, {\tt F}, +{\tt e}, {\tt E}, {\tt g}, {\tt G} e {\tt s}. Estas especificações +possuem a mesma sintaxe e semântica que na linguagem de programação C. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][64pt]{468pt}{ +% \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +% {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +% {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>} +% {\it filename} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} +% {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>>} +% {\it filename} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it domain} is an optional indexing expression, which specifies +% a subscript domain of the printf statement; +% +% \noindent +% {\it format} is a symbolic expression whose value specifies a format +% control string. (The colon preceding the format expression may be +% omitted.) +% +% \noindent +% {\it expression}, \dots, {\it expression} are zero or more expressions +% whose values have to be formatted and printed. Each expression should +% be of numeric, symbolic, or logical type. +% +% \noindent +% {\it filename} is a symbolic expression whose value specifies a name +% of a text file, to which the output is redirected. The flag {\tt>} +% means creating a new empty file while the flag {\tt>>} means appending +% the output to an existing file. If no file name is specified, the +% output is written on the standard output (terminal). +% +% \para{Examples} +% +% \begin{verbatim} +% printf 'Hello, world!\n'; +% printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "result.txt"; +% printf{i in I, j in J}: "flow from %s to %s is %d\n", i, j, x[i,j] +% >> result_file & ".txt"; +% printf{i in I} 'total flow from %s is %g\n', i, sum{j in J} x[i,j]; +% printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), +% k, x[k]; +% \end{verbatim} +% +% The printf statement is similar to the display statement, however, it +% allows formatting data to be written. +% +% If a subscript domain is not specified, the printf statement is +% executed only once. Specifying a subscript domain causes executing the +% printf statement for every $n$-tuple in the domain set. In the latter +% case the format and expression may include dummy indices introduced in +% corresponding indexing expression. +% +% The format control string is a value of the symbolic expression +% {\it format} specified in the printf statement. It is composed of zero +% or more directives as follows: ordinary characters (not {\tt\%}), which +% are copied unchanged to the output stream, and conversion +% specifications, each of which causes evaluating corresponding +% expression specified in the printf statement, formatting it, and +% writing its resultant value to the output stream. +% +% Conversion specifications that may be used in the format control string +% are the following:\linebreak {\tt d}, {\tt i}, {\tt f}, {\tt F}, +% {\tt e}, {\tt E}, {\tt g}, {\tt G}, and {\tt s}. These specifications +% have the same syntax and semantics as in the C programming language. + +\section{Sentença for} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt for} {\it domínio} {\tt:} {\it sentença} {\tt;} + +\medskip + +\hspace{6pt} {\tt for} {\it domínio} {\tt:} {\tt\{} {\it sentença} +\dots {\it sentença} {\tt\}} {\tt;} +}} + +\medskip + +\noindent +{\it domínio} é uma expressão indexante que especifica um +domínio do subíndice da sentença for. (Os dois pontos que seguem a +expressão indexante podem ser omitidos). + +\noindent +{\it sentença} é uma sentença que deve ser executada sob o controle +da sentença for; + +\noindent +{\it sentença}, \dots, {\it sentença} é uma sequência de sentenças +(cercada entre chaves) que deve ser executada sob o controle da +sentença for. + +Apenas as sentenças seguintes podem ser usadas dentro da +sentença for: check, display, printf e outro for. + +\para{Exemplos} + +\begin{verbatim} +for {(i,j) in E: i != j} +{ printf "fluxo de %s para %s eh %g\n", i, j, x[i,j]; + check x[i,j] >= 0; +} +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} +for {1..72} printf("*"); +\end{verbatim} + +A sentença for faz com que a sentença, ou uma sequência de sentenças +especificadas como parte da sentença for, seja executada para cada +$n$-tupla no conjunto do domínio. Assim, sentenças dentro da sentença for +podem incluir índices introduzidos na expressão indexante correspondente. + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][44pt]{468pt}{ +% \hspace{6pt} {\tt for} {\it domain} {\tt:} {\it statement} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt for} {\it domain} {\tt:} {\tt\{} {\it statement} +% \dots {\it statement} {\tt\}} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it domain} is an indexing expression which specifies a subscript +% domain of the for statement. (The colon following the indexing +% expression may be omitted.) +% +% \noindent +% {\it statement} is a statement, which should be executed under control +% of the for statement; +% +% \noindent +% {\it statement}, \dots, {\it statement} is a sequence of statements +% (enclosed in curly braces), which should be executed under control of +% the for statement. +% +% Only the following statements can be used within the for statement: +% check, display, printf, and another for. +% +% \para{Examples} +% +% \begin{verbatim} +% for {(i,j) in E: i != j} +% { printf "flow from %s to %s is %g\n", i, j, x[i,j]; +% check x[i,j] >= 0; +% } +% for {i in 1..n} +% { for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; +% printf("\n"); +% } +% for {1..72} printf("*"); +% \end{verbatim} +% +% The for statement causes a statement or a sequence of statements +% specified as part of the for statement to be executed for every +% $n$-tuple in the domain set. Thus, statements within the for statement +% may include dummy indices introduced in corresponding indexing +% expression. + +\newpage + +\section{Sentença table} + +\noindent +\framebox[468pt][l]{ +\parbox[c][80pt]{468pt}{ +\hspace{6pt} {\tt table} {\it nome} {\it alias} {\tt IN} {\it controlador} +{\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it conjunto} {\tt<-} {\tt[} {\it cmp} {\tt,} +\dots {\tt,} {\it cmp} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +{\it cmp} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it cmp} +{\tt;} + +\medskip + +\hspace{6pt} {\tt table} {\it nome} {\it alias} {\it domínio} {\tt OUT} +{\it controlador} {\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it cmp} +{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it cmp} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico da tabela; + +\noindent +{\it alias} é um literal de cadeia opcional que especifica um pseudônimo +da tabela; + +\noindent +{\it domínio} é uma expressão indexante que especifica o domínio do +subíndice da tabela (de saída); + +\noindent +{\tt IN} significa ler dados de uma tabela de entrada; + +\noindent +{\tt OUT} significa escrever dados em uma tabela de saída; + +\noindent +{\it controlador} é uma expressão simbólica que especifica o controlador +usado para acessar a tabela (para mais detalhes, ver Apêndice \ref{drivers}, +página \pageref{drivers}); + +\noindent +{\it arg} é uma expressão simbólica opcional, que é um argumento +passado ao controlador da tabela. Esta expressão simbólica não deveria +incluir índices especificados no domínio; + +\noindent +{\it conjunto} é o nome de um conjunto simples opcional chamado +{\it conjunto de controle}. Pode ser omitido junto com o delimitador {\tt<-}; + +\noindent +{\it cmp} é um nome de campo. Entre colchetes, pelo menos um campo deve ser +especificado. O nome do campo, que segue o nome do parâmetro ou de uma +expressão, é opcional e pode ser omitido juntamente com o +delimitador~{\tt\textasciitilde}. Neste caso o nome do objeto de modelo +correspondente é usado como nome de campo; + +\noindent +{\it par} é um nome simbólico de um parâmetro do modelo; + +\noindent +{\it expr} é uma expressão numérica ou simbólica. + +\para{Exemplos} + +\begin{verbatim} +table dados IN "CSV" "dados.csv": S <- [DE,PARA], d~DISTANCIA, + c~CUSTO; +table resultado{(d,p) in S} OUT "CSV" "resultado.csv": d~DE, p~PARA, + x[d,p]~FLUXO; +\end{verbatim} + +A sentença table permite a leitura de dados de uma tabela para objetos +de modelo como conjuntos e parâmetros (não-escalares) assim como escrever +dados do modelo para uma tabela. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][80pt]{468pt}{ +% \hspace{6pt} {\tt table} {\it name} {\it alias} {\tt IN} {\it driver} +% {\it arg} \dots {\it arg} {\tt:} +% +% \hspace{6pt} {\tt\ \ \ \ \ } {\it set} {\tt<-} {\tt[} {\it fld} {\tt,} +% \dots {\tt,} {\it fld} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +% {\it fld} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it fld} +% {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt table} {\it name} {\it alias} {\it domain} {\tt OUT} +% {\it driver} {\it arg} \dots {\it arg} {\tt:} +% +% \hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it fld} +% {\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it fld} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the table; +% +% \noindent +% {\it alias} is an optional string literal, which specifies an alias of +% the table; +% +% \noindent +% {\it domain} is an indexing expression, which specifies a subscript +% domain of the (output) table; +% +% \noindent +% {\tt IN} means reading data from the input table; +% +% \noindent +% {\tt OUT} means writing data to the output table; +% +% \noindent +% {\it driver} is a symbolic expression, which specifies the driver used +% to access the table (for details see Appendix \ref{drivers}, page +% \pageref{drivers}); +% +% \noindent +% {\it arg} is an optional symbolic expression, which is an argument +% pass\-ed to the table driver. This symbolic expression should not +% include dummy indices specified in the domain; +% +% \noindent +% {\it set} is the name of an optional simple set called {\it control +% set}. It can be omitted along with the delimiter {\tt<-}; +% +% \noindent +% {\it fld} is a field name. Within square brackets at least one field +% should be specified. The field name following a parameter name or +% expression is optional and can be omitted along with the +% delimiter~{\tt\textasciitilde}, in which case the name of corresponding +% model object is used as the field name; +% +% \noindent +% {\it par} is a symbolic name of a model parameter; +% +% \noindent +% {\it expr} is a numeric or symbolic expression. +% +% \para{Examples} +% +% \begin{verbatim} +% table data IN "CSV" "data.csv": S <- [FROM,TO], d~DISTANCE, +% c~COST; +% table result{(f,t) in S} OUT "CSV" "result.csv": f~FROM, t~TO, +% x[f,t]~FLOW; +% \end{verbatim} +% +% The table statement allows reading data from a table into model +% objects such as sets and (non-scalar) parameters as well as writing +% data from the model to a table. + +\newpage + +\subsection{Estrutura de tabelas} + +Uma {\it tabela de dados} é um conjunto (desordenado) de {\it registros}, onde cada +registro consiste do mesmo número de {\it campos} e cada campo possui um único +nome simbólico denominado o {\it nome do campo}. Por exemplo: + +\bigskip + +\begin{tabular}{@{\hspace*{42mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c +@{\hspace*{9mm}}c} +Primeiro&Segundo&&Último\\ +campo&campo&.\ \ .\ \ .&campo\\ +$\downarrow$&$\downarrow$&&$\downarrow$\\ +\end{tabular} + +\begin{tabular}{ll@{}} +Cabeçalho da tabela&$\rightarrow$\\ +Primeiro registro&$\rightarrow$\\ +Segundo registro&$\rightarrow$\\ +\\ +\hfil .\ \ .\ \ .\\ +\\ +Último registro&$\rightarrow$\\ +\end{tabular} +\begin{tabular}{|l|l|c|c|} +\hline +{\tt DE}&{\tt PARA}&{\tt DISTANCIA}&{\tt CUSTO}\\ +\hline +{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +\hline +\end{tabular} + + +% A {\it data table} is an (unordered) set of {\it records}, where each +% record consists of the same number of {\it fields}, and each field is +% provided with a unique symbolic name called the {\it field name}. For +% example: +% +% \bigskip +% +% \begin{tabular}{@{\hspace*{42mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c +% @{\hspace*{9mm}}c} +% First&Second&&Last\\ +% field&field&.\ \ .\ \ .&field\\ +% $\downarrow$&$\downarrow$&&$\downarrow$\\ +% \end{tabular} +% +% \begin{tabular}{ll@{}} +% Table header&$\rightarrow$\\ +% First record&$\rightarrow$\\ +% Second record&$\rightarrow$\\ +% \\ +% \hfil .\ \ .\ \ .\\ +% \\ +% Last record&$\rightarrow$\\ +% \end{tabular} +% \begin{tabular}{|l|l|c|c|} +% \hline +% {\tt FROM}&{\tt TO}&{\tt DISTANCE}&{\tt COST}\\ +% \hline +% {\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +% {\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +% {\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +% {\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +% {\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +% {\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +% \hline +% \end{tabular} + +\subsection{Lendo dados de uma tabela de entrada} + +A sentença tabela de entrada faz a leitura de dados +da tabela especificada, registro por registro. + +Uma vez que o registro subsequente foi lido, valores numéricos ou simbólicos +dos campos, cujos nomes são cercados entre colchetes na sentença table, +são reunidos em um $n$-tuplo. Se o conjunto de controle é especificado +na sentença table, este $n$-tuplo é adicionado a ele. Além disso, um valor +numérico ou simbólico de cada campo associado com um parâmetro do modelo +é atribuído ao membro do parâmetro identificado por subíndices, que são +componentes da $n$-tupla que acabou de ser lida. + +Por exemplo, a seguinte sentença de tabela de entrada: + +\noindent\hfil +\verb|table dados IN "...": S <- [DE,PARA], d~DISTANCIA, c~CUSTO;| + +\noindent +faz a leitura de valores de quatro campos chamados {\tt DE}, {\tt PARA}, +{\tt DISTANCIA} e {\tt CUSTO} de cada registro da tabela especificada. +Os valores dos campos {\tt DE} e {\tt PARA} dão um par $(f,t)$, que é +adicionado ao conjunto de controle {\tt S}. O valor do campo {\tt DISTANCIA} é +atribuído ao membro do parâmetro ${\tt d}[f,t]$ enquanto que o valor do campo +{\tt CUSTO} é atribuído ao membro do parâmetro ${\tt c}[f,t]$. + +Note que a tabela de entrada pode conter campos adicionais cujos nomes +não sejam especificados na sentença tabela, neste caso, os valores destes +campos serão ignorados na leitura da tabela. + +% The input table statement causes reading data from the specified table +% record by record. +% +% Once a next record has been read, numeric or symbolic values of fields, +% whose names are enclosed in square brackets in the table statement, are +% gathered into $n$-tuple, and if the control set is specified in the +% table statement, this $n$-tuple is added to it. Besides, a numeric or +% symbolic value of each field associated with a model parameter is +% assigned to the parameter member identified by subscripts, which are +% components of the $n$-tuple just read. +% +% For example, the following input table statement: +% +% \noindent\hfil +% \verb|table data IN "...": S <- [FROM,TO], d~DISTANCE, c~COST;| +% +% \noindent +% causes reading values of four fields named {\tt FROM}, {\tt TO}, +% {\tt DISTANCE}, and {\tt COST} from each record of the specified table. +% Values of fields {\tt FROM} and {\tt TO} give a pair $(f,t)$, which is +% added to the control set {\tt S}. The value of field {\tt DISTANCE} is +% assigned to parameter member ${\tt d}[f,t]$, and the value of field +% {\tt COST} is assigned to parameter member ${\tt c}[f,t]$. +% +% Note that the input table may contain extra fields whose names are not +% specified in the table statement, in which case values of these fields +% on reading the table are ignored. + +\subsection{Escrevendo dados em uma tabela de saída} + +A sentença tabela de saída gera a escrita de dados na tabela especificada. +Note que alguns controladores (chamados CSV e xBASE) destroem a tabela de saída +antes de escrever os dados, i.e., deletam todos os registros existentes. + +Cada $n$-tupla no domínio do conjunto especificado gera um registro escrito na +tabela de saída. Os valores dos campos são valores numéricos ou simbólicos +das expressões correspondentes especificadas na sentença table. Estas +expressões são avaliadas para cada $n$-tupla no conjunto do domínio, +portanto, podem incluir índices introduzidos na expressão indexante correspondente. + +Por exemplo, a seguinte sentença da tabela de saída: + +\noindent\hfil +\verb|table resultado{(f,t) in S} OUT "...": f~DE, t~PARA, x[f,t]~FLUXO;| + +\noindent +gera a escrita de registros; um registro para cada par $(f,t)$ no conjunto +{\tt S} para a tabela de saída, onde cada registro consiste de três campos +chamados {\tt DE}, {\tt PARA} e {\tt FLUXO}. Os valores escritos nos campos +{\tt DE} e {\tt PARA} são os valores correntes dos índices {\tt f} e {\tt t}. +O valor escrito no campo {\tt FLUXO} é um valor do membro ${\tt x}[f,t]$ +do correspondente parâmetro ou variável indexada. + + +% The output table statement causes writing data to the specified table. +% Note that some drivers (namely, CSV and xBASE) destroy the output table +% before writing data, i.e. delete all its existing records. +% +% Each $n$-tuple in the specified domain set generates one record written +% to the output table. Values of fields are numeric or symbolic values of +% corresponding expressions specified in the table statement. These +% expressions are evaluated for each $n$-tuple in the domain set and, +% thus, may include dummy indices introduced in the corresponding indexing +% expression. +% +% For example, the following output table statement: +% +% \noindent\hfil +% \verb|table result{(f,t) in S} OUT "...": f~FROM, t~TO, x[f,t]~FLOW;| +% +% \noindent +% causes writing records, by one record for each pair $(f,t)$ in set +% {\tt S}, to the output table, where each record consists of three +% fields named {\tt FROM}, {\tt TO}, and {\tt FLOW}. The values written +% to fields {\tt FROM} and {\tt TO} are current values of dummy indices +% {\tt f} and {\tt t}, and the value written to field {\tt FLOW} is +% a value of member ${\tt x}[f,t]$ of corresponding subscripted parameter +% or variable. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Dados do modelo} + +Os {\it dados do modelo} includem conjuntos elementares, que são ``valores'' dos +conjuntos do modelo, e valores numéricos e simbólicos dos parâmetros do modelo. + +Em MathProg existem duas formas diferentes de fornecer valores aos conjuntos +e parâmetros do modelo. Uma forma é simplesmente prover os dados necessários +usando o atributo de atribuição. No entanto, em muitos casos é mais prático separar +o modelo próprio dos dados particulares necessários para o modelo. Para o último +caso, em MathProg há uma outra forma, em que a descrição do modelo é dividida +em duas partes: a seção de modelo e a seção de dados. + +A {\it seção de modelo} é a principal parte da descrição do modelo. Ela contém +todas as declarações de todos objetos do modelo, sendo comum a todos problemas +baseados naquele modelo. + +A {\it seção de dados} é uma parte opcional da descrição do modelo que contém +dados específicos para um problema particular. + +Em MathProg seções de modelo e de dados podem ser localizadas tanto em um arquivo +de texto ou em dois arquivos de texto separados. + +1. Se ambas seções de modelo e de dados estão localizados em um arquivo, +o arquivo é composto como segue: + + + +\bigskip + +\noindent\hfil +\framebox{\begin{tabular}{l} +{\it sentença}{\tt;}\\ +{\it sentença}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentença}{\tt;}\\ +{\tt data;}\\ +{\it bloco de dados}{\tt;}\\ +{\it bloco de dados}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloco de dados}{\tt;}\\ +{\tt end;} +\end{tabular}} + + + +% {\it Model data} include elemental sets, which are ``values'' of model +% sets, and numeric and symbolic values of model parameters. +% +% In MathProg there are two different ways to saturate model sets and +% parameters with data. One way is simply providing necessary data using +% the assign attribute. However, in many cases it is more practical to +% separate the model itself and particular data needed for the model. For +% the latter reason in MathProg there is another way, when the model +% description is divided into two parts: model section and data section. +% +% A {\it model section} is a main part of the model description that +% contains declarations of all model objects and is common for all +% problems based on that model. +% +% A {\it data section} is an optional part of the model description that +% contains model data specific for a particular problem. +% +% In MathProg model and data sections can be placed either in one text +% file or in two separate text files. +% +% 1. If both model and data sections are placed in one file, the file is +% composed as follows: +% +% \bigskip +% +% \noindent\hfil +% \framebox{\begin{tabular}{l} +% {\it statement}{\tt;}\\ +% {\it statement}{\tt;}\\ +% \hfil.\ \ .\ \ .\\ +% {\it statement}{\tt;}\\ +% {\tt data;}\\ +% {\it data block}{\tt;}\\ +% {\it data block}{\tt;}\\ +% \hfil.\ \ .\ \ .\\ +% {\it data block}{\tt;}\\ +% {\tt end;} +% \end{tabular}} + +% 2. Se a seção de modelo e dados são posicionados em dois arquivos separados, os +% arquivos são compostos como segue: + +\newpage + +2. Se a seção de modelo e dados são posicionados em dois arquivos separados, os +arquivos são compostos como segue: + +\bigskip + +\noindent\hfil +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\it sentença}{\tt;}\\ +{\it sentença}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentença}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\\\Arquivo de modelo\\ +\end{tabular} +\hspace{32pt} +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\tt data;}\\ +{\it bloco de dados}{\tt;}\\ +{\it bloco de dados}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloco de dados}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\Arquivo de dados\\ +\end{tabular} + +\bigskip + +Nota: Se a seção de dados é posicionada em um arquivo separado, a palavra-chave +{\tt data} é opcional e pode ser omitida juntamente como o ponto e vírgula que a segue. + + +% \bigskip +% +% \noindent\hfil +% \begin{tabular}{@{}c@{}} +% \framebox{\begin{tabular}{l} +% {\it statement}{\tt;}\\ +% {\it statement}{\tt;}\\ +% \hfil.\ \ .\ \ .\\ +% {\it statement}{\tt;}\\ +% {\tt end;}\\ +% \end{tabular}}\\ +% \\\\Model file\\ +% \end{tabular} +% \hspace{32pt} +% \begin{tabular}{@{}c@{}} +% \framebox{\begin{tabular}{l} +% {\tt data;}\\ +% {\it data block}{\tt;}\\ +% {\it data block}{\tt;}\\ +% \hfil.\ \ .\ \ .\\ +% {\it data block}{\tt;}\\ +% {\tt end;}\\ +% \end{tabular}}\\ +% \\Data file\\ +% \end{tabular} +% +% \bigskip +% +% Note: If the data section is placed in a separate file, the keyword +% {\tt data} is optional and may be omitted along with the semicolon that +% follows it. + + +\section{Programando a seção de dados} + +A {\it seção de dados} é uma sequência de blocos de dados em vários formatos +e são discutidos nas seções seguintes. A ordem na qual os blocos de dados +seguem na seção de dados pode ser arbitrária, portanto, não precisa ser +necessariamente a mesma ordem que seguem os elementos correspondentes +da seção de modelo. + +As regras para programar a seção de dados são comumente as mesmas que as regras +de \linebreak programar a descrição do modelo (ver Seção \ref{coding}, página +\pageref{coding}), i.e., blocos de dados são compostos com unidades léxicas +básicas, como nomes simbólicos, literais numéricos e de cadeia, +palavras-chave, \linebreak delimitadores e comentários. No entanto, por conveniência +e para melhorar legibilidade, há um desvio da regra comum: se um literal +de cadeia consiste unicamente de caracteres alfanuméricos (incluindo +o caractere sublinhado), os sinais {\tt+} e {\tt-} e/ou o ponto decimal, +ele pode ser programado sem aspas limitadoras (simples ou duplas). + +Todo material numérico e simbólico provido na seção de dados é programado +na forma de números e símbolos, i.e., diferentemente da seção de modelo, +não são permitidas expressões na seção de dados. Apesar disso, os sinais +{\tt+} e {\tt-} podem preceder literais numéricos para permitir a programação +de quantidades numéricas com sinais. Neste caso não deve haver caractere de +espaço em branco entre o sinal e o literal numérico seguinte (se houver +pelo menos uma espaço em branco, o sinal e o literal numérico seguinte são +reconhecidos como duas unidades léxicas diferentes). + + + +% The {\it data section} is a sequence of data blocks in various formats, +% which are discussed in following sections. The order, in which data +% blocks follow in the data section, may be arbitrary, not necessarily +% the same, in which corresponding model objects follow in the model +% section. +% +% The rules of coding the data section are commonly the same as the rules +% of coding the model description (see Section \ref{coding}, page +% \pageref{coding}), i.e. data blocks are composed from basic lexical +% units such as symbolic names, numeric and string literals, keywords, +% delimiters, and comments. However, for the sake of convenience and for +% improving readability there is one deviation from the common rule: if +% a string literal consists of only alphanumeric characters (including +% the underscore character), the signs {\tt+} and {\tt-}, and/or the +% decimal point, it may be coded without bordering by (single or double) +% quotes. +% +% All numeric and symbolic material provided in the data section is coded +% in the form of numbers and symbols, i.e. unlike the model section +% no expressions are allowed in the data section. Nevertheless, the signs +% {\tt+} and {\tt-} can precede numeric literals to allow coding signed +% numeric quantities, in which case there should be no white-space +% characters between the sign and following numeric literal (if there is +% at least one white-space, the sign and following numeric literal are +% recognized as two different lexical units). + +\newpage + +\section{Bloco de dados set} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nome} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt set} {\it nome} {\tt[} {\it símbolo} {\tt,} \dots +{\tt,} {\it símbolo} {\tt]} {\tt,} {\it registro} {\tt,} \dots {\tt,} +{\it registro} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico do conjunto; + +\noindent +{\it símbolo}, \dots, {\it símbolo} são subíndices que especificam +um membro particular do conjunto \linebreak(se o conjunto é uma matriz, i.e., +um conjunto de conjuntos); + +\noindent +{\it registro}, \dots, {\it registro} são registros. + +\noindent +As vírgulas que precedem os registros podem ser omitidas. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +é um elemento de atribuição de registro não-significativo que pode ser usado +livremente para melhorar a legibilidade; +\item[{\tt(} {\it fatia} {\tt)}]\hspace*{0pt}\\ +especifica uma fatia; +\item[{\it dados-simples}]\hspace*{0pt}\\ +especifica os dados do conjunto em formato simples; +\item[{\tt:} {\it dados matriciais}]\hspace*{0pt}\\ +especifica os dados do conjunto em formato de matriz; +\item[{\tt(tr)} {\tt:} {\it dados matriciais}]\hspace*{0pt}\\ +especifica os dados do conjunto em formato de matriz transposta. +(Neste caso, os dois pontos que seguem a palavra-chave {\tt(tr)} podem ser omitidos). +\end{description} + +\vspace*{-8pt} + +\para{Exemplos} + +\begin{verbatim} +set mes := Jan Fev Mar Abr Mai Jun; +set mes "Jan", "Fev", "Mar", "Abr", "Mai", "Jun"; +set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; +set A[3,'Mar'] : 1 2 3 4 := + 1 - + - - + 2 - + + - + 3 + - - + + 4 - + - + ; +set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +set B := (1,*,*) : 1 2 3 := + 1 + - - + 2 - + + + 3 - + - + (2,*,*) : 1 2 3 := + 1 + - + + 2 - - - + 3 + - - ; +\end{verbatim} + +\noindent(Nestes exemplos {\tt mes} é um conjunto simples de singletos, +{\tt A} é uma matriz 2-dimensional de duplas e {\tt B} é um conjunto +simples de triplas. Os blocos de dados para o mesmo conjunto são equivalentes +no sentido que especificam os mesmos dados em formatos distintos.) + +O {\it bloco de dados do conjunto} é usado para especificar um conjunto elementar +completo que é atribuído a um conjunto (se é um conjunto simples) ou a um de +seus membros (se o conjunto é uma matriz de conjuntos).\footnote{Há uma outra forma +de especificar dados para um conjunto simples com dados para os parâmetros. +Esta questão é discutida na próxima seção.} + +Blocos de dados podem ser especificados somente para conjuntos não-calculáveis, +i.e., para \linebreak conjuntos que possuem o atributo de atribuição ({\tt:=}) +na sentença set correspondente. + +Se o conjunto é um conjunto simples, somente seus nomes simbólicos devem ser +especificados no cabeçalho do bloco de dados. Caso contrário, se o conjunto +é uma matriz $n$-dimensional, seus nomes simbólicos devem ser fornecidos com +uma lista completa de subíndices separados por vírgulas e cercados em colchetes +para especificar um membro particular da matriz de conjuntos. O número de +subíndices deve ser igual ao da dimensão da matriz de conjuntos, onde +cada subíndice deve ser um número ou um símbolo. + +Um conjunto elementar definido no bloco de dados é programado como uma sequência +de \linebreak registros descritos abaixo.\footnote{{\it Registro} é simplesmente +um termo técnico. Não significa que os mesmos possuem qualquer formato +especial.} + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][44pt]{468pt}{ +% \hspace{6pt} {\tt set} {\it name} {\tt,} {\it record} {\tt,} \dots +% {\tt,} {\it record} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt set} {\it name} {\tt[} {\it symbol} {\tt,} \dots +% {\tt,} {\it symbol} {\tt]} {\tt,} {\it record} {\tt,} \dots {\tt,} +% {\it record} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the set; +% +% \noindent +% {\it symbol}, \dots, {\it symbol} are subscripts, which specify +% a particular member of the set (if the set is an array, i.e. a set of +% sets); +% +% \noindent +% {\it record}, \dots, {\it record} are data records. +% +% \noindent +% Commae preceding data records may be omitted. +% +% \para{Data records} +% +% \vspace*{-8pt} +% +% \begin{description} +% \item[{\tt :=}]\hspace*{0pt}\\ +% is a non-significant data record, which may be used freely to improve +% readability; +% \item[{\tt(} {\it slice} {\tt)}]\hspace*{0pt}\\ +% specifies a slice; +% \item[{\it simple-data}]\hspace*{0pt}\\ +% specifies set data in the simple format; +% \item[{\tt:} {\it matrix-data}]\hspace*{0pt}\\ +% specifies set data in the matrix format; +% \item[{\tt(tr)} {\tt:} {\it matrix-data}]\hspace*{0pt}\\ +% specifies set data in the transposed matrix format. (In this case the +% colon following the keyword {\tt(tr)} may be omitted.) +% \end{description} +% +% \vspace*{-8pt} +% +% \para{Examples} +% +% \begin{verbatim} +% set month := Jan Feb Mar Apr May Jun; +% set month "Jan", "Feb", "Mar", "Apr", "May", "Jun"; +% set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +% set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; +% set A[3,'Mar'] : 1 2 3 4 := +% 1 - + - - +% 2 - + + - +% 3 + - - + +% 4 - + - + ; +% set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +% set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +% set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +% set B := (1,*,*) : 1 2 3 := +% 1 + - - +% 2 - + + +% 3 - + - +% (2,*,*) : 1 2 3 := +% 1 + - + +% 2 - - - +% 3 + - - ; +% \end{verbatim} +% +% \noindent(In these examples {\tt month} is a simple set of singlets, +% {\tt A} is a 2-dimensional array of doublets, and {\tt B} is a simple +% set of triplets. Data blocks for the same set are equivalent in the +% sense that they specify the same data in different formats.) +% +% The {\it set data block} is used to specify a complete elemental set, +% which is assigned to a set (if it is a simple set) or one of its +% members (if the set is an array of sets).\footnote{There is another way +% to specify data for a simple set along with data for parameters. This +% feature is discussed in the next section.} +% +% Data blocks can be specified only for non-computable sets, i.e. for +% sets, which have no assign attribute ({\tt:=}) in the corresponding set +% statements. +% +% If the set is a simple set, only its symbolic name should be specified +% in the header of the data block. Otherwise, if the set is a +% $n$-dimensional array, its symbolic name should be provided with a +% complete list of subscripts separated by commae and enclosed in square +% brackets to specify a particular member of the set array. The number of +% subscripts should be the same as the dimension of the set array, where +% each subscript should be a number or symbol. +% +% An elemental set defined in the set data block is coded as a sequence +% of data records described below.\footnote{{\it Data record} is simply a +% technical term. It does not mean that data records have any special +% formatting.} + + +\subsection{Registro de atribuição de dados} + +O {\it registro de atribuição de dados} ({\tt:=}) é um elemento não-significante. +Ele pode ser usado para melhorar a legibilidade de blocos de dados. + +% The {\it assign data record} ({\tt:=}) is a non-signficant element. +% It may be used for improving readability of data blocks. + +\subsection{Registro em fatia de dados} + +O {\it registro em fatia de dados} é um registro de controle que especifica +uma {\it fatia} do conjunto elementar definido no bloco de dados. Ele possui +a seguinte forma sintática: +$$\mbox{{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}}$$ +onde $s_1$, $s_2$, \dots, $s_n$ são componentes da fatia. + +Cada componente da fatia pode ser um número, símbolo ou asterisco +({\tt*}). O número de \linebreak componentes na fatia deve ser o mesmo da +dimensão $n$-tuplas do conjunto elementar a ser definido. Por exemplo, +se o conjunto elementar contém 4-tuplas (quádruplas), a fatia deve ter +quatro \linebreak componentes. O número de asteriscos na fatia denomina a +{\it dimensão da fatia}. + +O efeito de usar fatias é o seguinte: se uma fatia $m$-dimensional +(i.e., uma fatia contendo $m$ asteriscos) é especificada no bloco de dados, +todos registros subsequentes devem especificar tuplas de dimensão~$m$. +Sempre que uma $m$-tupla é encontrada, cada asterisco da fatia é substituído +pelos componentes correspondentes da $m$-tupla, o que resulta na +$n$-tupla, que é incluída no conjunto \linebreak elementar a ser definido. +Por exemplo, se a fatia $(a,*,1,2,*)$ está vigente e a dupla +$(3,b)$ é encontrada no registro subsequente, a 5-tupla resultante a ser incluída +no conjunto elementar é $(a,3,1,2,b)$. + +Se a fatia não possui asteriscos, ela própria define uma $n$-tupla completa +que é incluída no conjunto elementar. + +Uma vez especificada uma fatia, a mesma está vigente até que apareça uma nova +fatia ou até que se encontre o fim do bloco de dados. Note que se uma fatia +não é especificada no bloco de dados, assume-se uma cujos componentes são +asteriscos em todas as posições. + + +% The {\it slice data record} is a control record, which specifies a +% {\it slice} of the elemental set defined in the data block. It has the +% following syntactic form: +% $$\mbox{{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}}$$ +% where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. +% +% Each component of the slice can be a number or symbol or the asterisk +% ({\tt*}). The number of components in the slice should be the same as +% the dimension of $n$-tuples in the elemental set to be defined. For +% instance, if the elemental set contains 4-tuples (quadruplets), the +% slice should have four components. The number of asterisks in the slice +% is called the {\it slice dimension}. +% +% The effect of using slices is the following. If a $m$-dimensional slice +% (i.e. a slice having $m$ asterisks) is specified in the data block, all +% subsequent data records should specify tuples of the dimension~$m$. +% Whenever a $m$-tuple is encountered, each asterisk in the slice is +% replaced by corresponding components of the $m$-tuple that gives the +% resultant $n$-tuple, which is included in the elemental set to be +% defined. For example, if the slice $(a,*,1,2,*)$ is in effect, and +% 2-tuple $(3,b)$ is encountered in a subsequent data record, the +% resultant 5-tuple included in the elemental set is $(a,3,1,2,b)$. +% +% The slice having no asterisks itself defines a complete $n$-tuple, +% which is included in the elemental set. +% +% Being once specified the slice effects until either a new slice or the +% end of data block is encountered. Note that if no slice is specified in +% the data block, one, components of which are all asterisks, is assumed. + +\subsection{Registro simples} + +O {\it registro simples} define uma $n$-tupla em um formato simples +e possui a seguinte forma sintática: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +onde $t_1$, $t_2$, \dots, $t_n$ são componentes da $n$-tupla. Cada +componente pode ser um número ou um símbolo. As vírgulas entre os componentes +são opcionais e podem ser omitidas. + +% The {\it simple data record} defines one $n$-tuple in a simple format +% and has the following syntactic form: +% $$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +% where $t_1$, $t_2$, \dots, $t_n$ are components of the $n$-tuple. Each +% component can be a number or symbol. Commae between components are +% optional and may be omitted. + +\subsection{Registro de matriz} + +O {\it registro de matriz} define diversas 2-tuplas (duplas) em +um formato matricial e possui a seguinte forma sintática: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +onde $r_1$, $r_2$, \dots, $r_m$ são números e/ou símbolos +que correspondem a linhas da matriz; $c_1$, $c_2$, \dots, $c_n$ são +números e/ou símbolos que correspondem a colunas da matriz, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ são elementos da matriz, que podem ser tanto +{\tt+} como {\tt-}. (Neste registro, o delimitador {\tt:} que precede a +lista de colunas e o delimitador {\tt:=} que segue após a lista de colunas, +não podem ser omitidos.) + +Cada elemento $a_{ij}$ do bloco de dados matricial (onde $1\leq i\leq m$, +$1\leq j\leq n$) correspondem a 2-tuplas $(r_i,c_j)$. Se $a_{ij}$ é o +sinal mais ({\tt+}), a 2-tupla correspondente (ou uma $n$-tupla maior, se uma +fatia é usada) é incluída no conjunto elementar. Caso contrário, se $a_{ij}$ é o +sinal menos ({\tt-}), aquela 2-tupla não é incluída no conjunto elementar. + +Uma vez que o registro de matriz define 2-tuplas, tanto o conjunto elementar +quanto a fatia vigente devem ser 2-dimensional. + +\newpage + +\subsection{Registro de matriz transposta} + +O {\it registro de matriz transposta} possui a seguinte forma sintática: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(Neste caso, o delimitador {\tt:} que segue a palavra-chave {\tt(tr)} é +opcional e pode ser omitido.) + +Este registro é completamente análogo ao registro de matriz (ver +anteriormente) com a única exceção de que neste caso, cada elemento $a_{ij}$ da +matriz passa a corresponder a 2-tupla $(c_j,r_i)$ ao invés de $(r_i,c_j)$. + +Uma vez especificado, o indicador {\tt(tr)} tem alcance em todos registros +subsequentes até que se encontre outra fatia ou o fim do bloco de dados. + + +% The {\it transposed matrix data record} has the following syntactic +% form: +% $$\begin{array}{cccccc} +% \mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +% r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +% r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +% \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +% r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +% \end{array}$$ +% (In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +% optional and may be omitted.) +% +% This data record is completely analogous to the matrix data record (see +% above) with only exception that in this case each element $a_{ij}$ of +% the matrix corresponds to 2-tuple $(c_j,r_i)$ rather than $(r_i,c_j)$. +% +% Being once specified the {\tt(tr)} indicator affects all subsequent +% data records until either a slice or the end of data block is +% encountered. + +\section{Bloco de dados de parâmetro} + +\noindent +\framebox[468pt][l]{ +\parbox[c][88pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nome} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\it nome} {\tt default} {\it valor} {\tt,} +{\it registro} {\tt,} \dots {\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt:} {\it dados-tabulação} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt default} {\it valor} {\tt:} +{\it dados-tabulação} {\tt;} +}} + +\medskip + +\noindent +{\it nome} é um nome simbólico do parâmetro; + +\noindent +{\it valor} é um valor opcional padrão do parâmetro; + +\noindent +{\it registro}, \dots, {\it registro} são registros; + +\noindent +{\it dados-tabulação} especifica os dados do parâmetro em formato tabulação. + +\noindent +As vírgulas que precedem os registros podem ser omitidas. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +é um elemento de atribuição de registro não-significativo que pode ser usado +livremente para melhorar a legibilidade; +\item[{\tt[} {\it fatia} {\tt]}]\hspace*{0pt}\\ +especifica uma fatia; +\item[{\it dados-planos}]\hspace*{0pt}\\ +especifica os dados do parâmetro em formato simples; +\item[{\tt:} {\it dados-tabulares}]\hspace*{0pt}\\ +especifica dados do parâmetro em formato tabular; +\item[{\tt(tr)} {\tt:} {\it dados-tabulares}]\hspace*{0pt}\\ +especifica dados do parâmetro no formato tabular transposto. +(Neste caso, os dois pontos que seguem a palavra-chave {\tt(tr)} podem ser omitidos). +\end{description} + +\vspace*{-8pt} + +\para{Exemplos} + +\begin{verbatim} +param T := 4; +param mes := 1 Jan 2 Fev 3 Mar 4 Abr 5 Mai; +param mes := [1] 'Jan', [2] 'Fev', [3] 'Mar', [4] 'Abr', [5] 'Mai'; +param estoque_inicial := ferro 7.32 niquel 35.8; +param estoque_inicial [*] ferro 7.32, niquel 35.8; +param custo [ferro] .025 [niquel] .03; +param valor := ferro -.1, niquel .02; +param : estoque_inicial custo valor := + ferro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param : insumo : estoque_inicial custo valor := + ferro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param demanda default 0 (tr) + : FRA DET LAN WIN STL FRE LAF := + chapa 300 . 100 75 . 225 250 + bobina 500 750 400 250 . 850 500 + placa 100 . . 50 200 . 250 ; +param custo_transporte := + [*,*,chapa]: FRA DET LAN WIN STL FRE LAF := + GARY 30 10 8 10 11 71 6 + CLEV 22 7 10 7 21 82 13 + PITT 19 11 12 10 25 83 15 + [*,*,bobina]: FRA DET LAN WIN STL FRE LAF := + GARY 39 14 11 14 16 82 8 + CLEV 27 9 12 9 26 95 17 + PITT 24 14 17 13 28 99 20 + [*,*,placa]: FRA DET LAN WIN STL FRE LAF := + GARY 41 15 12 16 17 86 8 + CLEV 29 9 13 9 28 99 18 + PITT 26 14 17 13 31 104 20 ; +\end{verbatim} + +O {\it bloco de dados do parâmetro} é usado para especificar dados +completos para um parâmetro (ou parâmetros, se os dados são especificados +no formato tabulação). + +Os blocos de dados podem ser especificados apenas para parâmetros não-calculáveis, i.e., +para parâmetros que não possuem o atributo de atribuição ({\tt:=}) nas +sentenças parameter correspondentes. + +Os dados definidos no bloco de dados do parâmetro são programados como uma sequência +de registros descritos em seguida. Adicionalmente, o bloco de dados pode vir com +o atributo opcional {\tt default}, que especifica um valor numérico ou simbólico +padrão do parâmetro (ou parâmetros). Este valor padrão é atribuído ao parâmetro ou +a seus membros quando não se definem valores apropriados no bloco de dados do +parâmetro. O atributo {\tt default} não pode ser usado se ele já tiver sido +especificado na sentença parameter correspondente. + + +% \noindent +% \framebox[468pt][l]{ +% \parbox[c][88pt]{468pt}{ +% \hspace{6pt} {\tt param} {\it name} {\tt,} {\it record} {\tt,} \dots +% {\tt,} {\it record} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt param} {\it name} {\tt default} {\it value} {\tt,} +% {\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt param} {\tt:} {\it tabbing-data} {\tt;} +% +% \medskip +% +% \hspace{6pt} {\tt param} {\tt default} {\it value} {\tt:} +% {\it tabbing-data} {\tt;} +% }} +% +% \medskip +% +% \noindent +% {\it name} is a symbolic name of the parameter; +% +% \noindent +% {\it value} is an optional default value of the parameter; +% +% \noindent +% {\it record}, \dots, {\it record} are data records; +% +% \noindent +% {\it tabbing-data} specifies parameter data in the tabbing format. +% +% \noindent +% Commae preceding data records may be omitted. +% +% \para{Data records} +% +% \vspace*{-8pt} +% +% \begin{description} +% \item[{\tt :=}]\hspace*{0pt}\\ +% is a non-significant data record, which may be used freely to improve +% readability; +% \item[{\tt[} {\it slice} {\tt]}]\hspace*{0pt}\\ +% specifies a slice; +% \item[{\it plain-data}]\hspace*{0pt}\\ +% specifies parameter data in the plain format; +% \item[{\tt:} {\it tabular-data}]\hspace*{0pt}\\ +% specifies parameter data in the tabular format; +% \item[{\tt(tr)} {\tt:} {\it tabular-data}]\hspace*{0pt}\\ +% specifies set data in the transposed tabular format. (In this case the +% colon following the keyword {\tt(tr)} may be omitted.) +% \end{description} +% +% \vspace*{-8pt} +% +% \para{Examples} +% +% \begin{verbatim} +% param T := 4; +% param month := 1 Jan 2 Feb 3 Mar 4 Apr 5 May; +% param month := [1] 'Jan', [2] 'Feb', [3] 'Mar', [4] 'Apr', [5] 'May'; +% param init_stock := iron 7.32 nickel 35.8; +% param init_stock [*] iron 7.32, nickel 35.8; +% param cost [iron] .025 [nickel] .03; +% param value := iron -.1, nickel .02; +% param : init_stock cost value := +% iron 7.32 .025 -.1 +% nickel 35.8 .03 .02 ; +% param : raw : init stock cost value := +% iron 7.32 .025 -.1 +% nickel 35.8 .03 .02 ; +% param demand default 0 (tr) +% : FRA DET LAN WIN STL FRE LAF := +% bands 300 . 100 75 . 225 250 +% coils 500 750 400 250 . 850 500 +% plate 100 . . 50 200 . 250 ; +% param trans_cost := +% [*,*,bands]: FRA DET LAN WIN STL FRE LAF := +% GARY 30 10 8 10 11 71 6 +% CLEV 22 7 10 7 21 82 13 +% PITT 19 11 12 10 25 83 15 +% [*,*,coils]: FRA DET LAN WIN STL FRE LAF := +% GARY 39 14 11 14 16 82 8 +% CLEV 27 9 12 9 26 95 17 +% PITT 24 14 17 13 28 99 20 +% [*,*,plate]: FRA DET LAN WIN STL FRE LAF := +% GARY 41 15 12 16 17 86 8 +% CLEV 29 9 13 9 28 99 18 +% PITT 26 14 17 13 31 104 20 ; +% \end{verbatim} +% +% The {\it parameter data block} is used to specify complete data for a +% parameter (or parameters, if data are specified in the tabbing format). +% +% Data blocks can be specified only for non-computable parameters, i.e. +% for parameters, which have no assign attribute ({\tt:=}) in the +% corresponding parameter statements. +% +% Data defined in the parameter data block are coded as a sequence of +% data records described below. Additionally the data block can be +% provided with the optional {\tt default} attribute, which specifies a +% default numeric or symbolic value of the parameter (parameters). This +% default value is assigned to the parameter or its members when +% no appropriate value is defined in the parameter data block. The +% {\tt default} attribute cannot be used, if it is already specified in +% the corresponding parameter statement. + +\subsection{Registro de atribuição} + +O {\it registro de atribuição} ({\tt:=}) é um elemento não-significativo. +Ele pode ser usado para melhorar a legibilidade dos blocos de dados; + +% The {\it assign data record} ({\tt:=}) is a non-signficant element. +% It may be used for improving readability of data blocks. + +\subsection{Registro em fatia} + +O {\it registro em fatia} é um registro de controle que especifica uma +{\it fatia} da matriz do parâmetro. Ele tem a seguinte forma sintática: +$$\mbox{{\tt[} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt]}}$$ +onde $s_1$, $s_2$, \dots, $s_n$ são componentes da fatia. + +Cada componente da fatia pode ser um número, símbolo ou asterisco +({\tt*}). O número de componentes na fatia deve ser o mesmo da +dimensão $n$-tuplas do parâmetro. Por exemplo, +se o parâmetro é uma matriz 4-dimensional, a fatia deve ter +quatro componentes. O número de \linebreak asteriscos na fatia denomina a +{\it dimensão da fatia}. + +O efeito de usar fatias é o seguinte: se uma fatia $m$-dimensional +(i.e., uma fatia contendo $m$ asteriscos) é especificada no bloco de dados, +todos registros subsequentes devem especificar os subíndices do membros do +parâmetro, como se o parâmetro fosse $m$-dimensional, não $n$-dimensional. + +Sempre que $m$ subíndices são encontrados, cada asterisco da fatia é substituído +pelos \linebreak componentes correspondentes que dão $n$ subíndices, que definem o +membro corrente do parâmetro. +Por exemplo, se a fatia $(a,*,1,2,*)$ está vigente e os subíndices 3 e +$b$ são encontradas no \linebreak registro subsequente, a lista completa de subíndices +usada para escolher o membro do parâmetro é $(a,3,1,2,b)$. + + +É permitido especificar uma fatia que não tenha asteriscos. Tal fatia, em si +própria, define uma lista completa de subíndice, em cujo caso o próximo +registro deve definir apenas um único valor do membro correspondentes do parâmetro. + +Uma vez especificada uma fatia, a mesma está vigente até que apareça uma nova +fatia ou até que se encontre o fim do bloco de dados. Note que se uma fatia +não é especificada no bloco de dados, assume-se uma cujos componentes são +asteriscos em todas as posições. + + +\subsection{Registro plano} + +O {\it registro plano} define uma lista de subíndice e um valor individual +no formato plano. Este registro possui a seguinte forma sintática: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +onde $t_1$, $t_2$, \dots, $t_n$ são subíndices e $v$ é um valor. +Cada subíndice, assim como o valor, pode ser um número ou um símbolo. As +vírgulas que seguem os subíndices são opcionais e podem ser omitidas. + +No caso de um parâmetro ou fatia 0-dimensional, o registro plano não possui +subíndice e consiste de um valor individual apenas. + + +% The {\it plain data record} defines a subscript list and a single value +% in the plain format. This record has the following syntactic form: +% $$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +% where $t_1$, $t_2$, \dots, $t_n$ are subscripts, and $v$ is a value. +% Each subscript as well as the value can be a number or symbol. Commae +% following subscripts are optional and may be omitted. +% +% In case of 0-dimensional parameter or slice the plain data record has +% no subscripts and consists of a single value only. + +\subsection{Registro tabular} + +O {\it registro tabular} define diversos valores onde cada valor é provido +de dois subíndices. Este registro possui a seguinte forma sintática: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +onde $r_1$, $r_2$, \dots, $r_m$ são números e/ou símbolos +que correspondem a linhas da tabela; enquanto que $c_1$, $c_2$, \dots, $c_n$ são +são números e/ou símbolos que correspondem a colunas da tabela, $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ são elementos da tabela. Cada elemento pode ser +um número, símbolo ou o ponto decimal ({\tt.}) individual. (neste registro, +o delimitador {\tt:} que precede a lista de colunas e o delimitador +{\tt:=} que segue após a lista de colunas, não podem ser omitidos). + +Cada elemento $a_{ij}$ do bloco de dados tabulares ($1\leq i\leq m$, +$1\leq j\leq n$) define dois subíndices, onde o primeiro subíndice é +$r_i$ e o segundo é $c_j$. Estes subíndices são usados juntamente com +a fatia vigente para formar a lista completa de subíndices que identifica +um membro particular da matriz de parâmetros. Se $a_{ij}$ +é um número ou um símbolo, este valor é atribuído ao membro do parâmetro. +No entanto, se $a_{ij}$ é um ponto decimal individual, o membro é atribuído +ao valor padrão especificado ou no bloco de dados do parâmetro +ou na sentença parameter, ou ainda, se nenhum valor padrão é especificado, +o membro permanece indefinido. + +Uma vez que o registro tabular fornece dois subíndices para cada valor, +tanto o parâmetro quanto a fatia vigente em uso devem ser 2-dimensional. + + +% The {\it tabular data record} defines several values, where each value +% is provided with two subscripts. This record has the following +% syntactic form: +% $$\begin{array}{cccccc} +% \mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +% r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +% r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +% \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +% r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +% \end{array}$$ +% where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols +% corresponding to rows of the table; $c_1$, $c_2$, \dots, $c_n$ are +% numbers and/or symbols corresponding to columns of the table, $a_{11}$, +% $a_{12}$, \dots, $a_{mn}$ are table elements. Each element can be a +% number or symbol or the single decimal point ({\tt.}). (In this data +% record the delimiter {\tt:} preceding the column list and the delimiter +% {\tt:=} following the column list cannot be omitted.) +% +% Each element $a_{ij}$ of the tabular data block ($1\leq i\leq m$, +% $1\leq j\leq n$) defines two subscripts, where the first subscript is +% $r_i$, and the second one is $c_j$. These subscripts are used in +% conjunction with the current slice to form the complete subscript list +% that identifies a particular member of the parameter array. If $a_{ij}$ +% is a number or symbol, this value is assigned to the parameter member. +% However, if $a_{ij}$ is the single decimal point, the member is +% assigned a default value specified either in the parameter data block +% or in the parameter statement, or, if no default value is specified, +% the member remains undefined. +% +% Since the tabular data record provides two subscripts for each value, +% either the parameter or the slice currently used should be +% 2-dimensional. + +\subsection{Registro tabular transposto} + +O {\it registro tabular transposto} possui a seguinte forma sintática: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(Neste caso, o delimitador {\tt:} que segue a palavra-chave {\tt(tr)} é +opcional e pode ser omitida.) + +Este registro é completamente análogo ao registro tabular +(ver anteriormente) com a única exceção que o primeiro subíndice definido +pelo elemento $a_{ij}$ é $c_j$ enquanto que o segundo é $r_i$. + +Uma vez especificado, o indicador {\tt(tr)} afeta todos registros subsequentes +até que se encontre outra fatia ou o fim do bloco de dados. + + +% The {\it transposed tabular data record} has the following syntactic +% form: +% $$\begin{array}{cccccc} +% \mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +% r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +% r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +% \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +% r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +% \end{array}$$ +% (In this case the delimiter {\tt:} following the keyword {\tt(tr)} is +% optional and may be omitted.) +% +% This data record is completely analogous to the tabular data record +% (see above) with only exception that the first subscript defined by +% element $a_{ij}$ is $c_j$ while the second one is $r_i$. +% +% Being once specified the {\tt(tr)} indicator affects all subsequent +% data records until either a slice or the end of data block is +% encountered. + +% \newpage + +\subsection{Formato de dados em tabulação} + +O bloco de dados do parâmetro no {\it formato tabulação} possui a seguinte +forma sintática: +$$ +\begin{array}{*{8}{l}} +\multicolumn{4}{l} +{{\tt param}\ {\tt default}\ valor\ {\tt :}\ s\ {\tt :}}& +p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_r\ \ \verb|:=|\\ +r_{11}\ \verb|,|& r_{12}\ \verb|,|& \dots\ \verb|,|& r_{1n}\ \verb|,|& +a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1r}\ \verb|,|\\ +r_{21}\ \verb|,|& r_{22}\ \verb|,|& \dots\ \verb|,|& r_{2n}\ \verb|,|& +a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2r}\ \verb|,|\\ +\dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +r_{m1}\ \verb|,|& r_{m2}\ \verb|,|& \dots\ \verb|,|& r_{mn}\ \verb|,|& +a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mr}\ \verb|;|\\ +\end{array} +$$ + +1. A palavra-chave {\tt default} pode ser omitida juntamente +com o valor que a segue. + +2. O nome simbólico $s$ pode ser omitido juntamente com +os dois pontos que o segue. + +3. Todas as vírgulas são opcionais e podem ser omitidas. + +O bloco de dados no formato tabulação mostrado acima é exatamente +equivalente aos seguintes blocos de dados: + +\verb|set| $s$\ \verb|:=|\ $ +\verb|(|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|) | +\verb|(|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|) | +\dots +\verb| (|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|);|$ + +\verb|param| $p_1$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{11} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{21} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m1} +\verb|;| +$ + +\verb|param| $p_2$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{12} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{22} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m2} +\verb|;| +$ + +\verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . + +\verb|param| $p_r$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{1r} +\verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{2r} +\verb| |\dots +\verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{mr} +\verb|;| +$ + + +% The parameter data block in the {\it tabbing format} has the following +% syntactic form: +% $$ +% \begin{array}{*{8}{l}} +% \multicolumn{4}{l} +% {{\tt param}\ {\tt default}\ value\ {\tt :}\ s\ {\tt :}}& +% p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_r\ \ \verb|:=|\\ +% r_{11}\ \verb|,|& r_{12}\ \verb|,|& \dots\ \verb|,|& r_{1n}\ \verb|,|& +% a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1r}\ \verb|,|\\ +% r_{21}\ \verb|,|& r_{22}\ \verb|,|& \dots\ \verb|,|& r_{2n}\ \verb|,|& +% a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2r}\ \verb|,|\\ +% \dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +% r_{m1}\ \verb|,|& r_{m2}\ \verb|,|& \dots\ \verb|,|& r_{mn}\ \verb|,|& +% a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mr}\ \verb|;|\\ +% \end{array} +% $$ +% +% 1. The keyword {\tt default} may be omitted along with a value +% following it. +% +% 2. Symbolic name $s$ may be omitted along with the colon following it. +% +% 3. All commae are optional and may be omitted. +% +% The data block in the tabbing format shown above is exactly equivalent +% to the following data blocks: +% +% \verb|set| $s$\ \verb|:=|\ $ +% \verb|(|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|) | +% \verb|(|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|) | +% \dots +% \verb| (|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|);|$ +% +% \verb|param| $p_1$\ \verb|default|\ $value$\ \verb|:=| +% +% $\verb| | +% \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{11} +% \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{21} +% \verb| |\dots +% \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m1} +% \verb|;| +% $ +% +% \verb|param| $p_2$\ \verb|default|\ $value$\ \verb|:=| +% +% $\verb| | +% \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{12} +% \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{22} +% \verb| |\dots +% \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m2} +% \verb|;| +% $ +% +% \verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . +% +% \verb|param| $p_r$\ \verb|default|\ $value$\ \verb|:=| +% +% $\verb| | +% \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{1r} +% \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{2r} +% \verb| |\dots +% \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{mr} +% \verb|;| +% $ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\chapter{Usando sufixos} + +\vspace*{-12pt} + +Sufixos podem ser usados para recuperar valores adicionais +associados com as variáveis, restrições e objetivos do modelo. + +Um {\it sufixo} consiste de um ponto ({\tt.}) seguido por uma palavra-chave +não-reservada. Por exemplo, se {\tt x} é uma variável bi-dimensional, +{\tt x[i,j].lb} é um valor numérico igual ao limite inferior da variável +elementar {\tt x[i,j]}, que (cujo valor) pode ser usado em expressões +como um parâmetro numérico. + +Para as variáveis do modelo, os sufixos possuem o seguinte significado: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&limite inferior (lower bound)\\ +{\tt.ub}&limite superior (upper bound)\\ +{\tt.status}&status na solução:\\ +&0 --- indefinida\\ +&1 --- básica\\ +&2 --- não-básica no limite inferior\\ +&3 --- não-básica no limite superior\\ +&4 --- variável não-básica livre (ilimitada)\\ +&5 --- variável não-básica fixa\\ +{\tt.val}&valor primal na solução\\ +{\tt.dual}&valor dual (custo reduzido) na solução\\ +\end{tabular} + +Para as restrições e objetivos do modelo, os sufixos têm os seguintes significados: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&limite inferior (lower bound) da forma linear\\ +{\tt.ub}&limite superior (upper bound) da forma linear\\ +{\tt.status}&status na solução:\\ +&0 --- indefinida\\ +&1 --- não-limitante\\ +&2 --- limitante no limite inferior\\ +&3 --- limitante no limite superior\\ +&4 --- linha limitante livre (ilimitada)\\ +&5 --- restrição de igualdade limitante\\ +{\tt.val}&valor primal da forma linear na solução\\ +{\tt.dual}&valor dual (custo reduzido) da forma linear na solução\\ +\end{tabular} + +Note que os sufixos {\tt.status}, {\tt.val} e {\tt.dual} podem ser usados +apenas abaixo da sentença solve. + + +% Suffixes can be used to retrieve additional values associated with +% model variables, constraints, and objectives. +% +% A {\it suffix} consists of a period ({\tt.}) followed by a non-reserved +% keyword. For example, if {\tt x} is a two-dimensional variable, +% {\tt x[i,j].lb} is a numeric value equal to the lower bound of +% elemental variable {\tt x[i,j]}, which (value) can be used everywhere +% in expressions like a numeric parameter. +% +% For model variables suffixes have the following meaning: +% +% \begin{tabular}{@{}ll@{}} +% {\tt.lb}&lower bound\\ +% {\tt.ub}&upper bound\\ +% {\tt.status}&status in the solution:\\ +% &0 --- undefined\\ +% &1 --- basic\\ +% &2 --- non-basic on lower bound\\ +% &3 --- non-basic on upper bound\\ +% &4 --- non-basic free (unbounded) variable\\ +% &5 --- non-basic fixed variable\\ +% {\tt.val}&primal value in the solution\\ +% {\tt.dual}&dual value (reduced cost) in the solution\\ +% \end{tabular} +% +% For model constraints and objectives suffixes have the following +% meaning: +% +% \begin{tabular}{@{}ll@{}} +% {\tt.lb}&lower bound of the linear form\\ +% {\tt.ub}&upper bound of the linear form\\ +% {\tt.status}&status in the solution:\\ +% &0 --- undefined\\ +% &1 --- non-active\\ +% &2 --- active on lower bound\\ +% &3 --- active on upper bound\\ +% &4 --- active free (unbounded) row\\ +% &5 --- active equality constraint\\ +% {\tt.val}&primal value of the linear form in the solution\\ +% {\tt.dual}&dual value (reduced cost) of the linear form in the +% solution\\ +% \end{tabular} +% +% Note that suffixes {\tt.status}, {\tt.val}, and {\tt.dual} can be used +% only below the solve statement. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Funções de data e hora} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +e Heinrich Schuchardt \verb||\\ +\end{tabular} + +\section{Obtendo o tempo de calendário corrente} +\label{gmtime} + +Para obter o tempo de calendário corrente em MathProg existe a função +{\tt gmtime}. Ela não possui argumentos e retorna o número de segundos +transcorridos desde 00:00:00 de 1{\textsuperscript{\b{o}}} +de Janeiro de 1970, pelo +Tempo Universal Coordenado (UTC). Por exemplo: + +\begin{verbatim} + param utc := gmtime(); +\end{verbatim} + +MathProg não possui uma função para converter o tempo UTC retornado pela função +{\tt gmtime} para os tempos de calendário {\it local}. Assim, para +determinar o tempo de calendário local corrente, é preciso que adicione ao +tempo UTC retornado a diferença de horas, com respeito a UTC, expressa em +segundos. Por exemplo, a hora em Berlim durante o inverno é uma hora à frente +do UTC, que corresponde a uma diferença horária de +1~hora~= +3600~segundos, +assim, o tempo de calendário corrente no inverno em Berlim pode ser determinado +como segue: + +\begin{verbatim} + param now := gmtime() + 3600; +\end{verbatim} + +\noindent De forma análoga, o horário de verão em Chicago (Zona Horária Central-CDT) +é cinco horas atrás da UTC, de modo que o horário corrente do calendário local +pode ser determinado como segue: + +\begin{verbatim} + param now := gmtime() - 5 * 3600; +\end{verbatim} + +Note que o valor retornado por {\tt gmtime} é volátil, i.e., ao ser +chamada diversas vezes, esta função pode retornar diferentes valores. + +% \noindent\hfil +% \begin{tabular}{c} +% by Andrew Makhorin \verb||\\ +% and Heinrich Schuchardt \verb||\\ +% \end{tabular} +% +% \section{Obtaining current calendar time} +% \label{gmtime} +% +% To obtain the current calendar time in MathProg there exists the +% function {\tt gmtime}. It has no arguments and returns the number of +% seconds elapsed since 00:00:00 on January 1, 1970, Coordinated +% Universal Time (UTC). For example: +% +% \begin{verbatim} +% param utc := gmtime(); +% \end{verbatim} +% +% MathProg has no function to convert UTC time returned by the function +% {\tt gmtime} to {\it local} calendar times. Thus, if you need to +% determine the current local calendar time, you have to add to the UTC +% time returned the time offset from UTC expressed in seconds. For +% example, the time in Berlin during the winter is one hour ahead of UTC +% that corresponds to the time offset +1~hour~= +3600~secs, so the +% current winter calendar time in Berlin may be determined as follows: +% +% \begin{verbatim} +% param now := gmtime() + 3600; +% \end{verbatim} +% +% \noindent Similarly, the summer time in Chicago (Central Daylight Time) +% is five hours behind UTC, so the corresponding current local calendar +% time may be determined as follows: +% +% \begin{verbatim} +% param now := gmtime() - 5 * 3600; +% \end{verbatim} +% +% Note that the value returned by {\tt gmtime} is volatile, i.e. being +% called several times this function may return different values. + +\section{Convertendo cadeia de caracteres ao tempo de calendário} +\label{str2time} + +A função {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converte uma +cadeia de caractere (impressão da data e hora) \linebreak especificada pelo seu +primeiro argumento {\it s}, que deve ser uma expressão simbólica, +para o tempo de calendário apropriado para cálculos aritméticos. +A conversão é controlada pela cadeia de formato especificado {\it f} +(o segundo argumento), que também deve ser uma expressão simbólica. + + +% The function {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converts a +% character string (timestamp) specified by its first argument {\it s}, +% which should be a symbolic expression, to the calendar time suitable +% for arithmetic calculations. The conversion is controlled by the +% specified format string {\it f} (the second argument), which also +% should be a symbolic expression. + +% \newpage + + +A conversão resultante retornada por {\tt str2time} possui o mesmo significado +dos valores retornados pela função {\tt gmtime} (ver Subseção +\ref{gmtime}, página \pageref{gmtime}). Note que {\tt str2time} +{\tt não corrige} o tempo de calendário retornado para zona horária local, +i.e., ao se aplicar a 00:00:00 de 1{\textsuperscript{\b{o}}} +de Janeiro de 1970, ela sempre retorna 0. + +% The result of conversion returned by {\tt str2time} has the same +% meaning as values returned by the function {\tt gmtime} (see Subsection +% \ref{gmtime}, page \pageref{gmtime}). Note that {\tt str2time} does +% {\tt not} correct the calendar time returned for the local timezone, +% i.e. being applied to 00:00:00 on January 1, 1970 it always returns 0. + +Por exemplo, as sentenças de modelo: + +\begin{verbatim} + param s, symbolic, := "07/14/98 13:47"; + param t := str2time(s, "%m/%d/%y %H:%M"); + display t; +\end{verbatim} + +\noindent produz a seguinte saída: + +\begin{verbatim} + t = 900424020 +\end{verbatim} + +\noindent onde o tempo de calendário impresso corresponde a 13:47:00 em +14 de Julho de 1998. + +A cadeia de formato passada à função {\tt str2time} consiste de +especificadores de conversão e caracteres ordinários. Cada especificador de +conversão inicia com um caractere de porcentagem ({\tt\%}) seguido de +uma letra. + +Os seguintes especificadores de conversão podem ser usados na cadeia de formato: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&O nome do mês abreviado (insensível a maiúsculas). Pelo menos as três +primeiras letras do mês devem aparecer na cadeia de entrada.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&O dia do mês como número decimal (de 1 até 31). +Se permite o zero como primeiro dígito, embora não seja necessário.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&O mesmo que {\tt\%b}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&A hora como um número decimal, usando um relógio de 24-horas (de 0 +a 23). Se permite o zero como primeiro dígito, embora não seja necessário.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&O mês como um número decimal (de 1 a 12). +Se permite o zero como primeiro dígito, embora não seja necessário.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&O minuto como um número decimal (de 0 a 59). +Se permite o zero como primeiro dígito, embora não seja necessário.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&O segundo como um número decimal (de 0 to 60). +Se permite o zero como primeiro dígito, embora não seja necessário.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&O ano sem o século, como um número decimal (de 0 to 99). +Se permite o zero como primeiro dígito, embora não seja necessário. +Valores de entrada de 0 a 68 são considerados dos anos 2000 a 2068 +enquanto que os valores 69 até 99 como dos anos 1969 to 1999.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%z}&A diferença horária do GMT no formato ISO 8601.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&Um caractere {\tt\%} literal.\\ +\end{tabular} + +Todos os outros caracteres (ordinários) na cadeia de formato devem ter um +caractere \linebreak correspondente com a cadeia de entrada a ser convertida. Exceções +são espaços na cadeia de entrada, a qual pode coincidir com zero ou mais +caracteres de espaço na cadeia de formato. + +% For example, the model statements: +% +% \begin{verbatim} +% param s, symbolic, := "07/14/98 13:47"; +% param t := str2time(s, "%m/%d/%y %H:%M"); +% display t; +% \end{verbatim} +% +% \noindent produce the following printout: +% +% \begin{verbatim} +% t = 900424020 +% \end{verbatim} +% +% \noindent where the calendar time printed corresponds to 13:47:00 on +% July 14, 1998. +% +% The format string passed to the function {\tt str2time} consists of +% conversion specifiers and ordinary characters. Each conversion +% specifier begins with a percent ({\tt\%}) character followed by a +% letter. +% +% The following conversion specifiers may be used in the format string: +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%b}&The abbreviated month name (case insensitive). At least three +% first letters of the month name should appear in the input string.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%d}&The day of the month as a decimal number (range 1 to 31). +% Leading zero is permitted, but not required.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%h}&The same as {\tt\%b}.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 0 +% to 23). Leading zero is permitted, but not required.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%m}&The month as a decimal number (range 1 to 12). Leading zero is +% permitted, but not required.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%M}&The minute as a decimal number (range 0 to 59). Leading zero +% is permitted, but not required.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%S}&The second as a decimal number (range 0 to 60). Leading zero +% is permitted, but not required.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%y}&The year without a century as a decimal number (range 0 to 99). +% Leading zero is permitted, but not required. Input values in the range +% 0 to 68 are considered as the years 2000 to 2068 while the values 69 to +% 99 as the years 1969 to 1999.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%z}&The offset from GMT in ISO 8601 format.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%\%}&A literal {\tt\%} character.\\ +% \end{tabular} +% +% All other (ordinary) characters in the format string should have a +% matching character in the input string to be converted. Exceptions are +% spaces in the input string which can match zero or more space +% characters in the format string. + +% \newpage + +Se algum componente de data e/ou hora estão ausentes no formato e, +portanto, na cadeia de entrada, a função {\tt str2time} usa seus valores +padrão correspondendo a 00:00:00 de 1{\textsuperscript{\b{o}}} +de Janeiro de 1970, ou seja, o valor padrão para o ano é 1970, o valor +padrão para o mês é Janeiro, etc. + +A função {\tt str2time} é aplicável a todos horários calendário desde +00:00:00 de 1{\textsuperscript{\b{o}}} de Janeiro de 0001 até 23:59:59 +de 31 de Dezembro de 4000 do calendário Gregoriano. + +% If some date and/or time component(s) are missing in the format and, +% therefore, in the input string, the function {\tt str2time} uses their +% default values corresponding to 00:00:00 on January 1, 1970, that is, +% the default value of the year is 1970, the default value of the month +% is January, etc. +% +% The function {\tt str2time} is applicable to all calendar times in the +% range 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of +% the Gregorian calendar. + + + +\section{Convertendo tempo de calendário a uma cadeia de caracteres} +\label{time2str} + +A função {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converte o tempo +de calendário especificado pelo seu primeiro \linebreak argumento {\it t}, que +deve ser uma expressão numérica, para uma cadeia de caracteres +(valor \linebreak simbólico). A conversão é controlada pela cadeia de formato +{\it f} (o segundo argumento), que deve ser uma expressão numérica. + +O tempo de calendário passado para {\tt time2str} possui o mesmo +significado dos valores retornados pela função {\tt gmtime} (ver Subseção +\ref{gmtime}, página \pageref{gmtime}). Note que {\tt time2str} +{\it não corrige} o tempo de calendário especificado para zona horária local, +i.e., o tempo de calendário 0 sempre corresponde a 00:00:00 de +1{\textsuperscript{\b{o}}} de Janeiro de 1970. + +Por exemplo, as sentenças de modelo: + +\begin{verbatim} + param s, symbolic, := time2str(gmtime(), "%FT%TZ"); + display s; +\end{verbatim} + +\noindent pode produzir a seguinte impressão: + +\begin{verbatim} + s = '2008-12-04T00:23:45Z' +\end{verbatim} + +\noindent que é a impressão da data e hora no formato ISO. + +A cadeia de formato passada para a função {\tt time2str} consiste de +especificadores de conversão e caracteres ordinários. Cada especificador +de conversão começa com um caractere de porcentagem ({\tt\%}) seguido +de uma letra. + +Os seguintes especificadores de conversão podem ser usados na cadeia de formato: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%a}&O nome do dia da semana abreviado(2 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%A}&O nome do dia da semana completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&O nome do dia do mês abreviado (3 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%B}&O nome do mês completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%C}&O século do ano, ou seja, o maior inteiro não maior que o +ano dividido por~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&O dia do mês como um número decimal (de 01 até 31).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%D}&A data usando o formato \verb|%m/%d/%y|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%e}&O dia do mês, como em \verb|%d|, mas preenchido com espaço +em branco ao invés de zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%F}&A data usando o formato \verb|%Y-%m-%d|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%g}&O ano correspondente ao número de semana ISO, mas sem o século +(de 00 até~99). Este possui o mesmo formato e valor que \verb|%y|, +exceto que se o número de semana ISO (ver \verb|%V|) pertence +ao ano anterior ou seguinte, se usa aquele ano em seu lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%G}&O ano correspondente ao número de semana ISO. +Este possui o mesmo formato e valor que \verb|%Y|, +exceto que se o número de semana ISO (ver \verb|%V|) pertence +ao ano anterior ou seguinte, se usa aquele ano em seu lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&O mesmo que \verb|%b|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&A hora como um número decimal usando um relógio 24 horas (de 00 até 23).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%I}&A hora como um número decimal usando um relógio 12 horas (de 01 até 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%j}&O dia do ano como um número decimal (de 001 até 366).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%k}&A hora como um número decimal usando um relógio 24 horas, como +\verb|%H|, mas preenchido com espaço em branco ao invés de zero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%l}&A hora como um número decimal usando um relógio 12 horas, como +\verb|%I|, mas preenchido com espaço em branco ao invés de zero. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&O mês como um número decimal (de 01 até 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&O minuto como um número decimal (de 00 até 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%p}&Tanto {\tt AM} como {\tt PM}, de acordo com o valor da hora fornecido. +Meia-noite é tratada como {\tt AM} e meio-dia, como {\tt PM}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%P}&Tanto {\tt am} como {\tt pm}, de acordo com o valor da hora fornecido. +Meia-noite é tratada como {\tt am} e meio-dia, como {\tt pm}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%R}&A hora e minuto em números decimais usando o formato +\verb|%H:%M|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&O segundo como um número decimal (de 00 até 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%T}&A hora do dia em números decimais usando o formato +\verb|%H:%M:%S|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%u}&O dia da semana como número decimal (de 1 até 7) em que Segunda +é 1.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%U}&O número da semana do ano corrente como um número decimal (de +00 até 53) iniciando com o primeiro Domingo como o primeiro dia da +primeira semana. Os dias que precedem o primeiro Domingo do ano são +considerados parte da semana 00. +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%V}&O número da semana ISO como um número decimal (de 01 até 53). +Semanas ISO iniciam com Segunda e finalizam com Domingo. +A semana 01 de um ano é a primeira semana que possui a maioria de +seus dias naquele ano. Isto é equivalente à semana contendo 4 de +Janeiro. A semana 01 de um ano pode conter dias do ano anterior. +A semana anterior à semana 01 de um ano é a última semana +(52 ou 53) do ano anterior, mesmo se ela contém dias do novo ano. +Em outras palavras, se 1{\textsuperscript{\b{o}}} de Janeiro +é Segunda, Terça, Quarta ou Quinta, ele está na semana 01; +Se 1{\textsuperscript{\b{o}}} de Janeiro é Sexta, +Sábado ou Domingo, ele está na semana 52 ou 53 do ano anterior.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%w}&O dia da semana como um número decimal (de 0 até 6) em que Domingo +é 0.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%W}&O número da semana do ano corrente como um número decimal (de +00 até 53), iniciando com a primeira Segunda como o primeiro dia da primeira +semana. Dias que precedem a primeira Segunda do ano são considerados parte +da semana 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&O ano sem o século como um número decimal (de 00 até +99), ou seja, o ano \verb|mod|~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%Y}&O ano como um número decimal, usando o calendário Gregoriano.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&Um caractere \verb|%| literal.\\ +\end{tabular} + +Todos os outros caracteres (ordinários) na cadeia de formato são simplesmente copiados +à cadeia resultante. + +O primeiro argumento (tempo do calendário) passado para a função {\tt time2str} +deve estar entre $-62135596800$ até $+64092211199$, o que corresponde ao período +de 00:00:00 de 1{\textsuperscript{\b{o}}} de Janeiro de 0001 até 23:59:59 +de 31 de Dezembro de 4000 do calendário Gregoriano. + + +% The function {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converts the +% calendar time specified by its first argument {\it t}, which should be +% a numeric expression, to a character string (symbolic value). The +% conversion is controlled by the specified format string {\it f} (the +% second argument), which should be a symbolic expression. +% +% The calendar time passed to {\tt time2str} has the same meaning as +% values returned by the function {\tt gmtime} (see Subsection +% \ref{gmtime}, page \pageref{gmtime}). Note that {\tt time2str} does +% {\it not} correct the specified calendar time for the local timezone, +% i.e. the calendar time 0 always corresponds to 00:00:00 on January 1, +% 1970. +% +% For example, the model statements: +% +% \begin{verbatim} +% param s, symbolic, := time2str(gmtime(), "%FT%TZ"); +% display s; +% \end{verbatim} +% +% \noindent may produce the following printout: +% +% \begin{verbatim} +% s = '2008-12-04T00:23:45Z' +% \end{verbatim} +% +% \noindent which is a timestamp in the ISO format. +% +% The format string passed to the function {\tt time2str} consists of +% conversion specifiers and ordinary characters. Each conversion +% specifier begins with a percent ({\tt\%}) character followed by a +% letter. +% +% The following conversion specifiers may be used in the format string: +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%a}&The abbreviated (2-character) weekday name.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%A}&The full weekday name.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%b}&The abbreviated (3-character) month name.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%B}&The full month name.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%C}&The century of the year, that is the greatest integer not +% greater than the year divided by~100.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%d}&The day of the month as a decimal number (range 01 to 31).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%D}&The date using the format \verb|%m/%d/%y|.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%e}&The day of the month like with \verb|%d|, but padded with +% blank rather than zero.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%F}&The date using the format \verb|%Y-%m-%d|.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%g}&The year corresponding to the ISO week number, but without the +% century (range 00 to~99). This has the same format and value as +% \verb|%y|, except that if the ISO week number (see \verb|%V|) belongs +% to the previous or next year, that year is used instead.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%G}&The year corresponding to the ISO week number. This has the +% same format and value as \verb|%Y|, except that if the ISO week number +% (see \verb|%V|) belongs to the previous or next year, that year is used +% instead. +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%h}&The same as \verb|%b|.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 00 +% to 23).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%I}&The hour as a decimal number, using a 12-hour clock (range 01 +% to 12).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%j}&The day of the year as a decimal number (range 001 to 366).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%k}&The hour as a decimal number, using a 24-hour clock like +% \verb|%H|, but padded with blank rather than zero.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%l}&The hour as a decimal number, using a 12-hour clock like +% \verb|%I|, but padded with blank rather than zero. +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%m}&The month as a decimal number (range 01 to 12).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%M}&The minute as a decimal number (range 00 to 59).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%p}&Either {\tt AM} or {\tt PM}, according to the given time value. +% Midnight is treated as {\tt AM} and noon as {\tt PM}.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%P}&Either {\tt am} or {\tt pm}, according to the given time value. +% Midnight is treated as {\tt am} and noon as {\tt pm}.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%R}&The hour and minute in decimal numbers using the format +% \verb|%H:%M|.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%S}&The second as a decimal number (range 00 to 59).\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%T}&The time of day in decimal numbers using the format +% \verb|%H:%M:%S|.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%u}&The day of the week as a decimal number (range 1 to 7), Monday +% being 1.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%U}&The week number of the current year as a decimal number (range +% 00 to 53), starting with the first Sunday as the first day of the first +% week. Days preceding the first Sunday in the year are considered to be +% in week 00. +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%V}&The ISO week number as a decimal number (range 01 to 53). ISO +% weeks start with Monday and end with Sunday. Week 01 of a year is the +% first week which has the majority of its days in that year; this is +% equivalent to the week containing January 4. Week 01 of a year can +% contain days from the previous year. The week before week 01 of a year +% is the last week (52 or 53) of the previous year even if it contains +% days from the new year. In other word, if 1 January is Monday, Tuesday, +% Wednesday or Thursday, it is in week 01; if 1 January is Friday, +% Saturday or Sunday, it is in week 52 or 53 of the previous year.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%w}&The day of the week as a decimal number (range 0 to 6), Sunday +% being 0.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%W}&The week number of the current year as a decimal number (range +% 00 to 53), starting with the first Monday as the first day of the first +% week. Days preceding the first Monday in the year are considered to be +% in week 00.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%y}&The year without a century as a decimal number (range 00 to +% 99), that is the year modulo~100.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%Y}&The year as a decimal number, using the Gregorian calendar.\\ +% \end{tabular} +% +% \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +% {\tt\%\%}&A literal \verb|%| character.\\ +% \end{tabular} +% +% All other (ordinary) characters in the format string are simply copied +% to the resultant string. +% +% The first argument (calendar time) passed to the function {\tt time2str} +% should be in the range from $-62135596800$ to $+64092211199$ that +% corresponds to the period from 00:00:00 on January 1, 0001 to 23:59:59 +% on December 31, 4000 of the Gregorian calendar. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\chapter{Controladores de tabelas} +\label{drivers} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +e Heinrich Schuchardt \verb||\\ +\end{tabular} + +\bigskip\bigskip + +O {\it controlador de tabelas} é um módulo do programa que permite transmitir +dados entre objetos de um modelo MathProg e tabela de dados. + +Atualmente, o pacote GLPK possui quatro controladores de tabelas: + +\vspace*{-8pt} + +\begin{itemize} +\item controlador interno de tabelas CSV; +\item controlador interno de tabelas xBASE; +\item controlador de tabelas ODBC; +\item controlador de tabelas MySQL. +\end{itemize} + + +% The {\it table driver} is a program module which provides transmitting +% data between MathProg model objects and data tables. +% +% Currently the GLPK package has four table drivers: +% +% \vspace*{-8pt} +% +% \begin{itemize} +% \item built-in CSV table driver; +% \item built-in xBASE table driver; +% \item ODBC table driver; +% \item MySQL table driver. +% \end{itemize} + +\vspace*{-8pt} + +\section{Controlador de tabelas CSV} + +O controlador de tabelas CSV assume que a tabela de dados está representada +na forma de \linebreak arquivo de texto plano, em formato de arquivo CSV +(valores serparados por vígula: \linebreak comma-separated values) como descrito +abaixo. + +Para escolher o controlador de tabelas CSV, seu nome na sentença table deve ser +especificado como \verb|"CSV"| e o único argumento deve especificar o nome do +arquivo de texto plano contendo a tabela. Por exemplo: + +\begin{verbatim} + table dados IN "CSV" "dados.csv": ... ; +\end{verbatim} + +O sufixo do nome do arquivo pode ser arbitrário, no entanto, +é recomendado usar o sufixo `\verb|.csv|'. + +Ao ler tabelas de entrada o controlador de tabelas CSV fornece um campo +implícito chamado \verb|RECNO|, que contém o número do registro corrente. +Este campo pode ser especificado na sentença de entrada table, como +se realmente houvesse um campo chamado \verb|RECNO| no arquivo CSV. Por exemplo: + +\begin{verbatim} + table lista IN "CSV" "lista.csv": num <- [RECNO], ... ; +\end{verbatim} + + +% The CSV table driver assumes that the data table is represented in the +% form of a plain text file in the CSV (comma-separated values) file +% format as described below. +% +% To choose the CSV table driver its name in the table statement should +% be specified as \verb|"CSV"|, and the only argument should specify the +% name of a plain text file containing the table. For example: +% +% \begin{verbatim} +% table data IN "CSV" "data.csv": ... ; +% \end{verbatim} +% +% The filename suffix may be arbitrary, however, it is recommended to use +% the suffix `\verb|.csv|'. +% +% On reading input tables the CSV table driver provides an implicit field +% named \verb|RECNO|, which contains the current record number. This +% field can be specified in the input table statement as if there were +% the actual field named \verb|RECNO| in the CSV file. For example: +% +% \begin{verbatim} +% table list IN "CSV" "list.csv": num <- [RECNO], ... ; +% \end{verbatim} + +\newpage + +\subsection*{Formato CSV\footnote{Este material é baseado no documento RFC +4180.}} + +O formato CSV (\textit{comma-separated values}) é um formato de arquivo de texto plano +definido como segue. + +1. Cada registro é localizado em uma linha separada, delimitada por uma quebra de linha. Por exemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +\noindent +onde \verb|\n| significa o caractere de controle \verb|LF| ({\tt 0x0A}). + +2. O último registro no arquivo pode ou não ter a quebra de linha. Por exemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz +\end{verbatim} + +3. Deve haver uma linha de cabeçalho na primeira linha do arquivo no +mesmo formato das linhas de registros normais. Este cabeçalho deve +conter nomes correspondendo aos campos no arquivo. O número de nomes +de campos na linha de cabeçalho deve ser o mesmo do número de campos +dos registros do arquivo. Por exemplo: + +\begin{verbatim} + nome1,nome2,nome3\n + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +4. Dentro do cabeçalho e de cada registro, podem haver um ou mais campos +separados por vírgulas. Cada linha deve conter o mesmo número de campos +por todos arquivo. Espaços são considerados parte de um campo, portanto, +não são ignorados. O último campo do registro não deve ser seguido de +vírgula. Por exemplo: + +\begin{verbatim} + aaa,bbb,ccc\n +\end{verbatim} + +5. Campos podem ou não estar cercados em aspas duplas. Por exemplo: + +\begin{verbatim} + "aaa","bbb","ccc"\n + zzz,yyy,xxx\n +\end{verbatim} + +6. Se um campo é cercado de aspas duplas, cada aspa dupla que faça +parte do campo deve ser codificado duas vezes. Por exemplo: + +\begin{verbatim} + "aaa","b""bb","ccc"\n +\end{verbatim} + +\para{Exemplo} + +\begin{verbatim} +DE,PARA,DISTANCIA,CUSTO +Seattle,New-York,2.5,0.12 +Seattle,Chicago,1.7,0.08 +Seattle,Topeka,1.8,0.09 +San-Diego,New-York,2.5,0.15 +San-Diego,Chicago,1.8,0.10 +San-Diego,Topeka,1.4,0.07 +\end{verbatim} + + + +% The CSV (comma-separated values) format is a plain text file format +% defined as follows. +% +% 1. Each record is located on a separate line, delimited by a line +% break. For example: +% +% \begin{verbatim} +% aaa,bbb,ccc\n +% xxx,yyy,zzz\n +% \end{verbatim} +% +% \noindent +% where \verb|\n| means the control character \verb|LF| ({\tt 0x0A}). +% +% 2. The last record in the file may or may not have an ending line +% break. For example: +% +% \begin{verbatim} +% aaa,bbb,ccc\n +% xxx,yyy,zzz +% \end{verbatim} +% +% 3. There should be a header line appearing as the first line of the +% file in the same format as normal record lines. This header should +% contain names corresponding to the fields in the file. The number of +% field names in the header line should be the same as the number of +% fields in the records of the file. For example: +% +% \begin{verbatim} +% name1,name2,name3\n +% aaa,bbb,ccc\n +% xxx,yyy,zzz\n +% \end{verbatim} +% +% 4. Within the header and each record there may be one or more fields +% separated by commas. Each line should contain the same number of fields +% throughout the file. Spaces are considered as part of a field and +% therefore not ignored. The last field in the record should not be +% followed by a comma. For example: +% +% \begin{verbatim} +% aaa,bbb,ccc\n +% \end{verbatim} +% +% 5. Fields may or may not be enclosed in double quotes. For example: +% +% \begin{verbatim} +% "aaa","bbb","ccc"\n +% zzz,yyy,xxx\n +% \end{verbatim} +% +% 6. If a field is enclosed in double quotes, each double quote which is +% part of the field should be coded twice. For example: +% +% \begin{verbatim} +% "aaa","b""bb","ccc"\n +% \end{verbatim} +% +% \para{Example} +% +% \begin{verbatim} +% FROM,TO,DISTANCE,COST +% Seattle,New-York,2.5,0.12 +% Seattle,Chicago,1.7,0.08 +% Seattle,Topeka,1.8,0.09 +% San-Diego,New-York,2.5,0.15 +% San-Diego,Chicago,1.8,0.10 +% San-Diego,Topeka,1.4,0.07 +% \end{verbatim} + +\newpage + +\section{Controlador de tabelas xBASE} + +O controlador de tabelas xBASE assume que a tabela de dados é armazenada no +formato de arquivo .dbf. + +Para escolher o controlador de tabela xBASE, seu nome na sentença table deve ser +especificado como \verb|"xBASE"| e o primeiro argumento deve especificar o nome +de um arquivo .dbf contendo a tabela. Para a tabela de saída deve haver um +segundo argumento definindo o formato da tabela na forma +\verb|"FF...F"|, onde \verb|F| é tanto {\tt C({\it n})}, +que especifica um campo de caractere de tamanho $n$, ou +{\tt N({\it n}{\rm [},{\it p}{\rm ]})}, que especifica um campo numérico +de tamanho $n$ e precisão $p$ (por padrão $p$ é 0). + +Adiante está um simples exemplo que ilustra a criação e leitura de um arquivo .dbf: + +\begin{verbatim} +table tab1{i in 1..10} OUT "xBASE" "foo.dbf" + "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, + "?" ~ FOO, "[" & i & "]" ~ C; +set S, dimen 4; +table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A]; +display S; +end; +\end{verbatim} + + +% The xBASE table driver assumes that the data table is stored in the +% .dbf file format. +% +% To choose the xBASE table driver its name in the table statement should +% be specified as \verb|"xBASE"|, and the first argument should specify +% the name of a .dbf file containing the table. For the output table there +% should be the second argument defining the table format in the form +% \verb|"FF...F"|, where \verb|F| is either {\tt C({\it n})}, +% which specifies a character field of length $n$, or +% {\tt N({\it n}{\rm [},{\it p}{\rm ]})}, which specifies a numeric field +% of length $n$ and precision $p$ (by default $p$ is 0). +% +% The following is a simple example which illustrates creating and +% reading a .dbf file: +% +% \begin{verbatim} +% table tab1{i in 1..10} OUT "xBASE" "foo.dbf" +% "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, +% "?" ~ FOO, "[" & i & "]" ~ C; +% set S, dimen 4; +% table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A]; +% display S; +% end; +% \end{verbatim} + +\section{Controlador de tabelas ODBC} + +O controlador de tabelas ODBC permite conexões com bancos de dados SQL usando +uma \linebreak implementação da interface ODBC baseada na Call Level Interface +(CLI).\footnote{A norma software correspondente é definida na +ISO/IEC 9075-3:2003.} + +\para{Debian GNU/Linux.} +No Debian GNU/Linux o controlador de tabelas ODBC usa o pacote iODBC, +\footnote{Ver {\tt}.} que deve ser instalado antes +de montar o pacote GLPK. A instalação pode ser efetuada com o seguinte +comando: + +\begin{verbatim} + sudo apt-get install libiodbc2-dev +\end{verbatim} + +Note que, ao configurar o pacote GLPK, para habilitar o uso da biblioteca do iODBC +a opção `\verb|--enable-odbc|' deve ser passada para o script de configuração. + +Para seu uso em todo sistema, as bases de dados individuais devem ser inseridas em +\verb|/etc/odbc.ini| e \verb|/etc/odbcinst.ini|. As conexões das bases de dados +a serem usadas por um único usuário são especificadas por arquivos do diretório +home (\verb|.odbc.ini| e \verb|.odbcinst.ini|). + +\para{Microsoft Windows.} +No Microsoft Windows o controlador de tabelas ODBC usa a biblioteca Microsoft ODBC. +Para habilitar esta funcionalidade, o símbolo: + +\begin{verbatim} + #define ODBC_DLNAME "odbc32.dll" +\end{verbatim} + +\noindent +deve ser definido no arquivo de configuração do GLPK `\verb|config.h|'. + +Fontes de dados podem ser criados via Ferramentas Administrativas do +Painel de Controle. + +Para escolher do controlador de tabelas ODBC, seu nome na sentença table deve +ser especificado como \verb|'ODBC'| ou \verb|'iODBC'|. + +% \newpage + +A lista de argumentos é especificada como segue. + +O primeiro argumento é a cadeia de conexão passada para a biblioteca ODBC, +por exemplo: + +\verb|'DSN=glpk;UID=user;PWD=password'|, ou + +\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. + +Diferentes partes da cadeia são separadas por ponto e vírgula. Cada parte +consiste de um par {\it nome-do-campo} e {\it valor} separados pelo sinar +de igualdade. Os nomes de campo permitidos dependem da biblioteca ODBC. +Tipicamente os seguintes nomes-de-campo são permitidos: + +\verb|DATABASE | base de dados; + +\verb|DRIVER | controlador ODBC; + +\verb|DSN | nome de uma fonte de dados; + +\verb|FILEDSN | nome de um arquivo de fonte de dados; + +\verb|PWD | senha de usuário; + +\verb|SERVER | base de dados; + +\verb|UID | nome de usuário. + +O segundo argumento e todos os seguintes são considerados como +sentenças SQL. + +As sentenças SQL podem ser estendidas sobre múltiplos argumentos. Se o +último caractere de um argumento é um ponto e vírgula, este indica +o fim de uma sentença SQL. + +Os argumentos de uma sentença SQL são concatenados separados por espaço. +O eventual ponto e vírgula final será removido. + +Todas as sentenças SQL, exceto a última, serão executadas diretamente. + +Para tabela-IN, a última sentença SQL pode ser um comando SELECT que se inicia +com \verb|'SELECT '| em letras maiúsculas. Se a cadeia não se inicia com +\verb|'SELECT '|, se considera que é um nome de uma tabela e uma sentença +SELECT é automaticamente gerada. + + +Para tabela-OUT, a última sentença SQL pode conter um ou múltiplos pontos de +interrogação. Se contém um ponto de interrogação, é considerado um gabarito +para a rotina de escrita. Caso contrário, a cadeia é considerada um +nome de tabela e um gabarito INSERT é automaticamente gerado. + +A rotina de escrita usa um gabarito com o pontos de interrogação e +o substitui o primeiro ponto de interrogação pelo primeiro parâmetro +de saída, o segundo ponto de interrogação, pelo segundo parâmetro e +assim por diante. Em seguida, o comando SQL é emitido. + +O que segue é um exemplo da sentença table de saída: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultado;' + 'CREATE TABLE resultado ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO resultado 'VALUES ( 4, ?, ? )' : + l ~ LOC, quantidade[l] ~ QUAN; +\end{verbatim} + +% \newpage + +\noindent +Alternativamente pode se escrever como segue: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultado;' + 'CREATE TABLE resultado ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'resultado' : + l ~ LOC, quantidade[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +O uso de gabaritos com `\verb|?|' não só permite INSERT, como também o +UPDATE, DELETE, etc. Por exemplo: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultado SET DATA = ' & data & ' WHERE ID = 4;' + 'UPDATE resultado SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantidade[l], l; +\end{verbatim} + + + +% The ODBC table driver allows connecting to SQL databases using an +% implementation of the ODBC interface based on the Call Level Interface +% (CLI).\footnote{The corresponding software standard is defined in +% ISO/IEC 9075-3:2003.} +% +% \para{Debian GNU/Linux.} +% Under Debian GNU/Linux the ODBC table driver uses the iODBC +% package,\footnote{See {\tt}.} which should be +% installed before building the GLPK package. The installation can be +% effected with the following command: +% +% \begin{verbatim} +% sudo apt-get install libiodbc2-dev +% \end{verbatim} +% +% Note that on configuring the GLPK package to enable using the iODBC +% library the option `\verb|--enable-odbc|' should be passed to the +% configure script. +% +% The individual databases should be entered for systemwide usage in +% \verb|/etc/odbc.ini| and\linebreak \verb|/etc/odbcinst.ini|. Database +% connections to be used by a single user are specified by files in the +% home directory (\verb|.odbc.ini| and \verb|.odbcinst.ini|). +% +% \para{Microsoft Windows.} +% Under Microsoft Windows the ODBC table driver uses the Microsoft ODBC +% library. To enable this feature the symbol: +% +% \begin{verbatim} +% #define ODBC_DLNAME "odbc32.dll" +% \end{verbatim} +% +% \noindent +% should be defined in the GLPK configuration file `\verb|config.h|'. +% +% Data sources can be created via the Administrative Tools from the +% Control Panel. +% +% To choose the ODBC table driver its name in the table statement should +% be specified as \verb|'ODBC'| or \verb|'iODBC'|. +% +% \newpage +% +% The argument list is specified as follows. +% +% The first argument is the connection string passed to the ODBC library, +% for example: +% +% \verb|'DSN=glpk;UID=user;PWD=password'|, or +% +% \verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. +% +% Different parts of the string are separated by semicolons. Each part +% consists of a pair {\it fieldname} and {\it value} separated by the +% equal sign. Allowable fieldnames depend on the ODBC library. Typically +% the following fieldnames are allowed: +% +% \verb|DATABASE | database; +% +% \verb|DRIVER | ODBC driver; +% +% \verb|DSN | name of a data source; +% +% \verb|FILEDSN | name of a file data source; +% +% \verb|PWD | user password; +% +% \verb|SERVER | database; +% +% \verb|UID | user name. +% +% The second argument and all following are considered to be SQL +% statements +% +% SQL statements may be spread over multiple arguments. If the last +% character of an argument is a semicolon this indicates the end of +% a SQL statement. +% +% The arguments of a SQL statement are concatenated separated by space. +% The eventual trailing semicolon will be removed. +% +% All but the last SQL statement will be executed directly. +% +% For IN-table the last SQL statement can be a SELECT command starting +% with the capitalized letters \verb|'SELECT '|. If the string does not +% start with \verb|'SELECT '| it is considered to be a table name and a +% SELECT statement is automatically generated. +% +% For OUT-table the last SQL statement can contain one or multiple +% question marks. If it contains a question mark it is considered a +% template for the write routine. Otherwise the string is considered a +% table name and an INSERT template is automatically generated. +% +% The writing routine uses the template with the question marks and +% replaces the first question mark by the first output parameter, the +% second question mark by the second output parameter and so forth. Then +% the SQL command is issued. +% +% The following is an example of the output table statement: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'ODBC' +% 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'DROP TABLE IF EXISTS result;' +% 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' +% 'INSERT INTO result 'VALUES ( 4, ?, ? )' : +% l ~ LOC, quantity[l] ~ QUAN; +% \end{verbatim} +% +% \newpage +% +% \noindent +% Alternatively it could be written as follows: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'ODBC' +% 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'DROP TABLE IF EXISTS result;' +% 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' +% 'result' : +% l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +% \end{verbatim} +% +% Using templates with `\verb|?|' supports not only INSERT, but also +% UPDATE, DELETE, etc. For example: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'ODBC' +% 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' +% 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : +% quantity[l], l; +% \end{verbatim} + + +\section{Controlador de tabelas MySQL} + +O controlador de tabelas MySQL permite a conexão a base de dados MySQL. + +\para{Debian GNU/Linux.} +No Debian GNU/Linux o controlador de tabelas MySQL usa o pacote MySQL, +\footnote{Para fazer o download de arquivos de desenvolvimento, ver +{\tt}.} que deve ser instalado +antes da criação do pacote GLPK. A instalação pode ser efetuada com +o seguinte comando: + +\begin{verbatim} + sudo apt-get install libmysqlclient15-dev +\end{verbatim} + +Note que ao configurar o pacote GLPK para habilitar o uso da biblioteca MySQL +a opção `\verb|--enable-mysql|' deve ser passada ao script de +configuração. + +\para{Microsoft Windows.} +No Microsoft Windows o controlador de tabelas MySQL também usa +a biblioteca MySQL. Para habilitar esta funcionalidade o símbolo: + +\begin{verbatim} + #define MYSQL_DLNAME "libmysql.dll" +\end{verbatim} + +\noindent +deve ser definido no arquivo de configuração do GLPK `\verb|config.h|'. + +Para escolher o controlador de tabelas MySQL, seu nome na sentença table deve +ser especificada como \verb|'MySQL'|. + +A lista de argumentos é especificada como segue. + +O primeiro argumento especifica como conectar a base de dados no estilo DSN, +por exemplo: + +\verb|'Database=glpk;UID=glpk;PWD=gnu'|. + +Diferentes partes da cadeia são separadas por ponto e vírgula. Cada parte +consiste de um par {\it nome-do-campo} e {\it valor} separado pelo sinal +de igualdade. Os seguintes nomes de campo são permitidos: + +% \newpage + +\verb|Server | servidor rodando a base de dados (localhost por padrão); + +\verb|Database | nome da base de dados; + +\verb|UID | nome de usuário; + +\verb|PWD | senha de usuário; + +\verb|Port | porta usada pelo servidor (3306 por padrão). + +O segundo argumento e todos os seguintes são considerados sentenças SQL. + +Sentenças SQL podem se estender sobre múltiplos argumentos. Se o último +caractere de um argumento é um ponto e vírgula, isto indica o fim de uma +sentença SQL. + +Os argumentos de uma sentença SQL são concatenados e separados por espaço. +O eventual ponto e vírgula final será removido. + +Todas sentenças SQL, menos a última, serão executadas diretamente. + +Para tabela-IN, a última sentença SQL pode ser um comando SELECT iniciado +com letras maiúsculas \verb|'SELECT '|. Se a cadeia não inicia com +\verb|'SELECT '| é considerado um nome de tabela e a sentença +SELECT é automaticamente gerada. + +Para tabela-OUT, a última sentença SQL pode conter um ou múltiplos pontos de +interrogação. Se contém um ponto de interrogação, é considerado um gabarito +para a rotina de escrita. Caso contrário, a cadeia é considerada um +nome de tabela e um gabarito INSERT é automaticamente gerado. + +A rotina de escrita usa um gabarito com o pontos de interrogação e +o substitui o primeiro ponto de interrogação pelo primeiro parâmetro +de saída, o segundo ponto de interrogação, pelo segundo parâmetro e +assim por diante. Em seguida, o comando SQL é emitido. + +O que segue é um exemplo da sentença table de saída: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultado;' + 'CREATE TABLE resultado ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'INSERT INTO resultado VALUES ( 4, ?, ? )' : + l ~ LOC, quantidade[l] ~ QUAN; +\end{verbatim} + +\noindent +Alternativamente poderia ser escrito como segue: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultado;' + 'CREATE TABLE resultado ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' + 'resultado' : + l ~ LOC, quantidade[l] ~ QUAN, 4 ~ ID; +\end{verbatim} + +% \newpage + +O uso de gabaritos com `\verb|?|' não só permite INSERT, como também o +UPDATE, DELETE, etc. Por exemplo: + +\begin{verbatim} +table ta { l in LOCAIS } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultado SET DATE = ' & date & ' WHERE ID = 4;' + 'UPDATE resultado SET QUAN = ? WHERE LOC = ? AND ID = 4' : + quantidade[l], l; +\end{verbatim} + + +% The MySQL table driver allows connecting to MySQL databases. +% +% \para{Debian GNU/Linux.} +% Under Debian GNU/Linux the MySQL table driver uses the MySQL +% package,\footnote{For download development files see +% {\tt}.} which should be +% installed before building the GLPK package. The installation can be +% effected with the following command: +% +% \begin{verbatim} +% sudo apt-get install libmysqlclient15-dev +% \end{verbatim} +% +% Note that on configuring the GLPK package to enable using the MySQL +% library the option `\verb|--enable-mysql|' should be passed to the +% configure script. +% +% \para{Microsoft Windows.} +% Under Microsoft Windows the MySQL table driver also uses the MySQL +% library. To enable this feature the symbol: +% +% \begin{verbatim} +% #define MYSQL_DLNAME "libmysql.dll" +% \end{verbatim} +% +% \noindent +% should be defined in the GLPK configuration file `\verb|config.h|'. +% +% To choose the MySQL table driver its name in the table statement should +% be specified as \verb|'MySQL'|. +% +% The argument list is specified as follows. +% +% The first argument specifies how to connect the data base in the DSN +% style, for example: +% +% \verb|'Database=glpk;UID=glpk;PWD=gnu'|. +% +% Different parts of the string are separated by semicolons. Each part +% consists of a pair {\it fieldname} and {\it value} separated by the +% equal sign. The following fieldnames are allowed: +% +% \newpage +% +% \verb|Server | server running the database (defaulting to localhost); +% +% \verb|Database | name of the database; +% +% \verb|UID | user name; +% +% \verb|PWD | user password; +% +% \verb|Port | port used by the server (defaulting to 3306). +% +% The second argument and all following are considered to be SQL +% statements. +% +% SQL statements may be spread over multiple arguments. If the last +% character of an argument is a semicolon this indicates the end of +% a SQL statement. +% +% The arguments of a SQL statement are concatenated separated by space. +% The eventual trailing semicolon will be removed. +% +% All but the last SQL statement will be executed directly. +% +% For IN-table the last SQL statement can be a SELECT command starting +% with the capitalized letters \verb|'SELECT '|. If the string does not +% start with \verb|'SELECT '| it is considered to be a table name and a +% SELECT statement is automatically generated. +% +% For OUT-table the last SQL statement can contain one or multiple +% question marks. If it contains a question mark it is considered a +% template for the write routine. Otherwise the string is considered a +% table name and an INSERT template is automatically generated. +% +% The writing routine uses the template with the question marks and +% replaces the first question mark by the first output parameter, the +% second question mark by the second output parameter and so forth. Then +% the SQL command is issued. +% +% The following is an example of the output table statement: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'MySQL' +% 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'DROP TABLE IF EXISTS result;' +% 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' +% 'INSERT INTO result VALUES ( 4, ?, ? )' : +% l ~ LOC, quantity[l] ~ QUAN; +% \end{verbatim} +% +% \noindent +% Alternatively it could be written as follows: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'MySQL' +% 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'DROP TABLE IF EXISTS result;' +% 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' +% 'result' : +% l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; +% \end{verbatim} +% +% \newpage +% +% Using templates with `\verb|?|' supports not only INSERT, but also +% UPDATE, DELETE, etc. For example: +% +% \begin{verbatim} +% table ta { l in LOCATIONS } OUT +% 'MySQL' +% 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' +% 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' +% 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : +% quantity[l], l; +% \end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% ##################### PAREI AQUI % ##################### + +\chapter{Resolvendo modelos com glpsol} + +O pacote GLPK \footnote{{\tt http://www.gnu.org/software/glpk/}} +inclui o programa {\tt glpsol}, um solver de PL/PIM autônomo. Este +programa pode ser chamado por uma linha de comando ou pelo shell para +resolver modelos escritos na \linebreak linguagem de modelagem GNU MathProg. + +Para comunicar ao solver que o arquivo de entrada contém uma descrição +do modelo, é necessário especificar a opção \verb|--model| na linha de +comando. Por exemplo: + +\begin{verbatim} + glpsol --model foo.mod +\end{verbatim} + +Às vezes é necessário usar a seção de dados posicionado em um arquivo +separado. Neste caso, deve-se usar o seguinte comando: + +\begin{verbatim} + glpsol --model foo.mod --data foo.dat +\end{verbatim} + +\noindent Note que ser o arquivo de modelo também contém a seção de dados, +aquela seção é ignorada. + +Também é permitido especificar mais de um arquivo contendo a seção de dados, +por exemplo: + +\begin{verbatim} + glpsol --model foo.mod --data foo1.dat --data foo2.dat +\end{verbatim} + +Se a descrição do modelo contém alguma sentença display e/ou printf, +o resultado é enviado para o terminal por padrão. Se há a necessidade +de redirecionar a saída para um arquivo, deve-se usar o seguinte comando: + +\begin{verbatim} + glpsol --model foo.mod --display foo.out +\end{verbatim} + +Se há a necessidade de ver o problema que está sendo gerado pelo tradutor +de modelo, deve-ser usar a opção \verb|--wlp| como segue: + +\begin{verbatim} + glpsol --model foo.mod --wlp foo.lp +\end{verbatim} + +\noindent Neste caso, os dados do problema são escritos no arquivo +\verb|foo.lp| no formato CPLEX LP viável para análise visual. + +Ás vezes, é necessário checar a descrição do modelo sem ter que resolver +a instância do problema gerado. Neste caso, deve-se especificar a opção +\verb|--check|, por exemplo: + +\begin{verbatim} + glpsol --check --model foo.mod --wlp foo.lp +\end{verbatim} + +\newpage + +Se há a necessidade de escrever uma solução numérica obtida pelo solver +para um arquivo, deve-se usar o seguinte comando: + +\begin{verbatim} + glpsol --model foo.mod --output foo.sol +\end{verbatim} + +\noindent neste caso, a solução é escrita no arquivo \verb|foo.sol| +em formato de texto plano, viável para análise visual. + +A lista completa de opções do \verb|glpsol| pode ser encontrada no manual +de referência do GLPK incluída na distribuição do GLPK. + + + +% The GLPK package\footnote{{\tt http://www.gnu.org/software/glpk/}} +% includes the program {\tt glpsol}, a stand-alone LP/MIP solver. This +% program can be launched from the command line or from the shell to +% solve models written in the GNU MathProg modeling language. +% +% To tell the solver that the input file contains a model description you +% need to specify the option \verb|--model| in the command line. +% For example: +% +% \begin{verbatim} +% glpsol --model foo.mod +% \end{verbatim} +% +% Sometimes it is necessary to use the data section placed in a separate +% file, in which case you may use the following command: +% +% \begin{verbatim} +% glpsol --model foo.mod --data foo.dat +% \end{verbatim} +% +% \noindent Note that if the model file also contains the data section, +% that section is ignored. +% +% It is also allowed to specify more than one file containing the data +% section, for example: +% +% \begin{verbatim} +% glpsol --model foo.mod --data foo1.dat --data foo2.dat +% \end{verbatim} +% +% If the model description contains some display and/or printf +% statements, by default the output is sent to the terminal. If you need +% to redirect the output to a file, you may use the following command: +% +% \begin{verbatim} +% glpsol --model foo.mod --display foo.out +% \end{verbatim} +% +% If you need to look at the problem, which has been generated by the +% model translator, you may use the option \verb|--wlp| as follows: +% +% \begin{verbatim} +% glpsol --model foo.mod --wlp foo.lp +% \end{verbatim} +% +% \noindent In this case the problem data is written to file +% \verb|foo.lp| in CPLEX LP format suitable for visual analysis. +% +% Sometimes it is needed merely to check the model description not +% solving the generated problem instance. In this case you may specify +% the option \verb|--check|, for example: +% +% \begin{verbatim} +% glpsol --check --model foo.mod --wlp foo.lp +% \end{verbatim} +% +% \newpage +% +% If you need to write a numeric solution obtained by the solver to +% a file, you may use the following command: +% +% \begin{verbatim} +% glpsol --model foo.mod --output foo.sol +% \end{verbatim} +% +% \noindent in which case the solution is written to file \verb|foo.sol| +% in a plain text format suitable for visual analysis. +% +% The complete list of the \verb|glpsol| options can be found in the +% GLPK reference manual included in the GLPK distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Exemplo de descrição de modelo} + +\section{Descrição de modelo escrito em MathProg} + +Este é um exemplo completo de descrição de modelo escrito na linguagem +de modelagem GNU MathProg. + +\bigskip + +\begin{verbatim} +# UM PROBLEMA DE TRANSPORTE +# +# Este problema encontra a logística de custo mínimo que atende das demandas +# de mercado e as ofertas das fábricas. +# +# Referência: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* fábricas de enlatados*/ + +set J; +/* mercados */ + +param a{i in I}; +/* capacidade da fábrica i, em caixas */ + +param b{j in J}; +/* demanda no mercado j, em caixas */ + +param d{i in I, j in J}; +/* distância, em milhares de milhas */ + +param f; +/* frete, em dólares por caixa a cada mil milhas */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* custo de transporte, em milhares de dólares por caixa */ + +var x{i in I, j in J} >= 0; +/* quantidade enviada, em caixas */ + +minimize custo: sum{i in I, j in J} c[i,j] * x[i,j]; +/* custo total de transporte, em milhares de dólares */ + +s.t. suprimento{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observa o limite de suprimento na fábrica i */ + +s.t. demanda{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfaz a demanda do mercado j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; +\end{verbatim} + + +% Below here is a complete example of the model description written in +% the GNU MathProg modeling language. +% +% \bigskip +% +% \begin{verbatim} +% # A TRANSPORTATION PROBLEM +% # +% # This problem finds a least cost shipping schedule that meets +% # requirements at markets and supplies at factories. +% # +% # References: +% # Dantzig G B, "Linear Programming and Extensions." +% # Princeton University Press, Princeton, New Jersey, 1963, +% # Chapter 3-3. +% +% set I; +% /* canning plants */ +% +% set J; +% /* markets */ +% +% param a{i in I}; +% /* capacity of plant i in cases */ +% +% param b{j in J}; +% /* demand at market j in cases */ +% +% param d{i in I, j in J}; +% /* distance in thousands of miles */ +% +% param f; +% /* freight in dollars per case per thousand miles */ +% +% param c{i in I, j in J} := f * d[i,j] / 1000; +% /* transport cost in thousands of dollars per case */ +% +% var x{i in I, j in J} >= 0; +% /* shipment quantities in cases */ +% +% minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +% /* total transportation costs in thousands of dollars */ +% +% s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +% /* observe supply limit at plant i */ +% +% s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +% /* satisfy demand at market j */ +% +% data; +% +% set I := Seattle San-Diego; +% +% set J := New-York Chicago Topeka; +% +% param a := Seattle 350 +% San-Diego 600; +% +% param b := New-York 325 +% Chicago 300 +% Topeka 275; +% +% param d : New-York Chicago Topeka := +% Seattle 2.5 1.7 1.8 +% San-Diego 2.5 1.8 1.4 ; +% +% param f := 90; +% +% end; +% \end{verbatim} + +\newpage + +\section{Instância gerada do problema de PL} + +Este é o resultado da tradução do modelo de exemplo produzido +pelo solver \verb|glpsol| e escrito no formato CPLEX LP +com a opção \verb|--wlp|. + +\medskip + +\begin{verbatim} +\* Problem: transporte *\ + +Minimize + custo: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) + +Subject To + suprimento(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + + x(Seattle,Topeka) <= 350 + suprimento(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + + x(San~Diego,Topeka) <= 600 + demanda(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 + demanda(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 + demanda(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 + +End +\end{verbatim} + +\section{solução ótima do problema de PL} + +Esta é a solução ótima da instância gerada do problema de PL +encontrada pelo solver \verb|glpsol| e escrita em formato de texto plano +com a opção\verb|--output|. + +\medskip + +\begin{footnotesize} +\begin{verbatim} +Problem: transporte +Rows: 6 +Columns: 6 +Non-zeros: 18 +Status: OPTIMAL +Objective: custo = 153.675 (MINimum) + + No. Row name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 cust B 153.675 + 2 suprimento[Seattle] + NU 350 350 < eps + 3 suprimento[San-Diego] + B 550 600 + 4 demanda[New-York] + NL 325 325 0.225 + 5 demanda[Chicago] + NL 300 300 0.153 + 6 demanda[Topeka] + NL 275 275 0.126 + + No. Column name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 x[Seattle,New-York] + B 50 0 + 2 x[Seattle,Chicago] + B 300 0 + 3 x[Seattle,Topeka] + NL 0 0 0.036 + 4 x[San-Diego,New-York] + B 275 0 + 5 x[San-Diego,Chicago] + NL 0 0 0.009 + 6 x[San-Diego,Topeka] + B 275 0 + +End of output +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section*{Agradecimentos} +\addcontentsline{toc}{chapter}{Agradecimentos} + +Os autores gostariam de agradecer as seguintes pessoas que gentilmente leram, +comentaram e corrigiram o rascunho deste documento: + +\noindent Juan Carlos Borras \verb|| + +\noindent Harley Mackenzie \verb|| + +\noindent Robbie Morrison \verb|| + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.pdf new file mode 100644 index 000000000..b3c7fe0ee Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.tex b/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.tex new file mode 100644 index 000000000..446a858c6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/graphs.tex @@ -0,0 +1,4202 @@ +%* graphs.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013, 2016 Andrew Makhorin, Department for Applied +% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +% reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +% To make graphs.pdf from graphs.tex run the following two commands: +% latex graphs.tex +% dvipdfm -p letter graphs.dvi +% Note: You need TeX Live 2010 or later version. + +\documentclass[11pt]{report} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} +\usepackage{niceframe} +\usepackage[all]{xy} + +% US Letter = 8.5 x 11 in +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{9in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +%\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +%\setlength{\itemsep}{\parskip} +%\setlength{\parsep}{0pt} +%\setlength{\leftmargini}{\parindent} +%\renewcommand{\labelitemi}{---} + +\newcommand{\Item}[1]{\parbox[t]{\parindent}{#1}} +\def\para#1{\noindent{\bf#1}} +\def\synopsis{\para{Synopsis}} +\def\description{\para{Description}} +\def\note{\para{Note}} +\def\returns{\para{Returns}} + +\renewcommand\contentsname{\sf\bfseries Contents} +\renewcommand\chaptername{\sf\bfseries Chapter} +\renewcommand\appendixname{\sf\bfseries Appendix} + +\newenvironment{retlist} +{ \def\arraystretch{1.5} + \noindent + \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} +} +{\end{tabular}} + +\begin{document} + +\thispagestyle{empty} + +\curlyframe{ + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries GNU Linear Programming Kit +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Graph and Network Routines +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf for GLPK Version 4.59 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (DRAFT, March 2016) +\end{Large} +\end{center} + +\vspace*{4.1in} +} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +The GLPK package is part of the GNU Project released under the aegis of +GNU. + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013, 2016\linebreak +Andrew Makhorin, Department for Applied Informatics, Moscow Aviation +Institute, Moscow, Russia. All rights reserved. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +02110-1301, USA. + +\noindent +Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + +\noindent +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided also that the +entire resulting derived work is distributed under the terms of +a permission notice identical to this one. + +\noindent +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt}\tableofcontents} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Basic Graph API Routines} + +\section{Graph program object} + +In GLPK the base program object used to represent graphs and networks +is a directed graph (digraph). + +Formally, {\it digraph} (or simply, {\it graph}) is a pair $G=(V,A)$, +where $V$ is a set of {\it vertices}, and $A$ is a set +{\it arcs}.\footnote{$A$ may be a multiset.} Each arc $a\in A$ is an +ordered pair of vertices $a=(x,y)$, where $x\in V$ is called {\it tail +vertex} of arc $a$, and $y\in V$ is called its {\it head vertex}. + +Representation of a graph in the program includes three structs defined +by typedef in the header \verb|glpk.h|: + +%\vspace*{-8pt} + +%\begin{itemize} +\Item{---}\verb|glp_graph|, which represents the graph in a whole, + +\Item{---}\verb|glp_vertex|, which represents a vertex of the graph, and + +\Item{---}\verb|glp_arc|, which represents an arc of the graph. +%\end{itemize} + +%\vspace*{-8pt} + +All these three structs are ``semi-opaque'', i.e. the application +program can directly access their fields through pointers, however, +changing the fields directly is not allowed --- all changes should be +performed only with appropriate GLPK API routines. + +\newenvironment{comment} +{\addtolength{\leftskip}{16pt}\noindent} +{\par\addtolength{\leftskip}{-16pt}} + +\subsection{Structure glp\_graph} + +%\para{\bf glp\_graph.} +The struct \verb|glp_graph| has the following fields available to the +application program. + +\noindent +\verb|char *name;| + +\begin{comment}Symbolic name assigned to the graph. It is a pointer to +a null terminated character string of length from 1 to 255 characters. +If no name is assigned to the graph, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|int nv;| + +\begin{comment}The number of vertices in the graph, $nv\geq 0$. +\end{comment} + +\noindent +\verb|int na;| + +\begin{comment}The number of arcs in the graph, $na\geq 0$. +\end{comment} + +\newpage + +\noindent +\verb|glp_vertex **v;| + +\begin{comment}Pointer to an array containing the list of vertices. +Element $v[0]$ is not used. Element $v[i]$, $1\leq i\leq nv$, is a +pointer to $i$-th vertex of the graph. Note that on adding new vertices +to the graph the field $v$ may be altered due to reallocation. However, +pointers $v[i]$ are not changed while corresponding vertices exist in +the graph. +\end{comment} + +\noindent +\verb|int v_size;| + +\begin{comment}Size of vertex data blocks, in bytes, +$0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct +\verb|glp_vertex|.) +\end{comment} + +\noindent +\verb|int a_size;| + +\begin{comment}Size of arc data blocks, in bytes, +$0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct +\verb|glp_arc|.) +\end{comment} + +\subsection{Structure glp\_vertex} + +%\para{\bf glp\_vertex.} +The struct \verb|glp_vertex| has the following fields available to the +application program. + +\noindent +\verb|int i;| + +\begin{comment}Ordinal number of the vertex, $1\leq i\leq nv$. Note +that element $v[i]$ in the struct \verb|glp_graph| points to the vertex, +whose ordinal number is $i$. +\end{comment} + +\noindent +\verb|char *name;| + +\begin{comment}Symbolic name assigned to the vertex. It is a pointer to +a null terminated character string of length from 1 to 255 characters. +If no name is assigned to the vertex, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *data;| + +\begin{comment}Pointer to a data block associated with the vertex. This +data block is automatically allocated on creating a new vertex and freed +on deleting the vertex. If $v\_size=0$, the block is not allocated, and +this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *temp;| + +\begin{comment}Working pointer, which may be used freely for any +purposes. The application program can change this field directly. +\end{comment} + +\noindent +\verb|glp_arc *in;| + +\begin{comment}Pointer to the (unordered) list of incoming arcs. If the +vertex has no incoming arcs, this field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|glp_arc *out;| + +\begin{comment}Pointer to the (unordered) list of outgoing arcs. If the +vertex has no outgoing arcs, this field contains \verb|NULL|. +\end{comment} + +\subsection{Structure glp\_arc} + +%\para{\bf glp\_arc.} +The struct \verb|glp_arc| has the following fields available to the +application program. + +\noindent +\verb|glp_vertex *tail;| + +\begin{comment}Pointer to a vertex, which is tail endpoint of the arc. +\end{comment} + +\newpage + +\noindent +\verb|glp_vertex *head;| + +\begin{comment}Pointer to a vertex, which is head endpoint of the arc. +\end{comment} + +%\newpage + +\noindent +\verb|void *data;| + +\begin{comment}Pointer to a data block associated with the arc. This +data block is automatically allocated on creating a new arc and freed on +deleting the arc. If $v\_size=0$, the block is not allocated, and this +field contains \verb|NULL|. +\end{comment} + +\noindent +\verb|void *temp;| + +\begin{comment}Working pointer, which may be used freely for any +purposes. The application program can change this field directly. +\end{comment} + +\noindent +\verb|glp_arc *t_next;| + +\begin{comment}Pointer to another arc, which has the same tail endpoint +as this one. \verb|NULL| in this field indicates the end of the list of +outgoing arcs. +\end{comment} + +\noindent +\verb|glp_arc *h_next;| + +\begin{comment}Pointer to another arc, which has the same head endpoint +as this one. \verb|NULL| in this field indicates the end of the list of +incoming arcs. +\end{comment} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\setlength{\parskip}{4.6pt} + +\section{Graph creating and modifying routines} + +\subsection{glp\_create\_graph --- create graph} + +\synopsis + +\begin{verbatim} + glp_graph *glp_create_graph(int v_size, int a_size); +\end{verbatim} + +\description + +The routine \verb|glp_create_graph| creates a new graph, which +initially is empty, i.e. has no vertices and arcs. + +The parameter \verb|v_size| specifies the size of vertex data blocks, +in bytes, $0\leq v\_size\leq 256$. + +The parameter \verb|a_size| specifies the size of arc data blocks, in +bytes, $0\leq a\_size\leq 256$. + +\returns + +The routine returns a pointer to the graph object created. + +\subsection{glp\_set\_graph\_name --- assign (change) graph name} + +\synopsis + +\begin{verbatim} + void glp_set_graph_name(glp_graph *G, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_graph_name| assigns a symbolic name specified +by the character string \verb|name| (1 to 255 chars) to the graph. + +If the parameter \verb|name| is \verb|NULL| or an empty string, the +routine erases the existing symbolic name of the graph. + +\subsection{glp\_add\_vertices --- add new vertices to graph} + +\synopsis + +\begin{verbatim} + int glp_add_vertices(glp_graph *G, int nadd); +\end{verbatim} + +\description + +The routine \verb|glp_add_vertices| adds \verb|nadd| vertices to the +specified graph. New vertices are always added to the end of the vertex +list, so ordinal numbers of existing vertices remain unchanged. Note +that this operation may change the field \verb|v| in the struct +\verb|glp_graph| (pointer to the vertex array) due to reallocation. + +Being added each new vertex is isolated, i.e. has no incident arcs. + +If the size of vertex data blocks specified on creating the graph is +non-zero, the routine also allocates a memory block of that size for +each new vertex added, fills it by binary zeros, and stores a pointer +to it in the field \verb|data| of the struct \verb|glp_vertex|. +Otherwise, if the block size is zero, the field \verb|data| is set to +\verb|NULL|. + +\returns + +The routine \verb|glp_add_vertices| returns the ordinal number of the +first new vertex added to the graph. + +\setlength{\parskip}{5pt} + +\newpage + +\subsection{glp\_set\_vertex\_name --- assign (change) vertex name} + +\synopsis + +\begin{verbatim} + void glp_set_vertex_name(glp_graph *G, int i, const char *name); +\end{verbatim} + +\description + +The routine \verb|glp_set_vertex_name| assigns a given symbolic name +(1 up to 255 characters) to \verb|i|-th vertex of the specified graph. + +If the parameter \verb|name| is \verb|NULL| or empty string, the +routine erases an existing name of \verb|i|-th vertex. + +\subsection{glp\_add\_arc --- add new arc to graph} + +\synopsis + +\begin{verbatim} + glp_arc *glp_add_arc(glp_graph *G, int i, int j); +\end{verbatim} + +\description + +The routine \verb|glp_add_arc| adds one new arc to the specified graph. + +The parameters \verb|i| and \verb|j| specify the ordinal numbers of, +resp., tail and head endpoints (vertices) of the arc. Note that +self-loops and multiple arcs are allowed. + +If the size of arc data blocks specified on creating the graph is +non-zero, the routine also allocates a memory block of that size, fills +it by binary zeros, and stores a pointer to it in the field \verb|data| +of the struct \verb|glp_arc|. Otherwise, if the block size is zero, the +field \verb|data| is set to \verb|NULL|. + +\subsection{glp\_del\_vertices --- delete vertices from graph} + +\synopsis + +\begin{verbatim} + void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +\end{verbatim} + +\description + +The routine \verb|glp_del_vertices| deletes vertices along with all +incident arcs from the specified graph. Ordinal numbers of vertices to +be deleted should be placed in locations \verb|num[1]|, \dots, +\verb|num[ndel]|, \verb|ndel| $>0$. + +Note that deleting vertices involves changing ordinal numbers of other +vertices remaining in the graph. New ordinal numbers of the remaining +vertices are assigned under the assumption that the original order of +vertices is not changed. + +%\newpage + +\subsection{glp\_del\_arc --- delete arc from graph} + +\synopsis + +\begin{verbatim} + void glp_del_arc(glp_graph *G, glp_arc *a); +\end{verbatim} + +\description + +The routine \verb|glp_del_arc| deletes an arc from the specified graph. +The arc to be deleted must exist. + +\subsection{glp\_erase\_graph --- erase graph content} + +\synopsis + +\begin{verbatim} + void glp_erase_graph(glp_graph *G, int v_size, int a_size); +\end{verbatim} + +\description + +The routine \verb|glp_erase_graph| erases the content of the specified +graph. The effect of this operation is the same as if the graph would +be deleted with the routine \verb|glp_delete_graph| and then created +anew with the routine \verb|glp_create_graph|, with exception that the +pointer to the graph remains valid. + +The parameters \verb|v_size| and \verb|a_size| have the same meaning as +for \verb|glp_create_graph|. + +\subsection{glp\_delete\_graph --- delete graph} + +\synopsis + +\begin{verbatim} + void glp_delete_graph(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_delete_graph| deletes the specified graph and +frees all the memory allocated to this program object. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph searching routines} + +\subsection{glp\_create\_v\_index --- create vertex name index} + +\synopsis + +\begin{verbatim} + void glp_create_v_index(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_create_v_index| creates the name index for the +specified graph. The name index is an auxiliary data structure, which +is intended to quickly (i.e. for logarithmic time) find vertices by +their names. + +This routine can be called at any time. If the name index already +exists, the routine does nothing. + +\subsection{glp\_find\_vertex --- find vertex by its name} + +\synopsis + +\begin{verbatim} + int glp_find_vertex(glp_graph *G, const char *name); +\end{verbatim} + +\returns + +The routine \verb|glp_find_vertex| returns the ordinal number of +a vertex, which is assigned (by the routine \verb|glp_set_vertex_name|) +the specified symbolic \verb|name|. If no such vertex exists, the +routine returns 0. + +\subsection{glp\_delete\_v\_index --- delete vertex name index} + +\synopsis + +\begin{verbatim} + void glp_delete_v_index(glp_graph *G); +\end{verbatim} + +\description + +The routine \verb|glp_delete_v_index| deletes the name index previously +created by the routine \verb|glp_create_v_index| and frees the memory +allocated to this auxiliary data structure. + +This routine can be called at any time. If the name index does not +exist, the routine does nothing. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph reading/writing routines} + +\subsection{glp\_read\_graph --- read graph from text file} + +\synopsis + +\begin{verbatim} + int glp_read_graph(glp_graph *G, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_graph| reads a graph from a text file, whose +name is specified by the parameter \verb|fname|. It is equivalent to + +\begin{verbatim} + glp_read_ccdata(G, -1, fname); +\end{verbatim} + +Note that before reading data the current content of the graph object +is completely erased with the routine \verb|glp_erase_graph|. + +\returns + +If the operation was successful, the routine returns zero. Otherwise +it prints an error message and returns non-zero. + +\subsection{glp\_write\_graph --- write graph to text file} + +\synopsis + +\begin{verbatim} + int glp_write_graph(glp_graph *G, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_graph| writes the graph to a text file, +whose name is specified by the parameter \verb|fname|. +It is equivalent to + +\begin{verbatim} + glp_write_ccdata(G, -1, fname); +\end{verbatim} + +\returns + +If the operation was successful, the routine returns zero. Otherwise +it prints an error message and returns non-zero. + +\subsection{glp\_read\_ccdata --- read graph from text file in DIMACS +clique/coloring\\format} + +\synopsis + +\begin{verbatim} + int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +\end{verbatim} + +\description + +The routine {\tt glp\_read\_ccdata} reads a graph from a text file in +DIMACS clique/coloring format. (Though this format is originally +designed to represent data for the minimal vertex coloring and maximal +clique problems, it may be used to represent general undirected and +directed graphs, because the routine allows reading self-loops and +multiple edges/arcs keeping the order of vertices specified for each +edge/arc of the graph.) + +\newpage + +The parameter {\tt G} specifies the graph object to be read in. Note +that before reading data the current content of the graph object is +completely erased with the routine {\tt glp\_erase\_graph}. + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, to which the routine stores the +vertex weight. If {\tt v\_wgt} $<0$, the vertex weights are not stored. + +The character string {\tt fname} specifies the name of a text file to +be read in. (If the file name ends with the suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{DIMACS clique/coloring format\footnote{This material is +based on the paper ``Clique and Coloring Problems Graph Format'', which +is publicly available at \url{http://dimacs.rutgers.edu/Challenges}.}} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. +The problem line must appear before any node or edge descriptor lines. +It has the following format: + +\begin{verbatim} + p edge NODES EDGES +\end{verbatim} + +\noindent +The lower-case letter \verb|p| signifies that this is a problem line. +The four-character problem designator \verb|edge| identifies the file +as containing data for the minimal vertex coloring or maximal clique +problem. The \verb|NODES| field contains an integer value specifying +the number of vertices in the graph. The \verb|EDGES| field contains an +integer value specifying the number of edges (arcs) in the graph. + +\para{Vertex descriptors.} These lines give the weight assigned to +a vertex of the graph. There is one vertex descriptor line for each +vertex, with the following format. Vertices without a descriptor take +on a default value of 1. + +\begin{verbatim} + n ID VALUE +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a vertex +descriptor line. The \verb|ID| field gives a vertex identification +number, an integer between 1 and $n$, where $n$ is the number of +vertices in the graph. The \verb|VALUE| field gives a vertex weight, +which can either positive or negative (or zero). + +\para{Edge descriptors.} There is one edge descriptor line for each +edge (arc) of the graph, each with the following format: + +\begin{verbatim} + e I J +\end{verbatim} + +\noindent +The lower-case character \verb|e| signifies that this is an edge +descriptor line. For an edge (arc) $(i,j)$ the fields \verb|I| and +\verb|J| specify its endpoints. + +\newpage + +\para{Example.} The following undirected graph + +\bigskip + +\noindent\hfil +\xymatrix %@C=32pt +{&{v_1}\ar@{-}[ldd]\ar@{-}[dd]\ar@{-}[rd]\ar@{-}[rr]&&{v_2}\ar@{-}[ld] +\ar@{-}[dd]\ar@{-}[rdd]&\\ +&&{v_7}\ar@{-}[ld]\ar@{-}[rd]&&\\ +{v_6}\ar@{-}[r]\ar@{-}[rdd]&{v_{10}}\ar@{-}[rr]\ar@{-}[rd]\ar@{-}[dd]&& +{v_8}\ar@{-}[ld]\ar@{-}[dd]\ar@{-}[r]&{v_3}\ar@{-}[ldd]\\ +&&{v_9}\ar@{-}[ld]\ar@{-}[rd]&&\\ +&{v_5}\ar@{-}[rr]&&{v_4}&\\ +} + +\bigskip + +\noindent +might be coded in DIMACS clique/coloring format as follows. + +\begin{footnotesize} +\begin{verbatim} +c sample.col +c +c This is an example of the vertex coloring problem data +c in DIMACS format. +c +p edge 10 21 +c +e 1 2 +e 1 6 +e 1 7 +e 1 10 +e 2 3 +e 2 7 +e 2 8 +e 3 4 +e 3 8 +e 4 5 +e 4 8 +e 4 9 +e 5 6 +e 5 9 +e 5 10 +e 6 10 +e 7 8 +e 7 10 +e 8 9 +e 8 10 +e 9 10 +c +c eof +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_write\_ccdata --- write graph to text file in DIMACS +clique/coloring\\format} + +\synopsis + +\begin{verbatim} + int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +\end{verbatim} + +\description + +The routine {\tt glp\_write\_ccdata} writes the graph object specified +by the parameter {\tt G} to a text file in DIMACS clique/coloring +format. (Though this format is originally designed to represent data +for the minimal vertex coloring and maximal clique problems, it may be +used to represent general undirected and directed graphs, because the +routine allows writing self-loops and multiple edges/arcs keeping the +order of vertices specified for each edge/arc of the graph.) + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, which contains the vertex +weight. If {\tt v\_wgt} $<0$, it is assumed that the weight of each +vertex is 1. + +The character string {\tt fname} specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Graph analysis routines} + +\subsection{glp\_weak\_comp --- find all weakly connected components of +graph} + +\synopsis + +\begin{verbatim} + int glp_weak_comp(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_weak_comp| finds all weakly connected components +of the specified graph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +number of a weakly connected component containing that vertex. If +\verb|v_num| $<0$, no component numbers are stored. + +The components are numbered in arbitrary order from 1 to \verb|nc|, +where \verb|nc| is the total number of components found, +$0\leq$ \verb|nc| $\leq|V|$. + +\returns + +The routine returns \verb|nc|, the total number of components found. + +\subsection{glp\_strong\_comp --- find all strongly connected +components of graph} + +\synopsis + +\begin{verbatim} + int glp_strong_comp(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_strong_comp| finds all strongly connected +components of the specified graph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +number of a strongly connected component containing that vertex. If +\verb|v_num| $<0$, no component numbers are stored. + +The components are numbered in arbitrary order from 1 to \verb|nc|, +where \verb|nc| is the total number of components found, +$0\leq$ \verb|nc| $\leq|V|$. However, the component numbering has the +property that for every arc $(i\rightarrow j)$ in the graph the +condition $num(i)\geq num(j)$ holds. + +\returns + +The routine returns \verb|nc|, the total number of components found. + +\para{References} + +I.~S.~Duff, J.~K.~Reid, Algorithm 529: Permutations to block triangular +form, ACM Trans. on Math. Softw. 4 (1978), 189-92. + +\newpage + +\para{Example} + +The following program reads a graph from a plain text file +`\verb|graph.txt|' and finds all its strongly connected components. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { int num; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i, nc; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_graph(G, "graph.txt"); + nc = glp_strong_comp(G, offsetof(v_data, num)); + printf("nc = %d\n", nc); + for (i = 1; i <= G->nv; i++) + printf("num[%d] = %d\n", i, vertex(G->v[i])->num); + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +\noindent +If the file `\verb|graph.txt|' contains the following graph: + +\medskip + +\noindent\hfil +\xymatrix +{1\ar[r]&2\ar[r]&3\ar[r]\ar[dd]&4\ar[dd]\\ +5\ar[u]&6\ar[l]\\ +7\ar[u]&&8\ar[lu]\ar[ll]\ar[r]&9\ar[r]&10\ar[r]\ar[d]&11\ar[d]\\ +12\ar[u]\ar[rru]\ar@/_/[rr]&&13\ar[ll]\ar[u]\ar[rr]&&14\ar[lu]&15\ar[l] +\\ +} + +\medskip\medskip + +\noindent +the program output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `graph.txt'... +Graph has 15 vertices and 30 arcs +31 lines were read +nc = 4 +num[1] = 3 +num[2] = 3 +num[3] = 3 +num[4] = 2 +num[5] = 3 +num[6] = 3 +num[7] = 3 +num[8] = 3 +num[9] = 1 +num[10] = 1 +num[11] = 1 +num[12] = 4 +num[13] = 4 +num[14] = 1 +num[15] = 1 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_top\_sort --- topological sorting of acyclic digraph} + +\synopsis + +\begin{verbatim} + int glp_top_sort(glp_graph *G, int v_num); +\end{verbatim} + +\description + +The routine \verb|glp_top_sort| performs topological sorting of +vertices of the specified acyclic digraph. + +The parameter \verb|v_num| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +vertex number assigned. If \verb|v_num| $<0$, vertex numbers are not +stored. + +The vertices are numbered from 1 to $n$, where $n$ is the total number +of vertices in the graph. The vertex numbering has the property that +for every arc $(i\rightarrow j)$ in the graph the condition +$num(i) +#include +#include +#include + +typedef struct { int num; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i, cnt; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_graph(G, "graph.txt"); + cnt = glp_top_sort(G, offsetof(v_data, num)); + printf("cnt = %d\n", cnt); + for (i = 1; i <= G->nv; i++) + printf("num[%d] = %d\n", i, vertex(G->v[i])->num); + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +\newpage + +\noindent +If the file `\verb|graph.txt|' contains the following graph: + +\medskip + +\noindent\hfil +\xymatrix @=20pt +{ +1\ar[rrr]&&&2\ar[r]\ar[rddd]&3\ar[rd]&&&&\\ +&&&4\ar[ru]&&5\ar[r]&6\ar[rd]\ar[dd]&&\\ +7\ar[r]&8\ar[r]&9\ar[ruu]\ar[ru]\ar[r]\ar[rd]&10\ar[rr]\ar[rru]&& +11\ar[ru]&&12\ar[r]&13\\ +&&&14\ar[r]&15\ar[rrru]\ar[rr]&&16\ar[rru]\ar[rr]&&17\\ +} + +\medskip\medskip + +\noindent +the program output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `graph.txt'... +Graph has 17 vertices and 23 arcs +24 lines were read +cnt = 0 +num[1] = 8 +num[2] = 9 +num[3] = 10 +num[4] = 4 +num[5] = 11 +num[6] = 12 +num[7] = 1 +num[8] = 2 +num[9] = 3 +num[10] = 5 +num[11] = 6 +num[12] = 14 +num[13] = 16 +num[14] = 7 +num[15] = 13 +num[16] = 15 +num[17] = 17 +\end{verbatim} +\end{footnotesize} + +\noindent +The output corresponds to the following vertex numbering: + +\medskip + +\noindent\hfil +\xymatrix @=20pt +{ +8\ar[rrr]&&&9\ar[r]\ar[rddd]&10\ar[rd]&&&&\\ +&&&4\ar[ru]&&11\ar[r]&12\ar[rd]\ar[dd]&&\\ +1\ar[r]&2\ar[r]&3\ar[ruu]\ar[ru]\ar[r]\ar[rd]&5\ar[rr]\ar[rru]&& +6\ar[ru]&&14\ar[r]&16\\ +&&&7\ar[r]&13\ar[rrru]\ar[rr]&&15\ar[rru]\ar[rr]&&17\\ +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Network optimization API routines} + +\section{Minimum cost flow problem} + +\subsection{Background} + +The {\it minimum cost flow problem} (MCFP) is stated as follows. Let +there be given a directed graph (flow network) $G=(V,A)$, where $V$ is +a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. +Let for each node $i\in V$ there be given a quantity $b_i$ having the +following meaning: + +if $b_i>0$, then $|b_i|$ is a {\it supply} at node $i$, which shows +how many flow units are {\it generated} at node $i$ (or, equivalently, +entering the network through node $i$ from outside); + +if $b_i<0$, then $|b_i|$ is a {\it demand} at node $i$, which shows how +many flow units are {\it lost} at node $i$ (or, equivalently, leaving +the network through node $i$ to outside); + +if $b_i=0$, then $i$ is a {\it transshipment} node, at which the flow +is conserved, i.e. neither generated nor lost. + +Let also for each arc $a=(i,j)\in A$ there be given the following three +quantities: + +$l_{ij}$, a (non-negative) lower bound to the flow through arc $(i,j)$; + +$u_{ij}$, an upper bound to the flow through arc $(i,j)$, which is the +{\it arc capacity}; + +$c_{ij}$, a per-unit cost of the flow through arc $(i,j)$. + +The problem is to find flows $x_{ij}$ through every arc of the network, +which satisfy the specified bounds and the conservation constraints at +all nodes, and minimize the total flow cost. Here the conservation +constraint at a node means that the total flow entering this node +through its incoming arcs plus the supply at this node must be equal to +the total flow leaving this node through its outgoing arcs plus the +demand at this node. + +An example of the minimum cost flow problem is shown on Fig.~1. + +\newpage + +\noindent\hfil +\xymatrix @C=48pt +{_{20}\ar@{~>}[d]& +v_2\ar[r]|{_{0,10,\$2}}\ar[dd]|{_{0,9,\$3}}& +v_3\ar[dd]|{_{2,12,\$1}}\ar[r]|{_{0,18,\$0}}& +v_8\ar[rd]|{_{0,20,\$9}}&\\ +v_1\ar[ru]|{_{0,14,\$0}}\ar[rd]|{_{0,23,\$0}}&&& +v_6\ar[d]|{_{0,7,\$0}}\ar[u]|{_{4,8,\$0}}& +v_9\ar@{~>}[d]\\ +&v_4\ar[r]|{_{0,26,\$0}}& +v_5\ar[luu]|{_{0,11,\$1}}\ar[ru]|{_{0,25,\$5}}\ar[r]|{_{0,4,\$7}}& +v_7\ar[ru]|{_{0,15,\$3}}&_{20}\\ +} + +\noindent\hfil +\begin{tabular}{ccc} +\xymatrix @C=48pt{v_i\ar[r]|{\ l,u,\$c\ }&v_j\\}& +\xymatrix{\hbox{\footnotesize supply}\ar@{~>}[r]&v_i\\}& +\xymatrix{v_i\ar@{~>}[r]&\hbox{\footnotesize demand}\\}\\ +\end{tabular} + +\noindent\hfil +Fig.~1. An example of the minimum cost flow problem. + +\medskip + +The minimum cost flow problem can be naturally formulated as the +following LP problem: + +\noindent +\hspace{1in}minimize +$$z=\sum_{(i,j)\in A}c_{ij}x_{ij}\eqno(1)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=b_i\ \ \ \hbox +{for all}\ i\in V\eqno(2)$$ +$$l_{ij}\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(3)$$ + +\subsection{glp\_read\_mincost --- read minimum cost flow problem data +in DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_mincost| reads the minimum cost flow problem +data from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +$b_i$, the supply/demand value. If \verb|v_rhs| $<0$, the value is not +stored. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$l_{ij}$, the lower bound to the arc flow. If \verb|a_low| $<0$, the +lower bound is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$u_{ij}$, the upper bound to the arc flow (the arc capacity). If +\verb|a_cap| $<0$, the upper bound is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$c_{ij}$, the per-unit cost of the arc flow. If \verb|a_cost| $<0$, the +cost is not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* vertex data block */ + ... + double rhs; + ... +} v_data; + +typedef struct +{ /* arc data block */ + ... + double low, cap, cost; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int ret; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\para{DIMACS minimum cost flow problem format\footnote{This +material is based on the paper ``The First DIMACS International +Algorithm Implementation Challenge: Problem Definitions and +Specifications'', which is publicly available at +\url{http://dimacs.rutgers.edu/Challenges}.}} +\label{subsecmincost} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +%\newpage + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. It +has the following format: + +\begin{verbatim} + p min NODES ARCS +\end{verbatim} + +\newpage + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|min| identifies the file as +containing specification information for the minimum cost flow problem. +The \verb|NODES| field contains an integer value specifying the number +of nodes in the network. The \verb|ARCS| field contains an integer value +specifying the number of arcs in the network. + +\para{Node descriptors.} All node descriptor lines must appear before +all arc descriptor lines. The node descriptor lines describe supply and +demand nodes, but not transshipment nodes. That is, only nodes with +non-zero node supply/demand values appear. There is one node descriptor +line for each such node, with the following format: + +\begin{verbatim} + n ID FLOW +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a node +descriptor line. The \verb|ID| field gives a node identification +number, an integer between 1 and \verb|NODES|. The \verb|FLOW| field +gives the amount of supply (if positive) or demand (if negative) at +node \verb|ID|. + +\para{Arc descriptors.} There is one arc descriptor line for each arc +in the network. Arc descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST LOW CAP COST +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an arc +descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives +the identification number $i$ for the tail endpoint, and the \verb|DST| +field gives the identification number $j$ for the head endpoint. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|LOW| field specifies the minimum amount of flow that can be sent +along arc $(i,j)$, and the \verb|CAP| field gives the maximum amount of +flow that can be sent along arc $(i,j)$ in a feasible flow. The +\verb|COST| field contains the per-unit cost of flow sent along arc +$(i,j)$. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the minimum cost flow problem shown on Fig~1. + +\begin{footnotesize} +\begin{verbatim} +c sample.min +c +c This is an example of the minimum cost flow problem data +c in DIMACS format. +c +p min 9 14 +c +n 1 20 +n 9 -20 +c +a 1 2 0 14 0 +a 1 4 0 23 0 +a 2 3 0 10 2 +a 2 4 0 9 3 +a 3 5 2 12 1 +a 3 8 0 18 0 +a 4 5 0 26 0 +a 5 2 0 11 1 +a 5 6 0 25 5 +a 5 7 0 4 7 +a 6 7 0 7 0 +a 6 8 4 8 0 +a 7 9 0 15 3 +a 8 9 0 20 9 +c +c eof +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_write\_mincost --- write minimum cost flow problem +data in DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_mincost| writes the minimum cost flow +problem data to a text file in DIMACS format. + +The parameter \verb|G| is the graph (network) program object, which +specifies the minimum cost flow problem instance. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ +for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed +that $c_{ij}=0$ for all arcs. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +%\newpage + +\subsection{glp\_mincost\_lp --- convert minimum cost flow problem +to LP} + +\synopsis + +\begin{verbatim} + void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_lp| builds LP problem (1)---(3), which +corresponds to the specified minimum cost flow problem. + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|G| is the graph (network) program object, which +specifies the minimum cost flow problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the flag is +\verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ +for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed that +$c_{ij}=0$ for all arcs. + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', converts the instance to +LP, and then writes the resultant LP in CPLEX format to file +`\verb|mincost.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include +#include + +typedef struct { double rhs; } v_data; +typedef struct { double low, cap, cost; } a_data; + +int main(void) +{ glp_graph *G; + glp_prob *P; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + P = glp_create_prob(); + glp_mincost_lp(P, G, GLP_ON, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost)); + glp_delete_graph(G); + glp_write_lp(P, NULL, "mincost.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, file `\verb|mincost.lp|' may look +like follows: + +\begin{footnotesize} +\begin{verbatim} +Minimize + obj: + 3 x(2,4) + 2 x(2,3) + x(3,5) + 7 x(5,7) + 5 x(5,6) + + x(5,2) + 3 x(7,9) + 9 x(8,9) + +Subject To + r_1: + x(1,2) + x(1,4) = 20 + r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 + r_3: + x(3,5) + x(3,8) - x(2,3) = 0 + r_4: + x(4,5) - x(2,4) - x(1,4) = 0 + r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 + r_6: + x(6,7) + x(6,8) - x(5,6) = 0 + r_7: + x(7,9) - x(6,7) - x(5,7) = 0 + r_8: + x(8,9) - x(6,8) - x(3,8) = 0 + r_9: - x(8,9) - x(7,9) = -20 + +Bounds + 0 <= x(1,4) <= 23 + 0 <= x(1,2) <= 14 + 0 <= x(2,4) <= 9 + 0 <= x(2,3) <= 10 + 0 <= x(3,8) <= 18 + 2 <= x(3,5) <= 12 + 0 <= x(4,5) <= 26 + 0 <= x(5,7) <= 4 + 0 <= x(5,6) <= 25 + 0 <= x(5,2) <= 11 + 4 <= x(6,8) <= 8 + 0 <= x(6,7) <= 7 + 0 <= x(7,9) <= 15 + 0 <= x(8,9) <= 20 + +End +\end{verbatim} +\end{footnotesize} + +%\newpage + +\subsection{glp\_mincost\_okalg --- solve minimum cost flow problem +with out-of-kilter\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_okalg| finds optimal solution to the +minimum cost flow problem with the out-of-kilter +algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm +is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, +``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), +Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this +routine requires all the problem data to be integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the minimum cost flow problem instance to be solved. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. This value must be integer in the range +[$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|v_rhs| $<0$, it is +assumed that $b_i=0$ for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. This bound must be integer in the range +[$0$, \verb|INT_MAX|]. If \verb|a_low| $<0$, it is assumed that +$l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [$l_{ij}$, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is +assumed that $u_{ij}=1$ for all arcs. + +\newpage + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. This value must be integer in the range +[$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|a_cost| $<0$, it is +assumed that $c_{ij}=0$ for all arcs. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. If +\verb|sol| is NULL, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is +not stored. + +The parameter \verb|v_pi| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +$\pi_i$, the node potential, which is the Lagrange multiplier for the +corresponding flow conservation equality constraint (see (2) in +Subsection ``Background''). If necessary, the application program may +use the node potentials to compute $\lambda_{ij}$, reduced costs of the +arc flows $x_{ij}$, which are the Lagrange multipliers for the arc flow +bound constraints (see (3) ibid.), using the following formula: +$$\lambda_{ij}=c_{ij}-(\pi_i-\pi_j),$$ +where $c_{ij}$ is the per-unit cost for arc $(i,j)$. + +%\newpage + +Note that all solution components (the objective value, arc flows, and +node potentials) computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range. This code is also +returned if the total supply, which is the sum of $b_i$ over all source +nodes (nodes with $b_i>0$), exceeds \verb|INT_MAX|.\\ + +\verb|GLP_ERANGE| & The search was prematurely terminated because of +integer overflow.\\ + +\verb|GLP_EFAIL| & An error has been detected in the program logic. +(If this code is returned for your problem instance, please report to +\verb||.)\\ +\end{retlist} + +\para{Comments} + +By design the out-of-kilter algorithm is applicable only to networks, +where $b_i=0$ for {\it all} nodes, i.e. actually this algorithm finds a +minimal cost {\it circulation}. Due to this requirement the routine +\verb|glp_mincost_okalg| converts the original network to a network +suitable for the out-of-kilter algorithm in the following +way:\footnote{The conversion is performed internally and does not change +the original network program object passed to the routine.} + +1) it adds two auxiliary nodes $s$ and $t$; + +2) for each original node $i$ with $b_i>0$ the routine adds auxiliary +supply arc $(s\rightarrow i)$, flow $x_{si}$ through which is costless +($c_{si}=0$) and fixed to $+b_i$ ($l_{si}=u_{si}=+b_i$); + +3) for each original node $i$ with $b_i<0$ the routine adds auxiliary +demand arc $(i\rightarrow t)$, flow $x_{it}$ through which is costless +($c_{it}=0$) and fixed to $-b_i$ ($l_{it}=u_{it}=-b_i$); + +4) finally, the routine adds auxiliary feedback arc $(t\rightarrow s)$, +flow $x_{ts}$ through which is also costless ($c_{ts}=0$) and fixed to +$F$ ($l_{ts}=u_{ts}=F$), where $\displaystyle F=\sum_{b_i>0}b_i$ is the +total supply. + +\newpage + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', solves it by using the +routine \verb|glp_mincost_okalg|, and writes the solution found on the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { double rhs, pi; } v_data; +typedef struct { double low, cap, cost, x; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + ret = glp_mincost_okalg(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), &sol, offsetof(a_data, x), + offsetof(v_data, pi)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + printf("node %d: pi = %5g\n", i, node(v)->pi); + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("arc %d->%d: x = %5g; lambda = %5g\n", + v->i, w->i, arc(a)->x, + arc(a)->cost - (node(v)->pi - node(w)->pi)); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading min-cost flow problem data from `sample.min'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 213 +node 1: pi = -12 +arc 1->4: x = 13; lambda = 0 +arc 1->2: x = 7; lambda = 0 +node 2: pi = -12 +arc 2->4: x = 0; lambda = 3 +arc 2->3: x = 7; lambda = 0 +node 3: pi = -14 +arc 3->8: x = 5; lambda = 0 +arc 3->5: x = 2; lambda = 3 +node 4: pi = -12 +arc 4->5: x = 13; lambda = 0 +node 5: pi = -12 +arc 5->7: x = 4; lambda = -1 +arc 5->6: x = 11; lambda = 0 +arc 5->2: x = 0; lambda = 1 +node 6: pi = -17 +arc 6->8: x = 4; lambda = 3 +arc 6->7: x = 7; lambda = -3 +node 7: pi = -20 +arc 7->9: x = 11; lambda = 0 +node 8: pi = -14 +arc 8->9: x = 9; lambda = 0 +node 9: pi = -23 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_mincost\_relax4 --- solve minimum cost flow problem +with relaxation\\method of Bertsekas and Tseng (RELAX-IV)} + +\synopsis + +\begin{verbatim} + int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_relax4| finds optimal solution to the +minimum cost flow problem with the relaxation method RELAX-IV developed +by Bertsekas and Tseng.\footnote{GLPK implementation of this method is +based on a C translation of the original Fortran code {\tt RELAX4} +written by Dimitri P. Bertsekas and Paul Tseng, with a contribution by +Jonathan Eckstein in the phase II initialization.} This method is one +of most efficient methods for network optimization. + +Note that this routine requires all the problem data to be +integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the minimum cost flow problem instance to be solved. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains $b_i$, the +supply/demand value. This value must be integer in the range +[$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|v_rhs| $<0$, it is +assumed that $b_i=0$ for all nodes. + +The parameter \verb|a_low| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $l_{ij}$, the lower +bound to the arc flow. This bound must be integer in the range +{\linebreak} [$0$, \verb|INT_MAX|/4]. If \verb|a_low| $<0$, it is +assumed that $l_{ij}=0$ for all arcs. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [$l_{ij}$, \verb|INT_MAX|/4]. If \verb|a_cap| $<0$, it is +assumed that $u_{ij}=1$ for all arcs. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the +per-unit cost of the arc flow. This value must be integer in the range +[$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|a_cost| $<0$, it +is assumed that $c_{ij}=0$ for all arcs. + +\newpage + +The parameter \verb|crash| is an option that specifies initialization +method: + +0 --- default initialization is used; + +1 --- auction initialization is used. + +\noindent +If \verb|crash| = 1, initialization is performed with a special crash +procedure based on an auction/shorest path method. This option is +recommended for difficult problems where the default initialization +results in long running times. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. If +\verb|sol| is NULL, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is +not stored. + +The parameter \verb|a_rc| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +the reduced cost for corresponding arc flow (see (3) in Subsection +``Background''). If \verb|a_rc| $<0$, the reduced cost is not stored. + +Note that all solution components (the objective value, arc flows, and +node potentials) computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range.\\ + +\verb|GLP_ERANGE| & Unable to start the search because of integer +overflow.\\ +\end{retlist} + +\para{Example} + +The example program below reads the minimum cost problem instance in +DIMACS format from file `\verb|sample.min|', solves it by using the +routine \verb|glp_mincost_relax4|, and writes the solution found on the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { double rhs; } v_data; +typedef struct { double low, cap, cost, x, rc; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_mincost(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), "sample.min"); + ret = glp_mincost_relax4(G, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), 0, &sol, offsetof(a_data, x), + offsetof(a_data, rc)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("arc %d->%d: x = %5g; rc = %5g\n", + v->i, w->i, arc(a)->x, arc(a)->rc); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.min|' is the example data file from the subsection +describing \verb|glp_read_mincost|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading min-cost flow problem data from `sample.min'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 213 +arc 1->4: x = 13; rc = 0 +arc 1->2: x = 7; rc = 0 +arc 2->4: x = 0; rc = 3 +arc 2->3: x = 7; rc = 0 +arc 3->8: x = 5; rc = 0 +arc 3->5: x = 2; rc = 3 +arc 4->5: x = 13; rc = 0 +arc 5->7: x = 4; rc = -1 +arc 5->6: x = 11; rc = 0 +arc 5->2: x = 0; rc = 1 +arc 6->8: x = 4; rc = 3 +arc 6->7: x = 7; rc = -3 +arc 7->9: x = 11; rc = 0 +arc 8->9: x = 9; rc = 0 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_netgen --- Klingman's network problem generator} + +\synopsis + +\begin{verbatim} + int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+15]); +\end{verbatim} + +\description + +The routine \verb|glp_netgen| is a GLPK version of the network problem +generator developed by Dr.~Darwin~Klingman.\footnote{D.~Klingman, +A.~Napier, and J.~Stutz. NETGEN: A program for generating large scale +capacitated assignment, transportation, and minimum cost flow networks. +Management Science 20 (1974), 814-20.} It can create capacitated and +uncapacitated minimum cost flow (or transshipment), transportation, and +assignment problems. + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +\newpage + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores the +supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not +stored. + +The array \verb|parm| contains description of the network to be +generated: + +\begin{tabular}{@{}lll@{}} +\verb|parm[0] |& ¬ used\\ +\verb|parm[1] |&\verb|iseed |&8-digit positive random number seed\\ +\verb|parm[2] |&\verb|nprob |&8-digit problem id number\\ +\verb|parm[3] |&\verb|nodes |&total number of nodes\\ +\verb|parm[4] |&\verb|nsorc |&total number of source nodes +(including transshipment nodes)\\ +\verb|parm[5] |&\verb|nsink |&total number of sink nodes +(including transshipment nodes)\\ +\verb|parm[6] |&\verb|iarcs |&number of arc\\ +\verb|parm[7] |&\verb|mincst|&minimum cost for arcs\\ +\verb|parm[8] |&\verb|maxcst|&maximum cost for arcs\\ +\verb|parm[9] |&\verb|itsup |&total supply\\ +\verb|parm[10]|&\verb|ntsorc|&number of transshipment source nodes\\ +\verb|parm[11]|&\verb|ntsink|&number of transshipment sink nodes\\ +\verb|parm[12]|&\verb|iphic |&percentage of skeleton arcs to be given +the maximum cost\\ +\verb|parm[13]|&\verb|ipcap |&percentage of arcs to be capacitated\\ +\verb|parm[14]|&\verb|mincap|&minimum upper bound for capacitated arcs\\ +\verb|parm[15]|&\verb|maxcap|&maximum upper bound for capacitated arcs\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_netgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\para{Notes} + +1. The routine generates a transportation problem if: +$${\tt nsorc}+{\tt nsink}={\tt nodes}, +\ {\tt ntsorc}=0,\ \mbox{and}\ {\tt ntsink}=0.$$ + +2. The routine generates an assignment problem if the requirements for +a transportation problem are met and: +$${\tt nsorc}={\tt nsink}\ \mbox{and}\ {\tt itsup}={\tt nsorc}.$$ + +3. The routine always generates connected graphs. So, if the number of +requested arcs has been reached and the generated instance is not fully +connected, the routine generates a few remaining arcs to ensure +connectedness. Thus, the actual number of arcs generated by the routine +may be greater than the requested number of arcs. + +\newpage + +\subsection{glp\_netgen\_prob --- Klingman's standard network problem +instance} + +\synopsis + +\begin{verbatim} + void glp_netgen_prob(int nprob, int parm[1+15]); +\end{verbatim} + +\description + +The routine \verb|glp_netgen_prob| provides the set of parameters for +Klingman's network problem generator (see the routine +\verb|glp_netgen|), which describe a standard network problem instance. + +The parameter \verb|nprob| ($101\leq$ \verb|nprob| $\leq 150$) +specifies the problem instance number. + +The array \verb|parm| contains description of the network, provided by +the routine. (For detailed description of these parameters see comments +to the routine \verb|glp_netgen|.) + +\para{Problem characteristics} + +The table below shows characteristics of Klingman's standard network +problem instances. +$$ +\begin{array}{crrr} +{\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ +\hline +101 & 5000 & 25336 & 6191726 \\ +102 & 5000 & 25387 & 72337144 \\ +103 & 5000 & 25355 & 218947553 \\ +104 & 5000 & 25344 & -19100371 \\ +105 & 5000 & 25332 & 31192578 \\ +106 & 5000 & 12870 & 4314276 \\ +107 & 5000 & 37832 & 7393769 \\ +108 & 5000 & 50309 & 8405738 \\ +109 & 5000 & 75299 & 9190300 \\ +110 & 5000 & 12825 & 8975048 \\ +111 & 5000 & 37828 & 4747532 \\ +112 & 5000 & 50325 & 4012671 \\ +113 & 5000 & 75318 & 2979725 \\ +114 & 5000 & 26514 & 5821181 \\ +115 & 5000 & 25962 & 6353310 \\ +116 & 5000 & 25304 & 5915426 \\ +117 & 5000 & 12816 & 4420560 \\ +118 & 5000 & 37797 & 7045842 \\ +119 & 5000 & 50301 & 7724179 \\ +120 & 5000 & 75330 & 8455200 \\ +121 & 5000 & 25000 & 66366360 \\ +122 & 5000 & 25000 & 30997529 \\ +123 & 5000 & 25000 & 23388777 \\ +124 & 5000 & 25000 & 17803443 \\ +125 & 5000 & 25000 & 14119622 \\ +\end{array} +\hspace{.5in} +\begin{array}{crrr} +{\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ +\hline +126 & 5000 & 12500 & 18802218 \\ +127 & 5000 & 37500 & 27674647 \\ +128 & 5000 & 50000 & 30906194 \\ +129 & 5000 & 75000 & 40905209 \\ +130 & 5000 & 12500 & 38939608 \\ +131 & 5000 & 37500 & 16752978 \\ +132 & 5000 & 50000 & 13302951 \\ +133 & 5000 & 75000 & 9830268 \\ +134 & 1000 & 25000 & 3804874 \\ +135 & 2500 & 25000 & 11729616 \\ +136 & 7500 & 25000 & 33318101 \\ +137 & 10000 & 25000 & 46426030 \\ +138 & 5000 & 25000 & 60710879 \\ +139 & 5000 & 25000 & 32729682 \\ +140 & 5000 & 25000 & 27183831 \\ +141 & 5000 & 25000 & 19963286 \\ +142 & 5000 & 25000 & 20243457 \\ +143 & 5000 & 25000 & 18586777 \\ +144 & 5000 & 25000 & 2504591 \\ +145 & 5000 & 25000 & 215956138 \\ +146 & 5000 & 25000 & 2253113811 \\ +147 & 5000 & 25000 & -427908373 \\ +148 & 5000 & 25000 & -92965318 \\ +149 & 5000 & 25000 & 86051224 \\ +150 & 5000 & 25000 & 619314919 \\ +\end{array} +$$ + +\newpage + +\subsection{glp\_gridgen --- grid-like network problem generator} + +\synopsis + +\begin{verbatim} + int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+14]); +\end{verbatim} + +\description + +The routine \verb|glp_gridgen| is a GLPK version of the grid-like +network problem generator developed by Yusin Lee and Jim +Orlin.\footnote{Y.~Lee and J.~Orlin. GRIDGEN generator., 1991. The +original code is publicly available from +\url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen}.} + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +The parameter \verb|v_rhs| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores the +supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not +stored. + +The array \verb|parm| contains parameters of the network to be +generated: + +\begin{tabular}{@{}ll@{}} +\verb|parm[0] |¬ used\\ +\verb|parm[1] |&two-ways arcs indicator:\\ + &1 --- if links in both direction should be generated\\ + &0 --- otherwise\\ +\verb|parm[2] |&random number seed (a positive integer)\\ +\verb|parm[3] |&number of nodes (the number of nodes generated might +be slightly different to\\&make the network a grid)\\ +\verb|parm[4] |&grid width\\ +\verb|parm[5] |&number of sources\\ +\verb|parm[6] |&number of sinks\\ +\verb|parm[7] |&average degree\\ +\verb|parm[8] |&total flow\\ +\verb|parm[9] |&distribution of arc costs: +1 --- uniform, 2 --- exponential\\ +\verb|parm[10]|&lower bound for arc cost (uniform), +$100\lambda$ (exponential)\\ +\verb|parm[11]|&upper bound for arc cost (uniform), +not used (exponential)\\ +\verb|parm[12]|&distribution of arc capacities: +1 --- uniform, 2 --- exponential\\ +\verb|parm[13]|&lower bound for arc capacity (uniform), +$100\lambda$ (exponential)\\ +\verb|parm[14]|&upper bound for arc capacity (uniform), +not used (exponential)\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_gridgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\newpage + +\para{Comments\footnote{This material is based on comments +to the original version of GRIDGEN.}} + +This network generator generates a grid-like network plus a super node. +In additional to the arcs connecting the nodes in the grid, there is an +arc from each supply node to the super node and from the super node to +each demand node to guarantee feasiblity. These arcs have very high +costs and very big capacities. + +The idea of this network generator is as follows: First, a grid of +$n_1\times n_2$ is generated. For example, $5\times 3$. The nodes are +numbered as 1 to 15, and the supernode is numbered as +$n_1\times n_2+1$. Then arcs between adjacent nodes are generated. +For these arcs, the user is allowed to specify either to generate +two-way arcs or one-way arcs. If two-way arcs are to be generated, two +arcs, one in each direction, will be generated between each adjacent +node pairs. Otherwise, only one arc will be generated. If this is the +case, the arcs will be generated in alterntive directions as shown +below. + +\medskip + +\noindent\hfil +\xymatrix +{1\ar[r]\ar[d]&2\ar[r]&3\ar[r]\ar[d]&4\ar[r]&5\ar[d]\\ +6\ar[d]&7\ar[l]\ar[u]&8\ar[l]\ar[d]&9\ar[l]\ar[u]&10\ar[l]\ar[d]\\ +11\ar[r]&12\ar[r]\ar[u]&13\ar[r]&14\ar[r]\ar[u]&15\\ +} + +\medskip + +Then the arcs between the super node and the source/sink nodes are +added as mentioned before. If the number of arcs still doesn't reach +the requirement, additional arcs will be added by uniformly picking +random node pairs. There is no checking to prevent multiple arcs +between any pair of nodes. However, there will be no self-arcs (arcs +that poins back to its tail node) in the network. + +The source and sink nodes are selected uniformly in the network, and +the imbalances of each source/sink node are also assigned by uniform +distribution. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Maximum flow problem} + +\subsection{Background} + +The {\it maximum flow problem} (MAXFLOW) is stated as follows. Let +there be given a directed graph (flow network) $G=(V,A)$, where $V$ is +a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. +Let also for each arc $a=(i,j)\in A$ there be given its capacity +$u_{ij}$. The problem is, for given {\it source} node $s\in V$ and +{\it sink} node $t\in V$, to find flows $x_{ij}$ through every arc of +the network, which satisfy the specified arc capacities and the +conservation constraints at all nodes, and maximize the total flow $F$ +through the network from $s$ to $t$. Here the conservation constraint +at a node means that the total flow entering this node through its +incoming arcs (plus $F$, if it is the source node) must be equal to the +total flow leaving this node through its outgoing arcs (plus $F$, if it +is the sink node). An example of the maximum flow problem, +where $s=v_1$ and $t=v_9$, is shown on Fig.~2. + +\medskip + +\noindent\hfil +\xymatrix @C=48pt +{_{F}\ar@{~>}[d]& +v_2\ar[r]|{_{10}}\ar[dd]|{_{9}}& +v_3\ar[dd]|{_{12}}\ar[r]|{_{18}}& +v_8\ar[rd]|{_{20}}&\\ +v_1\ar[ru]|{_{14}}\ar[rd]|{_{23}}&&& +v_6\ar[d]|{_{7}}\ar[u]|{_{8}}& +v_9\ar@{~>}[d]\\ +&v_4\ar[r]|{_{26}}& +v_5\ar[luu]|{_{11}}\ar[ru]|{_{25}}\ar[r]|{_{4}}& +v_7\ar[ru]|{_{15}}&_{F}\\ +} + +\medskip + +\noindent\hfil +Fig.~2. An example of the maximum flow problem. + +\medskip + +The maximum flow problem can be naturally formulated as the following +LP problem: + +\noindent +\hspace{1in}maximize +$$F\eqno(4)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=\left\{ +\begin{array}{@{\ }rl} ++F,&\hbox{for}\ i=s\\ + 0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ +-F,&\hbox{for}\ i=t\\ +\end{array} +\right.\eqno(5) +$$ +$$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(6)$$ + +\noindent +where $F\geq 0$ is an additional variable playing the role of the +objective. + +Another LP formulation of the maximum flow problem, which does not +include the variable $F$, is the following: + +\noindent +\hspace{1in}maximize +$$z=\sum_{(s,j)\in A}x_{sj}-\sum_{(j,s)\in A}x_{js}\ (=F)\eqno(7)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}\left\{ +\begin{array}{@{\ }rl} +\geq 0,&\hbox{for}\ i=s\\ +=0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ +\leq 0,&\hbox{for}\ i=t\\ +\end{array} +\right.\eqno(8) +$$ +$$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A +\eqno(9)$$ + +\newpage + +\subsection{glp\_read\_maxflow --- read maximum flow problem data in +DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_maxflow| reads the maximum flow problem +data from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The pointer \verb|s| specifies a location, to which the routine stores +the ordinal number of the source node. If \verb|s| is \verb|NULL|, the +source node number is not stored. + +The pointer \verb|t| specifies a location, to which the routine stores +the ordinal number of the sink node. If \verb|t| is \verb|NULL|, the +sink node number is not stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$u_{ij}$, the arc capacity. If \verb|a_cap| $<0$, the arc capacity is +not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example} + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* arc data block */ + ... + double cap; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int s, t, ret; + G = glp_create_graph(..., sizeof(a_data)); + ret = glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), + "sample.max"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\newpage + +\para{DIMACS maximum flow problem format\footnote{This material is +based on the paper ``The First DIMACS International Algorithm +Implementation Challenge: Problem Definitions and Specifications'', +which is publicly available at +\url{http://dimacs.rutgers.edu/Challenges/}.}} +\label{subsecmaxflow} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. +It has the following format: + +\begin{verbatim} + p max NODES ARCS +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|max| identifies the file as +containing specification information for the maximum flow problem. The +\verb|NODES| field contains an integer value specifying the number of +nodes in the network. The \verb|ARCS| field contains an integer value +specifying the number of arcs in the network. + +\para{Node descriptors.} Two node descriptor lines for the source and +sink nodes must appear before all arc descriptor lines. They may appear +in either order, each with the following format: + +\begin{verbatim} + n ID WHICH +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this a node descriptor +line. The \verb|ID| field gives a node identification number, +an integer between 1 and \verb|NODES|. The \verb|WHICH| field gives +either a lower-case \verb|s| or \verb|t|, designating the source and +sink, respectively. + +\para{Arc descriptors.} There is one arc descriptor line for each arc +in the network. Arc descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST CAP +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an arc +descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives +the identification number $i$ for the tail endpoint, and the \verb|DST| +field gives the identification number $j$ for the head endpoint. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|CAP| field gives the arc capacity, i.e. maximum amount of flow +that can be sent along arc $(i,j)$ in a feasible flow. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the maximum flow problem shown on Fig~2. + +\begin{footnotesize} +\begin{verbatim} +c sample.max +c +c This is an example of the maximum flow problem data +c in DIMACS format. +c +p max 9 14 +c +n 1 s +n 9 t +c +a 1 2 14 +a 1 4 23 +a 2 3 10 +a 2 4 9 +a 3 5 12 +a 3 8 18 +a 4 5 26 +a 5 2 11 +a 5 6 25 +a 5 7 4 +a 6 7 7 +a 6 8 8 +a 7 9 15 +a 8 9 20 +c +c eof +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_write\_maxflow --- write maximum flow problem data in +DIMACS\\format} + +\synopsis + +\begin{verbatim} + int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_maxflow| writes the maximum flow problem +data to a text file in DIMACS format. + +The parameter \verb|G| is the graph (network) program object, which +specifies the maximum flow problem instance. + +The parameter \verb|s| specifies the ordinal number of the source node. + +The parameter \verb|t| specifies the ordinal number of the sink node. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\newpage + +\subsection{glp\_maxflow\_lp --- convert maximum flow problem to LP} + +\synopsis + +\begin{verbatim} + void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, int t, + int a_cap); +\end{verbatim} + +\description + +The routine \verb|glp_maxflow_lp| builds LP problem (7)---(9), which +corresponds to the specified maximum flow problem. + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|G| is the graph (network) program object, which +specifies the maximum flow problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the flag is +\verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|s| specifies the ordinal number of the source node. + +The parameter \verb|t| specifies the ordinal number of the sink node. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). If the upper bound is +specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. +the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +\para{Example} + +The example program below reads the maximum flow problem in DIMACS +format from file `\verb|sample.max|', converts the instance to LP, and +then writes the resultant LP in CPLEX format to file +`\verb|maxflow.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include +#include + +int main(void) +{ glp_graph *G; + glp_prob *P; + int s, t; + G = glp_create_graph(0, sizeof(double)); + glp_read_maxflow(G, &s, &t, 0, "sample.max"); + P = glp_create_prob(); + glp_maxflow_lp(P, G, GLP_ON, s, t, 0); + glp_delete_graph(G); + glp_write_lp(P, NULL, "maxflow.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.max|' is the example data file from the previous +subsection, the output `\verb|maxflow.lp|' may look like follows: + +\newpage + +\begin{footnotesize} +\begin{verbatim} +Maximize + obj: + x(1,4) + x(1,2) + +Subject To + r_1: + x(1,2) + x(1,4) >= 0 + r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 + r_3: + x(3,5) + x(3,8) - x(2,3) = 0 + r_4: + x(4,5) - x(2,4) - x(1,4) = 0 + r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 + r_6: + x(6,7) + x(6,8) - x(5,6) = 0 + r_7: + x(7,9) - x(6,7) - x(5,7) = 0 + r_8: + x(8,9) - x(6,8) - x(3,8) = 0 + r_9: - x(8,9) - x(7,9) <= 0 + +Bounds + 0 <= x(1,4) <= 23 + 0 <= x(1,2) <= 14 + 0 <= x(2,4) <= 9 + 0 <= x(2,3) <= 10 + 0 <= x(3,8) <= 18 + 0 <= x(3,5) <= 12 + 0 <= x(4,5) <= 26 + 0 <= x(5,7) <= 4 + 0 <= x(5,6) <= 25 + 0 <= x(5,2) <= 11 + 0 <= x(6,8) <= 8 + 0 <= x(6,7) <= 7 + 0 <= x(7,9) <= 15 + 0 <= x(8,9) <= 20 + +End +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_maxflow\_ffalg --- solve maximum flow problem with +Ford-Fulkerson\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, double *sol, + int a_x, int v_cut); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_ffalg| finds optimal solution to the +maximum flow problem with the Ford-Fulkerson algorithm.\footnote{GLPK +implementation of the Ford-Fulkerson algorithm is based on the +following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, ``Flows in +Networks,'' The RAND Corp., Report R-375-PR (August 1962), Chap. I +``Static Maximal Flow,'' pp.~30-33.} Note that this routine requires +all the problem data to be integer-valued. + +The parameter \verb|G| is a graph (network) program object which +specifies the maximum flow problem instance to be solved. + +The parameter $s$ specifies the ordinal number of the source node. + +The parameter $t$ specifies the ordinal number of the sink node. + +\newpage + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $u_{ij}$, the upper +bound to the arc flow (the arc capacity). This bound must be integer in +the range [0, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is assumed that +$u_{ij}=1$ for all arcs. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total flow from $s$ to $t$) +found. If \verb|sol| is NULL, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores +$x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow values +are not stored. + +The parameter \verb|v_cut| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores node +flags corresponding to the optimal solution found: if the node flag is +1, the node is labelled, and if the node flag is 0, the node is +unlabelled. The calling program may use these node flags to determine +the {\it minimal cut}, which is a subset of arcs whose one endpoint is +labelled and other is not. If \verb|v_cut| $<0$, the node flags are not +stored. + +Note that all solution components (the objective value and arc flows) +computed by the routine are always integer-valued. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some problem +data are either not integer-valued or out of range.\\ +\end{retlist} + +\para{Example} + +The example program shown below reads the maximum flow problem instance +in DIMACS format from file `\verb|sample.max|', solves it using the +routine \verb|glp_maxflow_ffalg|, and write the solution found to the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { int cut; } v_data; +typedef struct { double cap, x; } a_data; + +#define node(v) ((v_data *)((v)->data)) +#define arc(a) ((a_data *)((a)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v, *w; + glp_arc *a; + int i, s, t, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), + "sample.max"); + ret = glp_maxflow_ffalg(G, s, t, offsetof(a_data, cap), + &sol, offsetof(a_data, x), offsetof(v_data, cut)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { w = a->head; + printf("x[%d->%d] = %5g (%d)\n", v->i, w->i, + arc(a)->x, node(v)->cut ^ node(w)->cut); + } + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.max|' is the example data file from the subsection +describing \verb|glp_read_maxflow|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading maximum flow problem data from `sample.max'... +Flow network has 9 nodes and 14 arcs +24 lines were read +ret = 0; sol = 29 +x[1->4] = 19 (0) +x[1->2] = 10 (0) +x[2->4] = 0 (0) +x[2->3] = 10 (1) +x[3->8] = 10 (0) +x[3->5] = 0 (1) +x[4->5] = 19 (0) +x[5->7] = 4 (1) +x[5->6] = 15 (0) +x[5->2] = 0 (0) +x[6->8] = 8 (1) +x[6->7] = 7 (1) +x[7->9] = 11 (0) +x[8->9] = 18 (0) +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_rmfgen --- Goldfarb's maximum flow problem generator} + +\synopsis + +\begin{verbatim} + int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, const int parm[1+5]); +\end{verbatim} + +\description + +The routine \verb|glp_rmfgen| is a GLPK version of the maximum flow +problem generator developed by D.~Goldfarb and +M.~Grigoriadis.\footnote{D.~Goldfarb and M.~D.~Grigoriadis, +``A computational comparison of the Dinic and network simplex methods +for maximum flow.'' Annals of Op. Res. 13 (1988), +pp.~83-123.}$^{,}$\footnote{U.~Derigs and W.~Meier, ``Implementing +Goldberg's max-flow algorithm: A computational investigation.'' +Zeitschrift f\"ur Operations Research 33 (1989), +pp.~383-403.}$^{,}$\footnote{The original code of RMFGEN implemented by +Tamas Badics is publicly available from +\url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf}.} + +The parameter \verb|G| specifies the graph object, to which the +generated problem data have to be stored. Note that on entry the graph +object is erased with the routine \verb|glp_erase_graph|. + +The pointers \verb|s| and \verb|t| specify locations, to which the +routine stores the source and sink node numbers, respectively. If +\verb|s| or \verb|t| is \verb|NULL|, corresponding node number is not +stored. + +The parameter \verb|a_cap| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. + +\newpage + +The array \verb|parm| contains description of the network to be +generated: + +\begin{tabular}{@{}lll@{}} +\verb|parm[0]|& ¬ used\\ +\verb|parm[1]|&\verb|seed|&random number seed (a positive integer)\\ +\verb|parm[2]|&\verb|a |&frame size\\ +\verb|parm[3]|&\verb|b |&depth\\ +\verb|parm[4]|&\verb|c1 |&minimal arc capacity\\ +\verb|parm[5]|&\verb|c2 |&maximal arc capacity\\ +\end{tabular} + +\returns + +If the instance was successfully generated, the routine +\verb|glp_netgen| returns zero; otherwise, if specified parameters are +inconsistent, the routine returns a non-zero error code. + +\para{Comments\footnote{This material is based on comments to the +original version of RMFGEN.}} + +The generated network is as follows. It has $b$ pieces of frames of +size $a\times a$. (So alltogether the number of vertices is +$a\times a\times b$.) + +In each frame all the vertices are connected with their neighbours +(forth and back). In addition the vertices of a frame are connected +one to one with the vertices of next frame using a random permutation +of those vertices. + +The source is the lower left vertex of the first frame, the sink is +the upper right vertex of the $b$-th frame. + +\begin{verbatim} + t + +-------+ + | .| + | . | + / | / | + +-------+/ -+ b + | | |/. + a | -v- |/ + | | |/ + +-------+ 1 + s a +\end{verbatim} + +The capacities are randomly chosen integers from the range of +$[c_1,c_2]$ in the case of interconnecting edges, and $c_2\cdot a^2$ +for the in-frame edges. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Assignment problem} + +\subsection{Background} + +Let there be given an undirected bipartite graph $G=(R\cup S,E)$, where +$R$ and $S$ are disjoint sets of vertices (nodes), and +$E\subseteq R\times S$ is a set of edges. Let also for each edge +$e=(i,j)\in E$ there be given its cost $c_{ij}$. A {\it matching} +(which in case of bipartite graph is also called {\it assignment}) +$M\subseteq E$ in $G$ is a set of pairwise non-adjacent edges, that is, +no two edges in $M$ share a common vertex. A matching, which matches +all vertices of the graph, is called a {\it perfect matching}. +Obviously, a perfect matching in bipartite graph $G=(R\cup S,E)$ +defines some bijection $R\leftrightarrow S$. + +The {\it assignment problem} has two different variants. In the first +variant the problem is to find matching (assignment) $M$, which +maximizes the sum: +$$\sum_{(i,j)\in M}c_{ij}\eqno(10)$$ +(so this variant is also called the {\it maximum weighted bipartite +matching problem} or, if all $c_{ij}=1$, the {\it maximum cardinality +bipartite matching problem}). In the second, classic variant the +problem is to find {\it perfect} matching (assignment) $M$, which +minimizes or maximizes the sum (10). + +An example of the assignment problem, which is the maximum weighted +bipartite matching problem, is shown on Fig. 3. + +The maximum weighted bipartite matching problem can be naturally +formulated as the following LP problem: + +\noindent +\hspace{1in}maximize +$$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(11)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ i\in R\eqno(12)$$ +$$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ j\in S\eqno(13)$$ +$$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E +\eqno(14)$$ + +\noindent +where $x_{ij}=1$ means that $(i,j)\in M$, and $x_{ij}=0$ means that +$(i,j)\notin M$.\footnote{The constraint matrix of LP formulation +(11)---(14) is totally unimodular, due to which $x_{ij}\in\{0,1\}$ for +any basic solution.} + +\newpage + +\noindent\hfil +\xymatrix @C=48pt +{v_1\ar@{-}[rr]|{_{13}}\ar@{-}[rrd]|{_{21}}\ar@{-}[rrddd]|(.2){_{20}}&& +v_9\\ +v_2\ar@{-}[rr]|{_{12}}\ar@{-}[rrdd]|(.3){_{8}} +\ar@{-}[rrddd]|(.4){_{26}}&&v_{10}\\ +v_3\ar@{-}[rr]|(.2){_{22}}\ar@{-}[rrdd]|(.3){_{11}}&&v_{11}\\ +v_4\ar@{-}[rruuu]|(.6){_{12}}\ar@{-}[rr]|(.2){_{36}} +\ar@{-}[rrdd]|(.7){_{25}}&&v_{12}\\ +v_5\ar@{-}[rruu]|(.42){_{41}}\ar@{-}[rru]|(.4){_{40}} +\ar@{-}[rr]|(.75){_{11}}\ar@{-}[rrd]|(.6){_{4}}\ar@{-}[rrdd]|{_{8}} +\ar@{-}[rrddd]|{_{35}}\ar@{-}[rrdddd]|{_{32}}&&v_{13}\\ +v_6\ar@{-}[rruuuuu]|(.7){_{13}}&&v_{14}\\ +v_7\ar@{-}[rruuuuu]|(.15){_{19}}&&v_{15}\\ +v_8\ar@{-}[rruuuuuu]|(.25){_{39}}\ar@{-}[rruuuuu]|(.65){_{15}}&& +v_{16}\\ +&&v_{17}\\ +} + +\medskip + +\noindent\hfil +Fig.~3. An example of the assignment problem. + +\medskip + +Similarly, the perfect assignment problem can be naturally formulated +as the following LP problem: + +\noindent +\hspace{1in}minimize (or maximize) +$$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(15)$$ +\hspace{1in}subject to +$$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ i\in R\eqno(16)$$ +$$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ j\in S\eqno(17)$$ +$$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E +\eqno(18)$$ + +\noindent +where variables $x_{ij}$ have the same meaning as for (11)---(14) +above. + +In GLPK an undirected bipartite graph $G=(R\cup S,E)$ is represented as +directed graph $\overline{G}=(V,A)$, where $V=R\cup S$ and +$A=\{(i,j):(i,j)\in E\}$, i.e. every edge $(i,j)\in E$ in $G$ +corresponds to arc $(i\rightarrow j)\in A$ in $\overline{G}$. + +\newpage + +\setlength{\parskip}{4.4pt} + +\subsection{glp\_read\_asnprob --- read assignment problem data in +DIMACS format} + +\synopsis + +\begin{verbatim} + int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_read_asnprob| reads the assignment problem data +from a text file in DIMACS format. + +The parameter \verb|G| specifies the graph object, to which the problem +data have to be stored. Note that before reading data the current +content of the graph object is completely erased with the routine +\verb|glp_erase_graph|. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, to which the routine stores the +node set indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, the node set indicator is not stored. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, to which the routine stores the +edge cost $c_{ij}$. If \verb|a_cost| $<0$, the edge cost is not stored. + +The character string \verb|fname| specifies the name of a text file to +be read in. (If the file name name ends with the suffix `\verb|.gz|', +the file is assumed to be compressed, in which case the routine +decompresses it ``on the fly''.) + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\para{Example.} Below here is an example program that read the +assignment problem data in DIMACS format from a text file +`\verb|sample.asn|'. + +\begin{footnotesize} +\begin{verbatim} +typedef struct +{ /* vertex data block */ + ... + int set; + ... +} v_data; + +typedef struct +{ /* arc data block */ + ... + double cost; + ... +} a_data; + +int main(void) +{ glp_graph *G; + int ret; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_asnprob(G, offsetof(v_data, set), + offsetof(a_data, cost), "sample.asn"); + if (ret != 0) goto ... + ... +} +\end{verbatim} +\end{footnotesize} + +\setlength{\parskip}{5pt} + +\newpage + +\para{DIMACS assignment problem format\footnote{This material is based +on the paper ``The First DIMACS International Algorithm Implementation +Challenge: Problem Definitions and Specifications'', which is +publicly available at \url{http://dimacs.rutgers.edu/Challenges/}.}} +\label{subsecasnprob} + +The DIMACS input file is a plain ASCII text file. It contains +{\it lines} of several types described below. A line is terminated with +an end-of-line character. Fields in each line are separated by at least +one blank space. Each line begins with a one-character designator to +identify the line type. + +Note that DIMACS requires all numerical quantities to be integers in +the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be +floating-point numbers. + +\para{Comment lines.} Comment lines give human-readable information +about the file and are ignored by programs. Comment lines can appear +anywhere in the file. Each comment line begins with a lower-case +character \verb|c|. + +\begin{verbatim} + c This is a comment line +\end{verbatim} + +\para{Problem line.} There is one problem line per data file. The +problem line must appear before any node or arc descriptor lines. It +has the following format: + +\begin{verbatim} + p asn NODES EDGES +\end{verbatim} + +\noindent +The lower-case character \verb|p| signifies that this is a problem line. +The three-character problem designator \verb|asn| identifies the file as +containing specification information for the assignment problem. +The \verb|NODES| field contains an integer value specifying the total +number of nodes in the graph (i.e. in both sets $R$ and $S$). The +\verb|EDGES| field contains an integer value specifying the number of +edges in the graph. + +\para{Node descriptors.} All node descriptor lines must appear before +all edge descriptor lines. The node descriptor lines lists the nodes in +set $R$ only, and all other nodes are assumed to be in set $S$. There +is one node descriptor line for each such node, with the following +format: + +\begin{verbatim} + n ID +\end{verbatim} + +\noindent +The lower-case character \verb|n| signifies that this is a node +descriptor line. The \verb|ID| field gives a node identification number, +an integer between 1 and \verb|NODES|. + +\para{Edge descriptors.} There is one edge descriptor line for each +edge in the graph. Edge descriptor lines are of the following format: + +\begin{verbatim} + a SRC DST COST +\end{verbatim} + +\noindent +The lower-case character \verb|a| signifies that this is an edge +descriptor line. For each edge $(i,j)$, where $i\in R$ and $j\in S$, +the \verb|SRC| field gives the identification number of vertex $i$, and +the \verb|DST| field gives the identification number of vertex $j$. +Identification numbers are integers between 1 and \verb|NODES|. The +\verb|COST| field contains the cost of edge $(i,j)$. + +\para{Example.} Below here is an example of the data file in DIMACS +format corresponding to the assignment problem shown on Fig~3. + +\begin{footnotesize} +\begin{verbatim} +c sample.asn +c +c This is an example of the assignment problem data +c in DIMACS format. +c +p asn 17 22 +c +n 1 +n 2 +n 3 +n 4 +n 5 +n 6 +n 7 +n 8 +c +a 1 9 13 +a 1 10 21 +a 1 12 20 +a 2 10 12 +a 2 12 8 +a 2 13 26 +a 3 11 22 +a 3 13 11 +a 4 9 12 +a 4 12 36 +a 4 14 25 +a 5 11 41 +a 5 12 40 +a 5 13 11 +a 5 14 4 +a 5 15 8 +a 5 16 35 +a 5 17 32 +a 6 9 13 +a 7 10 19 +a 8 10 39 +a 8 11 15 +c +c eof +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_write\_asnprob --- write assignment problem data in +DIMACS format} + +\synopsis + +\begin{verbatim} + int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); +\end{verbatim} + +\description + +The routine \verb|glp_write_asnprob| writes the assignment problem data +to a text file in DIMACS format. + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all +edges. + +\newpage + +The character string \verb|fname| specifies a name of the text file to +be written out. (If the file name ends with suffix `\verb|.gz|', the +file is assumed to be compressed, in which case the routine performs +automatic compression on writing it.) + +\para{Note} + +The routine \verb|glp_write_asnprob| does not check that the specified +graph object correctly represents a bipartite graph. To make sure that +the problem data are correct, use the routine \verb|glp_check_asnprob|. + +\returns + +If the operation was successful, the routine returns zero. Otherwise, +it prints an error message and returns non-zero. + +\vspace*{-4pt} + +\subsection{glp\_check\_asnprob --- check correctness of assignment +problem data} + +\synopsis + +\begin{verbatim} + int glp_check_asnprob(glp_graph *G, int v_set); +\end{verbatim} + +\description + +The routine \verb|glp_check_asnprob| checks that the specified graph +object \verb|G| correctly represents a bipartite graph. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +\returns + +0 --- the data are correct; + +1 --- the set indicator of some node is 0, however, that node has one +or more incoming arcs; + +2 --- the set indicator of some node is 1, however, that node has one +or more outgoing arcs; + +3 --- the set indicator of some node is invalid (neither 0 nor 1); + +4 --- some node has both incoming and outgoing arcs. + +\subsection{glp\_asnprob\_lp --- convert assignment problem to LP} + +\synopsis + +\begin{verbatim} + int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, + int a_cost); +\end{verbatim} + +\description + +The routine \verb|glp_asnprob_lp| builds LP problem, which corresponds +to the specified assignment problem. + +\newpage + +The parameter \verb|P| is the resultant LP problem object to be built. +Note that on entry its current content is erased with the routine +\verb|glp_erase_prob|. + +The parameter \verb|form| defines which LP formulation should be used: + +\verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; + +\verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; + +\verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the +routine uses symbolic names of the graph object components to assign +symbolic names to the LP problem object components. If the \verb|flag| +is \verb|GLP_OFF|, no symbolic names are assigned. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all +edges. + +\returns + +If the LP problem has been successfully built, the routine +\verb|glp_asnprob_lp| returns zero, otherwise, non-zero (see the +routine \verb|glp_check_asnprob|). + +\para{Example} + +The example program below reads the assignment problem instance in +DIMACS format from file `\verb|sample.asn|', converts the instance to +LP (11)---(14), and writes the resultant LP in CPLEX format to file +`\verb|matching.lp|'. + +\begin{footnotesize} +\begin{verbatim} +#include +#include + +typedef struct { int set; } v_data; +typedef struct { double cost; } a_data; + +int main(void) +{ glp_graph *G; + glp_prob *P; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + glp_read_asnprob(G, offsetof(v_data, set), + offsetof(a_data, cost), "sample.asn"); + P = glp_create_prob(); + glp_asnprob_lp(P, GLP_ASN_MMP, G, GLP_ON, + offsetof(v_data, set), offsetof(a_data, cost)); + glp_delete_graph(G); + glp_write_lp(P, NULL, "matching.lp"); + glp_delete_prob(P); + return 0; +} +\end{verbatim} +\end{footnotesize} + +\newpage + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, file `\verb|matching.lp|' may look +like follows: + +\begin{footnotesize} +\begin{verbatim} +Maximize + obj: + 20 x(1,12) + 21 x(1,10) + 13 x(1,9) + 26 x(2,13) + 8 x(2,12) + + 12 x(2,10) + 11 x(3,13) + 22 x(3,11) + 25 x(4,14) + 36 x(4,12) + + 12 x(4,9) + 32 x(5,17) + 35 x(5,16) + 8 x(5,15) + 4 x(5,14) + + 11 x(5,13) + 40 x(5,12) + 41 x(5,11) + 13 x(6,9) + 19 x(7,10) + + 15 x(8,11) + 39 x(8,10) + +Subject To + r_1: + x(1,9) + x(1,10) + x(1,12) <= 1 + r_2: + x(2,10) + x(2,12) + x(2,13) <= 1 + r_3: + x(3,11) + x(3,13) <= 1 + r_4: + x(4,9) + x(4,12) + x(4,14) <= 1 + r_5: + x(5,11) + x(5,12) + x(5,13) + x(5,14) + x(5,15) + x(5,16) + + x(5,17) <= 1 + r_6: + x(6,9) <= 1 + r_7: + x(7,10) <= 1 + r_8: + x(8,10) + x(8,11) <= 1 + r_9: + x(6,9) + x(4,9) + x(1,9) <= 1 + r_10: + x(8,10) + x(7,10) + x(2,10) + x(1,10) <= 1 + r_11: + x(8,11) + x(5,11) + x(3,11) <= 1 + r_12: + x(5,12) + x(4,12) + x(2,12) + x(1,12) <= 1 + r_13: + x(5,13) + x(3,13) + x(2,13) <= 1 + r_14: + x(5,14) + x(4,14) <= 1 + r_15: + x(5,15) <= 1 + r_16: + x(5,16) <= 1 + r_17: + x(5,17) <= 1 + +Bounds + 0 <= x(1,12) <= 1 + 0 <= x(1,10) <= 1 + 0 <= x(1,9) <= 1 + 0 <= x(2,13) <= 1 + 0 <= x(2,12) <= 1 + 0 <= x(2,10) <= 1 + 0 <= x(3,13) <= 1 + 0 <= x(3,11) <= 1 + 0 <= x(4,14) <= 1 + 0 <= x(4,12) <= 1 + 0 <= x(4,9) <= 1 + 0 <= x(5,17) <= 1 + 0 <= x(5,16) <= 1 + 0 <= x(5,15) <= 1 + 0 <= x(5,14) <= 1 + 0 <= x(5,13) <= 1 + 0 <= x(5,12) <= 1 + 0 <= x(5,11) <= 1 + 0 <= x(6,9) <= 1 + 0 <= x(7,10) <= 1 + 0 <= x(8,11) <= 1 + 0 <= x(8,10) <= 1 + +End +\end{verbatim} +\end{footnotesize} + +\newpage + +\subsection{glp\_asnprob\_okalg --- solve assignment problem with +out-of-kilter\\algorithm} + +\synopsis + +\begin{verbatim} + int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x); +\end{verbatim} + +\description + +The routine \verb|glp_mincost_okalg| finds optimal solution to the +assignment problem with the out-of-kilter +algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm +is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, +``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), +Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this +routine requires all the problem data to be integer-valued. + +The parameter \verb|form| defines which LP formulation should be used: + +\verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; + +\verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; + +\verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). + +The parameter \verb|G| is the graph program object, which specifies the +assignment problem instance. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_cost| specifies an offset of the field of type +\verb|double| in the arc data block, which contains $c_{ij}$, the edge +cost. This value must be integer in the range [\verb|-INT_MAX|, +\verb|+INT_MAX|]. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ +for all edges. + +The parameter \verb|sol| specifies a location, to which the routine +stores the objective value (that is, the total cost) found. +If \verb|sol| is \verb|NULL|, the objective value is not stored. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|int| in the arc data block, to which the routine stores $x_{ij}$. +If \verb|a_x| $<0$, this value is not stored. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ + +\verb|GLP_EDATA| & Unable to start the search, because the assignment +problem data are either incorrect (this error is detected by the +routine \verb|glp_check_asnprob|), not integer-valued or out of range.\\ + +\verb|GLP_ERANGE| & The search was prematurely terminated because of +integer overflow.\\ + +\verb|GLP_EFAIL| & An error has been detected in the program logic. +(If this code is returned for your problem instance, please report to +\verb||.)\\ +\end{retlist} + +\newpage + +\para{Comments} + +Since the out-of-kilter algorithm is designed to find a minimal cost +circulation, the routine \verb|glp_asnprob_okalg| converts the original +graph to a network suitable for this algorithm in the following +way:\footnote{The conversion is performed internally and does not +change the original graph program object passed to the routine.} + +1) it replaces each edge $(i,j)$ by arc $(i\rightarrow j)$, +flow $x_{ij}$ through which has zero lower bound ($l_{ij}=0$), unity +upper bound ($u_{ij}=1$), and per-unit cost $+c_{ij}$ (in case of +\verb|GLP_ASN_MIN|), or $-c_{ij}$ (in case of \verb|GLP_ASN_MAX| and +\verb|GLP_ASN_MMP|); + +2) then it adds one auxiliary feedback node $k$; + +3) for each original node $i\in R$ the routine adds auxiliary supply +arc $(k\rightarrow i)$, flow $x_{ki}$ through which is costless +($c_{ki}=0$) and either fixed at 1 ($l_{ki}=u_{ki}=1$, in case of +\verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound and +unity upper bound ($l_{ij}=0$, $u_{ij}=1$, in case of +\verb|GLP_ASN_MMP|); + +4) similarly, for each original node $j\in S$ the routine adds +auxiliary demand arc $(j\rightarrow k)$, flow $x_{jk}$ through which is +costless ($c_{jk}=0$) and either fixed at 1 ($l_{jk}=u_{jk}=1$, in case +of \verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound +and unity upper bound ($l_{jk}=0$, $u_{jk}=1$, in case of +\verb|GLP_ASN_MMP|). + +\para{Example} + +The example program shown below reads the assignment problem instance +in DIMACS format from file `\verb|sample.asn|', solves it by using the +routine \verb|glp_asnprob_okalg|, and writes the solution found to the +standard output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { int set; } v_data; +typedef struct { double cost; int x; } e_data; + +#define node(v) ((v_data *)((v)->data)) +#define edge(e) ((e_data *)((e)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + glp_arc *e; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), sizeof(e_data)); + glp_read_asnprob(G, offsetof(v_data, set), + offsetof(e_data, cost), "sample.asn"); + ret = glp_asnprob_okalg(GLP_ASN_MMP, G, + offsetof(v_data, set), offsetof(e_data, cost), &sol, + offsetof(e_data, x)); + printf("ret = %d; sol = %5g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + printf("edge %2d %2d: x = %d; c = %g\n", + e->tail->i, e->head->i, edge(e)->x, edge(e)->cost); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, the output may look like follows: + +\begin{footnotesize} +\begin{verbatim} +Reading assignment problem data from `sample.asn'... +Assignment problem has 8 + 9 = 17 nodes and 22 arcs +38 lines were read +ret = 0; sol = 180 +edge 1 12: x = 1; c = 20 +edge 1 10: x = 0; c = 21 +edge 1 9: x = 0; c = 13 +edge 2 13: x = 1; c = 26 +edge 2 12: x = 0; c = 8 +edge 2 10: x = 0; c = 12 +edge 3 13: x = 0; c = 11 +edge 3 11: x = 1; c = 22 +edge 4 14: x = 1; c = 25 +edge 4 12: x = 0; c = 36 +edge 4 9: x = 0; c = 12 +edge 5 17: x = 0; c = 32 +edge 5 16: x = 1; c = 35 +edge 5 15: x = 0; c = 8 +edge 5 14: x = 0; c = 4 +edge 5 13: x = 0; c = 11 +edge 5 12: x = 0; c = 40 +edge 5 11: x = 0; c = 41 +edge 6 9: x = 1; c = 13 +edge 7 10: x = 0; c = 19 +edge 8 11: x = 0; c = 15 +edge 8 10: x = 1; c = 39 +\end{verbatim} +\end{footnotesize} + +\subsection{glp\_asnprob\_hall --- find bipartite matching of maximum +cardinality} + +\synopsis + +\begin{verbatim} + int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +\end{verbatim} + +\description + +The routine \verb|glp_asnprob_hall| finds a matching of maximal +cardinality in the specified bipartite graph. It uses a version of the +Fortran routine \verb|MC21A| developed by +I.~S.~Duff\footnote{I.~S.~Duff, Algorithm 575: Permutations for +zero-free diagonal, ACM Trans. on Math. Softw. 7 (1981),\linebreak +pp.~387-390.}, which implements Hall's algorithm.\footnote{M.~Hall, +``An Algorithm for Distinct Representatives,'' Am. Math. Monthly 63 +(1956), pp.~716-717.} + +The parameter \verb|G| is a pointer to the graph program object. + +The parameter \verb|v_set| specifies an offset of the field of type +\verb|int| in the vertex data block, which contains the node set +indicator: + +0 --- the node is in set $R$; + +1 --- the node is in set $S$. + +\newpage + +\noindent +If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs +is in set $R$, and a node having no outgoing arcs is in set $S$. + +The parameter \verb|a_x| specifies an offset of the field of type +\verb|int| in the arc data block, to which the routine stores $x_{ij}$. +If \verb|a_x| $<0$, this value is not stored. + +\returns + +The routine \verb|glp_asnprob_hall| returns the cardinality of the +matching found. However, if the specified graph is incorrect (as +detected by the routine \verb|glp_check_asnprob|), this routine returns +a negative value. + +\para{Comments} + +The same solution may be obtained with the routine +\verb|glp_asnprob_okalg| (for LP formulation \verb|GLP_ASN_MMP| and +all edge costs equal to 1). However, the routine +\verb|glp_asnprob_hall| is much faster. + +\para{Example} + +The example program shown below reads the assignment problem instance +in DIMACS format from file `\verb|sample.asn|', finds a bipartite +matching of maximal cardinality by using the routine +\verb|glp_asnprob_hall|, and writes the solution found to the standard +output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { int set; } v_data; +typedef struct { int x; } e_data; + +#define node(v) ((v_data *)((v)->data)) +#define edge(e) ((e_data *)((e)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + glp_arc *e; + int i, card; + G = glp_create_graph(sizeof(v_data), sizeof(e_data)); + glp_read_asnprob(G, offsetof(v_data, set), -1, + "sample.asn"); + card = glp_asnprob_hall(G, offsetof(v_data, set), + offsetof(e_data, x)); + printf("card = %d\n", card); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + printf("edge %2d %2d: x = %d\n", + e->tail->i, e->head->i, edge(e)->x); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +If `\verb|sample.asn|' is the example data file from the subsection +describing \verb|glp_read_asnprob|, the output may look like follows: + +\newpage + +\begin{footnotesize} +\begin{verbatim} +Reading assignment problem data from `sample.asn'... +Assignment problem has 8 + 9 = 17 nodes and 22 arcs +38 lines were read +card = 7 +edge 1 12: x = 1 +edge 1 10: x = 0 +edge 1 9: x = 0 +edge 2 13: x = 1 +edge 2 12: x = 0 +edge 2 10: x = 0 +edge 3 13: x = 0 +edge 3 11: x = 1 +edge 4 14: x = 1 +edge 4 12: x = 0 +edge 4 9: x = 0 +edge 5 17: x = 1 +edge 5 16: x = 0 +edge 5 15: x = 0 +edge 5 14: x = 0 +edge 5 13: x = 0 +edge 5 12: x = 0 +edge 5 11: x = 0 +edge 6 9: x = 1 +edge 7 10: x = 1 +edge 8 11: x = 0 +edge 8 10: x = 0 +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section{Critical path problem} + +\subsection{Background} + +The {\it critical path problem} (CPP) is stated as follows. Let there +be given a project $J$, which is a set of jobs (tasks, activities, +etc.). Performing each job $i\in J$ requires time $t_i\geq 0$. Besides, +over the set $J$ there is given a precedence relation +$R\subseteq J\times J$, where $(i,j)\in R$ means that job $i$ +immediately precedes job $j$, i.e. performing job $j$ cannot start +until job $i$ has been completely performed. The problem is to find +starting times $x_i$ for each job $i\in J$, which satisfy to the +precedence relation and minimize the total duration (makespan) of the +project. + +The following is an example of the critical path problem: + +\bigskip + +\begin{center} +\begin{tabular}{|c|l|c|c|} +\hline +Job&Desription&Time&Predecessors\\ +\hline +A&Excavate&3&---\\ +B&Lay foundation&4&A\\ +C&Rough plumbing&3&B\\ +D&Frame&10&B\\ +E&Finish exterior&8&D\\ +F&Install HVAC&4&D\\ +G&Rough electric&6&D\\ +H&Sheet rock&8&C, E, F, G\\ +I&Install cabinets&5&H\\ +J&Paint&5&H\\ +K&Final plumbing&4&I\\ +L&Final electric&2&J\\ +M&Install flooring&4&K, L\\ +\hline +\end{tabular} +\end{center} + +\bigskip + +Obviously, the project along with the precedence relation can be +represented as a directed graph $G=(J,R)$ called {\it project network}, +where each node $i\in J$ corresponds to a job, and arc +$(i\rightarrow j)\in R$ means that job $i$ immediately precedes job +$j$.\footnote{There exists another network representation of the +critical path problem, where jobs correspond to arcs while nodes +correspond to events introduced to express the precedence relation. +That representation, however, is much less convenient than the one, +where jobs are represented as nodes of the network.} The project network +for the example above is shown on Fig.~4. + +\hspace*{.5in} +\xymatrix +{&&&C|3\ar[rd]&&I|5\ar[r]&K|4\ar[rd]&\\ +A|3\ar[r]&B|4\ar[rru]\ar[rd]&&E|8\ar[r]&H|8\ar[ru]\ar[rd]&&&M|4\\ +&&D|10\ar[ru]\ar[r]\ar[rd]&F|4\ar[ru]&&J|5\ar[r]&L|2\ar[ru]&\\ +&&&G|6\ar[ruu]&&&&\\ +} + +\medskip + +\noindent\hfil +Fig.~4. An example of the project network. + +\newpage + +May note that the project network must be acyclic; otherwise, it would +be impossible to satisfy to the precedence relation for any job that +belongs to a cycle. + +The critical path problem can be naturally formulated as the following +LP problem: + +\medskip + +\noindent +\hspace{.5in}minimize +$$z\eqno(19)$$ +\hspace{.5in}subject to +$$x_i+t_i\leq z\ \ \ \hbox{for all}\ i\in J\ \ \ \ \eqno(20)$$ +$$x_i+t_i\leq x_j\ \ \ \hbox{for all}\ (i,j)\in R\eqno(21)$$ +$$x_i\geq 0\ \ \ \ \ \ \ \hbox{for all}\ i\in J\ \ \eqno(22)$$ + +The inequality constraints (21), which are active in the optimal +solution, define so called {\it critical path} having the following +property: the minimal project duration $z$ can be decreased only by +decreasing the times $t_j$ for jobs on the critical path, and delaying +any critical job delays the entire project. + +\subsection{glp\_cpp --- solve critical path problem} + +\synopsis + +\begin{verbatim} + double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +\end{verbatim} + +\description + +The routine \verb|glp_cpp| solves the critical path problem represented +in the form of the project network. + +The parameter \verb|G| is a pointer to the graph object, which +specifies the project network. This graph must be acyclic. Multiple +arcs are allowed being considered as single arcs. + +The parameter \verb|v_t| specifies an offset of the field of type +\verb|double| in the vertex data block, which contains time $t_i\geq 0$ +needed to perform corresponding job $j\in J$. If \verb|v_t| $<0$, it is +assumed that $t_i=1$ for all jobs. + +The parameter \verb|v_es| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +the {\it earliest start time} for corresponding job. If \verb|v_es| +$<0$, this time is not stored. + +The parameter \verb|v_ls| specifies an offset of the field of type +\verb|double| in the vertex data block, to which the routine stores +the {\it latest start time} for corresponding job. If \verb|v_ls| +$<0$, this time is not stored. + +The difference between the latest and earliest start times of some job +is called its {\it time reserve}. Delaying a job within its time +reserve does not affect the project duration, so if the time reserve is +zero, the corresponding job is critical. + +\para{Returns} + +The routine \verb|glp_cpp| returns the minimal project duration, i.e. +minimal time needed to perform all jobs in the project. + +\newpage + +\para{Example} + +The example program below solves the critical path problem shown on +Fig.~4 by using the routine \verb|glp_cpp| and writes the solution +found on the standard output. + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { double t, es, ls; } v_data; + +#define node(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + int i; + double t, es, ef, ls, lf, total; + G = glp_create_graph(sizeof(v_data), 0); + glp_add_vertices(G, 13); + node(G->v[1])->t = 3; /* A: Excavate */ + node(G->v[2])->t = 4; /* B: Lay foundation */ + node(G->v[3])->t = 3; /* C: Rough plumbing */ + node(G->v[4])->t = 10; /* D: Frame */ + node(G->v[5])->t = 8; /* E: Finish exterior */ + node(G->v[6])->t = 4; /* F: Install HVAC */ + node(G->v[7])->t = 6; /* G: Rough elecrtic */ + node(G->v[8])->t = 8; /* H: Sheet rock */ + node(G->v[9])->t = 5; /* I: Install cabinets */ + node(G->v[10])->t = 5; /* J: Paint */ + node(G->v[11])->t = 4; /* K: Final plumbing */ + node(G->v[12])->t = 2; /* L: Final electric */ + node(G->v[13])->t = 4; /* M: Install flooring */ + glp_add_arc(G, 1, 2); /* A precedes B */ + glp_add_arc(G, 2, 3); /* B precedes C */ + glp_add_arc(G, 2, 4); /* B precedes D */ + glp_add_arc(G, 4, 5); /* D precedes E */ + glp_add_arc(G, 4, 6); /* D precedes F */ + glp_add_arc(G, 4, 7); /* D precedes G */ + glp_add_arc(G, 3, 8); /* C precedes H */ + glp_add_arc(G, 5, 8); /* E precedes H */ + glp_add_arc(G, 6, 8); /* F precedes H */ + glp_add_arc(G, 7, 8); /* G precedes H */ + glp_add_arc(G, 8, 9); /* H precedes I */ + glp_add_arc(G, 8, 10); /* H precedes J */ + glp_add_arc(G, 9, 11); /* I precedes K */ + glp_add_arc(G, 10, 12); /* J precedes L */ + glp_add_arc(G, 11, 13); /* K precedes M */ + glp_add_arc(G, 12, 13); /* L precedes M */ + total = glp_cpp(G, offsetof(v_data, t), offsetof(v_data, es), + offsetof(v_data, ls)); + printf("Minimal project duration is %.2f\n\n", total); + printf("Job Time ES EF LS LF\n"); + printf("--- ------ ------ ------ ------ ------\n"); + for (i = 1; i <= G->nv; i++) + { t = node(G->v[i])->t; + es = node(G->v[i])->es; + ef = es + node(G->v[i])->t; + ls = node(G->v[i])->ls; + lf = ls + node(G->v[i])->t; + printf("%3d %6.2f %s %6.2f %6.2f %6.2f %6.2f\n", + i, t, ls - es < 0.001 ? "*" : " ", es, ef, ls, lf); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +The output from the example program shown below includes job number, +the time needed to perform a job, earliest start time (\verb|ES|), +earliest finish time (\verb|EF|), latest start time (\verb|LS|), and +latest finish time (\verb|LF|) for each job in the project. Critical +jobs are marked by asterisks. + +\begin{footnotesize} +\begin{verbatim} +Minimal project duration is 46.00 + +Job Time ES EF LS LF +--- ------ ------ ------ ------ ------ + 1 3.00 * 0.00 3.00 0.00 3.00 + 2 4.00 * 3.00 7.00 3.00 7.00 + 3 3.00 7.00 10.00 22.00 25.00 + 4 10.00 * 7.00 17.00 7.00 17.00 + 5 8.00 * 17.00 25.00 17.00 25.00 + 6 4.00 17.00 21.00 21.00 25.00 + 7 6.00 17.00 23.00 19.00 25.00 + 8 8.00 * 25.00 33.00 25.00 33.00 + 9 5.00 * 33.00 38.00 33.00 38.00 + 10 5.00 33.00 38.00 35.00 40.00 + 11 4.00 * 38.00 42.00 38.00 42.00 + 12 2.00 38.00 40.00 40.00 42.00 + 13 4.00 * 42.00 46.00 42.00 46.00 +\end{verbatim} +\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\end{document} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Graph Optimization API Routines} + +\section{Maximum clique problem} + +\subsection{Background} + +The {\it maximum clique problem (MCP)} is a classic combinatorial +optimization problem. Given an undirected graph $G=(V,E)$, where $V$ is +a set of vertices, and $E$ is a set of edges, this problem is to find +the largest {\it clique} $C\subseteq G$, i.e. the largest induced +complete subgraph. A generalization of this problem is the {\it maximum +weight clique problem (MWCP)}, which is to find a clique $C\subseteq G$ +of the largest weight $\displaystyle\sum_{v\in C}w(v)\rightarrow\max$, +where $w(v)$ is a weight of vertex $v\in V$. + +An example of the maximum weight clique problem is shown on Fig.~5. + +\begin{figure} +\noindent\hfil +\begin{tabular}{c} +{\xymatrix %@C=16pt +{&&&{v_1}\ar@{-}[lllddd]\ar@{-}[llddddd]\ar@{-}[dddddd] +\ar@{-}[rrrddd]&&&\\ +&{v_2}\ar@{-}[rrrr]\ar@{-}[rrrrdddd]\ar@{-}[rrddddd]\ar@{-}[dddd]&&&& +{v_3}\ar@{-}[llllldd]\ar@{-}[lllldddd]\ar@{-}[dddd]&\\ +&&&&&&\\ +{v_4}\ar@{-}[rrrrrr]\ar@{-}[rrrddd]&&&&&&{v_5}\ar@{-}[lllddd] +\ar@{-}[ldd]\\ +&&&&&&\\ +&{v_6}\ar@{-}[rrrr]&&&&{v_7}&\\ +&&&{v_8}&&&\\ +}} +\end{tabular} +\begin{tabular}{r@{\ }c@{\ }l} +$w(v_1)$&=&3\\$w(v_2)$&=&4\\$w(v_3)$&=&8\\$w(v_4)$&=&1\\ +$w(v_5)$&=&5\\$w(v_6)$&=&2\\$w(v_7)$&=&1\\$w(v_8)$&=&3\\ +\end{tabular} + +\bigskip + +\begin{center} +Fig.~5. An example of the maximum weight clique problem. +\end{center} +\end{figure} + +\subsection{glp\_wclique\_exact --- find maximum weight clique with +exact algorithm} + +\synopsis + +\begin{verbatim} + int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); +\end{verbatim} + +\description + +The routine {\tt glp\_wclique\_exact} finds a maximum weight clique in +the specified undirected graph with the exact algorithm developed by +Patric \"Osterg{\aa}rd.\footnote{P.~R.~J.~\"Osterg{\aa}rd, A new +algorithm for the maximum-weight clique problem, Nordic J. of +Computing, Vol.~8, No.~4, 2001, pp.~424--36.} + +The parameter {\tt G} is the program object, which specifies +an undirected graph. Each arc $(x\rightarrow y)$ in {\tt G} is +considered as edge $(x,y)$, self-loops are ignored, and multiple edges, +if present, are replaced (internally) by simple edges. + +The parameter {\tt v\_wgt} specifies an offset of the field of type +{\tt double} in the vertex data block, which contains a weight of +corresponding vertex. Vertex weights must be integer-valued in the +range $[0,$ {\tt INT\_MAX}$]$. If {\tt v\_wgt} $<0$, it is assumed that +all vertices of the graph have the weight 1. + +\newpage + +The parameter {\tt sol} specifies a location, to which the routine +stores the weight of the clique found (the clique weight is the sum +of weights of all vertices included in the clique.) If {\tt sol} is +{\tt NULL}, the solution is not stored. + +The parameter {\tt v\_set} specifies an offset of the field of type +{\tt int} in the vertex data block, to which the routines stores a +vertex flag: 1 means that the corresponding vertex is included in the +clique found, and 0 otherwise. If {\tt v\_set} $<0$, vertex flags are +not stored. + +\returns + +\begin{retlist} +0 & Optimal solution found.\\ + +\verb|GLP_EDATA| & Unable to start the search, because some vertex +weights are either not integer-valued or out of range. This code is +also returned if the sum of weights of all vertices exceeds +{\tt INT\_MAX}. \\ +\end{retlist} + +\para{Notes} + +1. The routine {\it glp\_wclique\_exact} finds exact solution. Since +both MCP and MWCP problems are NP-complete, the algorithm may require +exponential time in worst cases. + +2. Internally the specified graph is converted to an adjacency matrix +in {\it dense} format. This requires about $|V|^2/16$ bytes of memory, +where $|V|$ is the number of vertices in the graph. + +\para{Example} + +The example program shown below reads a MWCP instance in DIMACS +clique/coloring format from file `\verb|sample.clq|', finds the clique +of largest weight, and writes the solution found on the standard +output. + +\newpage + +\begin{footnotesize} +\begin{verbatim} +#include +#include +#include +#include + +typedef struct { double wgt; int set; } v_data; + +#define vertex(v) ((v_data *)((v)->data)) + +int main(void) +{ glp_graph *G; + glp_vertex *v; + int i, ret; + double sol; + G = glp_create_graph(sizeof(v_data), 0); + glp_read_ccdata(G, offsetof(v_data, wgt), "sample.clq"); + ret = glp_wclique_exact(G, offsetof(v_data, wgt), &sol, + offsetof(v_data, set)); + printf("ret = %d; sol = %g\n", ret, sol); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + printf("vertex %d: weight = %g, flag = %d\n", + i, vertex(v)->wgt, vertex(v)->set); + } + glp_delete_graph(G); + return 0; +} +\end{verbatim} +\end{footnotesize} + +For the example shown on Fig.~5 the data file may look like follows: + +\begin{footnotesize} +\begin{verbatim} +c sample.clq +c +c This is an example of the maximum weight clique +c problem in DIMACS clique/coloring format. +c +p edge 8 16 +n 1 3 +n 2 4 +n 3 8 +n 5 5 +n 6 2 +n 8 3 +e 1 4 +e 1 5 +e 1 6 +e 1 8 +e 2 3 +e 2 6 +e 2 7 +e 2 8 +e 3 4 +e 3 6 +e 3 7 +e 4 5 +e 4 8 +e 5 7 +e 5 8 +e 6 7 +c +c eof +\end{verbatim} +\end{footnotesize} + +The corresponding output from the example program is the following: + +\begin{footnotesize} +\begin{verbatim} +Reading graph from `sample.clq'... +Graph has 8 vertices and 16 edges +28 lines were read +ret = 0; sol = 15 +vertex 1: weight = 3, flag = 0 +vertex 2: weight = 4, flag = 1 +vertex 3: weight = 8, flag = 1 +vertex 4: weight = 1, flag = 0 +vertex 5: weight = 5, flag = 0 +vertex 6: weight = 2, flag = 1 +vertex 7: weight = 1, flag = 1 +vertex 8: weight = 3, flag = 0 +\end{verbatim} +\end{footnotesize} + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/miplib2.txt b/WebAPP/SOLVERs/GLPK/glpk/doc/miplib2.txt new file mode 100644 index 000000000..762c83f89 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/miplib2.txt @@ -0,0 +1,135 @@ +Solver: GLPSOL 4.40 (options used: --pcost) +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: MIPLIB 2.0 + +Problem Optimal Solution Cuts Used Nodes Iters Time,s Mem,MB +-------- ---------------- --------- -------- ------ ------ ------ +air01 +6.796000000e+03 3 41 < 1 1.2 +air02 +7.810000000e+03 43 201 6 13.8 +air03 +3.401600000e+05 33 414 12 21.0 +air04 +5.613700000e+04 1901 109800 396 32.4 +air05 +2.637400000e+04 6445 201649 452 45.0 +air06 +4.964900000e+04 11 6868 31 18.1 +bell3a +8.784303160e+05 --gomory 7965 42363 17 6.1 +bell3b +1.178616062e+07 --gomory 6031 30467 19 3.2 +bell4 +1.854148420e+07 --gomory 7203 25019 16 2.9 +bell5 +8.966406492e+06 --gomory 5605 18555 8 1.5 +bm23 +3.400000000e+01 373 878 < 1 0.2 +cracpb1 +2.219900000e+04 47 5258 2 1.3 +dcmulti +1.881820000e+05 743 3366 2 1.1 +diamond infeasible 3 4 < 1 0.1 +dsbmip -3.051981750e+02 --mir 217 46088 24 4.5 +egout +5.681007000e+02 91 137 < 1 0.3 +enigma +0.000000000e+00 16419 55071 6 3.2 +fixnet3 +5.197300000e+04 81 380 < 1 1.4 +fixnet4 +8.936000000e+03 211 1095 1 1.4 +fixnet6 +3.983000000e+03 1031 3136 2 1.7 +flugpl +1.201500000e+06 397 231 < 1 0.1 +gen +1.123133627e+05 195 3991 1 1.7 +khb05250 +1.069402260e+08 2163 14498 5 2.8 +l152lav +4.722000000e+03 7419 95299 68 12.0 +lp4l +2.967000000e+03 173 1331 2 1.7 +lseu +1.120000000e+03 10821 31954 5 2.5 +misc01 +5.635000000e+02 769 4593 1 0.5 +misc02 +1.690000000e+03 29 282 < 1 0.2 +misc03 +3.360000000e+03 957 6742 2 1.1 +misc04 +2.666699247e+03 17 2052 1 7.0 +misc05 +2.984500000e+03 293 2520 1 1.1 +misc06 +1.285086074e+04 57 941 < 1 2.7 +misc07 +2.810000000e+03 --mir 66075 579129 424 33.4 +mod008 +3.070000000e+02 8185 24245 8 2.3 +mod010 +6.548000000e+03 315 6283 7 5.3 +mod011 +mod013 +2.809500000e+02 545 1155 < 1 0.3 +modglob +2.074050809e+07 --mir 5197 31985 20 2.8 +noswot +p0033 +3.089000000e+03 305 955 < 1 0.2 +p0040 +6.202700000e+04 17 66 < 1 0.1 +p0201 +7.615000000e+03 521 3660 1 0.9 +p0282 +2.584110000e+05 623 1204 1 0.8 +p0291 +5.223749000e+03 71 154 < 1 0.7 +p0548 +8.691000000e+03 7617 23556 9 2.9 +p2756 +3.124000000e+03 --mir 3911 15157 57 10.9 +p6000 -2.451377000e+06 19209 40906 570 15.8 +pipex +7.882630000e+02 1569 2469 < 1 0.4 +qiu -1.328731369e+02 80473 1918742 1174 69.2 +rentacar +3.035676098e+07 43 1649 3 12.1 +rgn +8.219999924e+01 3325 18700 2 1.2 +sample2 +3.750000000e+02 163 347 < 1 0.2 +sentoy -7.772000000e+03 335 723 < 1 0.4 +set1al +1.586975000e+04 --mir 17 532 < 1 1.5 +set1ch +set1cl +6.484250000e+03 --mir 1 502 < 1 1.1 +stein15 +9.000000000e+00 87 375 < 1 0.2 +stein27 +1.800000000e+01 3255 15327 2 1.0 +stein45 +3.000000000e+01 52301 389140 139 19.2 +stein9 +5.000000000e+00 17 45 < 1 0.1 +vpm1 +2.000000000e+01 --mir 9 836 < 1 0.9 + +PROBLEM CHARACTERISTICS + +Problem Rows Cols ( Int 0/1) Nonz Best Solution +-------- ------ ---------------------- ------ -------------------------- +air01 24 771 ( all all) 4986 6796 (opt) +air02 51 6774 ( all all) 68329 7810 (opt) +air03 125 10757 ( all all) 101785 340160 (opt) +air04 824 8904 ( all all) 81869 56138 (opt) +air05 427 7195 ( all all) 59316 26402 (not opt) +air06 826 8627 ( all all) 79433 49649 (opt) +bell3a 124 133 ( 71 39) 441 878430.32 (opt) +bell3b 124 133 ( 71 39) 441 11786160.62 (opt) +bell4 106 117 ( 64 34) 385 18541484.20 (opt) +bell5 92 104 ( 58 30) 340 8966406.49 (opt) +bm23 21 27 ( all all) 505 34 (opt) +cracpb1 144 572 ( all all) 4730 22199 (opt) +dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) +diamond 5 2 ( all all) 9 integer infeasible +dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) +egout 99 141 ( 55 all) 392 568.101 (opt) +enigma 22 100 ( all all) 298 0.0 (opt) +fixnet3 479 878 ( 378 all) 2631 51973 (opt) +fixnet4 479 878 ( 378 all) 2621 8936 (opt) +fixnet6 479 878 ( 378 all) 2550 3983 (opt) +flugpl 19 18 ( 11 none) 64 1201500 (opt) +gen 781 870 ( 150 144) 3174 112313 (opt) +khb05250 102 1350 ( 24 all) 3973 106940226 (opt) +l152lav 98 1989 ( all all) 11911 4750 (not opt) +lp4l 86 1086 ( all all) 5763 2967 (opt) +lseu 29 89 ( all all) 394 1120 (opt) +misc01 55 83 ( 82 all) 746 563.5 (opt) +misc02 40 59 ( 58 all) 414 1690 (opt) +misc03 97 160 ( 159 all) 2054 3360 (opt) +misc04 1726 4897 ( 30 all) 17253 2666.699 (opt) +misc05 301 136 ( 74 all) 2946 2984.5 (opt) +misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) +misc07 213 260 ( 259 all) 8620 2810 (not opt) +mod008 7 319 ( all all) 1562 307 (opt) +mod010 147 2655 ( all all) 13858 6548 (opt) +mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) +mod013 63 96 ( 48 all) 288 280.95 (opt) +modglob 292 422 ( 98 all) 1390 20740508 (opt) +noswot 183 128 ( 100 75) 760 -43 (opt) +p0033 17 33 ( all all) 131 3089 (opt) +p0040 24 40 ( all all) 150 62027 (opt) +p0201 134 201 ( all all) 2124 7615 (opt) +p0282 242 282 ( all all) 2248 258411 (opt) +p0291 253 291 ( all all) 349 5223.7490 (opt) +p0548 177 548 ( all all) 2127 8691 (opt) +p2756 756 2756 ( all all) 11103 3124 (opt) +p6000 2177 6000 ( all all) 54238 -2451377 (opt) +pipex 26 48 ( all all) 240 788.263 (opt) +qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) +rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) +rgn 25 180 ( 100 all) 540 82.1999 (opt) +sample2 46 67 ( 21 all) 179 375 (opt) +sentoy 31 60 ( all all) 1860 -7772 (opt) +set1al 493 712 ( 240 all) 1884 15869.7 (opt) +set1ch 493 712 ( 240 all) 1884 54537.7 (opt) +set1cl 493 712 ( 240 all) 1884 6484.25 (opt) +stein15 37 15 ( all all) 135 9 (opt) +stein27 119 27 ( all all) 405 18 (opt) +stein45 332 45 ( all all) 1079 30 (opt) +stein9 14 9 ( all all) 54 5 (opt) +vpm1 235 378 ( 168 all) 917 20 (opt) diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/miplib3.txt b/WebAPP/SOLVERs/GLPK/glpk/doc/miplib3.txt new file mode 100644 index 000000000..ad7884bb2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/miplib3.txt @@ -0,0 +1,143 @@ +Solver: GLPSOL 4.40 +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: MIPLIB 3.0 + +Problem Optimal Solution Options Used Nodes Iters Time,s Mem,MB +-------- ---------------- ---------------- -------- ------ ------ ------ +10teams +9.240000000e+02 --pcost --gomory 6013 349276 207 12.7 +air03 +3.401600000e+05 --pcost 33 414 12 21.0 +air04 +5.613700000e+04 --pcost 1901 109800 396 32.4 +air05 +2.637400000e+04 --pcost 6445 201649 452 45.0 +arki001 +bell3a +8.784303160e+05 --pcost --gomory 7965 42363 17 6.1 +bell5 +8.966406492e+06 --pcost --gomory 5605 18555 8 1.5 +blend2 +7.598985000e+00 --pcost 7185 24256 7 2.1 +cap6000 -2.451377000e+06 --pcost 19209 40906 569 15.8 +dano3mip +danoint +dcmulti +1.881820000e+05 --pcost 743 3366 2 1.1 +dsbmip -3.051981750e+02 --pcost --mir 217 46088 24 4.5 +egout +5.681007000e+02 --pcost 91 137 < 1 0.3 +enigma +0.000000000e+00 --pcost 16419 55071 6 3.2 +fast0507 +fiber +4.059351800e+05 --pcost --mir 407 3108 4 2.4 +fixnet6 +3.983000000e+03 --pcost 1031 3136 2 1.7 +flugpl +1.201500000e+06 --pcost 397 231 < 1 0.1 +gen +1.123133627e+05 --pcost 195 3991 1 1.7 +gesa2 +2.577985637e+07 --pcost --mir 59 2723 4 4.1 +gesa2_o +2.577985637e+07 --pcost --mir 69 2588 5 3.7 +gesa3 +2.799104265e+07 --pcost --mir 93 2774 5 3.7 +gesa3_o +2.799104265e+07 --pcost --mir 117 3271 6 3.6 +gt2 +2.116600000e+04 --pcost 5613 26115 2 1.2 +harp2 +khb05250 +1.069402260e+08 --pcost 2163 14498 5 2.8 +l152lav +4.722000000e+03 --pcost 7419 95299 68 12.0 +lseu +1.120000000e+03 --pcost 10821 31954 5 2.5 +marksh1 +marksh2 +mas74 +mas76 +misc03 +3.360000000e+03 --pcost 957 6742 2 1.1 +misc06 +1.285086074e+04 --pcost 57 941 < 1 2.7 +misc07 +2.810000000e+03 --pcost --mir 66075 579129 424 33.4 +mitre +mkc +mod008 +3.070000000e+02 --pcost 8185 24245 8 2.3 +mod010 +6.548000000e+03 --pcost 315 6283 7 5.3 +mod011 +modglob +2.074050809e+07 --pcost --mir 5197 31985 20 2.8 +noswot +nw04 +1.686200000e+04 (none) 361 5544 345 138.3 +p0033 +3.089000000e+03 --pcost 305 955 < 1 0.2 +p0201 +7.615000000e+03 --pcost 521 3660 1 0.9 +p0282 +2.584110000e+05 --pcost 623 1204 1 0.8 +p0548 +8.691000000e+03 --pcost 7617 23556 9 2.9 +p2756 +3.124000000e+03 --pcost --mir 3911 15157 57 10.9 +pk1 +pp08a +7.350000000e+03 --pcost --mir 663 9196 4 1.3 +pp08acut +7.350000000e+03 --pcost --mir 17233 260160 154 21.1 +qiu -1.328731369e+02 --pcost 80473 1918742 1174 69.2 +qnet1 +1.602969268e+04 --pcost --mir 183 20352 16 3.6 +qnet1_o +1.602969268e+04 --pcost --mir 75 7645 9 3.3 +rentacar +3.035676098e+07 --pcost 43 1649 3 12.1 +rgn +8.219999924e+01 --pcost 3325 18700 2 1.2 +rout +set1ch +seymour +stein27 +1.800000000e+01 --pcost 3255 15327 2 1.0 +stein45 +3.000000000e+01 --pcost 52301 389140 139 19.2 +swath +vpm1 +2.000000000e+01 --pcost --mir 9 836 < 1 0.9 +vpm2 +1.375000000e+01 --pcost --mir 11729 164856 91 9.2 + +PROBLEM CHARACTERISTICS + +Problem Rows Cols ( Int 0/1) Nonz Best Solution +-------- ------ ---------------------- ------ -------------------------- +10teams 230 2025 ( 1800 all) 12150 924 (opt) +air03 125 10757 ( all all) 101785 340160 (opt) +air04 824 8904 ( all all) 81869 56138 (opt) +air05 427 7195 ( all all) 59316 26402 (not opt) +arki001 1048 1388 ( 538 415) 20439 7580813.0459 (not opt) +bell3a 124 133 ( 71 39) 441 878430.32 (opt) +bell5 92 104 ( 58 30) 340 8966406.49 (opt) +blend2 274 353 ( 264 231) 1409 7.598985 (opt) +cap6000 2176 6000 ( all all) 48249 -2451377 (opt) +dano3mip 3202 13873 ( 552 all) 79655 728.1111 (not opt) +danoint 664 521 ( 56 all) 3232 65.67 (opt) +dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) +dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) +egout 99 141 ( 55 all) 392 568.101 (opt) +enigma 22 100 ( all all) 298 0.0 (opt) +fast0507 507 63009 ( all all) 409439 174 (opt) +fiber 363 1298 ( 1254 all) 2944 405935.18000 (opt) +fixnet6 479 878 ( 378 all) 2550 3983 (opt) +flugpl 19 18 ( 11 none) 64 1201500 (opt) +gen 781 870 ( 150 144) 3174 112313 (opt) +gesa2 1392 1224 ( 408 240) 5064 25779856.372 (opt) +gesa2_o 1248 1224 ( 720 384) 3672 25779856.372 (opt) +gesa3 1368 1152 ( 384 216) 4944 27991042.648 (opt) +gesa3_o 1224 1152 ( 672 336) 3624 27991042.648 (opt) +gt2 29 188 ( all 24) 376 21166.000 (opt) +harp2 112 2993 ( all all) 5840 -73899798.00 (opt) +khb05250 102 1350 ( 24 all) 3973 106940226 (opt) +l152lav 98 1989 ( all all) 11911 4750 (not opt) +lseu 29 89 ( all all) 394 1120 (opt) +marksh1 7 62 ( 50 all) 324 +marksh2 8 74 ( 60 all) 448 +mas74 13 151 ( 150 all) 1705 11801.1857 (opt) +mas76 12 151 ( 150 all) 1639 40005.0541 (opt) +misc03 97 160 ( 159 all) 2054 3360 (opt) +misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) +misc07 213 260 ( 259 all) 8620 2810 (not opt) +mitre 2054 10724 ( all all) 39704 115155 (opt) +mkc 3412 5325 ( 5323 all) 20621 +mod008 7 319 ( all all) 1562 307 (opt) +mod010 147 2655 ( all all) 13858 6548 (opt) +mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) +modglob 292 422 ( 98 all) 1390 20740508 (opt) +noswot 183 128 ( 100 75) 760 -43 (opt) +nw04 36 87482 ( all all) 636666 16862 (opt) +p0033 17 33 ( all all) 131 3089 (opt) +p0201 134 201 ( all all) 2124 7615 (opt) +p0282 242 282 ( all all) 2248 258411 (opt) +p0548 177 548 ( all all) 2127 8691 (opt) +p2756 756 2756 ( all all) 11103 3124 (opt) +pk1 45 86 ( 55 all) 915 11 (opt) +pp08a 136 240 ( 64 all) 480 7350 (opt) +pp08acut 246 240 ( 64 all) 839 7350 (opt) +qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) +qnet1 503 1541 ( 1417 1288) 4622 16029.692681 (opt) +qnet1_o 456 1541 ( 1417 1288) 4214 16029.692681 (opt) +rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) +rgn 25 180 ( 100 all) 540 82.1999 (opt) +rout 291 556 ( 315 300) 2431 1077.56 (opt) +set1ch 493 712 ( 240 all) 1884 54537.7 (opt) +seymour 4944 1372 ( all all) 33549 423 (not opt) +stein27 119 27 ( all all) 405 18 (opt) +stein45 332 45 ( all all) 1079 30 (opt) +swath 885 6805 ( 6724 all) 34966 +vpm1 235 378 ( 168 all) 917 20 (opt) +vpm2 234 378 ( 168 all) 917 13.75 (opt) diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/netlib.txt b/WebAPP/SOLVERs/GLPK/glpk/doc/netlib.txt new file mode 100644 index 000000000..a5c01ca80 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/netlib.txt @@ -0,0 +1,103 @@ +Solver: GLPSOL 4.40 (default options used) +Computer: Intel Pentium 4, 3.0 GHz +Platform: Cygwin 1.5.25 +Compiler: GCC 3.4.4 (options used: -O3) +Test set: Netlib LP collection + +Problem Rows Cols Nonz Optimum Iters Time,s Mem,MB +-------- ----- ----- ------ ---------------- ------ ------ ------ +25fv47 822 1571 11127 +5.501845888e+03 1651 < 1 2.1 +80bau3b 2263 9799 29063 +9.872241924e+05 5358 3 6.4 +adlittle 57 97 465 +2.254949632e+05 71 < 1 0.1 +afiro 28 32 88 -4.647531429e+02 10 < 1 0.1 +agg 489 163 2541 -3.599176729e+07 100 < 1 0.5 +agg2 517 302 4515 -2.023925236e+07 178 < 1 0.8 +agg3 517 302 4531 +1.031211594e+07 182 < 1 0.8 +bandm 306 472 2659 -1.586280185e+02 252 < 1 0.6 +beaconfd 174 262 3476 +3.359248581e+04 61 < 1 0.4 +blend 75 83 521 -3.081214985e+01 41 < 1 0.1 +bnl1 644 1175 6129 +1.977629562e+03 581 < 1 1.4 +bnl2 2325 3489 16124 +1.811236540e+03 1730 1 3.7 +boeing1 351 384 3865 -3.352135675e+02 419 < 1 0.7 +boeing2 167 143 1339 -3.150187280e+02 161 < 1 0.3 +bore3d 234 315 1525 +1.373080394e+03 38 < 1 0.3 +brandy 221 249 2150 +1.518509896e+03 191 < 1 0.5 +capri 272 353 1786 +2.690012914e+03 203 < 1 0.4 +cycle 1904 2857 21322 -5.226393025e+00 953 < 1 3.5 +czprob 930 3523 14173 +2.185196699e+06 754 < 1 2.6 +d2q06c 2172 5167 35674 +1.227842108e+05 5368 7 6.2 +d6cube 416 6184 43888 +3.154916667e+02 6596 6 6.0 +degen2 445 534 4449 -1.435178000e+03 506 < 1 1.0 +degen3 1504 1818 26230 -9.872940000e+02 2205 2 4.1 +dfl001 6072 12230 41873 +1.126639605e+07 39863 117 11.0 +e226 224 282 2767 -2.586492907e+01 206 < 1 0.5 +etamacro 401 688 2489 -7.557152333e+02 444 < 1 0.7 +fffff800 525 854 6235 +5.556795648e+05 167 < 1 1.0 +finnis 498 614 2714 +1.727910656e+05 338 < 1 0.6 +fit1d 25 1026 14430 -9.146378092e+03 488 < 1 1.7 +fit1p 628 1677 10894 +9.146378092e+03 1379 < 1 1.9 +fit2d 26 10500 138018 -6.846429329e+04 5751 16 15.8 +fit2p 3001 13525 60784 +6.846429329e+04 11960 17 11.3 +forplan 162 421 4916 -6.642189613e+02 170 < 1 0.7 +ganges 1310 1681 7021 -1.095857361e+05 724 < 1 1.9 +gfrd-pnc 617 1092 3467 +6.902236000e+06 416 < 1 1.0 +greenbea 2393 5405 31499 -7.255524813e+07 3012 3 5.8 +greenbeb 2393 5405 31499 -4.302260261e+06 2153 2 5.8 +grow15 301 645 5665 -1.068709413e+08 358 < 1 1.1 +grow22 441 946 8318 -1.608343365e+08 606 < 1 1.6 +grow7 141 301 2633 -4.778781181e+07 159 < 1 0.5 +israel 175 142 2358 -8.966448219e+05 123 < 1 0.4 +kb2 44 41 291 -1.749900130e+03 38 < 1 0.1 +lotfi 154 308 1086 -2.526470606e+01 104 < 1 0.3 +maros 847 1443 10006 -5.806374370e+04 703 < 1 1.8 +maros-r7 3137 9408 151120 +1.497185166e+06 2340 5 16.7 +modszk1 688 1620 4158 +3.206197291e+02 705 < 1 1.4 +nesm 663 2923 13988 +1.407603649e+07 2240 1 2.4 +perold 626 1376 6026 -9.380755278e+03 1103 < 1 1.5 +pilot 1442 3652 43220 -5.574831533e+02 5726 11 7.8 +pilot-ja 941 1988 14706 -6.113136466e+03 1697 1 2.5 +pilot-we 723 2789 9218 -2.720107533e+06 1382 1 2.3 +pilot4 411 1000 5145 -2.581139259e+03 532 < 1 1.3 +pilot87 2031 4883 73804 +3.017103744e+02 7573 28 12.2 +pilotnov 976 2172 13129 -4.497276188e+03 988 1 2.5 +recipe 92 180 752 -2.666160000e+02 17 < 1 0.2 +sc105 106 103 281 -5.220206121e+01 51 < 1 0.2 +sc205 206 203 552 -5.220206121e+01 124 < 1 0.3 +sc50a 51 48 131 -6.457507706e+01 25 < 1 0.1 +sc50b 51 48 119 -7.000000000e+01 30 < 1 0.1 +scagr25 472 500 2029 -1.475343306e+07 352 < 1 0.7 +scagr7 130 140 553 -2.331389824e+06 94 < 1 0.2 +scfxm1 331 457 2612 +1.841675903e+04 281 < 1 0.6 +scfxm2 661 914 5229 +3.666026156e+04 587 < 1 1.1 +scfxm3 991 1371 7846 +5.490125455e+04 881 < 1 1.7 +scorpion 389 358 1708 +1.878124823e+03 146 < 1 0.4 +scrs8 491 1169 4029 +9.042969538e+02 545 < 1 1.1 +scsd1 78 760 3148 +8.666666674e+00 91 < 1 0.6 +scsd6 148 1350 5666 +5.050000008e+01 182 < 1 1.0 +scsd8 398 2750 11334 +9.049999999e+02 397 < 1 2.1 +sctap1 301 480 2052 +1.412250000e+03 196 < 1 0.5 +sctap2 1091 1880 8124 +1.724807143e+03 425 < 1 1.7 +sctap3 1481 2480 10734 +1.424000000e+03 729 < 1 2.4 +seba 516 1028 4874 +1.571160000e+04 883 < 1 1.0 +share1b 118 225 1182 -7.658931858e+04 167 < 1 0.3 +share2b 97 79 730 -4.157322407e+02 87 < 1 0.2 +shell 537 1775 4900 +1.208825346e+09 467 < 1 1.2 +ship04l 403 2118 8450 +1.793324538e+06 373 < 1 1.5 +ship04s 403 1458 5810 +1.798714700e+06 262 < 1 1.0 +ship08l 779 4283 17085 +1.909055211e+06 516 < 1 2.9 +ship08s 779 2387 9501 +1.920098211e+06 274 < 1 1.7 +ship12l 1152 5427 21597 +1.470187919e+06 686 < 1 3.7 +ship12s 1152 2763 10941 +1.489236134e+06 383 < 1 2.0 +sierra 1228 2036 9252 +1.539436218e+07 857 < 1 2.1 +stair 357 467 3857 -2.512669512e+02 399 < 1 1.0 +standata 360 1075 3038 +1.257699500e+03 140 < 1 0.7 +standgub 362 1184 3147 +1.257699500e+03 140 < 1 0.8 +standmps 468 1075 3686 +1.406017500e+03 299 < 1 0.9 +stocfor1 118 111 474 -4.113197622e+04 24 < 1 0.2 +stocfor2 2158 2031 9492 -3.902440854e+04 499 < 1 2.6 +stocfor3 16676 15695 74004 -3.997678394e+04 4456 11 19.7 +truss 1001 8806 36642 +4.588158472e+05 4744 4 6.5 +tuff 334 587 4523 +2.921477651e-01 61 < 1 0.8 +vtp-base 199 203 914 +1.298314625e+05 69 < 1 0.2 +wood1p 245 2594 70216 +1.442902412e+00 326 < 1 7.1 +woodw 1099 8405 37478 +1.304476333e+00 1093 < 1 6.0 diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/notes/gomory.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/gomory.pdf new file mode 100644 index 000000000..b68062704 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/gomory.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/notes/keller.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/keller.pdf new file mode 100644 index 000000000..3aa69388b Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/keller.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/notes/scf.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/scf.pdf new file mode 100644 index 000000000..da324f27f Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/scf.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex1.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex1.pdf new file mode 100644 index 000000000..af8306dae Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex1.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex2.pdf b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex2.pdf new file mode 100644 index 000000000..313ca69a8 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/doc/notes/simplex2.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/doc/npp.txt b/WebAPP/SOLVERs/GLPK/glpk/doc/npp.txt new file mode 100644 index 000000000..e5dc14485 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/doc/npp.txt @@ -0,0 +1,283 @@ +@.@ LP/MIP PREPROCESSING ROUTINES +================================= + +@.@.1 Introduction + +GLPK has a set of routines that constitute so called the LP/MIP +preprocessor. Its main purpose is to improve a given formulation of the +LP or MIP problem instance provided by the user. + +As a rule the LP/MIP preprocessor is used internally (if enabled) in +the LP or MIP solver. However, for various reasons the user may need +to call the preprocessing routines directly in his/her application +program, in which case he/she may use API routines described in this +section. + +The preprocessing of an LP/MIP problem instance and recovering its +solution include several steps, which are performed in the following +order. + +1. Allocating the workspace. The preprocessor allocates the workspace, + an internal data structure used on all subsequent steps. + +2. Loading the original problem instance. The preprocessor copies all + the problem components from the original problem object (glp_prob) + specified by the user into the workspace. On this step the user also + should specify the solution type: basic solution (assumes the + primal or dual simplex solver), interior-point solution (assumes the + interior-point solver), or MIP solution (assumes the MIP solver). + This is needed, because some preprocessing transformations depend on + the solution type. + +3. Preprocessing. The user calls preprocessing routines that transform + the problem instance residing in the workspace. + +4. Building the resultant problem instance. The preprocessor converts + the problem instance from an internal workspace representation + to the standard problem object (glp_prob) and returns that object to + the user. + +5. Solving the resultant problem instance. The user calls an + appropriate solver routine to obtain a solution to the resultant + problem instance. + +6. Postprocessing. The user provides the solution to the resultant + problem instance found on the previous step, and the preprocessor + performs inverse transformations to recover the solution to the + original problem instance. Should note that only optimal or integer + feasible (for MIP) solutions can be recovered. + +7. Obtaining original solution. The preprocessor copies the solution + to the original problem instance recovered on the previous step from + the workspace to the original problem object (glp_prob). The effect + is the same as if the solution were computed by a solver. Note that + steps 6 and 7 can be performed multiple times (for example, to + recover intermediate integer feasible solutions during the integer + optimization). + +8. Freeing the workspace. The preprocessor frees all the memory + allocated to the workspace. + +EXAMPLE + +In this example the program reads the LP problem data from input file +murtagh.mps\footnote{This is an example model included in the GLPK +distribution.}, performs standard preprocessing, solves the resultant +LP with the primal simplex method, and then recovers the solution to +the original LP. + +/* nppsamp.c */ + +#include +#include +#include + +int main(void) +{ glp_prep *npp; + glp_prob *P, *Q; + int ret; + npp = glp_npp_alloc_wksp(); + P = glp_create_prob(); + ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "murtagh.mps"); + if (ret != 0) + { printf("Error on reading problem data\n"); + goto skip; + } + glp_set_obj_dir(P, GLP_MAX); + glp_npp_load_prob(npp, P, GLP_SOL, GLP_ON); + ret = glp_npp_preprocess1(npp, 0); + switch (ret) + { case 0: + break; + case GLP_ENOPFS: + printf("LP has no primal feasible solution\n"); + goto skip; + case GLP_ENODFS: + printf("LP has no dual feasible solution\n"); + goto skip; + default: + xassert(ret != ret); + } + Q = glp_create_prob(); + glp_npp_build_prob(npp, Q); + ret = glp_simplex(Q, NULL); + if (ret == 0 && glp_get_status(Q) == GLP_OPT) + { glp_npp_postprocess(npp, Q); + glp_npp_obtain_sol(npp, P); + } + else + printf("Unable to recover non-optimal solution\n"); + glp_delete_prob(Q); +skip: glp_npp_free_wksp(npp); + glp_delete_prob(P); + return 0; +} + +/* eof */ +------------------------------------------------------------------------ +@.@.2 glp_npp_alloc_wksp - allocate the preprocessor workspace + +SYNOPSIS + +glp_prep *glp_npp_alloc_wksp(void); + +DESCRIPTION + +The routine glp_npp_alloc_wksp allocates the preprocessor workspace. +(Note that multiple instances of the workspace may be allocated, if +necessary.) + +RETURNS + +The routine returns a pointer to the workspace, which should be used in +all subsequent operations. +------------------------------------------------------------------------ +@.@.3 glp_npp_load_prob - load original problem instance + +SYNOPSIS + +void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol, + int names); + +DESCRIPTION + +The routine glp_npp_load_prob loads the original problem instance from +the specified problem object P into the preprocessor workspace. (Note +that this operation can be performed only once.) + +The parameter sol specifies which solution is required: + +GLP_SOL - basic solution; + +GLP_IPT - interior-point solution; + +GLP_MIP - mixed integer solution. + +The parameter names is a flag. If it is GLP_ON, the symbolic names of +original rows and columns are also loaded into the workspace. Otherwise, +if the flag is GLP_OFF, the row and column names are not loaded. +------------------------------------------------------------------------ +@.@.4 glp_npp_preprocess1 - perform basic LP/MIP preprocessing + +SYNOPSIS + +int glp_npp_preprocess1(glp_prep *prep, int hard); + +DESCRIPTION + +The routine glp_npp_preprocess1 performs basic LP/MIP preprocessing +that currently includes: + +-- removing free rows; + +-- replacing double-sided constraint rows with almost identical bounds, + by equality constraint rows; + +-- removing fixed columns; + +-- replacing double-bounded columns with almost identical bounds by + fixed columns and removing those columns; + +-- removing empty rows; + +-- removing equality constraint row singletons and corresponding + columns; + +-- removing inequality constraint row singletons and corresponding + columns; + +-- performing general row analysis; + +-- removing redundant row bounds; + +-- removing forcing rows and corresponding columns; + +-- removing rows which become free due to redundant bounds; + +-- computing implied bounds for all columns and using them to + strengthen current column bounds (MIP only, optional, performed if + the flag hard is on); + +-- fixing and removing empty columns; + +-- removing column singletons, which are implied slack variables, and + corresponding rows; + +-- removing bounds of columns, which are implied free variables, and + replacing corresponding rows by equality constraints. + +If the flag hard is GLP_ON, the routine attempts to improve current +column bounds multiple times within the main processing loop, in which +case this feature may take a time. Otherwise, if the flag hard is +GLP_OFF, improving column bounds is performed only once at the end of +the main loop. (Note that this feature is used for MIP only.) + +RETURNS + +0 - the problem instance has been successfully preprocessed; + +GLP_ENOPFS - primal/integer infeasibility has been detected; + +GLP_ENODFS - dual infeasibility has been detected. +------------------------------------------------------------------------ +@.@.5 glp_npp_build_prob - build resultant problem instance + +SYNOPSIS + +void glp_npp_build_prob(glp_prep *prep, glp_prob *Q); + +DESCRIPTION + +The routine glp_npp_build_prob obtains all necessary information from +the preprocessor workspace to build the resultant (preprocessed) +problem instance, and stores it in the specified problem object Q. Note +that before building the current content of this problem object is +erased with the routine glp_erase_prob. +------------------------------------------------------------------------ +@.@.6 glp_npp_postprocess - postprocess solution to resultant problem + +SYNOPSIS + +void glp_npp_postprocess(glp_prep *prep, glp_prob *Q); + +DESCRIPTION + +The routine glp_npp_postprocess performs postprocessing of a solution +to the resultant (preprocessed) problem instance specified by the +problem object Q and recovers corrseponding solution to the original +problem instance. The recovered solution is stored in the preprocessor +workspace and can be obtained with the routine glp_npp_obtain_sol. + +It is assumed that the resultant problem instance Q has been solved +with an appropriate solver depending on the solution type previously +passed to the routine glp_npp_load_prob (the parameter sol). Note that +only optimal or integer feasible (for MIP) solution can be recovered, +so the calling program should use the routine glp_status to make sure +that this condition is met. +------------------------------------------------------------------------ +@.@.7 glp_npp_obtain_sol - obtain solution to original problem + +SYNOPSIS + +void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P); + +DESCRIPTION + +The routine glp_npp_obtain_sol copies the solution to the original +problem instance previously recovered by the routine +glp_npp_postorocess from the preprocessor workspace to the problem +object P. The effect is the same as if the solution were computed by an +appropriate solver. +------------------------------------------------------------------------ +@.@.8 glp_npp_free_wksp - free the preprocessor workspace + +SYNOPSIS + +void glp_npp_free_wksp(glp_prep *prep); + +DESCRIPTION + +The routine glp_npp_free_wksp frees all the memory allocated to the +preprocessor workspace. + +===EOF=== diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/INDEX b/WebAPP/SOLVERs/GLPK/glpk/examples/INDEX new file mode 100644 index 000000000..6b51bf2c8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/INDEX @@ -0,0 +1,69 @@ +alloy.mps Aluminium alloy blending +assign.mod Assignment problem +bpp.mod Bin packing problem +cal.mod Print an ASCII calendar of the given year +cf12a.mod Curve fitting problem +cf12b.mod Curve fitting problem +cflsq.mod Curve fitting problem by least squares +color.mod Graph coloring problem +cpp.mod Critical path problem +crypto.mod A crypto-arithmetic puzzle +dea.mod Data envelopment analysis (DEA) +diet.mod Stigler's nutrition model +dist.mod A product distribution model +egypt.mod A static model for fertilizer production +fctp.mod Fixed-charge transportation problem +food.mod Food manufacture model +food2.mod Food manufacture model +furnace.mps Electric-arc furnace steelmaking +gap.mod Generalized assignment problem +graceful.mod Graceful Tree Labeling Problem +graph.mod Graph visualization +hashi.mod A solver for the Japanese number-puzzle Hashiwokakero +huge.mod Arithmetic mean of a large number of integers +icecream.mps Ice cream blending +jssp.mod Job-shop scheduling problem +life_goe.mod Conway's Game of Life garden of eden checker +magic.mod Magic square +maxcut.mod Maximum cut problem +maxflow.mod Maximum flow problem +mfasp.mod Minimum feedback arc set problem +mfvsp.mod Minimum feedback vertex set problem +min01ks.mod Finding minimal equivalent 0-1 knapsack inequality +misp.mod Maximum independent set problem +money.mod A crypto-arithmetic puzzle +murtagh.mps Oil refinery model +mvcp.mod Minimum vertex cover problem +numbrix.mod Number placement puzzle +pbn/*.* Paint-by-numbers puzzle +pentomino.mod A geometric placement puzzle +plan.lp A simple LP problem (CPLEX LP format) +plan.mod A simple LP problem (MathProg format) +plan.mps A simple LP problem (MPS format) +planarity.mod Graph planarity testing +powpl25h.mod Power plant LP scheduler (25hrs for daylightsavings) +powplant.mod Power plant LP scheduler +prod.mod A multiperiod production model +qfit.mod Quadratic curve fitting solution +queens.mod A classic combinatorial optimization problem +sat.mod Satisfiability problem +shiftcov.mod Workforce shift coverage assignment problem +shikaku.mod A solver for the logic puzzle Shikaku +sorting.mod How to sort arrays in MathProg +spp.mod Shortest path problem +stigler.mod Original Stigler's 1939 diet problem +sudoku.mod Number placement puzzle +tas.mod Tail assignment problem +tiling.mod Rectifiable polyomino tilings generator +todd.mod A class of hard instances of 0-1 knapsack problems +toto.mod Covering code generator, especially for football pool + systems +train.mod A model of railroad passenger car allocation +transp.mod A transportation problem +trick.mod A transportation design problem +tsp.mod Traveling salesman problem +wolfra6d.lp Neumann CA grid emulator generator +wolfra6d.mod Neumann CA grid emulator generator +xyacfs.mod Extended yet another curve fitting solution +yacfs.mod Yet another curve fitting solution +zebra.mod Who owns the zebra? diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.am b/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.am new file mode 100644 index 000000000..7fff13603 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.am @@ -0,0 +1,15 @@ +## Process this file with automake to produce Makefile.in ## + +AM_CPPFLAGS = -I$(srcdir)/../src + +LDADD = ../src/libglpk.la + +bin_PROGRAMS = glpsol + +glpsol_SOURCES = glpsol.c + +check: glpsol$(EXEEXT) + ./glpsol$(EXEEXT) --version + ./glpsol$(EXEEXT) --mps $(srcdir)/murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.in b/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.in new file mode 100644 index 000000000..efbf3d773 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/Makefile.in @@ -0,0 +1,559 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = glpsol$(EXEEXT) +subdir = examples +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_glpsol_OBJECTS = glpsol.$(OBJEXT) +glpsol_OBJECTS = $(am_glpsol_OBJECTS) +glpsol_LDADD = $(LDADD) +glpsol_DEPENDENCIES = ../src/libglpk.la +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(glpsol_SOURCES) +DIST_SOURCES = $(glpsol_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUNDEFINED = @NOUNDEFINED@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(srcdir)/../src +LDADD = ../src/libglpk.la +glpsol_SOURCES = glpsol.c +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu examples/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +glpsol$(EXEEXT): $(glpsol_OBJECTS) $(glpsol_DEPENDENCIES) $(EXTRA_glpsol_DEPENDENCIES) + @rm -f glpsol$(EXEEXT) + $(LINK) $(glpsol_OBJECTS) $(glpsol_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glpsol.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS + + +check: glpsol$(EXEEXT) + ./glpsol$(EXEEXT) --version + ./glpsol$(EXEEXT) --mps $(srcdir)/murtagh.mps --max + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/alloy.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/alloy.mps new file mode 100644 index 000000000..9f774f165 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/alloy.mps @@ -0,0 +1,282 @@ +*NAME: ALLOY +*ROWS: 22 +*COLUMNS: 20 +*NONZERO: 203 +*OPT SOLN: 2149.247891 +*SOURCE: Linear Programming--Aluminium Alloy Blending +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Aluminium Alloy Blending +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME ALLOY +ROWS + N COST $ Cost $ + G ZN $ Zinc Minimum lbs + L ZX $ Zinc Maximum lbs + G CN $ Copper Minimum lbs + L CX $ Copper Maximum lbs + G MN $ Magnesium Minimum lbs + L MX $ Magnesium Maximum lbs + G CHN $ Chromium Minimum lbs + L CHX $ Chromium Maximum lbs + G BN $ Beryllium Minimum lbs + L BX $ Beryllium Maximum lbs + L IX $ Iron Maximum lbs + L SX $ Silicon Maximum lbs + L MGX $ Manganese Maximum lbs + L NX $ Nickel Maximum lbs + L TX $ Titanium Maximum lbs + L LX $ Lead Maximum lbs + L TNX $ Tin Maximum lbs + L BIX $ Bismuth Maximum lbs + L GX $ General Impurities lbs + L SCX $ Scrap 1 Limit lbs + G FL $ Furnance Load lbs +COLUMNS +* Pure Aluminium 1 + A1 COST .28 + IX .0004 + SX .0005 + FL 1.0 +* Pure Aluminium 2 + A2 COST .26 + IX .0006 + SX .0006 + FL 1.0 +* Pure Aluminium 3 + A3 COST .25 + IX .0011 + SX .0007 + FL 1.0 +* Pure Aluminium 4 + A4 COST .23 + IX .0026 + SX .0012 + FL 1.0 +* Pure Copper + C COST .31 + CN 1.00 + CX 1.00 + FL 1.0 +* Pure Magnesium + M COST .38 + MN 1.00 + MX 1.00 + FL 1.0 +* Beryllium/Aluminium Alloy + B/A COST 3.60 + BN 0.0600 + BX 0.0600 + FL 1.0 +* Pure Zinc + Z COST .22 + ZN .95 + ZX .95 + FL 1.0 +* Chromium Aluminium Alloy + C/A COST .27 + CHN .0300 + CHX .0300 + FL 1.0 +* Scrap 1 + SC1 COST .21 + ZN .0009 + ZX .0009 + CN .0444 + CX .0444 + MN .0042 + MX .0042 + CHN .0001 + CHX .0001 + IX .0024 + SX .0101 + MGX .0079 + NX .0001 + TX .0004 + LX .0001 + TNX .0001 + GX .0001 + SCX 1.00 + FL 1.0 +* Scrap 2 + SC2 COST .20 + ZN .0012 + ZX .0012 + CN .0026 + CX .0026 + MN .0060 + MX .0060 + CHN .0018 + CHX .0018 + IX .0026 + SX .0106 + MGX .0003 + NX .0002 + TX .0004 + LX .0001 + TNX .0001 + GX .0002 + FL 1.0 +* Scrap 3 + SC3 COST .21 + ZN .0568 + ZX .0568 + CN .0152 + CX .0152 + MN .0248 + MX .0248 + CHN .0020 + CHX .0020 + IX .0016 + SX .0013 + MGX .0005 + TX .0004 + LX .0003 + TNX .0003 + FL 1.0 +* Scrap 4 + SC4 COST .20 + ZN .0563 + ZX .0563 + CN .0149 + CX .0149 + MN .0238 + MX .0238 + CHN .0019 + CHX .0019 + IX .0019 + SX .0011 + MGX .0004 + TX .0004 + LX .0003 + TNX .0003 + FL 1.0 +* Scrap 5 + SC5 COST .21 + ZN .0460 + ZX .0460 + CN .0071 + CX .0071 + MN .0343 + MX .0343 + CHN .0013 + CHX .0013 + IX .0017 + SX .0013 + MGX .0018 + TX .0002 + LX .0002 + TNX .0002 + FL 1.0 +* Scrap 6 + SC6 COST .20 + ZN .0455 + ZX .0455 + CN .0071 + CX .0071 + MN .0343 + MX .0343 + IX .0016 + SX .0011 + MGX .0017 + TX .0002 + LX .0002 + TNX .0002 + FL 1.0 +* Scrap 7 + SC7 COST .21 + ZN .0009 + ZX .0009 + CN .0447 + CX .0447 + MN .0143 + MX .0143 + IX .0026 + SX .0013 + MGX .0052 + TX .0003 + LX .0001 + TNX .0001 + FL 1.0 +* Scrap 8 + SC8 COST .20 + ZN .0006 + ZX .0006 + CN .0623 + CX .0623 + IX .0017 + SX .0010 + MGX .0025 + TX .0005 + LX .0001 + TNX .0001 + GX .0025 + FL 1.0 +* Scrap 9 + SC9 COST .21 + ZN .0009 + ZX .0009 + CN .0034 + CX .0034 + MN .0093 + MX .0093 + CHN .0019 + CHX .0019 + IX .0030 + SX .0062 + MGX .0002 + TX .0003 + BIX .0005 + FL 1.0 +* Scrap 10 + SC10 COST .20 + ZN .0008 + ZX .0008 + CN .0003 + CX .0003 + MN .0249 + MX .0249 + CHN .0016 + CHX .0016 + IX .0015 + SX .0011 + MGX .0002 + FL 1.0 +* Scrap 11 + SC11 COST .21 + ZN .0675 + ZX .0675 + CN .0195 + CX .0195 + MN .0265 + MX .0265 + CHN .0020 + CHX .0020 + IX .0014 + SX .0008 + MGX .0002 + FL 1.0 +RHS + ZN 555. + ZX 590. + CN 140.0 + CX 190.0 + MN 245.0 + MX 275.0 + CHN 19.0 + CHX 22.0 + BN 2.0 + BX 4.0 + IX 15.0 + SX 10.0 + MGX 3.0 + NX 2.0 + TX 2.0 + LX 2.0 + TNX 2.0 + BIX 8.0 + GX 8.0 + SCX 900.0 + FL 10000. +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/assign.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/assign.mod new file mode 100644 index 000000000..6f700bb16 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/assign.mod @@ -0,0 +1,77 @@ +/* ASSIGN, Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The assignment problem is one of the fundamental combinatorial + optimization problems. + + In its most general form, the problem is as follows: + + There are a number of agents and a number of tasks. Any agent can be + assigned to perform any task, incurring some cost that may vary + depending on the agent-task assignment. It is required to perform all + tasks by assigning exactly one agent to each task in such a way that + the total cost of the assignment is minimized. + + (From Wikipedia, the free encyclopedia.) */ + +param m, integer, > 0; +/* number of agents */ + +param n, integer, > 0; +/* number of tasks */ + +set I := 1..m; +/* set of agents */ + +set J := 1..n; +/* set of tasks */ + +param c{i in I, j in J}, >= 0; +/* cost of allocating task j to agent i */ + +var x{i in I, j in J}, >= 0; +/* x[i,j] = 1 means task j is assigned to agent i + note that variables x[i,j] are binary, however, there is no need to + declare them so due to the totally unimodular constraint matrix */ + +s.t. phi{i in I}: sum{j in J} x[i,j] <= 1; +/* each agent can perform at most one task */ + +s.t. psi{j in J}: sum{i in I} x[i,j] = 1; +/* each task must be assigned exactly to one agent */ + +minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; +/* the objective is to find a cheapest assignment */ + +solve; + +printf "\n"; +printf "Agent Task Cost\n"; +printf{i in I} "%5d %5d %10g\n", i, sum{j in J} j * x[i,j], + sum{j in J} c[i,j] * x[i,j]; +printf "----------------------\n"; +printf " Total: %10g\n", sum{i in I, j in J} c[i,j] * x[i,j]; +printf "\n"; + +data; + +/* These data correspond to an example from [Christofides]. */ + +/* Optimal solution is 76 */ + +param m := 8; + +param n := 8; + +param c : 1 2 3 4 5 6 7 8 := + 1 13 21 20 12 8 26 22 11 + 2 12 36 25 41 40 11 4 8 + 3 35 32 13 36 26 21 13 37 + 4 34 54 7 8 12 22 11 40 + 5 21 6 45 18 24 34 12 48 + 6 42 19 39 15 14 16 28 46 + 7 16 34 38 3 34 40 22 24 + 8 26 20 5 17 45 31 37 43 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/bpp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/bpp.mod new file mode 100644 index 000000000..8dd354ed8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/bpp.mod @@ -0,0 +1,83 @@ +/* BPP, Bin Packing Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Given a set of items I = {1,...,m} with weight w[i] > 0, the Bin + Packing Problem (BPP) is to pack the items into bins of capacity c + in such a way that the number of bins used is minimal. */ + +param m, integer, > 0; +/* number of items */ + +set I := 1..m; +/* set of items */ + +param w{i in 1..m}, > 0; +/* w[i] is weight of item i */ + +param c, > 0; +/* bin capacity */ + +/* We need to estimate an upper bound of the number of bins sufficient + to contain all items. The number of items m can be used, however, it + is not a good idea. To obtain a more suitable estimation an easy + heuristic is used: we put items into a bin while it is possible, and + if the bin is full, we use another bin. The number of bins used in + this way gives us a more appropriate estimation. */ + +param z{i in I, j in 1..m} := +/* z[i,j] = 1 if item i is in bin j, otherwise z[i,j] = 0 */ + + if i = 1 and j = 1 then 1 + /* put item 1 into bin 1 */ + + else if exists{jj in 1..j-1} z[i,jj] then 0 + /* if item i is already in some bin, do not put it into bin j */ + + else if sum{ii in 1..i-1} w[ii] * z[ii,j] + w[i] > c then 0 + /* if item i does not fit into bin j, do not put it into bin j */ + + else 1; + /* otherwise put item i into bin j */ + +check{i in I}: sum{j in 1..m} z[i,j] = 1; +/* each item must be exactly in one bin */ + +check{j in 1..m}: sum{i in I} w[i] * z[i,j] <= c; +/* no bin must be overflowed */ + +param n := sum{j in 1..m} if exists{i in I} z[i,j] then 1; +/* determine the number of bins used by the heuristic; obviously it is + an upper bound of the optimal solution */ + +display n; + +set J := 1..n; +/* set of bins */ + +var x{i in I, j in J}, binary; +/* x[i,j] = 1 means item i is in bin j */ + +var used{j in J}, binary; +/* used[j] = 1 means bin j contains at least one item */ + +s.t. one{i in I}: sum{j in J} x[i,j] = 1; +/* each item must be exactly in one bin */ + +s.t. lim{j in J}: sum{i in I} w[i] * x[i,j] <= c * used[j]; +/* if bin j is used, it must not be overflowed */ + +minimize obj: sum{j in J} used[j]; +/* objective is to minimize the number of bins used */ + +data; + +/* The optimal solution is 3 bins */ + +param m := 6; + +param w := 1 50, 2 60, 3 30, 4 70, 5 50, 6 40; + +param c := 100; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cal.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/cal.mod new file mode 100644 index 000000000..2555182e0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cal.mod @@ -0,0 +1,49 @@ +/* cal.mod - print an ASCII calendar of the given year */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +param year, integer, >= 0001, <= 3999, default 2010; + +param first_day{m in 1..12}, integer, >= 0, <= 6, := + time2str(str2time(year & "-" & m & "-01", "%Y-%m-%d"), "%w"); + +param days_in_month{m in 1..12}, integer, >= 28, <= 31, := + (str2time(year + (if m < 12 then 0 else 1) & "-" & + (if m < 12 then m+1 else 1) & "-01", "%Y-%m-%d") - + str2time(year & "-" & m & "-01", "%Y-%m-%d")) / 86400; + +param foo{m in 1..12, k in 0..5, d in 0..6}, integer, := + 7 * k + d + 1 - first_day[m]; + +param cal{m in 1..12, k in 0..5, d in 0..6}, integer, := + if 1 <= foo[m,k,d] and foo[m,k,d] <= days_in_month[m] then + foo[m,k,d]; + +printf "\n"; +printf "%33s%04d\n", "", year; +printf "\n"; +for {t in 1..12 by 3} +{ for {m in t..t+2} + { printf "%7s%-14s", "", time2str(str2time(m, "%m"), "%B"); + printf{0..0: m < t+2} " "; + } + printf "\n"; + for {m in t..t+2} + { printf " S M Tu W Th F S"; + printf{0..0: m < t+2} " "; + } + printf "\n"; + for {k in 0..5} + { for {m in t..t+2} + { for {d in 0..6} + { printf{0..0: cal[m,k,d] = 0} " "; + printf{0..0: cal[m,k,d] != 0} " %2d", cal[m,k,d]; + } + printf{0..0: m < t+2} " "; + } + printf "\n"; + } +} +printf "\n"; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cf12a.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/cf12a.mod new file mode 100644 index 000000000..61a76c050 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cf12a.mod @@ -0,0 +1,81 @@ +/* + + Curve fitting problem 12.11(a) H P Williams "Model Building in Mathematical Programming" + + Dr. H J Mackenzie + HARD software + hjm@hardsoftware.com + + 2006-01-05 + + */ + +# set of points + +set I; + +# independent variable + +param x {i in I}; + +# dependent variable + +param y {i in I}; + +# output input values + +printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; + +# define equation variables + +var a; + +var b; + +var u {i in I}, >= 0; + +var v {i in I}, >= 0; + +# define objective function + +minimize error: sum {i in I} u[i] + sum {i in I} v[i]; + +# define equation constraint + +s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; + +solve; + +printf "y = %.4fx + %.4f\n", b, a; + +/* + * + * DATA section + * + */ + +data; + +param : I : x y := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cf12b.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/cf12b.mod new file mode 100644 index 000000000..56f1ba106 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cf12b.mod @@ -0,0 +1,88 @@ +/* + + Curve fitting problem 12.11(b) H P Williams "Model Building in Mathematical Programming" + + Dr. H J Mackenzie + HARD software + hjm@hardsoftware.com + + 2006-01-23 + + */ + +# set of points + +set I; + +# independent variable + +param x {i in I}; + +# dependent variable + +param y {i in I}; + +# output input values + +printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; + +# define equation variables + +var a; + +var b; + +var u {i in I}, >= 0; + +var v {i in I}, >= 0; + +var z; + +# define objective function + +minimize deviation: z; + +# define equation constraint + +s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; + +# define deviation constrains + +s.t. u_deviation {i in I} : z - u[i] >= 0; +s.t. v_deviation {i in I} : z - v[i] >= 0; + +solve; + +printf "y = %.4fx + %.4f Max deviation = %.4f\n", b, a, z; + +/* + * + * DATA section + * + */ + +data; + +param : I : x y := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cflsq.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/cflsq.mod new file mode 100644 index 000000000..4af4d029b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cflsq.mod @@ -0,0 +1,51 @@ +/*Curve fitting problem by Least Squares + Nigel_Galloway@operamail.com + October 1st., 2007 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var X; +var Y; +var Ex{z in Sample}; +var Ey{z in Sample}; + +/* sum of variances is zero for Sx*/ +variencesX{z in Sample}: X + Ex[z] = Sx[z]; +zumVariancesX: sum{z in Sample} Ex[z] = 0; +/* sum of variances is zero for Sy*/ +variencesY{z in Sample}: Y + Ey[z] = Sy[z]; +zumVariancesY: sum{z in Sample} Ey[z] = 0; + +solve; + +param b1 := (sum{z in Sample} Ex[z]*Ey[z])/(sum{z in Sample} Ex[z]*Ex[z]); +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", Y-b1*X, if b1 < 0 then "-" else "+", abs(b1); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/color.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/color.mod new file mode 100644 index 000000000..9a279c387 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/color.mod @@ -0,0 +1,113 @@ +/* COLOR, Graph Coloring Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Given an undirected loopless graph G = (V, E), where V is a set of + nodes, E <= V x V is a set of arcs, the Graph Coloring Problem is to + find a mapping (coloring) F: V -> C, where C = {1, 2, ... } is a set + of colors whose cardinality is as small as possible, such that + F(i) != F(j) for every arc (i,j) in E, that is adjacent nodes must + be assigned different colors. */ + +param n, integer, >= 2; +/* number of nodes */ + +set V := {1..n}; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +check{(i,j) in E}: i != j; +/* there must be no loops */ + +/* We need to estimate an upper bound of the number of colors |C|. + The number of nodes |V| can be used, however, for sparse graphs such + bound is not very good. To obtain a more suitable estimation we use + an easy "greedy" heuristic. Let nodes 1, ..., i-1 are already + assigned some colors. To assign a color to node i we see if there is + an existing color not used for coloring nodes adjacent to node i. If + so, we use this color, otherwise we introduce a new color. */ + +set EE := setof{(i,j) in E} (i,j) union setof{(i,j) in E} (j,i); +/* symmetrisized set of arcs */ + +param z{i in V, case in 0..1} := +/* z[i,0] = color index assigned to node i + z[i,1] = maximal color index used for nodes 1, 2, ..., i-1 which are + adjacent to node i */ +( if case = 0 then + ( /* compute z[i,0] */ + min{c in 1..z[i,1]} + ( if not exists{j in V: j < i and (i,j) in EE} z[j,0] = c then + c + else + z[i,1] + 1 + ) + ) + else + ( /* compute z[i,1] */ + if not exists{j in V: j < i} (i,j) in EE then + 1 + else + max{j in V: j < i and (i,j) in EE} z[j,0] + ) +); + +check{(i,j) in E}: z[i,0] != z[j,0]; +/* check that all adjacent nodes are assigned distinct colors */ + +param nc := max{i in V} z[i,0]; +/* number of colors used by the heuristic; obviously, it is an upper + bound of the optimal solution */ + +display nc; + +var x{i in V, c in 1..nc}, binary; +/* x[i,c] = 1 means that node i is assigned color c */ + +var u{c in 1..nc}, binary; +/* u[c] = 1 means that color c is used, i.e. assigned to some node */ + +s.t. map{i in V}: sum{c in 1..nc} x[i,c] = 1; +/* each node must be assigned exactly one color */ + +s.t. arc{(i,j) in E, c in 1..nc}: x[i,c] + x[j,c] <= u[c]; +/* adjacent nodes cannot be assigned the same color */ + +minimize obj: sum{c in 1..nc} u[c]; +/* objective is to minimize the number of colors used */ + +data; + +/* These data correspond to the instance myciel3.col from: + http://mat.gsia.cmu.edu/COLOR/instances.html */ + +/* The optimal solution is 4 */ + +param n := 11; + +set E := + 1 2 + 1 4 + 1 7 + 1 9 + 2 3 + 2 6 + 2 8 + 3 5 + 3 7 + 3 10 + 4 5 + 4 6 + 4 10 + 5 8 + 5 9 + 6 11 + 7 11 + 8 11 + 9 11 + 10 11 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/README b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/README new file mode 100644 index 000000000..38bb8b4d3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/README @@ -0,0 +1,44 @@ +The program module in this subdirectory is a crude implementation of +CPLEX-like interface to GLPK API. It consists of two files: cplex.c and +cplex.h. + +NOTE that this module is NOT a clean room implementation of the CPLEX +callable library. It only implements a CPLEX-like interface to the GLPK +API routines, and its main purpose is to provide possibility to build +and run applications which normally use the CPLEX callable library. + +This module approximately corresponds to CPLEX 9.0. + +Currently this module can be used as a linear programming solver for +Concorde, the state-of-the-art computer code for solving the symmetric +traveling salesman problem (TSP) developed by David Applegate, Robert +Bixby, Vasek Chvatal, and William Cook. For details about Concorde see +its web page at http://www.tsp.gatech.edu/concorde.html. + +To build Concorde along with GLPK you need to do the following: + +1. Configure, build, and install GLPK. + +2. Download the Concorde tarball co031219.tgz (version Dec 19, 2003), + unpack and unarchive it. + +3. Copy files cplex.h and cplex.c to subdirectory concorde/LP/. + +4. Create file named lpglpk.c in subdirectory concorde/LP/. This file + must contain the following two lines: + + #include "cplex.c" + #include "lpcplex8.c" + +5. Configure Concorde in usual way (./configure) and then build it with + the following command: + + make CPPFLAGS=-I. LPSOLVER_INTERFACE=lpglpk.c LPSOLVER_LIB=-lglpk + + The Concorde executable can be found in subdirectory concorde/TSP/. + +Please note that currently this GLPK interface module does not support +some important features (namely, CPXgetijdiv, CPXmdleave, CPXpivotin, +CPXpivotout, and CPXstrongbranch), so large (more than 1000 nodes) TSP +instances cannot be solved in a reasonable time, and some instances may +cause abnormal termination of Concorde (if CPXgetijdiv is called). diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/concorde.txt b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/concorde.txt new file mode 100644 index 000000000..c6f7aec9b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/concorde.txt @@ -0,0 +1,121 @@ +Solver: Concorde-03.12.19 (options used: -s 99) + http://www.tsp.gatech.edu/concorde.html +LP Solver: GLPK 4.34 (CPLEX-like interface module examples/cplex) +Computer: Intel Pentium 4 CPU 3GHz, 2GB of RAM +Platform: Cygwin 1.5.24 (Windows XP 5.1 Build 2600 Service Pack 4) +Compiler: GCC 3.4.4 (options used: -O2) +Test set: http://www.iwr.uni-heidelberg.de/groups/comopt/software/ + TSPLIB95/ + +Problem Solution B&B Time, s +--------- -------- --- ------- +a280 2579 1 3.09 +ali535 202339 1 21.88 +att48 10628 1 0.20 +att532 27686 7 74.31 +bayg29 1610 1 0.08 +bays29 2020 1 0.08 +berlin52 7542 1 0.11 +bier127 118282 1 0.62 +brazil58 25395 1 0.23 +brd14051 +brg180 1950 1 0.34 +burma14 3323 1 0.06 +ch130 6110 1 0.92 +ch150 6528 1 1.69 +d1291 +d15112 +d1655 +d18512 +d198 15780 3 4.92 +d2103 +d493 35002 5 123.89 +d657 48913 11 148.17 +dantzig42 699 1 0.08 +dsj1000 18660188 13 251.00 +eil101 (failed due to CPXgetijdiv) +eil51 426 1 0.17 +eil76 538 1 0.11 +fl1400 +fl1577 +fl3795 +fl417 11861 1 47.20 +fnl4461 +fri26 937 1 0.05 +gil262 2378 3 10.39 +gr120 6942 1 0.66 +gr137 69853 1 2.09 +gr17 2085 1 0.03 +gr202 40160 1 3.97 +gr21 2707 1 0.03 +gr229 134602 7 19.45 +gr24 1272 1 0.03 +gr431 171414 9 40.67 +gr48 5046 1 0.22 +gr666 294358 3 40.23 +gr96 55209 1 1.22 +hk48 11461 1 0.08 +kroA100 21282 1 0.41 +kroA150 26524 1 2.09 +kroA200 29368 1 2.44 +kroB100 22141 1 1.20 +kroB150 26130 1 1.66 +kroB200 29437 1 1.41 +kroC100 20749 1 0.42 +kroD100 21294 1 0.50 +kroE100 22068 1 0.94 +lin105 14379 1 0.23 +lin318 42029 1 4.28 +nrw1379 +p654 34643 1 17.08 +pa561 2763 15 370.70 +pcb1173 56892 11 370.30 +pcb3038 +pcb442 59778 13 35.86 +pla33810 +pla7397 +pla85900 +pr1002 259045 1 23.08 +pr107 44303 1 0.38 +pr124 59030 1 1.23 +pr136 96772 1 2.19 +pr144 58537 1 0.89 +pr152 73682 1 2.73 +pr226 80369 1 2.72 +pr2392 +pr264 49135 1 1.61 +pr299 48191 3 14.52 +pr439 107217 15 117.75 +pr76 108159 1 0.95 +rat195 2323 5 12.91 +rat575 6773 19 202.52 +rat783 8806 1 37.92 +rat99 1211 1 0.50 +rd100 7910 1 0.28 +rd400 15281 11 74.41 +rl11849 +rl1304 +rl1323 +rl1889 +rl5915 +rl5934 +si1032 92650 1 82.09 +si175 21407 3 8.97 +si535 48450 1 71.28 +st70 675 1 0.20 +swiss42 1273 1 0.06 +ts225 126643 1 21.25 +tsp225 3916 1 10.14 +u1060 224094 13 507.44 +u1432 +u159 42080 1 0.41 +u1817 +u2152 +u2319 +u574 36905 1 32.84 +u724 41910 19 238.42 +ulysses16 6859 1 0.19 +ulysses22 7013 1 0.47 +usa13509 +vm1084 239297 9 543.38 +vm1748 diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.c b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.c new file mode 100644 index 000000000..ef9e2dffe --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.c @@ -0,0 +1,2130 @@ +/* cplex.c (CPLEX-like interface to GLPK API) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "cplex.h" + +struct CPXENV +{ /* environment block */ + CPXLP *list; + /* linked list of problem objects */ + int *intparam; /* int intparam[]; */ + /* integer control parameters */ + double *dblparam; /* double dblparam[]; */ + /* floating-point control parameters */ +}; + +struct CPXLP +{ /* problem object */ + CPXENV *env; + /* pointer to environment block */ + glp_prob *prob; + /* pointer to underlying GLPK problem object */ + int rflen; + /* length of the array rflag */ + char *rflag; /* char rflag[rflen]; */ + /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */ +#define RF_NOT_RANGED 0 /* not ranged */ +#define RF_RANGED_POS 1 /* ranged, RHS = lower bound */ +#define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */ + int stat; + /* solution status reported by CPXgetstat; zero means no solution + exists */ + int meth; + /* method indicator reported by CPXgetmethod */ + int iwlen; + /* length of the working array */ + int *iwork; /* int iwork[iwlen] */ + /* working array initialized by binary zeros */ + CPXLP *link; + /* pointer to another problem object */ +}; + +struct intparam +{ int which; + int defv; + int minv; + int maxv; +}; + +struct dblparam +{ int which; + double defv; + double minv; + double maxv; +}; + +struct errstring +{ int code; + const char *string; +}; + +#define BIGINT 2100000000 +#define BIGDBL 1e75 + +static const struct intparam intparam[] = +{ {CPX_PARAM_ADVIND, 0, 0, 2}, + {CPX_PARAM_AGGIND, -1, -1, BIGINT}, + {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO, + CPX_DPRIIND_DEVEX}, + {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */ + {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT}, + {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL, + CPX_PPRIIND_FULL}, + {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON}, + {CPX_PARAM_REINV, 0, 0, 10000}, + {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON}, + {CPX_PARAM_SIMDISPLAY, 1, 0, 2}, +}; + +static const struct dblparam dblparam[] = +{ {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1}, + {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL}, + {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1}, + {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL}, + {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL}, +}; + +static const struct errstring errstring[] = +{ {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"}, + {CPXERR_BAD_ARGUMENT, "Invalid argument"}, + {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"}, + {CPXERR_BAD_FILETYPE, "Invalid filetype"}, + {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"}, + {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"}, + {CPXERR_BAD_SENSE, "Invalid sense entry %d"}, + {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat" + "ion"}, + {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"}, + {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo" + "wed"}, + {CPXERR_DUP_ENTRY, "Duplicate entry"}, + {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"}, + {CPXERR_INDEX_RANGE, "Index is outside range of valid values"}, + {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"}, + {CPXERR_NO_BASIC_SOLN, "No basic solution exists"}, + {CPXERR_NO_ENVIRONMENT, "No environment exists"}, + {CPXERR_NO_FILENAME, "File name not specified"}, + {CPXERR_NO_MEMORY, "Out of memory"}, + {CPXERR_NO_PROBLEM, "No problem exists"}, + {CPXERR_NO_SOLN, "No solution exists"}, + {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"}, + {CPXERR_NULL_NAME, "Null pointer %d in name array"}, + {CPXERR_NULL_POINTER, "Null pointer for required data"}, + {CPXERR_PARAM_TOO_BIG, "Parameter value too big"}, + {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"}, + {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"}, +}; + +/**********************************************************************/ + +#define xassert glp_assert +#define xprintf glp_printf +#define xmalloc glp_malloc +#define xcalloc glp_calloc +#define xfree glp_free + +/**********************************************************************/ + +static int findintparam(int whichparam) +{ int k, card; + card = sizeof(intparam) / sizeof(struct intparam); + for (k = 0; k < card; k++) + if (intparam[k].which == whichparam) return k; + return -1; +} + +static int getintparam(CPXENV *env, int whichparam) +{ int k; + xassert(env != NULL); + k = findintparam(whichparam); + xassert(k >= 0); + return env->intparam[k]; +} + +static int finddblparam(int whichparam) +{ int k, card; + card = sizeof(dblparam) / sizeof(struct dblparam); + for (k = 0; k < card; k++) + if (dblparam[k].which == whichparam) return k; + return -1; +} + +static double getdblparam(CPXENV *env, int whichparam) +{ int k; + xassert(env != NULL); + k = finddblparam(whichparam); + xassert(k >= 0); + return env->dblparam[k]; +} + +static const char *finderrstring(int errcode) +{ int k, card; + card = sizeof(errstring) / sizeof(struct errstring); + for (k = 0; k < card; k++) + { if (errstring[k].code == errcode) + return errstring[k].string; + } + return NULL; +} + +static int error(CPXENV *env, int errcode, ...) +{ va_list arg; + char buffer[510]; + xassert(env != NULL); + if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON) + { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer); + va_start(arg, errcode); + vprintf(buffer, arg); + va_end(arg); + } + return errcode; +} + +static int checkenv(CPXENV *env) +{ int errcode; + if (env == NULL) + errcode = CPXERR_NO_ENVIRONMENT; + else + errcode = 0; + return errcode; +} + +static checklp(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = checkenv(env); + if (errcode) goto done; + if (lp == NULL) + errcode = error(env, CPXERR_NO_PROBLEM); +done: return errcode; +} + +static void invalidate(CPXLP *lp) +{ lp->stat = 0; + lp->meth = CPX_ALG_NONE; + return; +} + +static void enlargerflag(CPXLP *lp) +{ int m; + xassert(lp != NULL); + m = glp_get_num_rows(lp->prob); + if (lp->rflen < m) + { int rflen = lp->rflen; + char *rflag = lp->rflag; + while (lp->rflen < m) + { lp->rflen += lp->rflen; + xassert(lp->rflen > 0); + } + lp->rflag = xcalloc(lp->rflen, sizeof(char)); + memcpy(lp->rflag, rflag, rflen); + xfree(rflag); + } + return; +} + +static void enlargeiwork(CPXLP *lp, int len) +{ xassert(len >= 0); + if (lp->iwlen < len) + { xfree(lp->iwork); + while (lp->iwlen < len) + { lp->iwlen += lp->iwlen; + xassert(lp->iwlen > 0); + } + lp->iwork = xcalloc(lp->iwlen, sizeof(int)); + memset(lp->iwork, 0, lp->iwlen * sizeof(int)); + } + return; +} + +/**********************************************************************/ + +int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, + const double obj[], const int cmatbeg[], const int cmatind[], + const double cmatval[], const double lb[], const double ub[], + char *colname[]) +{ int j, k, m, n, beg, end, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0 || nzcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (ccnt > 0) + { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, m); + for (j = 0; j < ccnt; j++) + { beg = cmatbeg[j]; + if (j > 0 && !(cmatbeg[j-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); + goto done; + } + if (!(0 <= beg && beg <= nzcnt)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); + for (k = beg; k < end; k++) + { if (!(0 <= cmatind[k] && cmatind[k] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[cmatind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[cmatind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[cmatind[k]] = 0; + if (errcode) goto done; + if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); + if (obj != NULL) + glp_set_obj_coef(lp->prob, n+j+1, obj[j]); + beg = cmatbeg[j]; + end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = cmatind[k]+1; + glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1, + cmatval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } +done: return errcode; +} + +int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, + const double rhs[], const char sense[], const int rmatbeg[], + const int rmatind[], const double rmatval[], char *colname[], + char *rowname[]) +{ int i, j, k, m, n, beg, end, type, errcode; + double temp; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0 || rcnt < 0 || nzcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (rcnt > 0) + { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, n+ccnt); + for (i = 0; i < rcnt; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + beg = rmatbeg[i]; + if (i > 0 && !(rmatbeg[i-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i); + goto done; + } + if (!(0 <= beg && beg <= nzcnt)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); + for (k = beg; k < end; k++) + { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[rmatind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[rmatind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[rmatind[k]] = 0; + if (errcode) goto done; + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (rcnt > 0) + glp_add_rows(lp->prob, rcnt); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + enlargerflag(lp); + for (i = 0; i < rcnt; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, m+i+1, rowname[i]); + temp = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_FX; + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp); + beg = rmatbeg[i]; + end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = rmatind[k]+1; + glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1, + rmatval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0); + } +done: return errcode; +} + +int CPXbaropt(CPXENV *env, CPXLP *lp) +{ xassert(env == env); + xassert(lp == lp); + xprintf("CPXbaropt: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(i == i); + xassert(y == y); + xprintf("CPXbinvrow: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char lu[], const double bd[]) +{ int j, n, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (cnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (cnt > 0) + { if (indices == NULL || lu == NULL || bd == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + n = glp_get_num_cols(lp->prob); + for (j = 0; j < cnt; j++) + { if (!(0 <= indices[j] && indices[j] < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B')) + { errcode = error(env, CPXERR_BAD_LUB, j); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (j = 0; j < cnt; j++) + { type = glp_get_col_type(lp->prob, indices[j]+1); + lbnd = glp_get_col_lb(lp->prob, indices[j]+1); + ubnd = glp_get_col_ub(lp->prob, indices[j]+1); + if (type == GLP_FR || type == GLP_UP) + lbnd = -CPX_INFBOUND; + if (type == GLP_FR || type == GLP_LO) + ubnd = +CPX_INFBOUND; + if (lu[j] == 'L') + lbnd = bd[j]; + else if (lu[j] == 'U') + ubnd = bd[j]; + else if (lu[j] == 'B') + lbnd = ubnd = bd[j]; + else + xassert(lu != lu); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd); + } +done: return errcode; +} + +int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, + const int rowlist[], const int collist[], const double vallist[]) +{ int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode; + int *head, *next, *ind; + double *val; + errcode = checklp(env, lp); + if (errcode) goto done; + if (numcoefs < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (numcoefs == 0) + { errcode = 0; + goto done; + } + if (rowlist == NULL || collist == NULL || vallist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + /* check triplets and determine the number of rows and columns + to be changed */ + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + enlargeiwork(lp, m); + enlargeiwork(lp, n); + rcnt = ccnt = 0; + for (k = 0; k < numcoefs; k++) + { i = rowlist[k]; + if (!(0 <= i && i < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + if (!(lp->iwork[i] & 0x01)) + rcnt++, lp->iwork[i] |= 0x01; + j = collist[k]; + if (!(0 <= j && j < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (!(lp->iwork[j] & 0x02)) + ccnt++, lp->iwork[j] |= 0x02; + } + memset(lp->iwork, 0, m * sizeof(int)); + memset(lp->iwork, 0, n * sizeof(int)); + errcode = 0; + invalidate(lp); + if (rcnt <= ccnt) + { /* change the matrix by rows */ + /* build the linked list of triplets: + head[i] is a pointer to first triplet for row i + next[k] is a pointer to next triplet for the same row */ + head = xcalloc(m, sizeof(int)); + for (i = 0; i < m; i++) + head[i] = -1; + next = xcalloc(numcoefs, sizeof(int)); + for (k = 0; k < numcoefs; k++) + { i = rowlist[k]; + next[k] = head[i]; + head[i] = k; + } + /* check duplicate columns */ + for (i = 0; i < m; i++) + { for (k = head[i]; k >= 0; k = next[k]) + { j = collist[k]; + if (lp->iwork[j]) + { xfree(head); + xfree(next); + errcode = error(env, CPXERR_DUP_ENTRY); + goto done; + } + lp->iwork[j] = 1; + } + for (k = head[i]; k >= 0; k = next[k]) + lp->iwork[collist[k]] = 0; + } + /* perform operation */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = 0; i < m; i++) + { if (head[i] < 0) continue; + len = glp_get_mat_row(lp->prob, i+1, ind, val); + for (ptr = 1; ptr <= len; ptr++) + { j = ind[ptr]-1; + xassert(lp->iwork[j] == 0); + lp->iwork[j] = ptr; + } + for (k = head[i]; k >= 0; k = next[k]) + { j = collist[k]; + if (lp->iwork[j] == 0) + lp->iwork[j] = ++len; + ptr = lp->iwork[j]; + ind[ptr] = j+1, val[ptr] = vallist[k]; + } + glp_set_mat_row(lp->prob, i+1, len, ind, val); + for (ptr = 1; ptr <= len; ptr++) + lp->iwork[ind[ptr]-1] = 0; + } + } + else + { /* change the matrix by columns */ + /* build the linked lists of triplets: + head[j] is a pointer to first triplet for column j + next[k] is a pointer to next triplet for the same column */ + head = xcalloc(n, sizeof(int)); + for (j = 0; j < n; j++) + head[j] = -1; + next = xcalloc(numcoefs, sizeof(int)); + for (k = 0; k < numcoefs; k++) + { j = collist[k]; + next[k] = head[j]; + head[j] = k; + } + /* check duplicate rows */ + for (j = 0; j < n; j++) + { for (k = head[j]; k >= 0; k = next[k]) + { i = rowlist[k]; + if (lp->iwork[i]) + { xfree(head); + xfree(next); + errcode = error(env, CPXERR_DUP_ENTRY); + goto done; + } + lp->iwork[i] = 1; + } + for (k = head[j]; k >= 0; k = next[k]) + lp->iwork[rowlist[k]] = 0; + } + /* perform operation */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + for (j = 0; j < n; j++) + { if (head[j] < 0) continue; + len = glp_get_mat_col(lp->prob, j+1, ind, val); + for (ptr = 1; ptr <= len; ptr++) + { i = ind[ptr]-1; + xassert(lp->iwork[i] == 0); + lp->iwork[i] = ptr; + } + for (k = head[j]; k >= 0; k = next[k]) + { i = rowlist[k]; + if (lp->iwork[i] == 0) + lp->iwork[i] = ++len; + ptr = lp->iwork[i]; + ind[ptr] = i+1, val[ptr] = vallist[k]; + } + glp_set_mat_col(lp->prob, j+1, len, ind, val); + for (ptr = 1; ptr <= len; ptr++) + lp->iwork[ind[ptr]-1] = 0; + } + } + xfree(head); + xfree(next); + xfree(ind); + xfree(val); +done: return errcode; +} + +void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin) +{ int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!(maxormin == CPX_MIN || maxormin == CPX_MAX)) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + errcode = 0; + invalidate(lp); + if (maxormin == CPX_MIN) + glp_set_obj_dir(lp->prob, GLP_MIN); + else + glp_set_obj_dir(lp->prob, GLP_MAX); +done: xassert(errcode == errcode); + return; +} + +int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char sense[]) +{ int i, m, type, errcode; + double rhs; + errcode = checklp(env, lp); + if (errcode) goto done; + if (cnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (cnt > 0 && (indices == NULL || sense == NULL)) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + m = glp_get_num_rows(lp->prob); + for (i = 0; i < cnt; i++) + { if (!(0 <= indices[i] && indices[i] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || + sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (i = 0; i < cnt; i++) + { type = glp_get_row_type(lp->prob, indices[i]+1); + if (lp->rflag[indices[i]] == RF_NOT_RANGED) + { if (type == GLP_LO || type == GLP_FX) + rhs = glp_get_row_lb(lp->prob, indices[i]+1); + else if (type == GLP_UP) + rhs = glp_get_row_ub(lp->prob, indices[i]+1); + else + xassert(type != type); + } + else if (lp->rflag[indices[i]] == RF_RANGED_POS) + { xassert(type == GLP_DB || type == GLP_FX); + rhs = glp_get_row_lb(lp->prob, indices[i]+1); + } + else if (lp->rflag[indices[i]] == RF_RANGED_NEG) + { xassert(type == GLP_DB); + rhs = glp_get_row_ub(lp->prob, indices[i]+1); + } + else + xassert(lp != lp); + if (sense[i] == 'L') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'E') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'G') + { lp->rflag[indices[i]] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { lp->rflag[indices[i]] = RF_RANGED_POS; + type = GLP_FX; + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs); + } +done: return errcode; +} + +int CPXcloseCPLEX(CPXENV **_env) +{ CPXENV *env; + CPXLP *lp; + int errcode; + if (_env == NULL) + { errcode = CPXERR_NULL_POINTER; + goto done; + } + env = *_env; + errcode = checkenv(env); + if (errcode) goto done; + while (env->list != NULL) + { lp = env->list; + errcode = CPXfreeprob(env, &lp); + xassert(!errcode); + } + xfree(env->intparam); + xfree(env->dblparam); + xfree(env); + *_env = NULL; + errcode = 0; +done: return errcode; +} + +int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[]) +{ int i, j, m, n, stat, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + if (m > 0 && rstat == NULL || n > 0 && cstat == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + for (i = 0; i < m; i++) + { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC || + rstat[i] == CPX_AT_UPPER)) + { errcode = error(env, CPXERR_BAD_STATUS, i); + goto done; + } + } + for (j = 0; j < n; j++) + { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC || + cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER)) + { errcode = error(env, CPXERR_BAD_STATUS, j); + goto done; + } + } + errcode = 0; + invalidate(lp); + for (i = 0; i < m; i++) + { if (rstat[i] == CPX_AT_LOWER) + stat = GLP_NL; + else if (rstat[i] == CPX_BASIC) + stat = GLP_BS; + else if (rstat[i] == CPX_AT_UPPER) + stat = GLP_NU; + else + xassert(rstat != rstat); + glp_set_row_stat(lp->prob, i+1, stat); + } + for (j = 0; j < n; j++) + { if (cstat[j] == CPX_AT_LOWER) + stat = GLP_NL; + else if (cstat[j] == CPX_BASIC) + stat = GLP_BS; + else if (cstat[j] == CPX_AT_UPPER) + stat = GLP_NU; + else if (cstat[j] == CPX_FREE_SUPER) + stat = GLP_NF; + else + xassert(cstat != cstat); + glp_set_col_stat(lp->prob, j+1, stat); + } +done: return errcode; +} + +int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[], const double dnorm[]) +{ int errcode; + errcode = CPXcopybase(env, lp, cstat, rstat); + xassert(dnorm == dnorm); + return errcode; +} + +int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[]) +{ int errcode; + errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj, + rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval, + NULL, NULL); + return errcode; +} + +int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[], char *colname[], + char *rowname[]) +{ int i, j, k, beg, end, type, errcode; + double lbnd, ubnd; + char name[255+1]; + errcode = checklp(env, lp); + if (errcode) goto done; + if (numcols < 0 || numrows < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (!(objsen == CPX_MIN || objsen == CPX_MAX)) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (numcols > 0) + { if (matbeg == NULL || matcnt == NULL || matind == NULL || + matval == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + } + for (i = 0; i < numrows; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + enlargeiwork(lp, numrows); + for (j = 0; j < numcols; j++) + { beg = matbeg[j]; + if (j > 0 && !(matbeg[j-1] <= beg)) + { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); + goto done; + } + if (beg < 0) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + end = beg + matcnt[j]; + if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1])) + { errcode = error(env, CPXERR_COUNT_RANGE, j); + goto done; + } + for (k = beg; k < end; k++) + { if (!(0 <= matind[k] && matind[k] < numrows)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); + goto done; + } + } + errcode = 0; + for (k = beg; k < end; k++) + { if (lp->iwork[matind[k]]) + { errcode = error(env, CPXERR_DUP_ENTRY); + break; + } + lp->iwork[matind[k]] = 1; + } + for (k = beg; k < end; k++) + lp->iwork[matind[k]] = 0; + if (errcode) goto done; + if (colname != NULL) + { if (colname[j] != NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + if (glp_get_prob_name(lp->prob) == NULL) + name[0] = '\0'; + else + strcpy(name, glp_get_prob_name(lp->prob)); + glp_erase_prob(lp->prob); + glp_set_prob_name(lp->prob, name); + if (objsen == CPX_MIN) + glp_set_obj_dir(lp->prob, GLP_MIN); + else if (objsen == CPX_MAX) + glp_set_obj_dir(lp->prob, GLP_MAX); + else + xassert(objsen != objsen); + if (numrows > 0) + glp_add_rows(lp->prob, numrows); + enlargerflag(lp); + for (i = 0; i < numrows; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, i+1, rowname[i]); + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { if (rngval == NULL || rngval[i] == 0.0) + { lp->rflag[i] = RF_RANGED_POS; + type = GLP_FX; + } + else if (rngval[i] > 0.0) + { lp->rflag[i] = RF_RANGED_POS; + type = GLP_DB; + ubnd += rngval[i]; + } + else /* rngval[i] < 0.0 */ + { lp->rflag[i] = RF_RANGED_NEG; + type = GLP_DB; + lbnd += rngval[i]; + } + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd); + } + if (numcols > 0) + glp_add_cols(lp->prob, numcols); + for (j = 0; j < numcols; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, j+1, colname[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd); + if (obj != NULL) + glp_set_obj_coef(lp->prob, j+1, obj[j]); + beg = matbeg[j]; + end = beg + matcnt[j]; + for (k = beg; k < end; k++) + lp->iwork[k-beg] = matind[k]+1; + glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1, + matval+beg-1); + for (k = beg; k < end; k++) + lp->iwork[k-beg] = 0; + } +done: return errcode; +} + +CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname) +{ CPXLP *lp = NULL; + int errcode; + errcode = checkenv(env); + if (errcode) goto done; + lp = xmalloc(sizeof(struct CPXLP)); + lp->env = env; + lp->prob = glp_create_prob(); + glp_set_prob_name(lp->prob, probname); + lp->rflen = 100; + lp->rflag = xcalloc(lp->rflen, sizeof(char)); + lp->iwlen = 100; + lp->iwork = xcalloc(lp->iwlen, sizeof(int)); + memset(lp->iwork, 0, lp->iwlen * sizeof(int)); + lp->link = env->list; + env->list = lp; + invalidate(lp); +done: if (status != NULL) *status = errcode; + return lp; +} + +int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, end-begin+1); + for (j = begin; j <= end; j++) + lp->iwork[j-begin] = j+1; + glp_del_cols(lp->prob, end-begin+1, lp->iwork-1); + for (j = begin; j <= end; j++) + lp->iwork[j-begin] = 0; +done: return errcode; +} + +int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, end-begin+1); + for (i = begin; i <= end; i++) + lp->iwork[i-begin] = i+1; + glp_del_rows(lp->prob, end-begin+1, lp->iwork-1); + for (i = begin; i <= end; i++) + lp->iwork[i-begin] = 0; + for (i = end+1; i < m; i++) + lp->rflag[i-(end-begin+1)] = lp->rflag[i]; +done: return errcode; +} + +int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(delstat == delstat); + xprintf("CPXdelsetcols: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]) +{ int i, m, cnt, ind, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (m > 0 && delstat == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + errcode = 0; + invalidate(lp); + enlargeiwork(lp, m); + cnt = ind = 0; + for (i = 0; i < m; i++) + { if (delstat[i] == 1) + { delstat[i] = -1; + lp->iwork[cnt++] = i+1; + } + else + { delstat[i] = ind; + lp->rflag[ind++] = lp->rflag[i]; + } + } + if (cnt > 0) + glp_del_rows(lp->prob, cnt, lp->iwork-1); + for (i = 0; i < cnt; i++) + lp->iwork[i] = 0; +done: return errcode; +} + +int CPXdualopt(CPXENV *env, CPXLP *lp); + +int CPXfreeprob(CPXENV *env, CPXLP **_lp) +{ CPXLP *lp; + int errcode; + errcode = checkenv(env); + if (errcode) goto done; + if (_lp == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + lp = *_lp; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + env = lp->env; + if (env->list == lp) + env->list = lp->link; + else + { CPXLP *pp; + for (pp = env->list; pp != NULL; pp = pp->link) + if (pp->link == lp) break; + xassert(pp != NULL); + pp->link = lp->link; + } + glp_delete_prob(lp->prob); + xfree(lp->rflag); + xfree(lp->iwork); + xfree(lp); + *_lp = NULL; +done: return errcode; +} + +int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]) +{ int i, j, m, n, stat, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + ; + else + { errcode = error(env, CPXERR_NO_BASIC_SOLN); + goto done; + } + errcode = 0; + if (rstat != NULL) + { m = glp_get_num_rows(lp->prob); + for (i = 0; i < m; i++) + { stat = glp_get_row_stat(lp->prob, i+1); + if (stat == GLP_BS) + rstat[i] = CPX_BASIC; + else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU) + rstat[i] = CPX_AT_LOWER; + else + rstat[i] = CPX_AT_UPPER; + } + } + if (cstat != NULL) + { n = glp_get_num_cols(lp->prob); + for (j = 0; j < n; j++) + { stat = glp_get_col_stat(lp->prob, j+1); + if (stat == GLP_BS) + cstat[j] = CPX_BASIC; + else if (stat == GLP_NU) + cstat[j] = CPX_AT_UPPER; + else if (stat == GLP_NF) + cstat[j] = CPX_FREE_SUPER; + else + cstat[j] = CPX_AT_LOWER; + } + } +done: return errcode; +} + +int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], + double dnorm[]) +{ int i, m, errcode; + errcode = CPXgetbase(env, lp, cstat, rstat); + if (errcode) goto done; + if (dnorm != NULL) + { m = glp_get_num_rows(lp->prob); + for (i = 0; i < m; i++) dnorm[i] = 1.0; + } +done: return errcode; +} + +int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]) +{ xassert(env == env); + xassert(lp == lp); + xassert(head == head); + xassert(x == x); + xprintf("CPXgetbhead: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetdblparam(CPXENV *env, int whichparam, double *value) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (value != NULL) + *value = env->dblparam[k]; +done: return errcode; +} + +int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (dj != NULL) + { for (j = begin; j <= end; j++) + dj[j-begin] = glp_get_col_dual(lp->prob, j+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer) +{ const char *string; + xassert(env == env); + string = finderrstring(errcode); + if (string == NULL) + buffer = NULL; + else + sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string); + return buffer; +} + +int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv) +{ xassert(env == env); + xassert(lp == lp); + xassert(idiv == idiv); + xassert(jdiv == jdiv); + xprintf("CPXgetijdiv: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetintparam(CPXENV *env, int whichparam, int *value) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (value != NULL) + *value = env->intparam[k]; +done: return errcode; +} + +int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(lb == lb); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetlb: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetmethod(CPXENV *env, CPXLP *lp) +{ int method; + if (checklp(env, lp)) + method = CPX_ALG_NONE; + else + method = lp->meth; + return method; +} + +int CPXgetnumcols(CPXENV *env, CPXLP *lp) +{ int numcols; + if (checklp(env, lp)) + numcols = 0; + else + numcols = glp_get_num_cols(lp->prob); + return numcols; +} + +int CPXgetnumnz(CPXENV *env, CPXLP *lp) +{ int numnz; + if (checklp(env, lp)) + numnz = 0; + else + numnz = glp_get_num_nz(lp->prob); + return numnz; +} + +int CPXgetnumrows(CPXENV *env, CPXLP *lp) +{ int numrows; + if (checklp(env, lp)) + numrows = 0; + else + numrows = glp_get_num_rows(lp->prob); + return numrows; +} + +int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval) +{ int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (objval != NULL) + *objval = glp_get_obj_val(lp->prob); + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (pi != NULL) + { for (i = begin; i <= end; i++) + pi[i-begin] = glp_get_row_dual(lp->prob, i+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, + int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(sense == sense); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetsense: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, + int end) +{ int i, m, type, errcode; + double temp; + errcode = checklp(env, lp); + if (errcode) goto done; + m = glp_get_num_rows(lp->prob); + if (!(0 <= begin && begin <= end && end < m)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (slack != NULL) + { for (i = begin; i <= end; i++) + { type = glp_get_row_type(lp->prob, i+1); + temp = glp_get_row_prim(lp->prob, i+1); + if (lp->rflag[i] == RF_NOT_RANGED) + { if (type == GLP_LO || type == GLP_FX) + slack[i-begin] = + glp_get_row_lb(lp->prob, i+1) - temp; + else if (type == GLP_UP) + slack[i-begin] = + glp_get_row_ub(lp->prob, i+1) - temp; + else + xassert(type != type); + } + else if (lp->rflag[i] == RF_RANGED_POS) + { xassert(type == GLP_DB || type == GLP_FX); + slack[i-begin] = + temp - glp_get_row_lb(lp->prob, i+1); + } + else if (lp->rflag[i] == RF_RANGED_NEG) + { xassert(type == GLP_DB); + slack[i-begin] = + temp - glp_get_row_ub(lp->prob, i+1); + } + else + xassert(lp != lp); + } + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXgetstat(CPXENV *env, CPXLP *lp) +{ int stat; + if (checklp(env, lp)) + stat = 0; + else + stat = lp->stat; + return stat; +} + +int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end) +{ xassert(env == env); + xassert(lp == lp); + xassert(ub == ub); + xassert(begin == begin); + xassert(end == end); + xprintf("CPXgetub: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], + const int rmatind[], const double rmatval[], double weight[], + int dpriind) +{ xassert(env == env); + xassert(lp == lp); + xassert(rcnt == rcnt); + xassert(rmatbeg == rmatbeg); + xassert(rmatind == rmatind); + xassert(rmatval == rmatval); + xassert(weight == weight); + xassert(dpriind == dpriind); + xprintf("CPXgetweight: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + n = glp_get_num_cols(lp->prob); + if (!(0 <= begin && begin <= end && end < n)) + { errcode = error(env, CPXERR_INDEX_RANGE); + goto done; + } + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (x != NULL) + { for (j = begin; j <= end; j++) + x[j-begin] = glp_get_col_prim(lp->prob, j+1); + } + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, + double *minvalue, double *maxvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (defvalue != NULL) + *defvalue = dblparam[k].defv; + if (minvalue != NULL) + *minvalue = dblparam[k].minv; + if (maxvalue != NULL) + *maxvalue = dblparam[k].maxv; +done: return errcode; +} + +int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, + int *minvalue, int *maxvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + errcode = 0; + if (defvalue != NULL) + *defvalue = intparam[k].defv; + if (minvalue != NULL) + *minvalue = intparam[k].minv; + if (maxvalue != NULL) + *maxvalue = intparam[k].maxv; +done: return errcode; +} + +int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downratio[], double upratio[]) +{ int k; + xassert(env == env); + xassert(lp == lp); + xassert(goodlist == goodlist); + xassert(goodlen >= 0); + xassert(downratio != NULL); + xassert(upratio != NULL); + /* not implemented yet */ + for (k = 0; k < goodlen; k++) + downratio[k] = upratio[k] = 0.0; + return 0; +} + +int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], + const double lb[], const double ub[], const char ctype[], + char *colname[]) +{ int j, n, kind, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (ccnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + for (j = 0; j < ccnt; j++) + { if (ctype != NULL) + { if (!(ctype[j] == 'C' || ctype[j] == 'B' || + ctype[j] == 'I')) + { errcode = error(env, CPXERR_BAD_CTYPE, j); + goto done; + } + } + if (colname != NULL) + { if (colname[j] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, j); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + n = glp_get_num_cols(lp->prob); + if (ccnt > 0) + glp_add_cols(lp->prob, ccnt); + for (j = 0; j < ccnt; j++) + { if (colname != NULL) + glp_set_col_name(lp->prob, n+j+1, colname[j]); + if (obj != NULL) + glp_set_obj_coef(lp->prob, n+j+1, obj[j]); + lbnd = (lb == NULL ? 0.0 : lb[j]); + ubnd = (ub == NULL ? 0.0 : ub[j]); + if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) + type = GLP_FR; + else if (ubnd >= +CPX_INFBOUND) + type = GLP_LO; + else if (lbnd <= -CPX_INFBOUND) + type = GLP_UP; + else if (lbnd != ubnd) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); + if (ctype != NULL) + { if (ctype[j] == 'C') + kind = GLP_CV; + else if (ctype[j] == 'B') + kind = GLP_BV; + else if (ctype[j] == 'I') + kind = GLP_IV; + else + xassert(ctype != ctype); + glp_set_col_kind(lp->prob, n+j+1, kind); + } + } +done: return errcode; +} + +int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], + const char sense[], const double rngval[], char *rowname[]) +{ int i, m, type, errcode; + double lbnd, ubnd; + errcode = checklp(env, lp); + if (errcode) goto done; + if (rcnt < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + for (i = 0; i < rcnt; i++) + { if (sense != NULL) + { if (!(sense[i] == 'L' || sense[i] == 'E' || + sense[i] == 'G' || sense[i] == 'R')) + { errcode = error(env, CPXERR_BAD_SENSE, i); + goto done; + } + } + if (rowname != NULL) + { if (rowname[i] == NULL) + { errcode = error(env, CPXERR_NULL_NAME, i); + goto done; + } + } + } + errcode = 0; + invalidate(lp); + m = glp_get_num_rows(lp->prob); + if (rcnt > 0) + glp_add_rows(lp->prob, rcnt); + enlargerflag(lp); + for (i = 0; i < rcnt; i++) + { if (rowname != NULL) + glp_set_row_name(lp->prob, m+i+1, rowname[i]); + lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); + if (sense == NULL || sense[i] == 'E') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_FX; + } + else if (sense[i] == 'L') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_UP; + } + else if (sense[i] == 'G') + { lp->rflag[m+i] = RF_NOT_RANGED; + type = GLP_LO; + } + else if (sense[i] == 'R') + { if (rngval == NULL || rngval[i] == 0.0) + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_FX; + } + else if (rngval[i] > 0.0) + { lp->rflag[m+i] = RF_RANGED_POS; + type = GLP_DB; + ubnd += rngval[i]; + } + else /* rngval[i] < 0.0 */ + { lp->rflag[m+i] = RF_RANGED_NEG; + type = GLP_DB; + lbnd += rngval[i]; + } + } + else + xassert(sense != sense); + glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd); + } +done: return errcode; +} + +CPXENV *CPXopenCPLEX(int *status) +{ CPXENV *env; + int k, card; + env = xmalloc(sizeof(CPXENV)); + env->list = NULL; + card = sizeof(intparam) / sizeof(struct intparam); + env->intparam = xcalloc(card, sizeof(int)); + for (k = 0; k < card; k++) + env->intparam[k] = intparam[k].defv; + card = sizeof(dblparam) / sizeof(struct dblparam); + env->dblparam = xcalloc(card, sizeof(double)); + for (k = 0; k < card; k++) + env->dblparam[k] = dblparam[k].defv; + if (status != NULL) *status = 0; + return env; +} + +int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen) +{ int i, m, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (rlen < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (rlen > 0 && rlist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + m = glp_get_num_rows(lp->prob); + for (i = 0; i < rlen; i++) + { if (!(0 <= rlist[i] && rlist[i] < m)) + { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); + goto done; + } + } + errcode = 0; + for (i = 0; i < rlen; i++) + { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX) + { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS) + { /* not implemented yet */ + break; + } + } + } +done: return errcode; +} + +int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen) +{ int j, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (clen < 0) + { errcode = error(env, CPXERR_BAD_ARGUMENT); + goto done; + } + if (clen > 0 && clist == NULL) + { errcode = error(env, CPXERR_NULL_POINTER); + goto done; + } + n = glp_get_num_cols(lp->prob); + for (j = 0; j < clen; j++) + { if (!(0 <= clist[j] && clist[j] < n)) + { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); + goto done; + } + if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX) + { errcode = error(env, CPXERR_NOT_FIXED); + goto done; + } + } + errcode = 0; + for (j = 0; j < clen; j++) + { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS) + { /* not implemented yet */ + break; + } + } +done: return errcode; +} + +int CPXprimopt(CPXENV *env, CPXLP *lp); + +int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename) +{ xassert(env == env); + xassert(lp == lp); + xassert(filename == filename); + xprintf("CPXsavwrite: not implemented yet\n"); + exit(EXIT_FAILURE); + return -1; +} + +int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = finddblparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + if (newvalue < dblparam[k].minv) + { errcode = error(env, CPXERR_PARAM_TOO_SMALL); + goto done; + } + if (newvalue > dblparam[k].maxv) + { errcode = error(env, CPXERR_PARAM_TOO_BIG); + goto done; + } + errcode = 0; + env->dblparam[k] = newvalue; +done: return errcode; +} + +int CPXsetintparam(CPXENV *env, int whichparam, int newvalue) +{ int k, errcode; + errcode = checkenv(env); + if (errcode) goto done; + k = findintparam(whichparam); + if (k < 0) + { errcode = error(env, CPXERR_BAD_PARAM_NUM); + goto done; + } + if (newvalue < intparam[k].minv) + { errcode = error(env, CPXERR_PARAM_TOO_SMALL); + goto done; + } + if (newvalue > intparam[k].maxv) + { errcode = error(env, CPXERR_PARAM_TOO_BIG); + goto done; + } + errcode = 0; + env->intparam[k] = newvalue; +done: return errcode; +} + +int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, + int *pfeasind, int *dfeasind) +{ int type, pfeas, dfeas, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + if (!lp->stat) + type = CPX_NO_SOLN, pfeas = dfeas = 0; + else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { type = CPX_BASIC_SOLN; + pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS); + dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS); + } + else + xassert(lp != lp); + if (solnmethod != NULL) + *solnmethod = lp->meth; + if (solntype != NULL) + *solntype = type; + if (pfeasind != NULL) + *pfeasind = pfeas; + if (dfeasind != NULL) + *dfeasind = dfeas; +done: return errcode; +} + +int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, + double x[], double pi[], double slack[], double dj[]) +{ int m, n, errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + if (!lp->stat) + { errcode = error(env, CPXERR_NO_SOLN); + goto done; + } + errcode = 0; + m = glp_get_num_rows(lp->prob); + n = glp_get_num_cols(lp->prob); + if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) + { if (lpstat != NULL) + *lpstat = CPXgetstat(env, lp); + if (objval != NULL) + xassert(CPXgetobjval(env, lp, objval) == 0); + if (x != NULL) + xassert(CPXgetx(env, lp, x, 0, n-1) == 0); + if (pi != NULL) + xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0); + if (slack != NULL) + xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0); + if (dj != NULL) + xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0); + } + else + xassert(lp != lp); +done: return errcode; +} + +int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downpen[], double uppen[], int itlim) +{ int k; + xassert(env == env); + xassert(lp == lp); + xassert(goodlist == goodlist); + xassert(goodlen >= 0); + xassert(downpen != NULL); + xassert(uppen != NULL); + xassert(itlim == itlim); + /* not implemented yet */ + for (k = 0; k < goodlen; k++) + downpen[k] = uppen[k] = 0.0; + return 0; +} + +static int xstrcasecmp(const char *s1, const char *s2) +{ int c1, c2; + for (;;) + { c1 = toupper((unsigned char)*s1++); + c2 = toupper((unsigned char)*s2++); + if (c1 == '\0' || c1 != c2) break; + } + return c1 - c2; +} + +static void getfiletype(const char *filename, char type[3+1]) +{ /* determine filetype from filename */ + int beg, end; + beg = end = strlen(filename); + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) + beg--; + if (beg > 0 && filename[beg-1] == '.' && + xstrcasecmp(&filename[beg], "gz") == 0) + { end = --beg; + while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) + beg--; + } + if (beg > 0 && filename[beg-1] == '.') + { memcpy(type, &filename[beg], end - beg); + type[end - beg] = '\0'; + } + else + type[0] = '\0'; + return; +} + +int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, + const char *filetype) +{ glp_prob *copy; + int errcode; + char type[3+1]; + errcode = checklp(env, lp); + if (errcode) goto done; + if (filename == NULL) + { errcode = error(env, CPXERR_NO_FILENAME); + goto done; + } + if (filetype == NULL) + getfiletype(filename, type), filetype = type; + if (xstrcasecmp(filetype, "MPS") == 0) + { glp_term_out(GLP_OFF); + errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename) + ; + glp_term_out(GLP_ON); + } + else if (xstrcasecmp(filetype, "LP") == 0) + { glp_term_out(GLP_OFF); + errcode = glp_write_lp(lp->prob, NULL, filename); + glp_term_out(GLP_ON); + } + else if (xstrcasecmp(filetype, "RMP") == 0 || + xstrcasecmp(filetype, "REW") == 0) + { copy = glp_create_prob(); + glp_copy_prob(copy, lp->prob, GLP_OFF); + glp_term_out(GLP_OFF); + errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename); + glp_term_out(GLP_ON); + glp_delete_prob(copy); + } + else if (xstrcasecmp(filetype, "RLP") == 0) + { copy = glp_create_prob(); + glp_copy_prob(copy, lp->prob, GLP_OFF); + glp_term_out(GLP_OFF); + errcode = glp_write_lp(copy, NULL, filename); + glp_term_out(GLP_ON); + glp_delete_prob(copy); + } + else + { errcode = error(env, CPXERR_BAD_FILETYPE); + goto done; + } + if (errcode) + errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename); +done: return errcode; +} + +/**********************************************************************/ + +static int solvelp(CPXENV *env, CPXLP *lp, int meth) +{ glp_smcp parm; + int errcode; + errcode = checklp(env, lp); + if (errcode) goto done; + errcode = 0; + invalidate(lp); + glp_init_smcp(&parm); + switch (meth) + { case CPX_ALG_PRIMAL: + parm.meth = GLP_PRIMAL; + break; + case CPX_ALG_DUAL: + parm.meth = GLP_DUAL; + break; + default: + xassert(meth != meth); + } + switch (getintparam(env, CPX_PARAM_SIMDISPLAY)) + { case 0: + parm.msg_lev = GLP_MSG_OFF; + break; + case 1: + parm.msg_lev = GLP_MSG_ALL; + break; + case 2: + parm.msg_lev = GLP_MSG_ALL; + parm.out_frq = 1; + break; + default: + xassert(env != env); + } + xassert(getdblparam == getdblparam); + switch (getintparam(env, CPX_PARAM_ADVIND)) + { case 0: + glp_term_out(GLP_OFF); + glp_adv_basis(lp->prob, 0); + glp_term_out(GLP_ON); + break; + case 1: + case 2: + break; + default: + xassert(env != env); + } + if (!glp_bf_exists(lp->prob)) + { if (glp_factorize(lp->prob) != 0) + { glp_term_out(GLP_OFF); + glp_adv_basis(lp->prob, 0); + glp_term_out(GLP_ON); + if (glp_factorize(lp->prob) != 0) + glp_std_basis(lp->prob); + } + } + xassert(glp_simplex(lp->prob, &parm) == 0); + switch (glp_get_status(lp->prob)) + { case GLP_OPT: + lp->stat = CPX_STAT_OPTIMAL; + lp->meth = meth; + break; + case GLP_NOFEAS: + lp->stat = CPX_STAT_INFEASIBLE; + lp->meth = meth; + break; + case GLP_UNBND: + lp->stat = CPX_STAT_UNBOUNDED; + lp->meth = meth; + break; + default: + xassert(lp != lp); + } +done: return errcode; +} + +int CPXprimopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_PRIMAL); + return errcode; +} + +int CPXdualopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_DUAL); + return errcode; +} + +int CPXlpopt(CPXENV *env, CPXLP *lp) +{ int errcode; + errcode = solvelp(env, lp, CPX_ALG_PRIMAL); + return errcode; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.h b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.h new file mode 100644 index 000000000..94c3b204c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cplex/cplex.h @@ -0,0 +1,301 @@ +/* cplex.h (CPLEX-like interface to GLPK API) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef _CPLEX_H +#define _CPLEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CPXENV CPXENV, *CPXENVptr; +typedef struct CPXLP CPXLP, *CPXLPptr; + +#define CPX_VERSION 900 + +#define CPX_OFF 0 +#define CPX_ON 1 + +#define CPX_INFBOUND 1e20 + +/* error codes: */ +#define CPXERR_NO_MEMORY 1001 +#define CPXERR_NO_ENVIRONMENT 1002 +#define CPXERR_BAD_ARGUMENT 1003 +#define CPXERR_NULL_POINTER 1004 +#define CPXERR_NO_PROBLEM 1009 +#define CPXERR_BAD_PARAM_NUM 1013 +#define CPXERR_PARAM_TOO_SMALL 1014 +#define CPXERR_PARAM_TOO_BIG 1015 +#define CPXERR_INDEX_RANGE 1200 +#define CPXERR_COL_INDEX_RANGE 1201 +#define CPXERR_ROW_INDEX_RANGE 1203 +#define CPXERR_NEGATIVE_SURPLUS 1207 +#define CPXERR_BAD_SENSE 1215 +#define CPXERR_NO_SOLN 1217 +#define CPXERR_NOT_FIXED 1221 +#define CPXERR_DUP_ENTRY 1222 +#define CPXERR_NULL_NAME 1224 +#define CPXERR_ARRAY_NOT_ASCENDING 1226 +#define CPXERR_COUNT_RANGE 1227 +#define CPXERR_BAD_LUB 1229 +#define CPXERR_BAD_STATUS 1253 +#define CPXERR_NO_BASIC_SOLN 1261 +#define CPXERR_NO_FILENAME 1421 +#define CPXERR_FAIL_OPEN_WRITE 1422 +#define CPXERR_BAD_FILETYPE 1424 +#define CPXERR_BAD_CTYPE 3021 + +/* control parameters: */ +#define CPX_PARAM_ADVIND 1001 +#define CPX_PARAM_AGGIND 1003 +#define CPX_PARAM_DPRIIND 1009 +#define CPX_PARAM_EPOPT 1014 +#define CPX_PARAM_EPPER 1015 +#define CPX_PARAM_EPRHS 1016 +#define CPX_PARAM_FASTMIP 1017 /* ??? */ +#define CPX_PARAM_SIMDISPLAY 1019 +#define CPX_PARAM_ITLIM 1020 +#define CPX_PARAM_OBJLLIM 1025 +#define CPX_PARAM_OBJULIM 1026 +#define CPX_PARAM_PERIND 1027 +#define CPX_PARAM_PPRIIND 1029 +#define CPX_PARAM_PREIND 1030 +#define CPX_PARAM_REINV 1031 +#define CPX_PARAM_SCRIND 1035 +#define CPX_PARAM_DATACHECK 1056 + +/* CPX_PARAM_DPRIIND: */ +#define CPX_DPRIIND_AUTO 0 +#define CPX_DPRIIND_FULL 1 +#define CPX_DPRIIND_STEEP 2 +#define CPX_DPRIIND_FULL_STEEP 3 +#define CPX_DPRIIND_STEEPQSTART 4 +#define CPX_DPRIIND_DEVEX 5 + +/* CPX_PARAM_PPRIIND: */ +#define CPX_PPRIIND_PARTIAL (-1) +#define CPX_PPRIIND_AUTO 0 +#define CPX_PPRIIND_DEVEX 1 +#define CPX_PPRIIND_STEEP 2 +#define CPX_PPRIIND_STEEPQSTART 3 +#define CPX_PPRIIND_FULL 4 + +/* CPXgetprobtype: */ +#define CPXPROB_LP 0 +#define CPXPROB_MIP 1 +#define CPXPROB_RELAXED 2 +#define CPXPROB_FIXED 3 +#define CPXPROB_QP 5 +#define CPXPROB_ZEROEDQP 6 + +/* CPXgetobjsen: */ +#define CPX_MIN 1 +#define CPX_MAX (-1) + +/* CPXgetbase: */ +#define CPX_AT_LOWER 0 +#define CPX_BASIC 1 +#define CPX_AT_UPPER 2 +#define CPX_FREE_SUPER 3 + +/* CPXgetstat: */ +#define CPX_STAT_OPTIMAL 1 +#define CPX_STAT_UNBOUNDED 2 +#define CPX_STAT_INFEASIBLE 3 +#define CPX_STAT_INForUNBD 4 +#define CPX_STAT_OPTIMAL_INFEAS 5 +#define CPX_STAT_ABORT_IT_LIM 10 +#define CPX_STAT_ABORT_OBJ_LIM 12 + +/* CPXgetmethod: */ +#define CPX_ALG_NONE 0 +#define CPX_ALG_PRIMAL 1 +#define CPX_ALG_DUAL 2 +#define CPX_ALG_BARRIER 4 + +/* CPXsolninfo: */ +#define CPX_NO_SOLN 0 +#define CPX_BASIC_SOLN 1 +#define CPX_NONBASIC_SOLN 2 +#define CPX_PRIMAL_SOLN 3 + +int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, + const double obj[], const int cmatbeg[], const int cmatind[], + const double cmatval[], const double lb[], const double ub[], + char *colname[]); + +int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, + const double rhs[], const char sense[], const int rmatbeg[], + const int rmatind[], const double rmatval[], char *colname[], + char *rowname[]); + +int CPXbaropt(CPXENV *env, CPXLP *lp); + +int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]); + +int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char lu[], const double bd[]); + +int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, + const int rowlist[], const int collist[], const double vallist[]); + +void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin); + +int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], + const char sense[]); + +int CPXcloseCPLEX(CPXENV **env); + +int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[]); + +int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], + const int rstat[], const double dnorm[]); + +int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[]); + +int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, + int objsen, const double obj[], const double rhs[], + const char sense[], const int matbeg[], const int matcnt[], + const int matind[], const double matval[], const double lb[], + const double ub[], const double rngval[], char *colname[], + char *rowname[]); + +CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname); + +int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end); + +int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end); + +int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]); + +int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]); + +int CPXdualopt(CPXENV *env, CPXLP *lp); + +int CPXfreeprob(CPXENV *env, CPXLP **lp); + +int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]); + +int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], + double dnorm[]); + +int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]); + +int CPXgetdblparam(CPXENV *env, int whichparam, double *value); + +int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end); + +char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer); + +int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv); + +int CPXgetintparam(CPXENV *env, int whichparam, int *value); + +int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end); + +int CPXgetmethod(CPXENV *env, CPXLP *lp); + +int CPXgetnumcols(CPXENV *env, CPXLP *lp); + +int CPXgetnumnz(CPXENV *env, CPXLP *lp); + +int CPXgetnumrows(CPXENV *env, CPXLP *lp); + +int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval); + +int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end); + +int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, + int end); + +int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, + int end); + +int CPXgetstat(CPXENV *env, CPXLP *lp); + +int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end); + +int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], + const int rmatind[], const double rmatval[], double weight[], + int dpriind); + +int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end); + +int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, + double *minvalue, double *maxvalue); + +int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, + int *minvalue, int *maxvalue); + +int CPXlpopt(CPXENV *env, CPXLP *lp); + +int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downratio[], double upratio[]); + +int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], + const double lb[], const double ub[], const char ctype[], + char *colname[]); + +int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], + const char sense[], const double rngval[], char *rowname[]); + +CPXENV *CPXopenCPLEX(int *status); + +int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen); + +int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen); + +int CPXprimopt(CPXENV *env, CPXLP *lp); + +int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename); + +int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue); + +int CPXsetintparam(CPXENV *env, int whichparam, int newvalue); + +int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, + int *pfeasind, int *dfeasind); + +int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, + double x[], double pi[], double slack[], double dj[]); + +int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], + int goodlen, double downpen[], double uppen[], int itlim); + +int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, + const char *filetype); + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/cpp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/cpp.mod new file mode 100644 index 000000000..af3f1208b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/cpp.mod @@ -0,0 +1,67 @@ +/* CPP, Critical Path Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Note: Reduced costs of auxiliary variables phi[j,k] (see below) + can be only zero or one. The critical path is defined by the + constraints, whose reduced cost is one. */ + +set J; +/* set of jobs (activities) */ + +set P{j in J}, in J, default {}; +/* P[j] is a subset of jobs that immediately precede job j */ + +param t{j in J}, >= 0; +/* duration required to perform job j */ + +var x{j in J}, >= 0; +/* starting time of job j */ + +s.t. phi{j in J, k in P[j]}: x[j] >= x[k] + t[k]; +/* job j can start only after all immediately preceding jobs have been + completely performed */ + +var z; +/* project makespan */ + +s.t. fin{j in J}: z >= x[j] + t[j]; +/* which is the maximum of the completion times of all the jobs */ + +minimize obj: z; +/* the objective is make z as small as possible */ + +data; + +/* The optimal solution is 46 */ + +param : J : t := + A 3 /* Excavate */ + B 4 /* Lay foundation */ + C 3 /* Rough plumbing */ + D 10 /* Frame */ + E 8 /* Finish exterior */ + F 4 /* Install HVAC */ + G 6 /* Rough electric */ + H 8 /* Sheet rock */ + I 5 /* Install cabinets */ + J 5 /* Paint */ + K 4 /* Final plumbing */ + L 2 /* Final electric */ + M 4 /* Install flooring */ +; + +set P[B] := A; +set P[C] := B; +set P[D] := B; +set P[E] := D; +set P[F] := D; +set P[G] := D; +set P[H] := C E F G; +set P[I] := H; +set P[J] := H; +set P[K] := I; +set P[L] := J; +set P[M] := K L; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/crypto.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/crypto.mod new file mode 100644 index 000000000..bad50325f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/crypto.mod @@ -0,0 +1,84 @@ +/* CRYPTO, a crypto-arithmetic puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* This problem comes from the newsgroup rec.puzzle. + The numbers from 1 to 26 are assigned to the letters of the alphabet. + The numbers beside each word are the total of the values assigned to + the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal + 5, 9, 20 and 13, or any other combination that add up to 47). + Find the value of each letter under the equations: + + BALLET 45 GLEE 66 POLKA 59 SONG 61 + CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 + CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 + FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 + FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 + + Solution: + A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z + 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18 + + Reference: + Koalog Constraint Solver , + Simple problems, the crypto-arithmetic puzzle ALPHACIPHER. */ + +set LETTERS := +{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' +}; +/* set of letters */ + +set VALUES := 1..card(LETTERS); +/* set of values assigned to the letters */ + +set WORDS; +/* set of words */ + +param total{word in WORDS}; +/* total[word] is the total of the values assigned to the letters in + the word */ + +var x{i in LETTERS, j in VALUES}, binary; +/* x[i,j] = 1 means that letter i is assigned value j */ + +s.t. phi{i in LETTERS}: sum{j in VALUES} x[i,j] = 1; + +s.t. psi{j in VALUES}: sum{i in LETTERS} x[i,j] = 1; + +s.t. eqn{word in WORDS}: sum{k in 1..length(word), j in VALUES} + j * x[substr(word,k,1), j] = total[word]; + +solve; + +printf{i in LETTERS} " %s", i; +printf "\n"; + +printf{i in LETTERS} " %2d", sum{j in VALUES} j * x[i,j]; +printf "\n"; + +data; + +param : WORDS : total := + BALLET 45 + CELLO 43 + CONCERT 74 + FLUTE 30 + FUGUE 50 + GLEE 66 + JAZZ 58 + LYRE 47 + OBOE 53 + OPERA 65 + POLKA 59 + QUARTET 50 + SAXOPHONE 134 + SCALE 51 + SOLO 37 + SONG 61 + SOPRANO 82 + THEME 72 + VIOLIN 100 + WALTZ 34 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/csv/distances.csv b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/distances.csv new file mode 100644 index 000000000..8c7b419de --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/distances.csv @@ -0,0 +1,7 @@ +plant,market,distance +"Seattle","New York",2.5 +"Seattle","Chicago",1.7 +"Seattle","Topeka",1.8 +"San Diego","New York",2.5 +"San Diego","Chicago",1.8 +"San Diego","Topeka",1.4 diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/csv/markets.csv b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/markets.csv new file mode 100644 index 000000000..d04dec82c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/markets.csv @@ -0,0 +1,4 @@ +market,demand +"New York",325. +"Chicago",300. +"Topeka",275. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/csv/parameters.csv b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/parameters.csv new file mode 100644 index 000000000..c7c37e9af --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/parameters.csv @@ -0,0 +1,2 @@ +parameter,value +"transport cost",90. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/csv/plants.csv b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/plants.csv new file mode 100644 index 000000000..292f45f12 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/plants.csv @@ -0,0 +1,3 @@ +plant,capacity +"Seattle",350. +"San Diego",600. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/csv/transp_csv.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/transp_csv.mod new file mode 100644 index 000000000..d970bf61b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/csv/transp_csv.mod @@ -0,0 +1,70 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +set K dimen 2; +/* transportation lane */ + +set L; +/* parameters */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param e{l in L}; +/* parameters */ + +param f; +/* freight in dollars per case per thousand miles */ + +table tab_plant IN "CSV" "plants.csv" : + I <- [plant], a ~ capacity; + +table tab_market IN "CSV" "markets.csv" : + J <- [market], b ~ demand; + +table tab_distance IN "CSV" "distances.csv" : + K <- [plant, market], d ~ distance; + +table tab_parameter IN "CSV" "parameters.csv" : + L <- [parameter], e ~ value ; + +param c{i in I, j in J} := e['transport cost'] * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{(i,j) in K} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{(i,j) in K} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{(i,j) in K} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{(i,j) in K} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table tab_result{(i,j) in K} OUT "CSV" "result.csv" : + i ~ plant, j ~ market, x[i,j] ~ shipment; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod new file mode 100644 index 000000000..204846763 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod @@ -0,0 +1,226 @@ +# Model I Forest Estate Modelling using GLPK/MathProg +# Reading and writing dbf files + +# by Noli Sicad --- nsicad@gmail.com +# 18 December 2009 + +# Forest Management 4th Edition +# by Lawrence Davis, K. Norman Johnson, Pete Bettinger, Theodore Howard +# Chapter 11 - Daniel Pickett +# http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm + +# Model I Formulation + +/* Note: This is not the full LP model mentioned in the book. +Some of the constraints are deliberately omitted in this model for the purpose of clarity. + +The features of MathProg in this example are: +* reading and writing dbf from regular dbf files, +* reading dbf file (database of shapefile (stands.shp)) (e.g. area parameter), +* using the area data in the constraints and +* writing dbf file from result of LP model. + +Model I - Harvest Scheduling formulation for Sustainable Forest Management (SFM) + +Features are: +* Net Present Value for the objective function (Revenue - Cost) +* Harvest Constraints by period - Sustainable Yield per Period +* Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha (1-Apha) +* Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta (1 +Beta) +* Forest / Land Constraint -- Total Area of the forest +* Forest Stand Constraint -- Individual stands + +What is next? -- Forest Mgt Carbon Accounting for Climate Change + +Note: The model file that the data containing in +the dbf files is public domain material (so it is compatible with the +GNU GPL) and data can be found in +http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm + +# Noli Sicad --- nsicad@gmail.com + +*/ + +set G_STAND_TYPE; # A, B, C + +set I_CULTURAL_PRES; +set J_MGT_YEAR; + +param K_PERIOD; +param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR}; # cost + +param Yield_Table_Vol{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; + + +param Alpha >= 0; +param Beta >= 0; + +param TCost_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; + +param NetRev_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD}; + + +var XForestLand{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} >= 0; + + +#reading dbf tables +table tab IN "xBASE" "standtype.dbf": G_STAND_TYPE <- [STAND]; +display G_STAND_TYPE; + + +table tab2 IN "xBASE" "cultural_pres.dbf": I_CULTURAL_PRES <- [CUL_PRES]; +display I_CULTURAL_PRES; + +table tab3 IN "xBASE" "mgt_year.dbf": J_MGT_YEAR <- [MGT_YEAR]; +display J_MGT_YEAR; + +/* +param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR} default 0; # cost +*/ + +set S1, dimen 3; +table tab4 IN "xBASE" "Forest_Cost.dbf": S1 <- [STAND, CUL_PRES, MGT_YEAR],Forest_Cost ~FCOST; +display Forest_Cost; + +set S2, dimen 4; +table tab5 IN "xBASE" "Yield_Table_Vol.dbf": S2 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],Yield_Table_Vol ~YIELD; +display Yield_Table_Vol; + +set S3, dimen 4; +table tab5 IN "xBASE" "TCost_Table.dbf": S3 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],TCost_Table ~TCOST; +display TCost_Table; + + +set S4, dimen 4; +table tab5 IN "xBASE" "NetRev_Table.dbf": S4 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],NetRev_Table ~NETREV; +display NetRev_Table; + + +param MGT; + +param Area_Stand_Indi{g in G_STAND_TYPE, m in 1..MGT} default 0; + +set ST, dimen 2; +table tab5 IN "xBASE" "stands.dbf": ST <- [VEG_TYPE, MGT], Area_Stand_Indi ~ACRES; +display Area_Stand_Indi; + +param Area_Stand_Type{g in G_STAND_TYPE}:= sum {m in 1..MGT } Area_Stand_Indi[g,m]; +display Area_Stand_Type; + + +param Total_Area := sum {g in G_STAND_TYPE, m in 1..MGT } Area_Stand_Indi[g,m]; +display Total_Area; + +param Harvest_Min_Vol_Period; + + +var NetPresentValue; + +# Objective function +maximize Net_Present_Value: NetPresentValue; + +subject to NPV: + NetPresentValue = sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Forest_Cost[g,i,j] * XForestLand[g,i,j]; + +# Harvest Constraint by Period +subject to Harvest_Period_H {k in 1..K_PERIOD}: + sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] >= Harvest_Min_Vol_Period; + + +#Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha +subject to Even_Flow_Constaints_Alpha {k in 6..K_PERIOD-1}: + (1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - + sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] <= 0; + +# Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta +subject to Even_Flow_Constaints_Beta {k in 6..K_PERIOD-1}: + (1 + Beta) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - + sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] >= 0; + +# Forest / Land Constraints +subject to Total_Area_Constraint: + sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j] <= Total_Area; +display Total_Area; + +# Forest / Land Constraints for A B C +subject to Area {g in G_STAND_TYPE}: + sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j] = Area_Stand_Type[g]; + + + +solve; +#RESULT SECTION +printf '#################################\n'; +printf 'Forest Management Model I - Noli Sicad\n'; +printf '\n'; +printf 'Net Present Value = %.2f\n', NetPresentValue; +printf '\n'; + +printf '\n'; +printf 'Variables\n'; +printf 'Stand_Type Age_Class Mgt_Presc Sign Value \n'; +printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR}:'%5s %10s %11s = %10.2f\n', g,i,j, XForestLand[g,i,j]; +printf '\n'; + +printf 'Constraints\n'; +printf 'Period Harvest Sign \n'; +for {k in 1..K_PERIOD} { + printf '%5s %10.2f >= %.3f\n', k, sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j], Harvest_Min_Vol_Period; + } + +# xbase (dbf) output +table Harvest{k in 1..K_PERIOD} OUT "xBASE" "HarvestArea1.dbf" "N(5)N(15,2)" : k ~ Period, (sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]) ~ H_Area; + +# xbase (dbf) read +set S, dimen 2; +table tab2 IN "xBASE" "HarvestArea1.dbf": S <- [Period, H_Area]; +display S; + + + + +printf '\n'; +printf 'Constraint\n'; +printf 'Harvest Period\n'; +printf 'Type AgeClass PrescMgt Period Value\n'; +printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR, k in 1..K_PERIOD}:'%5s %11s %11s %5s %10.2f\n', g,i,j, k, (Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]); + + +printf 'Even_Flow_Constaint_Alpha (1-Alpha)\n'; +printf 'Period Sign \n'; +for {k in 6..K_PERIOD-1} { + printf "%s %10.2f <= %s\n", k, ((1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j]),0; + } +printf '\n'; + + +# Forest / Land Constraints +printf '\n'; +printf 'Total Area Constraint\n'; +printf 'Type AgeClass PrescMgt Value Sign Total_Area \n'; +printf '%5s <= %.3f\n',sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j], Total_Area; + +printf 'Area\n'; +printf 'Area Value Sign Areas_Stand\n'; +for {g in G_STAND_TYPE} { + printf '%5s %10.2f <= %.3f\n', g, sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j], Area_Stand_Type[g]; + } + + +#DATA SECTION + +data; + +# Most of the data has been moved to dbf format + +param MGT:=31; + +param K_PERIOD:= 7; + +param Alpha:= 0.20; +param Beta:= 0.20; + +param Harvest_Min_Vol_Period:= 12000; + +end; + diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Forest_Cost.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Forest_Cost.dbf new file mode 100644 index 000000000..acb8dcb19 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Forest_Cost.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/NetRev_Table.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/NetRev_Table.dbf new file mode 100644 index 000000000..6e6f2bd3a Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/NetRev_Table.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/README b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/README new file mode 100644 index 000000000..bbe9c3e71 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/README @@ -0,0 +1,2 @@ +This subdirectory contains an example MathProg model that demonstrates +using data tables in DBF format. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/TCost_Table.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/TCost_Table.dbf new file mode 100644 index 000000000..9a462c37a Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/TCost_Table.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Yield_Table_Vol.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Yield_Table_Vol.dbf new file mode 100644 index 000000000..b0d051ba7 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/Yield_Table_Vol.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/cultural_pres.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/cultural_pres.dbf new file mode 100644 index 000000000..76c8dfab5 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/cultural_pres.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/mgt_year.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/mgt_year.dbf new file mode 100644 index 000000000..043ba5a0d Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/mgt_year.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/stands.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/stands.dbf new file mode 100644 index 000000000..5ecfd2429 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/stands.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/standtype.dbf b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/standtype.dbf new file mode 100644 index 000000000..0306d5045 Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/dbf/standtype.dbf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dea.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/dea.mod new file mode 100644 index 000000000..ba610735a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/dea.mod @@ -0,0 +1,222 @@ +/* Data Envelopment Analysis (DEA) + * + * DEA quantifies the relative efficiency of decision making units (DMUs) by + * finding the efficient frontier in multiple input multiple output data. The + * inputs are resources (eg. number of employees, available machines, ...), + * the outputs are productive outputs (eg. contracts made, total sales, ...). + * The method is non-parametric. More details are available in the paper + * below. + * + * Models according to: Seiford, Threall, "Recent developments in DEA", 1990. + * + * Implementation: Sebastian Nowozin + */ + +### SETS ### + +set dmus; # Decision Making Units (DMU) +set inputs; # Input parameters +set outputs; # Output parameters + + +### PARAMETERS ### + +param input_data{dmus,inputs} >= 0; +param output_data{dmus,outputs} >= 0; + + +### PROGRAM ### + +var theta{dmus} >= 0; +var lambda{dmus,dmus} >= 0; + +minimize inefficiency: sum{td in dmus} theta[td]; + +s.t. output_lower_limit{o in outputs, td in dmus}: + sum{d in dmus} lambda[d,td]*output_data[d,o] >= output_data[td,o]; +s.t. input_upper_limit{i in inputs, td in dmus}: + sum{d in dmus} lambda[d,td]*input_data[d,i] <= theta[td]*input_data[td,i]; + + s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] = 1; +/* +possibilities: + i) (no constraint) + ii) s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] <= 1; + iii) s.t. PI1{td in dmus}: + sum{d in dmus} lambda[d,td] >= 1; +*/ + + +### SOLVE AND PRINT SOLUTION ### + +solve; + +printf "DMU\tEfficiency\n"; +for {td in dmus} { + printf "%s\t%1.4f\n", td, theta[td]; +} + +### DATA ### + +data; + +set dmus := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 + 61 62 63 64 65 66 67 68 69 ; +set inputs := AvgInventory LaborCost OperatingCost Population ; +set outputs := PrescrVol kDollarValue ; + +param input_data default 0.0 : + + AvgInventory LaborCost OperatingCost Population := + +1 8000 17030 1280 1410 +2 9000 25890 2779 1523 +3 13694 29076 2372 1354 +4 4250 17506 1385 822 +5 6500 23208 639 746 +6 7000 12946 802 1281 +7 4500 18001 1130 1016 +8 5000 14473 1097 1070 +9 27000 31760 5559 1694 +10 21560 50972 15010 1910 +11 15000 39523 4799 1745 +12 8500 13076 3489 1353 +13 35000 35427 1704 500 +14 18000 27554 2882 1016 +15 59750 53848 14208 2500 +16 19200 38253 1480 2293 +17 40000 109404 83016 2718 +18 8466 18198 1278 2877 +19 16000 40891 7599 4150 +20 10000 45444 5556 4421 +21 25000 35623 2121 3883 +22 14000 20192 5515 3519 +23 12500 34973 10475 32366 +24 17260 32284 14498 3393 +25 7000 17920 7585 4489 +26 14000 42094 3742 2217 +27 16400 35422 14236 4641 +28 13000 19100 3529 5968 +29 30000 72167 8656 8715 +30 12530 19970 1714 5968 +31 31500 39183 4919 5607 +32 10000 32048 3483 7324 +33 22000 68877 12279 8685 +34 10000 29812 3332 8685 +35 16000 47686 2507 5420 +36 10000 33415 4738 7703 +37 9000 12359 4603 4665 +38 16439 23614 2989 6317 +39 14500 36069 1793 31839 +40 39000 76307 9539 15619 +41 24927 40706 12661 30213 +42 13858 39267 4609 34719 +43 33375 29509 11323 31839 +44 29044 44482 5542 34719 +45 32257 61365 20550 32366 +46 8800 49671 3306 43561 +47 47000 40425 10396 31263 +48 12000 33034 4915 31263 +49 28000 69163 4688 15173 +50 13300 28931 16735 73064 +51 13500 29758 4260 62309 +52 24000 40927 8285 23166 +53 16000 40403 2131 99836 +54 17000 38730 2539 60348 +55 25000 35978 2502 99836 +56 16000 37509 6278 99836 +57 20000 46950 10715 85925 +58 14000 35966 3144 85925 +59 22000 68318 8015 108987 +60 21879 69537 7778 108987 +61 15000 25425 2812 201404 +62 10000 19508 2454 201404 +63 20000 28191 3367 201404 +64 18000 37073 8624 108987 +65 19051 23763 3496 201404 +66 15000 28642 3366 201404 +67 10000 35919 3868 201404 +68 24000 54653 26494 108987 +69 1800 6276 3413 60348 + ; + +param output_data default 0.0 : + + PrescrVol kDollarValue := + +1 12293 61.00 +2 18400 92.00 +3 16789 92.65 +4 10700 45.00 +5 9800 50.00 +6 6500 29.00 +7 8200 56.00 +8 8680 45.00 +9 33800 183.00 +10 23710 156.00 +11 24000 120.00 +12 17500 75.00 +13 25000 130.00 +14 26000 122.00 +15 26830 178.513 +16 16600 106.00 +17 90000 450.00 +18 11140 73.624 +19 25868 136.00 +20 32700 191.295 +21 29117 152.864 +22 18000 100.00 +23 11100 60.00 +24 23030 137.778 +25 10656 58.00 +26 24682 152.095 +27 26908 120.00 +28 16464 80.00 +29 57000 321.00 +30 17532 94.747 +31 30035 168.00 +32 16000 100.00 +33 63700 277.00 +34 18000 90.00 +35 27339 139.134 +36 19500 116.00 +37 13000 80.00 +38 15370 102.00 +39 18446 90.00 +40 56000 260.00 +41 73845 364.951 +42 28600 145.00 +43 27000 243.00 +44 52423 279.816 +45 73759 363.388 +46 20500 80.00 +47 27100 115.00 +48 15000 110.00 +49 50895 277.852 +50 19707 128.00 +51 17994 78.80 +52 36135 167.222 +53 30000 153.00 +54 26195 125.00 +55 28000 216.00 +56 24658 152.551 +57 36850 190.00 +58 29250 183.69 +59 50000 250.00 +60 40078 265.443 +61 20200 110.00 +62 12500 75.00 +63 30890 195.00 +64 31000 175.00 +65 31277 192.992 +66 11500 75.00 +67 30000 175.668 +68 38383 190.00 +69 2075 8.650 + ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/diet.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/diet.mod new file mode 100644 index 000000000..6d36391af --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/diet.mod @@ -0,0 +1,99 @@ +# STIGLER'S NUTRITION MODEL +# +# This model determines a least cost diet which meets the daily +# allowances of nutrients for a moderately active man weighing 154 lbs. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 27-1. + +set N; +/* nutrients */ + +set F; +/* foods */ + +param b{N}; +/* required daily allowances of nutrients */ + +param a{F,N}; +/* nutritive value of foods (per dollar spent) */ + +var x{f in F} >= 0; +/* dollars of food f to be purchased daily */ + +s.t. nb{n in N}: sum{f in F} a[f,n] * x[f] = b[n]; +/* nutrient balance (units) */ + +minimize cost: sum{f in F} x[f]; +/* total food bill (dollars) */ + +data; + +param : N : b := + Calorie 3 /* thousands */ + Protein 70 /* grams */ + Calcium 0.8 /* grams */ + Iron 12 /* milligrams */ + Vitamin-A 5 /* thousands IUs */ + Vitamin-B1 1.8 /* milligrams */ + Vitamin-B2 2.7 /* milligrams */ + Niacin 18 /* milligrams */ + Vitamin-C 75 /* milligrams */ ; + +set F := Wheat Cornmeal Cannedmilk Margarine Cheese Peanut-B Lard + Liver Porkroast Salmon Greenbeans Cabbage Onions Potatoes + Spinach Sweet-Pot Peaches Prunes Limabeans Navybeans; + +param a default 0 + +: Calorie Protein Calcium Iron Vitamin-A Vitamin-B1 := +# (1000) (g) (g) (mg) (1000IU) (mg) + +Wheat 44.7 1411 2.0 365 . 55.4 +Cornmeal 36 897 1.7 99 30.9 17.4 +Cannedmilk 8.4 422 15.1 9 26 3 +Margarine 20.6 17 .6 6 55.8 .2 +Cheese 7.4 448 16.4 19 28.1 .8 +Peanut-B 15.7 661 1 48 . 9.6 +Lard 41.7 . . . .2 . +Liver 2.2 333 .2 139 169.2 6.4 +Porkroast 4.4 249 .3 37 . 18.2 +Salmon 5.8 705 6.8 45 3.5 1 +Greenbeans 2.4 138 3.7 80 69 4.3 +Cabbage 2.6 125 4 36 7.2 9 +Onions 5.8 166 3.8 59 16.6 4.7 +Potatoes 14.3 336 1.8 118 6.7 29.4 +Spinach 1.1 106 . 138 918.4 5.7 +Sweet-Pot 9.6 138 2.7 54 290.7 8.4 +Peaches 8.5 87 1.7 173 86.8 1.2 +Prunes 12.8 99 2.5 154 85.7 3.9 +Limabeans 17.4 1055 3.7 459 5.1 26.9 +Navybeans 26.9 1691 11.4 792 . 38.4 + +: Vitamin-B2 Niacin Vitamin-C := +# (mg) (mg) (mg) + +Wheat 33.3 441 . +Cornmeal 7.9 106 . +Cannedmilk 23.5 11 60 +Margarine . . . +Cheese 10.3 4 . +Peanut-B 8.1 471 . +Lard .5 5 . +Liver 50.8 316 525 +Porkroast 3.6 79 . +Salmon 4.9 209 . +Greenbeans 5.8 37 862 +Cabbage 4.5 26 5369 +Onions 5.9 21 1184 +Potatoes 7.1 198 2522 +Spinach 13.8 33 2755 +Sweet-Pot 5.4 83 1912 +Peaches 4.3 55 57 +Prunes 4.3 65 257 +Limabeans 38.2 93 . +Navybeans 24.6 217 . ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/dist.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/dist.mod new file mode 100644 index 000000000..f3d66b513 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/dist.mod @@ -0,0 +1,565 @@ +# DIST, a product distribution model +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SHIPPING SETS AND PARAMETERS ### + +set whse 'warehouses'; # Locations from which demand is satisfied + +set dctr 'distribution centers' within whse; + + # Locations from which product may be shipped + +param sc 'shipping cost' {dctr,whse} >= 0; + + # Shipping costs, to whse from dctr, in $ / 100 lb + +param huge 'largest shipping cost' > 0; + + # Largest cost allowed for a usable shipping route + +param msr 'minimum size restriction' {dctr,whse} logical; + + # True indicates a minimum-size restriction on + # direct shipments using this dctr --> whse route + +param dsr 'direct shipment requirement' {dctr} >= 0; + + # Minimum total demand, in pallets, needed to + # allow shipment on routes subject to the + # minimum size restriction + +### PLANT SETS AND PARAMETERS ### + +set fact 'factories' within dctr; + + # Locations where product is manufactured + +param rtmin 'regular-time total minimum' >= 0; + + # Lower limit on (average) total regular-time + # crews employed at all factories + +param rtmax 'regular-time total maximum' >= rtmin; + + # Upper limit on (average) total regular-time + # crews employed at all factories + +param otmin 'overtime total minimum' >= 0; + + # Lower limit on total overtime hours at all factories + +param otmax 'overtime total maximum' >= otmin; + + # Upper limit on total overtime hours at all factories + +param rmin 'regular-time minimums' {fact} >= 0; + + # Lower limits on (average) regular-time crews + +param rmax 'regular-time maximums' {f in fact} >= rmin[f]; + + # Upper limits on (average) regular-time crews + +param omin 'overtime minimums' {fact} >= 0; + + # Lower limits on overtime hours + +param omax 'overtime maximums' {f in fact} >= omin[f]; + + # Upper limits on overtime hours + +param hd 'hours per day' {fact} >= 0; + + # Regular-time hours per working day + +param dp 'days in period' {fact} > 0; + + # Working days in the current planning period + +### PRODUCT SETS AND PARAMETERS ### + +set prd 'products'; # Elements of the product group + +param wt 'weight' {prd} > 0; + + # Weight in 100 lb / 1000 cases + +param cpp 'cases per pallet' {prd} > 0; + + # Cases of product per shipping pallet + +param tc 'transshipment cost' {prd} >= 0; + + # Transshipment cost in $ / 1000 cases + +param pt 'production time' {prd,fact} >= 0; + + # Crew-hours to produce 1000 cases + +param rpc 'regular-time production cost' {prd,fact} >= 0; + + # Cost of production on regular time, + # in $ / 1000 cases + +param opc 'overtime production cost' {prd,fact} >= 0; + + # Cost of production on overtime, in $ / 1000 cases + +### DEMAND SETS AND PARAMETERS ### + +param dt 'total demand' {prd} >= 0; + + # Total demands for products, in 1000s + +param ds 'demand shares' {prd,whse} >= 0.0, <= 1.0; + + # Historical demand data, from which each + # warehouse's share of total demand is deduced + +param dstot {p in prd} := sum {w in whse} ds[p,w]; + + # Total of demand shares; should be 1, but often isn't + +param dem 'demand' {p in prd, w in whse} := dt[p] * ds[p,w] / dstot[p]; + + # Projected demands to be satisfied, in 1000s + +set rt 'shipping routes available' := + + {d in dctr, w in whse: + d <> w and sc[d,w] < huge and + (w in dctr or sum {p in prd} dem[p,w] > 0) and + not (msr[d,w] and sum {p in prd} 1000*dem[p,w]/cpp[p] < dsr[d]) }; + + # List of ordered pairs that represent routes + # on which shipments are allowed + +### VARIABLES ### + +var Rprd 'regular-time production' {prd,fact} >= 0; + + # Regular-time production of each product + # at each factory, in 1000s of cases + +var Oprd 'overtime production' {prd,fact} >= 0; + + # Overtime production of each product + # at each factory, in 1000s of cases + +var Ship 'shipments' {prd,rt} >= 0; + + # Shipments of each product on each allowed route, + # in 1000s of cases + +var Trans 'transshipments' {prd,dctr} >= 0; + + # Transshipments of each product at each + # distribution center, in 1000s of cases + +### OBJECTIVE ### + +minimize cost: sum {p in prd, f in fact} rpc[p,f] * Rprd[p,f] + + sum {p in prd, f in fact} opc[p,f] * Oprd[p,f] + + sum {p in prd, (d,w) in rt} sc[d,w] * wt[p] * Ship[p,d,w] + + sum {p in prd, d in dctr} tc[p] * Trans[p,d]; + + # Total cost: regular production, overtime + # production, shipping, and transshipment + +### CONSTRAINTS ### + +rtlim 'regular-time total limits': + + rtmin <= sum {p in prd, f in fact} + (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rtmax; + + # Total crews must lie between limits + +otlim 'overtime total limits': + + otmin <= sum {p in prd, f in fact} pt[p,f] * Oprd[p,f] <= otmax; + + # Total overtime must lie between limits + +rlim 'regular-time limits' {f in fact}: + + rmin[f] <= sum {p in prd} + (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rmax[f]; + + # Crews at each factory must lie between limits + +olim 'overtime limits' {f in fact}: + + omin[f] <= sum {p in prd} pt[p,f] * Oprd[p,f] <= omax[f]; + + # Overtime at each factory must lie between limits + +noRprd 'no regular production' {p in prd, f in fact: rpc[p,f] = 0}: + + Rprd[p,f] = 0; + +noOprd 'no overtime production' {p in prd, f in fact: opc[p,f] = 0}: + + Oprd[p,f] = 0; # Do not produce where specified cost is zero + +bal 'material balance' {p in prd, w in whse}: + + sum {(v,w) in rt} + Ship [p,v,w] + (if w in fact then Rprd[p,w] + Oprd[p,w]) = + + dem[p,w] + (if w in dctr then sum {(w,v) in rt} Ship[p,w,v]); + + # Demand is satisfied by shipment into warehouse + # plus production (if it is a factory) + # minus shipment out (if it is a distn. center) + +trdef 'transshipment definition' {p in prd, d in dctr}: + + Trans[p,d] >= sum {(d,w) in rt} Ship [p,d,w] - + (if d in fact then Rprd[p,d] + Oprd[p,d]); + + # Transshipment at a distribution center is + # shipments out less production (if any) + +### DATA -- 3 PRODUCTS ### + +data; + +set prd := 18REG 24REG 24PRO ; + +set whse := w01 w02 w03 w04 w05 w06 w08 w09 w12 w14 w15 w17 + w18 w19 w20 w21 w24 w25 w26 w27 w28 w29 w30 w31 + w32 w33 w34 w35 w36 w37 w38 w39 w40 w41 w42 w43 + w44 w45 w46 w47 w48 w49 w50 w51 w53 w54 w55 w56 + w57 w59 w60 w61 w62 w63 w64 w65 w66 w68 w69 w71 + w72 w73 w74 w75 w76 w77 w78 w79 w80 w81 w82 w83 + w84 w85 w86 w87 w89 w90 w91 w92 w93 w94 w95 w96 + w98 x22 x23 ; + +set dctr := w01 w02 w03 w04 w05 w62 w76 w96 ; + +set fact := w01 w05 w96 ; + +param huge := 99. ; + +param rtmin := 0.0 ; +param rtmax := 8.0 ; + +param otmin := 0.0 ; +param otmax := 96.0 ; + +param rmin := w01 0.00 w05 0.00 w96 0.00 ; +param rmax := w01 3.00 w05 2.00 w96 3.00 ; + +param omin := w01 0.0 w05 0.0 w96 0.0 ; +param omax := w01 48.0 w05 0.0 w96 48.0 ; + +param hd := w01 8.0 w05 8.0 w96 8.0 ; + +param dp := w01 19.0 w05 19.0 w96 19.0 ; + +param wt := 18REG 47.3 24REG 63.0 24PRO 63.0 ; + +param tc := 18REG 40.00 24REG 45.00 24PRO 45.00 ; + +param dt := 18REG 376.0 24REG 172.4 24PRO 316.3 ; + +param cpp := 18REG 102. 24REG 91. 24PRO 91. ; + +param dsr := w01 96. w02 96. w03 96. w04 96. w05 96. + w62 96. w76 96. w96 96. ; + +param pt (tr) : + + 18REG 24REG 24PRO := + +w01 1.194 1.429 1.429 +w05 1.194 1.509 1.509 +w96 0.000 1.600 1.600 ; + +param rpc (tr) : + + 18REG 24REG 24PRO := + +w01 2119. 2653. 2617. +w05 2489. 3182. 3176. +w96 0. 2925. 2918. ; + +param opc (tr) : + + 18REG 24REG 24PRO := + +w01 2903. 3585. 3579. +w05 0. 0. 0. +w96 0. 3629. 3622. ; + +param sc default 99.99 (tr) : + + w01 w02 w03 w04 w05 w62 w76 w96 := + +w01 . 2.97 1.14 2.08 2.37 1.26 2.42 1.43 +w02 4.74 . 4.17 6.12 7.41 3.78 7.04 5.21 +w03 2.45 4.74 . 3.67 2.84 0.90 2.41 2.55 +w04 1.74 5.03 2.43 . 3.19 2.45 2.69 0.58 +w05 2.70 5.16 2.84 2.85 . 3.26 3.34 2.71 +w06 1.99 4.17 2.13 2.19 2.52 2.06 2.00 1.51 +w08 0.21 2.92 1.24 2.07 2.29 1.25 2.32 1.55 +w09 0.66 3.76 1.41 2.47 1.82 1.66 . 1.87 +w12 1.38 3.83 1.68 2.53 2.39 . 1.96 1.94 +w14 2.47 1.58 2.40 3.59 3.85 2.25 . 3.05 +w15 1.06 4.95 2.48 1.39 3.41 1.96 . 1.02 +w17 0.88 3.39 1.46 2.00 2.67 1.45 . 1.46 +w18 7.90 6.57 7.79 9.59 10.81 . . 6.70 +w19 1.42 4.12 1.96 1.99 3.52 1.88 . 1.26 +w20 3.03 1.59 2.34 4.76 3.98 1.88 . 3.73 +w24 1.58 2.80 2.27 2.87 3.19 1.31 . 2.05 +w25 1.51 5.05 2.74 0.57 2.98 . 2.95 0.27 +w26 1.75 3.61 2.70 1.54 4.07 3.52 . 1.03 +w27 2.48 6.87 3.17 1.59 2.08 3.45 . 0.99 +w28 2.05 6.83 2.97 1.13 2.91 . . 1.26 +w29 4.03 3.68 4.46 3.20 5.50 . . 3.20 +w30 2.48 5.78 2.99 2.24 1.79 3.10 . 1.39 +w31 2.34 5.41 2.87 1.67 1.66 . . 1.39 +w32 14.36 . . . . . . . +w33 3.87 4.27 5.11 3.48 5.66 4.03 . 3.05 +w34 3.26 4.80 3.21 2.70 4.14 . . 1.77 +w35 2.34 2.84 2.89 3.35 3.78 2.68 . 2.52 +w36 2.43 5.69 2.96 2.95 1.02 2.61 1.07 2.54 +w37 2.23 4.64 2.41 1.99 4.30 2.61 . 1.44 +w38 4.66 4.36 5.23 3.04 4.46 . . 3.82 +w39 1.11 3.51 1.10 2.53 3.07 1.12 . 2.23 +w40 2.99 4.78 4.23 1.57 3.92 . . 1.80 +w41 4.93 4.00 5.43 4.45 6.31 . . 3.81 +w42 3.86 6.55 5.03 2.11 4.41 . . 2.63 +w43 4.61 4.45 3.77 1.22 4.31 . . 2.35 +w44 2.05 4.48 1.06 3.70 3.46 1.10 . 3.21 +w45 0.92 3.42 1.58 3.04 1.82 1.94 . 2.52 +w46 1.36 2.44 0.95 3.08 2.78 0.39 2.16 2.37 +w47 1.30 3.39 1.60 2.49 4.29 2.04 . 1.68 +w48 1.65 3.78 1.03 2.97 2.21 1.31 . 2.74 +w49 1.96 3.00 1.50 3.24 3.68 1.00 . 2.99 +w50 0.90 4.14 1.60 1.95 3.61 1.61 . 1.52 +w51 1.59 3.95 0.25 2.96 2.58 1.00 2.41 2.71 +w53 1.59 3.79 1.28 3.12 3.10 0.89 . 2.98 +w54 1.72 4.36 1.61 2.92 2.34 1.91 1.97 3.05 +w55 2.45 2.73 2.21 4.47 4.30 2.57 . 4.48 +w56 1.10 3.73 1.59 2.74 2.33 1.45 . 2.44 +w57 0.95 3.39 1.37 2.30 2.47 1.15 . 1.95 +w59 3.29 5.35 3.32 3.81 1.52 3.38 1.34 4.08 +w60 2.41 6.12 2.46 3.65 2.35 . 1.37 4.06 +w61 3.32 5.50 3.41 3.38 1.23 . 0.99 4.28 +w62 1.12 3.00 0.82 3.22 2.95 . 3.33 2.53 +w63 3.59 6.36 3.25 4.12 1.84 3.59 1.46 4.03 +w64 1.85 4.45 2.17 3.43 2.13 2.03 . 4.02 +w65 2.78 4.79 2.81 2.94 1.54 2.90 1.07 2.94 +w66 3.90 5.79 3.05 3.65 1.36 3.39 1.22 3.57 +w68 2.61 5.20 2.90 2.34 1.68 3.19 1.48 2.31 +w69 2.94 5.21 2.78 3.43 0.21 3.26 0.68 2.54 +w71 2.06 4.98 2.38 2.44 1.59 2.97 1.05 2.55 +w72 2.61 5.50 2.83 3.12 1.35 3.23 0.88 2.99 +w73 8.52 6.16 8.03 8.83 10.44 7.38 10.26 . +w74 6.11 5.46 9.07 9.38 10.80 . . 8.25 +w75 2.66 4.94 2.87 3.69 1.52 3.15 1.24 4.00 +w76 1.99 5.26 2.23 3.36 0.58 3.17 . 2.50 +w77 4.32 3.07 5.05 3.88 6.04 . . 4.15 +w78 5.60 2.59 5.78 5.56 7.10 . . 5.60 +w79 4.25 2.32 4.93 4.57 6.04 . . 4.58 +w80 5.94 4.00 5.60 7.02 9.46 . . 7.51 +w81 5.39 2.21 5.10 6.22 6.46 . . 6.58 +w82 8.80 5.69 9.29 9.88 11.69 8.63 11.52 . +w83 4.40 . 5.24 5.21 5.81 3.91 7.04 5.33 +w84 5.87 5.43 6.17 5.70 7.63 . . 5.70 +w85 3.90 3.65 3.38 4.57 5.64 3.05 . 5.04 +w86 5.48 2.10 5.70 6.37 7.33 . . 6.19 +w87 8.88 5.54 9.50 9.71 11.64 8.85 11.68 . +w89 4.62 4.01 4.03 6.30 6.30 3.81 . 7.77 +w90 4.35 2.72 4.61 4.01 5.60 . . 3.20 +w91 7.61 4.42 7.83 6.85 8.79 . . 7.66 +w92 7.15 2.69 6.91 7.20 . . . 7.06 +w93 3.17 3.95 4.37 3.74 5.05 . . 2.40 +w94 1.21 3.07 0.90 2.74 3.17 . 2.63 2.39 +w95 5.82 3.29 6.55 7.06 11.47 . . 7.83 +w96 1.77 5.20 2.72 0.59 3.47 2.48 . . +w98 3.04 1.92 3.64 3.70 4.90 3.05 . 3.88 +x22 4.08 6.25 4.15 4.30 1.77 . 1.77 . +x23 3.39 5.74 3.55 4.08 1.69 . 1.47 . ; + +param msr (tr) : + + w01 w02 w03 w04 w05 w62 w76 w96 := + +w01 0 0 0 0 0 0 1 0 +w02 0 0 0 0 0 0 1 0 +w03 0 0 0 0 0 0 1 0 +w04 0 0 0 0 0 0 1 0 +w05 0 0 0 0 0 0 0 0 +w06 0 1 1 1 1 1 1 1 +w08 0 1 1 1 1 1 1 1 +w09 0 1 1 1 1 1 0 1 +w12 0 1 1 1 1 0 1 1 +w14 1 1 1 1 1 0 0 1 +w15 0 1 1 1 1 1 0 1 +w17 0 1 1 1 1 1 0 1 +w18 0 1 1 1 1 0 0 1 +w19 0 1 1 1 1 0 0 1 +w20 1 1 1 1 1 0 0 1 +w24 0 1 1 1 1 0 0 1 +w25 0 1 1 1 1 0 1 0 +w26 1 1 1 0 1 1 0 1 +w27 1 1 1 0 1 1 0 1 +w28 1 1 1 0 1 0 0 1 +w29 0 1 1 1 1 0 0 1 +w30 1 1 1 0 1 1 0 1 +w31 1 1 1 0 1 0 0 1 +w32 0 0 0 0 0 0 0 0 +w33 1 0 1 1 1 1 0 1 +w34 1 1 1 0 1 0 0 1 +w35 1 1 1 1 1 0 0 1 +w36 0 1 1 1 0 1 1 1 +w37 1 1 1 0 1 1 0 1 +w38 1 1 1 0 1 0 0 1 +w39 0 1 1 1 1 1 0 1 +w40 1 1 1 0 1 0 0 1 +w41 1 0 1 1 1 0 0 1 +w42 1 1 1 0 1 0 0 1 +w43 1 1 1 0 1 0 0 1 +w44 1 1 1 1 1 0 0 1 +w45 0 1 1 1 1 1 0 1 +w46 0 1 1 1 1 0 1 1 +w47 0 1 1 1 1 1 0 1 +w48 0 1 1 1 1 0 0 1 +w49 1 1 1 1 1 0 0 1 +w50 0 1 1 1 1 1 0 1 +w51 0 1 1 1 1 0 1 1 +w53 1 1 1 1 1 0 0 1 +w54 0 1 1 1 1 1 1 1 +w55 0 1 1 1 1 0 0 1 +w56 0 1 1 1 1 1 0 1 +w57 0 1 1 1 1 1 0 1 +w59 0 1 1 1 0 1 1 1 +w60 0 1 1 1 1 0 1 1 +w61 0 1 1 1 0 0 1 1 +w62 0 0 0 0 0 0 1 0 +w63 0 1 1 1 0 1 1 1 +w64 0 1 1 1 1 1 0 1 +w65 0 1 1 1 0 1 1 1 +w66 0 1 1 1 0 1 1 1 +w68 0 1 1 1 0 1 1 1 +w69 0 1 1 1 0 1 1 1 +w71 0 1 1 1 0 1 1 1 +w72 0 1 1 1 0 1 1 1 +w73 0 1 1 1 0 1 1 0 +w74 0 1 1 1 0 0 0 1 +w75 0 1 1 1 0 1 1 1 +w76 0 0 0 0 0 0 0 0 +w77 1 0 1 1 1 0 0 1 +w78 1 0 1 1 1 0 0 1 +w79 1 0 1 1 1 0 0 1 +w80 1 0 1 1 1 0 0 1 +w81 1 0 1 1 1 0 0 1 +w82 1 0 1 1 1 1 1 0 +w83 1 0 1 1 1 0 1 1 +w84 1 0 1 1 1 0 0 1 +w85 1 1 1 1 1 0 0 1 +w86 1 0 1 1 1 0 0 1 +w87 1 0 1 1 1 1 1 0 +w89 1 0 1 1 1 1 0 1 +w90 0 1 1 1 1 0 0 1 +w91 1 0 1 1 1 0 0 1 +w92 1 0 1 1 1 0 0 1 +w93 1 1 1 0 1 0 0 1 +w94 0 0 1 1 1 0 1 1 +w95 1 0 1 1 1 0 0 1 +w96 0 0 0 0 0 0 0 0 +w98 1 0 1 1 1 1 0 1 +x22 1 1 1 1 0 0 1 0 +x23 1 1 1 1 0 0 1 0 ; + +param ds default 0.000 (tr) : + + 18REG 24REG 24PRO := + +w01 0.000 0.000 0.008 +w02 0.004 0.000 0.000 +w03 0.000 0.000 0.000 +w04 0.010 0.002 0.000 +w05 0.000 0.000 0.000 +w06 0.010 0.008 0.008 +w08 0.030 0.024 0.024 +w09 0.014 0.018 0.020 +w12 0.014 0.012 0.010 +w14 0.007 0.007 0.012 +w15 0.010 0.019 0.018 +w17 0.013 0.010 0.011 +w19 0.015 0.012 0.009 +w20 0.012 0.021 0.022 +w21 0.000 0.000 0.000 +w24 0.012 0.022 0.018 +w25 0.019 0.025 0.020 +w26 0.006 0.015 0.021 +w27 0.008 0.010 0.015 +w28 0.011 0.016 0.019 +w29 0.008 0.020 0.013 +w30 0.011 0.013 0.015 +w31 0.011 0.013 0.017 +w32 0.006 0.000 0.000 +w33 0.000 0.015 0.014 +w34 0.008 0.007 0.005 +w35 0.002 0.006 0.014 +w36 0.015 0.013 0.005 +w37 0.017 0.016 0.015 +w38 0.015 0.009 0.012 +w39 0.007 0.017 0.022 +w40 0.009 0.014 0.020 +w41 0.003 0.014 0.011 +w42 0.017 0.011 0.012 +w43 0.009 0.013 0.011 +w44 0.002 0.012 0.012 +w45 0.016 0.025 0.028 +w46 0.038 0.062 0.040 +w47 0.007 0.010 0.010 +w48 0.003 0.015 0.016 +w49 0.005 0.016 0.017 +w50 0.011 0.008 0.007 +w51 0.010 0.022 0.021 +w53 0.004 0.026 0.020 +w54 0.020 0.017 0.025 +w55 0.004 0.019 0.028 +w56 0.004 0.010 0.008 +w57 0.014 0.020 0.018 +w59 0.012 0.006 0.007 +w60 0.019 0.010 0.009 +w61 0.028 0.010 0.012 +w62 0.000 0.000 0.000 +w63 0.070 0.027 0.037 +w64 0.009 0.004 0.005 +w65 0.022 0.015 0.016 +w66 0.046 0.017 0.020 +w68 0.005 0.012 0.016 +w69 0.085 0.036 0.039 +w71 0.011 0.013 0.010 +w72 0.089 0.031 0.034 +w75 0.026 0.012 0.010 +w77 0.001 0.004 0.002 +w78 0.002 0.004 0.002 +w79 0.001 0.004 0.002 +w80 0.001 0.001 0.002 +w81 0.001 0.003 0.002 +w83 0.009 0.010 0.008 +w84 0.001 0.002 0.002 +w85 0.001 0.004 0.005 +w86 0.001 0.002 0.002 +w87 0.002 0.003 0.000 +w89 0.001 0.001 0.002 +w90 0.006 0.017 0.013 +w91 0.002 0.010 0.013 +w92 0.000 0.003 0.002 +w93 0.002 0.006 0.007 +w95 0.001 0.007 0.007 +w96 0.000 0.000 0.000 +w98 0.006 0.005 0.002 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/egypt.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/egypt.mod new file mode 100644 index 000000000..b051d4a73 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/egypt.mod @@ -0,0 +1,519 @@ +# EGYPT, a static model of fertilizer production +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SETS ### + +set center; # Locations from which final product may be shipped +set port within center; # Locations at which imports can be received +set plant within center; # Locations of plants + +set region; # Demand regions + +set unit; # Productive units +set proc; # Processes + +set nutr; # Nutrients + +set c_final; # Final products (fertilizers) +set c_inter; # Intermediate products +set c_ship within c_inter; # Intermediates for shipment +set c_raw; # Domestic raw materials and miscellaneous inputs + +set commod := c_final union c_inter union c_raw; + + # All commodities + +### PARAMETERS ### + +param cf75 {region,c_final} >= 0; + + # Consumption of fertilizer 1974-75 (1000 tpy) + +param fn {c_final,nutr} >= 0; + + # Nutrient content of fertilizers + +param cn75 {r in region, n in nutr} := sum {c in c_final} cf75[r,c] * fn[c,n]; + + # Consumption of nutrients 1974-75 (1000 tpy) + +param road {region,center} >= 0; + + # Road distances + +param rail_half {plant,plant} >= 0; +param rail {p1 in plant, p2 in plant} := + if rail_half[p1,p2] > 0 then rail_half[p1,p2] else rail_half[p2,p1]; + + # Interplant rail distances (kms) + +param impd_barg {plant} >= 0; +param impd_road {plant} >= 0; + + # Import distances (kms) by barge and road + +param tran_final {pl in plant, r in region} := + if road[r,pl] > 0 then .5 + .0144 * road[r,pl] else 0; + +param tran_import {r in region, po in port} := + if road[r,po] > 0 then .5 + .0144 * road[r,po] else 0; + +param tran_inter {p1 in plant, p2 in plant} := + if rail[p1,p2] > 0 then 3.5 + .03 * rail[p1,p2] else 0; + +param tran_raw {pl in plant} := + (if impd_barg[pl] > 0 then 1.0 + .0030 * impd_barg[pl] else 0) + + (if impd_road[pl] > 0 then 0.5 + .0144 * impd_road[pl] else 0); + + # Transport cost (le per ton) for: + # final products, imported final products, + # interplant shipment, imported raw materials + +param io {commod,proc}; # Input-output coefficients + +param util {unit,proc} >= 0; + + # Capacity utilization coefficients + +param p_imp {commod} >= 0; # Import Price (cif US$ per ton 1975) + +param p_r {c_raw} >= 0; +param p_pr {plant,c_raw} >= 0; + +param p_dom {pl in plant, c in c_raw} := + if p_r[c] > 0 then p_r[c] else p_pr[pl,c]; + + # Domestic raw material prices + +param dcap {plant,unit} >= 0; + + # Design capacity of plants (t/day) + +param icap {u in unit, pl in plant} := 0.33 * dcap[pl,u]; + + # Initial capacity of plants (t/day) + +param exch := 0.4; # Exchange rate + +param util_pct := 0.85; # Utilization percent for initial capacity + +### DERIVED SETS OF "POSSIBILITIES" ### + +set m_pos {pl in plant} := {u in unit: icap[u,pl] > 0}; + + # At each plant, set of units for which there is + # initial capacity + +set p_cap {pl in plant} := + {pr in proc: forall {u in unit: util[u,pr] > 0} u in m_pos[pl] }; + + # At each plant, set of processes for which + # all necessary units have some initial capacity + +set p_except {plant} within proc; + + # At each plant, list of processes that are + # arbitrarily ruled out + +set p_pos {pl in plant} := p_cap[pl] diff p_except[pl]; + + # At each plant, set of possible processes + +set cp_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] > 0}; + +set cc_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] < 0}; + +set c_pos {c in commod} := cp_pos[c] union cc_pos[c]; + + # For each commodity, set of plants that can + # produce it (cp_pos) or consume it (cc_pos), + # and their union (c_pos) + +### VARIABLES ### + +var Z {pl in plant, p_pos[pl]} >= 0; + + # Z[pl,pr] is level of process pr at plant pl + +var Xf {c in c_final, cp_pos[c], region} >= 0; + + # Xf[c,pl,r] is amount of final product c + # shipped from plant pl to region r + +var Xi {c in c_ship, cp_pos[c], cc_pos[c]} >= 0; + + # Xi[c,p1,p2] is amount of intermediate c + # shipped from plant p1 to plant p2 + +var Vf {c_final,region,port} >= 0; + + # Vf[c,r,po] is amount of final product c + # imported by region r from port po + +var Vr {c in c_raw, cc_pos[c]} >= 0; + + # Vr[c,pl] is amount of raw material c + # imported for use at plant pl + +var U {c in c_raw, cc_pos[c]} >= 0; + + # U[c,pl] is amount of raw material c + # purchased domestically for use at plant pl + +var Psip; # Domestic recurrent cost +var Psil; # Transport cost +var Psii; # Import cost + +### OBJECTIVE ### + +minimize Psi: Psip + Psil + Psii; + +### CONSTRAINTS ### + +subject to mbd {n in nutr, r in region}: + + sum {c in c_final} fn[c,n] * + (sum {po in port} Vf[c,r,po] + + sum {pl in cp_pos[c]} Xf[c,pl,r]) >= cn75[r,n]; + + # Total nutrients supplied to a region by all + # final products (sum of imports plus internal + # shipments from plants) must meet requirements + +subject to mbdb {c in c_final, r in region: cf75[r,c] > 0}: + + sum {po in port} Vf[c,r,po] + + sum {pl in cp_pos[c]} Xf[c,pl,r] >= cf75[r,c]; + + # Total of each final product supplied to each + # region (as in previous constraint) must meet + # requirements + +subject to mb {c in commod, pl in plant}: + + sum {pr in p_pos[pl]} io[c,pr] * Z[pl,pr] + + + ( if c in c_ship then + ( if pl in cp_pos[c] then sum {p2 in cc_pos[c]} Xi[c,pl,p2] ) + - ( if pl in cc_pos[c] then sum {p2 in cp_pos[c]} Xi[c,p2,pl] )) + + + ( if (c in c_raw and pl in cc_pos[c]) then + (( if p_imp[c] > 0 then Vr[c,pl] ) + + ( if p_dom[pl,c] > 0 then U[c,pl] ))) + + >= if (c in c_final and pl in cp_pos[c]) then sum {r in region} Xf[c,pl,r]; + + # For each commodity at each plant: sum of + # (1) production or consumption at plant, + # (2) inter-plant shipments in or out, + # (3) import and domestic purchases (raw only) + # is >= 0 for raw materials and intermediates; + # is >= the total shipped for final products + +subject to cc {pl in plant, u in m_pos[pl]}: + + sum {pr in p_pos[pl]} util[u,pr] * Z[pl,pr] <= util_pct * icap[u,pl]; + + # For each productive unit at each plant, + # total utilization by all processes + # may not exceed the unit's capacity + +subject to ap: + + Psip = sum {c in c_raw, pl in cc_pos[c]} p_dom[pl,c] * U[c,pl]; + + # Psip is the cost of domestic raw materials, + # summed over all plants that consume them + +subject to al: + + Psil = sum {c in c_final} ( + + sum {pl in cp_pos[c], r in region} + tran_final[pl,r] * Xf[c,pl,r] + + + sum {po in port, r in region} tran_import[r,po] * Vf[c,r,po] ) + + + sum {c in c_ship, p1 in cp_pos[c], p2 in cc_pos[c]} + tran_inter[p1,p2] * Xi[c,p1,p2] + + + sum {c in c_raw, pl in cc_pos[c]: p_imp[c] > 0} + tran_raw[pl] * Vr[c,pl]; + + # Total transport cost is sum of shipping costs for + # (1) all final products from all plants, + # (2) all imports of final products, + # (3) all intermediates shipped between plants, + # (4) all imports of raw materials + +subject to ai: + + Psii / exch = sum {c in c_final, r in region, po in port} + p_imp[c] * Vf[c,r,po] + + + sum {c in c_raw, pl in cc_pos[c]} p_imp[c] * Vr[c,pl]; + + # Total import cost -- at exchange rate -- + # is sum of import costs for final products + # in each region and raw materials at each plant + +### DATA ### + +data; + +set center := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ABU_KIR TALKHA SUEZ ; + +set port := ABU_KIR ; + +set plant := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ; + +set region := ALEXANDRIA BEHERA GHARBIA KAFR_EL_SH DAKAHLIA DAMIETTA + SHARKIA ISMAILIA SUEZ MENOUFIA KALUBIA GIZA BENI_SUEF FAYOUM + MINIA ASSIOUT NEW_VALLEY SOHAG QUENA ASWAN ; + +set unit := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS C_AMM_NITR + AMM_SULF SSP ; + +set proc := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS CAN_310 CAN_335 + AMM_SULF SSP_155 ; + +set nutr := N P205 ; + +set c_final := UREA CAN_260 CAN_310 CAN_335 AMM_SULF DAP SSP_155 C_250_55 + C_300_100 ; + +set c_inter := AMMONIA NITR_ACID SULF_ACID ; + +set c_ship := AMMONIA SULF_ACID ; + +set c_raw := EL_ASWAN COKE_GAS PHOS_ROCK LIMESTONE EL_SULFUR PYRITES + ELECTRIC BF_GAS WATER STEAM BAGS ; + +set p_except[ASWAN] := CAN_335 ; +set p_except[HELWAN] := CAN_310 ; +set p_except[ASSIOUT] := ; +set p_except[KAFR_EL_ZT] := ; +set p_except[ABU_ZAABAL] := ; + +param cf75 default 0.0 : + + CAN_260 CAN_310 CAN_335 AMM_SULF UREA := + +ALEXANDRIA . . 5.0 3.0 1.0 +ASSIOUT 1.0 20.0 26.0 1.0 27.0 +ASWAN . 40.0 . . . +BEHERA 1.0 . 25.0 90.0 35.0 +BENI_SUEF 1.0 . 15.0 1.0 20.0 +DAKAHLIA 1.0 . 26.0 60.0 20.0 +DAMIETTA . . 2.0 15.0 8.0 +FAYOUM 1.0 . 20.0 6.0 20.0 +GHARBIA . . 17.0 60.0 28.0 +GIZA . . 40.0 6.0 2.0 +ISMAILIA . . 4.0 6.0 2.0 +KAFR_EL_SH 1.0 . 10.0 45.0 22.0 +KALUBIA . . 25.0 16.0 7.0 +MENOUFIA 1.0 . 24.0 21.0 30.0 +MINIA 2.0 15.0 35.0 1.0 41.0 +NEW_VALLEY . . . . 1.0 +QUENA . 95.0 2.0 . 3.0 +SHARKIA 1.0 . 31.0 50.0 28.0 +SOHAG . 65.0 3.0 . 7.0 +SUEZ . . 1.0 . . + + : SSP_155 C_250_55 C_300_100 DAP := + +ALEXANDRIA 8.0 . . . +ASSIOUT 35.0 5.0 .1 . +ASWAN 8.0 . . . +BEHERA 64.0 1.0 .1 .1 +BENI_SUEF 13.0 3.0 . . +DAKAHLIA 52.0 1.0 . . +DAMIETTA 5.0 . . . +FAYOUM 17.0 1.0 . . +GHARBIA 57.0 1.0 .2 .1 +GIZA 14.0 1.0 .1 . +ISMAILIA 4.0 . . . +KAFR_EL_SH 25.0 2.0 .1 . +KALUBIA 22.0 1.0 . .1 +MENOUFIA 33.0 2.0 .1 .1 +MINIA 50.0 3.0 .2 .1 +NEW_VALLEY 1.0 . . . +QUENA 8.0 . . . +SHARKIA 43.0 1.0 .1 . +SOHAG 20.0 1.0 . . +SUEZ 1.0 . . . ; + +param fn default 0.0 : N P205 := + + AMM_SULF .206 . + CAN_260 .26 . + CAN_310 .31 . + CAN_335 .335 . + C_250_55 .25 .055 + C_300_100 .30 .10 + DAP .18 .46 + SSP_155 . .15 + UREA .46 . ; + +param road default 0.0 : + + ABU_KIR ABU_ZAABAL ASSIOUT ASWAN HELWAN KAFR_EL_ZT SUEZ TALKHA := + +ALEXANDRIA 16 210 607 1135 244 119 362 187 +ASSIOUT 616 420 . 518 362 504 527 518 +ASWAN 1134 938 518 . 880 1022 1045 1036 +BEHERA 76 50 547 1065 184 42 288 120 +BENI_SUEF 359 163 257 775 105 248 270 261 +DAKAHLIA 208 138 515 1033 152 58 219 3 +DAMIETTA 267 216 596 1114 233 131 286 66 +FAYOUM 341 145 308 826 88 230 252 243 +GHARBIA 150 65 485 1003 122 20 226 55 +GIZA 287 48 372 890 .9 133 169 146 +ISMAILIA 365 142 536 1054 173 241 89 146 +KAFR_EL_SH 145 105 525 1043 162 20 266 35 +KALUBIA 190 97 439 957 76 66 180 81 +MENOUFIA 157 154 472 990 109 33 213 90 +MINIA 384 288 132 650 230 372 394 386 +NEW_VALLEY 815 619 199 519 561 703 726 717 +QUENA 858 662 242 276 604 746 769 760 +SHARKIA 240 60 473 991 110 78 214 58 +SOHAG 715 519 99 419 461 603 626 617 +SUEZ 370 224 541 1059 178 246 . 298 ; + +param rail_half default 0 : + + KAFR_EL_ZT ABU_ZAABAL HELWAN ASSIOUT := + +ABU_ZAABAL 85 . . . +HELWAN 142 57 . . +ASSIOUT 504 420 362 . +ASWAN 1022 938 880 518 ; + +param : impd_barg impd_road := + +ABU_ZAABAL 210 .1 +ASSIOUT 583 0 +ASWAN 1087 10 +HELWAN 183 0 +KAFR_EL_ZT 104 6 ; + +param io default 0.0 := + + [*,AMM_C_GAS] AMMONIA 1.0 + BF_GAS -609. + COKE_GAS -2.0 + ELECTRIC -1960. + STEAM -4. + WATER -700. + + [*,AMM_ELEC] AMMONIA 1.0 + EL_ASWAN -12.0 + + [*,AMM_SULF] AMMONIA -.26 + AMM_SULF 1.0 + BAGS -22. + ELECTRIC -19. + SULF_ACID -.76 + WATER -17. + + [*,CAN_310] AMMONIA -.20 + BAGS -23. + CAN_310 1.0 + LIMESTONE -.12 + NITR_ACID -.71 + STEAM -.4 + WATER -49. + + [*,CAN_335] AMMONIA -.21 + BAGS -23. + CAN_335 1.0 + LIMESTONE -.04 + NITR_ACID -.76 + STEAM -.4 + WATER -49. + + [*,NITR_ACID] AMMONIA -.292 + ELECTRIC -231. + NITR_ACID 1.0 + WATER -.6 + + [*,SSP_155] BAGS -22. + ELECTRIC -14. + PHOS_ROCK -.62 + SSP_155 1.0 + SULF_ACID -.41 + WATER -6. + + [*,SULF_A_P] ELECTRIC -75. + PYRITES -.826 + SULF_ACID 1.0 + WATER -60. + + [*,SULF_A_S] ELECTRIC -50. + EL_SULFUR -.334 + SULF_ACID 1.0 + WATER -20. ; + +param util default 0 := + + [*,*] SULF_A_S SULF_A_S 1 SULF_A_P SULF_A_P 1 + NITR_ACID NITR_ACID 1 AMM_ELEC AMM_ELEC 1 + AMM_C_GAS AMM_C_GAS 1 SSP SSP_155 1 + C_AMM_NITR CAN_310 1 C_AMM_NITR CAN_335 1 + AMM_SULF AMM_SULF 1 ; + +param p_imp default 0.0 := + + PYRITES 17.5 AMM_SULF 75. + EL_SULFUR 55. DAP 175. + UREA 150. SSP_155 80. + CAN_260 75. C_250_55 100. + CAN_310 90. C_300_100 130. + CAN_335 100. ; + +param p_r default 0.0 := + + ELECTRIC .007 + BF_GAS .007 + WATER .031 + STEAM 1.25 + BAGS .28 ; + +param p_pr default 0.0 := + + [HELWAN,COKE_GAS] 16.0 + [ASWAN,EL_ASWAN] 1.0 + + [*,LIMESTONE] ASWAN 1.2 + HELWAN 1.2 + + [*,PHOS_ROCK] ABU_ZAABAL 4.0 + ASSIOUT 3.5 + KAFR_EL_ZT 5.0 ; + +param dcap default 0.0 := + + [ABU_ZAABAL,*] SSP 600 + SULF_A_P 227 + SULF_A_S 242 + + [ASSIOUT,*] SSP 600 + SULF_A_S 250 + + [ASWAN,*] AMM_ELEC 450 + C_AMM_NITR 1100 + NITR_ACID 800 + + [HELWAN,*] AMM_C_GAS 172 + AMM_SULF 24 + C_AMM_NITR 364 + NITR_ACID 282 + + [KAFR_EL_ZT,*] SSP 600 + SULF_A_P 50 + SULF_A_S 200 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/fctp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/fctp.mod new file mode 100644 index 000000000..9d6382da6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/fctp.mod @@ -0,0 +1,93 @@ +/* FCTP, Fixed-Charge Transportation Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Fixed-Charge Transportation Problem (FCTP) is obtained from + classical transportation problem by imposing a fixed cost on each + transportation link if there is a positive flow on that link. */ + +param m, integer, > 0; +/* number of sources */ + +param n, integer, > 0; +/* number of customers */ + +set I := 1..m; +/* set of sources */ + +set J := 1..n; +/* set of customers */ + +param supply{i in I}, >= 0; +/* supply at source i */ + +param demand{j in J}, >= 0; +/* demand at customer j */ + +param varcost{i in I, j in J}, >= 0; +/* variable cost (a cost per one unit shipped from i to j) */ + +param fixcost{i in I, j in J}, >= 0; +/* fixed cost (a cost for shipping any amount from i to j) */ + +var x{i in I, j in J}, >= 0; +/* amount shipped from source i to customer j */ + +s.t. f{i in I}: sum{j in J} x[i,j] = supply[i]; +/* observe supply at source i */ + +s.t. g{j in J}: sum{i in I} x[i,j] = demand[j]; +/* satisfy demand at customer j */ + +var y{i in I, j in J}, binary; +/* y[i,j] = 1 means some amount is shipped from i to j */ + +s.t. h{i in I, j in J}: x[i,j] <= min(supply[i], demand[j]) * y[i,j]; +/* if y[i,j] is 0, force x[i,j] to be 0 (may note that supply[i] and + demand[j] are implicit upper bounds for x[i,j] as follows from the + constraints f[i] and g[j]) */ + +minimize cost: sum{i in I, j in J} varcost[i,j] * x[i,j] + + sum{i in I, j in J} fixcost[i,j] * y[i,j]; +/* total transportation costs */ + +data; + +/* These data correspond to the instance bal8x12 from [Balinski]. */ + +/* The optimal solution is 471.55 */ + +param m := 8; + +param n := 12; + +param supply := 1 15.00, 2 20.00, 3 45.00, 4 35.00, + 5 25.00, 6 35.00, 7 10.00, 8 25.00; + +param demand := 1 20.00, 2 15.00, 3 20.00, 4 15.00, + 5 5.00, 6 20.00, 7 30.00, 8 10.00, + 9 35.00, 10 25.00, 11 10.00, 12 5.00; + +param varcost + : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 0.69 0.64 0.71 0.79 1.70 2.83 2.02 5.64 5.94 5.94 5.94 7.68 + 2 1.01 0.75 0.88 0.59 1.50 2.63 2.26 5.64 5.85 5.62 5.85 4.94 + 3 1.05 1.06 1.08 0.64 1.22 2.37 1.66 5.64 5.91 5.62 5.91 4.94 + 4 1.94 1.50 1.56 1.22 1.98 1.98 1.36 6.99 6.99 6.99 6.99 3.68 + 5 1.61 1.40 1.61 1.33 1.68 2.83 1.54 4.26 4.26 4.26 4.26 2.99 + 6 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.31 0.21 0.17 0.31 1.53 + 7 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.55 0.35 0.40 0.19 1.53 + 8 5.29 6.08 6.08 5.29 5.96 6.45 5.08 2.43 2.30 2.33 1.81 2.50 ; + +param fixcost + : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 11.0 16.0 18.0 17.0 10.0 20.0 17.0 13.0 15.0 12.0 14.0 14.0 + 2 14.0 17.0 17.0 13.0 15.0 13.0 16.0 11.0 20.0 11.0 15.0 10.0 + 3 12.0 13.0 20.0 17.0 13.0 15.0 16.0 13.0 12.0 13.0 10.0 18.0 + 4 16.0 19.0 16.0 11.0 15.0 12.0 18.0 12.0 18.0 13.0 13.0 14.0 + 5 19.0 18.0 15.0 16.0 12.0 14.0 20.0 19.0 11.0 17.0 16.0 18.0 + 6 13.0 20.0 20.0 17.0 15.0 12.0 14.0 11.0 12.0 19.0 15.0 16.0 + 7 11.0 12.0 15.0 10.0 17.0 11.0 11.0 16.0 10.0 18.0 17.0 12.0 + 8 17.0 10.0 20.0 12.0 17.0 20.0 16.0 15.0 10.0 12.0 16.0 18.0 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/food.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/food.mod new file mode 100644 index 000000000..cb1aa05ad --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/food.mod @@ -0,0 +1,127 @@ +/* Food Manufacture 1, section 12.1 in + * Williams, "Model Building in Mathematical Programming" + * + * Sebastian Nowozin + */ + +set oils; +set month; + +/* Buying prices of the raw oils in the next six month. */ +param buyingprices{month,oils}; + +/* Actual amount bought in each month. */ +var buys{month,oils} >= 0; + +/* Stock for each oil. */ +var stock{month,oils} >= 0; + +/* Price of the produced product */ +param productprice >= 0; +param storagecost; + +param oilhardness{oils} >= 0; + +/* Actual amount of output oil produced in each month */ +var production{m in month} >= 0; +var useoil{m in month, o in oils} >= 0; + +maximize totalprofit: + sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]; + +/* Constraints */ + +/* 1. Starting stock */ +s.t. startstock{o in oils}: + stock[1,o] = 500; +s.t. endstock{o in oils}: + stock[6,o] + buys[6,o] - useoil[6,o] >= 500; + +/* 2. Stock constraints */ +s.t. stocklimit{m in month, o in oils}: + stock[m,o] <= 1000; + +s.t. production1{m in month, o in oils}: + useoil[m,o] <= stock[m,o] + buys[m,o]; +s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: + stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; + +s.t. production3a{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; +s.t. production3b{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; + +s.t. production4{m in month}: + production[m] = sum{o in oils} useoil[m,o]; + +/* 3. Refining constraints */ +s.t. refine1{m in month}: + useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; +s.t. refine2{m in month}: + useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; + +solve; + +for {m in month} { + printf "Month %d\n", m; + printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], + (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); + + printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; + printf "STOCK"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", stock[m,o]; + } + printf "\nBUY"; + for {o in oils} { + printf "\t%4.2f", buys[m,o]; + } + printf "\nUSE"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", useoil[m,o]; + } + printf "\n"; + printf "\n"; +} +printf "Total profit: %4.2f\n", + (sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]); +printf " turnover: %4.2f\n", + sum{m in month} productprice*production[m]; +printf " buying costs: %4.2f\n", + sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; +printf " storage costs: %4.2f\n", + sum{m in month, o in oils} storagecost*stock[m,o]; + + +data; + +param : oils : oilhardness := + VEG1 8.8 + VEG2 6.1 + OIL1 2.0 + OIL2 4.2 + OIL3 5.0 ; + +set month := 1 2 3 4 5 6; + +param buyingprices + +: VEG1 VEG2 OIL1 OIL2 OIL3 := + +1 110 120 130 110 115 +2 130 130 110 90 115 +3 110 140 130 100 95 +4 120 110 120 120 125 +5 100 120 150 110 105 +6 90 100 140 80 135 ; + +param productprice := 150; +param storagecost := 5; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/food2.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/food2.mod new file mode 100644 index 000000000..694b59462 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/food2.mod @@ -0,0 +1,150 @@ +/* Food Manufacture 2, section 12.2 in + * Williams, "Model Building in Mathematical Programming" + * + * Sebastian Nowozin + */ + +set oils; +set month; + +/* Buying prices of the raw oils in the next six month. */ +param buyingprices{month,oils}; + +/* Actual amount bought in each month. */ +var buys{month,oils} >= 0; + +/* Stock for each oil. */ +var stock{month,oils} >= 0; + +/* Price of the produced product */ +param productprice >= 0; +param storagecost; + +param oilhardness{oils} >= 0; +param M >= 0; + +/* Actual amount of output oil produced in each month */ +var production{m in month} >= 0; +var useoil{m in month, o in oils} >= 0, <= M; +var useoilb{m in month, o in oils}, binary; + +maximize totalprofit: + sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]; + +/* Constraints */ + +/* 1. Starting stock */ +s.t. startstock{o in oils}: + stock[1,o] = 500; +s.t. endstock{o in oils}: + stock[6,o] + buys[6,o] - useoil[6,o] >= 500; + +/* 2. Stock constraints */ +s.t. stocklimit{m in month, o in oils}: + stock[m,o] <= 1000; + +s.t. production1{m in month, o in oils}: + useoil[m,o] <= stock[m,o] + buys[m,o]; +s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: + stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; + +s.t. production3a{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; +s.t. production3b{m in month}: + sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; + +s.t. production4{m in month}: + production[m] = sum{o in oils} useoil[m,o]; + +/* 3. Refining constraints */ +s.t. refine1{m in month}: + useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; +s.t. refine2{m in month}: + useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; + +/* 4. Additional conditions: + * i) The food may never be made up of more than three oils every month + */ +s.t. useoilb_calc{m in month, o in oils}: + M*useoilb[m,o] >= useoil[m,o]; +s.t. useoilb_limit{m in month}: + sum{o in oils} useoilb[m,o] <= 3; + +/* ii) If an oil is used in a month, at least 20 tons must be used. + */ +s.t. useminimum{m in month, o in oils}: + 20*useoilb[m,o] <= useoil[m,o]; + +/* iii) If either of VEG1 or VEG2 is used in a month, OIL2 must also be used + */ +s.t. use_oil2a{m in month}: + useoilb[m,"VEG1"] <= useoilb[m,"OIL3"]; +s.t. use_oil2b{m in month}: + useoilb[m,"VEG2"] <= useoilb[m,"OIL3"]; + +solve; + +for {m in month} { + printf "Month %d\n", m; + printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], + (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); + + printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; + printf "STOCK"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", stock[m,o]; + } + printf "\nBUY"; + for {o in oils} { + printf "\t%4.2f", buys[m,o]; + } + printf "\nUSE"; + printf "%d", m; + for {o in oils} { + printf "\t%4.2f", useoil[m,o]; + } + printf "\n"; + printf "\n"; +} +printf "Total profit: %4.2f\n", + (sum{m in month} productprice*production[m] + - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] + - sum{m in month, o in oils} storagecost*stock[m,o]); +printf " turnover: %4.2f\n", + sum{m in month} productprice*production[m]; +printf " buying costs: %4.2f\n", + sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; +printf " storage costs: %4.2f\n", + sum{m in month, o in oils} storagecost*stock[m,o]; + + +data; + +param : oils : oilhardness := + VEG1 8.8 + VEG2 6.1 + OIL1 2.0 + OIL2 4.2 + OIL3 5.0 ; + +set month := 1 2 3 4 5 6; + +param buyingprices + +: VEG1 VEG2 OIL1 OIL2 OIL3 := + +1 110 120 130 110 115 +2 130 130 110 90 115 +3 110 140 130 100 95 +4 120 110 120 120 125 +5 100 120 150 110 105 +6 90 100 140 80 135 ; + +param productprice := 150; +param storagecost := 5; +param M := 1000; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/furnace.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/furnace.mps new file mode 100644 index 000000000..b89b7acbd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/furnace.mps @@ -0,0 +1,164 @@ +*NAME: FURNACE +*ROWS: 18 +*COLUMNS: 18 +*NONZERO: 90 +*OPT SOLN: 2141.923551 +*SOURCE: Linear Programming--Electric-Arc Furnace Steelmaking +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Electric-Arc Furnace Steelmaking +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME FURNACE +ROWS + N VALUE $ Price per pound (of initial charge materials) + E CR $ Chromium + E MN $ Manganese + E SI $ Silicon + E C $ Carbon + E FE $ Iron + E TOTCHG $ Total elements charged + E CRSLAG $ Chromium-oxidized-to-slag relationship + E TOTCRS $ Total modified chromium specification constraint + E MN/CR $ Total manganese specification constraint + E FESLAG $ Iron-oxidized-to-slag relationship + G ENDFE $ Total iron specification constraint + L CSPEC $ Total carbon specification constraint + E BASE $ Basicity relationship + L SISPEC $ Total silicon specification constraint + G TOTAL $ Total end metal + L TOTRS4 $ Inventory limitation on 430 grade scrap + L TOTRCF $ Inventory limitation on low-carbon ferrochrome +COLUMNS +* Steel scrap + STSCP VALUE .02 + CR 0 + MN .01 + SI .002 + C .006 + FE .982 +* 430 grade scrap + SP430 VALUE .075 + CR .16 + MN .01 + SI .0095 + C .0012 + FE .8143 + TOTRS4 1 +* High-carbon ferrochrome + HCFCR VALUE .27 + CR .556 + MN 0 + SI .02 + C .08 + FE .334 +* Low-carbon ferrochrome + LCFCR VALUE .40 + CR .65 + MN 0 + SI .01 + C .0009 + FE .3391 + TOTRCF 1 +* Chromium initially charged + CRIT VALUE 0 + CR -1 + TOTCHG 1 + CRSLAG 1 +* Manganese initially charged + MNIT VALUE 0 + MN -1 + TOTCHG 1 + CRSLAG 1 + MN/CR .98 +* Silicon initially charged + SIIT VALUE 0 + SI -1 + TOTCHG 1 + CSPEC -5 + BASE 2.14 + TOTAL -1 +* Carbon initially charged + CEIT VALUE 0 + C -1 + TOTCHG 1 + TOTAL -1 +* Iron initially charged + FEIT VALUE 0 + FE -1 + TOTCHG 1 + ENDFE 1 +* Total initial charge weight + TICW VALUE 0 + TOTCHG -1 + CRSLAG -.074 + TOTCRS .074 + FESLAG .075 + CSPEC 5 + TOTAL 1 +* Modified chromium in the slag + ISCR VALUE 0 + CRSLAG -1 + TOTCRS .95 + FESLAG -1 + CSPEC -.25 + SISPEC -.395 + TOTAL -.05 +* Chrome silicide additive at refining stage + CRSI VALUE .27 + TOTCRS .39 + ENDFE .18 + BASE 2.7606 + SISPEC .43 + TOTAL .57 +* 430 grade scrap at refining stage + RS430 VALUE .075 + TOTCRS .17 + MN/CR .01 + ENDFE .8143 + CSPEC 12 + SISPEC .0095 + TOTAL 1 + TOTRS4 1 +* Low-carbon ferrochrome at refining stage + RCFCR VALUE .40 + TOTCRS .65 + ENDFE .3391 + CSPEC 9 + SISPEC .01 + TOTAL 1 + TOTRCF 1 +* Iron in the slag + ISFE VALUE 0 + FESLAG -1 + ENDFE -.05 + CSPEC -.25 + SISPEC -.238 + TOTAL -.05 +* Lime at refining stage + LIME VALUE .01 + BASE -2 +* Low-carbon ferrochrome at finishing stage + FCFCR VALUE .40 + TOTCRS .65 + ENDFE .3391 + CSPEC 9 + SISPEC .01 + TOTAL 1 + TOTRCF 1 +* Slack in the chromium and manganese specifications + SIS VALUE 0 + TOTCRS 1 + MN/CR 1 +RHS + TOTCRS 3400 + MN/CR 200 + ENDFE 16200 + CSPEC 100000 + SISPEC 200 + TOTAL 20000 + TOTRS4 2000 + TOTRCF 2000 +BOUNDS + UP HCFCR 2000 +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/gap.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/gap.mod new file mode 100644 index 000000000..22cdefa9f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/gap.mod @@ -0,0 +1,79 @@ +/* GAP, Generalized Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Generalized Assignment Problem (GAP) is to assign a set of jobs + to a set of agents subject to the constraints that each job must be + assigned exactly to one agent and the total resources consumed by all + jobs assigned to an agent must not exceed the agent's capacity. */ + +param m, integer, > 0; +/* number of agents */ + +param n, integer, > 0; +/* number of jobs */ + +set I := 1..m; +/* set of agents */ + +set J := 1..n; +/* set of jobs */ + +param a{i in I, j in J}, >= 0; +/* resource consumed in allocating job j to agent i */ + +param b{i in I}, >= 0; +/* resource capacity of agent i */ + +param c{i in I, j in J}, >= 0; +/* cost of allocating job j to agent i */ + +var x{i in I, j in J}, binary; +/* x[i,j] = 1 means job j is assigned to agent i */ + +s.t. one{j in J}: sum{i in I} x[i,j] = 1; +/* job j must be assigned exactly to one agent */ + +s.t. lim{i in I}: sum{j in J} a[i,j] * x[i,j] <= b[i]; +/* total amount of resources consumed by all jobs assigned to agent i + must not exceed the agent's capacity */ + +minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; +/* the objective is to find cheapest assignment (note that gap can also + be formulated as maximization problem) */ + +data; + +/* These data correspond to the instance c515-1 (gap1) from: + + I.H. Osman, "Heuristics for the Generalised Assignment Problem: + Simulated Annealing and Tabu Search Approaches", OR Spektrum, Volume + 17, 211-225, 1995 + + D. Cattrysse, M. Salomon and L.N. Van Wassenhove, "A set partitioning + heuristic for the generalized assignment problem", European Journal + of Operational Research, Volume 72, 167-174, 1994 */ + +/* The optimal solution is 261 (minimization) or 336 (maximization) */ + +param m := 5; + +param n := 15; + +param a : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := + 1 8 15 14 23 8 16 8 25 9 17 25 15 10 8 24 + 2 15 7 23 22 11 11 12 10 17 16 7 16 10 18 22 + 3 21 20 6 22 24 10 24 9 21 14 11 14 11 19 16 + 4 20 11 8 14 9 5 6 19 19 7 6 6 13 9 18 + 5 8 13 13 13 10 20 25 16 16 17 10 10 5 12 23 ; + +param b := 1 36, 2 34, 3 38, 4 27, 5 33; + +param c : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := + 1 17 21 22 18 24 15 20 18 19 18 16 22 24 24 16 + 2 23 16 21 16 17 16 19 25 18 21 17 15 25 17 24 + 3 16 20 16 25 24 16 17 19 19 18 20 16 17 21 24 + 4 19 19 22 22 20 16 19 17 21 19 25 23 25 25 25 + 5 18 19 15 15 21 25 16 16 23 15 22 17 19 22 24 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/glpsol.c b/WebAPP/SOLVERs/GLPK/glpk/examples/glpsol.c new file mode 100644 index 000000000..7a0c42c88 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/glpsol.c @@ -0,0 +1,1584 @@ +/* glpsol.c (stand-alone GLPK LP/MIP solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define xassert glp_assert +#define xerror glp_error +#define xprintf glp_printf + +struct csa +{ /* common storage area */ + glp_prob *prob; + /* LP/MIP problem object */ + glp_bfcp bfcp; + /* basis factorization control parameters */ + glp_smcp smcp; + /* simplex method control parameters */ + glp_iptcp iptcp; + /* interior-point method control parameters */ + glp_iocp iocp; + /* integer optimizer control parameters */ + glp_tran *tran; + /* model translator workspace */ + glp_graph *graph; + /* network problem object */ + int format; + /* problem file format: */ +#define FMT_MPS_DECK 1 /* fixed MPS */ +#define FMT_MPS_FILE 2 /* free MPS */ +#define FMT_LP 3 /* CPLEX LP */ +#define FMT_GLP 4 /* GLPK LP/MIP */ +#define FMT_MATHPROG 5 /* MathProg */ +#define FMT_MIN_COST 6 /* DIMACS min-cost flow */ +#define FMT_MAX_FLOW 7 /* DIMACS maximum flow */ +#if 1 /* 06/VIII-2011 */ +#define FMT_CNF 8 /* DIMACS CNF-SAT */ +#endif + const char *in_file; + /* name of input problem file */ +#define DATA_MAX 10 + /* maximal number of input data files */ + int ndf; + /* number of input data files specified */ + const char *in_data[1+DATA_MAX]; + /* name(s) of input data file(s) */ + const char *out_dpy; + /* name of output file to send display output; NULL means the + display output is sent to the terminal */ + int seed; + /* seed value to be passed to the MathProg translator; initially + set to 1; 0x80000000 means the value is omitted */ + int solution; + /* solution type flag: */ +#define SOL_BASIC 1 /* basic */ +#define SOL_INTERIOR 2 /* interior-point */ +#define SOL_INTEGER 3 /* mixed integer */ + const char *in_res; + /* name of input solution file in raw format */ + int dir; + /* optimization direction flag: + 0 - not specified + GLP_MIN - minimization + GLP_MAX - maximization */ + int scale; + /* automatic problem scaling flag */ + const char *out_sol; + /* name of output solution file in printable format */ + const char *out_res; + /* name of output solution file in raw format */ + const char *out_ranges; + /* name of output file to write sensitivity analysis report */ + int check; + /* input data checking flag; no solution is performed */ + const char *new_name; + /* new name to be assigned to the problem */ +#if 1 /* 18/I-2018 */ + int hide; + /* clear all symbolic names in the problem object */ +#endif + const char *out_mps; + /* name of output problem file in fixed MPS format */ + const char *out_freemps; + /* name of output problem file in free MPS format */ + const char *out_cpxlp; + /* name of output problem file in CPLEX LP format */ + const char *out_glp; + /* name of output problem file in GLPK format */ +#if 0 + const char *out_pb; + /* name of output problem file in OPB format */ + const char *out_npb; + /* name of output problem file in normalized OPB format */ +#endif +#if 1 /* 06/VIII-2011 */ + const char *out_cnf; + /* name of output problem file in DIMACS CNF-SAT format */ +#endif + const char *log_file; + /* name of output file to hardcopy terminal output */ + int crash; + /* initial basis option: */ +#define USE_STD_BASIS 1 /* use standard basis */ +#define USE_ADV_BASIS 2 /* use advanced basis */ +#define USE_CPX_BASIS 3 /* use Bixby's basis */ +#define USE_INI_BASIS 4 /* use initial basis from ini_file */ + const char *ini_file; + /* name of input file containing initial basis */ + int exact; + /* flag to use glp_exact rather than glp_simplex */ + int xcheck; + /* flag to check final basis with glp_exact */ + int nomip; + /* flag to consider MIP as pure LP */ +#if 1 /* 15/VIII-2011 */ + int minisat; + /* option to solve feasibility problem with MiniSat solver */ + int use_bnd; + /* option to bound objective function */ + int obj_bnd; + /* upper (minization) or lower (maximization) objective bound */ +#endif +#if 1 /* 11/VII-2013 */ + const char *use_sol; + /* name of input mip solution file in GLPK format */ +#endif +}; + +static int str2int(const char *s, int *x) +{ /* convert string to integer */ + long t; + char *endptr; + t = strtol(s, &endptr, 10); + if (*endptr != '\0') + return 2; + if (!(INT_MIN <= t && t <= INT_MAX)) + return 1; + *x = t; +#if 0 + xprintf("str2int: x = %d\n", *x); +#endif + return 0; +} + +static int str2num(const char *s, double *x) +{ /* convert string to floating point */ + double t; + char *endptr; + t = strtod(s, &endptr); + if (*endptr != '\0') + return 2; + if (!(-DBL_MAX <= t && t <= +DBL_MAX)) + return 1; + *x = t; +#if 0 + xprintf("str2num: x = %g\n", *x); +#endif + return 0; +} + +static void print_help(const char *my_name) +{ /* print help information */ + xprintf("Usage: %s [options...] filename\n", my_name); + xprintf("\n"); + xprintf("General options:\n"); + xprintf(" --mps read LP/MIP problem in fixed MPS fo" + "rmat\n"); + xprintf(" --freemps read LP/MIP problem in free MPS for" + "mat (default)\n"); + xprintf(" --lp read LP/MIP problem in CPLEX LP for" + "mat\n"); + xprintf(" --glp read LP/MIP problem in GLPK format " + "\n"); + xprintf(" --math read LP/MIP model written in GNU Ma" + "thProg modeling\n"); + xprintf(" language\n"); + xprintf(" -m filename, --model filename\n"); + xprintf(" read model section and optional dat" + "a section from\n"); + xprintf(" filename (same as --math)\n"); + xprintf(" -d filename, --data filename\n"); + xprintf(" read data section from filename (fo" + "r --math only);\n"); + xprintf(" if model file also has data section" + ", it is ignored\n"); + xprintf(" -y filename, --display filename\n"); + xprintf(" send display output to filename (fo" + "r --math only);\n"); + xprintf(" by default the output is sent to te" + "rminal\n"); + xprintf(" --seed value initialize pseudo-random number gen" + "erator used in\n"); + xprintf(" MathProg model with specified seed " + "(any integer);\n"); + xprintf(" if seed value is ?, some random see" + "d will be used\n"); + xprintf(" --mincost read min-cost flow problem in DIMAC" + "S format\n"); + xprintf(" --maxflow read maximum flow problem in DIMACS" + " format\n"); +#if 1 /* 06/VIII-2011 */ + xprintf(" --cnf read CNF-SAT problem in DIMACS form" + "at\n"); +#endif + xprintf(" --simplex use simplex method (default)\n"); + xprintf(" --interior use interior point method (LP only)" + "\n"); + xprintf(" -r filename, --read filename\n"); + xprintf(" read solution from filename rather " + "to find it with\n"); + xprintf(" the solver\n"); + xprintf(" --min minimization\n"); + xprintf(" --max maximization\n"); + xprintf(" --scale scale problem (default)\n"); + xprintf(" --noscale do not scale problem\n"); + xprintf(" -o filename, --output filename\n"); + xprintf(" write solution to filename in print" + "able format\n"); + xprintf(" -w filename, --write filename\n"); + xprintf(" write solution to filename in plain" + " text format\n"); + xprintf(" --ranges filename\n"); + xprintf(" write sensitivity analysis report t" + "o filename in\n"); + xprintf(" printable format (simplex only)\n"); + xprintf(" --tmlim nnn limit solution time to nnn seconds " + "\n"); + xprintf(" --memlim nnn limit available memory to nnn megab" + "ytes\n"); + xprintf(" --check do not solve problem, check input d" + "ata only\n"); + xprintf(" --name probname change problem name to probname\n"); +#if 1 /* 18/I-2018 */ + xprintf(" --hide remove all symbolic names from prob" + "lem object\n"); +#endif + xprintf(" --wmps filename write problem to filename in fixed " + "MPS format\n"); + xprintf(" --wfreemps filename\n"); + xprintf(" write problem to filename in free M" + "PS format\n"); + xprintf(" --wlp filename write problem to filename in CPLEX " + "LP format\n"); + xprintf(" --wglp filename write problem to filename in GLPK f" + "ormat\n"); +#if 0 + xprintf(" --wpb filename write problem to filename in OPB fo" + "rmat\n"); + xprintf(" --wnpb filename write problem to filename in normal" + "ized OPB format\n"); +#endif +#if 1 /* 06/VIII-2011 */ + xprintf(" --wcnf filename write problem to filename in DIMACS" + " CNF-SAT format\n"); +#endif + xprintf(" --log filename write copy of terminal output to fi" + "lename\n"); + xprintf(" -h, --help display this help information and e" + "xit\n"); + xprintf(" -v, --version display program version and exit\n") + ; + xprintf("\n"); + xprintf("LP basis factorization options:\n"); +#if 0 /* 08/III-2014 */ + xprintf(" --luf LU + Forrest-Tomlin update\n"); + xprintf(" (faster, less stable; default)\n"); + xprintf(" --cbg LU + Schur complement + Bartels-Gol" + "ub update\n"); + xprintf(" (slower, more stable)\n"); + xprintf(" --cgr LU + Schur complement + Givens rota" + "tion update\n"); + xprintf(" (slower, more stable)\n"); +#else + xprintf(" --luf plain LU-factorization (default)\n") + ; + xprintf(" --btf block triangular LU-factorization\n" + ); + xprintf(" --ft Forrest-Tomlin update (requires --l" + "uf; default)\n"); + xprintf(" --cbg Schur complement + Bartels-Golub up" + "date\n"); + xprintf(" --cgr Schur complement + Givens rotation " + "update\n"); +#endif + xprintf("\n"); + xprintf("Options specific to simplex solver:\n"); + xprintf(" --primal use primal simplex (default)\n"); + xprintf(" --dual use dual simplex\n"); + xprintf(" --std use standard initial basis of all s" + "lacks\n"); + xprintf(" --adv use advanced initial basis (default" + ")\n"); + xprintf(" --bib use Bixby's initial basis\n"); + xprintf(" --ini filename use as initial basis previously sav" + "ed with -w\n"); + xprintf(" (disables LP presolver)\n"); + xprintf(" --steep use steepest edge technique (defaul" + "t)\n"); + xprintf(" --nosteep use standard \"textbook\" pricing\n" + ); + xprintf(" --relax use Harris' two-pass ratio test (de" + "fault)\n"); + xprintf(" --norelax use standard \"textbook\" ratio tes" + "t\n"); +#if 0 /* 23/VI-2017 */ +#if 1 /* 28/III-2016 */ + xprintf(" --flip use flip-flop ratio test (assumes -" + "-dual)\n"); +#endif +#else + /* now this option is implemented in both primal and dual */ + xprintf(" --flip use long-step ratio test\n"); +#endif + xprintf(" --presol use presolver (default; assumes --s" + "cale and --adv)\n"); + xprintf(" --nopresol do not use presolver\n"); + xprintf(" --exact use simplex method based on exact a" + "rithmetic\n"); + xprintf(" --xcheck check final basis using exact arith" + "metic\n"); + xprintf("\n"); + xprintf("Options specific to interior-point solver:\n"); + xprintf(" --nord use natural (original) ordering\n"); + xprintf(" --qmd use quotient minimum degree orderin" + "g\n"); + xprintf(" --amd use approximate minimum degree orde" + "ring (default)\n"); + xprintf(" --symamd use approximate minimum degree orde" + "ring\n"); + xprintf("\n"); + xprintf("Options specific to MIP solver:\n"); + xprintf(" --nomip consider all integer variables as c" + "ontinuous\n"); + xprintf(" (allows solving MIP as pure LP)\n"); + xprintf(" --first branch on first integer variable\n") + ; + xprintf(" --last branch on last integer variable\n"); + xprintf(" --mostf branch on most fractional variable " + "\n"); + xprintf(" --drtom branch using heuristic by Driebeck " + "and Tomlin\n"); + xprintf(" (default)\n"); + xprintf(" --pcost branch using hybrid pseudocost heur" + "istic (may be\n"); + xprintf(" useful for hard instances)\n"); + xprintf(" --dfs backtrack using depth first search " + "\n"); + xprintf(" --bfs backtrack using breadth first searc" + "h\n"); + xprintf(" --bestp backtrack using the best projection" + " heuristic\n"); + xprintf(" --bestb backtrack using node with best loca" + "l bound\n"); + xprintf(" (default)\n"); + xprintf(" --intopt use MIP presolver (default)\n"); + xprintf(" --nointopt do not use MIP presolver\n"); + xprintf(" --binarize replace general integer variables b" + "y binary ones\n"); + xprintf(" (assumes --intopt)\n"); + xprintf(" --fpump apply feasibility pump heuristic\n") + ; +#if 1 /* 29/VI-2013 */ + xprintf(" --proxy [nnn] apply proximity search heuristic (n" + "nn is time limit\n"); + xprintf(" in seconds; default is 60)\n"); +#endif + xprintf(" --gomory generate Gomory's mixed integer cut" + "s\n"); + xprintf(" --mir generate MIR (mixed integer roundin" + "g) cuts\n"); + xprintf(" --cover generate mixed cover cuts\n"); + xprintf(" --clique generate clique cuts\n"); + xprintf(" --cuts generate all cuts above\n"); + xprintf(" --mipgap tol set relative mip gap tolerance to t" + "ol\n"); +#if 1 /* 15/VIII-2011 */ + xprintf(" --minisat translate integer feasibility probl" + "em to CNF-SAT\n"); + xprintf(" and solve it with MiniSat solver\n") + ; + xprintf(" --objbnd bound add inequality obj <= bound (minimi" + "zation) or\n"); + xprintf(" obj >= bound (maximization) to inte" + "ger feasibility\n"); + xprintf(" problem (assumes --minisat)\n"); +#endif + xprintf("\n"); + xprintf("For description of the MPS and CPLEX LP formats see Refe" + "rence Manual.\n"); + xprintf("For description of the modeling language see \"GLPK: Mod" + "eling Language\n"); + xprintf("GNU MathProg\". Both documents are included in the GLPK " + "distribution.\n"); + xprintf("\n"); + xprintf("See GLPK web page at .\n"); + xprintf("\n"); + xprintf("Please report bugs to .\n"); + return; +} + +static void print_version(int briefly) +{ /* print version information */ + xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version()); + if (briefly) goto done; + xprintf("Copyright (C) 2000-2017 Andrew Makhorin, Department for " + "Applied\n"); + xprintf("Informatics, Moscow Aviation Institute, Moscow, Russia. " + "All rights\n"); + xprintf("reserved. E-mail: .\n"); + xprintf("\n"); + xprintf("This program has ABSOLUTELY NO WARRANTY.\n"); + xprintf("\n"); + xprintf("This program is free software; you may re-distribute it " + "under the terms\n"); + xprintf("of the GNU General Public License version 3 or later.\n") + ; +done: return; +} + +static int parse_cmdline(struct csa *csa, int argc, char *argv[]) +{ /* parse command-line parameters */ + int k; +#define p(str) (strcmp(argv[k], str) == 0) + for (k = 1; k < argc; k++) + { if (p("--mps")) + csa->format = FMT_MPS_DECK; + else if (p("--freemps")) + csa->format = FMT_MPS_FILE; + else if (p("--lp") || p("--cpxlp")) + csa->format = FMT_LP; + else if (p("--glp")) + csa->format = FMT_GLP; + else if (p("--math") || p("-m") || p("--model")) + csa->format = FMT_MATHPROG; + else if (p("-d") || p("--data")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input data file specified\n"); + return 1; + } + if (csa->ndf == DATA_MAX) + { xprintf("Too many input data files\n"); + return 1; + } + csa->in_data[++(csa->ndf)] = argv[k]; + } + else if (p("-y") || p("--display")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No display output file specified\n"); + return 1; + } + if (csa->out_dpy != NULL) + { xprintf("Only one display output file allowed\n"); + return 1; + } + csa->out_dpy = argv[k]; + } + else if (p("--seed")) + { k++; + if (k == argc || argv[k][0] == '\0' || + argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) + { xprintf("No seed value specified\n"); + return 1; + } + if (strcmp(argv[k], "?") == 0) + csa->seed = 0x80000000; + else if (str2int(argv[k], &csa->seed)) + { xprintf("Invalid seed value '%s'\n", argv[k]); + return 1; + } + } + else if (p("--mincost")) + csa->format = FMT_MIN_COST; + else if (p("--maxflow")) + csa->format = FMT_MAX_FLOW; +#if 1 /* 06/VIII-2011 */ + else if (p("--cnf")) + csa->format = FMT_CNF; +#endif + else if (p("--simplex")) + csa->solution = SOL_BASIC; + else if (p("--interior")) + csa->solution = SOL_INTERIOR; +#if 1 /* 28/V-2010 */ + else if (p("--alien")) + csa->iocp.alien = GLP_ON; +#endif + else if (p("-r") || p("--read")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input solution file specified\n"); + return 1; + } + if (csa->in_res != NULL) + { xprintf("Only one input solution file allowed\n"); + return 1; + } + csa->in_res = argv[k]; + } + else if (p("--min")) + csa->dir = GLP_MIN; + else if (p("--max")) + csa->dir = GLP_MAX; + else if (p("--scale")) + csa->scale = 1; + else if (p("--noscale")) + csa->scale = 0; + else if (p("-o") || p("--output")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output solution file specified\n"); + return 1; + } + if (csa->out_sol != NULL) + { xprintf("Only one output solution file allowed\n"); + return 1; + } + csa->out_sol = argv[k]; + } + else if (p("-w") || p("--write")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output solution file specified\n"); + return 1; + } + if (csa->out_res != NULL) + { xprintf("Only one output solution file allowed\n"); + return 1; + } + csa->out_res = argv[k]; + } + else if (p("--ranges") || p("--bounds")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output file specified to write sensitivity a" + "nalysis report\n"); + return 1; + } + if (csa->out_ranges != NULL) + { xprintf("Only one output file allowed to write sensitivi" + "ty analysis report\n"); + return 1; + } + csa->out_ranges = argv[k]; + } + else if (p("--tmlim")) + { int tm_lim; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No time limit specified\n"); + return 1; + } + if (str2int(argv[k], &tm_lim) || tm_lim < 0) + { xprintf("Invalid time limit '%s'\n", argv[k]); + return 1; + } + if (tm_lim <= INT_MAX / 1000) + csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim; + else + csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX; + } + else if (p("--memlim")) + { int mem_lim; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No memory limit specified\n"); + return 1; + } + if (str2int(argv[k], &mem_lim) || mem_lim < 1) + { xprintf("Invalid memory limit '%s'\n", argv[k]); + return 1; + } + glp_mem_limit(mem_lim); + } + else if (p("--check")) + csa->check = 1; + else if (p("--name")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem name specified\n"); + return 1; + } + if (csa->new_name != NULL) + { xprintf("Only one problem name allowed\n"); + return 1; + } + csa->new_name = argv[k]; + } +#if 1 /* 18/I-2018 */ + else if (p("--hide")) + csa->hide = 1; +#endif + else if (p("--wmps")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No fixed MPS output file specified\n"); + return 1; + } + if (csa->out_mps != NULL) + { xprintf("Only one fixed MPS output file allowed\n"); + return 1; + } + csa->out_mps = argv[k]; + } + else if (p("--wfreemps")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No free MPS output file specified\n"); + return 1; + } + if (csa->out_freemps != NULL) + { xprintf("Only one free MPS output file allowed\n"); + return 1; + } + csa->out_freemps = argv[k]; + } + else if (p("--wlp") || p("--wcpxlp") || p("--wlpt")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No CPLEX LP output file specified\n"); + return 1; + } + if (csa->out_cpxlp != NULL) + { xprintf("Only one CPLEX LP output file allowed\n"); + return 1; + } + csa->out_cpxlp = argv[k]; + } + else if (p("--wglp")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No GLPK LP/MIP output file specified\n"); + return 1; + } + if (csa->out_glp != NULL) + { xprintf("Only one GLPK LP/MIP output file allowed\n"); + return 1; + } + csa->out_glp = argv[k]; + } +#if 0 + else if (p("--wpb")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_pb != NULL) + { xprintf("Only one OPB output file allowed\n"); + return 1; + } + csa->out_pb = argv[k]; + } + else if (p("--wnpb")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_npb != NULL) + { xprintf("Only one normalized OPB output file allowed\n"); + return 1; + } + csa->out_npb = argv[k]; + } +#endif +#if 1 /* 06/VIII-2011 */ + else if (p("--wcnf")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No problem output file specified\n"); + return 1; + } + if (csa->out_cnf != NULL) + { xprintf("Only one output DIMACS CNF-SAT file allowed\n"); + return 1; + } + csa->out_cnf = argv[k]; + } +#endif + else if (p("--log")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No log file specified\n"); + return 1; + } + if (csa->log_file != NULL) + { xprintf("Only one log file allowed\n"); + return 1; + } + csa->log_file = argv[k]; + } + else if (p("-h") || p("--help")) + { print_help(argv[0]); + return -1; + } + else if (p("-v") || p("--version")) + { print_version(0); + return -1; + } +#if 0 /* 08/III-2014 */ + else if (p("--luf")) + csa->bfcp.type = GLP_BF_FT; + else if (p("--cbg")) + csa->bfcp.type = GLP_BF_BG; + else if (p("--cgr")) + csa->bfcp.type = GLP_BF_GR; +#else + else if (p("--luf")) + { csa->bfcp.type &= 0x0F; + csa->bfcp.type |= GLP_BF_LUF; + } + else if (p("--btf")) + { csa->bfcp.type &= 0x0F; + csa->bfcp.type |= GLP_BF_BTF; + } + else if (p("--ft")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_FT; + } + else if (p("--cbg")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_BG; + } + else if (p("--cgr")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_GR; + } +#endif + else if (p("--primal")) + csa->smcp.meth = GLP_PRIMAL; + else if (p("--dual")) + csa->smcp.meth = GLP_DUAL; + else if (p("--std")) + csa->crash = USE_STD_BASIS; + else if (p("--adv")) + csa->crash = USE_ADV_BASIS; + else if (p("--bib")) + csa->crash = USE_CPX_BASIS; + else if (p("--ini")) + { csa->crash = USE_INI_BASIS; + csa->smcp.presolve = GLP_OFF; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No initial basis file specified\n"); + return 1; + } + if (csa->ini_file != NULL) + { xprintf("Only one initial basis file allowed\n"); + return 1; + } + csa->ini_file = argv[k]; + } + else if (p("--steep")) + csa->smcp.pricing = GLP_PT_PSE; + else if (p("--nosteep")) + csa->smcp.pricing = GLP_PT_STD; + else if (p("--relax")) + csa->smcp.r_test = GLP_RT_HAR; + else if (p("--norelax")) + csa->smcp.r_test = GLP_RT_STD; +#if 1 /* 28/III-2016 */ + else if (p("--flip")) +#if 0 /* 23/VI-2017 */ + { csa->smcp.meth = GLP_DUAL; +#else + /* now this option is implemented in both primal and dual */ + { +#endif + csa->smcp.r_test = GLP_RT_FLIP; + csa->iocp.flip = GLP_ON; + } +#endif + else if (p("--presol")) + csa->smcp.presolve = GLP_ON; + else if (p("--nopresol")) + csa->smcp.presolve = GLP_OFF; + else if (p("--exact")) + csa->exact = 1; + else if (p("--xcheck")) + csa->xcheck = 1; + else if (p("--nord")) + csa->iptcp.ord_alg = GLP_ORD_NONE; + else if (p("--qmd")) + csa->iptcp.ord_alg = GLP_ORD_QMD; + else if (p("--amd")) + csa->iptcp.ord_alg = GLP_ORD_AMD; + else if (p("--symamd")) + csa->iptcp.ord_alg = GLP_ORD_SYMAMD; + else if (p("--nomip")) + csa->nomip = 1; + else if (p("--first")) + csa->iocp.br_tech = GLP_BR_FFV; + else if (p("--last")) + csa->iocp.br_tech = GLP_BR_LFV; + else if (p("--drtom")) + csa->iocp.br_tech = GLP_BR_DTH; + else if (p("--mostf")) + csa->iocp.br_tech = GLP_BR_MFV; + else if (p("--pcost")) + csa->iocp.br_tech = GLP_BR_PCH; + else if (p("--dfs")) + csa->iocp.bt_tech = GLP_BT_DFS; + else if (p("--bfs")) + csa->iocp.bt_tech = GLP_BT_BFS; + else if (p("--bestp")) + csa->iocp.bt_tech = GLP_BT_BPH; + else if (p("--bestb")) + csa->iocp.bt_tech = GLP_BT_BLB; + else if (p("--intopt")) + csa->iocp.presolve = GLP_ON; + else if (p("--nointopt")) + csa->iocp.presolve = GLP_OFF; + else if (p("--binarize")) + csa->iocp.presolve = csa->iocp.binarize = GLP_ON; + else if (p("--fpump")) + csa->iocp.fp_heur = GLP_ON; +#if 1 /* 29/VI-2013 */ + else if (p("--proxy")) + { csa->iocp.ps_heur = GLP_ON; + if (argv[k+1] && isdigit((unsigned char)argv[k+1][0])) + { int nnn; + k++; + if (str2int(argv[k], &nnn) || nnn < 1) + { xprintf("Invalid proxy time limit '%s'\n", argv[k]); + return 1; + } + csa->iocp.ps_tm_lim = 1000 * nnn; + } + } +#endif + else if (p("--gomory")) + csa->iocp.gmi_cuts = GLP_ON; + else if (p("--mir")) + csa->iocp.mir_cuts = GLP_ON; + else if (p("--cover")) + csa->iocp.cov_cuts = GLP_ON; + else if (p("--clique")) + csa->iocp.clq_cuts = GLP_ON; + else if (p("--cuts")) + csa->iocp.gmi_cuts = csa->iocp.mir_cuts = + csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON; + else if (p("--mipgap")) + { double mip_gap; + k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No relative gap tolerance specified\n"); + return 1; + } + if (str2num(argv[k], &mip_gap) || mip_gap < 0.0) + { xprintf("Invalid relative mip gap tolerance '%s'\n", + argv[k]); + return 1; + } + csa->iocp.mip_gap = mip_gap; + } +#if 1 /* 15/VIII-2011 */ + else if (p("--minisat")) + csa->minisat = 1; + else if (p("--objbnd")) + { k++; + if (k == argc || argv[k][0] == '\0' || + argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) + { xprintf("No objective bound specified\n"); + return 1; + } + csa->minisat = 1; + csa->use_bnd = 1; + if (str2int(argv[k], &csa->obj_bnd)) + { xprintf("Invalid objective bound '%s' (should be integer" + " value)\n", argv[k]); + return 1; + } + } +#endif +#if 1 /* 11/VII-2013 */ + else if (p("--use")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No input MIP solution file specified\n"); + return 1; + } + if (csa->use_sol != NULL) + { xprintf("Only one input MIP solution file allowed\n"); + return 1; + } + csa->use_sol = argv[k]; + } + else if (p("--save")) + { k++; + if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') + { xprintf("No output MIP solution file specified\n"); + return 1; + } + if (csa->iocp.save_sol != NULL) + { xprintf("Only one output MIP solution file allowed\n"); + return 1; + } + csa->iocp.save_sol = argv[k]; + } +#endif + else if (argv[k][0] == '-' || + (argv[k][0] == '-' && argv[k][1] == '-')) + { xprintf("Invalid option '%s'; try %s --help\n", + argv[k], argv[0]); + return 1; + } + else + { if (csa->in_file != NULL) + { xprintf("Only one input problem file allowed\n"); + return 1; + } + csa->in_file = argv[k]; + } + } +#undef p + return 0; +} + +typedef struct { double rhs, pi; } v_data; +typedef struct { double low, cap, cost, x; } a_data; + +#ifndef __WOE__ +int main(int argc, char *argv[]) +#else +int __cdecl main(int argc, char *argv[]) +#endif +{ /* stand-alone LP/MIP solver */ + struct csa _csa, *csa = &_csa; + int ret; +#if 0 /* 10/VI-2013 */ + glp_long start; +#else + double start; +#endif + /* perform initialization */ + csa->prob = glp_create_prob(); + glp_get_bfcp(csa->prob, &csa->bfcp); + glp_init_smcp(&csa->smcp); + csa->smcp.presolve = GLP_ON; + glp_init_iptcp(&csa->iptcp); + glp_init_iocp(&csa->iocp); + csa->iocp.presolve = GLP_ON; + csa->tran = NULL; + csa->graph = NULL; + csa->format = FMT_MPS_FILE; + csa->in_file = NULL; + csa->ndf = 0; + csa->out_dpy = NULL; + csa->seed = 1; + csa->solution = SOL_BASIC; + csa->in_res = NULL; + csa->dir = 0; + csa->scale = 1; + csa->out_sol = NULL; + csa->out_res = NULL; + csa->out_ranges = NULL; + csa->check = 0; + csa->new_name = NULL; +#if 1 /* 18/I-2018 */ + csa->hide = 0; +#endif + csa->out_mps = NULL; + csa->out_freemps = NULL; + csa->out_cpxlp = NULL; + csa->out_glp = NULL; +#if 0 + csa->out_pb = NULL; + csa->out_npb = NULL; +#endif +#if 1 /* 06/VIII-2011 */ + csa->out_cnf = NULL; +#endif + csa->log_file = NULL; + csa->crash = USE_ADV_BASIS; + csa->ini_file = NULL; + csa->exact = 0; + csa->xcheck = 0; + csa->nomip = 0; +#if 1 /* 15/VIII-2011 */ + csa->minisat = 0; + csa->use_bnd = 0; + csa->obj_bnd = 0; +#endif +#if 1 /* 11/VII-2013 */ + csa->use_sol = NULL; +#endif + /* parse command-line parameters */ + ret = parse_cmdline(csa, argc, argv); + if (ret < 0) + { ret = EXIT_SUCCESS; + goto done; + } + if (ret > 0) + { ret = EXIT_FAILURE; + goto done; + } + /*--------------------------------------------------------------*/ + /* remove all output files specified in the command line */ + if (csa->out_dpy != NULL) remove(csa->out_dpy); + if (csa->out_sol != NULL) remove(csa->out_sol); + if (csa->out_res != NULL) remove(csa->out_res); + if (csa->out_ranges != NULL) remove(csa->out_ranges); + if (csa->out_mps != NULL) remove(csa->out_mps); + if (csa->out_freemps != NULL) remove(csa->out_freemps); + if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); + if (csa->out_glp != NULL) remove(csa->out_glp); +#if 0 + if (csa->out_pb != NULL) remove(csa->out_pb); + if (csa->out_npb != NULL) remove(csa->out_npb); +#endif +#if 1 /* 06/VIII-2011 */ + if (csa->out_cnf != NULL) remove(csa->out_cnf); +#endif + if (csa->log_file != NULL) remove(csa->log_file); + /*--------------------------------------------------------------*/ + /* open log file, if required */ + if (csa->log_file != NULL) + { if (glp_open_tee(csa->log_file)) + { xprintf("Unable to create log file\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /*--------------------------------------------------------------*/ + /* print version information */ + print_version(1); + /*--------------------------------------------------------------*/ + /* print parameters specified in the command line */ + if (argc > 1) + { int k, len = INT_MAX; + xprintf("Parameter(s) specified in the command line:"); + for (k = 1; k < argc; k++) + { if (len > 72) + xprintf("\n"), len = 0; + xprintf(" %s", argv[k]); + len += 1 + strlen(argv[k]); + } + xprintf("\n"); + } + /*--------------------------------------------------------------*/ + /* read problem data from the input file */ + if (csa->in_file == NULL) + { xprintf("No input problem file specified; try %s --help\n", + argv[0]); + ret = EXIT_FAILURE; + goto done; + } + if (csa->format == FMT_MPS_DECK) + { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, + csa->in_file); + if (ret != 0) +err1: { xprintf("MPS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_MPS_FILE) + { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, + csa->in_file); + if (ret != 0) goto err1; + } + else if (csa->format == FMT_LP) + { ret = glp_read_lp(csa->prob, NULL, csa->in_file); + if (ret != 0) + { xprintf("CPLEX LP file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_GLP) + { ret = glp_read_prob(csa->prob, 0, csa->in_file); + if (ret != 0) + { xprintf("GLPK LP/MIP file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else if (csa->format == FMT_MATHPROG) + { int k; + /* allocate the translator workspace */ + csa->tran = glp_mpl_alloc_wksp(); + /* set seed value */ + if (csa->seed == 0x80000000) +#if 0 /* 10/VI-2013 */ + { csa->seed = glp_time().lo; +#else + { csa->seed = (int)fmod(glp_time(), 1000000000.0); +#endif + xprintf("Seed value %d will be used\n", csa->seed); + } + glp_mpl_init_rand(csa->tran, csa->seed); + /* read model section and optional data section */ + if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) +err2: { xprintf("MathProg model processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + /* read optional data section(s), if necessary */ + for (k = 1; k <= csa->ndf; k++) + { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) + goto err2; + } + /* generate the model */ + if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; + /* build the problem instance from the model */ + glp_mpl_build_prob(csa->tran, csa->prob); + } + else if (csa->format == FMT_MIN_COST) + { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), + offsetof(a_data, low), offsetof(a_data, cap), + offsetof(a_data, cost), csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_mincost_lp(csa->prob, csa->graph, GLP_ON, + offsetof(v_data, rhs), offsetof(a_data, low), + offsetof(a_data, cap), offsetof(a_data, cost)); + glp_set_prob_name(csa->prob, csa->in_file); + } + else if (csa->format == FMT_MAX_FLOW) + { int s, t; + csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); + ret = glp_read_maxflow(csa->graph, &s, &t, + offsetof(a_data, cap), csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, + offsetof(a_data, cap)); + glp_set_prob_name(csa->prob, csa->in_file); + } +#if 1 /* 06/VIII-2011 */ + else if (csa->format == FMT_CNF) + { ret = glp_read_cnfsat(csa->prob, csa->in_file); + if (ret != 0) + { xprintf("DIMACS file processing error\n"); + ret = EXIT_FAILURE; + goto done; + } + glp_set_prob_name(csa->prob, csa->in_file); + } +#endif + else + xassert(csa != csa); + /*--------------------------------------------------------------*/ + /* change problem name, if required */ + if (csa->new_name != NULL) + glp_set_prob_name(csa->prob, csa->new_name); + /* change optimization direction, if required */ + if (csa->dir != 0) + glp_set_obj_dir(csa->prob, csa->dir); + /* sort elements of the constraint matrix */ + glp_sort_matrix(csa->prob); +#if 1 /* 18/I-2018 */ + /*--------------------------------------------------------------*/ + /* remove all symbolic names from problem object, if required */ + if (csa->hide) + { int i, j; + glp_set_obj_name(csa->prob, NULL); + glp_delete_index(csa->prob); + for (i = glp_get_num_rows(csa->prob); i >= 1; i--) + glp_set_row_name(csa->prob, i, NULL); + for (j = glp_get_num_cols(csa->prob); j >= 1; j--) + glp_set_col_name(csa->prob, j, NULL); + } +#endif + /*--------------------------------------------------------------*/ + /* write problem data in fixed MPS format, if required */ + if (csa->out_mps != NULL) + { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, + csa->out_mps); + if (ret != 0) + { xprintf("Unable to write problem in fixed MPS format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in free MPS format, if required */ + if (csa->out_freemps != NULL) + { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, + csa->out_freemps); + if (ret != 0) + { xprintf("Unable to write problem in free MPS format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in CPLEX LP format, if required */ + if (csa->out_cpxlp != NULL) + { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); + if (ret != 0) + { xprintf("Unable to write problem in CPLEX LP format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in GLPK format, if required */ + if (csa->out_glp != NULL) + { ret = glp_write_prob(csa->prob, 0, csa->out_glp); + if (ret != 0) + { xprintf("Unable to write problem in GLPK format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#if 0 + /* write problem data in OPB format, if required */ + if (csa->out_pb != NULL) + { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); + if (ret != 0) + { xprintf("Unable to write problem in OPB format\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem data in normalized OPB format, if required */ + if (csa->out_npb != NULL) + { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); + if (ret != 0) + { xprintf( + "Unable to write problem in normalized OPB format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#endif +#if 1 /* 06/VIII-2011 */ + /* write problem data in DIMACS CNF-SAT format, if required */ + if (csa->out_cnf != NULL) + { ret = glp_write_cnfsat(csa->prob, csa->out_cnf); + if (ret != 0) + { xprintf( + "Unable to write problem in DIMACS CNF-SAT format\n"); + ret = EXIT_FAILURE; + goto done; + } + } +#endif + /*--------------------------------------------------------------*/ + /* if only problem data check is required, skip computations */ + if (csa->check) + { +#if 1 /* 29/III-2016 */ + /* report problem characteristics */ + int j, cnt = 0; + xprintf("--- Problem Characteristics ---\n"); + xprintf("Number of rows = %8d\n", + glp_get_num_rows(csa->prob)); + xprintf("Number of columns = %8d\n", + glp_get_num_cols(csa->prob)); + xprintf("Number of non-zeros (matrix) = %8d\n", + glp_get_num_nz(csa->prob)); + for (j = glp_get_num_cols(csa->prob); j >= 1; j--) + { if (glp_get_obj_coef(csa->prob, j) != 0.0) + cnt++; + } + xprintf("Number of non-zeros (objrow) = %8d\n", + cnt); +#endif + ret = EXIT_SUCCESS; + goto done; + } + /*--------------------------------------------------------------*/ + /* determine the solution type */ + if (!csa->nomip && + glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) + { if (csa->solution == SOL_INTERIOR) + { xprintf("Interior-point method is not able to solve MIP pro" + "blem; use --simplex\n"); + ret = EXIT_FAILURE; + goto done; + } + csa->solution = SOL_INTEGER; + } + /*--------------------------------------------------------------*/ + /* if solution is provided, read it and skip computations */ + if (csa->in_res != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_read_sol(csa->prob, csa->in_res); + else if (csa->solution == SOL_INTERIOR) + ret = glp_read_ipt(csa->prob, csa->in_res); + else if (csa->solution == SOL_INTEGER) + ret = glp_read_mip(csa->prob, csa->in_res); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to read problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + goto skip; + } +#if 1 /* 11/VII-2013 */ + /*--------------------------------------------------------------*/ + /* if initial MIP solution is provided, read it */ + if (csa->solution == SOL_INTEGER && csa->use_sol != NULL) + { ret = glp_read_mip(csa->prob, csa->use_sol); + if (ret != 0) + { xprintf("Unable to read initial MIP solution\n"); + ret = EXIT_FAILURE; + goto done; + } + csa->iocp.use_sol = GLP_ON; + } +#endif + /*--------------------------------------------------------------*/ + /* scale the problem data, if required */ + if (csa->scale) + { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || + csa->solution == SOL_INTERIOR || + csa->solution == SOL_INTEGER && !csa->iocp.presolve) + glp_scale_prob(csa->prob, GLP_SF_AUTO); + } + /*--------------------------------------------------------------*/ + /* construct starting LP basis */ + if (csa->solution == SOL_BASIC && !csa->smcp.presolve || + csa->solution == SOL_INTEGER && !csa->iocp.presolve) + { if (csa->crash == USE_STD_BASIS) + glp_std_basis(csa->prob); + else if (csa->crash == USE_ADV_BASIS) + glp_adv_basis(csa->prob, 0); + else if (csa->crash == USE_CPX_BASIS) + glp_cpx_basis(csa->prob); + else if (csa->crash == USE_INI_BASIS) + { ret = glp_read_sol(csa->prob, csa->ini_file); + if (ret != 0) + { xprintf("Unable to read initial basis\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else + xassert(csa != csa); + } + /*--------------------------------------------------------------*/ + /* solve the problem */ + start = glp_time(); + if (csa->solution == SOL_BASIC) + { if (!csa->exact) + { glp_set_bfcp(csa->prob, &csa->bfcp); + glp_simplex(csa->prob, &csa->smcp); + if (csa->xcheck) + { if (csa->smcp.presolve && + glp_get_status(csa->prob) != GLP_OPT) + xprintf("If you need to check final basis for non-opt" + "imal solution, use --nopresol\n"); + else + glp_exact(csa->prob, &csa->smcp); + } + if (csa->out_sol != NULL || csa->out_res != NULL) + { if (csa->smcp.presolve && + glp_get_status(csa->prob) != GLP_OPT) + xprintf("If you need actual output for non-optimal solut" + "ion, use --nopresol\n"); + } + } + else + glp_exact(csa->prob, &csa->smcp); + } + else if (csa->solution == SOL_INTERIOR) + glp_interior(csa->prob, &csa->iptcp); +#if 1 /* 15/VIII-2011 */ + else if (csa->solution == SOL_INTEGER && csa->minisat) + { if (glp_check_cnfsat(csa->prob) == 0) + glp_minisat1(csa->prob); + else + glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd); + } +#endif + else if (csa->solution == SOL_INTEGER) + { glp_set_bfcp(csa->prob, &csa->bfcp); + if (!csa->iocp.presolve) + glp_simplex(csa->prob, &csa->smcp); +#if 0 + csa->iocp.msg_lev = GLP_MSG_DBG; + csa->iocp.pp_tech = GLP_PP_NONE; +#endif +#ifdef GLP_CB_FUNC /* 05/IV-2016 */ + { extern void GLP_CB_FUNC(glp_tree *, void *); + csa->iocp.cb_func = GLP_CB_FUNC; + csa->iocp.cb_info = NULL; + } +#endif + glp_intopt(csa->prob, &csa->iocp); + } + else + xassert(csa != csa); + /*--------------------------------------------------------------*/ + /* display statistics */ + xprintf("Time used: %.1f secs\n", glp_difftime(glp_time(), + start)); +#if 0 /* 16/II-2012 */ + { glp_long tpeak; + char buf[50]; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%s bytes)\n", + xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); + } +#else + { size_t tpeak; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%.0f bytes)\n", + (double)tpeak / 1048576.0, (double)tpeak); + } +#endif + /*--------------------------------------------------------------*/ +skip: /* postsolve the model, if necessary */ + if (csa->tran != NULL) + { if (csa->solution == SOL_BASIC) + { if (!(glp_get_status(csa->prob) == GLP_OPT || + glp_get_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); + } + else if (csa->solution == SOL_INTERIOR) + { if (!(glp_ipt_status(csa->prob) == GLP_OPT || + glp_ipt_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); + } + else if (csa->solution == SOL_INTEGER) + { if (!(glp_mip_status(csa->prob) == GLP_OPT || + glp_mip_status(csa->prob) == GLP_FEAS)) + ret = -1; + else + ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); + } + else + xassert(csa != csa); + if (ret > 0) + { xprintf("Model postsolving error\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /*--------------------------------------------------------------*/ + /* write problem solution in printable format, if required */ + if (csa->out_sol != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_print_sol(csa->prob, csa->out_sol); + else if (csa->solution == SOL_INTERIOR) + ret = glp_print_ipt(csa->prob, csa->out_sol); + else if (csa->solution == SOL_INTEGER) + ret = glp_print_mip(csa->prob, csa->out_sol); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to write problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write problem solution in printable format, if required */ + if (csa->out_res != NULL) + { if (csa->solution == SOL_BASIC) + ret = glp_write_sol(csa->prob, csa->out_res); + else if (csa->solution == SOL_INTERIOR) + ret = glp_write_ipt(csa->prob, csa->out_res); + else if (csa->solution == SOL_INTEGER) + ret = glp_write_mip(csa->prob, csa->out_res); + else + xassert(csa != csa); + if (ret != 0) + { xprintf("Unable to write problem solution\n"); + ret = EXIT_FAILURE; + goto done; + } + } + /* write sensitivity analysis report, if required */ + if (csa->out_ranges != NULL) + { if (csa->solution == SOL_BASIC) + { if (glp_get_status(csa->prob) == GLP_OPT) + { if (glp_bf_exists(csa->prob)) +ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0, + csa->out_ranges); + if (ret != 0) + { xprintf("Unable to write sensitivity analysis repo" + "rt\n"); + ret = EXIT_FAILURE; + goto done; + } + } + else + { ret = glp_factorize(csa->prob); + if (ret == 0) goto ranges; + xprintf("Cannot produce sensitivity analysis report d" + "ue to error in basis factorization (glp_factorize" + " returned %d); try --nopresol\n", ret); + } + } + else + xprintf("Cannot produce sensitivity analysis report for " + "non-optimal basic solution\n"); + } + else + xprintf("Cannot produce sensitivity analysis report for int" + "erior-point or MIP solution\n"); + } + /*--------------------------------------------------------------*/ + /* all seems to be ok */ + ret = EXIT_SUCCESS; + /*--------------------------------------------------------------*/ +done: /* delete the LP/MIP problem object */ + if (csa->prob != NULL) + glp_delete_prob(csa->prob); + /* free the translator workspace, if necessary */ + if (csa->tran != NULL) + glp_mpl_free_wksp(csa->tran); + /* delete the network problem object, if necessary */ + if (csa->graph != NULL) + glp_delete_graph(csa->graph); +#if 0 /* 23/XI-2015 */ + xassert(gmp_pool_count() == 0); + gmp_free_mem(); +#endif + /* close log file, if necessary */ + if (csa->log_file != NULL) glp_close_tee(); + /* check that no memory blocks are still allocated */ +#if 0 /* 16/II-2012 */ + { int count; + glp_long total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(count == 0); + xassert(total.lo == 0 && total.hi == 0); + } +#else + { int count; + size_t total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(total == 0); + } +#endif + /* free the GLPK environment */ + glp_free_env(); + /* return to the control program */ + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/graceful.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/graceful.mod new file mode 100644 index 000000000..404206537 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/graceful.mod @@ -0,0 +1,152 @@ +/* Graceful Tree Labeling Problem */ + +/* Author: Mike Appleby */ + +/* The Graceful Labeling Problem for a tree G = (V, E), where V is the + set of vertices and E is the set of edges, is to find a labeling of + the vertices with the integers between 1 and |V| inclusive, such + that no two vertices share a label, and such that each edge is + uniquely identified by the positive, or absolute difference between + the labels of its endpoints. + + In other words, if vl are the vertex labels and el are the edge + labels, then for every edge (u,v) in E, el[u,v]=abs(vl[u] - vl[v]). + + https://en.wikipedia.org/wiki/Graceful_labeling */ + +set V; +/* set of vertices */ + +set E within V cross V; +/* set of edges */ + +set N := 1..card(V); +/* vertex labels */ + +set M := 1..card(V)-1; +/* edge labels */ + +var vx{V, N}, binary; +/* binary encoding of vertex labels. + vx[v,n] == 1 means vertex v has label n. */ + +s.t. vxa{v in V}: sum{n in N} vx[v,n] = 1; +/* each vertex is assigned exactly one label. */ + +s.t. vxb{n in N}: sum{v in V} vx[v,n] = 1; +/* each label is assigned to exactly one vertex. */ + +var vl{V}, integer, >= 1, <= card(V); +/* integer encoding of vertex labels. + vl[v] == n means vertex v has label n. */ + +s.t. vla{v in V}: vl[v] = sum{n in N} n * vx[v,n]; +/* by constraint vxa, exactly one of vx[v,n] == 1 and the rest are + zero. So if vx[v,3] == 1, then vl[v] = 3. */ + +var ex{E, M}, binary; +/* binary encoding of edge labels. + ex[u,v,n] == 1 means edge (u,v) has label n. */ + +s.t. exa{(u,v) in E}: sum{m in M} ex[u,v,m] = 1; +/* each edge is assigned exactly one label. */ + +s.t. exb{m in M}: sum{(u,v) in E} ex[u,v,m] = 1; +/* each label is assigned to exactly one edge. */ + +var el{E}, integer, >= 1, <= card(E); +/* integer encoding of edge labels. + el[u,v] == n means edge (u,v) has label n. */ + +s.t. ela{(u,v) in E}: el[u,v] = sum{m in M} m * ex[u,v,m]; +/* similar to vla above, define integer encoding of edge labels in + terms of the corresponding binary variable. */ + +var gt{E}, binary; +/* gt[u,v] = 1 if vl[u] > vl[v] else 0. + gt helps encode the absolute value constraint, below. */ + +s.t. elb{(u,v) in E}: el[u,v] >= vl[u] - vl[v]; +s.t. elc{(u,v) in E}: el[u,v] <= vl[u] - vl[v] + 2*card(V)*(1-gt[u,v]); +s.t. eld{(u,v) in E}: el[u,v] >= vl[v] - vl[u]; +s.t. ele{(u,v) in E}: el[u,v] <= vl[v] - vl[u] + 2*card(V)*gt[u,v]; + +/* These four constraints together model the absolute value constraint + of the graceful labeling problem: el[u,v] == abs(vl[u] - vl[v]). + However, since the absolute value is a non-linear function, we + transform it into a series of linear constraints, as above. + + To see that these four constraints model the absolute value + condition, consider the following cases: + + if vl[u] > vl[v] and gt[u,v] == 0 then + - ele is unsatisfiable, since the constraint ele amounts to + + el[u,v] <= vl[v] - vl[u] + 0 (since gt[u,v] == 0) + <= -1 (since vl[u] > vl[v]) + + but el[u,v] is declared with lower bound >= 1; hence, the + constraints cannot be satisfied if vl[u] > vl[v] and + gt[u,v] == 0. + + if vl[u] > vl[v] and gt[u,v] == 1 then + - elb and elc together are equivalent to + + vl[u] - vl[v] <= el[u,v] <= vl[u] - vl[v], i.e. + el[u,v] = vl[u] - vl[v] + = abs(vl[u] - vl[v]) (since vl[u] > vl[v]) + + - eld and elc together are equivalent to + + vl[v] - vl[u] <= el[u,v] <= vl[v] - vl[u] + 2|V| + + the tightest possible bounds are + + -1 <= el[u,v] <= |V|+1 + + which is satisfied since both bounds are looser than the + constraints on el's variable declaration, namely + + var el{E}, integer, >= 1, <= card(E); + + where |E| = |V|-1 + + The cases for vl[v] > vl[u] are similar, but with roles reversed + for elb/elc and eld/ele. + + In other words, when vl[u] > vl[v], then gt[u,v] == 1, elb and elc + together model the absolute value constraint, and ele and eld are + satisfied due to bounds constraints on el. When vl[v] > vl[u], then + gt[u,v] == 0, ele and eld model the absolute value constraint, and + elb and elc are satisfied due to bounds constraints on el. + + Note that vl[u] != vl[v], by a combination of constraints vxa, vxb, + and vla. */ + +solve; + +check 0 = card(N symdiff setof{v in V} vl[v]); +/* every vertex label is assigned to one vertex */ + +check 0 = card(M symdiff setof{(u,v) in E} el[u,v]); +/* every edge label is assigned to one edge */ + +check {(u,v) in E} el[u,v] = abs(vl[u] - vl[v]); +/* every edge label for every edge (u,v) == abs(vl[u] - vl[v]) */ + +printf "vertices:\n"; +for{v in V} { printf "\t%s: %d\n", v, vl[v]; } + +printf "edges:\n"; +printf "\torig\tvlabel\telabel\tabs(u-v)\n"; +for{(u,v) in E} { + printf "\t(%s,%s)\t(%d,%d)\t%d\t%d\n", + u, v, vl[u], vl[v], el[u,v], abs(vl[u]-vl[v]); +} + +data; + +set V := a b c d e f g; +set E := a b, a d, a g, b c, b e, e f; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/graph.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/graph.mod new file mode 100644 index 000000000..bdcc969ac --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/graph.mod @@ -0,0 +1,98 @@ +/* graph.mod - graph visualization */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* This model creates a picture in EPS format to visualize a graph. */ + +param file, symbolic, default "graph.eps"; +/* output file to write the picture */ + +param R, default 2; +/* radius to draw vertices, in mm */ + +param n, integer, > 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V; +/* set of edges */ + +param x{i in V}, default 50 * cos((i - 1) / card(V) * 8 * atan(1)); +param y{i in V}, default 50 * sin((i - 1) / card(V) * 8 * atan(1)); +/* x[i] and y[i] are coordinates of node i, in mm */ + +param x0 := (min{i in V} x[i]) - R - 3.0; +param y0 := (min{i in V} y[i]) - R - 3.0; +param x1 := (max{i in V} x[i]) + R + 3.0; +param y1 := (max{i in V} y[i]) + R + 3.0; + +printf "%%!PS-Adobe-3.0 EPSF-3.0\n" > file; +printf "%%%%BoundingBox: 0 0 %d %d\n", + (72 / 25.4) * (x1 - x0), (72 / 25.4) * (y1 - y0) >> file; +printf "/Helvetica findfont 6 scalefont setfont\n" >> file; +printf "/mm { 72 mul 25.4 div } def\n" >> file; + +for {(i,j) in E} +{ printf "newpath\n" >> file; + printf "%g mm %g mm moveto\n", x[i] - x0, y[i] - y0 >> file; + printf "%g mm %g mm lineto\n", x[j] - x0, y[j] - y0 >> file; + printf "closepath\n" >> file; + printf "stroke\n" >> file; +} + +for {i in V} +{ printf "newpath\n" >> file; + printf "%g mm %g mm %g mm 0 360 arc\n", + x[i] - x0, y[i] - y0, R >> file; + printf "closepath\n" >> file; + printf "gsave 1 1 1 setrgbcolor fill grestore\n" >> file; + printf "stroke\n" >> file; + printf "%g mm %g mm moveto\n", + x[i] - (if i <= 9 then 1.2 else 1.8) - x0, + y[i] - 0.8 - y0 >> file; + printf "( %d ) show\n", i >> file; +} + +printf "showpage\n" >> file; +printf "%%%%EOF\n" >> file; + +data; + +param +: V : x y := + 1 0 40 + 2 38 12 + 3 24 -32 + 4 -24 -32 + 5 -38 12 + 6 -19 26 + 7 19 26 + 8 31 -10 + 9 0 -32 + 10 -31 -10 + 11 -9 12 + 12 9 12 + 13 14 -5 + 14 0 -15 + 15 -14 -5 + 16 0 0 ; + +set E := + (1,*) 6 10 16 12 7 + (2,*) 7 6 16 13 8 + (3,*) 8 7 16 14 9 + (4,*) 9 8 16 15 10 + (5,*) 10 9 16 11 6 + (6,*) 14 + (7,*) 15 + (8,*) 11 + (9,*) 12 + (10,*) 13 + (11,*) 12 15 + (12,*) 13 + (13,*) 14 + (14,*) 15 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/hashi.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/hashi.mod new file mode 100644 index 000000000..48e8d9f7f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/hashi.mod @@ -0,0 +1,168 @@ +/* A solver for the Japanese number-puzzle Hashiwokakero + * (http://en.wikipedia.org/wiki/Hashiwokakero) + * + * Sebastian Nowozin , 13th January 2009 + */ + +param n := 25; +set rows := 1..n; +set cols := 1..n; +param givens{rows, cols}, integer, >= 0, <= 8, default 0; + +/* Set of vertices as (row,col) coordinates */ +set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; + +/* Set of feasible horizontal edges from (i,j) to (k,l) rightwards */ +set Eh := { (i,j,k,l) in { V, V }: + i = k and j < l and # Same row and left to right + card({ (s,t) in V: s = i and t > j and t < l }) = 0 # No vertex inbetween + }; + +/* Set of feasible vertical edges from (i,j) to (k,l) downwards */ +set Ev := { (i,j,k,l) in { V, V }: + j = l and i < k and # Same column and top to bottom + card({ (s,t) in V: t = j and s > i and s < k }) = 0 # No vertex inbetween + }; + +set E := Eh union Ev; + +/* Indicators: use edge once/twice */ +var xe1{E}, binary; +var xe2{E}, binary; + +/* Constraint: Do not use edge or do use once or do use twice */ +s.t. edge_sel{(i,j,k,l) in E}: + xe1[i,j,k,l] + xe2[i,j,k,l] <= 1; + +/* Constraint: There must be as many edges used as the node value */ +s.t. satisfy_vertex_demand{(s,t) in V}: + sum{(i,j,k,l) in E: (i = s and j = t) or (k = s and l = t)} + (xe1[i,j,k,l] + 2.0*xe2[i,j,k,l]) = givens[s,t]; + +/* Constraint: No crossings */ +s.t. no_crossing1{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe1[i,j,k,l] + xe1[s,t,u,v] <= 1; +s.t. no_crossing2{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe1[i,j,k,l] + xe2[s,t,u,v] <= 1; +s.t. no_crossing3{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe2[i,j,k,l] + xe1[s,t,u,v] <= 1; +s.t. no_crossing4{(i,j,k,l) in Eh, (s,t,u,v) in Ev: + s < i and u > i and j < t and l > t}: + xe2[i,j,k,l] + xe2[s,t,u,v] <= 1; + + +/* Model connectivity by auxiliary network flow problem: + * One vertex becomes a target node and all other vertices send a unit flow + * to it. The edge selection variables xe1/xe2 are VUB constraints and + * therefore xe1/xe2 select the feasible graph for the max-flow problems. + */ +set node_target := { (s,t) in V: + card({ (i,j) in V: i < s or (i = s and j < t) }) = 0}; +set node_sources := { (s,t) in V: (s,t) not in node_target }; + +var flow_forward{ E }, >= 0; +var flow_backward{ E }, >= 0; +s.t. flow_conservation{ (s,t) in node_target, (p,q) in V }: + /* All incoming flows */ + - sum{(i,j,k,l) in E: k = p and l = q} flow_forward[i,j,k,l] + - sum{(i,j,k,l) in E: i = p and j = q} flow_backward[i,j,k,l] + /* All outgoing flows */ + + sum{(i,j,k,l) in E: k = p and l = q} flow_backward[i,j,k,l] + + sum{(i,j,k,l) in E: i = p and j = q} flow_forward[i,j,k,l] + = 0 + (if (p = s and q = t) then card(node_sources) else -1); + +/* Variable-Upper-Bound (VUB) constraints: xe1/xe2 bound the flows. + */ +s.t. connectivity_vub1{(i,j,k,l) in E}: + flow_forward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); +s.t. connectivity_vub2{(i,j,k,l) in E}: + flow_backward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); + +/* A feasible solution is enough + */ +minimize cost: 0; + +solve; + +/* Output solution graphically */ +printf "\nSolution:\n"; +for { row in rows } { + for { col in cols } { + /* First print this cell information: givens or space */ + printf{0..0: givens[row,col] != 0} "%d", givens[row,col]; + printf{0..0: givens[row,col] = 0 and + card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe1[i,j,k,l] = 1}) = 1} "-"; + printf{0..0: givens[row,col] = 0 and + card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe2[i,j,k,l] = 1}) = 1} "="; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe1[i,j,k,l] = 1}) = 1} "|"; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe2[i,j,k,l] = 1}) = 1} '"'; + printf{0..0: givens[row,col] = 0 + and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and + (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0 + and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and + (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0} " "; + + /* Now print any edges */ + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1} "-"; + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1} "="; + + printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and + xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; + printf{0..0: card({(i,j,k,l) in Eh: i = row and col >= j and col < l}) = 0} " "; + } + printf "\n"; + for { col in cols } { + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1} "|"; + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1} '"'; + printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and + xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; + /* No vertical edges: skip also a field */ + printf{0..0: card({(i,j,k,l) in Ev: j = col and row >= i and row < k}) = 0} " "; + printf " "; + } + printf "\n"; +} + +data; + +/* This is a difficult 25x25 Hashiwokakero. + */ +param givens : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 +25 := + 1 2 . 2 . 2 . . 2 . 2 . . 2 . . . . 2 . 2 . 2 . 2 . + 2 . 1 . . . . 2 . . . 4 . . 5 . 2 . . 1 . 2 . 2 . 1 + 3 2 . . 5 . 4 . . 3 . . . . . 1 . . 4 . 5 . 1 . 1 . + 4 . . . . . . . . . . . 1 . 3 . . 1 . . . . . . . . + 5 2 . . 6 . 6 . . 8 . 5 . 2 . . 3 . 5 . 7 . . 2 . . + 6 . 1 . . . . . . . . . 1 . . 2 . . . . . 1 . . . 3 + 7 2 . . . . 5 . . 6 . 4 . . 2 . . . 2 . 5 . 4 . 2 . + 8 . 2 . 2 . . . . . . . . . . . 3 . . 3 . . . 1 . 2 + 9 . . . . . . . . . . 4 . 2 . 2 . . 1 . . . 3 . 1 . + 10 2 . 3 . . 6 . . 2 . . . . . . . . . . 3 . . . . . + 11 . . . . 1 . . 2 . . 5 . . 1 . 4 . 3 . . . . 2 . 4 + 12 . . 2 . . 1 . . . . . . 5 . 4 . . . . 4 . 3 . . . + 13 2 . . . 3 . 1 . . . . . . . . 3 . . 5 . 5 . . 2 . + 14 . . . . . 2 . 5 . . 7 . 5 . 3 . 1 . . 1 . . 1 . 4 + 15 2 . 5 . 3 . . . . 1 . 2 . 1 . . . . 2 . 4 . . 2 . + 16 . . . . . 1 . . . . . . . . . . 2 . . 2 . 1 . . 3 + 17 2 . 6 . 6 . . 2 . . 2 . 2 . 5 . . . . . 2 . . . . + 18 . . . . . 1 . . . 3 . . . . . 1 . . 1 . . 4 . 3 . + 19 . . 4 . 5 . . 2 . . . 2 . . 6 . 6 . . 3 . . . . 3 + 20 2 . . . . . . . . . 2 . . 1 . . . . . . 1 . . 1 . + 21 . . 3 . . 3 . 5 . 5 . . 4 . 6 . 7 . . 4 . 6 . . 4 + 22 2 . . . 3 . 5 . 2 . 1 . . . . . . . . . . . . . . + 23 . . . . . . . . . 1 . . . . . . 3 . 2 . . 5 . . 5 + 24 2 . 3 . 3 . 5 . 4 . 3 . 3 . 4 . . 2 . 2 . . . 1 . + 25 . 1 . 2 . 2 . . . 2 . 2 . . . 2 . . . . 2 . 2 . 2 + ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/huge.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/huge.mod new file mode 100644 index 000000000..a7d17e4c5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/huge.mod @@ -0,0 +1,25 @@ +/*Arithmetic Mean of a large number of Integers + - or - solve a very large constraint matrix + over 1 million rows and columns + Nigel_Galloway@operamail.com + March 18th., 2008. +*/ + +param e := 20; +/* set Sample := {-2**e..2**e-1}; */ +set Sample := {1..2**e-1}; + +var Mean; +var E{z in Sample}; + +/* sum of variances is zero */ +zumVariance: sum{z in Sample} E[z] = 0; + +/* Mean + variance[n] = Sample[n] */ +variances{z in Sample}: Mean + E[z] = z; + +solve; + +printf "The arithmetic mean of the integers from 1 to %d is %f\n", 2**e-1, Mean; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/icecream.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/icecream.mps new file mode 100644 index 000000000..5d741306d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/icecream.mps @@ -0,0 +1,345 @@ +*NAME: ICECREAM +*ROWS: 17 +*COLUMNS: 27 +*NONZERO: 264 +*OPT SOLN: 962.8214691 +*SOURCE: Linear Programming--Ice Cream Blending +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Ice Cream Blending +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME ICECREAM +ROWS + N COST $ Minimum cost $ + G MIN.BF $ Butterfat lbs + L MAX.BF + G MIN.MSNF $ Milk solids (nonfat) lbs + L MAX.MSNF + G MIN.TMS $ Total milk solids lbs + L MAX.TMS + G MIN.SUG $ Sweetness lbs + L MAX.SUG + L CSS $ Corn syrup solids lbs + G MIN.TS $ Total solids lbs + L MAX.TS + G MIN.H2O $ Water lbs + L MAX.H2O + E STAB $ Stabilizer lbs + E EMUL $ Emulsifier lbs + E YIELD $ Amount to be made lbs +COLUMNS +* Cream (40%) + I1 COST 27.9 + MIN.BF .40 + MAX.BF .40 + MIN.MSNF .054 + MAX.MSNF .054 + MIN.TMS .454 + MAX.TMS .454 + MIN.TS .454 + MAX.TS .454 + MIN.H2O .546 + MAX.H2O .546 + YIELD 1 +* Cream (38%) + I2 COST 26.3 + MIN.BF .38 + MAX.BF .38 + MIN.MSNF .056 + MAX.MSNF .056 + MIN.TMS .436 + MAX.TMS .436 + MIN.TS .436 + MAX.TS .436 + MIN.H2O .564 + MAX.H2O .564 + YIELD 1 +* Milk (3.2%) + I3 COST 3.2 + MIN.BF .032 + MAX.BF .032 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .119 + MAX.TMS .119 + MIN.TS .119 + MAX.TS .119 + MIN.H2O .881 + MAX.H2O .881 + YIELD 1 +* Milk (3.4%) + I4 COST 3.2 + MIN.BF .034 + MAX.BF .034 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .121 + MAX.TMS .121 + MIN.TS .121 + MAX.TS .121 + MIN.H2O .879 + MAX.H2O .879 + YIELD 1 +* Milk (3.5%) + I5 COST 3.3 + MIN.BF .035 + MAX.BF .035 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .122 + MAX.TMS .122 + MIN.TS .122 + MAX.TS .122 + MIN.H2O .879 + MAX.H2O .879 + YIELD 1 +* Milk (3.6%) + I6 COST 3.3 + MIN.BF .036 + MAX.BF .036 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .123 + MAX.TMS .123 + MIN.TS .123 + MAX.TS .123 + MIN.H2O .877 + MAX.H2O .877 + YIELD 1 +* Milk (3.7%) + I7 COST 3.4 + MIN.BF .037 + MAX.BF .037 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .124 + MAX.TMS .124 + MIN.TS .124 + MAX.TS .124 + MIN.H2O .876 + MAX.H2O .876 + YIELD 1 +* Milk (3.8%) + I8 COST 3.5 + MIN.BF .038 + MAX.BF .038 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .125 + MAX.TMS .125 + MIN.TS .125 + MAX.TS .125 + MIN.H2O .875 + MAX.H2O .875 + YIELD 1 +* Milk (3.9%) + I9 COST 3.5 + MIN.BF .039 + MAX.BF .039 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .125 + MAX.TMS .125 + MIN.TS .125 + MAX.TS .125 + MIN.H2O .875 + MAX.H2O .875 + YIELD 1 +* Milk (4.0%) + I10 COST 3.6 + MIN.BF .040 + MAX.BF .040 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .126 + MAX.TMS .126 + MIN.TS .126 + MAX.TS .126 + MIN.H2O .874 + MAX.H2O .874 + YIELD 1 +* Milk (4.2%) + I11 COST 3.7 + MIN.BF .042 + MAX.BF .042 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .128 + MAX.TMS .128 + MIN.TS .128 + MAX.TS .128 + MIN.H2O .872 + MAX.H2O .872 + YIELD 1 +* Skim Milk + I12 COST 1.8 + MIN.MSNF .09 + MAX.MSNF .09 + MIN.TMS .09 + MAX.TMS .09 + MIN.TS .09 + MAX.TS .09 + MIN.H2O .91 + MAX.H2O .91 + YIELD 1 +* Condensed Whole Milk + I13 COST 7.6 + MIN.BF .08 + MAX.BF .08 + MIN.MSNF .2 + MAX.MSNF .2 + MIN.TMS .28 + MAX.TMS .28 + MIN.TS .28 + MAX.TS .28 + MIN.H2O .72 + MAX.H2O .72 + YIELD 1 +* Condensed Skim Milk (28%) + I14 COST 3.9 + MIN.MSNF .28 + MAX.MSNF .28 + MIN.TMS .28 + MAX.TMS .28 + MIN.TS .28 + MAX.TS .28 + MIN.H2O .72 + MAX.H2O .72 + YIELD 1 +* Condensed Skim Milk (30%) + I15 COST 4.9 + MIN.MSNF .3 + MAX.MSNF .3 + MIN.TMS .3 + MAX.TMS .3 + MIN.TS .3 + MAX.TS .3 + MIN.H2O .7 + MAX.H2O .7 + YIELD 1 +* Condensed Skim Milk (32%) + I16 COST 4.5 + MIN.MSNF .32 + MAX.MSNF .32 + MIN.TMS .32 + MAX.TMS .32 + MIN.TS .32 + MAX.TS .32 + MIN.H2O .68 + MAX.H2O .68 + YIELD 1 +* Dry Skim Milk + I17 COST 14.8 + MIN.BF .01 + MAX.BF .01 + MIN.MSNF .96 + MAX.MSNF .96 + MIN.TMS .97 + MAX.TMS .97 + MIN.TS .97 + MAX.TS .97 + MIN.H2O .03 + MAX.H2O .03 + YIELD 1 +* Dry Buttermilk + I18 COST 15.0 + MIN.BF .05 + MAX.BF .05 + MIN.MSNF .92 + MAX.MSNF .92 + MIN.TMS .97 + MAX.TMS .97 + MIN.TS .97 + MAX.TS .97 + MIN.H2O .03 + MAX.H2O .03 + YIELD 1 +* Dry Whey Solids + I19 COST 10.7 + MIN.MSNF .95 + MAX.MSNF .95 + MIN.TMS .95 + MAX.TMS .95 + MIN.TS .95 + MAX.TS .95 + MIN.H2O .05 + MAX.H2O .05 + YIELD 1 +* Dry Sucrose + I20 COST 10.2 + MIN.SUG 1.0 + MAX.SUG 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Cane Syrup + I21 COST 9.9 + MIN.SUG .67 + MAX.SUG .67 + MIN.TS .67 + MAX.TS .67 + MIN.H2O .33 + MAX.H2O .33 + YIELD 1 +* Corn Sgr. Solids (50% Sweetness) + I22 COST 7.0 + MIN.SUG .5 + MAX.SUG .5 + CSS 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Corn Sgr. Solids (45% Sweetness) + I23 COST 9.0 + MIN.SUG .45 + MAX.SUG .45 + CSS 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Corn Syrup + I24 COST 6.6 + MIN.SUG .4 + MAX.SUG .4 + CSS .8 + MIN.TS .8 + MAX.TS .8 + MIN.H2O .2 + MAX.H2O .2 + YIELD 1 +* Stabilizer + I25 COST 55.0 + STAB 1.0 + YIELD 1 +* Emulsifier + I26 COST 78.0 + EMUL 1.0 + YIELD 1 +* Water + I27 COST 0 + MIN.H2O 1.0 + MAX.H2O 1.0 + YIELD 1 +RHS + MIN.BF 10 + MAX.BF 16 + MIN.MSNF 10.5 + MAX.MSNF 13 + MIN.TMS 20.5 + MAX.TMS 25 + MIN.SUG 11 + MAX.SUG 17 + CSS 6 + MIN.TS 37.5 + MAX.TS 41.5 + MIN.H2O 58.5 + MAX.H2O 62.5 + STAB .37 + EMUL .01 + YIELD 100 +BOUNDS + UP I1 10 + LO I6 40 + UP I19 4 +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/iptsamp.c b/WebAPP/SOLVERs/GLPK/glpk/examples/iptsamp.c new file mode 100644 index 000000000..d622d7361 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/iptsamp.c @@ -0,0 +1,17 @@ +/* iptsamp.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_interior(P, NULL); + glp_print_ipt(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/jssp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/jssp.mod new file mode 100644 index 000000000..7ee51b989 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/jssp.mod @@ -0,0 +1,114 @@ +/* JSSP, Job-Shop Scheduling Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Job-Shop Scheduling Problem (JSSP) is to schedule a set of jobs + on a set of machines, subject to the constraint that each machine can + handle at most one job at a time and the fact that each job has a + specified processing order through the machines. The objective is to + schedule the jobs so as to minimize the maximum of their completion + times. + + Reference: + D. Applegate and W. Cook, "A Computational Study of the Job-Shop + Scheduling Problem", ORSA J. On Comput., Vol. 3, No. 2, Spring 1991, + pp. 149-156. */ + +param n, integer, > 0; +/* number of jobs */ + +param m, integer, > 0; +/* number of machines */ + +set J := 1..n; +/* set of jobs */ + +set M := 1..m; +/* set of machines */ + +param sigma{j in J, t in 1..m}, in M; +/* permutation of the machines, which represents the processing order + of j through the machines: j must be processed first on sigma[j,1], + then on sigma[j,2], etc. */ + +check{j in J, t1 in 1..m, t2 in 1..m: t1 <> t2}: + sigma[j,t1] != sigma[j,t2]; +/* sigma must be permutation */ + +param p{j in J, a in M}, >= 0; +/* processing time of j on a */ + +var x{j in J, a in M}, >= 0; +/* starting time of j on a */ + +s.t. ord{j in J, t in 2..m}: + x[j, sigma[j,t]] >= x[j, sigma[j,t-1]] + p[j, sigma[j,t-1]]; +/* j can be processed on sigma[j,t] only after it has been completely + processed on sigma[j,t-1] */ + +/* The disjunctive condition that each machine can handle at most one + job at a time is the following: + + x[i,a] >= x[j,a] + p[j,a] or x[j,a] >= x[i,a] + p[i,a] + + for all i, j in J, a in M. This condition is modeled through binary + variables Y as shown below. */ + +var Y{i in J, j in J, a in M}, binary; +/* Y[i,j,a] is 1 if i scheduled before j on machine a, and 0 if j is + scheduled before i */ + +param K := sum{j in J, a in M} p[j,a]; +/* some large constant */ + +display K; + +s.t. phi{i in J, j in J, a in M: i <> j}: + x[i,a] >= x[j,a] + p[j,a] - K * Y[i,j,a]; +/* x[i,a] >= x[j,a] + p[j,a] iff Y[i,j,a] is 0 */ + +s.t. psi{i in J, j in J, a in M: i <> j}: + x[j,a] >= x[i,a] + p[i,a] - K * (1 - Y[i,j,a]); +/* x[j,a] >= x[i,a] + p[i,a] iff Y[i,j,a] is 1 */ + +var z; +/* so-called makespan */ + +s.t. fin{j in J}: z >= x[j, sigma[j,m]] + p[j, sigma[j,m]]; +/* which is the maximum of the completion times of all the jobs */ + +minimize obj: z; +/* the objective is to make z as small as possible */ + +data; + +/* These data correspond to the instance ft06 (mt06) from: + + H. Fisher, G.L. Thompson (1963), Probabilistic learning combinations + of local job-shop scheduling rules, J.F. Muth, G.L. Thompson (eds.), + Industrial Scheduling, Prentice Hall, Englewood Cliffs, New Jersey, + 225-251 */ + +/* The optimal solution is 55 */ + +param n := 6; + +param m := 6; + +param sigma : 1 2 3 4 5 6 := + 1 3 1 2 4 6 5 + 2 2 3 5 6 1 4 + 3 3 4 6 1 2 5 + 4 2 1 3 4 5 6 + 5 3 2 5 6 1 4 + 6 2 4 6 1 5 3 ; + +param p : 1 2 3 4 5 6 := + 1 3 6 1 7 6 3 + 2 10 8 5 4 10 10 + 3 9 1 5 4 7 8 + 4 5 5 5 3 8 9 + 5 3 3 9 1 5 4 + 6 10 3 1 3 4 9 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/life_goe.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/life_goe.mod new file mode 100644 index 000000000..57ca3c367 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/life_goe.mod @@ -0,0 +1,165 @@ +/* Conway's Game of Life garden of eden checker */ + +/* Written and converted to GNU MathProg by NASZVADI, Peter, 199x-2017 + */ + +/* + Conway's Game of Life (ref'd: CGoL) is a Cellular Automata described and + inspected by John H. Conway in the 1970s. CGoL is nothing but a 0-player + game on an infinite two-dimensional Euclydean grid. In the beginning of + the "game", some 1 values are put on some of the grid vertices, and all + others are set to 0. Grid vertices with values are called cells, and a + cell is called "alive", if its value is 1, and called "dead" otherwise, + these are the two "states". The game then turns to an infinite repetitive + process: all cells change together independently at the same time their + states depending only on their actual state and the actual number of + living cells in their so called Moore-neighbourhood: the 4 orthogonal and + 4 diagonal neighbouring cells. Conway also defined the transitions rule: + dead cell become alive if it has exactly 3 living adjacents, and an alive + cell survives only if it has 2 or 3 living neighbours. After executing a + transition for all cells, the two patterns are in a relationship: the + older is the father, the newer is the child. + + It is an interesting problem both in Mathematics and Phylosophy if + there is a fatherless pattern (in CGoL). Fairly trivial existence + proofs had been published since then, and immediately explicit + constructions are followed. + + This GMPL model searches for a father pattern of the pattern specified in + the c parameter matrix, and prints the found one if any both in human + readable format and in RLE format, which could be open with some Cellular + Automata simulators like Golly, for example. + + See more about Garden of Edens: + http://conwaylife.com/wiki/Garden_of_Eden + + Golly CA simulator: + http://golly.sourceforge.net/ + + Tip for running with the example pattern: + glpsol --math life_goe.mod --cuts --last + + WARNING: Rather CPU- and memory-intensive process to find out if a given + pattern is a GOE if it really is! +*/ + +param height, integer, > 0; +/* height of the successor pattern */ + +param width, integer, > 0; +/* width of the successor pattern */ + +set ROWS := 0..height + 1; +/* set of rows of the predecessor */ + +set COLUMNS := 0..width + 1; +/* set of columns of the predecessor */ + +set MOORE := {(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, 1), (1, -1), + (-1, -1)}; +/* Moore-neighbourhood relative coordinates */ + +param c{ROWS, COLUMNS}, >= 0; +/* Denotes the cellspace of 1st generation, where 0, 1 and 2 means dead, + alive or arbitrary cell values respectively. Usually the frame values + must be set to "2", and also "2" is allowed in the inner rectangle. */ + +set IJalive := setof{(i, j) in ROWS cross COLUMNS: c[i, j] = 1}(i, j); +/* set of alive cells in the child */ + +set IJdead := setof{(i, j) in ROWS cross COLUMNS: c[i, j] = 0}(i, j); +/* set of dead cells in the child */ + +set IJ := IJalive union IJdead; +/* set of cells in the child with enforced states */ + +var x{ROWS, COLUMNS}, binary; +/* father's states */ + +var dpos{ROWS, COLUMNS}, >= 0; +/* positive part of the distances from 6 */ + +var dneg{ROWS, COLUMNS}, >= 0; +/* negative part of the distances from 6 */ + +var dposup{ROWS, COLUMNS}, binary; +/* positive part's upper bound enforcement */ + +var dnegup{ROWS, COLUMNS}, binary; +/* negative part's upper bound enforcement */ + +s.t. maincons{(i, j) in IJ}: + x[i, j] + sum{(a, b) in MOORE} (2 * x[i + a, j + b]) = + 6 + dpos[i,j] - dneg[i,j]; +/* in the LHS, there is a function that maps from all possible 512 state + combinations of a father cell and its Moore-neighbourhood to [0..17]. + And for CGoL, if the child is alive, then it should be between 5 and 7. + Also implicit introduced "d" as distance from 6 in RHS, and immediately + decomposed "d" into positive and negative parts denoted dpos and dneg. */ + +s.t. posbound{(i,j) in IJ}: dpos[i,j] <= 11 * dposup[i,j]; +/* constraining positive part of distance */ + +s.t. negbound{(i,j) in IJ}: dneg[i,j] <= 6 * dnegup[i,j]; +/* constraining negative part of distance */ + +s.t. mutex{(i,j) in IJ}: dposup[i,j] + dnegup[i,j] = 1; +/* Ensuring that at most one is positive among the pos./neg. parts */ + +s.t. alive{(i,j) in IJalive}: dpos[i,j] + dneg[i,j] <= 1; +/* LHS of maincons must be 5, 6 or 7 either due to child cell is alive */ + +s.t. dead{(i,j) in IJdead}: dpos[i,j] + dneg[i,j] >= 2; +/* LHS of maincons must be at most 4 or at least 8 */ + +/* This is a feasibility problem, so no objective is needed */ + +solve; + +printf '\nFound a father pattern:\n\n'; +for{i in ROWS}{ + for{j in COLUMNS}{ + printf '%s%s', if j then ' ' else '', x[i, j].val; + } + printf '\n'; +} + +printf '\nThe father pattern in rle format:\n\n'; +for{i in ROWS}{ + for{j in COLUMNS}{ + printf '%s', if x[i, j].val then 'o' else 'b'; + } + printf '$'; +} +printf '!\n\n'; + +data; +/* + This example is a halved of a 10x10 garden of eden pattern from: + http://wwwhomes.uni-bielefeld.de/achim/orphan_7th.html + It has a 90 degree rotational symmetry, so if having enough resources, + just comment the line denoted with "8", and uncomment the following part! + And also do not forget to increase height parameter, respectively! +*/ + +param height := 7; + +param width := 10; + +param c : 0 1 2 3 4 5 6 7 8 9 10 11 := + 0 2 2 2 2 2 2 2 2 2 2 2 2 + 1 2 0 1 0 1 1 1 0 1 0 0 2 + 2 2 0 0 1 0 1 0 1 0 0 1 2 + 3 2 1 0 1 1 1 0 0 1 1 0 2 + 4 2 0 1 0 1 1 1 1 1 0 1 2 + 5 2 1 0 0 1 0 0 1 1 1 1 2 + 6 2 1 1 1 1 0 0 1 0 0 1 2 + 7 2 1 0 1 1 1 1 1 0 1 0 2 + 8 2 2 2 2 2 2 2 2 2 2 2 2; + +/* 8 2 0 1 1 0 0 1 1 1 0 1 2 + 9 2 1 0 0 1 0 1 0 1 0 0 2 + 10 2 0 0 1 0 1 1 1 0 1 0 2 + 11 2 2 2 2 2 2 2 2 2 2 2 2; */ + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/magic.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/magic.mod new file mode 100644 index 000000000..d1e64d018 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/magic.mod @@ -0,0 +1,54 @@ +/* MAGIC, Magic Square */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* In recreational mathematics, a magic square of order n is an + arrangement of n^2 numbers, usually distinct integers, in a square, + such that n numbers in all rows, all columns, and both diagonals sum + to the same constant. A normal magic square contains the integers + from 1 to n^2. + + (From Wikipedia, the free encyclopedia.) */ + +param n, integer, > 0, default 4; +/* square order */ + +set N := 1..n^2; +/* integers to be placed */ + +var x{i in 1..n, j in 1..n, k in N}, binary; +/* x[i,j,k] = 1 means that cell (i,j) contains integer k */ + +s.t. a{i in 1..n, j in 1..n}: sum{k in N} x[i,j,k] = 1; +/* each cell must be assigned exactly one integer */ + +s.t. b{k in N}: sum{i in 1..n, j in 1..n} x[i,j,k] = 1; +/* each integer must be assigned exactly to one cell */ + +var s; +/* the magic sum */ + +s.t. r{i in 1..n}: sum{j in 1..n, k in N} k * x[i,j,k] = s; +/* the sum in each row must be the magic sum */ + +s.t. c{j in 1..n}: sum{i in 1..n, k in N} k * x[i,j,k] = s; +/* the sum in each column must be the magic sum */ + +s.t. d: sum{i in 1..n, k in N} k * x[i,i,k] = s; +/* the sum in the diagonal must be the magic sum */ + +s.t. e: sum{i in 1..n, k in N} k * x[i,n-i+1,k] = s; +/* the sum in the co-diagonal must be the magic sum */ + +solve; + +printf "\n"; +printf "Magic sum is %d\n", s; +printf "\n"; +for{i in 1..n} +{ printf{j in 1..n} "%3d", sum{k in N} k * x[i,j,k]; + printf "\n"; +} +printf "\n"; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/maxcut.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/maxcut.mod new file mode 100644 index 000000000..db30b92e5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/maxcut.mod @@ -0,0 +1,85 @@ +/* MAXCUT, Maximum Cut Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Maximum Cut Problem in a network G = (V, E), where V is a set + of nodes, E is a set of edges, is to find the partition of V into + disjoint sets V1 and V2, which maximizes the sum of edge weights + w(e), where edge e has one endpoint in V1 and other endpoint in V2. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Network design, Cuts and + Connectivity, Maximum Cut, ND16]. */ + +set E, dimen 2; +/* set of edges */ + +param w{(i,j) in E}, >= 0, default 1; +/* w[i,j] is weight of edge (i,j) */ + +set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); +/* set of nodes */ + +var x{i in V}, binary; +/* x[i] = 0 means that node i is in set V1 + x[i] = 1 means that node i is in set V2 */ + +/* We need to include in the objective function only that edges (i,j) + from E, for which x[i] != x[j]. This can be modeled through binary + variables s[i,j] as follows: + + s[i,j] = x[i] xor x[j] = (x[i] + x[j]) mod 2, (1) + + where s[i,j] = 1 iff x[i] != x[j], that leads to the following + objective function: + + z = sum{(i,j) in E} w[i,j] * s[i,j]. (2) + + To describe "exclusive or" (1) we could think that s[i,j] is a minor + bit of the sum x[i] + x[j]. Then introducing binary variables t[i,j], + which represent a major bit of the sum x[i] + x[j], we can write: + + x[i] + x[j] = s[i,j] + 2 * t[i,j]. (3) + + An easy check shows that conditions (1) and (3) are equivalent. + + Note that condition (3) can be simplified by eliminating variables + s[i,j]. Indeed, from (3) it follows that: + + s[i,j] = x[i] + x[j] - 2 * t[i,j]. (4) + + Since the expression in the right-hand side of (4) is integral, this + condition can be rewritten in the equivalent form: + + 0 <= x[i] + x[j] - 2 * t[i,j] <= 1. (5) + + (One might note that (5) means t[i,j] = x[i] and x[j].) + + Substituting s[i,j] from (4) to (2) leads to the following objective + function: + + z = sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]), (6) + + which does not include variables s[i,j]. */ + +var t{(i,j) in E}, binary; +/* t[i,j] = x[i] and x[j] = (x[i] + x[j]) div 2 */ + +s.t. xor{(i,j) in E}: 0 <= x[i] + x[j] - 2 * t[i,j] <= 1; +/* see (4) */ + +maximize z: sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]); +/* see (6) */ + +data; + +/* In this example the network has 15 nodes and 22 edges. */ + +/* Optimal solution is 20 */ + +set E := + 1 2, 1 5, 2 3, 2 6, 3 4, 3 8, 4 9, 5 6, 5 7, 6 8, 7 8, 7 12, 8 9, + 8 12, 9 10, 9 14, 10 11, 10 14, 11 15, 12 13, 13 14, 14 15; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/maxflow.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/maxflow.mod new file mode 100644 index 000000000..20dfc3ee2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/maxflow.mod @@ -0,0 +1,83 @@ +/* MAXFLOW, Maximum Flow Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Maximum Flow Problem in a network G = (V, E), where V is a set + of nodes, E within V x V is a set of arcs, is to maximize the flow + from one given node s (source) to another given node t (sink) subject + to conservation of flow constraints at each node and flow capacities + on each arc. */ + +param n, integer, >= 2; +/* number of nodes */ + +set V, default {1..n}; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +param a{(i,j) in E}, > 0; +/* a[i,j] is capacity of arc (i,j) */ + +param s, symbolic, in V, default 1; +/* source node */ + +param t, symbolic, in V, != s, default n; +/* sink node */ + +var x{(i,j) in E}, >= 0, <= a[i,j]; +/* x[i,j] is elementary flow through arc (i,j) to be found */ + +var flow, >= 0; +/* total flow from s to t */ + +s.t. node{i in V}: +/* node[i] is conservation constraint for node i */ + + sum{(j,i) in E} x[j,i] + (if i = s then flow) + /* summary flow into node i through all ingoing arcs */ + + = /* must be equal to */ + + sum{(i,j) in E} x[i,j] + (if i = t then flow); + /* summary flow from node i through all outgoing arcs */ + +maximize obj: flow; +/* objective is to maximize the total flow through the network */ + +solve; + +printf{1..56} "="; printf "\n"; +printf "Maximum flow from node %s to node %s is %g\n\n", s, t, flow; +printf "Starting node Ending node Arc capacity Flow in arc\n"; +printf "------------- ----------- ------------ -----------\n"; +printf{(i,j) in E: x[i,j] != 0}: "%13s %11s %12g %11g\n", i, j, + a[i,j], x[i,j]; +printf{1..56} "="; printf "\n"; + +data; + +/* These data correspond to an example from [Christofides]. */ + +/* Optimal solution is 29 */ + +param n := 9; + +param : E : a := + 1 2 14 + 1 4 23 + 2 3 10 + 2 4 9 + 3 5 12 + 3 8 18 + 4 5 26 + 5 2 11 + 5 6 25 + 5 7 4 + 6 7 7 + 6 8 8 + 7 9 15 + 8 9 20; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/mfasp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/mfasp.mod new file mode 100644 index 000000000..b4382818a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/mfasp.mod @@ -0,0 +1,62 @@ +/* MFASP, Minimum Feedback Arc Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Minimum Feedback Arc Set Problem for a given directed graph + G = (V, E), where V is a set of vertices and E is a set of arcs, is + to find a minimal subset of arcs, which being removed from the graph + make it acyclic. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Feedback Arc Set, GT9]. */ + +param n, integer, >= 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V, +default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); +/* set of arcs */ + +printf "Graph has %d vertices and %d arcs\n", card(V), card(E); + +var x{(i,j) in E}, binary; +/* x[i,j] = 1 means that (i->j) is a feedback arc */ + +/* It is known that a digraph G = (V, E) is acyclic if and only if its + vertices can be assigned numbers from 1 to |V| in such a way that + k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number + assigned to vertex i. We may use this condition to require that the + digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is + acyclic. */ + +var k{i in V}, >= 1, <= card(V); +/* k[i] is a number assigned to vertex i */ + +s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * x[i,j]; +/* note that x[i,j] = 1 leads to a redundant constraint */ + +minimize obj: sum{(i,j) in E} x[i,j]; +/* the objective is to minimize the cardinality of a subset of feedback + arcs */ + +solve; + +printf "Minimum feedback arc set:\n"; +printf{(i,j) in E: x[i,j]} "%d %d\n", i, j; + +data; + +/* The optimal solution is 3 */ + +param n := 15; + +set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, + 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, + 14 9, 15 14; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/mfvsp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/mfvsp.mod new file mode 100644 index 000000000..a03009dea --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/mfvsp.mod @@ -0,0 +1,62 @@ +/* MFVSP, Minimum Feedback Vertex Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Minimum Feedback Vertex Set Problem for a given directed graph + G = (V, E), where V is a set of vertices and E is a set of arcs, is + to find a minimal subset of vertices, which being removed from the + graph make it acyclic. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Feedback Vertex Set, GT8]. */ + +param n, integer, >= 0; +/* number of vertices */ + +set V, default 1..n; +/* set of vertices */ + +set E, within V cross V, +default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); +/* set of arcs */ + +printf "Graph has %d vertices and %d arcs\n", card(V), card(E); + +var x{i in V}, binary; +/* x[i] = 1 means that i is a feedback vertex */ + +/* It is known that a digraph G = (V, E) is acyclic if and only if its + vertices can be assigned numbers from 1 to |V| in such a way that + k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number + assigned to vertex i. We may use this condition to require that the + digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is + acyclic. */ + +var k{i in V}, >= 1, <= card(V); +/* k[i] is a number assigned to vertex i */ + +s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * (x[i] + x[j]); +/* note that x[i] = 1 or x[j] = 1 leads to a redundant constraint */ + +minimize obj: sum{i in V} x[i]; +/* the objective is to minimize the cardinality of a subset of feedback + vertices */ + +solve; + +printf "Minimum feedback vertex set:\n"; +printf{i in V: x[i]} "%d\n", i; + +data; + +/* The optimal solution is 3 */ + +param n := 15; + +set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, + 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, + 14 9, 15 14; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/min01ks.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/min01ks.mod new file mode 100644 index 000000000..4baa3f406 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/min01ks.mod @@ -0,0 +1,111 @@ +/* min01ks.mod - finding minimal equivalent 0-1 knapsack inequality */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* It is obvious that for a given 0-1 knapsack inequality + + a[1] x[1] + ... + a[n] x[n] <= b, x[j] in {0, 1} (1) + + there exist infinitely many equivalent inequalities with exactly the + same feasible solutions. + + Given a[j]'s and b this model allows to find an inequality + + alfa[1] x[1] + ... + alfa[n] x[n] <= beta, x[j] in {0, 1}, (2) + + which is equivalent to (1) and where alfa[j]'s and beta are smallest + non-negative integers. + + This model has the following formulation: + + minimize + + z = |alfa[1]| + ... + |alfa[n]| + |beta| = (3) + + = alfa[1] + ... + alfa[n] + beta + + subject to + + alfa[1] x[1] + ... + alfa[n] x[n] <= beta (4) + + for all x satisfying to (1) + + alfa[1] x[1] + ... + alfa[n] x[n] >= beta + 1 (5) + + for all x not satisfying to (1) + + alfa[1], ..., alfa[n], beta are non-negative integers. + + Note that this model has n+1 variables and 2^n constraints. + + It is interesting, as noticed in [1] and explained in [2], that + in most cases LP relaxation of the MIP formulation above has integer + optimal solution. + + References + + 1. G.H.Bradley, P.L.Hammer, L.Wolsey, "Coefficient Reduction for + Inequalities in 0-1 Variables", Math.Prog.7 (1974), 263-282. + + 2. G.J.Koehler, "A Study on Coefficient Reduction of Binary Knapsack + Inequalities", University of Florida, 2001. */ + +param n, integer, > 0; +/* number of variables in the knapsack inequality */ + +set N := 1..n; +/* set of knapsack items */ + +/* all binary n-vectors are numbered by 0, 1, ..., 2^n-1, where vector + 0 is 00...00, vector 1 is 00...01, etc. */ + +set U := 0..2^n-1; +/* set of numbers of all binary n-vectors */ + +param x{i in U, j in N}, binary, := (i div 2^(j-1)) mod 2; +/* x[i,j] is j-th component of i-th binary n-vector */ + +param a{j in N}, >= 0; +/* original coefficients */ + +param b, >= 0; +/* original right-hand side */ + +set D := setof{i in U: sum{j in N} a[j] * x[i,j] <= b} i; +/* set of numbers of binary n-vectors, which (vectors) are feasible, + i.e. satisfy to the original knapsack inequality (1) */ + +var alfa{j in N}, integer, >= 0; +/* coefficients to be found */ + +var beta, integer, >= 0; +/* right-hand side to be found */ + +minimize z: sum{j in N} alfa[j] + beta; /* (3) */ + +phi{i in D}: sum{j in N} alfa[j] * x[i,j] <= beta; /* (4) */ + +psi{i in U diff D}: sum{j in N} alfa[j] * x[i,j] >= beta + 1; /* (5) */ + +solve; + +printf "\nOriginal 0-1 knapsack inequality:\n"; +for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", + a[j], j; +printf " <= %g\n", b; +printf "\nMinimized equivalent inequality:\n"; +for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", + alfa[j], j; +printf " <= %g\n\n", beta; + +data; + +/* These data correspond to the very first example from [1]. */ + +param n := 8; + +param a := [1]65, [2]64, [3]41, [4]22, [5]13, [6]12, [7]8, [8]2; + +param b := 80; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/misp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/misp.mod new file mode 100644 index 000000000..b2b1f6b94 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/misp.mod @@ -0,0 +1,665 @@ +/* MISP, Maximum Independent Set Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Let G = (V,E) be an undirected graph with vertex set V and edge set + * E. Vertices u, v in V are non-adjacent if (u,v) not in E. A subset + * of the vertices S within V is independent if all vertices in S are + * pairwise non-adjacent. The Maximum Independent Set Problem (MISP) is + * to find an independent set having the largest cardinality. */ + +param n, integer, > 0; +/* number of vertices */ + +set V := 1..n; +/* set of vertices */ + +set E within V cross V; +/* set of edges */ + +var x{i in V}, binary; +/* x[i] = 1 means vertex i belongs to independent set */ + +s.t. edge{(i,j) in E}: x[i] + x[j] <= 1; +/* if there is edge (i,j), vertices i and j cannot belong to the same + independent set */ + +maximize obj: sum{i in V} x[i]; +/* the objective is to maximize the cardinality of independent set */ + +data; + +/* These data corresponds to the test instance from: + * + * M.G.C. Resende, T.A.Feo, S.H.Smith, "Algorithm 787 -- FORTRAN + * subroutines for approximate solution of the maximum independent set + * problem using GRASP," Trans. on Math. Softw., Vol. 24, No. 4, + * December 1998, pp. 386-394. */ + +/* The optimal solution is 7. */ + +param n := 50; + +set E := + 1 2 + 1 3 + 1 5 + 1 7 + 1 8 + 1 12 + 1 15 + 1 16 + 1 19 + 1 20 + 1 21 + 1 22 + 1 28 + 1 30 + 1 34 + 1 35 + 1 37 + 1 41 + 1 42 + 1 47 + 1 50 + 2 3 + 2 5 + 2 6 + 2 7 + 2 8 + 2 9 + 2 10 + 2 13 + 2 17 + 2 19 + 2 20 + 2 21 + 2 23 + 2 25 + 2 26 + 2 29 + 2 31 + 2 35 + 2 36 + 2 44 + 2 45 + 2 46 + 2 50 + 3 5 + 3 6 + 3 8 + 3 9 + 3 10 + 3 11 + 3 14 + 3 16 + 3 23 + 3 24 + 3 26 + 3 27 + 3 28 + 3 29 + 3 30 + 3 31 + 3 34 + 3 35 + 3 36 + 3 39 + 3 41 + 3 42 + 3 43 + 3 44 + 3 50 + 4 6 + 4 7 + 4 9 + 4 10 + 4 11 + 4 13 + 4 14 + 4 15 + 4 17 + 4 21 + 4 22 + 4 23 + 4 24 + 4 25 + 4 27 + 4 28 + 4 30 + 4 31 + 4 33 + 4 34 + 4 35 + 4 36 + 4 37 + 4 38 + 4 40 + 4 41 + 4 42 + 4 46 + 4 49 + 5 6 + 5 11 + 5 14 + 5 21 + 5 24 + 5 25 + 5 28 + 5 35 + 5 38 + 5 39 + 5 41 + 5 44 + 5 49 + 5 50 + 6 8 + 6 9 + 6 10 + 6 13 + 6 14 + 6 16 + 6 17 + 6 19 + 6 22 + 6 23 + 6 26 + 6 27 + 6 30 + 6 34 + 6 35 + 6 38 + 6 39 + 6 40 + 6 41 + 6 44 + 6 45 + 6 47 + 6 50 + 7 8 + 7 9 + 7 10 + 7 11 + 7 13 + 7 15 + 7 16 + 7 18 + 7 20 + 7 22 + 7 23 + 7 24 + 7 25 + 7 33 + 7 35 + 7 36 + 7 38 + 7 43 + 7 45 + 7 46 + 7 47 + 8 10 + 8 11 + 8 13 + 8 16 + 8 17 + 8 18 + 8 19 + 8 20 + 8 21 + 8 22 + 8 23 + 8 24 + 8 25 + 8 26 + 8 33 + 8 35 + 8 36 + 8 39 + 8 42 + 8 44 + 8 48 + 8 49 + 9 12 + 9 14 + 9 17 + 9 19 + 9 20 + 9 23 + 9 28 + 9 30 + 9 31 + 9 32 + 9 33 + 9 34 + 9 38 + 9 39 + 9 42 + 9 44 + 9 45 + 9 46 + 10 11 + 10 13 + 10 15 + 10 16 + 10 17 + 10 20 + 10 21 + 10 22 + 10 23 + 10 25 + 10 26 + 10 27 + 10 28 + 10 30 + 10 31 + 10 32 + 10 37 + 10 38 + 10 41 + 10 43 + 10 44 + 10 45 + 10 50 + 11 12 + 11 14 + 11 15 + 11 18 + 11 21 + 11 24 + 11 25 + 11 26 + 11 29 + 11 32 + 11 33 + 11 35 + 11 36 + 11 37 + 11 39 + 11 40 + 11 42 + 11 43 + 11 45 + 11 47 + 11 49 + 11 50 + 12 13 + 12 16 + 12 17 + 12 19 + 12 24 + 12 25 + 12 26 + 12 30 + 12 31 + 12 32 + 12 34 + 12 36 + 12 37 + 12 39 + 12 41 + 12 44 + 12 47 + 12 48 + 12 49 + 13 15 + 13 16 + 13 18 + 13 19 + 13 20 + 13 22 + 13 23 + 13 24 + 13 27 + 13 28 + 13 29 + 13 31 + 13 33 + 13 35 + 13 36 + 13 37 + 13 44 + 13 47 + 13 49 + 13 50 + 14 15 + 14 16 + 14 17 + 14 18 + 14 19 + 14 20 + 14 21 + 14 26 + 14 28 + 14 29 + 14 30 + 14 31 + 14 32 + 14 34 + 14 35 + 14 36 + 14 38 + 14 39 + 14 41 + 14 44 + 14 46 + 14 47 + 14 48 + 15 18 + 15 21 + 15 22 + 15 23 + 15 25 + 15 28 + 15 29 + 15 30 + 15 33 + 15 34 + 15 36 + 15 37 + 15 38 + 15 39 + 15 40 + 15 43 + 15 44 + 15 46 + 15 50 + 16 17 + 16 19 + 16 20 + 16 25 + 16 26 + 16 29 + 16 35 + 16 38 + 16 39 + 16 40 + 16 41 + 16 42 + 16 44 + 17 18 + 17 19 + 17 21 + 17 22 + 17 23 + 17 25 + 17 26 + 17 28 + 17 29 + 17 33 + 17 37 + 17 44 + 17 45 + 17 48 + 18 20 + 18 24 + 18 27 + 18 28 + 18 31 + 18 32 + 18 34 + 18 35 + 18 36 + 18 37 + 18 38 + 18 45 + 18 48 + 18 49 + 18 50 + 19 22 + 19 24 + 19 28 + 19 29 + 19 36 + 19 37 + 19 39 + 19 41 + 19 43 + 19 45 + 19 48 + 19 49 + 20 21 + 20 22 + 20 24 + 20 25 + 20 26 + 20 27 + 20 29 + 20 30 + 20 31 + 20 33 + 20 34 + 20 35 + 20 38 + 20 39 + 20 41 + 20 42 + 20 43 + 20 44 + 20 45 + 20 46 + 20 48 + 20 49 + 21 22 + 21 23 + 21 29 + 21 31 + 21 35 + 21 38 + 21 42 + 21 46 + 21 47 + 22 23 + 22 26 + 22 27 + 22 28 + 22 29 + 22 30 + 22 39 + 22 40 + 22 41 + 22 42 + 22 44 + 22 45 + 22 46 + 22 47 + 22 49 + 22 50 + 23 28 + 23 31 + 23 32 + 23 33 + 23 34 + 23 35 + 23 36 + 23 39 + 23 40 + 23 41 + 23 42 + 23 44 + 23 45 + 23 48 + 23 49 + 23 50 + 24 25 + 24 27 + 24 29 + 24 30 + 24 31 + 24 33 + 24 34 + 24 38 + 24 42 + 24 43 + 24 44 + 24 49 + 24 50 + 25 26 + 25 27 + 25 29 + 25 30 + 25 33 + 25 34 + 25 36 + 25 38 + 25 40 + 25 41 + 25 42 + 25 44 + 25 46 + 25 47 + 25 48 + 25 49 + 26 28 + 26 31 + 26 32 + 26 33 + 26 37 + 26 38 + 26 39 + 26 40 + 26 41 + 26 42 + 26 45 + 26 47 + 26 48 + 26 49 + 27 29 + 27 30 + 27 33 + 27 34 + 27 35 + 27 39 + 27 40 + 27 46 + 27 48 + 28 29 + 28 37 + 28 40 + 28 42 + 28 44 + 28 46 + 28 47 + 28 50 + 29 35 + 29 38 + 29 39 + 29 41 + 29 42 + 29 48 + 30 31 + 30 32 + 30 35 + 30 37 + 30 38 + 30 40 + 30 43 + 30 45 + 30 46 + 30 47 + 30 48 + 31 33 + 31 35 + 31 38 + 31 40 + 31 41 + 31 42 + 31 44 + 31 46 + 31 47 + 31 50 + 32 33 + 32 35 + 32 39 + 32 40 + 32 46 + 32 49 + 32 50 + 33 34 + 33 36 + 33 37 + 33 40 + 33 42 + 33 43 + 33 44 + 33 45 + 33 50 + 34 35 + 34 36 + 34 37 + 34 38 + 34 40 + 34 43 + 34 44 + 34 49 + 34 50 + 35 36 + 35 38 + 35 41 + 35 42 + 35 43 + 35 45 + 35 46 + 35 47 + 35 49 + 35 50 + 36 37 + 36 39 + 36 40 + 36 41 + 36 42 + 36 43 + 36 48 + 36 50 + 37 38 + 37 41 + 37 43 + 37 46 + 37 47 + 37 48 + 37 49 + 37 50 + 38 41 + 38 45 + 38 46 + 38 48 + 38 49 + 38 50 + 39 43 + 39 46 + 39 47 + 39 48 + 39 49 + 40 43 + 40 45 + 40 48 + 40 50 + 41 42 + 41 43 + 41 44 + 41 45 + 41 46 + 41 48 + 41 49 + 42 43 + 42 44 + 42 46 + 42 48 + 42 49 + 43 45 + 43 46 + 43 48 + 43 50 + 44 45 + 44 48 + 45 46 + 45 47 + 45 48 + 46 49 + 47 49 + 47 50 + 48 49 + 48 50 + 49 50 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/misp1.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/misp1.dat new file mode 100644 index 000000000..2c2ed1ba5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/misp1.dat @@ -0,0 +1,1489 @@ +/* misp1.dat (data for misp.mod to illustrate clique cuts) */ + +/* These data corresponds to the test instance 1dc.128 (graphs from + * single-deletion-correcting codes) from: + * + * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." + * http://neilsloane.com/doc/graphs.html (June 2013). */ + +/* Optimal solution is 16. */ + +data; + +param n := 128; + +set E := /* 1471 edges */ + 1 2 + 1 3 + 1 5 + 1 9 + 1 17 + 1 33 + 1 65 + 2 3 + 2 4 + 2 5 + 2 6 + 2 9 + 2 10 + 2 17 + 2 18 + 2 33 + 2 34 + 2 65 + 2 66 + 3 4 + 3 5 + 3 6 + 3 7 + 3 9 + 3 10 + 3 11 + 3 17 + 3 18 + 3 19 + 3 33 + 3 34 + 3 35 + 3 65 + 3 66 + 3 67 + 4 6 + 4 7 + 4 8 + 4 10 + 4 12 + 4 18 + 4 20 + 4 34 + 4 36 + 4 66 + 4 68 + 5 6 + 5 7 + 5 9 + 5 10 + 5 11 + 5 13 + 5 17 + 5 19 + 5 21 + 5 33 + 5 35 + 5 37 + 5 65 + 5 67 + 5 69 + 6 7 + 6 8 + 6 10 + 6 11 + 6 12 + 6 14 + 6 18 + 6 19 + 6 20 + 6 22 + 6 34 + 6 35 + 6 36 + 6 38 + 6 66 + 6 67 + 6 68 + 6 70 + 7 8 + 7 11 + 7 12 + 7 13 + 7 14 + 7 15 + 7 19 + 7 20 + 7 23 + 7 35 + 7 36 + 7 39 + 7 67 + 7 68 + 7 71 + 8 12 + 8 14 + 8 15 + 8 16 + 8 20 + 8 24 + 8 36 + 8 40 + 8 68 + 8 72 + 9 10 + 9 11 + 9 13 + 9 17 + 9 18 + 9 19 + 9 21 + 9 25 + 9 33 + 9 37 + 9 41 + 9 65 + 9 69 + 9 73 + 10 11 + 10 12 + 10 13 + 10 14 + 10 18 + 10 19 + 10 20 + 10 21 + 10 22 + 10 26 + 10 34 + 10 37 + 10 38 + 10 42 + 10 66 + 10 69 + 10 70 + 10 74 + 11 12 + 11 13 + 11 14 + 11 15 + 11 19 + 11 21 + 11 22 + 11 23 + 11 27 + 11 35 + 11 37 + 11 38 + 11 39 + 11 43 + 11 67 + 11 69 + 11 70 + 11 71 + 11 75 + 12 14 + 12 15 + 12 16 + 12 20 + 12 22 + 12 23 + 12 24 + 12 28 + 12 36 + 12 38 + 12 40 + 12 44 + 12 68 + 12 70 + 12 72 + 12 76 + 13 14 + 13 15 + 13 21 + 13 23 + 13 25 + 13 26 + 13 27 + 13 29 + 13 37 + 13 39 + 13 45 + 13 69 + 13 71 + 13 77 + 14 15 + 14 16 + 14 22 + 14 23 + 14 24 + 14 26 + 14 27 + 14 28 + 14 30 + 14 38 + 14 39 + 14 40 + 14 46 + 14 70 + 14 71 + 14 72 + 14 78 + 15 16 + 15 23 + 15 24 + 15 27 + 15 29 + 15 30 + 15 31 + 15 39 + 15 40 + 15 47 + 15 71 + 15 72 + 15 79 + 16 24 + 16 28 + 16 30 + 16 31 + 16 32 + 16 40 + 16 48 + 16 72 + 16 80 + 17 18 + 17 19 + 17 21 + 17 25 + 17 33 + 17 34 + 17 35 + 17 37 + 17 41 + 17 49 + 17 65 + 17 73 + 17 81 + 18 19 + 18 20 + 18 21 + 18 22 + 18 25 + 18 26 + 18 34 + 18 35 + 18 36 + 18 38 + 18 41 + 18 42 + 18 50 + 18 66 + 18 73 + 18 74 + 18 82 + 19 20 + 19 21 + 19 22 + 19 23 + 19 25 + 19 26 + 19 27 + 19 35 + 19 37 + 19 38 + 19 39 + 19 41 + 19 42 + 19 43 + 19 51 + 19 67 + 19 73 + 19 74 + 19 75 + 19 83 + 20 22 + 20 23 + 20 24 + 20 26 + 20 28 + 20 36 + 20 38 + 20 39 + 20 40 + 20 42 + 20 44 + 20 52 + 20 68 + 20 74 + 20 76 + 20 84 + 21 22 + 21 23 + 21 25 + 21 26 + 21 27 + 21 29 + 21 37 + 21 41 + 21 42 + 21 43 + 21 45 + 21 53 + 21 69 + 21 73 + 21 75 + 21 77 + 21 85 + 22 23 + 22 24 + 22 26 + 22 27 + 22 28 + 22 30 + 22 38 + 22 42 + 22 43 + 22 44 + 22 46 + 22 54 + 22 70 + 22 74 + 22 75 + 22 76 + 22 78 + 22 86 + 23 24 + 23 27 + 23 28 + 23 29 + 23 30 + 23 31 + 23 39 + 23 43 + 23 44 + 23 45 + 23 46 + 23 47 + 23 55 + 23 71 + 23 75 + 23 76 + 23 79 + 23 87 + 24 28 + 24 30 + 24 31 + 24 32 + 24 40 + 24 44 + 24 46 + 24 47 + 24 48 + 24 56 + 24 72 + 24 76 + 24 80 + 24 88 + 25 26 + 25 27 + 25 29 + 25 41 + 25 45 + 25 49 + 25 50 + 25 51 + 25 53 + 25 57 + 25 73 + 25 77 + 25 89 + 26 27 + 26 28 + 26 29 + 26 30 + 26 42 + 26 45 + 26 46 + 26 50 + 26 51 + 26 52 + 26 54 + 26 58 + 26 74 + 26 77 + 26 78 + 26 90 + 27 28 + 27 29 + 27 30 + 27 31 + 27 43 + 27 45 + 27 46 + 27 47 + 27 51 + 27 53 + 27 54 + 27 55 + 27 59 + 27 75 + 27 77 + 27 78 + 27 79 + 27 91 + 28 30 + 28 31 + 28 32 + 28 44 + 28 46 + 28 48 + 28 52 + 28 54 + 28 55 + 28 56 + 28 60 + 28 76 + 28 78 + 28 80 + 28 92 + 29 30 + 29 31 + 29 45 + 29 47 + 29 53 + 29 57 + 29 58 + 29 59 + 29 61 + 29 77 + 29 79 + 29 93 + 30 31 + 30 32 + 30 46 + 30 47 + 30 48 + 30 54 + 30 58 + 30 59 + 30 60 + 30 62 + 30 78 + 30 79 + 30 80 + 30 94 + 31 32 + 31 47 + 31 48 + 31 55 + 31 59 + 31 61 + 31 62 + 31 63 + 31 79 + 31 80 + 31 95 + 32 48 + 32 56 + 32 60 + 32 62 + 32 63 + 32 64 + 32 80 + 32 96 + 33 34 + 33 35 + 33 37 + 33 41 + 33 49 + 33 65 + 33 66 + 33 67 + 33 69 + 33 73 + 33 81 + 33 97 + 34 35 + 34 36 + 34 37 + 34 38 + 34 41 + 34 42 + 34 49 + 34 50 + 34 66 + 34 67 + 34 68 + 34 70 + 34 74 + 34 81 + 34 82 + 34 98 + 35 36 + 35 37 + 35 38 + 35 39 + 35 41 + 35 42 + 35 43 + 35 49 + 35 50 + 35 51 + 35 67 + 35 69 + 35 70 + 35 71 + 35 75 + 35 81 + 35 82 + 35 83 + 35 99 + 36 38 + 36 39 + 36 40 + 36 42 + 36 44 + 36 50 + 36 52 + 36 68 + 36 70 + 36 71 + 36 72 + 36 76 + 36 82 + 36 84 + 36 100 + 37 38 + 37 39 + 37 41 + 37 42 + 37 43 + 37 45 + 37 49 + 37 51 + 37 53 + 37 69 + 37 73 + 37 74 + 37 75 + 37 77 + 37 81 + 37 83 + 37 85 + 37 101 + 38 39 + 38 40 + 38 42 + 38 43 + 38 44 + 38 46 + 38 50 + 38 51 + 38 52 + 38 54 + 38 70 + 38 74 + 38 75 + 38 76 + 38 78 + 38 82 + 38 83 + 38 84 + 38 86 + 38 102 + 39 40 + 39 43 + 39 44 + 39 45 + 39 46 + 39 47 + 39 51 + 39 52 + 39 55 + 39 71 + 39 75 + 39 77 + 39 78 + 39 79 + 39 83 + 39 84 + 39 87 + 39 103 + 40 44 + 40 46 + 40 47 + 40 48 + 40 52 + 40 56 + 40 72 + 40 76 + 40 78 + 40 79 + 40 80 + 40 84 + 40 88 + 40 104 + 41 42 + 41 43 + 41 45 + 41 49 + 41 50 + 41 51 + 41 53 + 41 57 + 41 73 + 41 81 + 41 82 + 41 83 + 41 85 + 41 89 + 41 105 + 42 43 + 42 44 + 42 45 + 42 46 + 42 50 + 42 51 + 42 52 + 42 53 + 42 54 + 42 58 + 42 74 + 42 82 + 42 83 + 42 84 + 42 85 + 42 86 + 42 90 + 42 106 + 43 44 + 43 45 + 43 46 + 43 47 + 43 51 + 43 53 + 43 54 + 43 55 + 43 59 + 43 75 + 43 83 + 43 85 + 43 86 + 43 87 + 43 91 + 43 107 + 44 46 + 44 47 + 44 48 + 44 52 + 44 54 + 44 55 + 44 56 + 44 60 + 44 76 + 44 84 + 44 86 + 44 87 + 44 88 + 44 92 + 44 108 + 45 46 + 45 47 + 45 53 + 45 55 + 45 57 + 45 58 + 45 59 + 45 61 + 45 77 + 45 85 + 45 87 + 45 89 + 45 90 + 45 91 + 45 93 + 45 109 + 46 47 + 46 48 + 46 54 + 46 55 + 46 56 + 46 58 + 46 59 + 46 60 + 46 62 + 46 78 + 46 86 + 46 87 + 46 88 + 46 90 + 46 91 + 46 92 + 46 94 + 46 110 + 47 48 + 47 55 + 47 56 + 47 59 + 47 61 + 47 62 + 47 63 + 47 79 + 47 87 + 47 88 + 47 91 + 47 93 + 47 94 + 47 95 + 47 111 + 48 56 + 48 60 + 48 62 + 48 63 + 48 64 + 48 80 + 48 88 + 48 92 + 48 94 + 48 95 + 48 96 + 48 112 + 49 50 + 49 51 + 49 53 + 49 57 + 49 81 + 49 89 + 49 97 + 49 98 + 49 99 + 49 101 + 49 105 + 49 113 + 50 51 + 50 52 + 50 53 + 50 54 + 50 57 + 50 58 + 50 82 + 50 89 + 50 90 + 50 98 + 50 99 + 50 100 + 50 102 + 50 106 + 50 114 + 51 52 + 51 53 + 51 54 + 51 55 + 51 57 + 51 58 + 51 59 + 51 83 + 51 89 + 51 90 + 51 91 + 51 99 + 51 101 + 51 102 + 51 103 + 51 107 + 51 115 + 52 54 + 52 55 + 52 56 + 52 58 + 52 60 + 52 84 + 52 90 + 52 92 + 52 100 + 52 102 + 52 103 + 52 104 + 52 108 + 52 116 + 53 54 + 53 55 + 53 57 + 53 58 + 53 59 + 53 61 + 53 85 + 53 89 + 53 91 + 53 93 + 53 101 + 53 105 + 53 106 + 53 107 + 53 109 + 53 117 + 54 55 + 54 56 + 54 58 + 54 59 + 54 60 + 54 62 + 54 86 + 54 90 + 54 91 + 54 92 + 54 94 + 54 102 + 54 106 + 54 107 + 54 108 + 54 110 + 54 118 + 55 56 + 55 59 + 55 60 + 55 61 + 55 62 + 55 63 + 55 87 + 55 91 + 55 92 + 55 95 + 55 103 + 55 107 + 55 109 + 55 110 + 55 111 + 55 119 + 56 60 + 56 62 + 56 63 + 56 64 + 56 88 + 56 92 + 56 96 + 56 104 + 56 108 + 56 110 + 56 111 + 56 112 + 56 120 + 57 58 + 57 59 + 57 61 + 57 89 + 57 93 + 57 105 + 57 113 + 57 114 + 57 115 + 57 117 + 57 121 + 58 59 + 58 60 + 58 61 + 58 62 + 58 90 + 58 93 + 58 94 + 58 106 + 58 114 + 58 115 + 58 116 + 58 118 + 58 122 + 59 60 + 59 61 + 59 62 + 59 63 + 59 91 + 59 93 + 59 94 + 59 95 + 59 107 + 59 115 + 59 117 + 59 118 + 59 119 + 59 123 + 60 62 + 60 63 + 60 64 + 60 92 + 60 94 + 60 96 + 60 108 + 60 116 + 60 118 + 60 119 + 60 120 + 60 124 + 61 62 + 61 63 + 61 93 + 61 95 + 61 109 + 61 117 + 61 121 + 61 122 + 61 123 + 61 125 + 62 63 + 62 64 + 62 94 + 62 95 + 62 96 + 62 110 + 62 118 + 62 122 + 62 123 + 62 124 + 62 126 + 63 64 + 63 95 + 63 96 + 63 111 + 63 119 + 63 123 + 63 125 + 63 126 + 63 127 + 64 96 + 64 112 + 64 120 + 64 124 + 64 126 + 64 127 + 64 128 + 65 66 + 65 67 + 65 69 + 65 73 + 65 81 + 65 97 + 66 67 + 66 68 + 66 69 + 66 70 + 66 73 + 66 74 + 66 81 + 66 82 + 66 97 + 66 98 + 67 68 + 67 69 + 67 70 + 67 71 + 67 73 + 67 74 + 67 75 + 67 81 + 67 82 + 67 83 + 67 97 + 67 98 + 67 99 + 68 70 + 68 71 + 68 72 + 68 74 + 68 76 + 68 82 + 68 84 + 68 98 + 68 100 + 69 70 + 69 71 + 69 73 + 69 74 + 69 75 + 69 77 + 69 81 + 69 83 + 69 85 + 69 97 + 69 99 + 69 101 + 70 71 + 70 72 + 70 74 + 70 75 + 70 76 + 70 78 + 70 82 + 70 83 + 70 84 + 70 86 + 70 98 + 70 99 + 70 100 + 70 102 + 71 72 + 71 75 + 71 76 + 71 77 + 71 78 + 71 79 + 71 83 + 71 84 + 71 87 + 71 99 + 71 100 + 71 103 + 72 76 + 72 78 + 72 79 + 72 80 + 72 84 + 72 88 + 72 100 + 72 104 + 73 74 + 73 75 + 73 77 + 73 81 + 73 82 + 73 83 + 73 85 + 73 89 + 73 97 + 73 101 + 73 105 + 74 75 + 74 76 + 74 77 + 74 78 + 74 82 + 74 83 + 74 84 + 74 85 + 74 86 + 74 90 + 74 98 + 74 101 + 74 102 + 74 106 + 75 76 + 75 77 + 75 78 + 75 79 + 75 83 + 75 85 + 75 86 + 75 87 + 75 91 + 75 99 + 75 101 + 75 102 + 75 103 + 75 107 + 76 78 + 76 79 + 76 80 + 76 84 + 76 86 + 76 87 + 76 88 + 76 92 + 76 100 + 76 102 + 76 104 + 76 108 + 77 78 + 77 79 + 77 85 + 77 87 + 77 89 + 77 90 + 77 91 + 77 93 + 77 101 + 77 103 + 77 109 + 78 79 + 78 80 + 78 86 + 78 87 + 78 88 + 78 90 + 78 91 + 78 92 + 78 94 + 78 102 + 78 103 + 78 104 + 78 110 + 79 80 + 79 87 + 79 88 + 79 91 + 79 93 + 79 94 + 79 95 + 79 103 + 79 104 + 79 111 + 80 88 + 80 92 + 80 94 + 80 95 + 80 96 + 80 104 + 80 112 + 81 82 + 81 83 + 81 85 + 81 89 + 81 97 + 81 98 + 81 99 + 81 101 + 81 105 + 81 113 + 82 83 + 82 84 + 82 85 + 82 86 + 82 89 + 82 90 + 82 98 + 82 99 + 82 100 + 82 102 + 82 105 + 82 106 + 82 114 + 83 84 + 83 85 + 83 86 + 83 87 + 83 89 + 83 90 + 83 91 + 83 99 + 83 101 + 83 102 + 83 103 + 83 105 + 83 106 + 83 107 + 83 115 + 84 86 + 84 87 + 84 88 + 84 90 + 84 92 + 84 100 + 84 102 + 84 103 + 84 104 + 84 106 + 84 108 + 84 116 + 85 86 + 85 87 + 85 89 + 85 90 + 85 91 + 85 93 + 85 101 + 85 105 + 85 106 + 85 107 + 85 109 + 85 117 + 86 87 + 86 88 + 86 90 + 86 91 + 86 92 + 86 94 + 86 102 + 86 106 + 86 107 + 86 108 + 86 110 + 86 118 + 87 88 + 87 91 + 87 92 + 87 93 + 87 94 + 87 95 + 87 103 + 87 107 + 87 108 + 87 109 + 87 110 + 87 111 + 87 119 + 88 92 + 88 94 + 88 95 + 88 96 + 88 104 + 88 108 + 88 110 + 88 111 + 88 112 + 88 120 + 89 90 + 89 91 + 89 93 + 89 105 + 89 109 + 89 113 + 89 114 + 89 115 + 89 117 + 89 121 + 90 91 + 90 92 + 90 93 + 90 94 + 90 106 + 90 109 + 90 110 + 90 114 + 90 115 + 90 116 + 90 118 + 90 122 + 91 92 + 91 93 + 91 94 + 91 95 + 91 107 + 91 109 + 91 110 + 91 111 + 91 115 + 91 117 + 91 118 + 91 119 + 91 123 + 92 94 + 92 95 + 92 96 + 92 108 + 92 110 + 92 112 + 92 116 + 92 118 + 92 119 + 92 120 + 92 124 + 93 94 + 93 95 + 93 109 + 93 111 + 93 117 + 93 121 + 93 122 + 93 123 + 93 125 + 94 95 + 94 96 + 94 110 + 94 111 + 94 112 + 94 118 + 94 122 + 94 123 + 94 124 + 94 126 + 95 96 + 95 111 + 95 112 + 95 119 + 95 123 + 95 125 + 95 126 + 95 127 + 96 112 + 96 120 + 96 124 + 96 126 + 96 127 + 96 128 + 97 98 + 97 99 + 97 101 + 97 105 + 97 113 + 98 99 + 98 100 + 98 101 + 98 102 + 98 105 + 98 106 + 98 113 + 98 114 + 99 100 + 99 101 + 99 102 + 99 103 + 99 105 + 99 106 + 99 107 + 99 113 + 99 114 + 99 115 + 100 102 + 100 103 + 100 104 + 100 106 + 100 108 + 100 114 + 100 116 + 101 102 + 101 103 + 101 105 + 101 106 + 101 107 + 101 109 + 101 113 + 101 115 + 101 117 + 102 103 + 102 104 + 102 106 + 102 107 + 102 108 + 102 110 + 102 114 + 102 115 + 102 116 + 102 118 + 103 104 + 103 107 + 103 108 + 103 109 + 103 110 + 103 111 + 103 115 + 103 116 + 103 119 + 104 108 + 104 110 + 104 111 + 104 112 + 104 116 + 104 120 + 105 106 + 105 107 + 105 109 + 105 113 + 105 114 + 105 115 + 105 117 + 105 121 + 106 107 + 106 108 + 106 109 + 106 110 + 106 114 + 106 115 + 106 116 + 106 117 + 106 118 + 106 122 + 107 108 + 107 109 + 107 110 + 107 111 + 107 115 + 107 117 + 107 118 + 107 119 + 107 123 + 108 110 + 108 111 + 108 112 + 108 116 + 108 118 + 108 119 + 108 120 + 108 124 + 109 110 + 109 111 + 109 117 + 109 119 + 109 121 + 109 122 + 109 123 + 109 125 + 110 111 + 110 112 + 110 118 + 110 119 + 110 120 + 110 122 + 110 123 + 110 124 + 110 126 + 111 112 + 111 119 + 111 120 + 111 123 + 111 125 + 111 126 + 111 127 + 112 120 + 112 124 + 112 126 + 112 127 + 112 128 + 113 114 + 113 115 + 113 117 + 113 121 + 114 115 + 114 116 + 114 117 + 114 118 + 114 121 + 114 122 + 115 116 + 115 117 + 115 118 + 115 119 + 115 121 + 115 122 + 115 123 + 116 118 + 116 119 + 116 120 + 116 122 + 116 124 + 117 118 + 117 119 + 117 121 + 117 122 + 117 123 + 117 125 + 118 119 + 118 120 + 118 122 + 118 123 + 118 124 + 118 126 + 119 120 + 119 123 + 119 124 + 119 125 + 119 126 + 119 127 + 120 124 + 120 126 + 120 127 + 120 128 + 121 122 + 121 123 + 121 125 + 122 123 + 122 124 + 122 125 + 122 126 + 123 124 + 123 125 + 123 126 + 123 127 + 124 126 + 124 127 + 124 128 + 125 126 + 125 127 + 126 127 + 126 128 + 127 128 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/misp2.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/misp2.dat new file mode 100644 index 000000000..c9a61161e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/misp2.dat @@ -0,0 +1,3857 @@ +/* misp2.dat (data for misp.mod to illustrate clique cuts) */ + +/* These data corresponds to the test instance 1dc.256 (graphs from + * single-deletion-correcting codes) from: + * + * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." + * http://neilsloane.com/doc/graphs.html (June 2013). */ + +/* Optimal solution is 30. */ + +data; + +param n := 256; + +set E := /* 3839 edges */ + 1 2 + 1 3 + 1 5 + 1 9 + 1 17 + 1 33 + 1 65 + 1 129 + 2 3 + 2 4 + 2 5 + 2 6 + 2 9 + 2 10 + 2 17 + 2 18 + 2 33 + 2 34 + 2 65 + 2 66 + 2 129 + 2 130 + 3 4 + 3 5 + 3 6 + 3 7 + 3 9 + 3 10 + 3 11 + 3 17 + 3 18 + 3 19 + 3 33 + 3 34 + 3 35 + 3 65 + 3 66 + 3 67 + 3 129 + 3 130 + 3 131 + 4 6 + 4 7 + 4 8 + 4 10 + 4 12 + 4 18 + 4 20 + 4 34 + 4 36 + 4 66 + 4 68 + 4 130 + 4 132 + 5 6 + 5 7 + 5 9 + 5 10 + 5 11 + 5 13 + 5 17 + 5 19 + 5 21 + 5 33 + 5 35 + 5 37 + 5 65 + 5 67 + 5 69 + 5 129 + 5 131 + 5 133 + 6 7 + 6 8 + 6 10 + 6 11 + 6 12 + 6 14 + 6 18 + 6 19 + 6 20 + 6 22 + 6 34 + 6 35 + 6 36 + 6 38 + 6 66 + 6 67 + 6 68 + 6 70 + 6 130 + 6 131 + 6 132 + 6 134 + 7 8 + 7 11 + 7 12 + 7 13 + 7 14 + 7 15 + 7 19 + 7 20 + 7 23 + 7 35 + 7 36 + 7 39 + 7 67 + 7 68 + 7 71 + 7 131 + 7 132 + 7 135 + 8 12 + 8 14 + 8 15 + 8 16 + 8 20 + 8 24 + 8 36 + 8 40 + 8 68 + 8 72 + 8 132 + 8 136 + 9 10 + 9 11 + 9 13 + 9 17 + 9 18 + 9 19 + 9 21 + 9 25 + 9 33 + 9 37 + 9 41 + 9 65 + 9 69 + 9 73 + 9 129 + 9 133 + 9 137 + 10 11 + 10 12 + 10 13 + 10 14 + 10 18 + 10 19 + 10 20 + 10 21 + 10 22 + 10 26 + 10 34 + 10 37 + 10 38 + 10 42 + 10 66 + 10 69 + 10 70 + 10 74 + 10 130 + 10 133 + 10 134 + 10 138 + 11 12 + 11 13 + 11 14 + 11 15 + 11 19 + 11 21 + 11 22 + 11 23 + 11 27 + 11 35 + 11 37 + 11 38 + 11 39 + 11 43 + 11 67 + 11 69 + 11 70 + 11 71 + 11 75 + 11 131 + 11 133 + 11 134 + 11 135 + 11 139 + 12 14 + 12 15 + 12 16 + 12 20 + 12 22 + 12 23 + 12 24 + 12 28 + 12 36 + 12 38 + 12 40 + 12 44 + 12 68 + 12 70 + 12 72 + 12 76 + 12 132 + 12 134 + 12 136 + 12 140 + 13 14 + 13 15 + 13 21 + 13 23 + 13 25 + 13 26 + 13 27 + 13 29 + 13 37 + 13 39 + 13 45 + 13 69 + 13 71 + 13 77 + 13 133 + 13 135 + 13 141 + 14 15 + 14 16 + 14 22 + 14 23 + 14 24 + 14 26 + 14 27 + 14 28 + 14 30 + 14 38 + 14 39 + 14 40 + 14 46 + 14 70 + 14 71 + 14 72 + 14 78 + 14 134 + 14 135 + 14 136 + 14 142 + 15 16 + 15 23 + 15 24 + 15 27 + 15 29 + 15 30 + 15 31 + 15 39 + 15 40 + 15 47 + 15 71 + 15 72 + 15 79 + 15 135 + 15 136 + 15 143 + 16 24 + 16 28 + 16 30 + 16 31 + 16 32 + 16 40 + 16 48 + 16 72 + 16 80 + 16 136 + 16 144 + 17 18 + 17 19 + 17 21 + 17 25 + 17 33 + 17 34 + 17 35 + 17 37 + 17 41 + 17 49 + 17 65 + 17 73 + 17 81 + 17 129 + 17 137 + 17 145 + 18 19 + 18 20 + 18 21 + 18 22 + 18 25 + 18 26 + 18 34 + 18 35 + 18 36 + 18 38 + 18 41 + 18 42 + 18 50 + 18 66 + 18 73 + 18 74 + 18 82 + 18 130 + 18 137 + 18 138 + 18 146 + 19 20 + 19 21 + 19 22 + 19 23 + 19 25 + 19 26 + 19 27 + 19 35 + 19 37 + 19 38 + 19 39 + 19 41 + 19 42 + 19 43 + 19 51 + 19 67 + 19 73 + 19 74 + 19 75 + 19 83 + 19 131 + 19 137 + 19 138 + 19 139 + 19 147 + 20 22 + 20 23 + 20 24 + 20 26 + 20 28 + 20 36 + 20 38 + 20 39 + 20 40 + 20 42 + 20 44 + 20 52 + 20 68 + 20 74 + 20 76 + 20 84 + 20 132 + 20 138 + 20 140 + 20 148 + 21 22 + 21 23 + 21 25 + 21 26 + 21 27 + 21 29 + 21 37 + 21 41 + 21 42 + 21 43 + 21 45 + 21 53 + 21 69 + 21 73 + 21 75 + 21 77 + 21 85 + 21 133 + 21 137 + 21 139 + 21 141 + 21 149 + 22 23 + 22 24 + 22 26 + 22 27 + 22 28 + 22 30 + 22 38 + 22 42 + 22 43 + 22 44 + 22 46 + 22 54 + 22 70 + 22 74 + 22 75 + 22 76 + 22 78 + 22 86 + 22 134 + 22 138 + 22 139 + 22 140 + 22 142 + 22 150 + 23 24 + 23 27 + 23 28 + 23 29 + 23 30 + 23 31 + 23 39 + 23 43 + 23 44 + 23 45 + 23 46 + 23 47 + 23 55 + 23 71 + 23 75 + 23 76 + 23 79 + 23 87 + 23 135 + 23 139 + 23 140 + 23 143 + 23 151 + 24 28 + 24 30 + 24 31 + 24 32 + 24 40 + 24 44 + 24 46 + 24 47 + 24 48 + 24 56 + 24 72 + 24 76 + 24 80 + 24 88 + 24 136 + 24 140 + 24 144 + 24 152 + 25 26 + 25 27 + 25 29 + 25 41 + 25 45 + 25 49 + 25 50 + 25 51 + 25 53 + 25 57 + 25 73 + 25 77 + 25 89 + 25 137 + 25 141 + 25 153 + 26 27 + 26 28 + 26 29 + 26 30 + 26 42 + 26 45 + 26 46 + 26 50 + 26 51 + 26 52 + 26 54 + 26 58 + 26 74 + 26 77 + 26 78 + 26 90 + 26 138 + 26 141 + 26 142 + 26 154 + 27 28 + 27 29 + 27 30 + 27 31 + 27 43 + 27 45 + 27 46 + 27 47 + 27 51 + 27 53 + 27 54 + 27 55 + 27 59 + 27 75 + 27 77 + 27 78 + 27 79 + 27 91 + 27 139 + 27 141 + 27 142 + 27 143 + 27 155 + 28 30 + 28 31 + 28 32 + 28 44 + 28 46 + 28 48 + 28 52 + 28 54 + 28 55 + 28 56 + 28 60 + 28 76 + 28 78 + 28 80 + 28 92 + 28 140 + 28 142 + 28 144 + 28 156 + 29 30 + 29 31 + 29 45 + 29 47 + 29 53 + 29 57 + 29 58 + 29 59 + 29 61 + 29 77 + 29 79 + 29 93 + 29 141 + 29 143 + 29 157 + 30 31 + 30 32 + 30 46 + 30 47 + 30 48 + 30 54 + 30 58 + 30 59 + 30 60 + 30 62 + 30 78 + 30 79 + 30 80 + 30 94 + 30 142 + 30 143 + 30 144 + 30 158 + 31 32 + 31 47 + 31 48 + 31 55 + 31 59 + 31 61 + 31 62 + 31 63 + 31 79 + 31 80 + 31 95 + 31 143 + 31 144 + 31 159 + 32 48 + 32 56 + 32 60 + 32 62 + 32 63 + 32 64 + 32 80 + 32 96 + 32 144 + 32 160 + 33 34 + 33 35 + 33 37 + 33 41 + 33 49 + 33 65 + 33 66 + 33 67 + 33 69 + 33 73 + 33 81 + 33 97 + 33 129 + 33 145 + 33 161 + 34 35 + 34 36 + 34 37 + 34 38 + 34 41 + 34 42 + 34 49 + 34 50 + 34 66 + 34 67 + 34 68 + 34 70 + 34 74 + 34 81 + 34 82 + 34 98 + 34 130 + 34 145 + 34 146 + 34 162 + 35 36 + 35 37 + 35 38 + 35 39 + 35 41 + 35 42 + 35 43 + 35 49 + 35 50 + 35 51 + 35 67 + 35 69 + 35 70 + 35 71 + 35 75 + 35 81 + 35 82 + 35 83 + 35 99 + 35 131 + 35 145 + 35 146 + 35 147 + 35 163 + 36 38 + 36 39 + 36 40 + 36 42 + 36 44 + 36 50 + 36 52 + 36 68 + 36 70 + 36 71 + 36 72 + 36 76 + 36 82 + 36 84 + 36 100 + 36 132 + 36 146 + 36 148 + 36 164 + 37 38 + 37 39 + 37 41 + 37 42 + 37 43 + 37 45 + 37 49 + 37 51 + 37 53 + 37 69 + 37 73 + 37 74 + 37 75 + 37 77 + 37 81 + 37 83 + 37 85 + 37 101 + 37 133 + 37 145 + 37 147 + 37 149 + 37 165 + 38 39 + 38 40 + 38 42 + 38 43 + 38 44 + 38 46 + 38 50 + 38 51 + 38 52 + 38 54 + 38 70 + 38 74 + 38 75 + 38 76 + 38 78 + 38 82 + 38 83 + 38 84 + 38 86 + 38 102 + 38 134 + 38 146 + 38 147 + 38 148 + 38 150 + 38 166 + 39 40 + 39 43 + 39 44 + 39 45 + 39 46 + 39 47 + 39 51 + 39 52 + 39 55 + 39 71 + 39 75 + 39 77 + 39 78 + 39 79 + 39 83 + 39 84 + 39 87 + 39 103 + 39 135 + 39 147 + 39 148 + 39 151 + 39 167 + 40 44 + 40 46 + 40 47 + 40 48 + 40 52 + 40 56 + 40 72 + 40 76 + 40 78 + 40 79 + 40 80 + 40 84 + 40 88 + 40 104 + 40 136 + 40 148 + 40 152 + 40 168 + 41 42 + 41 43 + 41 45 + 41 49 + 41 50 + 41 51 + 41 53 + 41 57 + 41 73 + 41 81 + 41 82 + 41 83 + 41 85 + 41 89 + 41 105 + 41 137 + 41 145 + 41 149 + 41 153 + 41 169 + 42 43 + 42 44 + 42 45 + 42 46 + 42 50 + 42 51 + 42 52 + 42 53 + 42 54 + 42 58 + 42 74 + 42 82 + 42 83 + 42 84 + 42 85 + 42 86 + 42 90 + 42 106 + 42 138 + 42 146 + 42 149 + 42 150 + 42 154 + 42 170 + 43 44 + 43 45 + 43 46 + 43 47 + 43 51 + 43 53 + 43 54 + 43 55 + 43 59 + 43 75 + 43 83 + 43 85 + 43 86 + 43 87 + 43 91 + 43 107 + 43 139 + 43 147 + 43 149 + 43 150 + 43 151 + 43 155 + 43 171 + 44 46 + 44 47 + 44 48 + 44 52 + 44 54 + 44 55 + 44 56 + 44 60 + 44 76 + 44 84 + 44 86 + 44 87 + 44 88 + 44 92 + 44 108 + 44 140 + 44 148 + 44 150 + 44 152 + 44 156 + 44 172 + 45 46 + 45 47 + 45 53 + 45 55 + 45 57 + 45 58 + 45 59 + 45 61 + 45 77 + 45 85 + 45 87 + 45 89 + 45 90 + 45 91 + 45 93 + 45 109 + 45 141 + 45 149 + 45 151 + 45 157 + 45 173 + 46 47 + 46 48 + 46 54 + 46 55 + 46 56 + 46 58 + 46 59 + 46 60 + 46 62 + 46 78 + 46 86 + 46 87 + 46 88 + 46 90 + 46 91 + 46 92 + 46 94 + 46 110 + 46 142 + 46 150 + 46 151 + 46 152 + 46 158 + 46 174 + 47 48 + 47 55 + 47 56 + 47 59 + 47 61 + 47 62 + 47 63 + 47 79 + 47 87 + 47 88 + 47 91 + 47 93 + 47 94 + 47 95 + 47 111 + 47 143 + 47 151 + 47 152 + 47 159 + 47 175 + 48 56 + 48 60 + 48 62 + 48 63 + 48 64 + 48 80 + 48 88 + 48 92 + 48 94 + 48 95 + 48 96 + 48 112 + 48 144 + 48 152 + 48 160 + 48 176 + 49 50 + 49 51 + 49 53 + 49 57 + 49 81 + 49 89 + 49 97 + 49 98 + 49 99 + 49 101 + 49 105 + 49 113 + 49 145 + 49 153 + 49 177 + 50 51 + 50 52 + 50 53 + 50 54 + 50 57 + 50 58 + 50 82 + 50 89 + 50 90 + 50 98 + 50 99 + 50 100 + 50 102 + 50 106 + 50 114 + 50 146 + 50 153 + 50 154 + 50 178 + 51 52 + 51 53 + 51 54 + 51 55 + 51 57 + 51 58 + 51 59 + 51 83 + 51 89 + 51 90 + 51 91 + 51 99 + 51 101 + 51 102 + 51 103 + 51 107 + 51 115 + 51 147 + 51 153 + 51 154 + 51 155 + 51 179 + 52 54 + 52 55 + 52 56 + 52 58 + 52 60 + 52 84 + 52 90 + 52 92 + 52 100 + 52 102 + 52 103 + 52 104 + 52 108 + 52 116 + 52 148 + 52 154 + 52 156 + 52 180 + 53 54 + 53 55 + 53 57 + 53 58 + 53 59 + 53 61 + 53 85 + 53 89 + 53 91 + 53 93 + 53 101 + 53 105 + 53 106 + 53 107 + 53 109 + 53 117 + 53 149 + 53 153 + 53 155 + 53 157 + 53 181 + 54 55 + 54 56 + 54 58 + 54 59 + 54 60 + 54 62 + 54 86 + 54 90 + 54 91 + 54 92 + 54 94 + 54 102 + 54 106 + 54 107 + 54 108 + 54 110 + 54 118 + 54 150 + 54 154 + 54 155 + 54 156 + 54 158 + 54 182 + 55 56 + 55 59 + 55 60 + 55 61 + 55 62 + 55 63 + 55 87 + 55 91 + 55 92 + 55 95 + 55 103 + 55 107 + 55 109 + 55 110 + 55 111 + 55 119 + 55 151 + 55 155 + 55 156 + 55 159 + 55 183 + 56 60 + 56 62 + 56 63 + 56 64 + 56 88 + 56 92 + 56 96 + 56 104 + 56 108 + 56 110 + 56 111 + 56 112 + 56 120 + 56 152 + 56 156 + 56 160 + 56 184 + 57 58 + 57 59 + 57 61 + 57 89 + 57 93 + 57 105 + 57 113 + 57 114 + 57 115 + 57 117 + 57 121 + 57 153 + 57 157 + 57 185 + 58 59 + 58 60 + 58 61 + 58 62 + 58 90 + 58 93 + 58 94 + 58 106 + 58 114 + 58 115 + 58 116 + 58 118 + 58 122 + 58 154 + 58 157 + 58 158 + 58 186 + 59 60 + 59 61 + 59 62 + 59 63 + 59 91 + 59 93 + 59 94 + 59 95 + 59 107 + 59 115 + 59 117 + 59 118 + 59 119 + 59 123 + 59 155 + 59 157 + 59 158 + 59 159 + 59 187 + 60 62 + 60 63 + 60 64 + 60 92 + 60 94 + 60 96 + 60 108 + 60 116 + 60 118 + 60 119 + 60 120 + 60 124 + 60 156 + 60 158 + 60 160 + 60 188 + 61 62 + 61 63 + 61 93 + 61 95 + 61 109 + 61 117 + 61 121 + 61 122 + 61 123 + 61 125 + 61 157 + 61 159 + 61 189 + 62 63 + 62 64 + 62 94 + 62 95 + 62 96 + 62 110 + 62 118 + 62 122 + 62 123 + 62 124 + 62 126 + 62 158 + 62 159 + 62 160 + 62 190 + 63 64 + 63 95 + 63 96 + 63 111 + 63 119 + 63 123 + 63 125 + 63 126 + 63 127 + 63 159 + 63 160 + 63 191 + 64 96 + 64 112 + 64 120 + 64 124 + 64 126 + 64 127 + 64 128 + 64 160 + 64 192 + 65 66 + 65 67 + 65 69 + 65 73 + 65 81 + 65 97 + 65 129 + 65 130 + 65 131 + 65 133 + 65 137 + 65 145 + 65 161 + 65 193 + 66 67 + 66 68 + 66 69 + 66 70 + 66 73 + 66 74 + 66 81 + 66 82 + 66 97 + 66 98 + 66 130 + 66 131 + 66 132 + 66 134 + 66 138 + 66 146 + 66 161 + 66 162 + 66 194 + 67 68 + 67 69 + 67 70 + 67 71 + 67 73 + 67 74 + 67 75 + 67 81 + 67 82 + 67 83 + 67 97 + 67 98 + 67 99 + 67 131 + 67 133 + 67 134 + 67 135 + 67 139 + 67 147 + 67 161 + 67 162 + 67 163 + 67 195 + 68 70 + 68 71 + 68 72 + 68 74 + 68 76 + 68 82 + 68 84 + 68 98 + 68 100 + 68 132 + 68 134 + 68 135 + 68 136 + 68 140 + 68 148 + 68 162 + 68 164 + 68 196 + 69 70 + 69 71 + 69 73 + 69 74 + 69 75 + 69 77 + 69 81 + 69 83 + 69 85 + 69 97 + 69 99 + 69 101 + 69 133 + 69 137 + 69 138 + 69 139 + 69 141 + 69 149 + 69 161 + 69 163 + 69 165 + 69 197 + 70 71 + 70 72 + 70 74 + 70 75 + 70 76 + 70 78 + 70 82 + 70 83 + 70 84 + 70 86 + 70 98 + 70 99 + 70 100 + 70 102 + 70 134 + 70 138 + 70 139 + 70 140 + 70 142 + 70 150 + 70 162 + 70 163 + 70 164 + 70 166 + 70 198 + 71 72 + 71 75 + 71 76 + 71 77 + 71 78 + 71 79 + 71 83 + 71 84 + 71 87 + 71 99 + 71 100 + 71 103 + 71 135 + 71 139 + 71 141 + 71 142 + 71 143 + 71 151 + 71 163 + 71 164 + 71 167 + 71 199 + 72 76 + 72 78 + 72 79 + 72 80 + 72 84 + 72 88 + 72 100 + 72 104 + 72 136 + 72 140 + 72 142 + 72 143 + 72 144 + 72 152 + 72 164 + 72 168 + 72 200 + 73 74 + 73 75 + 73 77 + 73 81 + 73 82 + 73 83 + 73 85 + 73 89 + 73 97 + 73 101 + 73 105 + 73 137 + 73 145 + 73 146 + 73 147 + 73 149 + 73 153 + 73 161 + 73 165 + 73 169 + 73 201 + 74 75 + 74 76 + 74 77 + 74 78 + 74 82 + 74 83 + 74 84 + 74 85 + 74 86 + 74 90 + 74 98 + 74 101 + 74 102 + 74 106 + 74 138 + 74 146 + 74 147 + 74 148 + 74 150 + 74 154 + 74 162 + 74 165 + 74 166 + 74 170 + 74 202 + 75 76 + 75 77 + 75 78 + 75 79 + 75 83 + 75 85 + 75 86 + 75 87 + 75 91 + 75 99 + 75 101 + 75 102 + 75 103 + 75 107 + 75 139 + 75 147 + 75 149 + 75 150 + 75 151 + 75 155 + 75 163 + 75 165 + 75 166 + 75 167 + 75 171 + 75 203 + 76 78 + 76 79 + 76 80 + 76 84 + 76 86 + 76 87 + 76 88 + 76 92 + 76 100 + 76 102 + 76 104 + 76 108 + 76 140 + 76 148 + 76 150 + 76 151 + 76 152 + 76 156 + 76 164 + 76 166 + 76 168 + 76 172 + 76 204 + 77 78 + 77 79 + 77 85 + 77 87 + 77 89 + 77 90 + 77 91 + 77 93 + 77 101 + 77 103 + 77 109 + 77 141 + 77 149 + 77 153 + 77 154 + 77 155 + 77 157 + 77 165 + 77 167 + 77 173 + 77 205 + 78 79 + 78 80 + 78 86 + 78 87 + 78 88 + 78 90 + 78 91 + 78 92 + 78 94 + 78 102 + 78 103 + 78 104 + 78 110 + 78 142 + 78 150 + 78 154 + 78 155 + 78 156 + 78 158 + 78 166 + 78 167 + 78 168 + 78 174 + 78 206 + 79 80 + 79 87 + 79 88 + 79 91 + 79 93 + 79 94 + 79 95 + 79 103 + 79 104 + 79 111 + 79 143 + 79 151 + 79 155 + 79 157 + 79 158 + 79 159 + 79 167 + 79 168 + 79 175 + 79 207 + 80 88 + 80 92 + 80 94 + 80 95 + 80 96 + 80 104 + 80 112 + 80 144 + 80 152 + 80 156 + 80 158 + 80 159 + 80 160 + 80 168 + 80 176 + 80 208 + 81 82 + 81 83 + 81 85 + 81 89 + 81 97 + 81 98 + 81 99 + 81 101 + 81 105 + 81 113 + 81 145 + 81 161 + 81 162 + 81 163 + 81 165 + 81 169 + 81 177 + 81 209 + 82 83 + 82 84 + 82 85 + 82 86 + 82 89 + 82 90 + 82 98 + 82 99 + 82 100 + 82 102 + 82 105 + 82 106 + 82 114 + 82 146 + 82 162 + 82 163 + 82 164 + 82 166 + 82 169 + 82 170 + 82 178 + 82 210 + 83 84 + 83 85 + 83 86 + 83 87 + 83 89 + 83 90 + 83 91 + 83 99 + 83 101 + 83 102 + 83 103 + 83 105 + 83 106 + 83 107 + 83 115 + 83 147 + 83 163 + 83 165 + 83 166 + 83 167 + 83 169 + 83 170 + 83 171 + 83 179 + 83 211 + 84 86 + 84 87 + 84 88 + 84 90 + 84 92 + 84 100 + 84 102 + 84 103 + 84 104 + 84 106 + 84 108 + 84 116 + 84 148 + 84 164 + 84 166 + 84 167 + 84 168 + 84 170 + 84 172 + 84 180 + 84 212 + 85 86 + 85 87 + 85 89 + 85 90 + 85 91 + 85 93 + 85 101 + 85 105 + 85 106 + 85 107 + 85 109 + 85 117 + 85 149 + 85 165 + 85 169 + 85 170 + 85 171 + 85 173 + 85 181 + 85 213 + 86 87 + 86 88 + 86 90 + 86 91 + 86 92 + 86 94 + 86 102 + 86 106 + 86 107 + 86 108 + 86 110 + 86 118 + 86 150 + 86 166 + 86 170 + 86 171 + 86 172 + 86 174 + 86 182 + 86 214 + 87 88 + 87 91 + 87 92 + 87 93 + 87 94 + 87 95 + 87 103 + 87 107 + 87 108 + 87 109 + 87 110 + 87 111 + 87 119 + 87 151 + 87 167 + 87 171 + 87 172 + 87 173 + 87 174 + 87 175 + 87 183 + 87 215 + 88 92 + 88 94 + 88 95 + 88 96 + 88 104 + 88 108 + 88 110 + 88 111 + 88 112 + 88 120 + 88 152 + 88 168 + 88 172 + 88 174 + 88 175 + 88 176 + 88 184 + 88 216 + 89 90 + 89 91 + 89 93 + 89 105 + 89 109 + 89 113 + 89 114 + 89 115 + 89 117 + 89 121 + 89 153 + 89 169 + 89 173 + 89 177 + 89 178 + 89 179 + 89 181 + 89 185 + 89 217 + 90 91 + 90 92 + 90 93 + 90 94 + 90 106 + 90 109 + 90 110 + 90 114 + 90 115 + 90 116 + 90 118 + 90 122 + 90 154 + 90 170 + 90 173 + 90 174 + 90 178 + 90 179 + 90 180 + 90 182 + 90 186 + 90 218 + 91 92 + 91 93 + 91 94 + 91 95 + 91 107 + 91 109 + 91 110 + 91 111 + 91 115 + 91 117 + 91 118 + 91 119 + 91 123 + 91 155 + 91 171 + 91 173 + 91 174 + 91 175 + 91 179 + 91 181 + 91 182 + 91 183 + 91 187 + 91 219 + 92 94 + 92 95 + 92 96 + 92 108 + 92 110 + 92 112 + 92 116 + 92 118 + 92 119 + 92 120 + 92 124 + 92 156 + 92 172 + 92 174 + 92 176 + 92 180 + 92 182 + 92 183 + 92 184 + 92 188 + 92 220 + 93 94 + 93 95 + 93 109 + 93 111 + 93 117 + 93 121 + 93 122 + 93 123 + 93 125 + 93 157 + 93 173 + 93 175 + 93 181 + 93 185 + 93 186 + 93 187 + 93 189 + 93 221 + 94 95 + 94 96 + 94 110 + 94 111 + 94 112 + 94 118 + 94 122 + 94 123 + 94 124 + 94 126 + 94 158 + 94 174 + 94 175 + 94 176 + 94 182 + 94 186 + 94 187 + 94 188 + 94 190 + 94 222 + 95 96 + 95 111 + 95 112 + 95 119 + 95 123 + 95 125 + 95 126 + 95 127 + 95 159 + 95 175 + 95 176 + 95 183 + 95 187 + 95 189 + 95 190 + 95 191 + 95 223 + 96 112 + 96 120 + 96 124 + 96 126 + 96 127 + 96 128 + 96 160 + 96 176 + 96 184 + 96 188 + 96 190 + 96 191 + 96 192 + 96 224 + 97 98 + 97 99 + 97 101 + 97 105 + 97 113 + 97 161 + 97 177 + 97 193 + 97 194 + 97 195 + 97 197 + 97 201 + 97 209 + 97 225 + 98 99 + 98 100 + 98 101 + 98 102 + 98 105 + 98 106 + 98 113 + 98 114 + 98 162 + 98 177 + 98 178 + 98 194 + 98 195 + 98 196 + 98 198 + 98 202 + 98 210 + 98 226 + 99 100 + 99 101 + 99 102 + 99 103 + 99 105 + 99 106 + 99 107 + 99 113 + 99 114 + 99 115 + 99 163 + 99 177 + 99 178 + 99 179 + 99 195 + 99 197 + 99 198 + 99 199 + 99 203 + 99 211 + 99 227 + 100 102 + 100 103 + 100 104 + 100 106 + 100 108 + 100 114 + 100 116 + 100 164 + 100 178 + 100 180 + 100 196 + 100 198 + 100 199 + 100 200 + 100 204 + 100 212 + 100 228 + 101 102 + 101 103 + 101 105 + 101 106 + 101 107 + 101 109 + 101 113 + 101 115 + 101 117 + 101 165 + 101 177 + 101 179 + 101 181 + 101 197 + 101 201 + 101 202 + 101 203 + 101 205 + 101 213 + 101 229 + 102 103 + 102 104 + 102 106 + 102 107 + 102 108 + 102 110 + 102 114 + 102 115 + 102 116 + 102 118 + 102 166 + 102 178 + 102 179 + 102 180 + 102 182 + 102 198 + 102 202 + 102 203 + 102 204 + 102 206 + 102 214 + 102 230 + 103 104 + 103 107 + 103 108 + 103 109 + 103 110 + 103 111 + 103 115 + 103 116 + 103 119 + 103 167 + 103 179 + 103 180 + 103 183 + 103 199 + 103 203 + 103 205 + 103 206 + 103 207 + 103 215 + 103 231 + 104 108 + 104 110 + 104 111 + 104 112 + 104 116 + 104 120 + 104 168 + 104 180 + 104 184 + 104 200 + 104 204 + 104 206 + 104 207 + 104 208 + 104 216 + 104 232 + 105 106 + 105 107 + 105 109 + 105 113 + 105 114 + 105 115 + 105 117 + 105 121 + 105 169 + 105 177 + 105 181 + 105 185 + 105 201 + 105 209 + 105 210 + 105 211 + 105 213 + 105 217 + 105 233 + 106 107 + 106 108 + 106 109 + 106 110 + 106 114 + 106 115 + 106 116 + 106 117 + 106 118 + 106 122 + 106 170 + 106 178 + 106 181 + 106 182 + 106 186 + 106 202 + 106 210 + 106 211 + 106 212 + 106 214 + 106 218 + 106 234 + 107 108 + 107 109 + 107 110 + 107 111 + 107 115 + 107 117 + 107 118 + 107 119 + 107 123 + 107 171 + 107 179 + 107 181 + 107 182 + 107 183 + 107 187 + 107 203 + 107 211 + 107 213 + 107 214 + 107 215 + 107 219 + 107 235 + 108 110 + 108 111 + 108 112 + 108 116 + 108 118 + 108 119 + 108 120 + 108 124 + 108 172 + 108 180 + 108 182 + 108 184 + 108 188 + 108 204 + 108 212 + 108 214 + 108 215 + 108 216 + 108 220 + 108 236 + 109 110 + 109 111 + 109 117 + 109 119 + 109 121 + 109 122 + 109 123 + 109 125 + 109 173 + 109 181 + 109 183 + 109 189 + 109 205 + 109 213 + 109 217 + 109 218 + 109 219 + 109 221 + 109 237 + 110 111 + 110 112 + 110 118 + 110 119 + 110 120 + 110 122 + 110 123 + 110 124 + 110 126 + 110 174 + 110 182 + 110 183 + 110 184 + 110 190 + 110 206 + 110 214 + 110 218 + 110 219 + 110 220 + 110 222 + 110 238 + 111 112 + 111 119 + 111 120 + 111 123 + 111 125 + 111 126 + 111 127 + 111 175 + 111 183 + 111 184 + 111 191 + 111 207 + 111 215 + 111 219 + 111 221 + 111 222 + 111 223 + 111 239 + 112 120 + 112 124 + 112 126 + 112 127 + 112 128 + 112 176 + 112 184 + 112 192 + 112 208 + 112 216 + 112 220 + 112 222 + 112 223 + 112 224 + 112 240 + 113 114 + 113 115 + 113 117 + 113 121 + 113 177 + 113 185 + 113 209 + 113 225 + 113 226 + 113 227 + 113 229 + 113 233 + 113 241 + 114 115 + 114 116 + 114 117 + 114 118 + 114 121 + 114 122 + 114 178 + 114 185 + 114 186 + 114 210 + 114 226 + 114 227 + 114 228 + 114 230 + 114 234 + 114 242 + 115 116 + 115 117 + 115 118 + 115 119 + 115 121 + 115 122 + 115 123 + 115 179 + 115 185 + 115 186 + 115 187 + 115 211 + 115 227 + 115 229 + 115 230 + 115 231 + 115 235 + 115 243 + 116 118 + 116 119 + 116 120 + 116 122 + 116 124 + 116 180 + 116 186 + 116 188 + 116 212 + 116 228 + 116 230 + 116 231 + 116 232 + 116 236 + 116 244 + 117 118 + 117 119 + 117 121 + 117 122 + 117 123 + 117 125 + 117 181 + 117 185 + 117 187 + 117 189 + 117 213 + 117 229 + 117 233 + 117 234 + 117 235 + 117 237 + 117 245 + 118 119 + 118 120 + 118 122 + 118 123 + 118 124 + 118 126 + 118 182 + 118 186 + 118 187 + 118 188 + 118 190 + 118 214 + 118 230 + 118 234 + 118 235 + 118 236 + 118 238 + 118 246 + 119 120 + 119 123 + 119 124 + 119 125 + 119 126 + 119 127 + 119 183 + 119 187 + 119 188 + 119 191 + 119 215 + 119 231 + 119 235 + 119 237 + 119 238 + 119 239 + 119 247 + 120 124 + 120 126 + 120 127 + 120 128 + 120 184 + 120 188 + 120 192 + 120 216 + 120 232 + 120 236 + 120 238 + 120 239 + 120 240 + 120 248 + 121 122 + 121 123 + 121 125 + 121 185 + 121 189 + 121 217 + 121 233 + 121 241 + 121 242 + 121 243 + 121 245 + 121 249 + 122 123 + 122 124 + 122 125 + 122 126 + 122 186 + 122 189 + 122 190 + 122 218 + 122 234 + 122 242 + 122 243 + 122 244 + 122 246 + 122 250 + 123 124 + 123 125 + 123 126 + 123 127 + 123 187 + 123 189 + 123 190 + 123 191 + 123 219 + 123 235 + 123 243 + 123 245 + 123 246 + 123 247 + 123 251 + 124 126 + 124 127 + 124 128 + 124 188 + 124 190 + 124 192 + 124 220 + 124 236 + 124 244 + 124 246 + 124 247 + 124 248 + 124 252 + 125 126 + 125 127 + 125 189 + 125 191 + 125 221 + 125 237 + 125 245 + 125 249 + 125 250 + 125 251 + 125 253 + 126 127 + 126 128 + 126 190 + 126 191 + 126 192 + 126 222 + 126 238 + 126 246 + 126 250 + 126 251 + 126 252 + 126 254 + 127 128 + 127 191 + 127 192 + 127 223 + 127 239 + 127 247 + 127 251 + 127 253 + 127 254 + 127 255 + 128 192 + 128 224 + 128 240 + 128 248 + 128 252 + 128 254 + 128 255 + 128 256 + 129 130 + 129 131 + 129 133 + 129 137 + 129 145 + 129 161 + 129 193 + 130 131 + 130 132 + 130 133 + 130 134 + 130 137 + 130 138 + 130 145 + 130 146 + 130 161 + 130 162 + 130 193 + 130 194 + 131 132 + 131 133 + 131 134 + 131 135 + 131 137 + 131 138 + 131 139 + 131 145 + 131 146 + 131 147 + 131 161 + 131 162 + 131 163 + 131 193 + 131 194 + 131 195 + 132 134 + 132 135 + 132 136 + 132 138 + 132 140 + 132 146 + 132 148 + 132 162 + 132 164 + 132 194 + 132 196 + 133 134 + 133 135 + 133 137 + 133 138 + 133 139 + 133 141 + 133 145 + 133 147 + 133 149 + 133 161 + 133 163 + 133 165 + 133 193 + 133 195 + 133 197 + 134 135 + 134 136 + 134 138 + 134 139 + 134 140 + 134 142 + 134 146 + 134 147 + 134 148 + 134 150 + 134 162 + 134 163 + 134 164 + 134 166 + 134 194 + 134 195 + 134 196 + 134 198 + 135 136 + 135 139 + 135 140 + 135 141 + 135 142 + 135 143 + 135 147 + 135 148 + 135 151 + 135 163 + 135 164 + 135 167 + 135 195 + 135 196 + 135 199 + 136 140 + 136 142 + 136 143 + 136 144 + 136 148 + 136 152 + 136 164 + 136 168 + 136 196 + 136 200 + 137 138 + 137 139 + 137 141 + 137 145 + 137 146 + 137 147 + 137 149 + 137 153 + 137 161 + 137 165 + 137 169 + 137 193 + 137 197 + 137 201 + 138 139 + 138 140 + 138 141 + 138 142 + 138 146 + 138 147 + 138 148 + 138 149 + 138 150 + 138 154 + 138 162 + 138 165 + 138 166 + 138 170 + 138 194 + 138 197 + 138 198 + 138 202 + 139 140 + 139 141 + 139 142 + 139 143 + 139 147 + 139 149 + 139 150 + 139 151 + 139 155 + 139 163 + 139 165 + 139 166 + 139 167 + 139 171 + 139 195 + 139 197 + 139 198 + 139 199 + 139 203 + 140 142 + 140 143 + 140 144 + 140 148 + 140 150 + 140 151 + 140 152 + 140 156 + 140 164 + 140 166 + 140 168 + 140 172 + 140 196 + 140 198 + 140 200 + 140 204 + 141 142 + 141 143 + 141 149 + 141 151 + 141 153 + 141 154 + 141 155 + 141 157 + 141 165 + 141 167 + 141 173 + 141 197 + 141 199 + 141 205 + 142 143 + 142 144 + 142 150 + 142 151 + 142 152 + 142 154 + 142 155 + 142 156 + 142 158 + 142 166 + 142 167 + 142 168 + 142 174 + 142 198 + 142 199 + 142 200 + 142 206 + 143 144 + 143 151 + 143 152 + 143 155 + 143 157 + 143 158 + 143 159 + 143 167 + 143 168 + 143 175 + 143 199 + 143 200 + 143 207 + 144 152 + 144 156 + 144 158 + 144 159 + 144 160 + 144 168 + 144 176 + 144 200 + 144 208 + 145 146 + 145 147 + 145 149 + 145 153 + 145 161 + 145 162 + 145 163 + 145 165 + 145 169 + 145 177 + 145 193 + 145 201 + 145 209 + 146 147 + 146 148 + 146 149 + 146 150 + 146 153 + 146 154 + 146 162 + 146 163 + 146 164 + 146 166 + 146 169 + 146 170 + 146 178 + 146 194 + 146 201 + 146 202 + 146 210 + 147 148 + 147 149 + 147 150 + 147 151 + 147 153 + 147 154 + 147 155 + 147 163 + 147 165 + 147 166 + 147 167 + 147 169 + 147 170 + 147 171 + 147 179 + 147 195 + 147 201 + 147 202 + 147 203 + 147 211 + 148 150 + 148 151 + 148 152 + 148 154 + 148 156 + 148 164 + 148 166 + 148 167 + 148 168 + 148 170 + 148 172 + 148 180 + 148 196 + 148 202 + 148 204 + 148 212 + 149 150 + 149 151 + 149 153 + 149 154 + 149 155 + 149 157 + 149 165 + 149 169 + 149 170 + 149 171 + 149 173 + 149 181 + 149 197 + 149 201 + 149 203 + 149 205 + 149 213 + 150 151 + 150 152 + 150 154 + 150 155 + 150 156 + 150 158 + 150 166 + 150 170 + 150 171 + 150 172 + 150 174 + 150 182 + 150 198 + 150 202 + 150 203 + 150 204 + 150 206 + 150 214 + 151 152 + 151 155 + 151 156 + 151 157 + 151 158 + 151 159 + 151 167 + 151 171 + 151 172 + 151 173 + 151 174 + 151 175 + 151 183 + 151 199 + 151 203 + 151 204 + 151 207 + 151 215 + 152 156 + 152 158 + 152 159 + 152 160 + 152 168 + 152 172 + 152 174 + 152 175 + 152 176 + 152 184 + 152 200 + 152 204 + 152 208 + 152 216 + 153 154 + 153 155 + 153 157 + 153 169 + 153 173 + 153 177 + 153 178 + 153 179 + 153 181 + 153 185 + 153 201 + 153 205 + 153 217 + 154 155 + 154 156 + 154 157 + 154 158 + 154 170 + 154 173 + 154 174 + 154 178 + 154 179 + 154 180 + 154 182 + 154 186 + 154 202 + 154 205 + 154 206 + 154 218 + 155 156 + 155 157 + 155 158 + 155 159 + 155 171 + 155 173 + 155 174 + 155 175 + 155 179 + 155 181 + 155 182 + 155 183 + 155 187 + 155 203 + 155 205 + 155 206 + 155 207 + 155 219 + 156 158 + 156 159 + 156 160 + 156 172 + 156 174 + 156 176 + 156 180 + 156 182 + 156 183 + 156 184 + 156 188 + 156 204 + 156 206 + 156 208 + 156 220 + 157 158 + 157 159 + 157 173 + 157 175 + 157 181 + 157 185 + 157 186 + 157 187 + 157 189 + 157 205 + 157 207 + 157 221 + 158 159 + 158 160 + 158 174 + 158 175 + 158 176 + 158 182 + 158 186 + 158 187 + 158 188 + 158 190 + 158 206 + 158 207 + 158 208 + 158 222 + 159 160 + 159 175 + 159 176 + 159 183 + 159 187 + 159 189 + 159 190 + 159 191 + 159 207 + 159 208 + 159 223 + 160 176 + 160 184 + 160 188 + 160 190 + 160 191 + 160 192 + 160 208 + 160 224 + 161 162 + 161 163 + 161 165 + 161 169 + 161 177 + 161 193 + 161 194 + 161 195 + 161 197 + 161 201 + 161 209 + 161 225 + 162 163 + 162 164 + 162 165 + 162 166 + 162 169 + 162 170 + 162 177 + 162 178 + 162 194 + 162 195 + 162 196 + 162 198 + 162 202 + 162 209 + 162 210 + 162 226 + 163 164 + 163 165 + 163 166 + 163 167 + 163 169 + 163 170 + 163 171 + 163 177 + 163 178 + 163 179 + 163 195 + 163 197 + 163 198 + 163 199 + 163 203 + 163 209 + 163 210 + 163 211 + 163 227 + 164 166 + 164 167 + 164 168 + 164 170 + 164 172 + 164 178 + 164 180 + 164 196 + 164 198 + 164 199 + 164 200 + 164 204 + 164 210 + 164 212 + 164 228 + 165 166 + 165 167 + 165 169 + 165 170 + 165 171 + 165 173 + 165 177 + 165 179 + 165 181 + 165 197 + 165 201 + 165 202 + 165 203 + 165 205 + 165 209 + 165 211 + 165 213 + 165 229 + 166 167 + 166 168 + 166 170 + 166 171 + 166 172 + 166 174 + 166 178 + 166 179 + 166 180 + 166 182 + 166 198 + 166 202 + 166 203 + 166 204 + 166 206 + 166 210 + 166 211 + 166 212 + 166 214 + 166 230 + 167 168 + 167 171 + 167 172 + 167 173 + 167 174 + 167 175 + 167 179 + 167 180 + 167 183 + 167 199 + 167 203 + 167 205 + 167 206 + 167 207 + 167 211 + 167 212 + 167 215 + 167 231 + 168 172 + 168 174 + 168 175 + 168 176 + 168 180 + 168 184 + 168 200 + 168 204 + 168 206 + 168 207 + 168 208 + 168 212 + 168 216 + 168 232 + 169 170 + 169 171 + 169 173 + 169 177 + 169 178 + 169 179 + 169 181 + 169 185 + 169 201 + 169 209 + 169 210 + 169 211 + 169 213 + 169 217 + 169 233 + 170 171 + 170 172 + 170 173 + 170 174 + 170 178 + 170 179 + 170 180 + 170 181 + 170 182 + 170 186 + 170 202 + 170 210 + 170 211 + 170 212 + 170 213 + 170 214 + 170 218 + 170 234 + 171 172 + 171 173 + 171 174 + 171 175 + 171 179 + 171 181 + 171 182 + 171 183 + 171 187 + 171 203 + 171 211 + 171 213 + 171 214 + 171 215 + 171 219 + 171 235 + 172 174 + 172 175 + 172 176 + 172 180 + 172 182 + 172 183 + 172 184 + 172 188 + 172 204 + 172 212 + 172 214 + 172 215 + 172 216 + 172 220 + 172 236 + 173 174 + 173 175 + 173 181 + 173 183 + 173 185 + 173 186 + 173 187 + 173 189 + 173 205 + 173 213 + 173 215 + 173 217 + 173 218 + 173 219 + 173 221 + 173 237 + 174 175 + 174 176 + 174 182 + 174 183 + 174 184 + 174 186 + 174 187 + 174 188 + 174 190 + 174 206 + 174 214 + 174 215 + 174 216 + 174 218 + 174 219 + 174 220 + 174 222 + 174 238 + 175 176 + 175 183 + 175 184 + 175 187 + 175 189 + 175 190 + 175 191 + 175 207 + 175 215 + 175 216 + 175 219 + 175 221 + 175 222 + 175 223 + 175 239 + 176 184 + 176 188 + 176 190 + 176 191 + 176 192 + 176 208 + 176 216 + 176 220 + 176 222 + 176 223 + 176 224 + 176 240 + 177 178 + 177 179 + 177 181 + 177 185 + 177 209 + 177 217 + 177 225 + 177 226 + 177 227 + 177 229 + 177 233 + 177 241 + 178 179 + 178 180 + 178 181 + 178 182 + 178 185 + 178 186 + 178 210 + 178 217 + 178 218 + 178 226 + 178 227 + 178 228 + 178 230 + 178 234 + 178 242 + 179 180 + 179 181 + 179 182 + 179 183 + 179 185 + 179 186 + 179 187 + 179 211 + 179 217 + 179 218 + 179 219 + 179 227 + 179 229 + 179 230 + 179 231 + 179 235 + 179 243 + 180 182 + 180 183 + 180 184 + 180 186 + 180 188 + 180 212 + 180 218 + 180 220 + 180 228 + 180 230 + 180 231 + 180 232 + 180 236 + 180 244 + 181 182 + 181 183 + 181 185 + 181 186 + 181 187 + 181 189 + 181 213 + 181 217 + 181 219 + 181 221 + 181 229 + 181 233 + 181 234 + 181 235 + 181 237 + 181 245 + 182 183 + 182 184 + 182 186 + 182 187 + 182 188 + 182 190 + 182 214 + 182 218 + 182 219 + 182 220 + 182 222 + 182 230 + 182 234 + 182 235 + 182 236 + 182 238 + 182 246 + 183 184 + 183 187 + 183 188 + 183 189 + 183 190 + 183 191 + 183 215 + 183 219 + 183 220 + 183 223 + 183 231 + 183 235 + 183 237 + 183 238 + 183 239 + 183 247 + 184 188 + 184 190 + 184 191 + 184 192 + 184 216 + 184 220 + 184 224 + 184 232 + 184 236 + 184 238 + 184 239 + 184 240 + 184 248 + 185 186 + 185 187 + 185 189 + 185 217 + 185 221 + 185 233 + 185 241 + 185 242 + 185 243 + 185 245 + 185 249 + 186 187 + 186 188 + 186 189 + 186 190 + 186 218 + 186 221 + 186 222 + 186 234 + 186 242 + 186 243 + 186 244 + 186 246 + 186 250 + 187 188 + 187 189 + 187 190 + 187 191 + 187 219 + 187 221 + 187 222 + 187 223 + 187 235 + 187 243 + 187 245 + 187 246 + 187 247 + 187 251 + 188 190 + 188 191 + 188 192 + 188 220 + 188 222 + 188 224 + 188 236 + 188 244 + 188 246 + 188 247 + 188 248 + 188 252 + 189 190 + 189 191 + 189 221 + 189 223 + 189 237 + 189 245 + 189 249 + 189 250 + 189 251 + 189 253 + 190 191 + 190 192 + 190 222 + 190 223 + 190 224 + 190 238 + 190 246 + 190 250 + 190 251 + 190 252 + 190 254 + 191 192 + 191 223 + 191 224 + 191 239 + 191 247 + 191 251 + 191 253 + 191 254 + 191 255 + 192 224 + 192 240 + 192 248 + 192 252 + 192 254 + 192 255 + 192 256 + 193 194 + 193 195 + 193 197 + 193 201 + 193 209 + 193 225 + 194 195 + 194 196 + 194 197 + 194 198 + 194 201 + 194 202 + 194 209 + 194 210 + 194 225 + 194 226 + 195 196 + 195 197 + 195 198 + 195 199 + 195 201 + 195 202 + 195 203 + 195 209 + 195 210 + 195 211 + 195 225 + 195 226 + 195 227 + 196 198 + 196 199 + 196 200 + 196 202 + 196 204 + 196 210 + 196 212 + 196 226 + 196 228 + 197 198 + 197 199 + 197 201 + 197 202 + 197 203 + 197 205 + 197 209 + 197 211 + 197 213 + 197 225 + 197 227 + 197 229 + 198 199 + 198 200 + 198 202 + 198 203 + 198 204 + 198 206 + 198 210 + 198 211 + 198 212 + 198 214 + 198 226 + 198 227 + 198 228 + 198 230 + 199 200 + 199 203 + 199 204 + 199 205 + 199 206 + 199 207 + 199 211 + 199 212 + 199 215 + 199 227 + 199 228 + 199 231 + 200 204 + 200 206 + 200 207 + 200 208 + 200 212 + 200 216 + 200 228 + 200 232 + 201 202 + 201 203 + 201 205 + 201 209 + 201 210 + 201 211 + 201 213 + 201 217 + 201 225 + 201 229 + 201 233 + 202 203 + 202 204 + 202 205 + 202 206 + 202 210 + 202 211 + 202 212 + 202 213 + 202 214 + 202 218 + 202 226 + 202 229 + 202 230 + 202 234 + 203 204 + 203 205 + 203 206 + 203 207 + 203 211 + 203 213 + 203 214 + 203 215 + 203 219 + 203 227 + 203 229 + 203 230 + 203 231 + 203 235 + 204 206 + 204 207 + 204 208 + 204 212 + 204 214 + 204 215 + 204 216 + 204 220 + 204 228 + 204 230 + 204 232 + 204 236 + 205 206 + 205 207 + 205 213 + 205 215 + 205 217 + 205 218 + 205 219 + 205 221 + 205 229 + 205 231 + 205 237 + 206 207 + 206 208 + 206 214 + 206 215 + 206 216 + 206 218 + 206 219 + 206 220 + 206 222 + 206 230 + 206 231 + 206 232 + 206 238 + 207 208 + 207 215 + 207 216 + 207 219 + 207 221 + 207 222 + 207 223 + 207 231 + 207 232 + 207 239 + 208 216 + 208 220 + 208 222 + 208 223 + 208 224 + 208 232 + 208 240 + 209 210 + 209 211 + 209 213 + 209 217 + 209 225 + 209 226 + 209 227 + 209 229 + 209 233 + 209 241 + 210 211 + 210 212 + 210 213 + 210 214 + 210 217 + 210 218 + 210 226 + 210 227 + 210 228 + 210 230 + 210 233 + 210 234 + 210 242 + 211 212 + 211 213 + 211 214 + 211 215 + 211 217 + 211 218 + 211 219 + 211 227 + 211 229 + 211 230 + 211 231 + 211 233 + 211 234 + 211 235 + 211 243 + 212 214 + 212 215 + 212 216 + 212 218 + 212 220 + 212 228 + 212 230 + 212 231 + 212 232 + 212 234 + 212 236 + 212 244 + 213 214 + 213 215 + 213 217 + 213 218 + 213 219 + 213 221 + 213 229 + 213 233 + 213 234 + 213 235 + 213 237 + 213 245 + 214 215 + 214 216 + 214 218 + 214 219 + 214 220 + 214 222 + 214 230 + 214 234 + 214 235 + 214 236 + 214 238 + 214 246 + 215 216 + 215 219 + 215 220 + 215 221 + 215 222 + 215 223 + 215 231 + 215 235 + 215 236 + 215 237 + 215 238 + 215 239 + 215 247 + 216 220 + 216 222 + 216 223 + 216 224 + 216 232 + 216 236 + 216 238 + 216 239 + 216 240 + 216 248 + 217 218 + 217 219 + 217 221 + 217 233 + 217 237 + 217 241 + 217 242 + 217 243 + 217 245 + 217 249 + 218 219 + 218 220 + 218 221 + 218 222 + 218 234 + 218 237 + 218 238 + 218 242 + 218 243 + 218 244 + 218 246 + 218 250 + 219 220 + 219 221 + 219 222 + 219 223 + 219 235 + 219 237 + 219 238 + 219 239 + 219 243 + 219 245 + 219 246 + 219 247 + 219 251 + 220 222 + 220 223 + 220 224 + 220 236 + 220 238 + 220 240 + 220 244 + 220 246 + 220 247 + 220 248 + 220 252 + 221 222 + 221 223 + 221 237 + 221 239 + 221 245 + 221 249 + 221 250 + 221 251 + 221 253 + 222 223 + 222 224 + 222 238 + 222 239 + 222 240 + 222 246 + 222 250 + 222 251 + 222 252 + 222 254 + 223 224 + 223 239 + 223 240 + 223 247 + 223 251 + 223 253 + 223 254 + 223 255 + 224 240 + 224 248 + 224 252 + 224 254 + 224 255 + 224 256 + 225 226 + 225 227 + 225 229 + 225 233 + 225 241 + 226 227 + 226 228 + 226 229 + 226 230 + 226 233 + 226 234 + 226 241 + 226 242 + 227 228 + 227 229 + 227 230 + 227 231 + 227 233 + 227 234 + 227 235 + 227 241 + 227 242 + 227 243 + 228 230 + 228 231 + 228 232 + 228 234 + 228 236 + 228 242 + 228 244 + 229 230 + 229 231 + 229 233 + 229 234 + 229 235 + 229 237 + 229 241 + 229 243 + 229 245 + 230 231 + 230 232 + 230 234 + 230 235 + 230 236 + 230 238 + 230 242 + 230 243 + 230 244 + 230 246 + 231 232 + 231 235 + 231 236 + 231 237 + 231 238 + 231 239 + 231 243 + 231 244 + 231 247 + 232 236 + 232 238 + 232 239 + 232 240 + 232 244 + 232 248 + 233 234 + 233 235 + 233 237 + 233 241 + 233 242 + 233 243 + 233 245 + 233 249 + 234 235 + 234 236 + 234 237 + 234 238 + 234 242 + 234 243 + 234 244 + 234 245 + 234 246 + 234 250 + 235 236 + 235 237 + 235 238 + 235 239 + 235 243 + 235 245 + 235 246 + 235 247 + 235 251 + 236 238 + 236 239 + 236 240 + 236 244 + 236 246 + 236 247 + 236 248 + 236 252 + 237 238 + 237 239 + 237 245 + 237 247 + 237 249 + 237 250 + 237 251 + 237 253 + 238 239 + 238 240 + 238 246 + 238 247 + 238 248 + 238 250 + 238 251 + 238 252 + 238 254 + 239 240 + 239 247 + 239 248 + 239 251 + 239 253 + 239 254 + 239 255 + 240 248 + 240 252 + 240 254 + 240 255 + 240 256 + 241 242 + 241 243 + 241 245 + 241 249 + 242 243 + 242 244 + 242 245 + 242 246 + 242 249 + 242 250 + 243 244 + 243 245 + 243 246 + 243 247 + 243 249 + 243 250 + 243 251 + 244 246 + 244 247 + 244 248 + 244 250 + 244 252 + 245 246 + 245 247 + 245 249 + 245 250 + 245 251 + 245 253 + 246 247 + 246 248 + 246 250 + 246 251 + 246 252 + 246 254 + 247 248 + 247 251 + 247 252 + 247 253 + 247 254 + 247 255 + 248 252 + 248 254 + 248 255 + 248 256 + 249 250 + 249 251 + 249 253 + 250 251 + 250 252 + 250 253 + 250 254 + 251 252 + 251 253 + 251 254 + 251 255 + 252 254 + 252 255 + 252 256 + 253 254 + 253 255 + 254 255 + 254 256 + 255 256 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/money.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/money.mod new file mode 100644 index 000000000..e43ef390b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/money.mod @@ -0,0 +1,62 @@ +/* MONEY, a crypto-arithmetic puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* This is the classic example of a crypto-arithmetic puzzle published + in the Strand Magazine by Henry Dudeney: + + S E N D + + + M O R E + --------- + M O N E Y + + In this puzzle the same letters mean the same digits. The question + is: how to replace all the letters with the respective digits that + makes the calculation correct? + + The solution to this puzzle is: + O = 0, M = 1, Y = 2, E = 5, N = 6, D = 7, R = 8, and S = 9. + + References: + H. E. Dudeney, in Strand Magazine vol. 68 (July 1924), pp. 97, 214. + + (From Wikipedia, the free encyclopedia.) */ + +set LETTERS := { 'D', 'E', 'M', 'N', 'O', 'R', 'S', 'Y' }; +/* set of letters */ + +set DIGITS := 0..9; +/* set of digits */ + +var x{i in LETTERS, d in DIGITS}, binary; +/* x[i,d] = 1 means that letter i is digit d */ + +s.t. one{i in LETTERS}: sum{d in DIGITS} x[i,d] = 1; +/* each letter must correspond exactly to one digit */ + +s.t. alldiff{d in DIGITS}: sum{i in LETTERS} x[i,d] <= 1; +/* different letters must correspond to different digits; note that + some digits may not correspond to any letters at all */ + +var dig{i in LETTERS}; +/* dig[i] is a digit corresponding to letter i */ + +s.t. map{i in LETTERS}: dig[i] = sum{d in DIGITS} d * x[i,d]; + +var carry{1..3}, binary; +/* carry bits */ + +s.t. sum1: dig['D'] + dig['E'] = dig['Y'] + 10 * carry[1]; +s.t. sum2: dig['N'] + dig['R'] + carry[1] = dig['E'] + 10 * carry[2]; +s.t. sum3: dig['E'] + dig['O'] + carry[2] = dig['N'] + 10 * carry[3]; +s.t. sum4: dig['S'] + dig['M'] + carry[3] = dig['O'] + 10 * dig['M']; +s.t. note: dig['M'] >= 1; /* M must not be 0 */ + +solve; +/* solve the puzzle */ + +display dig; +/* and display its solution */ + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp1.c b/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp1.c new file mode 100644 index 000000000..7c5e47d4d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp1.c @@ -0,0 +1,32 @@ +/* mplsamp1.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *lp; + glp_tran *tran; + int ret; + lp = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "egypt.mod", 0); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, lp); + ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); + if (ret != 0) + fprintf(stderr, "Error on writing MPS file\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp2.c b/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp2.c new file mode 100644 index 000000000..0ff6ad0ff --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/mplsamp2.c @@ -0,0 +1,39 @@ +/* mplsamp2.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *mip; + glp_tran *tran; + int ret; + mip = glp_create_prob(); + tran = glp_mpl_alloc_wksp(); + ret = glp_mpl_read_model(tran, "sudoku.mod", 1); + if (ret != 0) + { fprintf(stderr, "Error on translating model\n"); + goto skip; + } + ret = glp_mpl_read_data(tran, "sudoku.dat"); + if (ret != 0) + { fprintf(stderr, "Error on translating data\n"); + goto skip; + } + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) + { fprintf(stderr, "Error on generating model\n"); + goto skip; + } + glp_mpl_build_prob(tran, mip); + glp_simplex(mip, NULL); + glp_intopt(mip, NULL); + ret = glp_mpl_postsolve(tran, mip, GLP_MIP); + if (ret != 0) + fprintf(stderr, "Error on postsolving model\n"); +skip: glp_mpl_free_wksp(tran); + glp_delete_prob(mip); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/murtagh.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/murtagh.mps new file mode 100644 index 000000000..c03741b51 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/murtagh.mps @@ -0,0 +1,600 @@ +*NAME: OIL +*ROWS: 74 +*COLUMNS: 81 +*NONZERO: 504 +*OPT SOLN: 126.057 +*SOURCE: Bruce Murtagh, "Advanced Linear Programming" +*APPLICATION: oil refinery model +*COMMENTS: problem is maximization +* +NAME OIL REFINERY EXAMPLE +ROWS + N PROFIT + L MVOLBOL + L MVOLCOL + E MVOLLNC + E MVOLLNB + E MVOLSRK + E MVOLSRD + E MVOLVBB + E MVOLVBC + E MVOLRCR + E MVOLHVO + E UBALKWH + E UBALH2O + E UBALSTM + E UBALFUL + E MVOLB95 + E MVOLB90 + E MVOLLHG + E MVOLC3S + E MVOLNC4 + E MVOLLSR + E MVOLHSR + E MVOLIC4 + L VCAPSGP + E MVOLRFG + E MSCFHYL + E MVOLR90 + E MVOLR95 + E MVOLF90 + E MVOLF95 + L VCAPRFG + E MVOLLCO + E MVOLHHG + E MVOLHCD + L VCAPHVO + L VCAPHOL + E MVOLC3U + E MVOLC4U + E MVOLFCG + E MVOLSLR + L VCAPCCU + E MVOLLA3 + E MVOLLA4 + L VCAPALK + L XLPRPRE + L XHPRPRE + L XTELPRE + L XRVPPRE + L X200PRE + L X230PRE + E EVOLPRE + L XPSCPRE + L XRSCREG + L XLPRINT + L XHPRINT + L XTELINT + L XRVPINT + L X200INT + L X230INT + E EVOLINT + L XLPRREG + L XHPRREG + L XTELREG + L XRVPREG + L X200REG + L X230REG + E EVOLREG + E EVOLLPG + E EVOLJP4 + L XRVXJP4 + L XRVNJP4 + E EVOLDSL + E EVOLRSD + L XVISRSD +COLUMNS + VCRDBOL MVOLBOL 1.0 + VCRDBOL MVOLLNB -.537 + VCRDBOL MVOLSRK -.131 + VCRDBOL MVOLSRD -.1155 + VCRDBOL MVOLVBB -.037 + VCRDBOL MVOLRCR -.0365 + VCRDBOL MVOLHVO -.143 + VCRDBOL UBALKWH .302 + VCRDBOL UBALH2O .150 + VCRDBOL UBALSTM .003 + VCRDBOL UBALFUL .0587 + VCRDBOL PROFIT -12.8 + VCRDCOL MVOLCOL 1. + VCRDCOL MVOLLNC -.2931 + VCRDCOL MVOLSRK -.1170 + VCRDCOL MVOLSRD -.0649 + VCRDCOL MVOLVBC -.18 + VCRDCOL MVOLRCR -.1233 + VCRDCOL MVOLHVO -.2217 + VCRDCOL UBALKWH .384 + VCRDCOL UBALH2O .185 + VCRDCOL UBALSTM .003 + VCRDCOL UBALFUL .1053 + VCRDCOL PROFIT -11.48 + VSGPLNC MVOLLNC 1. + VSGPLNC MVOLC3S -.0112 + VSGPLNC MVOLNC4 -.0378 + VSGPLNC MVOLLSR -.1502 + VSGPLNC MVOLHSR -.7953 + VSGPLNC MVOLIC4 -.0099 + VSGPLNC UBALKWH .721 + VSGPLNC UBALH2O .185 + VSGPLNC UBALSTM .013 + VSGPLNC UBALFUL .0488 + VSGPLNC VCAPSGP 1. + VSGPLNB MVOLLNB 1. + VSGPLNB MVOLC3S -.0277 + VSGPLNB MVOLNC4 -.0563 + VSGPLNB MVOLLSR -.199 + VSGPLNB MVOLHSR -.6873 + VSGPLNB MVOLIC4 -.017 + VSGPLNB UBALKWH .495 + VSGPLNB UBALH2O .209 + VSGPLNB UBALSTM .013 + VSGPLNB UBALFUL .0506 + VSGPLNB VCAPSGP 1. + VSGPLHG MVOLLHG 1.0 + VSGPLHG MVOLC3S -.175 + VSGPLHG MVOLNC4 -.27 + VSGPLHG MVOLLSR -.028 + VSGPLHG MVOLIC4 -.455 + VSGPLHG UBALKWH .495 + VSGPLHG UBALH2O .209 + VSGPLHG UBALSTM .013 + VSGPLHG UBALFUL .0448 + VSGPB95 MVOLB95 1. + VSGPB95 MVOLC3S -.2836 + VSGPB95 MVOLNC4 -.3285 + VSGPB95 MVOLLSR -.0241 + VSGPB95 MVOLIC4 -.2502 + VSGPB95 UBALKWH .495 + VSGPB95 UBALH2O .209 + VSGPB95 UBALSTM .013 + VSGPB95 UBALFUL .0506 + VSGPB90 MVOLB90 1. + VSGPB90 MVOLC3S -.271 + VSGPB90 MVOLNC4 -.3289 + VSGPB90 MVOLLSR -.0255 + VSGPB90 MVOLIC4 -.2656 + VSGPB90 UBALKWH .495 + VSGPB90 UBALH2O .209 + VSGPB90 UBALSTM .013 + VSGPB90 UBALFUL .0506 + VH2RHSR MVOLHSR 1. + VH2RHSR MVOLRFG -1. + VH2RHSR MSCFHYL .0327 + VH2RHSR UBALKWH .793 + VH2RHSR UBALH2O .045 + VH2RHSR UBALFUL .094 + VH2RHSR PROFIT -.0176 + VRFFRF1 MVOLRFG 1.0 + VRFFRF1 MVOLR90 -1.0 + VRFFRF2 MVOLRFG 1.0 + VRFFRF2 MVOLR95 -1.0 + VRFFHH1 MVOLR90 -1.0 + VRFFHH1 MVOLHHG 1.0 + VRFFHH2 MVOLR95 -1.0 + VRFFHH2 MVOLHHG 1.0 + VRFGR90 MVOLR90 1.0 + VRFGR90 MVOLB90 -.0404 + VRFGR90 MVOLF90 -0.8564 + VRFGR90 MSCFHYL -0.8239 + VRFGR90 UBALKWH .792 + VRFGR90 UBALH2O .297 + VRFGR90 UBALSTM 0.0063 + VRFGR90 UBALFUL -0.156 + VRFGR90 VCAPRFG 1.0 + VRFGR90 PROFIT -0.1512 + VRFGR95 MVOLR95 1.0 + VRFGR95 MVOLB95 -0.0588 + VRFGR95 MVOLF95 -0.8145 + VRFGR95 MSCFHYL -.7689 + VRFGR95 UBALKWH 1.03 + VRFGR95 UBALH2O .387 + VRFGR95 UBALSTM 0.008 + VRFGR95 UBALFUL -.2112 + VRFGR95 VCAPRFG 1.3 + VRFGR95 PROFIT -0.304 + VHOLLCO MVOLLCO 1.0 + VHOLLCO MVOLHHG -.6627 + VHOLLCO MVOLLHG -0.2414 + VHOLLCO MVOLHCD -.2930 + VHOLLCO MSCFHYL 2.3 + VHOLLCO UBALFUL -.2054 + VHOLLCO UBALH2O 0.826 + VHOLLCO UBALKWH 14.61 + VHOLLCO VCAPHOL 1.0 + VHOLLCO PROFIT -0.2112 + VHOLSRD MVOLSRD 1.0 + VHOLSRD MVOLHHG -.6627 + VHOLSRD MVOLLHG -0.2414 + VHOLSRD MVOLHCD -.2930 + VHOLSRD MSCFHYL 2.3 + VHOLSRD UBALFUL -.2054 + VHOLSRD UBALH2O 0.826 + VHOLSRD UBALKWH 14.61 + VHOLSRD VCAPHOL 1.0 + VHOLSRD PROFIT -0.2112 + VHOLRCR MVOLRCR 1.0 + VHOLRCR MVOLHHG -.5875 + VHOLRCR MVOLLHG -0.3321 + VHOLRCR MVOLHCD -.3620 + VHOLRCR MSCFHYL 2.3 + VHOLRCR UBALFUL -.2054 + VHOLRCR UBALH2O 0.826 + VHOLRCR UBALKWH 14.61 + VHOLRCR VCAPHOL 1.0 + VHOLRCR PROFIT -0.2112 + VHOLHVO MVOLHVO 1.0 + VHOLHVO MVOLHHG -.5875 + VHOLHVO MVOLLHG -0.3321 + VHOLHVO MVOLHCD -.3620 + VHOLHVO MSCFHYL 2.3 + VHOLHVO UBALFUL -.2054 + VHOLHVO UBALH2O 0.826 + VHOLHVO UBALKWH 14.61 + VHOLHVO VCAPHVO 1.0 + VHOLHVO VCAPHOL 1.0 + VHOLHVO PROFIT -0.2112 + VCCUSRK MVOLSRK 1.0 + VCCUSRK MVOLNC4 -0.0184 + VCCUSRK MVOLC3S -0.0303 + VCCUSRK MVOLIC4 -0.0564 + VCCUSRK MVOLC3U -0.0655 + VCCUSRK MVOLC4U -0.0780 + VCCUSRK MVOLFCG -0.4750 + VCCUSRK MVOLLCO -0.3050 + VCCUSRK UBALSTM -.0654 + VCCUSRK UBALFUL -.2703 + VCCUSRK UBALH2O .632 + VCCUSRK UBALKWH .6807 + VCCUSRK VCAPCCU 1. + VCCUSRK PROFIT -.2112 + VCCUSRD MVOLSRD 1. + VCCUSRD MVOLNC4 -.0184 + VCCUSRD MVOLC3S -.0303 + VCCUSRD MVOLIC4 -.0564 + VCCUSRD MVOLC3U -.0655 + VCCUSRD MVOLC4U -.0780 + VCCUSRD MVOLFCG -.4750 + VCCUSRD MVOLLCO -.3050 + VCCUSRD UBALSTM -.0654 + VCCUSRD UBALFUL -.2703 + VCCUSRD UBALH2O 0.632 + VCCUSRD UBALKWH .6807 + VCCUSRD VCAPCCU 1. + VCCUSRD PROFIT -.2112 + VCCURCR MVOLRCR 1.0 + VCCURCR MVOLNC4 -.0185 + VCCURCR MVOLC3S -.0328 + VCCURCR MVOLIC4 -.0568 + VCCURCR MVOLC3U -.0658 + VCCURCR MVOLC4U -.0806 + VCCURCR MVOLFCG -.4934 + VCCURCR MVOLLCO -.2922 + VCCURCR MVOLSLR -.0096 + VCCURCR UBALSTM -.0654 + VCCURCR UBALFUL -.2703 + VCCURCR UBALH2O 0.632 + VCCURCR UBALKWH .6807 + VCCURCR VCAPCCU 1. + VCCURCR PROFIT -.2112 + VCCUHVO MVOLHVO 1.0 + VCCUHVO MVOLNC4 -.0185 + VCCUHVO MVOLC3S -.0328 + VCCUHVO MVOLIC4 -.0568 + VCCUHVO MVOLC3U -.0658 + VCCUHVO MVOLC4U -.0806 + VCCUHVO MVOLFCG -.4934 + VCCUHVO MVOLLCO -.2922 + VCCUHVO MVOLSLR -.0096 + VCCUHVO UBALSTM -.0654 + VCCUHVO UBALFUL -.2703 + VCCUHVO UBALH2O 0.632 + VCCUHVO UBALKWH .6807 + VCCUHVO VCAPHVO 1. + VCCUHVO VCAPCCU 1. + VCCUHVO PROFIT -.2112 + VALKLA3 MVOLIC4 .7600 + VALKLA3 MVOLC3U .5714 + VALKLA3 MVOLLA3 -1.0 + VALKLA3 UBALSTM .1869 + VALKLA3 UBALFUL .2796 + VALKLA3 UBALH2O 2.241 + VALKLA3 UBALKWH 2.766 + VALKLA3 VCAPALK 1.0 + VALKLA3 PROFIT -.512 + VALKLA4 MVOLIC4 .6571 + VALKLA4 MVOLC4U .5714 + VALKLA4 MVOLC3S -.0571 + VALKLA4 MVOLNC4 -.0114 + VALKLA4 MVOLLA4 -1.0 + VALKLA4 UBALSTM .1724 + VALKLA4 UBALFUL .2579 + VALKLA4 UBALH2O 2.067 + VALKLA4 UBALKWH 2.552 + VALKLA4 VCAPALK 1.0 + VALKLA4 PROFIT -.472 + VALKIC4 MVOLIC4 1.0 + VALKIC4 MVOLNC4 -1.0 + VALKC3U MVOLC3U 1.0 + VALKC3U MVOLC3S -1.0 + VALKC4U MVOLC4U 1.0 + VALKC4U MVOLNC4 -1.0 + UTILC3S MVOLC3S 1. + UTILC3S UBALFUL -3.814 + UTILNC4 MVOLNC4 1. + UTILNC4 UBALFUL -4.316 + UTILIC4 MVOLIC4 1. + UTILIC4 UBALFUL -4.153 + UTILC3U MVOLC3U 1. + UTILC3U UBALFUL -3.808 + UTILC4U MVOLC4U 1. + UTILC4U UBALFUL -4.44 + UTILHYL MSCFHYL 1. + UTILHYL UBALFUL -.305 + UTILSTM UBALSTM -1. + UTILSTM UBALFUL 1.42 + UTILSTM PROFIT -.16 + PURCPC4 MVOLIC4 -.5 + PURCPC4 MVOLNC4 -.5 + PURCPC4 PROFIT -12. + PURCH2O UBALH2O -1. + PURCH2O PROFIT -.0528 + PURCKWH UBALKWH -1. + PURCKWH PROFIT -.04 + PURCFUL UBALFUL -1. + PURCFUL PROFIT -1.6 + PURCFLR UBALFUL 1. + BLPGC3S MVOLC3S 1.0 + BLPGC3S EVOLLPG -1.0 + BLPGNC4 MVOLNC4 1.0 + BLPGNC4 EVOLLPG -1.0 + SELLLPG EVOLLPG 1.0 + SELLLPG PROFIT 11.0 + BUP4LSR MVOLLSR 1.0 + BUP4LSR EVOLJP4 -1.0 + BUP4LSR XRVXJP4 14.0 + BUP4LSR XRVNJP4 -14.0 + BUP4HSR MVOLHSR 1.0 + BUP4HSR EVOLJP4 -1.0 + BUP4HSR XRVXJP4 0.8 + BUP4HSR XRVNJP4 -0.8 + SELLJP4 EVOLJP4 1.0 + SELLJP4 XRVXJP4 -3.0 + SELLJP4 XRVNJP4 2.0 + SELLJP4 PROFIT 16.8 + BDSLSRK MVOLSRK 1.0 + BDSLSRK EVOLDSL -1.0 + BDSLSRD MVOLSRD 1.0 + BDSLSRD EVOLDSL -1.0 + SELLDSL EVOLDSL 1.0 + SELLDSL PROFIT 14.4 + BPRELSR MVOLLSR 1. + BPRELSR XLPRPRE -7.95 + BPRELSR XHPRPRE -8.70 + BPRELSR XTELPRE -3.00 + BPRELSR XRVPPRE 14.00 + BPRELSR X200PRE 1. + BPRELSR X230PRE -1. + BPRELSR EVOLPRE -1. + BPREHCD MVOLHCD 1.0 + BPREHCD XLPRPRE -8.84 + BPREHCD XHPRPRE -9.45 + BPREHCD XTELPRE -3.00 + BPREHCD XRVPPRE 12.00 + BPREHCD X200PRE 1. + BPREHCD X230PRE -1. + BPREHCD EVOLPRE -1. + BPREF95 MVOLF95 1.0 + BPREF95 XLPRPRE -9.43 + BPREF95 XHPRPRE -9.57 + BPREF95 XTELPRE -3. + BPREF95 XRVPPRE 3.5 + BPREF95 X200PRE .233 + BPREF95 X230PRE -.358 + BPREF95 EVOLPRE -1. + BPREF90 MVOLF90 1.0 + BPREF90 XLPRPRE -9.03 + BPREF90 XHPRPRE -9.32 + BPREF90 XTELPRE -3.0 + BPREF90 XRVPPRE 3.5 + BPREF90 X200PRE .205 + BPREF90 X230PRE -.333 + BPREF90 EVOLPRE -1. + BPREFCG MVOLFCG 1.0 + BPREFCG XLPRPRE -9.23 + BPREFCG XHPRPRE -9.22 + BPREFCG XTELPRE -3. + BPREFCG XRVPPRE 6. + BPREFCG X200PRE .381 + BPREFCG X230PRE -.509 + BPREFCG EVOLPRE -1. + BPRELA3 MVOLLA3 1.0 + BPRELA3 XLPRPRE -9.4 + BPRELA3 XHPRPRE -9.85 + BPRELA3 XTELPRE -3.0 + BPRELA3 XRVPPRE 2.5 + BPRELA3 X200PRE 0.39 + BPRELA3 X230PRE -0.77 + BPRELA3 EVOLPRE -1.0 + BPRELA4 MVOLLA4 1.0 + BPRELA4 XLPRPRE -9.74 + BPRELA4 XHPRPRE -10.1 + BPRELA4 XTELPRE -3.0 + BPRELA4 XRVPPRE 3.3 + BPRELA4 X200PRE 0.233 + BPRELA4 X230PRE -0.58 + BPRELA4 EVOLPRE -1.0 + BPRENC4 MVOLNC4 1.0 + BPRENC4 XLPRPRE -9.74 + BPRENC4 XHPRPRE -9.9 + BPRENC4 XTELPRE -3.0 + BPRENC4 XRVPPRE 66.0 + BPRENC4 X200PRE 1.0 + BPRENC4 X230PRE -1.0 + BPRENC4 EVOLPRE -1.0 + BPRETEL XLPRPRE -0.493 + BPRETEL XHPRPRE -0.165 + BPRETEL XTELPRE 1.0 + BPRETEL PROFIT -0.3696 + SELLPRE XLPRPRE 10.03 + SELLPRE XHPRPRE 10.03 + SELLPRE XRVPPRE -9.5 + SELLPRE X200PRE -0.5 + SELLPRE X230PRE 0.5 + SELLPRE XPSCPRE 0.64 + SELLPRE XRSCREG 0.35 + SELLPRE EVOLPRE 1.0 + SELLPRE PROFIT 21.44 + BINTLSR MVOLLSR 1.0 + BINTLSR XLPRINT -7.98 + BINTLSR XHPRINT -8.58 + BINTLSR XTELINT -3.0 + BINTLSR XRVPINT 14.0 + BINTLSR X200INT 1.0 + BINTLSR X230INT -1.0 + BINTLSR EVOLINT -1.0 + BINTHCD MVOLHCD 1. + BINTHCD XLPRINT -8.87 + BINTHCD XHPRINT -9.33 + BINTHCD XTELINT -3.0 + BINTHCD XRVPINT 12.0 + BINTHCD X200INT 1.0 + BINTHCD X230INT -1. + BINTHCD EVOLINT -1.0 + BINTF95 MVOLF95 1. + BINTF95 XLPRINT -9.46 + BINTF95 XHPRINT -9.45 + BINTF95 XTELINT -3.0 + BINTF95 XRVPINT 3.5 + BINTF95 X200INT .233 + BINTF95 X230INT -.358 + BINTF95 EVOLINT -1.0 + BINTF90 MVOLF90 1. + BINTF90 XLPRINT -9.06 + BINTF90 XHPRINT -9.20 + BINTF90 XTELINT -3.0 + BINTF90 XRVPINT 3.5 + BINTF90 X200INT .205 + BINTF90 X230INT -.333 + BINTF90 EVOLINT -1.0 + BINTFCG MVOLFCG 1. + BINTFCG XLPRINT -9.26 + BINTFCG XHPRINT -9.13 + BINTFCG XTELINT -3.0 + BINTFCG XRVPINT 6. + BINTFCG X200INT .318 + BINTFCG X230INT -.509 + BINTFCG EVOLINT -1.0 + BINTNC4 MVOLNC4 1. + BINTNC4 XLPRINT -9.77 + BINTNC4 XHPRINT -9.78 + BINTNC4 XTELINT -3.0 + BINTNC4 XRVPINT 66. + BINTNC4 X200INT 1.0 + BINTNC4 X230INT -1. + BINTNC4 EVOLINT -1.0 + BINTTEL XLPRINT -.435 + BINTTEL XHPRINT -.208 + BINTTEL XTELINT 1. + BINTTEL PROFIT -.3696 + SELLINT XLPRINT 9.65 + SELLINT XHPRINT 9.65 + SELLINT XRVPINT -9.5 + SELLINT X200INT -0.5 + SELLINT X230INT 0.5 + SELLINT XPSCPRE -.36 + SELLINT XRSCREG 0.35 + SELLINT EVOLINT 1.0 + SELLINT PROFIT 20.32 + BREGLSR MVOLLSR 1.0 + BREGLSR XLPRREG -7.99 + BREGLSR XHPRREG -8.59 + BREGLSR XTELREG -3.0 + BREGLSR XRVPREG 14.0 + BREGLSR X200REG 1.0 + BREGLSR X230REG -1.0 + BREGLSR EVOLREG -1.0 + BREGHCD MVOLHCD 1.0 + BREGHCD XLPRREG -8.88 + BREGHCD XHPRREG -9.34 + BREGHCD XTELREG -3.0 + BREGHCD XRVPREG 12.0 + BREGHCD X200REG 1.0 + BREGHCD X230REG -1.0 + BREGHCD EVOLREG -1.0 + BREGF95 MVOLF95 1.0 + BREGF95 XLPRREG -9.47 + BREGF95 XHPRREG -9.46 + BREGF95 XTELREG -3.0 + BREGF95 XRVPREG 3.5 + BREGF95 X200REG .233 + BREGF95 X230REG -0.358 + BREGF95 EVOLREG -1.0 + BREGF90 MVOLF90 1.0 + BREGF90 XLPRREG -9.07 + BREGF90 XHPRREG -9.21 + BREGF90 XTELREG -3.0 + BREGF90 XRVPREG 3.5 + BREGF90 X200REG .205 + BREGF90 X230REG -0.333 + BREGF90 EVOLREG -1.0 + BREGFCG MVOLFCG 1.0 + BREGFCG XLPRREG -9.27 + BREGFCG XHPRREG -9.14 + BREGFCG XTELREG -3.0 + BREGFCG XRVPREG 6.0 + BREGFCG X200REG 0.318 + BREGFCG X230REG -0.509 + BREGFCG EVOLREG -1.0 + BREGNC4 MVOLNC4 1.0 + BREGNC4 XLPRREG -9.78 + BREGNC4 XHPRREG -9.79 + BREGNC4 XTELREG -3.0 + BREGNC4 XRVPREG 66.0 + BREGNC4 X200REG 1.0 + BREGNC4 X230REG -1.0 + BREGNC4 EVOLREG -1.0 + BREGTEL XLPRREG -0.426 + BREGTEL XHPRREG -.204 + BREGTEL XTELREG 1.0 + BREGTEL PROFIT -0.3696 + SELLREG XLPRREG 9.05 + SELLREG XHPRREG 9.05 + SELLREG XRVPREG -9.5 + SELLREG X200REG -0.5 + SELLREG X230REG 0.5 + SELLREG XPSCPRE -0.36 + SELLREG XRSCREG -0.65 + SELLREG EVOLREG 1.0 + SELLREG PROFIT 18.04 + BRSDVBB MVOLVBB 1.0 + BRSDVBB EVOLRSD -1.0 + BRSDVBB XVISRSD 10.1 + BRSDVBC MVOLVBC 1.0 + BRSDVBC EVOLRSD -1.0 + BRSDVBC XVISRSD 12.63 + BRSDRCR MVOLRCR 1.0 + BRSDRCR EVOLRSD -1.0 + BRSDRCR XVISRSD 6.9 + BRSDHVO MVOLHVO 1.0 + BRSDHVO EVOLRSD -1.0 + BRSDHVO XVISRSD 8.05 + BRSDHVO VCAPHVO 1.0 + BRSDSLR MVOLSLR 1.0 + BRSDSLR EVOLRSD -1.0 + BRSDSLR XVISRSD 8.05 + BRSDLCO MVOLLCO 1.0 + BRSDLCO EVOLRSD -1.0 + BRSDLCO XVISRSD 4.4 + SELLRSD EVOLRSD 1.0 + SELLRSD XVISRSD -10.1 + SELLRSD PROFIT 8.00 +RHS + LIMITMAX MVOLBOL 26.316 + LIMITMAX MVOLCOL 21.052 + LIMITMAX VCAPSGP 23.25 + LIMITMAX VCAPHVO 5.25 + LIMITMAX VCAPRFG 13.455 + LIMITMAX VCAPHOL 3.87 + LIMITMAX VCAPCCU 7.26 + LIMITMAX VCAPALK 10. +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/mvcp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/mvcp.mod new file mode 100644 index 000000000..e016bda28 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/mvcp.mod @@ -0,0 +1,43 @@ +/* MVCP, Minimum Vertex Cover Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Minimum Vertex Cover Problem in a network G = (V, E), where V + is a set of nodes, E is a set of arcs, is to find a subset V' within + V such that each edge (i,j) in E has at least one its endpoint in V' + and which minimizes the sum of node weights w(i) over V'. + + Reference: + Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: + A guide to the theory of NP-completeness [Graph Theory, Covering and + Partitioning, Minimum Vertex Cover, GT1]. */ + +set E, dimen 2; +/* set of edges */ + +set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); +/* set of nodes */ + +param w{i in V}, >= 0, default 1; +/* w[i] is weight of vertex i */ + +var x{i in V}, binary; +/* x[i] = 1 means that node i is included into V' */ + +s.t. cov{(i,j) in E}: x[i] + x[j] >= 1; +/* each edge (i,j) must have node i or j (or both) in V' */ + +minimize z: sum{i in V} w[i] * x[i]; +/* we need to minimize the sum of node weights over V' */ + +data; + +/* These data correspond to an example from [Papadimitriou]. */ + +/* Optimal solution is 6 (greedy heuristic gives 13) */ + +set E := a1 b1, b1 c1, a1 b2, b2 c2, a2 b3, b3 c3, a2 b4, b4 c4, a3 b5, + b5 c5, a3 b6, b6 c6, a4 b1, a4 b2, a4 b3, a5 b4, a5 b5, a5 b6, + a6 b1, a6 b2, a6 b3, a6 b4, a7 b2, a7 b3, a7 b4, a7 b5, a7 b6; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/netgen.c b/WebAPP/SOLVERs/GLPK/glpk/examples/netgen.c new file mode 100644 index 000000000..eebb2c867 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/netgen.c @@ -0,0 +1,141 @@ +/* netgen.c */ + +/* This main program generates 50 original NETGEN instances of the + minimum cost flow problem and writes them in DIMACS format to the + current directory. */ + +#include +#include +#include +#include + +static int parm[50][15] = +{ {13502460, 101, + 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4281922, 102, + 5000, 2500, 2500, 25000, 1, 100, 2500000, 0, 0, 0, 100, 1, 1000, + },{44820113, 103, + 5000, 2500, 2500, 25000, 1, 100, 6250000, 0, 0, 0, 100, 1, 1000, + },{13450451, 104, + 5000, 2500, 2500, 25000, -100, -1, 250000, 0, 0, 0, 100, 1, 1000, + },{14719436, 105, + 5000, 2500, 2500, 25000, 101, 200, 250000, 0, 0, 0, 100, 1, 1000, + },{17365786, 106, + 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 100, 1, 1000, + },{19540113, 107, + 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 100, 1, 1000, + },{19560313, 108, + 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 100, 1, 1000, + },{2403509, 109, + 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 100, 1, 1000, + },{92480414, 110, + 5000, 2500, 2500, 12500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4230140, 111, + 5000, 2500, 2500, 37500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{10032490, 112, + 5000, 2500, 2500, 50000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{17307474, 113, + 5000, 2500, 2500, 75000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{4925114, 114, + 5000, 500, 4500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{19842704, 115, + 5000, 1500, 3500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, + },{88392060, 116, + 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 0, 1, 1000, + },{12904407, 117, + 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 0, 1, 1000, + },{11811811, 118, + 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 0, 1, 1000, + },{90023593, 119, + 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 0, 1, 1000, + },{93028922, 120, + 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 0, 1, 1000, + },{72707401, 121, + 5000, 50, 50, 25000, 1, 100, 250000, 50, 50, 0, 100, 1, 1000, + },{93040771, 122, + 5000, 250, 250, 25000, 1, 100, 250000, 250, 250, 0, 100, 1, 1000, + },{70220611, 123, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{52774811, 124, + 5000, 1000, 1000, 25000, 1, 100, 250000, 1000, 1000, 0, 100, 1, + 1000, + },{22492311, 125, + 5000, 1500, 1500, 25000, 1, 100, 250000, 1500, 1500, 0, 100, 1, + 1000, + },{35269337, 126, + 5000, 500, 500, 12500, 1, 100, 125000, 500, 500, 0, 100, 1, 1000, + },{30140502, 127, + 5000, 500, 500, 37500, 1, 100, 375000, 500, 500, 0, 100, 1, 1000, + },{49205455, 128, + 5000, 500, 500, 50000, 1, 100, 500000, 500, 500, 0, 100, 1, 1000, + },{42958341, 129, + 5000, 500, 500, 75000, 1, 100, 750000, 500, 500, 0, 100, 1, 1000, + },{25440925, 130, + 5000, 500, 500, 12500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{75294924, 131, + 5000, 500, 500, 37500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{4463965, 132, + 5000, 500, 500, 50000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{13390427, 133, + 5000, 500, 500, 75000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{95250971, 134, + 1000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{54830522, 135, + 2500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{520593, 136, + 7500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{52900925, 137, + 10000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, + },{22603395, 138, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 50, + },{55253099, 139, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 250, + },{75357001, 140, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 500, + },{10072459, 141, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 2500, + },{55728492, 142, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 5000, + },{593043, 143, + 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 0, 1, 1000, + },{94236572, 144, + 5000, 500, 500, 25000, 1, 10, 250000, 500, 500, 0, 100, 1, 1000, + },{94882955, 145, + 5000, 500, 500, 25000, 1, 1000, 250000, 500, 500, 0, 100, 1, 1000, + },{48489922, 146, + 5000, 500, 500, 25000, 1, 10000, 250000, 500, 500, 0, 100, 1, + 1000, + },{75578374, 147, + 5000, 500, 500, 25000, -100, -1, 250000, 500, 500, 0, 100, 1, + 1000, + },{44821152, 148, + 5000, 500, 500, 25000, -50, 49, 250000, 500, 500, 0, 100, 1, 1000, + },{45224103, 149, + 5000, 500, 500, 25000, 101, 200, 250000, 500, 500, 0, 100, 1, + 1000, + },{63491741, 150, + 5000, 500, 500, 25000, 1001, 1100, 250000, 500, 500, 0, 100, 1, + 1000, + } +}; + +typedef struct { double rhs; } v_data; +typedef struct { double cap, cost; } a_data; + +int main(void) +{ glp_graph *G; + int k; + char fname[100+1]; + G = glp_create_graph(sizeof(v_data), sizeof(a_data)); + for (k = 1; k <= 50; k++) + { sprintf(fname, "netgn%03d.min", parm[k-1][1]); + glp_netgen(G, offsetof(v_data, rhs), offsetof(a_data, cap), + offsetof(a_data, cost), &parm[k-1][-1]); + glp_write_mincost(G, offsetof(v_data, rhs), -1, + offsetof(a_data, cap), offsetof(a_data, cost), fname); + } + glp_delete_graph(G); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/nppsamp.c b/WebAPP/SOLVERs/GLPK/glpk/examples/nppsamp.c new file mode 100644 index 000000000..65f0e693e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/nppsamp.c @@ -0,0 +1,48 @@ +/* nppsamp.c */ + +#include +#include +#include + +int main(void) +{ glp_prep *prep; + glp_prob *P, *Q; + int ret; + prep = glp_npp_alloc_wksp(); + P = glp_create_prob(); + ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "murtagh.mps"); + if (ret != 0) + { printf("Error on reading problem data\n"); + goto skip; + } + glp_set_obj_dir(P, GLP_MAX); + glp_npp_load_prob(prep, P, GLP_SOL, GLP_ON); + ret = glp_npp_preprocess1(prep, 0); + switch (ret) + { case 0: + break; + case GLP_ENOPFS: + printf("LP has no primal feasible solution\n"); + goto skip; + case GLP_ENODFS: + printf("LP has no dual feasible solution\n"); + goto skip; + default: + glp_assert(ret != ret); + } + Q = glp_create_prob(); + glp_npp_build_prob(prep, Q); + ret = glp_simplex(Q, NULL); + if (ret == 0 && glp_get_status(Q) == GLP_OPT) + { glp_npp_postprocess(prep, Q); + glp_npp_obtain_sol(prep, P); + } + else + printf("Unable to recover non-optimal solution\n"); + glp_delete_prob(Q); +skip: glp_npp_free_wksp(prep); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/numbrix.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/numbrix.mod new file mode 100644 index 000000000..b36fbfd04 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/numbrix.mod @@ -0,0 +1,84 @@ +/* Numbrix, Number Placement Puzzle */ + +/* Written in GNU MathProg by Robert Wood */ + +/* Numbrix is a logic-based number-placement puzzle.[1] + * The objective is to fill the grid so that each cell contains + * digits in sequential order taking a horizontal or vertical + * path; diagonal paths are not allowed. The puzzle setter + * provides a grid often with the outer most cells completed. + * + * Completed Numbrix puzzles are usually a square of numbers + * in order from 1 to 64 (8x8 grid) or from 1 to 81 (9x9 grid), + * following a continuous path in sequence. + * + * The modern puzzle was invented by Marilyn vos Savant in 2008 + * and published by Parade Magazine under the name "Numbrix", + * near her weekly Ask Marilyn article. + * + * http://en.wikipedia.org/wiki/Numbrix */ + +set I := {1..9}; +set J := {1..9}; +set VALS := {1..81}; + +param givens{I, J}, integer, >= 0, <= 81, default 0; +/* the "givens" */ + +param neighbors{i in I,j in J, i2 in I, j2 in J} , binary := +(if abs(i - i2) + abs(j -j2) == 1 then + 1 + else + 0 +); +/* defines which spots are the boards are neighbors */ + +var x{i in I, j in J, k in VALS}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in I, j in J, k in VALS: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in I, j in J}: sum{k in VALS} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. singleNum {k in VALS}: sum{i in I, j in J} x[i,j,k] = 1; +/* a value can only occur once */ + +s.t. neighborContraint {i in I, j in J, k in 1..80}: + x[i,j,k] <= sum{i2 in I, j2 in J} x[i2,j2,k+1] * neighbors[i,j,i2,j2]; +/* each cell must have a neighbor with the next higher value */ + + +/* there is no need for an objective function here */ + + +solve; + +for {i in I} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +----------+----------+----------+\n"; + for {j in J} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %2d", sum{k in VALS} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +----------+----------+----------+\n"; +} + +data; + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 . . . . . . . . . + 2 . 11 12 15 18 21 62 61 . + 3 . 6 . . . . . 60 . + 4 . 33 . . . . . 57 . + 5 . 32 . . . . . 56 . + 6 . 37 . . . . . 73 . + 7 . 38 . . . . . 72 . + 8 . 43 44 47 48 51 76 77 . + 9 . . . . . . . . . ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/README b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/README new file mode 100644 index 000000000..e52ee2c09 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/README @@ -0,0 +1,11 @@ +The program module in this subdirectory contains an implementation of +the old GLPK API as it was defined in GLPK 4.48. + +To compile an existing project using the old GLPK API you need to add +to the project two files lpx.h and lpx.c. + +Please note that you may mix calls to old and new GLPK API routines in +the same project (except calls to glp_create_prob and glp_delete_prob). + +The file lpxsamp.c is an example that illustrates using the old GLPK +API routines. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.c b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.c new file mode 100644 index 000000000..c508306b0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.c @@ -0,0 +1,1505 @@ +/* lpx.c (old GLPK API) */ + +/* Written by Andrew Makhorin , August 2013. */ + +/* This file contains routines that implement the old GLPK API as it +* was defined in GLPK 4.48. +* +* To compile an existing project using these routines you need to add +* to the project this file and the header lpx.h. +* +* Please note that you may mix calls to old and new GLPK API routines +* (except calls to glp_create_prob and glp_delete_prob). */ + +#include +#include +#include "lpx.h" + +#define xassert glp_assert +#define xerror glp_error + +struct CPS +{ /* control parameters */ + LPX *lp; + /* pointer to corresponding problem object */ + int msg_lev; + /* level of messages output by the solver: + 0 - no output + 1 - error messages only + 2 - normal output + 3 - full output (includes informational messages) */ + int scale; + /* scaling option: + 0 - no scaling + 1 - equilibration scaling + 2 - geometric mean scaling + 3 - geometric mean scaling, then equilibration scaling */ + int dual; + /* dual simplex option: + 0 - use primal simplex + 1 - use dual simplex */ + int price; + /* pricing option (for both primal and dual simplex): + 0 - textbook pricing + 1 - steepest edge pricing */ + double relax; + /* relaxation parameter used in the ratio test; if it is zero, + the textbook ratio test is used; if it is non-zero (should be + positive), Harris' two-pass ratio test is used; in the latter + case on the first pass basic variables (in the case of primal + simplex) or reduced costs of non-basic variables (in the case + of dual simplex) are allowed to slightly violate their bounds, + but not more than (relax * tol_bnd) or (relax * tol_dj) (thus, + relax is a percentage of tol_bnd or tol_dj) */ + double tol_bnd; + /* relative tolerance used to check if the current basic solution + is primal feasible */ + double tol_dj; + /* absolute tolerance used to check if the current basic solution + is dual feasible */ + double tol_piv; + /* relative tolerance used to choose eligible pivotal elements of + the simplex table in the ratio test */ + int round; + /* solution rounding option: + 0 - report all computed values and reduced costs "as is" + 1 - if possible (allowed by the tolerances), replace computed + values and reduced costs which are close to zero by exact + zeros */ + double obj_ll; + /* lower limit of the objective function; if on the phase II the + objective function reaches this limit and continues decreasing, + the solver stops the search */ + double obj_ul; + /* upper limit of the objective function; if on the phase II the + objective function reaches this limit and continues increasing, + the solver stops the search */ + int it_lim; + /* simplex iterations limit; if this value is positive, it is + decreased by one each time when one simplex iteration has been + performed, and reaching zero value signals the solver to stop + the search; negative value means no iterations limit */ + double tm_lim; + /* searching time limit, in seconds; if this value is positive, + it is decreased each time when one simplex iteration has been + performed by the amount of time spent for the iteration, and + reaching zero value signals the solver to stop the search; + negative value means no time limit */ + int out_frq; + /* output frequency, in iterations; this parameter specifies how + frequently the solver sends information about the solution to + the standard output */ + double out_dly; + /* output delay, in seconds; this parameter specifies how long + the solver should delay sending information about the solution + to the standard output; zero value means no delay */ + int branch; /* MIP */ + /* branching heuristic: + 0 - branch on first variable + 1 - branch on last variable + 2 - branch using heuristic by Driebeck and Tomlin + 3 - branch on most fractional variable */ + int btrack; /* MIP */ + /* backtracking heuristic: + 0 - select most recent node (depth first search) + 1 - select earliest node (breadth first search) + 2 - select node using the best projection heuristic + 3 - select node with best local bound */ + double tol_int; /* MIP */ + /* absolute tolerance used to check if the current basic solution + is integer feasible */ + double tol_obj; /* MIP */ + /* relative tolerance used to check if the value of the objective + function is not better than in the best known integer feasible + solution */ + int mps_info; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps outputs several + comment cards that contains some information about the problem; + otherwise the routine outputs no comment cards */ + int mps_obj; /* lpx_write_mps */ + /* this parameter tells the routine lpx_write_mps how to output + the objective function row: + 0 - never output objective function row + 1 - always output objective function row + 2 - output objective function row if and only if the problem + has no free rows */ + int mps_orig; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps uses original + row and column symbolic names; otherwise the routine generates + plain names using ordinal numbers of rows and columns */ + int mps_wide; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps uses all data + fields; otherwise the routine keeps fields 5 and 6 empty */ + int mps_free; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps omits column + and vector names everytime if possible (free style); otherwise + the routine never omits these names (pedantic style) */ + int mps_skip; /* lpx_write_mps */ + /* if this flag is set, the routine lpx_write_mps skips empty + columns (i.e. which has no constraint coefficients); otherwise + the routine outputs all columns */ + int lpt_orig; /* lpx_write_lpt */ + /* if this flag is set, the routine lpx_write_lpt uses original + row and column symbolic names; otherwise the routine generates + plain names using ordinal numbers of rows and columns */ + int presol; /* lpx_simplex */ + /* LP presolver option: + 0 - do not use LP presolver + 1 - use LP presolver */ + int binarize; /* lpx_intopt */ + /* if this flag is set, the routine lpx_intopt replaces integer + columns by binary ones */ + int use_cuts; /* lpx_intopt */ + /* if this flag is set, the routine lpx_intopt tries generating + cutting planes: + LPX_C_COVER - mixed cover cuts + LPX_C_CLIQUE - clique cuts + LPX_C_GOMORY - Gomory's mixed integer cuts + LPX_C_ALL - all cuts */ + double mip_gap; /* MIP */ + /* relative MIP gap tolerance */ + struct CPS *link; + /* pointer to CPS for another problem object */ +}; + +static struct CPS *cps_ptr = NULL; +/* initial pointer to CPS linked list */ + +static struct CPS *find_cps(LPX *lp) +{ /* find CPS for specified problem object */ + struct CPS *cps; + for (cps = cps_ptr; cps != NULL; cps = cps->link) + if (cps->lp == lp) break; + /* if cps is NULL (not found), the problem object was created + with glp_create_prob rather than with lpx_create_prob */ + xassert(cps != NULL); + return cps; +} + +static void reset_cps(struct CPS *cps) +{ /* reset control parameters to default values */ + cps->msg_lev = 3; + cps->scale = 1; + cps->dual = 0; + cps->price = 1; + cps->relax = 0.07; + cps->tol_bnd = 1e-7; + cps->tol_dj = 1e-7; + cps->tol_piv = 1e-9; + cps->round = 0; + cps->obj_ll = -DBL_MAX; + cps->obj_ul = +DBL_MAX; + cps->it_lim = -1; + cps->tm_lim = -1.0; + cps->out_frq = 200; + cps->out_dly = 0.0; + cps->branch = 2; + cps->btrack = 3; + cps->tol_int = 1e-5; + cps->tol_obj = 1e-7; + cps->mps_info = 1; + cps->mps_obj = 2; + cps->mps_orig = 0; + cps->mps_wide = 1; + cps->mps_free = 0; + cps->mps_skip = 0; + cps->lpt_orig = 0; + cps->presol = 0; + cps->binarize = 0; + cps->use_cuts = 0; + cps->mip_gap = 0.0; + return; +} + +LPX *lpx_create_prob(void) +{ /* create problem object */ + LPX *lp; + struct CPS *cps; + lp = glp_create_prob(); + cps = glp_alloc(1, sizeof(struct CPS)); + cps->lp = lp; + reset_cps(cps); + cps->link = cps_ptr; + cps_ptr = cps; + return lp; +} + +void lpx_set_prob_name(LPX *lp, const char *name) +{ /* assign (change) problem name */ + glp_set_prob_name(lp, name); + return; +} + +void lpx_set_obj_name(LPX *lp, const char *name) +{ /* assign (change) objective function name */ + glp_set_obj_name(lp, name); + return; +} + +void lpx_set_obj_dir(LPX *lp, int dir) +{ /* set (change) optimization direction flag */ + glp_set_obj_dir(lp, dir - LPX_MIN + GLP_MIN); + return; +} + +int lpx_add_rows(LPX *lp, int nrs) +{ /* add new rows to problem object */ + return glp_add_rows(lp, nrs); +} + +int lpx_add_cols(LPX *lp, int ncs) +{ /* add new columns to problem object */ + return glp_add_cols(lp, ncs); +} + +void lpx_set_row_name(LPX *lp, int i, const char *name) +{ /* assign (change) row name */ + glp_set_row_name(lp, i, name); + return; +} + +void lpx_set_col_name(LPX *lp, int j, const char *name) +{ /* assign (change) column name */ + glp_set_col_name(lp, j, name); + return; +} + +void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub) +{ /* set (change) row bounds */ + glp_set_row_bnds(lp, i, type - LPX_FR + GLP_FR, lb, ub); + return; +} + +void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub) +{ /* set (change) column bounds */ + glp_set_col_bnds(lp, j, type - LPX_FR + GLP_FR, lb, ub); + return; +} + +void lpx_set_obj_coef(glp_prob *lp, int j, double coef) +{ /* set (change) obj. coefficient or constant term */ + glp_set_obj_coef(lp, j, coef); + return; +} + +void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], + const double val[]) +{ /* set (replace) row of the constraint matrix */ + glp_set_mat_row(lp, i, len, ind, val); + return; +} + +void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], + const double val[]) +{ /* set (replace) column of the constraint matrix */ + glp_set_mat_col(lp, j, len, ind, val); + return; +} + +void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], + const double ar[]) +{ /* load (replace) the whole constraint matrix */ + glp_load_matrix(lp, ne, ia, ja, ar); + return; +} + +void lpx_del_rows(LPX *lp, int nrs, const int num[]) +{ /* delete specified rows from problem object */ + glp_del_rows(lp, nrs, num); + return; +} + +void lpx_del_cols(LPX *lp, int ncs, const int num[]) +{ /* delete specified columns from problem object */ + glp_del_cols(lp, ncs, num); + return; +} + +void lpx_delete_prob(LPX *lp) +{ /* delete problem object */ + struct CPS *cps = find_cps(lp); + if (cps_ptr == cps) + cps_ptr = cps->link; + else + { struct CPS *prev; + for (prev = cps_ptr; prev != NULL; prev = prev->link) + if (prev->link == cps) break; + xassert(prev != NULL); + prev->link = cps->link; + } + glp_free(cps); + glp_delete_prob(lp); + return; +} + +const char *lpx_get_prob_name(LPX *lp) +{ /* retrieve problem name */ + return glp_get_prob_name(lp); +} + +const char *lpx_get_obj_name(LPX *lp) +{ /* retrieve objective function name */ + return glp_get_obj_name(lp); +} + +int lpx_get_obj_dir(LPX *lp) +{ /* retrieve optimization direction flag */ + return glp_get_obj_dir(lp) - GLP_MIN + LPX_MIN; +} + +int lpx_get_num_rows(LPX *lp) +{ /* retrieve number of rows */ + return glp_get_num_rows(lp); +} + +int lpx_get_num_cols(LPX *lp) +{ /* retrieve number of columns */ + return glp_get_num_cols(lp); +} + +const char *lpx_get_row_name(LPX *lp, int i) +{ /* retrieve row name */ + return glp_get_row_name(lp, i); +} + +const char *lpx_get_col_name(LPX *lp, int j) +{ /* retrieve column name */ + return glp_get_col_name(lp, j); +} + +int lpx_get_row_type(LPX *lp, int i) +{ /* retrieve row type */ + return glp_get_row_type(lp, i) - GLP_FR + LPX_FR; +} + +double lpx_get_row_lb(glp_prob *lp, int i) +{ /* retrieve row lower bound */ + double lb; + lb = glp_get_row_lb(lp, i); + if (lb == -DBL_MAX) lb = 0.0; + return lb; +} + +double lpx_get_row_ub(glp_prob *lp, int i) +{ /* retrieve row upper bound */ + double ub; + ub = glp_get_row_ub(lp, i); + if (ub == +DBL_MAX) ub = 0.0; + return ub; +} + +void lpx_get_row_bnds(glp_prob *lp, int i, int *typx, double *lb, + double *ub) +{ /* retrieve row bounds */ + if (typx != NULL) *typx = lpx_get_row_type(lp, i); + if (lb != NULL) *lb = lpx_get_row_lb(lp, i); + if (ub != NULL) *ub = lpx_get_row_ub(lp, i); + return; +} + +int lpx_get_col_type(LPX *lp, int j) +{ /* retrieve column type */ + return glp_get_col_type(lp, j) - GLP_FR + LPX_FR; +} + +double lpx_get_col_lb(glp_prob *lp, int j) +{ /* retrieve column lower bound */ + double lb; + lb = glp_get_col_lb(lp, j); + if (lb == -DBL_MAX) lb = 0.0; + return lb; +} + +double lpx_get_col_ub(glp_prob *lp, int j) +{ /* retrieve column upper bound */ + double ub; + ub = glp_get_col_ub(lp, j); + if (ub == +DBL_MAX) ub = 0.0; + return ub; +} + +void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb, + double *ub) +{ /* retrieve column bounds */ + if (typx != NULL) *typx = lpx_get_col_type(lp, j); + if (lb != NULL) *lb = lpx_get_col_lb(lp, j); + if (ub != NULL) *ub = lpx_get_col_ub(lp, j); + return; +} + +double lpx_get_obj_coef(LPX *lp, int j) +{ /* retrieve obj. coefficient or constant term */ + return glp_get_obj_coef(lp, j); +} + +int lpx_get_num_nz(LPX *lp) +{ /* retrieve number of constraint coefficients */ + return glp_get_num_nz(lp); +} + +int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]) +{ /* retrieve row of the constraint matrix */ + return glp_get_mat_row(lp, i, ind, val); +} + +int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]) +{ /* retrieve column of the constraint matrix */ + return glp_get_mat_col(lp, j, ind, val); +} + +void lpx_create_index(LPX *lp) +{ /* create the name index */ + glp_create_index(lp); + return; +} + +int lpx_find_row(LPX *lp, const char *name) +{ /* find row by its name */ + return glp_find_row(lp, name); +} + +int lpx_find_col(LPX *lp, const char *name) +{ /* find column by its name */ + return glp_find_col(lp, name); +} + +void lpx_delete_index(LPX *lp) +{ /* delete the name index */ + glp_delete_index(lp); + return; +} + +void lpx_scale_prob(LPX *lp) +{ /* scale problem data */ + switch (lpx_get_int_parm(lp, LPX_K_SCALE)) + { case 0: + /* no scaling */ + glp_unscale_prob(lp); + break; + case 1: + /* equilibration scaling */ + glp_scale_prob(lp, GLP_SF_EQ); + break; + case 2: + /* geometric mean scaling */ + glp_scale_prob(lp, GLP_SF_GM); + break; + case 3: + /* geometric mean scaling, then equilibration scaling */ + glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ); + break; + default: + xassert(lp != lp); + } + return; +} + +void lpx_unscale_prob(LPX *lp) +{ /* unscale problem data */ + glp_unscale_prob(lp); + return; +} + +void lpx_set_row_stat(LPX *lp, int i, int stat) +{ /* set (change) row status */ + glp_set_row_stat(lp, i, stat - LPX_BS + GLP_BS); + return; +} + +void lpx_set_col_stat(LPX *lp, int j, int stat) +{ /* set (change) column status */ + glp_set_col_stat(lp, j, stat - LPX_BS + GLP_BS); + return; +} + +void lpx_std_basis(LPX *lp) +{ /* construct standard initial LP basis */ + glp_std_basis(lp); + return; +} + +void lpx_adv_basis(LPX *lp) +{ /* construct advanced initial LP basis */ + glp_adv_basis(lp, 0); + return; +} + +void lpx_cpx_basis(LPX *lp) +{ /* construct Bixby's initial LP basis */ + glp_cpx_basis(lp); + return; +} + +static void fill_smcp(LPX *lp, glp_smcp *parm) +{ glp_init_smcp(parm); + switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) + { case 0: parm->msg_lev = GLP_MSG_OFF; break; + case 1: parm->msg_lev = GLP_MSG_ERR; break; + case 2: parm->msg_lev = GLP_MSG_ON; break; + case 3: parm->msg_lev = GLP_MSG_ALL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_DUAL)) + { case 0: parm->meth = GLP_PRIMAL; break; + case 1: parm->meth = GLP_DUAL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_PRICE)) + { case 0: parm->pricing = GLP_PT_STD; break; + case 1: parm->pricing = GLP_PT_PSE; break; + default: xassert(lp != lp); + } + if (lpx_get_real_parm(lp, LPX_K_RELAX) == 0.0) + parm->r_test = GLP_RT_STD; + else + parm->r_test = GLP_RT_HAR; + parm->tol_bnd = lpx_get_real_parm(lp, LPX_K_TOLBND); + parm->tol_dj = lpx_get_real_parm(lp, LPX_K_TOLDJ); + parm->tol_piv = lpx_get_real_parm(lp, LPX_K_TOLPIV); + parm->obj_ll = lpx_get_real_parm(lp, LPX_K_OBJLL); + parm->obj_ul = lpx_get_real_parm(lp, LPX_K_OBJUL); + if (lpx_get_int_parm(lp, LPX_K_ITLIM) < 0) + parm->it_lim = INT_MAX; + else + parm->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); + if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0) + parm->tm_lim = INT_MAX; + else + parm->tm_lim = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); + parm->out_frq = lpx_get_int_parm(lp, LPX_K_OUTFRQ); + parm->out_dly = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_OUTDLY)); + switch (lpx_get_int_parm(lp, LPX_K_PRESOL)) + { case 0: parm->presolve = GLP_OFF; break; + case 1: parm->presolve = GLP_ON; break; + default: xassert(lp != lp); + } + return; +} + +int lpx_simplex(LPX *lp) +{ /* easy-to-use driver to the simplex method */ + glp_smcp parm; + int ret; + fill_smcp(lp, &parm); + ret = glp_simplex(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EBADB: + case GLP_ESING: + case GLP_ECOND: + case GLP_EBOUND: ret = LPX_E_FAULT; break; + case GLP_EFAIL: ret = LPX_E_SING; break; + case GLP_EOBJLL: ret = LPX_E_OBJLL; break; + case GLP_EOBJUL: ret = LPX_E_OBJUL; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + case GLP_ENOPFS: ret = LPX_E_NOPFS; break; + case GLP_ENODFS: ret = LPX_E_NODFS; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_exact(LPX *lp) +{ /* easy-to-use driver to the exact simplex method */ + glp_smcp parm; + int ret; + fill_smcp(lp, &parm); + ret = glp_exact(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EBADB: + case GLP_ESING: + case GLP_EBOUND: + case GLP_EFAIL: ret = LPX_E_FAULT; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_get_status(glp_prob *lp) +{ /* retrieve generic status of basic solution */ + int status; + switch (glp_get_status(lp)) + { case GLP_OPT: status = LPX_OPT; break; + case GLP_FEAS: status = LPX_FEAS; break; + case GLP_INFEAS: status = LPX_INFEAS; break; + case GLP_NOFEAS: status = LPX_NOFEAS; break; + case GLP_UNBND: status = LPX_UNBND; break; + case GLP_UNDEF: status = LPX_UNDEF; break; + default: xassert(lp != lp); + } + return status; +} + +int lpx_get_prim_stat(glp_prob *lp) +{ /* retrieve status of primal basic solution */ + return glp_get_prim_stat(lp) - GLP_UNDEF + LPX_P_UNDEF; +} + +int lpx_get_dual_stat(glp_prob *lp) +{ /* retrieve status of dual basic solution */ + return glp_get_dual_stat(lp) - GLP_UNDEF + LPX_D_UNDEF; +} + +double lpx_get_obj_val(LPX *lp) +{ /* retrieve objective value (basic solution) */ + return glp_get_obj_val(lp); +} + +int lpx_get_row_stat(LPX *lp, int i) +{ /* retrieve row status (basic solution) */ + return glp_get_row_stat(lp, i) - GLP_BS + LPX_BS; +} + +double lpx_get_row_prim(LPX *lp, int i) +{ /* retrieve row primal value (basic solution) */ + return glp_get_row_prim(lp, i); +} + +double lpx_get_row_dual(LPX *lp, int i) +{ /* retrieve row dual value (basic solution) */ + return glp_get_row_dual(lp, i); +} + +void lpx_get_row_info(glp_prob *lp, int i, int *tagx, double *vx, + double *dx) +{ /* obtain row solution information */ + if (tagx != NULL) *tagx = lpx_get_row_stat(lp, i); + if (vx != NULL) *vx = lpx_get_row_prim(lp, i); + if (dx != NULL) *dx = lpx_get_row_dual(lp, i); + return; +} + +int lpx_get_col_stat(LPX *lp, int j) +{ /* retrieve column status (basic solution) */ + return glp_get_col_stat(lp, j) - GLP_BS + LPX_BS; +} + +double lpx_get_col_prim(LPX *lp, int j) +{ /* retrieve column primal value (basic solution) */ + return glp_get_col_prim(lp, j); +} + +double lpx_get_col_dual(glp_prob *lp, int j) +{ /* retrieve column dual value (basic solution) */ + return glp_get_col_dual(lp, j); +} + +void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx, + double *dx) +{ /* obtain column solution information */ + if (tagx != NULL) *tagx = lpx_get_col_stat(lp, j); + if (vx != NULL) *vx = lpx_get_col_prim(lp, j); + if (dx != NULL) *dx = lpx_get_col_dual(lp, j); + return; +} + +int lpx_get_ray_info(LPX *lp) +{ /* determine what causes primal unboundness */ + return glp_get_unbnd_ray(lp); +} + +void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt) +{ /* check Karush-Kuhn-Tucker conditions */ + int m = glp_get_num_rows(lp); + int ae_ind, re_ind; + double ae_max, re_max; + xassert(scaled == scaled); + glp_check_kkt(lp, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pe_ae_max = ae_max; + kkt->pe_ae_row = ae_ind; + kkt->pe_re_max = re_max; + kkt->pe_re_row = re_ind; + if (re_max <= 1e-9) + kkt->pe_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pe_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pe_quality = 'L'; + else + kkt->pe_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pb_ae_max = ae_max; + kkt->pb_ae_ind = ae_ind; + kkt->pb_re_max = re_max; + kkt->pb_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->pb_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pb_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pb_quality = 'L'; + else + kkt->pb_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->de_ae_max = ae_max; + if (ae_ind == 0) + kkt->de_ae_col = 0; + else + kkt->de_ae_col = ae_ind - m; + kkt->de_re_max = re_max; + if (re_ind == 0) + kkt->de_re_col = 0; + else + kkt->de_re_col = ae_ind - m; + if (re_max <= 1e-9) + kkt->de_quality = 'H'; + else if (re_max <= 1e-6) + kkt->de_quality = 'M'; + else if (re_max <= 1e-3) + kkt->de_quality = 'L'; + else + kkt->de_quality = '?'; + glp_check_kkt(lp, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->db_ae_max = ae_max; + kkt->db_ae_ind = ae_ind; + kkt->db_re_max = re_max; + kkt->db_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->db_quality = 'H'; + else if (re_max <= 1e-6) + kkt->db_quality = 'M'; + else if (re_max <= 1e-3) + kkt->db_quality = 'L'; + else + kkt->db_quality = '?'; + kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0; + kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0; + kkt->cs_quality = 'H'; + return; +} + +int lpx_warm_up(LPX *lp) +{ /* "warm up" LP basis */ + int ret; + ret = glp_warm_up(lp); + if (ret == 0) + ret = LPX_E_OK; + else if (ret == GLP_EBADB) + ret = LPX_E_BADB; + else if (ret == GLP_ESING) + ret = LPX_E_SING; + else if (ret == GLP_ECOND) + ret = LPX_E_SING; + else + xassert(ret != ret); + return ret; +} + +int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]) +{ /* compute row of the simplex tableau */ + return glp_eval_tab_row(lp, k, ind, val); +} + +int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]) +{ /* compute column of the simplex tableau */ + return glp_eval_tab_col(lp, k, ind, val); +} + +int lpx_transform_row(LPX *lp, int len, int ind[], double val[]) +{ /* transform explicitly specified row */ + return glp_transform_row(lp, len, ind, val); +} + +int lpx_transform_col(LPX *lp, int len, int ind[], double val[]) +{ /* transform explicitly specified column */ + return glp_transform_col(lp, len, ind, val); +} + +int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform primal ratio test */ + int piv; + piv = glp_prim_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform dual ratio test */ + int piv; + piv = glp_dual_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +int lpx_interior(LPX *lp) +{ /* easy-to-use driver to the interior-point method */ + int ret; + ret = glp_interior(lp, NULL); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_EFAIL: ret = LPX_E_FAULT; break; + case GLP_ENOFEAS: ret = LPX_E_NOFEAS; break; + case GLP_ENOCVG: ret = LPX_E_NOCONV; break; + case GLP_EITLIM: ret = LPX_E_ITLIM; break; + case GLP_EINSTAB: ret = LPX_E_INSTAB; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_ipt_status(glp_prob *lp) +{ /* retrieve status of interior-point solution */ + int status; + switch (glp_ipt_status(lp)) + { case GLP_UNDEF: status = LPX_T_UNDEF; break; + case GLP_OPT: status = LPX_T_OPT; break; + default: xassert(lp != lp); + } + return status; +} + +double lpx_ipt_obj_val(LPX *lp) +{ /* retrieve objective value (interior point) */ + return glp_ipt_obj_val(lp); +} + +double lpx_ipt_row_prim(LPX *lp, int i) +{ /* retrieve row primal value (interior point) */ + return glp_ipt_row_prim(lp, i); +} + +double lpx_ipt_row_dual(LPX *lp, int i) +{ /* retrieve row dual value (interior point) */ + return glp_ipt_row_dual(lp, i); +} + +double lpx_ipt_col_prim(LPX *lp, int j) +{ /* retrieve column primal value (interior point) */ + return glp_ipt_col_prim(lp, j); +} + +double lpx_ipt_col_dual(LPX *lp, int j) +{ /* retrieve column dual value (interior point) */ + return glp_ipt_col_dual(lp, j); +} + +void lpx_set_class(LPX *lp, int klass) +{ /* set problem class */ + xassert(lp == lp); + if (!(klass == LPX_LP || klass == LPX_MIP)) + xerror("lpx_set_class: invalid problem class\n"); + return; +} + +int lpx_get_class(LPX *lp) +{ /* determine problem klass */ + return glp_get_num_int(lp) == 0 ? LPX_LP : LPX_MIP; +} + +void lpx_set_col_kind(LPX *lp, int j, int kind) +{ /* set (change) column kind */ + glp_set_col_kind(lp, j, kind - LPX_CV + GLP_CV); + return; +} + +int lpx_get_col_kind(LPX *lp, int j) +{ /* retrieve column kind */ + return glp_get_col_kind(lp, j) == GLP_CV ? LPX_CV : LPX_IV; +} + +int lpx_get_num_int(LPX *lp) +{ /* retrieve number of integer columns */ + return glp_get_num_int(lp); +} + +int lpx_get_num_bin(LPX *lp) +{ /* retrieve number of binary columns */ + return glp_get_num_bin(lp); +} + +static int solve_mip(LPX *lp, int presolve) +{ glp_iocp parm; + int ret; + glp_init_iocp(&parm); + switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) + { case 0: parm.msg_lev = GLP_MSG_OFF; break; + case 1: parm.msg_lev = GLP_MSG_ERR; break; + case 2: parm.msg_lev = GLP_MSG_ON; break; + case 3: parm.msg_lev = GLP_MSG_ALL; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_BRANCH)) + { case 0: parm.br_tech = GLP_BR_FFV; break; + case 1: parm.br_tech = GLP_BR_LFV; break; + case 2: parm.br_tech = GLP_BR_DTH; break; + case 3: parm.br_tech = GLP_BR_MFV; break; + default: xassert(lp != lp); + } + switch (lpx_get_int_parm(lp, LPX_K_BTRACK)) + { case 0: parm.bt_tech = GLP_BT_DFS; break; + case 1: parm.bt_tech = GLP_BT_BFS; break; + case 2: parm.bt_tech = GLP_BT_BPH; break; + case 3: parm.bt_tech = GLP_BT_BLB; break; + default: xassert(lp != lp); + } + parm.tol_int = lpx_get_real_parm(lp, LPX_K_TOLINT); + parm.tol_obj = lpx_get_real_parm(lp, LPX_K_TOLOBJ); + if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0 || + lpx_get_real_parm(lp, LPX_K_TMLIM) > 1e6) + parm.tm_lim = INT_MAX; + else + parm.tm_lim = + (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); + parm.mip_gap = lpx_get_real_parm(lp, LPX_K_MIPGAP); + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_GOMORY) + parm.gmi_cuts = GLP_ON; + else + parm.gmi_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_MIR) + parm.mir_cuts = GLP_ON; + else + parm.mir_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_COVER) + parm.cov_cuts = GLP_ON; + else + parm.cov_cuts = GLP_OFF; + if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_CLIQUE) + parm.clq_cuts = GLP_ON; + else + parm.clq_cuts = GLP_OFF; + parm.presolve = presolve; + if (lpx_get_int_parm(lp, LPX_K_BINARIZE)) + parm.binarize = GLP_ON; + ret = glp_intopt(lp, &parm); + switch (ret) + { case 0: ret = LPX_E_OK; break; + case GLP_ENOPFS: ret = LPX_E_NOPFS; break; + case GLP_ENODFS: ret = LPX_E_NODFS; break; + case GLP_EBOUND: + case GLP_EROOT: ret = LPX_E_FAULT; break; + case GLP_EFAIL: ret = LPX_E_SING; break; + case GLP_EMIPGAP: ret = LPX_E_MIPGAP; break; + case GLP_ETMLIM: ret = LPX_E_TMLIM; break; + default: xassert(ret != ret); + } + return ret; +} + +int lpx_integer(LPX *lp) +{ /* easy-to-use driver to the branch-and-bound method */ + return solve_mip(lp, GLP_OFF); +} + +int lpx_intopt(LPX *lp) +{ /* easy-to-use driver to the branch-and-bound method */ + return solve_mip(lp, GLP_ON); +} + +int lpx_mip_status(glp_prob *lp) +{ /* retrieve status of MIP solution */ + int status; + switch (glp_mip_status(lp)) + { case GLP_UNDEF: status = LPX_I_UNDEF; break; + case GLP_OPT: status = LPX_I_OPT; break; + case GLP_FEAS: status = LPX_I_FEAS; break; + case GLP_NOFEAS: status = LPX_I_NOFEAS; break; + default: xassert(lp != lp); + } + return status; +} + +double lpx_mip_obj_val(LPX *lp) +{ /* retrieve objective value (MIP solution) */ + return glp_mip_obj_val(lp); +} + +double lpx_mip_row_val(LPX *lp, int i) +{ /* retrieve row value (MIP solution) */ + return glp_mip_row_val(lp, i); +} + +double lpx_mip_col_val(LPX *lp, int j) +{ /* retrieve column value (MIP solution) */ + return glp_mip_col_val(lp, j); +} + +void lpx_check_int(LPX *lp, LPXKKT *kkt) +{ /* check integer feasibility conditions */ + int ae_ind, re_ind; + double ae_max, re_max; + glp_check_kkt(lp, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pe_ae_max = ae_max; + kkt->pe_ae_row = ae_ind; + kkt->pe_re_max = re_max; + kkt->pe_re_row = re_ind; + if (re_max <= 1e-9) + kkt->pe_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pe_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pe_quality = 'L'; + else + kkt->pe_quality = '?'; + glp_check_kkt(lp, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + kkt->pb_ae_max = ae_max; + kkt->pb_ae_ind = ae_ind; + kkt->pb_re_max = re_max; + kkt->pb_re_ind = re_ind; + if (re_max <= 1e-9) + kkt->pb_quality = 'H'; + else if (re_max <= 1e-6) + kkt->pb_quality = 'M'; + else if (re_max <= 1e-3) + kkt->pb_quality = 'L'; + else + kkt->pb_quality = '?'; + return; +} + +void lpx_reset_parms(LPX *lp) +{ /* reset control parameters to default values */ + struct CPS *cps = find_cps(lp); + reset_cps(cps); + return; +} + +void lpx_set_int_parm(LPX *lp, int parm, int val) +{ /* set (change) integer control parameter */ + struct CPS *cps = find_cps(lp); + switch (parm) + { case LPX_K_MSGLEV: + if (!(0 <= val && val <= 3)) + xerror("lpx_set_int_parm: MSGLEV = %d; invalid value\n", + val); + cps->msg_lev = val; + break; + case LPX_K_SCALE: + if (!(0 <= val && val <= 3)) + xerror("lpx_set_int_parm: SCALE = %d; invalid value\n", + val); + cps->scale = val; + break; + case LPX_K_DUAL: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: DUAL = %d; invalid value\n", + val); + cps->dual = val; + break; + case LPX_K_PRICE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: PRICE = %d; invalid value\n", + val); + cps->price = val; + break; + case LPX_K_ROUND: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: ROUND = %d; invalid value\n", + val); + cps->round = val; + break; + case LPX_K_ITLIM: + cps->it_lim = val; + break; + case LPX_K_ITCNT: + glp_set_it_cnt(lp, val); + break; + case LPX_K_OUTFRQ: + if (!(val > 0)) + xerror("lpx_set_int_parm: OUTFRQ = %d; invalid value\n", + val); + cps->out_frq = val; + break; + case LPX_K_BRANCH: + if (!(val == 0 || val == 1 || val == 2 || val == 3)) + xerror("lpx_set_int_parm: BRANCH = %d; invalid value\n", + val); + cps->branch = val; + break; + case LPX_K_BTRACK: + if (!(val == 0 || val == 1 || val == 2 || val == 3)) + xerror("lpx_set_int_parm: BTRACK = %d; invalid value\n", + val); + cps->btrack = val; + break; + case LPX_K_MPSINFO: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSINFO = %d; invalid value\n", + val); + cps->mps_info = val; + break; + case LPX_K_MPSOBJ: + if (!(val == 0 || val == 1 || val == 2)) + xerror("lpx_set_int_parm: MPSOBJ = %d; invalid value\n", + val); + cps->mps_obj = val; + break; + case LPX_K_MPSORIG: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSORIG = %d; invalid value\n", + val); + cps->mps_orig = val; + break; + case LPX_K_MPSWIDE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSWIDE = %d; invalid value\n", + val); + cps->mps_wide = val; + break; + case LPX_K_MPSFREE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSFREE = %d; invalid value\n", + val); + cps->mps_free = val; + break; + case LPX_K_MPSSKIP: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: MPSSKIP = %d; invalid value\n", + val); + cps->mps_skip = val; + break; + case LPX_K_LPTORIG: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: LPTORIG = %d; invalid value\n", + val); + cps->lpt_orig = val; + break; + case LPX_K_PRESOL: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: PRESOL = %d; invalid value\n", + val); + cps->presol = val; + break; + case LPX_K_BINARIZE: + if (!(val == 0 || val == 1)) + xerror("lpx_set_int_parm: BINARIZE = %d; invalid value\n" + , val); + cps->binarize = val; + break; + case LPX_K_USECUTS: + if (val & ~LPX_C_ALL) + xerror("lpx_set_int_parm: USECUTS = 0x%X; invalid value\n", + val); + cps->use_cuts = val; + break; + case LPX_K_BFTYPE: + { glp_bfcp parm; + glp_get_bfcp(lp, &parm); + switch (val) + { case 1: + parm.type = GLP_BF_FT; break; + case 2: + parm.type = GLP_BF_BG; break; + case 3: + parm.type = GLP_BF_GR; break; + default: + xerror("lpx_set_int_parm: BFTYPE = %d; invalid val" + "ue\n", val); + } + glp_set_bfcp(lp, &parm); + } + break; + default: + xerror("lpx_set_int_parm: parm = %d; invalid parameter\n", + parm); + } + return; +} + +int lpx_get_int_parm(LPX *lp, int parm) +{ /* query integer control parameter */ + struct CPS *cps = find_cps(lp); + int val = 0; + switch (parm) + { case LPX_K_MSGLEV: + val = cps->msg_lev; break; + case LPX_K_SCALE: + val = cps->scale; break; + case LPX_K_DUAL: + val = cps->dual; break; + case LPX_K_PRICE: + val = cps->price; break; + case LPX_K_ROUND: + val = cps->round; break; + case LPX_K_ITLIM: + val = cps->it_lim; break; + case LPX_K_ITCNT: + val = glp_get_it_cnt(lp); break; + case LPX_K_OUTFRQ: + val = cps->out_frq; break; + case LPX_K_BRANCH: + val = cps->branch; break; + case LPX_K_BTRACK: + val = cps->btrack; break; + case LPX_K_MPSINFO: + val = cps->mps_info; break; + case LPX_K_MPSOBJ: + val = cps->mps_obj; break; + case LPX_K_MPSORIG: + val = cps->mps_orig; break; + case LPX_K_MPSWIDE: + val = cps->mps_wide; break; + case LPX_K_MPSFREE: + val = cps->mps_free; break; + case LPX_K_MPSSKIP: + val = cps->mps_skip; break; + case LPX_K_LPTORIG: + val = cps->lpt_orig; break; + case LPX_K_PRESOL: + val = cps->presol; break; + case LPX_K_BINARIZE: + val = cps->binarize; break; + case LPX_K_USECUTS: + val = cps->use_cuts; break; + case LPX_K_BFTYPE: + { glp_bfcp parm; + glp_get_bfcp(lp, &parm); + switch (parm.type) + { case GLP_BF_FT: + val = 1; break; + case GLP_BF_BG: + val = 2; break; + case GLP_BF_GR: + val = 3; break; + default: + xassert(lp != lp); + } + } + break; + default: + xerror("lpx_get_int_parm: parm = %d; invalid parameter\n", + parm); + } + return val; +} + +void lpx_set_real_parm(LPX *lp, int parm, double val) +{ /* set (change) real control parameter */ + struct CPS *cps = find_cps(lp); + switch (parm) + { case LPX_K_RELAX: + if (!(0.0 <= val && val <= 1.0)) + xerror("lpx_set_real_parm: RELAX = %g; invalid value\n", + val); + cps->relax = val; + break; + case LPX_K_TOLBND: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLBND = %g; invalid value\n", + val); + cps->tol_bnd = val; + break; + case LPX_K_TOLDJ: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLDJ = %g; invalid value\n", + val); + cps->tol_dj = val; + break; + case LPX_K_TOLPIV: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLPIV = %g; invalid value\n", + val); + cps->tol_piv = val; + break; + case LPX_K_OBJLL: + cps->obj_ll = val; + break; + case LPX_K_OBJUL: + cps->obj_ul = val; + break; + case LPX_K_TMLIM: + cps->tm_lim = val; + break; + case LPX_K_OUTDLY: + cps->out_dly = val; + break; + case LPX_K_TOLINT: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLINT = %g; invalid value\n", + val); + cps->tol_int = val; + break; + case LPX_K_TOLOBJ: + if (!(DBL_EPSILON <= val && val <= 0.001)) + xerror("lpx_set_real_parm: TOLOBJ = %g; invalid value\n", + val); + cps->tol_obj = val; + break; + case LPX_K_MIPGAP: + if (val < 0.0) + xerror("lpx_set_real_parm: MIPGAP = %g; invalid value\n", + val); + cps->mip_gap = val; + break; + default: + xerror("lpx_set_real_parm: parm = %d; invalid parameter\n", + parm); + } + return; +} + +double lpx_get_real_parm(LPX *lp, int parm) +{ /* query real control parameter */ + struct CPS *cps = find_cps(lp); + double val = 0.0; + switch (parm) + { case LPX_K_RELAX: + val = cps->relax; + break; + case LPX_K_TOLBND: + val = cps->tol_bnd; + break; + case LPX_K_TOLDJ: + val = cps->tol_dj; + break; + case LPX_K_TOLPIV: + val = cps->tol_piv; + break; + case LPX_K_OBJLL: + val = cps->obj_ll; + break; + case LPX_K_OBJUL: + val = cps->obj_ul; + break; + case LPX_K_TMLIM: + val = cps->tm_lim; + break; + case LPX_K_OUTDLY: + val = cps->out_dly; + break; + case LPX_K_TOLINT: + val = cps->tol_int; + break; + case LPX_K_TOLOBJ: + val = cps->tol_obj; + break; + case LPX_K_MIPGAP: + val = cps->mip_gap; + break; + default: + xerror("lpx_get_real_parm: parm = %d; invalid parameter\n", + parm); + } + return val; +} + +LPX *lpx_read_mps(const char *fname) +{ /* read problem data in fixed MPS format */ + LPX *lp = lpx_create_prob(); + if (glp_read_mps(lp, GLP_MPS_DECK, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_mps(LPX *lp, const char *fname) +{ /* write problem data in fixed MPS format */ + return glp_write_mps(lp, GLP_MPS_DECK, NULL, fname); +} + +int lpx_read_bas(LPX *lp, const char *fname) +{ /* read LP basis in fixed MPS format */ + xassert(lp == lp); + xassert(fname == fname); + xerror("lpx_read_bas: operation not supported\n"); + return 0; +} + +int lpx_write_bas(LPX *lp, const char *fname) +{ /* write LP basis in fixed MPS format */ + xassert(lp == lp); + xassert(fname == fname); + xerror("lpx_write_bas: operation not supported\n"); + return 0; +} + +LPX *lpx_read_freemps(const char *fname) +{ /* read problem data in free MPS format */ + LPX *lp = lpx_create_prob(); + if (glp_read_mps(lp, GLP_MPS_FILE, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_freemps(LPX *lp, const char *fname) +{ /* write problem data in free MPS format */ + return glp_write_mps(lp, GLP_MPS_FILE, NULL, fname); +} + +LPX *lpx_read_cpxlp(const char *fname) +{ /* read problem data in CPLEX LP format */ + LPX *lp; + lp = lpx_create_prob(); + if (glp_read_lp(lp, NULL, fname)) + lpx_delete_prob(lp), lp = NULL; + return lp; +} + +int lpx_write_cpxlp(LPX *lp, const char *fname) +{ /* write problem data in CPLEX LP format */ + return glp_write_lp(lp, NULL, fname); +} + +LPX *lpx_read_model(const char *model, const char *data, const char + *output) +{ /* read LP/MIP model written in GNU MathProg language */ + LPX *lp = NULL; + glp_tran *tran; + /* allocate the translator workspace */ + tran = glp_mpl_alloc_wksp(); + /* read model section and optional data section */ + if (glp_mpl_read_model(tran, model, data != NULL)) goto done; + /* read separate data section, if required */ + if (data != NULL) + if (glp_mpl_read_data(tran, data)) goto done; + /* generate the model */ + if (glp_mpl_generate(tran, output)) goto done; + /* build the problem instance from the model */ + lp = lpx_create_prob(); + glp_mpl_build_prob(tran, lp); +done: /* free the translator workspace */ + glp_mpl_free_wksp(tran); + /* bring the problem object to the calling program */ + return lp; +} + +int lpx_print_prob(LPX *lp, const char *fname) +{ /* write problem data in plain text format */ + return glp_write_lp(lp, NULL, fname); +} + +int lpx_print_sol(LPX *lp, const char *fname) +{ /* write LP problem solution in printable format */ + return glp_print_sol(lp, fname); +} + +int lpx_print_sens_bnds(LPX *lp, const char *fname) +{ /* write bounds sensitivity information */ + if (glp_get_status(lp) == GLP_OPT && !glp_bf_exists(lp)) + glp_factorize(lp); + return glp_print_ranges(lp, 0, NULL, 0, fname); +} + +int lpx_print_ips(LPX *lp, const char *fname) +{ /* write interior point solution in printable format */ + return glp_print_ipt(lp, fname); +} + +int lpx_print_mip(LPX *lp, const char *fname) +{ /* write MIP problem solution in printable format */ + return glp_print_mip(lp, fname); +} + +int lpx_is_b_avail(glp_prob *lp) +{ /* check if LP basis is available */ + return glp_bf_exists(lp); +} + +int lpx_main(int argc, const char *argv[]) +{ /* stand-alone LP/MIP solver */ + return glp_main(argc, argv); +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.h b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.h new file mode 100644 index 000000000..54af27eec --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpx.h @@ -0,0 +1,565 @@ +/* lpx.h (old GLPK API) */ + +/* Written by Andrew Makhorin , August 2013. */ + +#ifndef LPX_H +#define LPX_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LPX glp_prob + +/* problem class: */ +#define LPX_LP 100 /* linear programming (LP) */ +#define LPX_MIP 101 /* mixed integer programming (MIP) */ + +/* type of auxiliary/structural variable: */ +#define LPX_FR 110 /* free variable */ +#define LPX_LO 111 /* variable with lower bound */ +#define LPX_UP 112 /* variable with upper bound */ +#define LPX_DB 113 /* double-bounded variable */ +#define LPX_FX 114 /* fixed variable */ + +/* optimization direction flag: */ +#define LPX_MIN 120 /* minimization */ +#define LPX_MAX 121 /* maximization */ + +/* status of primal basic solution: */ +#define LPX_P_UNDEF 132 /* primal solution is undefined */ +#define LPX_P_FEAS 133 /* solution is primal feasible */ +#define LPX_P_INFEAS 134 /* solution is primal infeasible */ +#define LPX_P_NOFEAS 135 /* no primal feasible solution exists */ + +/* status of dual basic solution: */ +#define LPX_D_UNDEF 136 /* dual solution is undefined */ +#define LPX_D_FEAS 137 /* solution is dual feasible */ +#define LPX_D_INFEAS 138 /* solution is dual infeasible */ +#define LPX_D_NOFEAS 139 /* no dual feasible solution exists */ + +/* status of auxiliary/structural variable: */ +#define LPX_BS 140 /* basic variable */ +#define LPX_NL 141 /* non-basic variable on lower bound */ +#define LPX_NU 142 /* non-basic variable on upper bound */ +#define LPX_NF 143 /* non-basic free variable */ +#define LPX_NS 144 /* non-basic fixed variable */ + +/* status of interior-point solution: */ +#define LPX_T_UNDEF 150 /* interior solution is undefined */ +#define LPX_T_OPT 151 /* interior solution is optimal */ + +/* kind of structural variable: */ +#define LPX_CV 160 /* continuous variable */ +#define LPX_IV 161 /* integer variable */ + +/* status of integer solution: */ +#define LPX_I_UNDEF 170 /* integer solution is undefined */ +#define LPX_I_OPT 171 /* integer solution is optimal */ +#define LPX_I_FEAS 172 /* integer solution is feasible */ +#define LPX_I_NOFEAS 173 /* no integer solution exists */ + +/* status codes reported by the routine lpx_get_status: */ +#define LPX_OPT 180 /* optimal */ +#define LPX_FEAS 181 /* feasible */ +#define LPX_INFEAS 182 /* infeasible */ +#define LPX_NOFEAS 183 /* no feasible */ +#define LPX_UNBND 184 /* unbounded */ +#define LPX_UNDEF 185 /* undefined */ + +/* exit codes returned by solver routines: */ +#define LPX_E_OK 200 /* success */ +#define LPX_E_EMPTY 201 /* empty problem */ +#define LPX_E_BADB 202 /* invalid initial basis */ +#define LPX_E_INFEAS 203 /* infeasible initial solution */ +#define LPX_E_FAULT 204 /* unable to start the search */ +#define LPX_E_OBJLL 205 /* objective lower limit reached */ +#define LPX_E_OBJUL 206 /* objective upper limit reached */ +#define LPX_E_ITLIM 207 /* iterations limit exhausted */ +#define LPX_E_TMLIM 208 /* time limit exhausted */ +#define LPX_E_NOFEAS 209 /* no feasible solution */ +#define LPX_E_INSTAB 210 /* numerical instability */ +#define LPX_E_SING 211 /* problems with basis matrix */ +#define LPX_E_NOCONV 212 /* no convergence (interior) */ +#define LPX_E_NOPFS 213 /* no primal feas. sol. (LP presolver) */ +#define LPX_E_NODFS 214 /* no dual feas. sol. (LP presolver) */ +#define LPX_E_MIPGAP 215 /* relative mip gap tolerance reached */ + +/* control parameter identifiers: */ +#define LPX_K_MSGLEV 300 /* lp->msg_lev */ +#define LPX_K_SCALE 301 /* lp->scale */ +#define LPX_K_DUAL 302 /* lp->dual */ +#define LPX_K_PRICE 303 /* lp->price */ +#define LPX_K_RELAX 304 /* lp->relax */ +#define LPX_K_TOLBND 305 /* lp->tol_bnd */ +#define LPX_K_TOLDJ 306 /* lp->tol_dj */ +#define LPX_K_TOLPIV 307 /* lp->tol_piv */ +#define LPX_K_ROUND 308 /* lp->round */ +#define LPX_K_OBJLL 309 /* lp->obj_ll */ +#define LPX_K_OBJUL 310 /* lp->obj_ul */ +#define LPX_K_ITLIM 311 /* lp->it_lim */ +#define LPX_K_ITCNT 312 /* lp->it_cnt */ +#define LPX_K_TMLIM 313 /* lp->tm_lim */ +#define LPX_K_OUTFRQ 314 /* lp->out_frq */ +#define LPX_K_OUTDLY 315 /* lp->out_dly */ +#define LPX_K_BRANCH 316 /* lp->branch */ +#define LPX_K_BTRACK 317 /* lp->btrack */ +#define LPX_K_TOLINT 318 /* lp->tol_int */ +#define LPX_K_TOLOBJ 319 /* lp->tol_obj */ +#define LPX_K_MPSINFO 320 /* lp->mps_info */ +#define LPX_K_MPSOBJ 321 /* lp->mps_obj */ +#define LPX_K_MPSORIG 322 /* lp->mps_orig */ +#define LPX_K_MPSWIDE 323 /* lp->mps_wide */ +#define LPX_K_MPSFREE 324 /* lp->mps_free */ +#define LPX_K_MPSSKIP 325 /* lp->mps_skip */ +#define LPX_K_LPTORIG 326 /* lp->lpt_orig */ +#define LPX_K_PRESOL 327 /* lp->presol */ +#define LPX_K_BINARIZE 328 /* lp->binarize */ +#define LPX_K_USECUTS 329 /* lp->use_cuts */ +#define LPX_K_BFTYPE 330 /* lp->bfcp->type */ +#define LPX_K_MIPGAP 331 /* lp->mip_gap */ + +#define LPX_C_COVER 0x01 /* mixed cover cuts */ +#define LPX_C_CLIQUE 0x02 /* clique cuts */ +#define LPX_C_GOMORY 0x04 /* Gomory's mixed integer cuts */ +#define LPX_C_MIR 0x08 /* mixed integer rounding cuts */ +#define LPX_C_ALL 0xFF /* all cuts */ + +typedef struct +{ /* this structure contains results reported by the routines which + checks Karush-Kuhn-Tucker conditions (for details see comments + to those routines) */ + /*--------------------------------------------------------------*/ + /* xR - A * xS = 0 (KKT.PE) */ + double pe_ae_max; + /* largest absolute error */ + int pe_ae_row; + /* number of row with largest absolute error */ + double pe_re_max; + /* largest relative error */ + int pe_re_row; + /* number of row with largest relative error */ + int pe_quality; + /* quality of primal solution: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal solution is wrong */ + /*--------------------------------------------------------------*/ + /* l[k] <= x[k] <= u[k] (KKT.PB) */ + double pb_ae_max; + /* largest absolute error */ + int pb_ae_ind; + /* number of variable with largest absolute error */ + double pb_re_max; + /* largest relative error */ + int pb_re_ind; + /* number of variable with largest relative error */ + int pb_quality; + /* quality of primal feasibility: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal solution is infeasible */ + /*--------------------------------------------------------------*/ + /* A' * (dR - cR) + (dS - cS) = 0 (KKT.DE) */ + double de_ae_max; + /* largest absolute error */ + int de_ae_col; + /* number of column with largest absolute error */ + double de_re_max; + /* largest relative error */ + int de_re_col; + /* number of column with largest relative error */ + int de_quality; + /* quality of dual solution: + 'H' - high + 'M' - medium + 'L' - low + '?' - dual solution is wrong */ + /*--------------------------------------------------------------*/ + /* d[k] >= 0 or d[k] <= 0 (KKT.DB) */ + double db_ae_max; + /* largest absolute error */ + int db_ae_ind; + /* number of variable with largest absolute error */ + double db_re_max; + /* largest relative error */ + int db_re_ind; + /* number of variable with largest relative error */ + int db_quality; + /* quality of dual feasibility: + 'H' - high + 'M' - medium + 'L' - low + '?' - dual solution is infeasible */ + /*--------------------------------------------------------------*/ + /* (x[k] - bound of x[k]) * d[k] = 0 (KKT.CS) */ + double cs_ae_max; + /* largest absolute error */ + int cs_ae_ind; + /* number of variable with largest absolute error */ + double cs_re_max; + /* largest relative error */ + int cs_re_ind; + /* number of variable with largest relative error */ + int cs_quality; + /* quality of complementary slackness: + 'H' - high + 'M' - medium + 'L' - low + '?' - primal and dual solutions are not complementary */ +} LPXKKT; + +LPX *lpx_create_prob(void); +/* create problem object */ + +void lpx_set_prob_name(LPX *lp, const char *name); +/* assign (change) problem name */ + +void lpx_set_obj_name(LPX *lp, const char *name); +/* assign (change) objective function name */ + +void lpx_set_obj_dir(LPX *lp, int dir); +/* set (change) optimization direction flag */ + +int lpx_add_rows(LPX *lp, int nrs); +/* add new rows to problem object */ + +int lpx_add_cols(LPX *lp, int ncs); +/* add new columns to problem object */ + +void lpx_set_row_name(LPX *lp, int i, const char *name); +/* assign (change) row name */ + +void lpx_set_col_name(LPX *lp, int j, const char *name); +/* assign (change) column name */ + +void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub); +/* set (change) row bounds */ + +void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub); +/* set (change) column bounds */ + +void lpx_set_obj_coef(glp_prob *lp, int j, double coef); +/* set (change) obj. coefficient or constant term */ + +void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], + const double val[]); +/* set (replace) row of the constraint matrix */ + +void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], + const double val[]); +/* set (replace) column of the constraint matrix */ + +void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], + const double ar[]); +/* load (replace) the whole constraint matrix */ + +void lpx_del_rows(LPX *lp, int nrs, const int num[]); +/* delete specified rows from problem object */ + +void lpx_del_cols(LPX *lp, int ncs, const int num[]); +/* delete specified columns from problem object */ + +void lpx_delete_prob(LPX *lp); +/* delete problem object */ + +const char *lpx_get_prob_name(LPX *lp); +/* retrieve problem name */ + +const char *lpx_get_obj_name(LPX *lp); +/* retrieve objective function name */ + +int lpx_get_obj_dir(LPX *lp); +/* retrieve optimization direction flag */ + +int lpx_get_num_rows(LPX *lp); +/* retrieve number of rows */ + +int lpx_get_num_cols(LPX *lp); +/* retrieve number of columns */ + +const char *lpx_get_row_name(LPX *lp, int i); +/* retrieve row name */ + +const char *lpx_get_col_name(LPX *lp, int j); +/* retrieve column name */ + +int lpx_get_row_type(LPX *lp, int i); +/* retrieve row type */ + +double lpx_get_row_lb(LPX *lp, int i); +/* retrieve row lower bound */ + +double lpx_get_row_ub(LPX *lp, int i); +/* retrieve row upper bound */ + +void lpx_get_row_bnds(LPX *lp, int i, int *typx, double *lb, + double *ub); +/* retrieve row bounds */ + +int lpx_get_col_type(LPX *lp, int j); +/* retrieve column type */ + +double lpx_get_col_lb(LPX *lp, int j); +/* retrieve column lower bound */ + +double lpx_get_col_ub(LPX *lp, int j); +/* retrieve column upper bound */ + +void lpx_get_col_bnds(LPX *lp, int j, int *typx, double *lb, + double *ub); +/* retrieve column bounds */ + +double lpx_get_obj_coef(LPX *lp, int j); +/* retrieve obj. coefficient or constant term */ + +int lpx_get_num_nz(LPX *lp); +/* retrieve number of constraint coefficients */ + +int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]); +/* retrieve row of the constraint matrix */ + +int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]); +/* retrieve column of the constraint matrix */ + +void lpx_create_index(LPX *lp); +/* create the name index */ + +int lpx_find_row(LPX *lp, const char *name); +/* find row by its name */ + +int lpx_find_col(LPX *lp, const char *name); +/* find column by its name */ + +void lpx_delete_index(LPX *lp); +/* delete the name index */ + +void lpx_scale_prob(LPX *lp); +/* scale problem data */ + +void lpx_unscale_prob(LPX *lp); +/* unscale problem data */ + +void lpx_set_row_stat(LPX *lp, int i, int stat); +/* set (change) row status */ + +void lpx_set_col_stat(LPX *lp, int j, int stat); +/* set (change) column status */ + +void lpx_std_basis(LPX *lp); +/* construct standard initial LP basis */ + +void lpx_adv_basis(LPX *lp); +/* construct advanced initial LP basis */ + +void lpx_cpx_basis(LPX *lp); +/* construct Bixby's initial LP basis */ + +int lpx_simplex(LPX *lp); +/* easy-to-use driver to the simplex method */ + +int lpx_exact(LPX *lp); +/* easy-to-use driver to the exact simplex method */ + +int lpx_get_status(LPX *lp); +/* retrieve generic status of basic solution */ + +int lpx_get_prim_stat(LPX *lp); +/* retrieve primal status of basic solution */ + +int lpx_get_dual_stat(LPX *lp); +/* retrieve dual status of basic solution */ + +double lpx_get_obj_val(LPX *lp); +/* retrieve objective value (basic solution) */ + +int lpx_get_row_stat(LPX *lp, int i); +/* retrieve row status (basic solution) */ + +double lpx_get_row_prim(LPX *lp, int i); +/* retrieve row primal value (basic solution) */ + +double lpx_get_row_dual(LPX *lp, int i); +/* retrieve row dual value (basic solution) */ + +void lpx_get_row_info(LPX *lp, int i, int *tagx, double *vx, + double *dx); +/* obtain row solution information */ + +int lpx_get_col_stat(LPX *lp, int j); +/* retrieve column status (basic solution) */ + +double lpx_get_col_prim(LPX *lp, int j); +/* retrieve column primal value (basic solution) */ + +double lpx_get_col_dual(glp_prob *lp, int j); +/* retrieve column dual value (basic solution) */ + +void lpx_get_col_info(LPX *lp, int j, int *tagx, double *vx, + double *dx); +/* obtain column solution information (obsolete) */ + +int lpx_get_ray_info(LPX *lp); +/* determine what causes primal unboundness */ + +void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt); +/* check Karush-Kuhn-Tucker conditions */ + +int lpx_warm_up(LPX *lp); +/* "warm up" LP basis */ + +int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]); +/* compute row of the simplex table */ + +int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]); +/* compute column of the simplex table */ + +int lpx_transform_row(LPX *lp, int len, int ind[], double val[]); +/* transform explicitly specified row */ + +int lpx_transform_col(LPX *lp, int len, int ind[], double val[]); +/* transform explicitly specified column */ + +int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol); +/* perform primal ratio test */ + +int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], + const double val[], int how, double tol); +/* perform dual ratio test */ + +int lpx_interior(LPX *lp); +/* easy-to-use driver to the interior point method */ + +int lpx_ipt_status(LPX *lp); +/* retrieve status of interior-point solution */ + +double lpx_ipt_obj_val(LPX *lp); +/* retrieve objective value (interior point) */ + +double lpx_ipt_row_prim(LPX *lp, int i); +/* retrieve row primal value (interior point) */ + +double lpx_ipt_row_dual(LPX *lp, int i); +/* retrieve row dual value (interior point) */ + +double lpx_ipt_col_prim(LPX *lp, int j); +/* retrieve column primal value (interior point) */ + +double lpx_ipt_col_dual(LPX *lp, int j); +/* retrieve column dual value (interior point) */ + +void lpx_set_class(LPX *lp, int klass); +/* set problem class */ + +int lpx_get_class(LPX *lp); +/* determine problem klass */ + +void lpx_set_col_kind(LPX *lp, int j, int kind); +/* set (change) column kind */ + +int lpx_get_col_kind(LPX *lp, int j); +/* retrieve column kind */ + +int lpx_get_num_int(LPX *lp); +/* retrieve number of integer columns */ + +int lpx_get_num_bin(LPX *lp); +/* retrieve number of binary columns */ + +int lpx_integer(LPX *lp); +/* easy-to-use driver to the branch-and-bound method */ + +int lpx_intopt(LPX *lp); +/* easy-to-use driver to the branch-and-bound method */ + +int lpx_mip_status(LPX *lp); +/* retrieve status of MIP solution */ + +double lpx_mip_obj_val(LPX *lp); +/* retrieve objective value (MIP solution) */ + +double lpx_mip_row_val(LPX *lp, int i); +/* retrieve row value (MIP solution) */ + +double lpx_mip_col_val(LPX *lp, int j); +/* retrieve column value (MIP solution) */ + +void lpx_check_int(LPX *lp, LPXKKT *kkt); +/* check integer feasibility conditions */ + +void lpx_reset_parms(LPX *lp); +/* reset control parameters to default values */ + +void lpx_set_int_parm(LPX *lp, int parm, int val); +/* set (change) integer control parameter */ + +int lpx_get_int_parm(LPX *lp, int parm); +/* query integer control parameter */ + +void lpx_set_real_parm(LPX *lp, int parm, double val); +/* set (change) real control parameter */ + +double lpx_get_real_parm(LPX *lp, int parm); +/* query real control parameter */ + +LPX *lpx_read_mps(const char *fname); +/* read problem data in fixed MPS format */ + +int lpx_write_mps(LPX *lp, const char *fname); +/* write problem data in fixed MPS format */ + +int lpx_read_bas(LPX *lp, const char *fname); +/* read LP basis in fixed MPS format */ + +int lpx_write_bas(LPX *lp, const char *fname); +/* write LP basis in fixed MPS format */ + +LPX *lpx_read_freemps(const char *fname); +/* read problem data in free MPS format */ + +int lpx_write_freemps(LPX *lp, const char *fname); +/* write problem data in free MPS format */ + +LPX *lpx_read_cpxlp(const char *fname); +/* read problem data in CPLEX LP format */ + +int lpx_write_cpxlp(LPX *lp, const char *fname); +/* write problem data in CPLEX LP format */ + +LPX *lpx_read_model(const char *model, const char *data, + const char *output); +/* read LP/MIP model written in GNU MathProg language */ + +int lpx_print_prob(LPX *lp, const char *fname); +/* write problem data in plain text format */ + +int lpx_print_sol(LPX *lp, const char *fname); +/* write LP problem solution in printable format */ + +int lpx_print_sens_bnds(LPX *lp, const char *fname); +/* write bounds sensitivity information */ + +int lpx_print_ips(LPX *lp, const char *fname); +/* write interior point solution in printable format */ + +int lpx_print_mip(LPX *lp, const char *fname); +/* write MIP problem solution in printable format */ + +int lpx_is_b_avail(LPX *lp); +/* check if LP basis is available */ + +int lpx_main(int argc, const char *argv[]); +/* stand-alone LP/MIP solver */ + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpxsamp.c b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpxsamp.c new file mode 100644 index 000000000..dd081482f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/oldapi/lpxsamp.c @@ -0,0 +1,51 @@ +/* lpxsamp.c */ + +#include +#include +#include "lpx.h" + +int main(void) +{ LPX *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], Z, x1, x2, x3; +s1: lp = lpx_create_prob(); +s2: lpx_set_prob_name(lp, "sample"); +s3: lpx_set_obj_dir(lp, LPX_MAX); +s4: lpx_add_rows(lp, 3); +s5: lpx_set_row_name(lp, 1, "p"); +s6: lpx_set_row_bnds(lp, 1, LPX_UP, 0.0, 100.0); +s7: lpx_set_row_name(lp, 2, "q"); +s8: lpx_set_row_bnds(lp, 2, LPX_UP, 0.0, 600.0); +s9: lpx_set_row_name(lp, 3, "r"); +s10: lpx_set_row_bnds(lp, 3, LPX_UP, 0.0, 300.0); +s11: lpx_add_cols(lp, 3); +s12: lpx_set_col_name(lp, 1, "x1"); +s13: lpx_set_col_bnds(lp, 1, LPX_LO, 0.0, 0.0); +s14: lpx_set_obj_coef(lp, 1, 10.0); +s15: lpx_set_col_name(lp, 2, "x2"); +s16: lpx_set_col_bnds(lp, 2, LPX_LO, 0.0, 0.0); +s17: lpx_set_obj_coef(lp, 2, 6.0); +s18: lpx_set_col_name(lp, 3, "x3"); +s19: lpx_set_col_bnds(lp, 3, LPX_LO, 0.0, 0.0); +s20: lpx_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: lpx_load_matrix(lp, 9, ia, ja, ar); +s31: lpx_simplex(lp); +s32: Z = lpx_get_obj_val(lp); +s33: x1 = lpx_get_col_prim(lp, 1); +s34: x2 = lpx_get_col_prim(lp, 2); +s35: x3 = lpx_get_col_prim(lp, 3); +s36: printf("\nZ = %g; x1 = %g; x2 = %g; x3 = %g\n", Z, x1, x2, x3); +s37: lpx_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/9dom.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/9dom.dat new file mode 100644 index 000000000..80ece7af5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/9dom.dat @@ -0,0 +1,65 @@ +/* 9dom.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #8098 from . +* Copyright (C) 2010 by Josh Greifer. Used by permission. +* +* Domino Logic III (Abstract pattern) +* +* created by Josh Greifer +* Apr 5, 2010 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 19; + +param n := 19; + +param row : 1 2 := + 1 3 . + 2 1 . + 3 3 1 + 4 1 . + 5 3 1 + 6 1 . + 7 3 1 + 8 1 . + 9 3 1 + 10 1 . + 11 3 1 + 12 1 . + 13 3 1 + 14 1 . + 15 3 1 + 16 1 . + 17 3 1 + 18 1 . + 19 1 . +; + +param col : 1 2 := + 1 1 . + 2 1 . + 3 1 3 + 4 1 . + 5 1 3 + 6 1 . + 7 1 3 + 8 1 . + 9 1 3 + 10 1 . + 11 1 3 + 12 1 . + 13 1 3 + 14 1 . + 15 1 3 + 16 1 . + 17 1 3 + 18 1 . + 19 3 . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/README b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/README new file mode 100644 index 000000000..43dc82ce3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/README @@ -0,0 +1,6 @@ +This subdirectory contains examples, which illustrate how to use +GLPK and the GNU MathProg modeling language for practical solving the +paint-by-numbers puzzle. + +For details please see the document "Solving Paint-By-Numbers Puzzles +with GLPK" included in this subdirectory (file pbn.pdf). diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/bucks.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/bucks.dat new file mode 100644 index 000000000..5dfc4f100 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/bucks.dat @@ -0,0 +1,77 @@ +/* bucks.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #27 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Party at the Right [Political] +* +* created by Jan Wolter +* Apr 6, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 23; + +param n := 27; + +param row : 1 2 3 4 5 6 7 8 := + 1 11 . . . . . . . + 2 17 . . . . . . . + 3 3 5 5 3 . . . . + 4 2 2 2 1 . . . . + 5 2 1 3 1 3 1 4 . + 6 3 3 3 3 . . . . + 7 5 1 3 1 3 1 3 . + 8 3 2 2 4 . . . . + 9 5 5 5 5 . . . . + 10 23 . . . . . . . + 11 . . . . . . . . + 12 23 . . . . . . . + 13 1 1 . . . . . . + 14 1 1 . . . . . . + 15 1 2 1 . . . . . + 16 1 1 1 1 . . . . + 17 1 1 1 1 . . . . + 18 1 10 1 2 1 . . . + 19 1 1 1 1 1 1 3 . + 20 1 1 1 1 1 1 1 1 + 21 1 1 1 1 1 1 1 . + 22 1 1 1 1 2 2 . . + 23 5 5 3 . . . . . +; + +param col : 1 2 3 4 5 6 := + 1 4 12 . . . . + 2 6 1 1 . . . + 3 8 1 1 . . . + 4 3 2 2 1 1 . + 5 2 1 1 2 1 6 + 6 1 1 1 1 . . + 7 3 1 1 2 1 1 + 8 3 2 3 1 1 . + 9 10 1 1 . . . + 10 4 2 2 1 1 . + 11 3 1 1 2 1 1 + 12 2 1 1 1 . . + 13 3 1 1 2 1 1 + 14 3 2 3 1 6 . + 15 10 1 1 . . . + 16 4 2 2 1 1 . + 17 3 1 1 2 1 1 + 18 1 1 1 9 . . + 19 2 1 1 2 1 1 + 20 2 2 3 1 3 . + 21 8 1 5 . . . + 22 6 1 1 . . . + 23 4 9 1 . . . + 24 1 1 . . . . + 25 2 1 . . . . + 26 1 1 . . . . + 27 4 . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/cat.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/cat.dat new file mode 100644 index 000000000..a6554117d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/cat.dat @@ -0,0 +1,67 @@ +/* cat.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #6 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Scardy Cat +* +* created by Jan Wolter +* Mar 24, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 20; + +param n := 20; + +param row : 1 2 3 4 := + 1 2 . . . + 2 2 . . . + 3 1 . . . + 4 1 . . . + 5 1 3 . . + 6 2 5 . . + 7 1 7 1 1 + 8 1 8 2 2 + 9 1 9 5 . + 10 2 16 . . + 11 1 17 . . + 12 7 11 . . + 13 5 5 3 . + 14 5 4 . . + 15 3 3 . . + 16 2 2 . . + 17 2 1 . . + 18 1 1 . . + 19 2 2 . . + 20 2 2 . . +; + +param col : 1 2 3 := + 1 5 . . + 2 5 3 . + 3 2 3 4 + 4 1 7 2 + 5 8 . . + 6 9 . . + 7 9 . . + 8 8 . . + 9 7 . . + 10 8 . . + 11 9 . . + 12 10 . . + 13 13 . . + 14 6 2 . + 15 4 . . + 16 6 . . + 17 6 . . + 18 5 . . + 19 6 . . + 20 6 . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dancer.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dancer.dat new file mode 100644 index 000000000..42e3057a4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dancer.dat @@ -0,0 +1,42 @@ +/* dancer.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #1 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Demo Puzzle from Front Page +* +* created by Jan Wolter +* Mar 24, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 10; + +param n := 5; + +param row : 1 2 3 := + 1 2 . . + 2 2 1 . + 3 1 1 . + 4 3 . . + 5 1 1 . + 6 1 1 . + 7 2 . . + 8 1 1 . + 9 1 2 . + 10 2 . . +; + +param col : 1 2 3 := + 1 2 1 . + 2 2 1 3 + 3 7 . . + 4 1 3 . + 5 2 1 . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/disney.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/disney.dat new file mode 100644 index 000000000..2eab1fe2d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/disney.dat @@ -0,0 +1,115 @@ +/* disney.dat */ + +data; + +param m := 50; + +param n := 50; + +param row : 1 2 3 4 5 6 7 := + 1 8 . . . . . . + 2 7 15 . . . . . + 3 2 2 19 . . . . + 4 1 2 16 1 2 . . + 5 1 5 14 1 . . . + 6 2 4 13 1 1 . . + 7 6 12 5 . . . . + 8 1 5 6 11 . . . + 9 1 4 5 4 8 . . + 10 1 4 1 18 . . . + 11 1 5 2 11 4 . . + 12 1 8 2 6 3 . . + 13 1 7 1 3 2 . . + 14 1 13 2 . . . . + 15 1 12 1 . . . . + 16 1 2 7 4 2 . . + 17 2 3 4 2 . . . + 18 5 4 3 1 . . . + 19 8 4 3 1 . . . + 20 10 3 2 1 . . . + 21 12 1 1 . . . . + 22 13 1 1 1 . . . + 23 15 1 1 3 . . . + 24 3 5 5 1 2 1 . + 25 4 5 5 2 4 2 . + 26 3 3 5 1 1 2 1 + 27 3 3 2 4 2 2 . + 28 2 3 2 3 3 2 . + 29 2 4 3 3 5 . . + 30 2 7 4 1 4 3 . + 31 3 13 1 4 5 . . + 32 9 4 1 4 7 6 1 + 33 8 1 1 2 1 15 . + 34 6 6 3 1 1 6 6 + 35 6 3 8 1 2 6 6 + 36 2 5 13 3 1 . . + 37 5 1 11 3 4 . . + 38 9 8 4 3 . . . + 39 9 6 3 10 3 . . + 40 10 5 3 2 2 3 . + 41 10 6 3 2 10 . . + 42 10 4 2 1 9 . . + 43 11 3 2 2 4 . . + 44 11 2 2 1 1 2 3 + 45 8 2 2 2 8 . . + 46 5 1 2 2 4 4 . + 47 6 2 2 2 3 4 . + 48 8 2 2 2 3 3 . + 49 10 2 4 3 1 5 4 + 50 12 7 7 4 7 . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 := + 1 14 . . . . . . . . . + 2 9 15 . . . . . . . . + 3 28 . . . . . . . . . + 4 7 5 14 . . . . . . . + 5 6 4 14 . . . . . . . + 6 5 5 8 4 . . . . . . + 7 7 6 8 3 . . . . . . + 8 19 8 3 . . . . . . . + 9 16 9 2 . . . . . . . + 10 15 2 5 2 . . . . . . + 11 8 3 1 3 1 . . . . . + 12 4 7 2 2 3 1 . . . . + 13 2 12 6 3 1 2 . . . . + 14 1 1 12 1 2 . . . . . + 15 1 4 9 2 1 2 . . . . + 16 1 6 5 6 1 . . . . . + 17 1 7 5 3 5 1 1 . . . + 18 1 8 8 6 2 1 . . . . + 19 2 1 7 5 9 1 . . . . + 20 2 2 7 6 9 1 . . . . + 21 6 15 9 2 . . . . . . + 22 7 5 4 14 1 . . . . . + 23 8 4 4 3 6 1 1 . . . + 24 9 5 2 7 3 2 3 . . . + 25 9 7 4 10 1 2 1 . . . + 26 8 2 4 2 5 2 2 2 1 . + 27 7 2 6 2 3 5 2 1 . . + 28 7 4 4 2 5 2 2 1 . . + 29 7 3 4 1 1 2 1 . . . + 30 7 3 4 1 2 2 2 . . . + 31 8 6 1 1 2 1 . . . . + 32 6 1 3 1 2 1 2 . . . + 33 4 1 3 2 2 1 2 2 . . + 34 4 1 3 1 3 1 2 2 2 . + 35 3 5 1 1 1 2 1 1 1 2 + 36 2 6 1 1 3 1 1 3 . . + 37 2 5 1 5 6 1 3 . . . + 38 2 6 2 6 3 2 . . . . + 39 1 4 2 6 2 2 1 . . . + 40 2 5 3 4 1 2 2 . . . + 41 3 7 3 1 10 . . . . . + 42 5 2 1 9 . . . . . . + 43 3 2 2 2 6 . . . . . + 44 2 1 1 2 3 2 . . . . + 45 4 2 2 2 1 . . . . . + 46 4 1 2 3 1 . . . . . + 47 4 1 1 2 3 2 . . . . + 48 6 4 6 . . . . . . . + 49 3 3 5 . . . . . . . + 50 3 2 3 . . . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dragon.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dragon.dat new file mode 100644 index 000000000..d2b8b14de --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/dragon.dat @@ -0,0 +1,61 @@ +/* dragon.dat */ + +/*********************************************************************** +* Hard 20x20 paint-by-numbers puzzle designed by Won Yoon Jo +* from the article "Painting by Numbers" by Robert A. Bosch (2000), +* . +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 20; + +param n := 20; + +param row : 1 2 3 4 5 := + 1 7 1 . . . + 2 1 1 2 . . + 3 2 1 2 . . + 4 1 2 2 . . + 5 4 2 3 . . + 6 3 1 4 . . + 7 3 1 3 . . + 8 2 1 4 . . + 9 2 9 . . . + 10 2 1 5 . . + 11 2 7 . . . + 12 14 . . . . + 13 8 2 . . . + 14 6 2 2 . . + 15 2 8 1 3 . + 16 1 5 5 2 . + 17 1 3 2 4 1 + 18 3 1 2 4 1 + 19 1 1 3 1 3 + 20 2 1 1 2 . ; + +param col : 1 2 3 4 5 := + 1 1 1 1 2 . + 2 3 1 2 1 1 + 3 1 4 2 1 1 + 4 1 3 2 4 . + 5 1 4 6 1 . + 6 1 11 1 . . + 7 5 1 6 2 . + 8 14 . . . . + 9 7 2 . . . + 10 7 2 . . . + 11 6 1 1 . . + 12 9 2 . . . + 13 3 1 1 1 . + 14 3 1 3 . . + 15 2 1 3 . . + 16 2 1 5 . . + 17 3 2 2 . . + 18 3 3 2 . . + 19 2 3 2 . . + 20 2 6 . . . ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/edge.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/edge.dat new file mode 100644 index 000000000..cdd1864e9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/edge.dat @@ -0,0 +1,48 @@ +/* edge.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #23 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Nonrepresentational Test Pattern +* +* created by Jan Wolter +* Apr 5, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 11; + +param n := 10; + +param row : 1 := + 1 1 + 2 3 + 3 1 + 4 2 + 5 1 + 6 3 + 7 3 + 8 1 + 9 2 + 10 2 + 11 4 +; + +param col : 1 2 := + 1 1 . + 2 3 . + 3 1 . + 4 2 2 + 5 2 . + 6 4 . + 7 1 . + 8 3 . + 9 3 . + 10 1 . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/forever.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/forever.dat new file mode 100644 index 000000000..e3bebf75f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/forever.dat @@ -0,0 +1,77 @@ +/* forever.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #6574 from . +* Copyright (C) 2009 by Gator. Used by permission. +* +* Lasts Forever +* +* created by Gator +* Aug 24, 2009 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 25; + +param n := 25; + +param row : 1 2 3 4 5 6 7 8 := + 1 1 2 2 2 2 2 1 . + 2 1 2 2 2 2 2 1 1 + 3 1 1 . . . . . . + 4 1 1 . . . . . . + 5 1 3 1 . . . . . + 6 1 13 1 . . . . . + 7 1 13 1 . . . . . + 8 1 13 1 . . . . . + 9 1 4 4 1 . . . . + 10 1 4 3 4 1 . . . + 11 1 4 5 4 1 . . . + 12 1 7 1 . . . . . + 13 1 7 1 . . . . . + 14 1 7 1 . . . . . + 15 1 7 1 . . . . . + 16 1 1 5 1 . . . . + 17 1 2 6 1 . . . . + 18 1 4 6 1 . . . . + 19 1 6 6 1 . . . . + 20 1 3 1 . . . . . + 21 1 1 1 . . . . . + 22 1 1 . . . . . . + 23 1 1 . . . . . . + 24 1 1 2 2 2 2 2 1 + 25 1 2 2 2 2 2 1 . +; + +param col : 1 2 3 4 5 6 7 8 := + 1 1 2 2 2 2 2 1 . + 2 1 1 2 2 2 2 2 1 + 3 1 1 . . . . . . + 4 1 1 . . . . . . + 5 1 1 . . . . . . + 6 1 2 1 . . . . . + 7 1 6 1 1 . . . . + 8 1 6 2 1 . . . . + 9 1 6 3 1 . . . . + 10 1 4 8 1 . . . . + 11 1 3 5 2 1 . . . + 12 1 4 8 2 1 . . . + 13 1 4 9 2 1 . . . + 14 1 4 11 1 . . . . + 15 1 3 9 1 . . . . + 16 1 4 8 1 . . . . + 17 1 6 3 1 . . . . + 18 1 6 2 1 . . . . + 19 1 6 1 1 . . . . + 20 1 2 1 . . . . . + 21 1 1 . . . . . . + 22 1 1 . . . . . . + 23 1 1 . . . . . . + 24 1 2 2 2 2 2 1 1 + 25 1 2 2 2 2 2 1 . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/knot.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/knot.dat new file mode 100644 index 000000000..b9e12d796 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/knot.dat @@ -0,0 +1,95 @@ +/* knot.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #16 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Probably Not +* +* created by Jan Wolter +* Mar 27, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 34; + +param n := 34; + +param row : 1 2 3 4 5 6 7 8 := + 1 1 1 . . . . . . + 2 2 2 . . . . . . + 3 3 3 . . . . . . + 4 2 1 1 2 . . . . + 5 2 1 1 2 . . . . + 6 1 1 1 1 . . . . + 7 1 1 1 1 . . . . + 8 18 . . . . . . . + 9 2 1 1 1 1 2 . . + 10 1 1 1 1 1 1 . . + 11 1 1 1 1 1 1 . . + 12 26 . . . . . . . + 13 2 1 1 1 1 1 1 2 + 14 2 1 1 2 2 1 1 2 + 15 2 1 1 2 2 1 1 2 + 16 14 14 . . . . . . + 17 1 1 1 1 . . . . + 18 1 1 1 1 . . . . + 19 14 14 . . . . . . + 20 2 1 1 2 2 1 1 2 + 21 2 1 1 2 2 1 1 2 + 22 2 1 1 1 1 1 1 2 + 23 26 . . . . . . . + 24 1 1 1 1 1 1 . . + 25 1 1 1 1 1 1 . . + 26 2 1 1 1 1 2 . . + 27 18 . . . . . . . + 28 1 1 1 1 . . . . + 29 1 1 1 1 . . . . + 30 2 1 1 2 . . . . + 31 2 1 1 2 . . . . + 32 3 3 . . . . . . + 33 2 2 . . . . . . + 34 1 1 . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 := + 1 1 1 . . . . . . + 2 2 2 . . . . . . + 3 3 3 . . . . . . + 4 2 1 1 2 . . . . + 5 2 1 1 2 . . . . + 6 1 1 1 1 . . . . + 7 1 1 1 1 . . . . + 8 18 . . . . . . . + 9 2 1 1 1 1 2 . . + 10 1 1 1 1 1 1 . . + 11 1 1 1 1 1 1 . . + 12 26 . . . . . . . + 13 2 1 1 1 1 1 1 2 + 14 2 1 1 2 2 1 1 2 + 15 2 1 1 2 2 1 1 2 + 16 14 14 . . . . . . + 17 1 1 1 1 . . . . + 18 1 1 1 1 . . . . + 19 14 14 . . . . . . + 20 2 1 1 2 2 1 1 2 + 21 2 1 1 2 2 1 1 2 + 22 2 1 1 1 1 1 1 2 + 23 26 . . . . . . . + 24 1 1 1 1 1 1 . . + 25 1 1 1 1 1 1 . . + 26 2 1 1 1 1 2 . . + 27 18 . . . . . . . + 28 1 1 1 1 . . . . + 29 1 1 1 1 . . . . + 30 2 1 1 2 . . . . + 31 2 1 1 2 . . . . + 32 3 3 . . . . . . + 33 2 2 . . . . . . + 34 1 1 . . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/light.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/light.dat new file mode 100644 index 000000000..1ffc5d460 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/light.dat @@ -0,0 +1,122 @@ +/* light.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #803 from . +* Copyright (C) 2007 by Robert Kummerfeldt. Used by permission. +* +* You light up my life +* +* created by Robert Kummerfeldt +* Mar 15, 2007 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 45; + +param n := 50; + +param row : 1 2 3 4 := + 1 . . . . + 2 1 . . . + 3 1 . . . + 4 3 . . . + 5 2 2 . . + 6 1 1 . . + 7 7 . . . + 8 1 1 . . + 9 1 3 1 . + 10 1 3 1 . + 11 1 1 . . + 12 11 . . . + 13 1 1 . . + 14 1 1 . . + 15 2 2 . . + 16 1 1 . . + 17 1 1 . . + 18 1 1 . . + 19 1 1 . . + 20 2 2 . . + 21 1 1 . . + 22 1 1 . . + 23 1 1 . . + 24 1 1 . . + 25 1 1 . . + 26 1 1 . . + 27 1 1 . . + 28 1 1 . . + 29 1 1 . . + 30 1 1 . . + 31 2 2 . . + 32 1 1 . . + 33 1 1 . . + 34 1 1 . . + 35 1 1 . . + 36 1 1 . . + 37 1 4 1 . + 38 1 1 1 1 + 39 1 1 1 1 + 40 1 1 1 1 + 41 1 1 1 1 + 42 25 . . . + 43 6 5 . . + 44 5 6 . . + 45 4 5 . . +; + +param col : 1 2 3 4 5 := + 1 1 . . . . + 2 1 . . . . + 3 1 . . . . + 4 2 . . . . + 5 1 . . . . + 6 1 . . . . + 7 1 . . . . + 8 2 . . . . + 9 1 . . . . + 10 1 . . . . + 11 1 . . . . + 12 1 . . . . + 13 2 . . . . + 14 1 . . . . + 15 1 . . . . + 16 1 . . . . + 17 5 . . . . + 18 7 1 . . . + 19 6 1 . . . + 20 6 1 . . . + 21 1 6 1 . . + 22 4 1 . . . + 23 7 1 . . . + 24 1 1 1 1 . + 25 2 1 2 1 1 + 26 3 1 2 1 1 + 27 2 1 2 1 1 + 28 1 1 1 1 . + 29 7 6 . . . + 30 4 1 1 . . + 31 1 6 1 1 . + 32 6 6 . . . + 33 6 1 . . . + 34 5 1 . . . + 35 7 . . . . + 36 1 . . . . + 37 2 . . . . + 38 1 . . . . + 39 1 . . . . + 40 1 . . . . + 41 2 . . . . + 42 1 . . . . + 43 1 . . . . + 44 1 . . . . + 45 1 . . . . + 46 2 . . . . + 47 1 . . . . + 48 1 . . . . + 49 1 . . . . + 50 1 . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/mum.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/mum.dat new file mode 100644 index 000000000..a1baf5090 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/mum.dat @@ -0,0 +1,101 @@ +/* mum.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #65 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Mum's the Word [has only one solution] +* +* created by Jan Wolter +* Jul 10, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 40; + +param n := 34; + +param row : 1 2 3 4 5 6 7 8 9 := + 1 12 . . . . . . . . + 2 5 2 5 . . . . . . + 3 5 2 2 5 . . . . . + 4 1 2 2 2 2 2 1 . . + 5 4 2 2 4 2 2 4 . . + 6 4 2 2 4 2 2 4 . . + 7 1 2 2 2 2 2 1 . . + 8 6 2 2 2 2 2 6 . . + 9 6 2 2 2 2 2 6 . . + 10 1 14 1 . . . . . . + 11 10 10 . . . . . . . + 12 8 3 3 8 . . . . . + 13 1 1 2 1 1 2 1 1 . + 14 9 2 2 2 2 9 . . . + 15 9 9 . . . . . . . + 16 1 1 1 1 1 1 . . . + 17 12 2 12 . . . . . . + 18 12 12 . . . . . . . + 19 1 1 4 1 1 . . . . + 20 14 14 . . . . . . . + 21 12 12 . . . . . . . + 22 2 1 4 1 2 . . . . + 23 9 4 9 . . . . . . + 24 1 7 4 7 1 . . . . + 25 1 1 1 4 1 1 1 . . + 26 1 7 4 7 1 . . . . + 27 1 7 4 7 1 . . . . + 28 1 2 1 2 1 2 1 . . + 29 1 7 2 7 1 . . . . + 30 1 1 6 2 6 1 1 . . + 31 1 1 1 1 2 1 1 1 1 + 32 1 1 6 2 6 1 1 . . + 33 1 1 5 5 1 1 . . . + 34 1 1 1 8 1 1 1 . . + 35 1 1 4 4 1 1 . . . + 36 1 2 6 2 1 . . . . + 37 2 4 4 2 . . . . . + 38 2 6 2 . . . . . . + 39 4 4 . . . . . . . + 40 6 . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 11 12 := + 1 5 . . . . . . . . . . . + 2 3 2 1 . . . . . . . . . + 3 3 2 2 1 . . . . . . . . + 4 3 2 2 2 2 . . . . . . . + 5 3 2 2 2 2 3 . . . . . . + 6 1 2 2 2 2 2 16 . . . . . + 7 1 2 2 2 2 2 2 1 2 . . . + 8 1 2 2 2 2 2 2 13 1 . . . + 9 3 2 2 2 2 2 2 4 1 1 . . + 10 6 5 2 2 2 2 6 1 1 . . . + 11 1 7 3 2 2 2 2 2 1 1 1 . + 12 3 4 1 2 2 2 2 2 2 1 1 1 + 13 6 1 2 3 2 2 2 2 1 1 1 . + 14 1 7 2 16 1 1 . . . . . . + 15 1 4 1 1 1 1 1 1 1 1 1 . + 16 1 2 1 3 1 1 6 1 1 1 1 . + 17 2 7 1 1 11 1 1 1 1 . . . + 18 2 7 1 1 11 1 1 1 1 . . . + 19 1 2 1 3 1 1 6 1 1 1 1 . + 20 1 4 1 1 1 1 1 1 1 1 1 . + 21 1 7 2 16 1 1 . . . . . . + 22 6 1 2 3 2 2 2 2 1 1 1 . + 23 3 4 1 2 2 2 2 2 2 1 1 1 + 24 1 7 3 2 2 2 2 2 1 1 1 . + 25 6 5 2 2 2 2 6 1 1 . . . + 26 3 2 2 2 2 2 2 4 1 1 . . + 27 1 2 2 2 2 2 2 13 1 . . . + 28 1 2 2 2 2 2 2 1 2 . . . + 29 1 2 2 2 2 2 16 . . . . . + 30 3 2 2 2 2 3 . . . . . . + 31 3 2 2 2 2 . . . . . . . + 32 3 2 2 1 . . . . . . . . + 33 3 2 1 . . . . . . . . . + 34 5 . . . . . . . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.mod new file mode 100644 index 000000000..c4a1b2cf3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.mod @@ -0,0 +1,268 @@ +/* PBN, Paint-By-Numbers Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* NOTE: See also the document "Solving Paint-By-Numbers Puzzles with + GLPK", which is included in the GLPK distribution. */ + +/* A paint-by-numbers puzzle consists of an m*n grid of pixels (the + canvas) together with m+n cluster-size sequences, one for each row + and column. The goal is to paint the canvas with a picture that + satisfies the following constraints: + + 1. Each pixel must be blank or white. + + 2. If a row or column has cluster-size sequence s1, s2, ..., sk, + then it must contain k clusters of black pixels - the first with + s1 black pixels, the second with s2 black pixels, and so on. + + It should be noted that "first" means "leftmost" for rows and + "topmost" for columns, and that rows and columns need not begin or + end with black pixels. + + Example: + 1 1 + 1 1 + 2 1 1 1 1 1 2 3 + 3 2 1 2 1 2 3 4 8 9 + + 3 6 # # # . # # # # # # + 1 4 # . . . . . # # # # + 1 1 3 . . # . # . . # # # + 2 . . . . . . . . # # + 3 3 . . # # # . . # # # + 1 4 # . . . . . # # # # + 2 5 # # . . . # # # # # + 2 5 # # . . . # # # # # + 1 1 . . . # . . . . . # + 3 . . # # # . . . . . + + (In Russia such puzzles are known as "Japanese crosswords".) + + References: + Robert A. Bosch, "Painting by Numbers", 2000. + */ + +/*--------------------------------------------------------------------*/ +/* Main part based on the formulation proposed by Robert Bosch. */ + +param m, integer, >= 1; +/* the number of rows */ + +param n, integer, >= 1; +/* the number of columns */ + +param row{i in 1..m, 1..(n+1) div 2}, integer, >= 0, default 0; +/* the cluster-size sequence for row i (raw data) */ + +param col{j in 1..n, 1..(m+1) div 2}, integer, >= 0, default 0; +/* the cluster-size sequence for column j (raw data) */ + +param kr{i in 1..m} := sum{t in 1..(n+1) div 2: row[i,t] > 0} 1; +/* the number of clusters in row i */ + +param kc{j in 1..n} := sum{t in 1..(m+1) div 2: col[j,t] > 0} 1; +/* the number of clusters in column j */ + +param sr{i in 1..m, t in 1..kr[i]} := row[i,t], integer, >= 1; +/* the cluster-size sequence for row i */ + +param sc{j in 1..n, t in 1..kc[j]} := col[j,t], integer, >= 1; +/* the cluster-size sequence for column j */ + +check{i in 1..m}: sum{t in 1..kr[i]} sr[i,t] <= n - (kr[i] - 1); +/* check that the sum of the cluster sizes in each row is valid */ + +check{j in 1..n}: sum{t in 1..kc[j]} sc[j,t] <= m - (kc[j] - 1); +/* check that the sum of the cluster sizes in each column is valid */ + +check: sum{i in 1..m, t in 1..kr[i]} sr[i,t] = + sum{j in 1..n, t in 1..kc[j]} sc[j,t]; +/* check that the sum of the cluster sizes in all rows is equal to the + sum of the cluster sizes in all columns */ + +param er{i in 1..m, t in 1..kr[i]} := + if t = 1 then 1 else er[i,t-1] + sr[i,t-1] + 1; +/* the smallest value of j such that row i's t-th cluster can be + placed in row i with its leftmost pixel occupying pixel j */ + +param lr{i in 1..m, t in 1..kr[i]} := + if t = kr[i] then n + 1 - sr[i,t] else lr[i,t+1] - sr[i,t] - 1; +/* the largest value of j such that row i's t-th cluster can be + placed in row i with its leftmost pixel occupying pixel j */ + +param ec{j in 1..n, t in 1..kc[j]} := + if t = 1 then 1 else ec[j,t-1] + sc[j,t-1] + 1; +/* the smallest value of i such that column j's t-th cluster can be + placed in column j with its topmost pixel occupying pixel i */ + +param lc{j in 1..n, t in 1..kc[j]} := + if t = kc[j] then m + 1 - sc[j,t] else lc[j,t+1] - sc[j,t] - 1; +/* the largest value of i such that column j's t-th cluster can be + placed in column j with its topmost pixel occupying pixel i */ + +var z{i in 1..m, j in 1..n}, binary; +/* z[i,j] = 1, if row i's j-th pixel is painted black + z[i,j] = 0, if row i's j-th pixel is painted white */ + +var y{i in 1..m, t in 1..kr[i], j in er[i,t]..lr[i,t]}, binary; +/* y[i,t,j] = 1, if row i's t-th cluster is placed in row i with its + leftmost pixel occupying pixel j + y[i,t,j] = 0, if not */ + +var x{j in 1..n, t in 1..kc[j], i in ec[j,t]..lc[j,t]}, binary; +/* x[j,t,i] = 1, if column j's t-th cluster is placed in column j with + its topmost pixel occupying pixel i + x[j,t,i] = 0, if not */ + +s.t. fa{i in 1..m, t in 1..kr[i]}: + sum{j in er[i,t]..lr[i,t]} y[i,t,j] = 1; +/* row i's t-th cluster must appear in row i exactly once */ + +s.t. fb{i in 1..m, t in 1..kr[i]-1, j in er[i,t]..lr[i,t]}: + y[i,t,j] <= sum{jp in j+sr[i,t]+1..lr[i,t+1]} y[i,t+1,jp]; +/* row i's (t+1)-th cluster must be placed to the right of its t-th + cluster */ + +s.t. fc{j in 1..n, t in 1..kc[j]}: + sum{i in ec[j,t]..lc[j,t]} x[j,t,i] = 1; +/* column j's t-th cluster must appear in column j exactly once */ + +s.t. fd{j in 1..n, t in 1..kc[j]-1, i in ec[j,t]..lc[j,t]}: + x[j,t,i] <= sum{ip in i+sc[j,t]+1..lc[j,t+1]} x[j,t+1,ip]; +/* column j's (t+1)-th cluster must be placed below its t-th cluster */ + +s.t. fe{i in 1..m, j in 1..n}: + z[i,j] <= sum{t in 1..kr[i], jp in er[i,t]..lr[i,t]: + j-sr[i,t]+1 <= jp and jp <= j} y[i,t,jp]; +/* the double coverage constraint stating that if row i's j-th pixel + is painted black, then at least one of row i's clusters must be + placed in such a way that it covers row i's j-th pixel */ + +s.t. ff{i in 1..m, j in 1..n}: + z[i,j] <= sum{t in 1..kc[j], ip in ec[j,t]..lc[j,t]: + i-sc[j,t]+1 <= ip and ip <= i} x[j,t,ip]; +/* the double coverage constraint making sure that if row i's j-th + pixel is painted black, then at least one of column j's clusters + covers it */ + +s.t. fg{i in 1..m, j in 1..n, t in 1..kr[i], jp in er[i,t]..lr[i,t]: + j-sr[i,t]+1 <= jp and jp <= j}: z[i,j] >= y[i,t,jp]; +/* the constraint to prevent white pixels from being covered by the + row clusters */ + +s.t. fh{i in 1..m, j in 1..n, t in 1..kc[j], ip in ec[j,t]..lc[j,t]: + i-sc[j,t]+1 <= ip and ip <= i}: z[i,j] >= x[j,t,ip]; +/* the constraint to prevent white pixels from being covered by the + column clusters */ + +/* this is a feasibility problem, so no objective is needed */ + +/*--------------------------------------------------------------------*/ +/* The following part is used only to check for multiple solutions. */ + +param zz{i in 1..m, j in 1..n}, binary, default 0; +/* zz[i,j] is z[i,j] for a previously found solution */ + +s.t. fz{1..1 : sum{i in 1..m, j in 1..n} zz[i,j] > 0}: + sum{i in 1..m, j in 1..n} + (if zz[i,j] then (1 - z[i,j]) else z[i,j]) >= 1; +/* the constraint to forbid finding a solution, which is identical to + the previously found one; this constraint is included in the model + only if the previously found solution specified by the parameter zz + is provided in the data section */ + +solve; + +/*--------------------------------------------------------------------*/ +/* Print solution to the standard output. */ + +for {i in 1..m} +{ printf{j in 1..n} " %s", if z[i,j] then "#" else "."; + printf "\n"; +} + +/*--------------------------------------------------------------------*/ +/* Write solution to a text file in PostScript format. */ + +param ps, symbolic, default "solution.ps"; + +printf "%%!PS-Adobe-3.0\n" > ps; +printf "%%%%Creator: GLPK (pbn.mod)\n" >> ps; +printf "%%%%BoundingBox: 0 0 %d %d\n", + 6 * (n + 2), 6 * (m + 2) >> ps; +printf "%%%%EndComments\n" >> ps; +printf "<> setpagedevice\n", + 6 * (n + 2), 6 * (m + 2) >> ps; +printf "0.1 setlinewidth\n" >> ps; +printf "/A { 2 copy 2 copy 2 copy newpath moveto exch 6 add exch line" & + "to\n" >> ps; +printf "exch 6 add exch 6 add lineto 6 add lineto closepath } bind de" & + "f\n" >> ps; +printf "/W { A stroke } def\n" >> ps; +printf "/B { A fill } def\n" >> ps; +printf {i in 1..m, j in 1..n} "%d %d %s\n", + (j - 1) * 6 + 6, (m - i) * 6 + 6, + if z[i,j] then "B" else "W" >> ps; +printf "%%%%EOF\n" >> ps; + +printf "Solution has been written to file %s\n", ps; + +/*--------------------------------------------------------------------*/ +/* Write solution to a text file in the form of MathProg data section, + which can be used later to check for multiple solutions. */ + +param dat, symbolic, default "solution.dat"; + +printf "data;\n" > dat; +printf "\n" >> dat; +printf "param zz :" >> dat; +printf {j in 1..n} " %d", j >> dat; +printf " :=\n" >> dat; +for {i in 1..m} +{ printf " %2d", i >> dat; + printf {j in 1..n} " %s", if z[i,j] then "1" else "." >> dat; + printf "\n" >> dat; +} +printf ";\n" >> dat; +printf "\n" >> dat; +printf "end;\n" >> dat; + +printf "Solution has also been written to file %s\n", dat; + +/*--------------------------------------------------------------------*/ +/* The following data correspond to the example above. */ + +data; + +param m := 10; + +param n := 10; + +param row : 1 2 3 := + 1 3 6 . + 2 1 4 . + 3 1 1 3 + 4 2 . . + 5 3 3 . + 6 1 4 . + 7 2 5 . + 8 2 5 . + 9 1 1 . + 10 3 . . +; + +param col : 1 2 3 4 := + 1 2 3 . . + 2 1 2 . . + 3 1 1 1 1 + 4 1 2 . . + 5 1 1 1 1 + 6 1 2 . . + 7 2 3 . . + 8 3 4 . . + 9 8 . . . + 10 9 . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.pdf b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.pdf new file mode 100644 index 000000000..8342189cf Binary files /dev/null and b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.pdf differ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.tex b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.tex new file mode 100644 index 000000000..c73a441b0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/pbn.tex @@ -0,0 +1,279 @@ +%* pbn.tex *% + +\documentclass[11pt,draft]{article} +\usepackage{amssymb} + +\begin{document} + +\title{Solving Paint-By-Numbers Puzzles with GLPK} + +\author{Andrew Makhorin {\tt}} + +\date{August 2011} + +\maketitle + +\section{Introduction$^1$} + +\footnotetext[1]{This section is based on the material from [1].} + +A {\it paint-by-numbers} puzzle consists of an $m\times n$ grid of +pixels (the {\it canvas}) together with $m+n$ {\it cluster-size +sequences}, one for each row and column. The goal is to paint the canvas +with a picture that satisfies the following constraints: + +1. Each pixel must be blank or white. + +2. If a row or column has cluster-size sequence $s_1$, $s_2$, \dots, +$s_k$, then it must contain $k$ clusters of black pixels---the first +with $s_1$ black pixels, the second with $s_2$ black pixels, and so on. + +It should be noted that ``first'' means ``leftmost'' for rows and +``topmost'' for columns, and that rows and columns need not begin or end +with black pixels. + +\subsubsection*{Example} + +\def\arraystretch{.8} + +\begin{center} +\begin{tabular}{*{3}{@{$\;\;$}c}c*{10}{@{\ }c}@{}} + & & && & &1& &1& & & & & \\ + & & && & &1& &1& & & & & \\ + & & &&2&1&1&1&1&1&2&3& & \\ + & & &&3&2&1&2&1&2&3&4&8&9\\ +\\ + &3&6&&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$&$\blacksquare$\\ + &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$& +$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ +1&1&3&&$\square$&$\square$&$\blacksquare$&$\square$&$\blacksquare$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + & &2&&$\square$&$\square$&$\square$&$\square$&$\square$&$\square$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$\\ + &3&3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ + &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$\\ + &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& +$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\blacksquare$\\ + &1&1&&$\square$&$\square$&$\square$&$\blacksquare$&$\square$&$\square$& +$\square$&$\square$&$\square$&$\blacksquare$\\ + & &3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& +$\square$&$\square$&$\square$&$\square$&$\square$\\ +\end{tabular} +\end{center} + +\def\arraystretch{1} + +\section{Solving a puzzle} + +The Paint-By-Numbers puzzle can be formulated as a 0-1 integer +feasibility problem. The formulation used in GLPK was proposed in [1]. + +For solving puzzles there are used two components, which both are +coded in the GNU MathProg modeling language [2]: the model section and +the data section. The model section is common for all puzzles and +placed in file \verb|pbn.mod|. This file is included in the GLPK +distribution and can be found in subdirectory \verb|examples/pbn|. + +To solve a particular puzzle the user only needs to prepare the data +section, which defines input data to the puzzle. The data section for +the example puzzle from the previous section may look like follows +(here \verb|m| is the number of rows, and \verb|n| is the number of +columns): + +\begin{footnotesize} +\begin{verbatim} +data; + +param m := 10; + +param n := 10; + +param row : 1 2 3 := + 1 3 6 . + 2 1 4 . + 3 1 1 3 + 4 2 . . + 5 3 3 . + 6 1 4 . + 7 2 5 . + 8 2 5 . + 9 1 1 . + 10 3 . . +; + +param col : 1 2 3 4 := + 1 2 3 . . + 2 1 2 . . + 3 1 1 1 1 + 4 1 2 . . + 5 1 1 1 1 + 6 1 2 . . + 7 2 3 . . + 8 3 4 . . + 9 8 . . . + 10 9 . . . +; + +end; +\end{verbatim} +\end{footnotesize} + +\newpage + +Let the data section for a puzzle be placed in file \verb|foo.dat|. +Then to solve the puzzle the user should enter the following command: + +\begin{verbatim} + glpsol --minisat -m pbn.mod -d foo.dat +\end{verbatim} + +\noindent +This command invokes \verb|glpsol|, the GLPK LP/MIP stand-alone solver, +which reads the model section from file \verb|pbn.mod|, the data section +from file \verb|foo.dat|, translates them to an internal representation, +and solves the resulting 0-1 integer feasibility problem. The option +\verb|--minisat| tells \verb|glpsol| to translate the feasibility +problem to a CNF satisfiability problem and then use the MiniSat solver +[3] to solve it. + +If a solution to the puzzle has been found, that is indicated by the +message \verb|SATISFIABLE|, \verb|glpsol| prints the solution to the +standard output (terminal), writes it to file \verb|solution.ps| in the +PostScript format, and also writes it to file \verb|solution.dat| in the +form of MathProg data section, which can be used later to check for +multiple solutions, if necessary (for details see the next section). +The message \verb|UNSATISFIABLE| means that the puzzle has no solution. + +Usually the time taken to solve a puzzle of moderate size (up to 50 rows +and columns) varies from several seconds to several minutes. However, +hard or large puzzles may require much more time. + +Data sections for some example puzzles included in the GLPK distribution +can be found in subdirectory \verb|examples/pbn|. + +\section{Checking for multiple solutions} + +Sometimes the user may be interested to know if the puzzle has exactly +one (unique) solution or it has multiple solutions. To check that the +user should solve the puzzle as explained above in the previous section +and then enter the following command: + +\begin{verbatim} + glpsol --minisat -m pbn.mod -d foo.dat -d solution.dat +\end{verbatim} + +\noindent +In this case \verb|glpsol| reads an additional data section from file +\verb|solution.dat|, which contains the previously found solution, +activates an additional constraint in the model section to forbid +finding the solution specified in the additional data section, and +attempts to find another solution. The message \verb|UNSATISFIABLE| +reported by \verb|glpsol| will mean that the puzzle has a unique +solution, while the message \verb|SATISFIABLE| will mean that the puzzle +has at least two different solutions. + +\newpage + +\section{Solution times} + +The table on the next page shows solution times on a sample set of +the paint-by-numbers puzzles from the \verb|| website. +This sample set was used in the survey [4] to compare efficiency of +existing PBN solvers. + +The authors of some puzzles from the sample set have given permission +for their puzzles to be freely redistributed as long as the original +attribution and copyright statement are retained. In the table these +puzzles are marked by an asterisk (*). The files containing the +MathProg data sections for these puzzles are included in the GLPK +distribution and can be found in subdirectory \verb|examples/pbn|. + +All runs were performed on Intel Pentium 4 (CPU 3GHz, 2GB of RAM). +The C compiler used was GCC 3.4.4 with default optimization options. + +The column `Sol.Time' shows the time, in seconds, taken by the +\verb|glpsol| solver to find a solution to corresponding puzzle. The +column `Chk.Time' shows the time, in seconds, taken by \verb|glpsol| to +check for multiple solutions, i.e. either to prove that the puzzle has +a unique solution or find another solution to the puzzle. Both these +times do not include the time used to translate the MathProg model and +data sections into an internal MIP representation, but include the time +used to translate the 0-1 feasibility problem to a CNF satisfiability +problem. + +\begin{thebibliography}{10} + +\bibitem{1} +Robert A. Bosch, ``Painting by Numbers'', 2000.\\ +\verb||. + +\bibitem{2} +GLPK: Modeling Language GNU MathProg. Language Reference. (This +document is included in the GLPK distribution and can be found in +subdirectory \verb|doc|.) + +\bibitem{3} +Niklas E\'en, Niklas S\"orensson, ``An Extensible SAT-solver'', +Chalmers University of Technology, Sweden. \verb||. + +\bibitem{4} +Jan Wolter, ``Survey of Paint-by-Number Puzzle Solvers''.\\ +\verb||. + +\end{thebibliography} + +\newpage + +\begin{table} +\caption{Solution times on the sample set of puzzles from [4]} +\begin{center} +\begin{tabular}{@{}lllcrr@{}} +\hline +\multicolumn{2}{c}{Puzzle}&Size&Notes&Sol.Time, s&Chk.Time, s\\ +\hline +\#1&Dancer* &$10\times 5$&L&$<1$&$<1$\\ +\#6&Cat* &$20\times 20$&L&$<1$&$<1$\\ +\#21&Skid* &$25\times 14$&L, B&$<1$&$<1$\\ +\#27&Bucks* &$23\times 27$&B&$<1$&$<1$\\ +\#23&Edge* &$11\times 10$&&$<1$&$<1$\\ +\#2413&Smoke &$20\times 20$&&$<1$&$<1$\\ +\#16&Knot* &$34\times 34$&L&1&1\\ +\#529&Swing* &$45\times 45$&L&1&1\\ +\#65&Mum* &$40\times 34$&&1&1\\ +\#7604&DiCap &$55\times 55$&&10&10\\ +\#1694&Tragic &$50\times 45$&&3&3\\ +\#1611&Merka &$60\times 55$&B&4&4\\ +\#436&Petro* &$35\times 40$&&1&1\\ +\#4645&M\&M &$70\times 50$&B&5&6\\ +\#3541&Signed &$50\times 60$&&7&7\\ +\#803&Light* &$45\times 50$&B&1&1\\ +\#6574&Forever*&$25\times 25$&&1&1\\ +\#2040&Hot &$60\times 55$&&6&6\\ +\#6739&Karate &$40\times 40$&M&2&2\\ +\#8098&9-Dom* &$19\times 19$&&1&2\\ +\#2556&Flag &$45\times 65$&M, B&2&2\\ +\#2712&Lion &$47\times 47$&M&11&12\\ +\#10088&Marley &$63\times 52$&M&135&226\\ +\#9892&Nature &$40\times 50$&M&850&1053\\ +\hline +\end{tabular} + +\begin{tabular}{@{}lp{102mm}@{}} +*&Puzzle designer has given permission to redistribute the puzzle.\\ +L&Puzzle is line solvable. That is, it can be solved one line at a +time.\\ +B&Puzzle contains blank rows or columns.\\ +M&Puzzle has multiple solutions.\\ +\end{tabular} +\end{center} +\end{table} + +\end{document} diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/petro.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/petro.dat new file mode 100644 index 000000000..15ccc4a16 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/petro.dat @@ -0,0 +1,102 @@ +/* petro.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #436 from . +* Copyright (C) 2006 by Jan Wolter. Used by permission. +* +* Old Stone Face +* +* created by Jan Wolter +* Jun 17, 2006 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 35; + +param n := 40; + +param row : 1 2 3 4 5 6 7 8 9 := + 1 2 2 . . . . . . . + 2 2 3 2 . . . . . . + 3 3 3 3 2 . . . . . + 4 3 3 3 3 . . . . . + 5 2 3 3 3 3 2 . . . + 6 3 3 3 3 3 3 . . . + 7 4 2 3 2 2 4 . . . + 8 4 2 2 2 2 3 1 . . + 9 3 1 2 2 2 3 3 . . + 10 3 2 2 2 2 2 4 . . + 11 3 2 15 2 4 . . . . + 12 5 19 4 . . . . . . + 13 6 4 3 3 . . . . . + 14 6 4 4 . . . . . . + 15 2 4 6 2 . . . . . + 16 2 2 3 3 3 2 . . . + 17 9 2 2 2 3 9 . . . + 18 10 2 2 2 2 2 10 . . + 19 4 2 3 3 2 2 3 2 5 + 20 2 5 2 4 2 . . . . + 21 5 3 2 2 5 . . . . + 22 6 3 2 3 7 . . . . + 23 6 8 9 7 . . . . . + 24 4 8 7 5 . . . . . + 25 4 . . . . . . . . + 26 2 . . . . . . . . + 27 2 . . . . . . . . + 28 14 . . . . . . . . + 29 16 . . . . . . . . + 30 3 3 . . . . . . . + 31 2 2 . . . . . . . + 32 2 2 . . . . . . . + 33 4 4 . . . . . . . + 34 16 . . . . . . . . + 35 12 . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 := + 1 1 . . . . . . + 2 3 2 . . . . . + 3 2 3 3 . . . . + 4 3 3 3 . . . . + 5 3 3 3 3 . . . + 6 4 2 2 2 . . . + 7 3 3 2 3 . . . + 8 3 2 2 2 . . . + 9 3 2 6 . . . . + 10 2 9 . . . . . + 11 2 3 3 . . . . + 12 4 4 3 2 4 . . + 13 7 2 5 2 6 . . + 14 12 2 3 2 3 2 . + 15 3 1 2 2 2 3 . + 16 2 2 3 2 2 2 . + 17 6 2 6 2 2 2 . + 18 12 4 3 2 2 . . + 19 12 2 2 2 . . . + 20 2 6 2 . . . . + 21 2 6 5 2 . . . + 22 10 9 2 2 . . . + 23 12 3 3 2 2 . . + 24 6 2 2 2 2 2 2 + 25 2 2 3 2 2 2 . + 26 4 3 2 2 2 3 . + 27 7 3 3 2 3 2 . + 28 5 3 5 2 6 . . + 29 4 3 3 3 4 . . + 30 3 5 3 . . . . + 31 3 9 . . . . . + 32 4 2 6 . . . . + 33 4 2 2 2 . . . + 34 4 2 2 3 . . . + 35 3 2 2 3 . . . + 36 3 3 3 . . . . + 37 3 3 3 . . . . + 38 4 3 3 . . . . + 39 2 3 3 . . . . + 40 2 1 . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/skid.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/skid.dat new file mode 100644 index 000000000..865c73b37 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/skid.dat @@ -0,0 +1,66 @@ +/* skid.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #21 from . +* Copyright (C) 2004 by Jan Wolter. Used by permission. +* +* Slippery Conditions +* +* created by Jan Wolter +* Apr 4, 2004 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 25; + +param n := 14; + +param row : 1 2 3 := + 1 9 . . + 2 1 1 . + 3 1 1 1 + 4 1 3 1 + 5 13 . . + 6 13 . . + 7 13 . . + 8 13 . . + 9 2 2 . + 10 2 2 . + 11 . . . + 12 2 2 . + 13 2 2 . + 14 2 2 . + 15 2 2 . + 16 2 2 . + 17 2 2 . + 18 2 2 . + 19 2 2 . + 20 2 2 . + 21 2 2 . + 22 2 2 . + 23 2 2 . + 24 2 2 . + 25 2 2 . +; + +param col : 1 2 3 4 5 := + 1 2 . . . . + 2 4 6 . . . + 3 9 4 4 2 . + 4 1 6 2 6 . + 5 1 5 2 . . + 6 1 6 . . . + 7 1 5 . . . + 8 1 4 . . . + 9 1 4 . . . + 10 1 4 2 . . + 11 1 4 6 . . + 12 1 6 4 4 2 + 13 9 2 6 . . + 14 4 2 . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/swing.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/swing.dat new file mode 100644 index 000000000..547e0dbd8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pbn/swing.dat @@ -0,0 +1,117 @@ +/* swing.dat */ + +/*********************************************************************** +* Web Paint-by-Number Puzzle #529 from . +* Copyright (C) 2006 by Jan Wolter. Used by permission. +* +* Swing +* +* created by Jan Wolter +* Sep 28, 2006 +* +* Encoded in GNU MathProg by Andrew Makhorin . +***********************************************************************/ + +data; + +param m := 45; + +param n := 45; + +param row : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := + 1 7 1 1 1 1 1 . . . . . . . . + 2 3 1 3 1 4 1 4 1 5 1 5 1 2 . + 3 1 1 1 3 1 4 1 4 1 5 1 5 1 2 + 4 2 1 2 1 1 1 1 6 2 . . . . . + 5 3 30 1 5 . . . . . . . . . . + 6 1 5 8 1 1 7 1 1 3 . . . . . + 7 3 4 8 1 5 1 2 . . . . . . . + 8 3 20 6 6 . . . . . . . . . . + 9 3 3 7 2 5 1 . . . . . . . . + 10 3 3 1 1 9 1 1 5 6 . . . . . + 11 2 3 8 1 3 4 2 . . . . . . . + 12 5 3 1 10 4 5 2 . . . . . . . + 13 1 2 3 8 4 6 . . . . . . . . + 14 2 2 3 11 10 . . . . . . . . . + 15 2 2 3 10 7 . . . . . . . . . + 16 2 3 1 7 12 2 . . . . . . . . + 17 2 3 1 4 11 2 . . . . . . . . + 18 4 1 2 1 11 2 . . . . . . . . + 19 9 1 2 9 . . . . . . . . . . + 20 6 2 1 4 11 . . . . . . . . . + 21 2 5 1 2 6 6 . . . . . . . . + 22 6 2 4 8 4 . . . . . . . . . + 23 4 2 16 1 . . . . . . . . . . + 24 2 2 15 2 . . . . . . . . . . + 25 3 2 15 4 . . . . . . . . . . + 26 3 3 13 4 . . . . . . . . . . + 27 4 12 9 . . . . . . . . . . . + 28 1 9 10 . . . . . . . . . . . + 29 2 1 17 7 2 . . . . . . . . . + 30 2 2 8 3 8 2 . . . . . . . . + 31 2 3 6 3 8 2 . . . . . . . . + 32 2 4 5 4 7 2 . . . . . . . . + 33 2 5 5 4 6 . . . . . . . . . + 34 4 4 5 4 9 . . . . . . . . . + 35 1 4 6 4 4 . . . . . . . . . + 36 4 3 6 4 3 2 . . . . . . . . + 37 2 1 2 7 4 4 2 . . . . . . . + 38 2 2 2 9 5 5 2 . . . . . . . + 39 2 2 2 10 6 6 . . . . . . . . + 40 3 2 1 9 18 . . . . . . . . . + 41 8 4 23 . . . . . . . . . . . + 42 1 2 1 2 2 1 1 1 2 . . . . . + 43 2 1 4 2 1 4 1 5 1 3 1 2 . . + 44 2 1 5 4 4 1 5 1 3 1 2 . . . + 45 1 10 1 1 1 . . . . . . . . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := + 1 7 1 1 1 1 1 . . . . . . . . + 2 2 2 4 1 4 1 5 1 4 1 4 1 2 . + 3 3 1 4 1 4 1 14 4 1 2 . . . . + 4 1 1 5 1 2 3 4 1 . . . . . . + 5 3 13 1 10 . . . . . . . . . . + 6 1 9 4 . . . . . . . . . . . + 7 6 7 2 2 . . . . . . . . . . + 8 8 4 1 4 . . . . . . . . . . + 9 2 8 3 2 5 3 . . . . . . . . + 10 10 1 3 7 2 . . . . . . . . . + 11 8 6 2 8 1 2 . . . . . . . . + 12 1 1 2 2 8 1 1 . . . . . . . + 13 2 1 1 1 2 1 3 1 3 3 1 . . . + 14 2 1 1 1 5 4 2 1 . . . . . . + 15 2 1 1 1 1 7 2 1 . . . . . . + 16 2 1 1 2 9 1 2 1 . . . . . . + 17 4 6 12 1 3 . . . . . . . . . + 18 16 13 3 2 . . . . . . . . . . + 19 12 21 2 . . . . . . . . . . . + 20 2 13 23 . . . . . . . . . . . + 21 2 14 19 . . . . . . . . . . . + 22 2 14 20 2 . . . . . . . . . . + 23 2 13 7 2 8 2 . . . . . . . . + 24 12 8 1 7 2 . . . . . . . . . + 25 5 1 1 1 2 8 1 5 2 . . . . . + 26 2 1 1 1 9 1 1 4 . . . . . . + 27 2 1 1 1 6 1 3 5 . . . . . . + 28 2 2 1 5 6 2 . . . . . . . . + 29 2 1 3 1 3 7 3 2 . . . . . . + 30 2 3 2 1 1 2 4 4 2 . . . . . + 31 2 2 1 1 2 3 1 8 2 . . . . . + 32 9 3 1 7 2 . . . . . . . . . + 33 12 4 1 6 2 . . . . . . . . . + 34 7 4 1 2 5 . . . . . . . . . + 35 2 6 6 5 6 . . . . . . . . . + 36 8 8 6 3 . . . . . . . . . . + 37 3 10 8 4 2 . . . . . . . . . + 38 5 11 9 5 2 . . . . . . . . . + 39 3 1 12 16 2 . . . . . . . . . + 40 3 1 12 16 . . . . . . . . . . + 41 5 2 13 21 . . . . . . . . . . + 42 6 1 3 3 1 1 . . . . . . . . + 43 5 1 3 1 3 1 1 2 1 4 1 3 1 3 + 44 5 1 3 1 3 1 4 1 4 1 3 1 3 . + 45 1 1 1 1 1 1 . . . . . . . . +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/pentomino.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/pentomino.mod new file mode 100644 index 000000000..56aca7e3b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/pentomino.mod @@ -0,0 +1,460 @@ +/* PENTOMINO, a geometric placement puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* A pentomino is a plane geometric figure by joining five equal + squares edge to edge. It is a polyomino with five cells. Pentominoes + were defined by Prof. Solomon W. Golomb in his book "Polyominoes: + Puzzles, Patterns, Problems, and Packings." + + There are twelve pentominoes, not counting rotations and reflections + as distinct: + + +---+ + | | + +---+ +---+ +---+ + | | | | | | + +---+---+ +---+ +---+ +---+ + | | | | | | | | | + +---+---+---+ +---+ +---+ +---+---+ + | | | | | | | | | | + +---+---+ +---+ +---+---+ +---+---+ + | | | | | | | | | + +---+ +---+ +---+---+ +---+ + F I L N + + +---+---+ +---+---+---+ +---+ + | | | | | | | | | + +---+---+ +---+---+---+ +---+ +---+ +---+ + | | | | | | | | | | | + +---+---+ +---+ +---+---+---+ +---+---+---+ + | | | | | | | | | | | | + +---+ +---+ +---+---+---+ +---+---+---+ + P T U V + + +---+ + | | + +---+ +---+ +---+---+ +---+---+ + | | | | | | | | | | + +---+---+ +---+---+---+ +---+---+ +---+---+ + | | | | | | | | | | | + +---+---+---+ +---+---+---+ +---+ +---+---+ + | | | | | | | | | | + +---+---+ +---+ +---+ +---+---+ + W X Y Z + + + A classic pentomino puzzle is to tile a given outline, i.e. cover + it without overlap and without gaps. Each of 12 pentominoes has an + area of 5 unit squares, so the outline must have area of 60 units. + Note that it is allowed to rotate and reflect the pentominoes. + + (From Wikipedia, the free encyclopedia.) */ + +set A; +check card(A) = 12; +/* basic set of pentominoes */ + +set B{a in A}; +/* B[a] is a set of distinct versions of pentomino a obtained by its + rotations and reflections */ + +set C := setof{a in A, b in B[a]} b; +check card(C) = 63; +/* set of distinct versions of all pentominoes */ + +set D{c in C}, within {0..4} cross {0..4}; +/* D[c] is a set of squares (i,j), relative to (0,0), that constitute + a distinct version of pentomino c */ + +param m, default 6; +/* number of rows in the outline */ + +param n, default 10; +/* number of columns in the outline */ + +set R, default {1..m} cross {1..n}; +/* set of squares (i,j), relative to (1,1), of the outline to be tiled + with the pentominoes */ + +check card(R) = 60; +/* the outline must have exactly 60 squares */ + +set S := setof{c in C, i in 1..m, j in 1..n: + forall{(ii,jj) in D[c]} ((i+ii,j+jj) in R)} (c,i,j); +/* set of all possible placements, where triplet (c,i,j) means that + the base square (0,0) of a distinct version of pentomino c is placed + at square (i,j) of the outline */ + +var x{(c,i,j) in S}, binary; +/* x[c,i,j] = 1 means that placement (c,i,j) is used in the tiling */ + +s.t. use{a in A}: sum{(c,i,j) in S: substr(c,1,1) = a} x[c,i,j] = 1; +/* every pentomino must be used exactly once */ + +s.t. cov{(i,j) in R}: + sum{(c,ii,jj) in S: (i-ii, j-jj) in D[c]} x[c,ii,jj] = 1; +/* every square of the outline must be covered exactly once */ + +/* this is a feasibility problem, so no objective is needed */ + +solve; + +for {i in 1..m} +{ for {j in 1..n} + { for {0..0: (i,j) in R} + { for {(c,ii,jj) in S: (i-ii,j-jj) in D[c] and x[c,ii,jj]} + printf " %s", substr(c,1,1); + } + for {0..0: (i,j) not in R} + printf " ."; + } + printf "\n"; +} + +data; + +/* These data correspond to a puzzle from the book "Pentominoes" by + Jon Millington */ + +param m := 8; + +param n := 15; + +set R : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := + 1 - - - - - - - + - - - - - - - + 2 - - - - - - + + + - - - - - - + 3 - - - - - + + + + + - - - - - + 4 - - - - + + + - + + + - - - - + 5 - - - + + + + - + + + + - - - + 6 - - + + + + + - + + + + + - - + 7 - + + + + + + - + + + + + + - + 8 + + + + + + + + + + + + + + + ; + +/* DO NOT CHANGE ANY DATA BELOW! */ + +set A := F, I, L, N, P, T, U, V, W, X, Y, Z; + +set B[F] := F1, F2, F3, F4, F5, F6, F7, F8; +set B[I] := I1, I2; +set B[L] := L1, L2, L3, L4, L5, L6, L7, L8; +set B[N] := N1, N2, N3, N4, N5, N6, N7, N8; +set B[P] := P1, P2, P3, P4, P5, P6, P7, P8; +set B[T] := T1, T2, T3, T4; +set B[U] := U1, U2, U3, U4; +set B[V] := V1, V2, V3, V4; +set B[W] := W1, W2, W3, W4; +set B[X] := X; +set B[Y] := Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8; +set B[Z] := Z1, Z2, Z3, Z4; + +set D[F1] : 0 1 2 := + 0 - + + + 1 + + - + 2 - + - ; + +set D[F2] : 0 1 2 := + 0 - + - + 1 + + + + 2 - - + ; + +set D[F3] : 0 1 2 := + 0 - + - + 1 - + + + 2 + + - ; + +set D[F4] : 0 1 2 := + 0 + - - + 1 + + + + 2 - + - ; + +set D[F5] : 0 1 2 := + 0 + + - + 1 - + + + 2 - + - ; + +set D[F6] : 0 1 2 := + 0 - - + + 1 + + + + 2 - + - ; + +set D[F7] : 0 1 2 := + 0 - + - + 1 + + - + 2 - + + ; + +set D[F8] : 0 1 2 := + 0 - + - + 1 + + + + 2 + - - ; + +set D[I1] : 0 := + 0 + + 1 + + 2 + + 3 + + 4 + ; + +set D[I2] : 0 1 2 3 4 := + 0 + + + + + ; + +set D[L1] : 0 1 := + 0 + - + 1 + - + 2 + - + 3 + + ; + +set D[L2] : 0 1 2 3 := + 0 + + + + + 1 + - - - ; + +set D[L3] : 0 1 := + 0 + + + 1 - + + 2 - + + 3 - + ; + +set D[L4] : 0 1 2 3 := + 0 - - - + + 1 + + + + ; + +set D[L5] : 0 1 := + 0 - + + 1 - + + 2 - + + 3 + + ; + +set D[L6] : 0 1 2 3 := + 0 + - - - + 1 + + + + ; + +set D[L7] : 0 1 := + 0 + + + 1 + - + 2 + - + 3 + - ; + +set D[L8] : 0 1 2 3 := + 0 + + + + + 1 - - - + ; + +set D[N1] : 0 1 := + 0 + - + 1 + - + 2 + + + 3 - + ; + +set D[N2] : 0 1 2 3 := + 0 - + + + + 1 + + - - ; + +set D[N3] : 0 1 := + 0 + - + 1 + + + 2 - + + 3 - + ; + +set D[N4] : 0 1 2 3 := + 0 - - + + + 1 + + + - ; + +set D[N5] : 0 1 := + 0 - + + 1 - + + 2 + + + 3 + - ; + +set D[N6] : 0 1 2 3 := + 0 + + - - + 1 - + + + ; + +set D[N7] : 0 1 := + 0 - + + 1 + + + 2 + - + 3 + - ; + +set D[N8] : 0 1 2 3 := + 0 + + + - + 1 - - + + ; + +set D[P1] : 0 1 := + 0 + + + 1 + + + 2 + - ; + +set D[P2] : 0 1 2 := + 0 + + + + 1 - + + ; + +set D[P3] : 0 1 := + 0 - + + 1 + + + 2 + + ; + +set D[P4] : 0 1 2 := + 0 + + - + 1 + + + ; + +set D[P5] : 0 1 := + 0 + + + 1 + + + 2 - + ; + +set D[P6] : 0 1 2 := + 0 - + + + 1 + + + ; + +set D[P7] : 0 1 := + 0 + - + 1 + + + 2 + + ; + +set D[P8] : 0 1 2 := + 0 + + + + 1 + + - ; + +set D[T1] : 0 1 2 := + 0 + + + + 1 - + - + 2 - + - ; + +set D[T2] : 0 1 2 := + 0 - - + + 1 + + + + 2 - - + ; + +set D[T3] : 0 1 2 := + 0 - + - + 1 - + - + 2 + + + ; + +set D[T4] : 0 1 2 := + 0 + - - + 1 + + + + 2 + - - ; + +set D[U1] : 0 1 2 := + 0 + - + + 1 + + + ; + +set D[U2] : 0 1 := + 0 + + + 1 + - + 2 + + ; + +set D[U3] : 0 1 2 := + 0 + + + + 1 + - + ; + +set D[U4] : 0 1 := + 0 + + + 1 - + + 2 + + ; + +set D[V1] : 0 1 2 := + 0 - - + + 1 - - + + 2 + + + ; + +set D[V2] : 0 1 2 := + 0 + - - + 1 + - - + 2 + + + ; + +set D[V3] : 0 1 2 := + 0 + + + + 1 + - - + 2 + - - ; + +set D[V4] : 0 1 2 := + 0 + + + + 1 - - + + 2 - - + ; + +set D[W1] : 0 1 2 := + 0 - - + + 1 - + + + 2 + + - ; + +set D[W2] : 0 1 2 := + 0 + - - + 1 + + - + 2 - + + ; + +set D[W3] : 0 1 2 := + 0 - + + + 1 + + - + 2 + - - ; + +set D[W4] : 0 1 2 := + 0 + + - + 1 - + + + 2 - - + ; + +set D[X] : 0 1 2 := + 0 - + - + 1 + + + + 2 - + - ; + +set D[Y1] : 0 1 := + 0 + - + 1 + - + 2 + + + 3 + - ; + +set D[Y2] : 0 1 2 3 := + 0 + + + + + 1 - + - - ; + +set D[Y3] : 0 1 := + 0 - + + 1 + + + 2 - + + 3 - + ; + +set D[Y4] : 0 1 2 3 := + 0 - - + - + 1 + + + + ; + +set D[Y5] : 0 1 := + 0 - + + 1 - + + 2 + + + 3 - + ; + +set D[Y6] : 0 1 2 3 := + 0 - + - - + 1 + + + + ; + +set D[Y7] : 0 1 := + 0 + - + 1 + + + 2 + - + 3 + - ; + +set D[Y8] : 0 1 2 3 := + 0 + + + + + 1 - - + - ; + +set D[Z1] : 0 1 2 := + 0 - + + + 1 - + - + 2 + + - ; + +set D[Z2] : 0 1 2 := + 0 + - - + 1 + + + + 2 - - + ; + +set D[Z3] : 0 1 2 := + 0 + + - + 1 - + - + 2 - + + ; + +set D[Z4] : 0 1 2 := + 0 - - + + 1 + + + + 2 + - - ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/plan.lp b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.lp new file mode 100644 index 000000000..cab649449 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.lp @@ -0,0 +1,39 @@ +\* plan.lp *\ + +Minimize + value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + + .21 alum + .38 silicon + +Subject To + yield: bin1 + bin2 + bin3 + bin4 + bin5 + + alum + silicon = 2000 + + fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + + .01 alum + .03 silicon <= 60 + + cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + + .01 alum <= 100 + + mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 + + mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 + + al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + + .97 alum >= 1500 + + si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon >= 250 + + si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + + .01 alum + .97 silicon <= 300 + +Bounds + bin1 <= 200 + bin2 <= 2500 + 400 <= bin3 <= 800 + 100 <= bin4 <= 700 + bin5 <= 1500 + +End + +\* eof *\ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mod new file mode 100644 index 000000000..effe8383c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mod @@ -0,0 +1,39 @@ +/* plan.mod */ + +var bin1, >= 0, <= 200; +var bin2, >= 0, <= 2500; +var bin3, >= 400, <= 800; +var bin4, >= 100, <= 700; +var bin5, >= 0, <= 1500; +var alum, >= 0; +var silicon, >= 0; + +minimize + +value: .03 * bin1 + .08 * bin2 + .17 * bin3 + .12 * bin4 + .15 * bin5 + + .21 * alum + .38 * silicon; + +subject to + +yield: bin1 + bin2 + bin3 + bin4 + bin5 + alum + silicon = 2000; + +fe: .15 * bin1 + .04 * bin2 + .02 * bin3 + .04 * bin4 + .02 * bin5 + + .01 * alum + .03 * silicon <= 60; + +cu: .03 * bin1 + .05 * bin2 + .08 * bin3 + .02 * bin4 + .06 * bin5 + + .01 * alum <= 100; + +mn: .02 * bin1 + .04 * bin2 + .01 * bin3 + .02 * bin4 + .02 * bin5 + <= 40; + +mg: .02 * bin1 + .03 * bin2 + .01 * bin5 <= 30; + +al: .70 * bin1 + .75 * bin2 + .80 * bin3 + .75 * bin4 + .80 * bin5 + + .97 * alum >= 1500; + +si: 250 <= .02 * bin1 + .06 * bin2 + .08 * bin3 + .12 * bin4 + + .02 * bin5 + .01 * alum + .97 * silicon <= 300; + +end; + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mps new file mode 100644 index 000000000..b6bb09458 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/plan.mps @@ -0,0 +1,54 @@ +*000000001111111111222222222233333333334444444444555555555566 +*234567890123456789012345678901234567890123456789012345678901 +NAME PLAN +ROWS + N VALUE + E YIELD + L FE + L CU + L MN + L MG + G AL + L SI +COLUMNS + BIN1 VALUE .03000 YIELD 1.00000 + FE .15000 CU .03000 + MN .02000 MG .02000 + AL .70000 SI .02000 + BIN2 VALUE .08000 YIELD 1.00000 + FE .04000 CU .05000 + MN .04000 MG .03000 + AL .75000 SI .06000 + BIN3 VALUE .17000 YIELD 1.00000 + FE .02000 CU .08000 + MN .01000 AL .80000 + SI .08000 + BIN4 VALUE .12000 YIELD 1.00000 + FE .04000 CU .02000 + MN .02000 AL .75000 + SI .12000 + BIN5 VALUE .15000 YIELD 1.00000 + FE .02000 CU .06000 + MN .02000 MG .01000 + AL .80000 SI .02000 + ALUM VALUE .21000 YIELD 1.00000 + FE .01000 CU .01000 + AL .97000 SI .01000 + SILICON VALUE .38000 YIELD 1.00000 + FE .03000 SI .97000 +RHS + RHS1 YIELD 2000.00000 FE 60.00000 + CU 100.00000 MN 40.00000 + SI 300.00000 + MG 30.00000 AL 1500.00000 +RANGES + RNG1 SI 50.00000 +BOUNDS + UP BND1 BIN1 200.00000 + UP BIN2 2500.00000 + LO BIN3 400.00000 + UP BIN3 800.00000 + LO BIN4 100.00000 + UP BIN4 700.00000 + UP BIN5 1500.00000 +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/planarity.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/planarity.mod new file mode 100644 index 000000000..28d608e42 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/planarity.mod @@ -0,0 +1,109 @@ +/* PLANARITY, Graph Planarity Testing */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Given a graph G = (V, E), where V is a set of vertices and E is + a set of edges (unordered pairs of vertices), this model tests if + G is planar, and if it is, finds its faces for some embedding. + It is assumed that G is loopless and the degree of any its vertex + is at least 2. + + Though there exist linear-time algorithms to test graph planarity, + this MIP feasibility model may be used, for example, to find + an embedding subject to some additional constraints or an "optimal" + embedding. + + This model is based on Mac Lane's planarity characterization that + states that a finite undirected graph is planar iff the cycle space + of the graph (in GF(2)) has a cycle basis in which each edge of the + graph participates in at most two basis vectors. */ + +param nv; +/* number of vertices */ + +set V := 1..nv; +/* set of vertices */ + +set E, within V cross V; +/* set of edges */ + +check{(i,j) in E} i <> j; +/* graph must have no loops */ + +set A := E union setof{(i,j) in E} (j,i); +/* set of arcs, where every edge (i,j) gives two arcs i->j and j->i */ + +check{i in V} sum{(i,j) in A} 1 >= 2; +/* degree of any vertex must be at least 2 */ + +param nf := 2 - nv + card(E); +/* number of faces (including outer face) */ + +set F := 1..nf; +/* set of faces = set of vertices of dual graph */ + +/* Let every face be assigned a unique color. Below we say that arc + i->j has color f if on moving from vertex i to vertex j face f is + located on the left to that arc. (Note that every face is defined + by a cycle mentioned in Mac Lane's characterization. In this model + cycles are constructed explicitly from arcs.) */ + +var x{(i,j) in A, f in F}, binary; +/* x[i,j,f] = 1 means that arc i->j has color f */ + +s.t. r1{(i,j) in A}: sum{f in F} x[i,j,f] = 1; +/* every arc must have exactly one color */ + +s.t. r2{j in V, f in F}: sum{(i,j) in A} x[i,j,f] <= 1; +/* two or more arcs of the same color must not enter the same vertex */ + +s.t. r3{j in V, f in F}: + sum{(i,j) in A} x[i,j,f] = sum{(j,i) in A} x[j,i,f]; +/* if arc of color f enters some vertex, exactly one arc of the same + color must leave that vertex */ + +s.t. r4{(i,j) in E, f in F}: x[i,j,f] + x[j,i,f] <= 1; +/* arcs that correspond to the same edge must have different colors + (to avoid invalid faces i->j->i) */ + +s.t. r5{f in F}: sum{(i,j) in A} x[i,j,f] >= 1; +/* every color must be used at least once */ + +/* this is a feasibility problem, so no objective is needed */ + +solve; + +printf "number of vertices = %d\n", nv; +printf "number of edges = %d\n", card(A) / 2; +printf "number of faces = %d\n", nf; + +for {f in F} +{ printf "face %d:", f; + printf {(i,j) in A: x[i,j,f] = 1} " %d->%d", i, j; + printf "\n"; +} + +data; + +/* The data below correspond to the following (planar) graph: + + 1 - 2 - - 3 - - 4 + | | | + | | | + 5 - 6 | | + | \ | | + | \ | | + 7 - - - - 8 - - 9 - - - - 10- - -11 + | / | \ | | + | / | \ | | + | / | \ | | + | / | \ | | + 12 - - - -13 - - - - - - - 14- - -15 */ + +param nv := 15; + +set E := (1,2) (1,5) (2,3) (3,4) (3,8) (4,9) (5,6) (5,7) (6,8) + (7,8) (7,12) (8,9) (8,12) (8,13) (9,10) (9,14) (10,11) + (10,14) (11,15) (12,13) (13,14) (14,15) ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/powpl25h.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/powpl25h.mod new file mode 100644 index 000000000..bdeefb9c3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/powpl25h.mod @@ -0,0 +1,203 @@ +/* Power plant LP scheduler, example data with 25hrs for daylightsavings */ + +/* Implemented, inspected, written and converted to GNU MathProg + by NASZVADI, Peter, 199x-2017 */ + +/* + Fast electric power plant scheduler implementation based on new + results in author's Thesis. + + The base problem is: + * given some power plants + * a short time scale partitioned to equidistant intervals + * the task is to yielding the cheapest schedule for the plants + * the daily demand forecast is usually accurate and part of the input + + The power plants has technical limitations: + * upper and lower bounds of produced energy + * and also a gradient barrier in both directions + (can depend on time, but this GMPL implementation is simplified) + * Also units with same properties (technical and price) should be + scheduled together usually with near same performance values + * Assumed a simplified network topology, which is contractive, so + keeping Kirchhoff's laws is a necessary constraint too + * All solutions must be integer + + The LP relaxation is equivalent with the MIP problem due to the + model's matrix interesting property: it is Totally Unimodular + (proven in 2004 by author) and also a Network Matrix (2006, + presented at OTDK 2016, Szeged, Hungary) so: + * it is strictly polynomial if it is solved by most simplex algs + * all base solutions become integer if the RHS vector is integer + (it is in real life, so this is an acceptable assumption) + * The transposed matrix is NOT a Network Matrix in most cases! + + However, adding several other constraints easily turns the problem + to be NP-hard, which is also pinpointed and discussed in the Thesis. + + See more about electric power plants' scheduling in the + author's Thesis (in Hungarian): + http://www.cs.elte.hu/matdiploma/vuk.pdf + + It is possible to run with custom parameters, what is needed + to define is: + * TIME set (daylightsaving cases or other than hour intervals) + * PLANTS set (the 'Demand' is mandatory and usually negative) + * PRICE parameter (can be negative if energy is sold to a consumer) + * BOUND parameter (technical bounds) + * MAXGRAD parameter (technical bounds) + + Then generate a pretty-printed solution by typing: + glpsol --math powpl25h.mod +*/ + +set TIME, default { + '00:00', '01:00', '02:00', '03:00', '04:00', + '05:00', '06:00', '07:00', '08:00', '09:00', + '10:00', '11:00', '12:00', '13:00', '14:00', + '15:00', '16:00', '17:00', '18:00', '19:00', + '20:00', '21:00', '22:00', '23:00', '24:00' +}; +/* Time labels, assumed natural ordering. daylightsaving's bias + can be inserted p.ex. in Central Europe like: + ... '01:00', '02:00', '02:00b', '03:00', ... */ + +set TADJ := setof{(r, s) in TIME cross TIME: r < s}(r, s) diff + setof{(t, u, v) in TIME cross TIME cross TIME: t < u and u < v}(t, v); +/* Tricky adjacent time label generator because GMPL lacks order determination + of set elements (except intervals composed of equidistant numbers) */ + +set PLANTS, default {'Demand'}; +/* Demand is a promoted, mandatory one, usually filled + with negative MW values in data section */ + +set DIRECTION, default {'Up', 'Down'}; +/* All possible directions of gradients, do not touch */ + +param MAXINT, default 10000; +/* A "macro" for bounding absolute value of all used numbers + and used as default value */ + +param PRICE{PLANTS}, default MAXINT; +/* Should be specified in data section, self-explanatory. + can be negative if there are energy buyers */ + +param BOUND{(p, t, d) in PLANTS cross TIME cross DIRECTION}, + default if t = '00:00' then if d = 'Down' then BOUND[p, t, 'Up'] else 0 else + if p <> 'Demand' or d = 'Up' then sum{(u, v) in TADJ: v = t} BOUND[p, u, d] + else BOUND[p, t, 'Up']; +/* Obvious, technical bounds of each power plant unit (real or virtual like + 'Demand'). If some parts are not given in data section, calculated + from preceeding values. Also for time '00:00', its 'Down' values by + default are the same as denoted with 'Up' */ + +param MAXGRAD{(p, d) in PLANTS cross DIRECTION}, default MAXINT; +/* Usually nonnegative integer, might differ in distinct directions per unit + in the cited thesis, it is allowed to gradient bounds to depend on time, + but this is a simplified model */ + +var x{(t, p) in TIME cross PLANTS}, <= BOUND[p, t, 'Up'], >= BOUND[p, t, 'Down']; +/* The schedule, dimension is MW */ + +s.t. kirchhoff{t in TIME: t <> '00:00'}: sum{p in PLANTS} x[t, p] = 0; +/* Conservative property */ + +s.t. gradient{(p, t, u) in PLANTS cross TADJ}: + -MAXGRAD[p, 'Down'] <= x[t, p] - x[u, p] <= MAXGRAD[p, 'Up']; +/* Technical limitations, each unit usually cannot change performance + arbitrarily in a short time, so limited in both directions per time unit*/ + +minimize obj: sum{(t, p) in TIME cross PLANTS}(x[t, p] * PRICE[p]); +/* The objective is the cost of the schedule */ + +solve; + +/* Pretty print solution in table */ + +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; +printf '|%7s |', ' '; +for{p in PLANTS}{ + printf ' % 6s |', p; +} +printf '\n'; +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; +for{t in TIME}{ + printf '|%7s |', t; + for{p in PLANTS}{ + printf ' % 6s |', x[t, p].val; + } + printf '\n'; +} +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; + +data; + +set TIME := + '00:00', '01:00', '02:00', '02:00b', '03:00', '04:00', + '05:00', '06:00', '07:00', '08:00', '09:00', + '10:00', '11:00', '12:00', '13:00', '14:00', + '15:00', '16:00', '17:00', '18:00', '19:00', + '20:00', '21:00', '22:00', '23:00', '24:00'; + +/* + Generated random default values and names, the demand is the sum of + 2 sinewaves. + Also specified a treshold for nuclear plants from 15:00 till 19:00 + The sun is shining only morning and in the afternoon: 07:00-18:00, so + solar plant cannot produce electric energy after sunset. + + Only touch this section, or export it to a data file! +*/ + +set PLANTS 'Demand', 'Atom1', 'Atom2', 'Coal', 'Gas1', 'Gas2', 'Green', 'Oil', 'Solar', 'Dam'; + +param PRICE := + 'Demand' 0 + 'Atom1' 2 + 'Atom2' 2 + 'Coal' 15.6 + 'Gas1' 12 + 'Gas2' 11.5 + 'Green' 8.8 + 'Oil' 23.3 + 'Solar' 7.6 + 'Dam' 3; +/* price per MW */ + +param BOUND := + [*, *, 'Up'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + '00:00' 240 240 100 150 150 20 90 0 20 + '01:00' 240 240 155 192 208 35 230 0 20 + [*, *, 'Up'] (tr): 'Atom1' 'Atom2' := + '15:00' 200 200 + '19:00' 235 235 + [*, *, 'Up'] (tr): 'Solar' := + '07:00' 20 + '18:00' 0 + [*, *, 'Down'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + '01:00' 100 100 50 62 68 0 75 0 20 + [*, *, 'Up'] : '01:00' '02:00' '02:00b' '03:00' '04:00' '05:00' '06:00' '07:00' '08:00' := + 'Demand' -868 -851 -842 -837 -791 -887 -912 -1046 -1155 + [*, *, 'Up'] : '09:00' '10:00' '11:00' '12:00' '13:00' '14:00' '15:00' '16:00' := + 'Demand' -945 -873 -797 -990 -1241 -1134 -815 -782 + [*, *, 'Up'] : '17:00' '18:00' '19:00' '20:00' '21:00' '22:00' '23:00' '24:00' := + 'Demand' -772 -827 -931 -1105 -1215 -1249 -1183 -952; + +param MAXGRAD (tr) + : 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + 'Up' 30 30 35 89 95 5 56 2 4 + 'Down' 30 30 45 96 102 5 56 2 4; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/powplant.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/powplant.mod new file mode 100644 index 000000000..3b5d73e32 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/powplant.mod @@ -0,0 +1,200 @@ +/* Power plant LP scheduler */ + +/* Implemented, inspected, written and converted to GNU MathProg + by NASZVADI, Peter, 199x-2017 */ + +/* + Fast electric power plant scheduler implementation based on new + results in author's Thesis. + + The base problem is: + * given some power plants + * a short time scale partitioned to equidistant intervals + * the task is to yielding the cheapest schedule for the plants + * the daily demand forecast is usually accurate and part of the input + + The power plants has technical limitations: + * upper and lower bounds of produced energy + * and also a gradient barrier in both directions + (can depend on time, but this GMPL implementation is simplified) + * Also units with same properties (technical and price) should be + scheduled together usually with near same performance values + * Assumed a simplified network topology, which is contractive, so + keeping Kirchhoff's laws is a necessary constraint too + * All solutions must be integer + + The LP relaxation is equivalent with the MIP problem due to the + model's matrix interesting property: it is Totally Unimodular + (proven in 2004 by author) and also a Network Matrix (2006, + presented at OTDK 2016, Szeged, Hungary) so: + * it is strictly polynomial if it is solved by most simplex algs + * all base solutions become integer if the RHS vector is integer + (it is in real life, so this is an acceptable assumption) + * The transposed matrix is NOT a Network Matrix in most cases! + + However, adding several other constraints easily turns the problem + to be NP-hard, which is also pinpointed and discussed in the Thesis. + + See more about electric power plants' scheduling in the + author's Thesis (in Hungarian): + http://www.cs.elte.hu/matdiploma/vuk.pdf + + It is possible to run with custom parameters, what is needed + to define is: + * TIME set (daylightsaving cases or other than hour intervals) + * PLANTS set (the 'Demand' is mandatory and usually negative) + * PRICE parameter (can be negative if energy is sold to a consumer) + * BOUND parameter (technical bounds) + * MAXGRAD parameter (technical bounds) + + Then generate a pretty-printed solution by typing: + glpsol --math powplant.mod [--data NEW_DATA.dat] + + where "NEW_DATA.dat" should contain the above 5 structures filled + with custom data. Square brackets shoudn't be entered, and specifying + custom data file is optional. +*/ + +set TIME, default { + '00:00', '01:00', '02:00', '03:00', '04:00', + '05:00', '06:00', '07:00', '08:00', '09:00', + '10:00', '11:00', '12:00', '13:00', '14:00', + '15:00', '16:00', '17:00', '18:00', '19:00', + '20:00', '21:00', '22:00', '23:00', '24:00' +}; +/* Time labels, assumed natural ordering. daylightsaving's bias + can be inserted p.ex. in Central Europe like: + ... '01:00', '02:00', '02:00b', '03:00', ... */ + +set TADJ := setof{(r, s) in TIME cross TIME: r < s}(r, s) diff + setof{(t, u, v) in TIME cross TIME cross TIME: t < u and u < v}(t, v); +/* Tricky adjacent time label generator because GMPL lacks order determination + of set elements (except intervals composed of equidistant numbers) */ + +set PLANTS, default {'Demand'}; +/* Demand is a promoted, mandatory one, usually filled + with negative MW values in data section */ + +set DIRECTION, default {'Up', 'Down'}; +/* All possible directions of gradients, do not touch */ + +param MAXINT, default 10000; +/* A "macro" for bounding absolute value of all used numbers + and used as default value */ + +param PRICE{PLANTS}, default MAXINT; +/* Should be specified in data section, self-explanatory. + can be negative if there are energy buyers */ + +param BOUND{(p, t, d) in PLANTS cross TIME cross DIRECTION}, + default if t = '00:00' then if d = 'Down' then BOUND[p, t, 'Up'] else 0 else + if p <> 'Demand' or d = 'Up' then sum{(u, v) in TADJ: v = t} BOUND[p, u, d] + else BOUND[p, t, 'Up']; +/* Obvious, technical bounds of each power plant unit (real or virtual like + 'Demand'). If some parts are not given in data section, calculated + from preceeding values. Also for time '00:00', its 'Down' values by + default are the same as denoted with 'Up' */ + +param MAXGRAD{(p, d) in PLANTS cross DIRECTION}, default MAXINT; +/* Usually nonnegative integer, might differ in distinct directions per unit + in the cited thesis, it is allowed to gradient bounds to depend on time, + but this is a simplified model */ + +var x{(t, p) in TIME cross PLANTS}, <= BOUND[p, t, 'Up'], >= BOUND[p, t, 'Down']; +/* The schedule, dimension is MW */ + +s.t. kirchhoff{t in TIME: t <> '00:00'}: sum{p in PLANTS} x[t, p] = 0; +/* Conservative property */ + +s.t. gradient{(p, t, u) in PLANTS cross TADJ}: + -MAXGRAD[p, 'Down'] <= x[t, p] - x[u, p] <= MAXGRAD[p, 'Up']; +/* Technical limitations, each unit usually cannot change performance + arbitrarily in a short time, so limited in both directions per time unit*/ + +minimize obj: sum{(t, p) in TIME cross PLANTS}(x[t, p] * PRICE[p]); +/* The objective is the cost of the schedule */ + +solve; + +/* Pretty print solution in table */ + +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; +printf '|%7s |', ' '; +for{p in PLANTS}{ + printf ' % 6s |', p; +} +printf '\n'; +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; +for{t in TIME}{ + printf '|%7s |', t; + for{p in PLANTS}{ + printf ' % 6s |', x[t, p].val; + } + printf '\n'; +} +printf '+--------+'; +for{p in PLANTS}{ + printf '-% 6s-+', '------'; +} +printf '\n'; + +data; + +/* + Generated random default values and names, the demand is the sum of + 2 sinewaves. + Also specified a treshold for nuclear plants from 15:00 till 19:00 + The sun is shining only morning and in the afternoon: 07:00-18:00, so + solar plant cannot produce electric energy after sunset. + + Only touch this section, or export it to a data file! +*/ + +set PLANTS 'Demand', 'Atom1', 'Atom2', 'Coal', 'Gas1', 'Gas2', 'Green', 'Oil', 'Solar', 'Dam'; + +param PRICE := + 'Demand' 0 + 'Atom1' 2 + 'Atom2' 2 + 'Coal' 15.6 + 'Gas1' 12 + 'Gas2' 11.5 + 'Green' 8.8 + 'Oil' 23.3 + 'Solar' 7.6 + 'Dam' 3; +/* price per MW */ + +param BOUND := + [*, *, 'Up'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + '00:00' 240 240 100 150 150 20 90 0 20 + '01:00' 240 240 155 192 208 35 230 0 20 + [*, *, 'Up'] (tr): 'Atom1' 'Atom2' := + '15:00' 200 200 + '19:00' 235 235 + [*, *, 'Up'] (tr): 'Solar' := + '07:00' 20 + '18:00' 0 + [*, *, 'Down'] (tr): 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + '01:00' 100 100 50 62 68 0 75 0 20 + [*, *, 'Up'] : '01:00' '02:00' '03:00' '04:00' '05:00' '06:00' '07:00' '08:00' := + 'Demand' -868 -851 -837 -791 -887 -912 -1046 -1155 + [*, *, 'Up'] : '09:00' '10:00' '11:00' '12:00' '13:00' '14:00' '15:00' '16:00' := + 'Demand' -945 -873 -797 -990 -1241 -1134 -815 -782 + [*, *, 'Up'] : '17:00' '18:00' '19:00' '20:00' '21:00' '22:00' '23:00' '24:00' := + 'Demand' -772 -827 -931 -1105 -1215 -1249 -1183 -952; + +param MAXGRAD (tr) + : 'Atom1' 'Atom2' 'Coal' 'Gas1' 'Gas2' 'Green' 'Oil' 'Solar' 'Dam' := + 'Up' 30 30 35 89 95 5 56 2 4 + 'Down' 30 30 45 96 102 5 56 2 4; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/prod.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/prod.mod new file mode 100644 index 000000000..aa793f76e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/prod.mod @@ -0,0 +1,331 @@ +# PROD, a multiperiod production model +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### PRODUCTION SETS AND PARAMETERS ### + +set prd 'products'; # Members of the product group + +param pt 'production time' {prd} > 0; + + # Crew-hours to produce 1000 units + +param pc 'production cost' {prd} > 0; + + # Nominal production cost per 1000, used + # to compute inventory and shortage costs + +### TIME PERIOD SETS AND PARAMETERS ### + +param first > 0 integer; + # Index of first production period to be modeled + +param last > first integer; + + # Index of last production period to be modeled + +set time 'planning horizon' := first..last; + +### EMPLOYMENT PARAMETERS ### + +param cs 'crew size' > 0 integer; + + # Workers per crew + +param sl 'shift length' > 0; + + # Regular-time hours per shift + +param rtr 'regular time rate' > 0; + + # Wage per hour for regular-time labor + +param otr 'overtime rate' > rtr; + + # Wage per hour for overtime labor + +param iw 'initial workforce' >= 0 integer; + + # Crews employed at start of first period + +param dpp 'days per period' {time} > 0; + + # Regular working days in a production period + +param ol 'overtime limit' {time} >= 0; + + # Maximum crew-hours of overtime in a period + +param cmin 'crew minimum' {time} >= 0; + + # Lower limit on average employment in a period + +param cmax 'crew maximum' {t in time} >= cmin[t]; + + # Upper limit on average employment in a period + +param hc 'hiring cost' {time} >= 0; + + # Penalty cost of hiring a crew + +param lc 'layoff cost' {time} >= 0; + + # Penalty cost of laying off a crew + +### DEMAND PARAMETERS ### + +param dem 'demand' {prd,first..last+1} >= 0; + + # Requirements (in 1000s) + # to be met from current production and inventory + +param pro 'promoted' {prd,first..last+1} logical; + + # true if product will be the subject + # of a special promotion in the period + +### INVENTORY AND SHORTAGE PARAMETERS ### + +param rir 'regular inventory ratio' >= 0; + + # Proportion of non-promoted demand + # that must be in inventory the previous period + +param pir 'promotional inventory ratio' >= 0; + + # Proportion of promoted demand + # that must be in inventory the previous period + +param life 'inventory lifetime' > 0 integer; + + # Upper limit on number of periods that + # any product may sit in inventory + +param cri 'inventory cost ratio' {prd} > 0; + + # Inventory cost per 1000 units is + # cri times nominal production cost + +param crs 'shortage cost ratio' {prd} > 0; + + # Shortage cost per 1000 units is + # crs times nominal production cost + +param iinv 'initial inventory' {prd} >= 0; + + # Inventory at start of first period; age unknown + +param iil 'initial inventory left' {p in prd, t in time} + := iinv[p] less sum {v in first..t} dem[p,v]; + + # Initial inventory still available for allocation + # at end of period t + +param minv 'minimum inventory' {p in prd, t in time} + := dem[p,t+1] * (if pro[p,t+1] then pir else rir); + + # Lower limit on inventory at end of period t + +### VARIABLES ### + +var Crews{first-1..last} >= 0; + + # Average number of crews employed in each period + +var Hire{time} >= 0; # Crews hired from previous to current period + +var Layoff{time} >= 0; # Crews laid off from previous to current period + +var Rprd 'regular production' {prd,time} >= 0; + + # Production using regular-time labor, in 1000s + +var Oprd 'overtime production' {prd,time} >= 0; + + # Production using overtime labor, in 1000s + +var Inv 'inventory' {prd,time,1..life} >= 0; + + # Inv[p,t,a] is the amount of product p that is + # a periods old -- produced in period (t+1)-a -- + # and still in storage at the end of period t + +var Short 'shortage' {prd,time} >= 0; + + # Accumulated unsatisfied demand at the end of period t + +### OBJECTIVE ### + +minimize cost: + + sum {t in time} rtr * sl * dpp[t] * cs * Crews[t] + + sum {t in time} hc[t] * Hire[t] + + sum {t in time} lc[t] * Layoff[t] + + sum {t in time, p in prd} otr * cs * pt[p] * Oprd[p,t] + + sum {t in time, p in prd, a in 1..life} cri[p] * pc[p] * Inv[p,t,a] + + sum {t in time, p in prd} crs[p] * pc[p] * Short[p,t]; + + # Full regular wages for all crews employed, plus + # penalties for hiring and layoffs, plus + # wages for any overtime worked, plus + # inventory and shortage costs + + # (All other production costs are assumed + # to depend on initial inventory and on demands, + # and so are not included explicitly.) + +### CONSTRAINTS ### + +rlim 'regular-time limit' {t in time}: + + sum {p in prd} pt[p] * Rprd[p,t] <= sl * dpp[t] * Crews[t]; + + # Hours needed to accomplish all regular-time + # production in a period must not exceed + # hours available on all shifts + +olim 'overtime limit' {t in time}: + + sum {p in prd} pt[p] * Oprd[p,t] <= ol[t]; + + # Hours needed to accomplish all overtime + # production in a period must not exceed + # the specified overtime limit + +empl0 'initial crew level': Crews[first-1] = iw; + + # Use given initial workforce + +empl 'crew levels' {t in time}: Crews[t] = Crews[t-1] + Hire[t] - Layoff[t]; + + # Workforce changes by hiring or layoffs + +emplbnd 'crew limits' {t in time}: cmin[t] <= Crews[t] <= cmax[t]; + + # Workforce must remain within specified bounds + +dreq1 'first demand requirement' {p in prd}: + + Rprd[p,first] + Oprd[p,first] + Short[p,first] + - Inv[p,first,1] = dem[p,first] less iinv[p]; + +dreq 'demand requirements' {p in prd, t in first+1..last}: + + Rprd[p,t] + Oprd[p,t] + Short[p,t] - Short[p,t-1] + + sum {a in 1..life} (Inv[p,t-1,a] - Inv[p,t,a]) + = dem[p,t] less iil[p,t-1]; + + # Production plus increase in shortage plus + # decrease in inventory must equal demand + +ireq 'inventory requirements' {p in prd, t in time}: + + sum {a in 1..life} Inv[p,t,a] + iil[p,t] >= minv[p,t]; + + # Inventory in storage at end of period t + # must meet specified minimum + +izero 'impossible inventories' {p in prd, v in 1..life-1, a in v+1..life}: + + Inv[p,first+v-1,a] = 0; + + # In the vth period (starting from first) + # no inventory may be more than v periods old + # (initial inventories are handled separately) + +ilim1 'new-inventory limits' {p in prd, t in time}: + + Inv[p,t,1] <= Rprd[p,t] + Oprd[p,t]; + + # New inventory cannot exceed + # production in the most recent period + +ilim 'inventory limits' {p in prd, t in first+1..last, a in 2..life}: + + Inv[p,t,a] <= Inv[p,t-1,a-1]; + + # Inventory left from period (t+1)-p + # can only decrease as time goes on + +### DATA ### + +data; + +set prd := 18REG 24REG 24PRO ; + +param first := 1 ; +param last := 13 ; +param life := 2 ; + +param cs := 18 ; +param sl := 8 ; +param iw := 8 ; + +param rtr := 16.00 ; +param otr := 43.85 ; +param rir := 0.75 ; +param pir := 0.80 ; + +param : pt pc cri crs iinv := + + 18REG 1.194 2304. 0.015 1.100 82.0 + 24REG 1.509 2920. 0.015 1.100 792.2 + 24PRO 1.509 2910. 0.015 1.100 0.0 ; + +param : dpp ol cmin cmax hc lc := + + 1 19.5 96.0 0.0 8.0 7500 7500 + 2 19.0 96.0 0.0 8.0 7500 7500 + 3 20.0 96.0 0.0 8.0 7500 7500 + 4 19.0 96.0 0.0 8.0 7500 7500 + 5 19.5 96.0 0.0 8.0 15000 15000 + 6 19.0 96.0 0.0 8.0 15000 15000 + 7 19.0 96.0 0.0 8.0 15000 15000 + 8 20.0 96.0 0.0 8.0 15000 15000 + 9 19.0 96.0 0.0 8.0 15000 15000 + 10 20.0 96.0 0.0 8.0 15000 15000 + 11 20.0 96.0 0.0 8.0 7500 7500 + 12 18.0 96.0 0.0 8.0 7500 7500 + 13 18.0 96.0 0.0 8.0 7500 7500 ; + +param dem (tr) : + + 18REG 24REG 24PRO := + + 1 63.8 1212.0 0.0 + 2 76.0 306.2 0.0 + 3 88.4 319.0 0.0 + 4 913.8 208.4 0.0 + 5 115.0 298.0 0.0 + 6 133.8 328.2 0.0 + 7 79.6 959.6 0.0 + 8 111.0 257.6 0.0 + 9 121.6 335.6 0.0 + 10 470.0 118.0 1102.0 + 11 78.4 284.8 0.0 + 12 99.4 970.0 0.0 + 13 140.4 343.8 0.0 + 14 63.8 1212.0 0.0 ; + +param pro (tr) : + + 18REG 24REG 24PRO := + + 1 0 1 0 + 2 0 0 0 + 3 0 0 0 + 4 1 0 0 + 5 0 0 0 + 6 0 0 0 + 7 0 1 0 + 8 0 0 0 + 9 0 0 0 + 10 1 0 1 + 11 0 0 0 + 12 0 0 0 + 13 0 1 0 + 14 0 1 0 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/qfit.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/qfit.mod new file mode 100644 index 000000000..f168c4b52 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/qfit.mod @@ -0,0 +1,49 @@ +/*Quadratic Curve Fitting Solution + + Find a plausable quadratic fit to a sample of points + + Nigel_Galloway@operamail.com + February 1st., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var a; +var b; +var c; + +equalz1 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z]*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]*Sx[z]; +equalz2 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +equalz3 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] + sum{z in Sample} c = sum{z in Sample} Sy[z]; + +solve; + +printf "\nbest quadratic fit is:\n\ty = %f %s %fx %s %fx^2\n\n", c, if b < 0 then "-" else "+", abs(b), if a < 0 then "-" else "+", abs(a); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/queens.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/queens.mod new file mode 100644 index 000000000..3f446ce4c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/queens.mod @@ -0,0 +1,41 @@ +/* QUEENS, a classic combinatorial optimization problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Queens Problem is to place as many queens as possible on the 8x8 + (or more generally, nxn) chess board in a way that they do not fight + each other. This problem is probably as old as the chess game itself, + and thus its origin is not known, but it is known that Gauss studied + this problem. */ + +param n, integer, > 0, default 8; +/* size of the chess board */ + +var x{1..n, 1..n}, binary; +/* x[i,j] = 1 means that a queen is placed in square [i,j] */ + +s.t. a{i in 1..n}: sum{j in 1..n} x[i,j] <= 1; +/* at most one queen can be placed in each row */ + +s.t. b{j in 1..n}: sum{i in 1..n} x[i,j] <= 1; +/* at most one queen can be placed in each column */ + +s.t. c{k in 2-n..n-2}: sum{i in 1..n, j in 1..n: i-j == k} x[i,j] <= 1; +/* at most one queen can be placed in each "\"-diagonal */ + +s.t. d{k in 3..n+n-1}: sum{i in 1..n, j in 1..n: i+j == k} x[i,j] <= 1; +/* at most one queen can be placed in each "/"-diagonal */ + +maximize obj: sum{i in 1..n, j in 1..n} x[i,j]; +/* objective is to place as many queens as possible */ + +/* solve the problem */ +solve; + +/* and print its optimal solution */ +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/samp1.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/samp1.mps new file mode 100644 index 000000000..dd60d1843 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/samp1.mps @@ -0,0 +1,29 @@ +NAME SAMP1 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + MARK0001 'MARKER' 'INTORG' + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + MARK0002 'MARKER' 'INTEND' + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UP BND1 X2 5.0 + UP BND1 X3 1.0 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/samp2.mps b/WebAPP/SOLVERs/GLPK/glpk/examples/samp2.mps new file mode 100644 index 000000000..d2da1a31d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/samp2.mps @@ -0,0 +1,27 @@ +NAME SAMP2 +ROWS + N Z + G R1 + G R2 + G R3 +COLUMNS + X1 R1 2.0 R2 1.0 + X1 R3 5.0 Z 3.0 + X2 R1 -1.0 R2 -1.0 + X2 R3 3.0 Z 7.0 + X3 R1 1.0 R2 -6.0 + X3 Z -1.0 + X4 R1 -1.0 R2 4.0 + X4 R3 1.0 Z 1.0 +RHS + RHS1 R1 1.0 + RHS1 R2 8.0 + RHS1 R3 5.0 +BOUNDS + UP BND1 X1 4.0 + LO BND1 X2 2.0 + UI BND1 X2 5.0 + BV BND1 X3 + LO BND1 X4 3.0 + UP BND1 X4 8.0 +ENDATA diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.asn b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.asn new file mode 100644 index 000000000..edb0aafd9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.asn @@ -0,0 +1,40 @@ +c sample.asn +c +c This is an example of the assignment problem data +c in DIMACS format. +c +p asn 17 22 +c +n 1 +n 2 +n 3 +n 4 +n 5 +n 6 +n 7 +n 8 +c +a 1 9 13 +a 1 10 21 +a 1 12 20 +a 2 10 12 +a 2 12 8 +a 2 13 26 +a 3 11 22 +a 3 13 11 +a 4 9 12 +a 4 12 36 +a 4 14 25 +a 5 11 41 +a 5 12 40 +a 5 13 11 +a 5 14 4 +a 5 15 8 +a 5 16 35 +a 5 17 32 +a 6 9 13 +a 7 10 19 +a 8 10 39 +a 8 11 15 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.c b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.c new file mode 100644 index 000000000..468a6a354 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.c @@ -0,0 +1,52 @@ +/* sample.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *lp; + int ia[1+1000], ja[1+1000]; + double ar[1+1000], z, x1, x2, x3; +s1: lp = glp_create_prob(); +s2: glp_set_prob_name(lp, "sample"); +s3: glp_set_obj_dir(lp, GLP_MAX); +s4: glp_add_rows(lp, 3); +s5: glp_set_row_name(lp, 1, "p"); +s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); +s7: glp_set_row_name(lp, 2, "q"); +s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); +s9: glp_set_row_name(lp, 3, "r"); +s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); +s11: glp_add_cols(lp, 3); +s12: glp_set_col_name(lp, 1, "x1"); +s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); +s14: glp_set_obj_coef(lp, 1, 10.0); +s15: glp_set_col_name(lp, 2, "x2"); +s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); +s17: glp_set_obj_coef(lp, 2, 6.0); +s18: glp_set_col_name(lp, 3, "x3"); +s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); +s20: glp_set_obj_coef(lp, 3, 4.0); +s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ +s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ +s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ +s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ +s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ +s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ +s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ +s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ +s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ +s30: glp_load_matrix(lp, 9, ia, ja, ar); +s31: glp_simplex(lp, NULL); +s32: z = glp_get_obj_val(lp); +s33: x1 = glp_get_col_prim(lp, 1); +s34: x2 = glp_get_col_prim(lp, 2); +s35: x3 = glp_get_col_prim(lp, 3); +s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", + z, x1, x2, x3); +s37: glp_delete_prob(lp); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.clq b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.clq new file mode 100644 index 000000000..741f71272 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.clq @@ -0,0 +1,30 @@ +c sample.clq +c +c This is an example of the Maximum Weight Clique +c Problem in DIMACS clique/coloring format. +c +p edge 8 16 +n 1 3 +n 2 4 +n 3 8 +n 5 5 +n 6 2 +n 8 3 +e 1 4 +e 1 5 +e 1 6 +e 1 8 +e 2 3 +e 2 6 +e 2 7 +e 2 8 +e 3 4 +e 3 6 +e 3 7 +e 4 5 +e 4 8 +e 5 7 +e 5 8 +e 6 7 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.cnf b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.cnf new file mode 100644 index 000000000..508f15046 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.cnf @@ -0,0 +1,12 @@ +c sample.cnf +c +c This is an example of the CNF-SAT problem data +c in DIMACS format. +c +p cnf 4 3 +1 2 0 +-4 3 +-2 0 +-1 4 0 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.col b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.col new file mode 100644 index 000000000..132f6e578 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.col @@ -0,0 +1,30 @@ +c sample.col +c +c This is an example of the vertex coloring problem data +c in DIMACS format. +c +p edge 10 21 +c +e 1 2 +e 1 6 +e 1 7 +e 1 10 +e 2 3 +e 2 7 +e 2 8 +e 3 4 +e 3 8 +e 4 5 +e 4 8 +e 4 9 +e 5 6 +e 5 9 +e 5 10 +e 6 10 +e 7 8 +e 7 10 +e 8 9 +e 8 10 +e 9 10 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.max b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.max new file mode 100644 index 000000000..6b8042297 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.max @@ -0,0 +1,26 @@ +c sample.max +c +c This is an example of the maximum flow problem data +c in DIMACS format. +c +p max 9 14 +c +n 1 s +n 9 t +c +a 1 2 14 +a 1 4 23 +a 2 3 10 +a 2 4 9 +a 3 5 12 +a 3 8 18 +a 4 5 26 +a 5 2 11 +a 5 6 25 +a 5 7 4 +a 6 7 7 +a 6 8 8 +a 7 9 15 +a 8 9 20 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sample.min b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.min new file mode 100644 index 000000000..5ebf58b1f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sample.min @@ -0,0 +1,26 @@ +c sample.min +c +c This is an example of the minimum cost flow problem data +c in DIMACS format. +c +p min 9 14 +c +n 1 20 +n 9 -20 +c +a 1 2 0 14 0 +a 1 4 0 23 0 +a 2 3 0 10 2 +a 2 4 0 9 3 +a 3 5 2 12 1 +a 3 8 0 18 0 +a 4 5 0 26 0 +a 5 2 0 11 1 +a 5 6 0 25 5 +a 5 7 0 4 7 +a 6 7 0 7 0 +a 6 8 4 8 0 +a 7 9 0 15 3 +a 8 9 0 20 9 +c +c eof diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sat.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sat.mod new file mode 100644 index 000000000..84ba95249 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sat.mod @@ -0,0 +1,201 @@ +/* SAT, Satisfiability Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +param m, integer, > 0; +/* number of clauses */ + +param n, integer, > 0; +/* number of variables */ + +set C{1..m}; +/* clauses; each clause C[i], i = 1, ..., m, is disjunction of some + variables or their negations; in the data section each clause is + coded as a set of indices of corresponding variables, where negative + indices mean negation; for example, the clause (x3 or not x7 or x11) + is coded as the set { 3, -7, 11 } */ + +var x{1..n}, binary; +/* main variables */ + +/* To solve the satisfiability problem means to determine all variables + x[j] such that conjunction of all clauses C[1] and ... and C[m] takes + on the value true, i.e. all clauses are satisfied. + + Let the clause C[i] be (t or t' or ... or t''), where t, t', ..., t'' + are either variables or their negations. The condition of satisfying + C[i] can be most naturally written as: + + t + t' + ... + t'' >= 1, (1) + + where t, t', t'' have to be replaced by either x[j] or (1 - x[j]). + The formulation (1) leads to the mip problem with no objective, i.e. + to a feasibility problem. + + Another, more practical way is to write the condition for C[i] as: + + t + t' + ... + t'' + y[i] >= 1, (2) + + where y[i] is an auxiliary binary variable, and minimize the sum of + y[i]. If the sum is zero, all y[i] are also zero, and therefore all + clauses are satisfied. If the sum is minimal but non-zero, its value + shows the number of clauses which cannot be satisfied. */ + +var y{1..m}, binary, >= 0; +/* auxiliary variables */ + +s.t. c{i in 1..m}: + sum{j in C[i]} (if j > 0 then x[j] else (1 - x[-j])) + y[i] >= 1; +/* the condition (2) */ + +minimize unsat: sum{i in 1..m} y[i]; +/* number of unsatisfied clauses */ + +data; + +/* These data correspond to the instance hole6 (pigeon hole problem for + 6 holes) from SATLIB, the Satisfiability Library, which is part of + the collection at the Forschungsinstitut fuer anwendungsorientierte + Wissensverarbeitung in Ulm Germany */ + +/* The optimal solution is 1 (one clause cannot be satisfied) */ + +param m := 133; + +param n := 42; + +set C[1] := -1 -7; +set C[2] := -1 -13; +set C[3] := -1 -19; +set C[4] := -1 -25; +set C[5] := -1 -31; +set C[6] := -1 -37; +set C[7] := -7 -13; +set C[8] := -7 -19; +set C[9] := -7 -25; +set C[10] := -7 -31; +set C[11] := -7 -37; +set C[12] := -13 -19; +set C[13] := -13 -25; +set C[14] := -13 -31; +set C[15] := -13 -37; +set C[16] := -19 -25; +set C[17] := -19 -31; +set C[18] := -19 -37; +set C[19] := -25 -31; +set C[20] := -25 -37; +set C[21] := -31 -37; +set C[22] := -2 -8; +set C[23] := -2 -14; +set C[24] := -2 -20; +set C[25] := -2 -26; +set C[26] := -2 -32; +set C[27] := -2 -38; +set C[28] := -8 -14; +set C[29] := -8 -20; +set C[30] := -8 -26; +set C[31] := -8 -32; +set C[32] := -8 -38; +set C[33] := -14 -20; +set C[34] := -14 -26; +set C[35] := -14 -32; +set C[36] := -14 -38; +set C[37] := -20 -26; +set C[38] := -20 -32; +set C[39] := -20 -38; +set C[40] := -26 -32; +set C[41] := -26 -38; +set C[42] := -32 -38; +set C[43] := -3 -9; +set C[44] := -3 -15; +set C[45] := -3 -21; +set C[46] := -3 -27; +set C[47] := -3 -33; +set C[48] := -3 -39; +set C[49] := -9 -15; +set C[50] := -9 -21; +set C[51] := -9 -27; +set C[52] := -9 -33; +set C[53] := -9 -39; +set C[54] := -15 -21; +set C[55] := -15 -27; +set C[56] := -15 -33; +set C[57] := -15 -39; +set C[58] := -21 -27; +set C[59] := -21 -33; +set C[60] := -21 -39; +set C[61] := -27 -33; +set C[62] := -27 -39; +set C[63] := -33 -39; +set C[64] := -4 -10; +set C[65] := -4 -16; +set C[66] := -4 -22; +set C[67] := -4 -28; +set C[68] := -4 -34; +set C[69] := -4 -40; +set C[70] := -10 -16; +set C[71] := -10 -22; +set C[72] := -10 -28; +set C[73] := -10 -34; +set C[74] := -10 -40; +set C[75] := -16 -22; +set C[76] := -16 -28; +set C[77] := -16 -34; +set C[78] := -16 -40; +set C[79] := -22 -28; +set C[80] := -22 -34; +set C[81] := -22 -40; +set C[82] := -28 -34; +set C[83] := -28 -40; +set C[84] := -34 -40; +set C[85] := -5 -11; +set C[86] := -5 -17; +set C[87] := -5 -23; +set C[88] := -5 -29; +set C[89] := -5 -35; +set C[90] := -5 -41; +set C[91] := -11 -17; +set C[92] := -11 -23; +set C[93] := -11 -29; +set C[94] := -11 -35; +set C[95] := -11 -41; +set C[96] := -17 -23; +set C[97] := -17 -29; +set C[98] := -17 -35; +set C[99] := -17 -41; +set C[100] := -23 -29; +set C[101] := -23 -35; +set C[102] := -23 -41; +set C[103] := -29 -35; +set C[104] := -29 -41; +set C[105] := -35 -41; +set C[106] := -6 -12; +set C[107] := -6 -18; +set C[108] := -6 -24; +set C[109] := -6 -30; +set C[110] := -6 -36; +set C[111] := -6 -42; +set C[112] := -12 -18; +set C[113] := -12 -24; +set C[114] := -12 -30; +set C[115] := -12 -36; +set C[116] := -12 -42; +set C[117] := -18 -24; +set C[118] := -18 -30; +set C[119] := -18 -36; +set C[120] := -18 -42; +set C[121] := -24 -30; +set C[122] := -24 -36; +set C[123] := -24 -42; +set C[124] := -30 -36; +set C[125] := -30 -42; +set C[126] := -36 -42; +set C[127] := 6 5 4 3 2 1; +set C[128] := 12 11 10 9 8 7; +set C[129] := 18 17 16 15 14 13; +set C[130] := 24 23 22 21 20 19; +set C[131] := 30 29 28 27 26 25; +set C[132] := 36 35 34 33 32 31; +set C[133] := 42 41 40 39 38 37; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/shiftcov.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/shiftcov.mod new file mode 100644 index 000000000..1e036c8a2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/shiftcov.mod @@ -0,0 +1,244 @@ +/* File: shiftcover.mod */ + +/* WORKFORCE SHIFT COVERAGE assignment problem */ + +/* Written by Larry D'Agostino + + Maximize Productivity with Industrial Engineer and Operations Research Tools + http://industrialengineertools.blogspot.com + + +/* The WORKFORCE SHIFT COVERAGE is an assigment problem that determines + the schedule of crew given available time and shifts. + + The objective is to cover the available time given hourly demand with the minimum + number of crew members. + + This is a set covering problem that is very common among finding crew + and shift allocations. Notice in the data section the workforce shift allocation + per day of the week.*/ + + +/* ----- Model PARAMTERS and SETS -----*/ + +param numhrs; +/* number of hours of operations in a given day */ + +param dys; +/* number of days in a week */ + +set S; +/* set of crew shifts */ + +set H := 1..numhrs; +/* set of hours of a day*/ + +set D; +/* set of days of a week*/ + +param dmnd{h in H, d in D}; +/* demand for crew members given h hour and d day */ + +param shifts{d in D, h in H, s in S}; +/* shifts to assign to crew members given d day, h hour, and s shift schedule + +/*----- Model VARIABLES -----*/ + +var crew{s in S}, integer, >=0; +/* number of crew assigned to shift S */ + + +/*----- Model CONSTRAINTS -----*/ + +s.t. Coverage{h in H, d in D}: sum{s in S} crew[s]*shifts[d,h,s] >= dmnd[h,d]; +/* number of crew to cover with a shift given hourly demand and day */ + + +/*----- Model OBJECTIVE -----*/ + +minimize obj: sum{s in S} crew[s]; +/* minimize number of crew to cover demand*/ + +solve; +display crew; + +printf "\n"; +printf "Total Crew: %3d\n\n", sum{s in S} crew[s]; + + + +printf "\n\n"; +printf "Weekly Crew Schedule\n\n"; +printf "Hour "; +printf{d in D} " %s ", d; +printf "\n"; +for {h in H} { + printf " %2s ",h; + printf{d in D} " %3d ", sum{s in S} crew[s]*shifts[d,h,s]; + printf "\n"; +} +printf"\n"; + + + +data; + +param numhrs := 16; + +set D := SUN, MON, TUE, WED, THU, FRI, SAT; + +set S := Sh1, Sh2, Sh3, Sh4, Sh5, Sh6, Sh7, Sh8, Sh9; + +param dmnd : SUN MON TUE WED THU FRI SAT := +1 0 3 3 4 3 2 0 +2 0 14 14 16 14 12 12 +3 0 24 24 27 24 20 15 +4 0 28 28 32 28 23 15 +5 0 33 33 37 33 24 16 +6 0 34 34 38 34 24 15 +7 0 35 35 39 35 25 11 +8 0 35 35 40 35 27 0 +9 0 34 34 39 34 25 0 +10 0 31 31 35 31 24 0 +11 2 24 24 27 24 25 0 +12 3 19 19 21 19 21 0 +13 2 24 24 27 24 13 0 +14 2 16 16 18 16 0 0 +15 0 7 7 7 7 0 0 +16 0 5 5 5 5 0 0; + + +param shifts := +['SUN',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 0 0 0 0 0 0 0 0 0 +2 0 0 0 0 0 0 0 0 0 +3 0 0 0 0 0 0 0 0 0 +4 0 0 0 0 0 0 0 0 0 +5 0 0 0 0 0 0 0 0 0 +6 0 0 0 0 0 0 0 0 0 +7 0 0 0 0 0 0 0 0 0 +8 0 0 0 0 0 0 0 0 0 +9 0 0 0 0 0 0 0 0 0 +10 0 0 0 0 0 0 0 0 0 +11 0 0 0 0 0 0 0 0 1 +12 0 0 0 0 0 0 0 0 1 +13 0 0 0 0 0 0 0 0 1 +14 0 0 0 0 0 0 0 0 1 +15 0 0 0 0 0 0 0 0 0 +16 0 0 0 0 0 0 0 0 0 + + +['MON',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['TUE',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['WED',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 1 +7 1 1 0 1 1 1 1 0 1 +8 1 1 1 0 1 1 1 1 1 +9 1 1 1 1 0 1 1 1 1 +10 0 1 1 1 1 0 1 1 1 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 1 +13 0 0 0 0 1 1 1 1 1 +14 0 0 0 0 0 1 1 1 1 +15 0 0 0 0 0 0 1 1 1 +16 0 0 0 0 0 0 0 1 1 + +['THU',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 0 +7 1 1 0 1 1 1 1 0 0 +8 1 1 1 0 1 1 1 1 0 +9 1 1 1 1 0 1 1 1 0 +10 0 1 1 1 1 0 1 1 0 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 0 +13 0 0 0 0 1 1 1 1 0 +14 0 0 0 0 0 1 1 1 0 +15 0 0 0 0 0 0 1 1 0 +16 0 0 0 0 0 0 0 1 0 + +['FRI',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 1 0 0 0 0 0 0 0 0 +2 1 1 0 0 0 0 0 0 0 +3 1 1 1 0 0 0 0 0 0 +4 1 1 1 1 0 0 0 0 0 +5 0 1 1 1 1 0 0 0 0 +6 1 0 1 1 1 1 0 0 0 +7 1 1 0 1 1 1 1 0 0 +8 1 1 1 0 1 1 1 1 0 +9 1 1 1 1 0 1 1 1 0 +10 0 1 1 1 1 0 1 1 0 +11 0 0 1 1 1 1 0 1 0 +12 0 0 0 1 1 1 1 0 0 +13 0 0 0 0 1 1 1 1 0 +14 0 0 0 0 0 1 1 1 0 +15 0 0 0 0 0 0 1 1 0 +16 0 0 0 0 0 0 0 1 0 + +['SAT',*,*]: + Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := +1 0 0 0 0 0 0 0 0 0 +2 0 0 0 0 0 0 0 0 1 +3 0 0 0 0 0 0 0 0 1 +4 0 0 0 0 0 0 0 0 1 +5 0 0 0 0 0 0 0 0 1 +6 0 0 0 0 0 0 0 0 1 +7 0 0 0 0 0 0 0 0 1 +8 0 0 0 0 0 0 0 0 0 +9 0 0 0 0 0 0 0 0 0 +10 0 0 0 0 0 0 0 0 0 +11 0 0 0 0 0 0 0 0 0 +12 0 0 0 0 0 0 0 0 0 +13 0 0 0 0 0 0 0 0 0 +14 0 0 0 0 0 0 0 0 0 +15 0 0 0 0 0 0 0 0 0 +16 0 0 0 0 0 0 0 0 0; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/shikaku.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/shikaku.mod new file mode 100644 index 000000000..19cf5ddbe --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/shikaku.mod @@ -0,0 +1,107 @@ +/* A solver for the Japanese number-puzzle Shikaku + * http://en.wikipedia.org/wiki/Shikaku + * + * Sebastian Nowozin , 27th January 2009 + */ + +param ndim := 10; +set rows := 1..ndim; +set rows1 := 1..(ndim+1); +set cols := 1..ndim; +set cols1 := 1..(ndim+1); +param givens{rows, cols}, integer, >= 0, default 0; + +/* Set of vertices as (row,col) coordinates */ +set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; + +/* Set of all feasible boxes of the right size: only this boxes are possible. + * The box contains (i,j) and ranges from (k,l) to (m,n) + */ +set B := { (i,j,k,l,m,n) in { V, rows, cols, rows1, cols1 }: + i >= k and i < m and j >= l and j < n and /* Contains (i,j) */ + ((m-k)*(n-l)) = givens[i,j] and /* Right size */ + card({ (s,t) in V: s >= k and s < m and t >= l and t < n }) = 1 + /* Contains only (i,j), no other number */ +}; + +var x{B}, binary; + +/* Cover each square exactly once */ +s.t. cover_once{ (s,t) in { rows, cols } }: + sum{(i,j,k,l,m,n) in B: s >= k and s < m and t >= l and t < n} + x[i,j,k,l,m,n] = 1; + +minimize cost: 0; + +solve; + +/* Output solution graphically */ +printf "\nSolution:\n"; +for { row in rows1 } { + for { col in cols1 } { + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0 and + card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "+"; + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "|"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0} "-"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row <= m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0 and + card({(i,j,k,l,m,n) in B: + col >= l and col <= n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col < n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) > 0} "---"; + printf{0..0: card({(i,j,k,l,m,n) in B: + col >= l and col < n and (row = k or row = m) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + } + printf "\n"; + + for { (col,p) in { cols, 1 }: card({ s in rows: s = row }) = 1 } { + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row < m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) > 0} "|"; + printf{0..0: card({(i,j,k,l,m,n) in B: + row >= k and row < m and (col = l or col = n) and + x[i,j,k,l,m,n] = 1}) = 0} " "; + printf{0..0: card({ (i,j) in V: i = row and j = col}) > 0} " %2d", givens[row,col]; + printf{0..0: card({ (i,j) in V: i = row and j = col}) = 0} " ."; + } + printf{0..0: card({ r in rows: r = row }) = 1} "|\n"; +} + +data; + +/* This Shikaku is from + * http://www.emn.fr/x-info/sdemasse/gccat/KShikaku.html#uid5449 + */ +param givens : 1 2 3 4 5 6 7 8 9 10 := + 1 9 . . . 12 . . 5 . . + 2 . . . . . . . . . . + 3 . . . . . . . . . 6 + 4 8 . 6 . 8 . . . . . + 5 . . . . . . . . . . + 6 . . . . . . . . . . + 7 . . . . . 6 . 8 . 12 + 8 4 . . . . . . . . . + 9 . . . . . . . . . . + 10 . . 3 . . 9 . . . 4 + ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sorting.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sorting.mod new file mode 100644 index 000000000..8f82b1fc5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sorting.mod @@ -0,0 +1,67 @@ +/* sorting.mod - how to sort arrays in MathProg */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +# Sometimes it is necessary to print parameters or variables in the +# order of ascending or descending their values. Suppose, for example, +# that we have the following subscripted parameter: + +set I := 1..12; + +param a{i in I} := Uniform(2, 7); + +# If we print all its members: + +printf{i in I} "a[%d] = %g\n", i, a[i]; + +# the output may look like follows: +# +# a[1] = 2.64156 +# a[2] = 2.04798 +# a[3] = 2.14843 +# a[4] = 4.76896 +# a[5] = 6.09132 +# a[6] = 3.27780 +# a[7] = 4.06113 +# a[8] = 4.05898 +# a[9] = 6.63120 +# a[10] = 6.50318 +# a[11] = 3.46065 +# a[12] = 4.69845 +# +# However, we would like the parameter members to appear in the order +# of ascending their values. +# +# Introduce the following auxiliary parameter: + +param pos{i in I} := + 1 + card({j in I: a[j] < a[i] or a[j] = a[i] and j < i}); + +# where pos[i] = k means that in the sorted list member a[i] would +# have k-th position, 1 <= k <= |I|. Then introduce another auxiliary +# parameter: + +param ind{k in 1..card(I)} := sum{i in I: pos[i] = k} i; + +# where ind[k] = i iff pos[k] = i. +# +# Now, the following statement: + +printf{k in 1..card(I)} "a[%d] = %g\n", ind[k], a[ind[k]]; + +# prints the parameter members in the desired order: +# +# a[2] = 2.04798 +# a[3] = 2.14843 +# a[1] = 2.64156 +# a[6] = 3.27780 +# a[11] = 3.46065 +# a[8] = 4.05898 +# a[7] = 4.06113 +# a[12] = 4.69845 +# a[4] = 4.76896 +# a[5] = 6.09132 +# a[10] = 6.50318 +# a[9] = 6.63120 + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/spp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/spp.mod new file mode 100644 index 000000000..53008f62c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/spp.mod @@ -0,0 +1,67 @@ +/* SPP, Shortest Path Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Given a directed graph G = (V,E), its edge lengths c(i,j) for all + (i,j) in E, and two nodes s, t in V, the Shortest Path Problem (SPP) + is to find a directed path from s to t whose length is minimal. */ + +param n, integer, > 0; +/* number of nodes */ + +set E, within {i in 1..n, j in 1..n}; +/* set of edges */ + +param c{(i,j) in E}; +/* c[i,j] is length of edge (i,j); note that edge lengths are allowed + to be of any sign (positive, negative, or zero) */ + +param s, in {1..n}; +/* source node */ + +param t, in {1..n}; +/* target node */ + +var x{(i,j) in E}, >= 0; +/* x[i,j] = 1 means that edge (i,j) belong to shortest path; + x[i,j] = 0 means that edge (i,j) does not belong to shortest path; + note that variables x[i,j] are binary, however, there is no need to + declare them so due to the totally unimodular constraint matrix */ + +s.t. r{i in 1..n}: sum{(j,i) in E} x[j,i] + (if i = s then 1) = + sum{(i,j) in E} x[i,j] + (if i = t then 1); +/* conservation conditions for unity flow from s to t; every feasible + solution is a path from s to t */ + +minimize Z: sum{(i,j) in E} c[i,j] * x[i,j]; +/* objective function is the path length to be minimized */ + +data; + +/* Optimal solution is 20 that corresponds to the following shortest + path: s = 1 -> 2 -> 4 -> 8 -> 6 = t */ + +param n := 8; + +param s := 1; + +param t := 6; + +param : E : c := + 1 2 1 + 1 4 8 + 1 7 6 + 2 4 2 + 3 2 14 + 3 4 10 + 3 5 6 + 3 6 19 + 4 5 8 + 4 8 13 + 5 8 12 + 6 5 7 + 7 4 5 + 8 6 4 + 8 7 10; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp1.c b/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp1.c new file mode 100644 index 000000000..715642341 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp1.c @@ -0,0 +1,18 @@ +/* spxsamp1.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_adv_basis(P, 0); + glp_simplex(P, NULL); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp2.c b/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp2.c new file mode 100644 index 000000000..f952e740e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/spxsamp2.c @@ -0,0 +1,20 @@ +/* spxsamp2.c */ + +#include +#include +#include + +int main(void) +{ glp_prob *P; + glp_smcp parm; + P = glp_create_prob(); + glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + glp_simplex(P, &parm); + glp_print_sol(P, "25fv47.txt"); + glp_delete_prob(P); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/README b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/README new file mode 100644 index 000000000..f78ec1574 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/README @@ -0,0 +1,5 @@ +This subdirectory contains files which demonstrate using data tables +in MathProg models for MySQL and iODBC. + +Script mysql_setup.sh is used to load the data from the *.sql files to +a MySQL database. Change the username, if necessary. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/mysql_setup.sh b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/mysql_setup.sh new file mode 100755 index 000000000..1dce8edd9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/mysql_setup.sh @@ -0,0 +1,6 @@ +#!/bin/sh +# This file can be used to create database glpk in MySQL. +echo MySQL is called for user root. +mysql -f -u root -p < sudoku.sql +echo MySQL is called for user root. +mysql -f -u root -p < transp.sql diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku.sql b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku.sql new file mode 100644 index 000000000..2fe40d777 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku.sql @@ -0,0 +1,101 @@ +CREATE DATABASE glpk; +CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; +GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; +USE glpk; +DROP TABLE sudoku; +CREATE TABLE sudoku ( + ID INT , + COL INT , + LIN INT , + VAL INT , + PRIMARY KEY ( ID, COL, LIN ) + ); +DROP TABLE sudoku_solution; +CREATE TABLE sudoku_solution ( + ID INT , + COL INT , + LIN INT , + VAL INT , + PRIMARY KEY ( ID, COL, LIN ) + ); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 1, 5); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 5, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 3, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 7, 6); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 8, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 6, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 9, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 3, 6); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 6, 7); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 7, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 1, 8); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 2, 1); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 8, 4); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 9, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 3, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 4, 1); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 1, 7); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 4, 5); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 2, 9); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 3, 2); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 5, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 7, 8); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 9, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 1, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 2, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 3, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 4, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 5, 3); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 6, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 7, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 8, 0); +INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 9, 6); diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_mysql.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_mysql.mod new file mode 100644 index 000000000..6e56f2c6d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_mysql.mod @@ -0,0 +1,113 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* This example shows how to use the table statement. + The sudoku to be solves is read from file sudoku_in.csv. + The solution is written to sudoku_out.csv. + The file format is CSV as defined in + RFC 4180 - Common Format and MIME Type for + Comma-Separated Values (CSV) Files */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ +set fields dimen 2; + +param id; + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +/* +table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'sudoku' : + fields <- [COL, LIN], givens ~ VAL; +*/ +table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'SELECT * FROM sudoku WHERE ID = ' & id : + fields <- [COL, LIN], givens ~ VAL; + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + +solve; + +table ta{(i,j) in fields} OUT + 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM sudoku_solution' + 'WHERE ID = ' & id & ';' + 'INSERT INTO sudoku_solution' + '(ID, COL, LIN, VAL)' + 'VALUES(?, ?, ?, ?);' : + id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; + +printf "\nSudoku to be solved\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", givens[i,j]; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; + } +printf "\nSolution\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +param id := 1; +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_odbc.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_odbc.mod new file mode 100644 index 000000000..9ffa3ab06 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/sudoku_odbc.mod @@ -0,0 +1,111 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* This example shows how to use the table statement. + The sudoku to be solves is read from file sudoku_in.csv. + The solution is written to sudoku_out.csv. + The file format is CSV as defined in + RFC 4180 - Common Format and MIME Type for + Comma-Separated Values (CSV) Files */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ +set fields dimen 2; + +param id; + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +table ti IN 'iODBC' + 'DSN=glpk;UID=glpk;PWD=gnu' + 'SELECT * FROM sudoku' + 'WHERE ID = ' & id : + fields <- [COL, LIN], givens ~ VAL; + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + + +solve; + +table ta {(i, j) in {i1 in 1..9} cross {i2 in 1..9}} OUT + 'iODBC' 'DSN=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM sudoku_solution' + 'WHERE ID = ' & id & ';' + 'INSERT INTO sudoku_solution' + '(ID, COL, LIN, VAL)' + 'VALUES(?, ?, ?, ?);' : + id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; + +printf "\nSudoku to be solved\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", givens[i,j]; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; + } +printf "\nSolution\n"; +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +param id := 1; +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp.sql b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp.sql new file mode 100644 index 000000000..873733303 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp.sql @@ -0,0 +1,45 @@ +CREATE DATABASE glpk; +CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; +GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; +USE glpk; +# production capacity +DROP TABLE transp_capa; +CREATE TABLE transp_capa ( + PLANT TEXT(127), + CAPA REAL, + PRIMARY KEY ( PLANT(127) ) + ); +INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'Seattle', 350 ); +INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'San Diego', 600 ); +# demand +DROP TABLE transp_demand; +CREATE TABLE transp_demand ( + MARKET TEXT(127), + DEMAND REAL, + PRIMARY KEY ( MARKET(127) ) + ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'New York', 325 ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Chicago', 300 ); +INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Topeka', 275 ); +# distance +DROP TABLE transp_dist; +CREATE TABLE transp_dist ( + LOC1 TEXT(127), + LOC2 TEXT(127), + DIST REAL, + PRIMARY KEY ( LOC1(127), LOC2(127) ) + ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'New York', 2.5 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Chicago', 1.7 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Topeka', 1.8 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'New York', 2.5 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Chicago', 1.8 ); +INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Topeka', 1.4 ); +# result +DROP TABLE transp_result; +CREATE TABLE transp_result ( + LOC1 TEXT(127), + LOC2 TEXT(127), + QUANTITY REAL, + PRIMARY KEY ( LOC1(127), LOC2(127) ) + ); diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_mysql.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_mysql.mod new file mode 100644 index 000000000..f375fa395 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_mysql.mod @@ -0,0 +1,71 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +param a{i in I}; +/* capacity of plant i in cases */ + +table plants IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'SELECT PLANT, CAPA AS CAPACITY FROM transp_capa' : + I <- [ PLANT ], a ~ CAPACITY; + +set J; +/* markets */ + +param b{j in J}; +/* demand at market j in cases */ + +table markets IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'transp_demand' : + J <- [ MARKET ], b ~ DEMAND; + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +table dist IN "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'transp_dist' : + [ LOC1, LOC2 ], d ~ DIST; + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table result{i in I, j in J: x[i,j]} OUT "MySQL" + 'Database=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM transp_result;' + 'INSERT INTO transp_result VALUES (?,?,?)' : + i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; + +data; + +param f := 90; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_odbc.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_odbc.mod new file mode 100644 index 000000000..36d807e41 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sql/transp_odbc.mod @@ -0,0 +1,72 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +param a{i in I}; +/* capacity of plant i in cases */ + +table plants IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'SELECT PLANT, CAPA AS CAPACITY' + 'FROM transp_capa' : + I <- [ PLANT ], a ~ CAPACITY; + +set J; +/* markets */ + +param b{j in J}; +/* demand at market j in cases */ + +table markets IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'transp_demand' : + J <- [ MARKET ], b ~ DEMAND; + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +table dist IN "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'transp_dist' : + [ LOC1, LOC2 ], d ~ DIST; + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +solve; + +table result{i in I, j in J: x[i,j]} OUT "iODBC" + 'DSN=glpk;UID=glpk;PWD=gnu' + 'DELETE FROM transp_result;' + 'INSERT INTO transp_result VALUES (?,?,?)' : + i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; + +data; + +param f := 90; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/stigler.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/stigler.mod new file mode 100644 index 000000000..20c5d9d13 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/stigler.mod @@ -0,0 +1,411 @@ +/* STIGLER, original Stigler's 1939 diet problem */ + +/* The Stigler Diet is an optimization problem named for George Stigler, + a 1982 Nobel Laureate in economics, who posed the following problem: + For a moderately active man weighing 154 pounds, how much of each of + 77 foods should be eaten on a daily basis so that the man's intake of + nine nutrients will be at least equal to the recommended dietary + allowances (RDSs) suggested by the National Research Council in 1943, + with the cost of the diet being minimal? + + The nutrient RDAs required to be met in Stigler's experiment were + calories, protein, calcium, iron, vitamin A, thiamine, riboflavin, + niacin, and ascorbic acid. The result was an annual budget allocated + to foods such as evaporated milk, cabbage, dried navy beans, and beef + liver at a cost of approximately $0.11 a day in 1939 U.S. dollars. + + While the name "Stigler Diet" was applied after the experiment by + outsiders, according to Stigler, "No one recommends these diets for + anyone, let alone everyone." The Stigler diet has been much ridiculed + for its lack of variety and palatability, however his methodology has + received praise and is considered to be some of the earliest work in + linear programming. + + The Stigler diet question is a linear programming problem. Lacking + any sophisticated method of solving such a problem, Stigler was + forced to utilize heuristic methods in order to find a solution. The + diet question originally asked in which quantities a 154 pound male + would have to consume 77 different foods in order to fulfill the + recommended intake of 9 different nutrients while keeping expense at + a minimum. Through "trial and error, mathematical insight and + agility," Stigler was able to eliminate 62 of the foods from the + original 77 (these foods were removed based because they lacked + nutrients in comparison to the remaining 15). From the reduced list, + Stigler calculated the required amounts of each of the remaining 15 + foods to arrive at a cost-minimizing solution to his question. + According to Stigler's calculations, the annual cost of his solution + was $39.93 in 1939 dollars. When corrected for inflation using the + consumer price index, the cost of the diet in 2005 dollars is + $561.43. The specific combination of foods and quantities is as + follows: + + Stigler's 1939 Diet + + Food Annual Quantities Annual Cost + ---------------- ----------------- ----------- + Wheat Flour 370 lb. $13.33 + Evaporated Milk 57 cans 3.84 + Cabbage 111 lb. 4.11 + Spinach 23 lb. 1.85 + Dried Navy Beans 285 lb. 16.80 + ---------------------------------------------- + Total Annual Cost $39.93 + + The 9 nutrients that Stigler's diet took into consideration and their + respective recommended daily amounts were: + + Table of nutrients considered in Stigler's diet + + Nutrient Daily Recommended Intake + ------------------------- ------------------------ + Calories 3,000 Calories + Protein 70 grams + Calcium .8 grams + Iron 12 milligrams + Vitamin A 5,000 IU + Thiamine (Vitamin B1) 1.8 milligrams + Riboflavin (Vitamin B2) 2.7 milligrams + Niacin 18 milligrams + Ascorbic Acid (Vitamin C) 75 milligrams + + Seven years after Stigler made his initial estimates, the development + of George Dantzig's Simplex algorithm made it possible to solve the + problem without relying on heuristic methods. The exact value was + determined to be $39.69 (using the original 1939 data). Dantzig's + algorithm describes a method of traversing the vertices of a polytope + of N+1 dimensions in order to find the optimal solution to a specific + situation. + + (From Wikipedia, the free encyclopedia.) */ + +/* Translated from GAMS by Andrew Makhorin . + + For the original GAMS model stigler1939.gms see [3]. + + References: + + 1. George J. Stigler, "The Cost of Subsistence," J. Farm Econ. 27, + 1945, pp. 303-14. + + 2. National Research Council, "Recommended Daily Allowances," Reprint + and Circular Series No. 115, January, 1943. + + 3. Erwin Kalvelagen, "Model building with GAMS," Chapter 2, "Building + linear programming models," pp. 128-34. */ + +set C; +/* commodities */ + +check card(C) = 77; +/* there must be 77 commodities */ + +set N; +/* nutrients */ + +param data{c in C, {"price", "weight"} union N}; +/* nutritive values per dollar of expenditure */ + +param allowance{n in N}; +/* recommended daily allowance for a moderately active man */ + +var x{c in C}, >= 0; +/* dollars of food to be purchased daily */ + +s.t. nb{n in N}: sum{c in C} data[c,n] * x[c] >= allowance[n]; +/* nutrient balance */ + +minimize cost: sum{c in C} x[c]; +/* total food bill */ + +solve; + +param days := 365.25; +/* days in a year */ + +param commodity{c in C}, symbolic; + +param unit{c in C}, symbolic; + +printf "\n"; +printf "MINIMUM COST ANNUAL DIET\n"; +printf "\n"; +printf " Commodity Unit Quantity Cost \n"; +printf "------------------------- ---------- ---------- ----------\n"; +printf{c in C: x[c] != 0} "%-25s %10s %10.2f $%7.2f\n", commodity[c], + unit[c], 100 * days * x[c] / data[c,"price"], days * x[c]; +printf " -----------------\n"; +printf " Total: $%7.2f\n", + days * sum{c in C} x[c]; +printf "\n"; + +data; + +param : C : commodity unit := +flour "Wheat Flour (Enriched)" "10 lb." +macaroni "Macaroni" "1 lb." +cereal "Wheat Cereal (Enriched)" "28 oz." +cornflakes "Corn Flakes" "8 oz." +cornmeal "Corn Meal" "1 lb." +grits "Hominy Grits" "24 oz." +rice "Rice" "1 lb." +oats "Rolled Oats" "1 lb." +whitebread "White Bread (Enriched)" "1 lb." +wheatbread "Whole Wheat Bread" "1 lb." +ryebread "Rye Bread" "1 lb." +poundcake "Pound Cake" "1 lb." +crackers "Soda Crackers" "1 lb." +milk "Milk" "1 qt." +evapmild "Evaporated Milk (can)" "14.5 oz." +butter "Butter" "1 lb." +margarine "Oleomargarine" "1 lb." +eggs "Eggs" "1 doz." +cheese "Cheese (Cheddar)" "1 lb." +cream "Cream" "1/2 pt." +peanutbutter "Peanut Butter" "1 lb." +mayonnaise "Mayonnaise" "1/2 pt." +crisco "Crisco" "1 lb." +lard "Lard" "1 lb." +sirloinsteak "Sirloin Steak" "1 lb." +roundsteak "Round Steak" "1 lb." +ribroast "Rib Roast" "1 lb." +chuckroast "Chuck Roast" "1 lb." +plate "Plate" "1 lb." +liver "Liver (Beef)" "1 lb." +lambleg "Leg of Lamb" "1 lb." +lambchops "Lamb Chops (Rib)" "1 lb." +porkchops "Pork Chops" "1 lb." +porkroast "Pork Loin Roast" "1 lb." +bacon "Bacon" "1 lb." +ham "Ham - smoked" "1 lb." +saltpork "Salt Pork" "1 lb." +chicken "Roasting Chicken" "1 lb." +veal "Veal Cutlets" "1 lb." +salmon "Salmon, Pink (can)" "16 oz." +apples "Apples" "1 lb." +bananas "Bananas" "1 lb." +lemons "Lemons" "1 doz." +oranges "Oranges" "1 doz." +greenbeans "Green Beans" "1 lb." +cabbage "Cabbage" "1 lb." +carrots "Carrots" "1 bunch" +celery "Celery" "1 stalk" +lettuce "Lettuce" "1 head" +onions "Onions" "1 lb." +potatoes "Potatoes" "15 lb." +spinach "Spinach" "1 lb." +sweetpotato "Sweet Potatoes" "1 lb." +peaches "Peaches (can)" "No. 2 1/2" +pears "Pears (can)" "No. 2 1/2" +pineapple "Pineapple (can)" "No. 2 1/2" +asparagus "Asparagus (can)" "No. 2" +cannedgrbn "Grean Beans (can)" "No. 2" +porkbeans "Pork and Beans (can)" "16 oz." +corn "Corn (can)" "No. 2" +peas "Peas (can)" "No. 2" +tomatoes "Tomatoes (can)" "No. 2" +tomatosoup "Tomato Soup (can)" "10 1/2 oz." +driedpeach "Peaches, Dried" "1 lb." +prunes "Prunes, Dried" "1 lb." +raisins "Raisins, Dried" "15 oz." +driedpeas "Peas, Dried" "1 lb." +limabeans "Lima Beans, Dried" "1 lb." +navybeans "Navy Beans, Dried" "1 lb." +coffee "Coffee" "1 lb." +tea "Tea" "1/4 lb." +cocoa "Cocoa" "8 oz." +chocolate "Chocolate" "8 oz." +sugar "Sugar" "10 lb." +cornsirup "Corn Sirup" "24 oz." +molasses "Molasses" "18 oz." +strawberry "Strawberry Preserve" "1 lb." +; + +set N := +calories /* Calories, unit = 1000 */ +protein /* Protein, unit = grams */ +calcium /* Calcium, unit = grams */ +iron /* Iron, unit = milligrams */ +vitaminA /* Vitamin A, unit = 1000 International Units */ +thiamine /* Thiamine, Vit. B1, unit = milligrams */ +riboflavin /* Riboflavin, Vit. B2, unit = milligrams */ +niacin /* Niacin (Nicotinic Acid), unit = milligrams */ +ascorbicAcid /* Ascorbic Acid, Vit. C, unit = milligrams */ +; + +param data +: price weight calories protein calcium iron := +# aug. 15 edible +# 1939 per $1 +# (cents) (grams) (1000) (grams) (grams) (mg.) +flour 36.0 12600 44.7 1411 2.0 365 +macaroni 14.1 3217 11.6 418 .7 54 +cereal 24.2 3280 11.8 377 14.4 175 +cornflakes 7.1 3194 11.4 252 .1 56 +cornmeal 4.6 9861 36.0 897 1.7 99 +grits 8.5 8005 28.6 680 .8 80 +rice 7.5 6048 21.2 460 .6 41 +oats 7.1 6389 25.3 907 5.1 341 +whitebread 7.9 5742 15.6 488 2.5 115 +wheatbread 9.1 4985 12.2 484 2.7 125 +ryebread 9.2 4930 12.4 439 1.1 82 +poundcake 24.8 1829 8.0 130 .4 31 +crackers 15.1 3004 12.5 288 .5 50 +milk 11.0 8867 6.1 310 10.5 18 +evapmild 6.7 6035 8.4 422 15.1 9 +butter 20.8 1473 10.8 9 .2 3 +margarine 16.1 2817 20.6 17 .6 6 +eggs 32.6 1857 2.9 238 1.0 52 +cheese 24.2 1874 7.4 448 16.4 19 +cream 14.1 1689 3.5 49 1.7 3 +peanutbutter 17.9 2534 15.7 661 1.0 48 +mayonnaise 16.7 1198 8.6 18 .2 8 +crisco 20.3 2234 20.1 0 .0 0 +lard 9.8 4628 41.7 0 .0 0 +sirloinsteak 39.6 1145 2.9 166 .1 34 +roundsteak 36.4 1246 2.2 214 .1 32 +ribroast 29.2 1553 3.4 213 .1 33 +chuckroast 22.6 2007 3.6 309 .2 46 +plate 14.6 3107 8.5 404 .2 62 +liver 26.8 1692 2.2 333 .2 139 +lambleg 27.6 1643 3.1 245 .1 20 +lambchops 36.6 1239 3.3 140 .1 15 +porkchops 30.7 1477 3.5 196 .2 80 +porkroast 24.2 1874 4.4 249 .3 37 +bacon 25.6 1772 10.4 152 .2 23 +ham 27.4 1655 6.7 212 .2 31 +saltpork 16.0 2835 18.8 164 .1 26 +chicken 30.3 1497 1.8 184 .1 30 +veal 42.3 1072 1.7 156 .1 24 +salmon 13.0 3489 5.8 705 6.8 45 +apples 4.4 9072 5.8 27 .5 36 +bananas 6.1 4982 4.9 60 .4 30 +lemons 26.0 2380 1.0 21 .5 14 +oranges 30.9 4439 2.2 40 1.1 18 +greenbeans 7.1 5750 2.4 138 3.7 80 +cabbage 3.7 8949 2.6 125 4.0 36 +carrots 4.7 6080 2.7 73 2.8 43 +celery 7.3 3915 .9 51 3.0 23 +lettuce 8.2 2247 .4 27 1.1 22 +onions 3.6 11844 5.8 166 3.8 59 +potatoes 34.0 16810 14.3 336 1.8 118 +spinach 8.1 4592 1.1 106 .0 138 +sweetpotato 5.1 7649 9.6 138 2.7 54 +peaches 16.8 4894 3.7 20 .4 10 +pears 20.4 4030 3.0 8 .3 8 +pineapple 21.3 3993 2.4 16 .4 8 +asparagus 27.7 1945 .4 33 .3 12 +cannedgrbn 10.0 5386 1.0 54 2.0 65 +porkbeans 7.1 6389 7.5 364 4.0 134 +corn 10.4 5452 5.2 136 .2 16 +peas 13.8 4109 2.3 136 .6 45 +tomatoes 8.6 6263 1.3 63 .7 38 +tomatosoup 7.6 3917 1.6 71 .6 43 +driedpeach 15.7 2889 8.5 87 1.7 173 +prunes 9.0 4284 12.8 99 2.5 154 +raisins 9.4 4524 13.5 104 2.5 136 +driedpeas 7.9 5742 20.0 1367 4.2 345 +limabeans 8.9 5097 17.4 1055 3.7 459 +navybeans 5.9 7688 26.9 1691 11.4 792 +coffee 22.4 2025 .0 0 .0 0 +tea 17.4 652 .0 0 .0 0 +cocoa 8.6 2637 8.7 237 3.0 72 +chocolate 16.2 1400 8.0 77 1.3 39 +sugar 51.7 8773 34.9 0 .0 0 +cornsirup 13.7 4996 14.7 0 .5 74 +molasses 13.6 3752 9.0 0 10.3 244 +strawberry 20.5 2213 6.4 11 .4 7 + +: vitaminA thiamine riboflavin niacin ascorbicAcid := +# (1000 IU) (mg.) (mg.) (mg.) (mg.) +flour .0 55.4 33.3 441 0 +macaroni .0 3.2 1.9 68 0 +cereal .0 14.4 8.8 114 0 +cornflakes .0 13.5 2.3 68 0 +cornmeal 30.9 17.4 7.9 106 0 +grits .0 10.6 1.6 110 0 +rice .0 2.0 4.8 60 0 +oats .0 37.1 8.9 64 0 +whitebread .0 13.8 8.5 126 0 +wheatbread .0 13.9 6.4 160 0 +ryebread .0 9.9 3.0 66 0 +poundcake 18.9 2.8 3.0 17 0 +crackers .0 .0 .0 0 0 +milk 16.8 4.0 16.0 7 177 +evapmild 26.0 3.0 23.5 11 60 +butter 44.2 .0 .2 2 0 +margarine 55.8 .2 .0 0 0 +eggs 18.6 2.8 6.5 1 0 +cheese 28.1 .8 10.3 4 0 +cream 16.9 .6 2.5 0 17 +peanutbutter .0 9.6 8.1 471 0 +mayonnaise 2.7 .4 .5 0 0 +crisco .0 .0 .0 0 0 +lard .2 .0 .5 5 0 +sirloinsteak .2 2.1 2.9 69 0 +roundsteak .4 2.5 2.4 87 0 +ribroast .0 .0 2.0 0 0 +chuckroast .4 1.0 4.0 120 0 +plate .0 .9 .0 0 0 +liver 169.2 6.4 50.8 316 525 +lambleg .0 2.8 3.0 86 0 +lambchops .0 1.7 2.7 54 0 +porkchops .0 17.4 2.7 60 0 +porkroast .0 18.2 3.6 79 0 +bacon .0 1.8 1.8 71 0 +ham .0 9.9 3.3 50 0 +saltpork .0 1.4 1.8 0 0 +chicken .1 .9 1.8 68 46 +veal .0 1.4 2.4 57 0 +salmon 3.5 1.0 4.9 209 0 +apples 7.3 3.6 2.7 5 544 +bananas 17.4 2.5 3.5 28 498 +lemons .0 .5 .0 4 952 +oranges 11.1 3.6 1.3 10 1993 +greenbeans 69.0 4.3 5.8 37 862 +cabbage 7.2 9.0 4.5 26 5369 +carrots 188.5 6.1 4.3 89 608 +celery .9 1.4 1.4 9 313 +lettuce 112.4 1.8 3.4 11 449 +onions 16.6 4.7 5.9 21 1184 +potatoes 6.7 29.4 7.1 198 2522 +spinach 918.4 5.7 13.8 33 2755 +sweetpotato 290.7 8.4 5.4 83 1912 +peaches 21.5 .5 1.0 31 196 +pears .8 .8 .8 5 81 +pineapple 2.0 2.8 .8 7 399 +asparagus 16.3 1.4 2.1 17 272 +cannedgrbn 53.9 1.6 4.3 32 431 +porkbeans 3.5 8.3 7.7 56 0 +corn 12.0 1.6 2.7 42 218 +peas 34.9 4.9 2.5 37 370 +tomatoes 53.2 3.4 2.5 36 1253 +tomatosoup 57.9 3.5 2.4 67 862 +driedpeach 86.8 1.2 4.3 55 57 +prunes 85.7 3.9 4.3 65 257 +raisins 4.5 6.3 1.4 24 136 +driedpeas 2.9 28.7 18.4 162 0 +limabeans 5.1 26.9 38.2 93 0 +navybeans .0 38.4 24.6 217 0 +coffee .0 4.0 5.1 50 0 +tea .0 .0 2.3 42 0 +cocoa .0 2.0 11.9 40 0 +chocolate .0 .9 3.4 14 0 +sugar .0 .0 .0 0 0 +cornsirup .0 .0 .0 5 0 +molasses .0 1.9 7.5 146 0 +strawberry .2 .2 .4 3 0 +; + +param allowance := +calories 3 +protein 70 +calcium .8 +iron 12 +vitaminA 5 +thiamine 1.8 +riboflavin 2.7 +niacin 18 +ascorbicAcid 75 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.dat b/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.dat new file mode 100644 index 000000000..074ff4f8f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.dat @@ -0,0 +1,16 @@ +/* sudoku.dat, a hard Sudoku puzzle which causes branching */ + +data; + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 1 . . . . . 7 . . + 2 . 2 . . . . 5 . . + 3 6 . . 3 8 . . . . + 4 . 7 8 . . . . . . + 5 . . . 6 . 9 . . . + 6 . . . . . . 1 4 . + 7 . . . . 2 5 . . 9 + 8 . . 3 . . . . 6 . + 9 . . 4 . . . . . 2 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.mod new file mode 100644 index 000000000..61f2fe2bf --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/sudoku.mod @@ -0,0 +1,84 @@ +/* SUDOKU, Number Placement Puzzle */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Sudoku, also known as Number Place, is a logic-based placement + puzzle. The aim of the canonical puzzle is to enter a numerical + digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 + subgrids (called "regions"), starting with various digits given in + some cells (the "givens"). Each row, column, and region must contain + only one instance of each numeral. + + Example: + + +-------+-------+-------+ + | 5 3 . | . 7 . | . . . | + | 6 . . | 1 9 5 | . . . | + | . 9 8 | . . . | . 6 . | + +-------+-------+-------+ + | 8 . . | . 6 . | . . 3 | + | 4 . . | 8 . 3 | . . 1 | + | 7 . . | . 2 . | . . 6 | + +-------+-------+-------+ + | . 6 . | . . . | 2 8 . | + | . . . | 4 1 9 | . . 5 | + | . . . | . 8 . | . 7 9 | + +-------+-------+-------+ + + (From Wikipedia, the free encyclopedia.) */ + +param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; +/* the "givens" */ + +var x{i in 1..9, j in 1..9, k in 1..9}, binary; +/* x[i,j,k] = 1 means cell [i,j] is assigned number k */ + +s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: + x[i,j,k] = (if givens[i,j] = k then 1 else 0); +/* assign pre-defined numbers using the "givens" */ + +s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; +/* each cell must be assigned exactly one number */ + +s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; +/* cells in the same row must be assigned distinct numbers */ + +s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; +/* cells in the same column must be assigned distinct numbers */ + +s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: + sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; +/* cells in the same region must be assigned distinct numbers */ + +/* there is no need for an objective function here */ + +solve; + +for {i in 1..9} +{ for {0..0: i = 1 or i = 4 or i = 7} + printf " +-------+-------+-------+\n"; + for {j in 1..9} + { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); + printf " %d", sum{k in 1..9} x[i,j,k] * k; + for {0..0: j = 9} printf(" |\n"); + } + for {0..0: i = 9} + printf " +-------+-------+-------+\n"; +} + +data; + +/* These data correspond to the example above. */ + +param givens : 1 2 3 4 5 6 7 8 9 := + 1 5 3 . . 7 . . . . + 2 6 . . 1 9 5 . . . + 3 . 9 8 . . . . 6 . + 4 8 . . . 6 . . . 3 + 5 4 . . 8 . 3 . . 1 + 6 7 . . . 2 . . . 6 + 7 . 6 . . . . 2 8 . + 8 . . . 4 1 9 . . 5 + 9 . . . . 8 . . 7 9 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/t1.cs b/WebAPP/SOLVERs/GLPK/glpk/examples/t1.cs new file mode 100644 index 000000000..d07780f4e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/t1.cs @@ -0,0 +1,99 @@ +/*Find the minimum value which satisfies the linear inequality: + a*x + b*y >= 1 {a,b,x,y Integers} {a,b > 0} {a,b entered on command line} + + Nigel_Galloway@operamail.com + February 2008 +*/ +using System; +using System.Runtime.InteropServices; + +unsafe class GLPK{ + double *lp; + public int a; + public int b; + + const string glpkLibrary = "libglpk.so"; + readonly int GLP_FR = 1; + readonly int GLP_IV = 2; + readonly int GLP_DB = 4; + struct ConstraintMatrix{ + public fixed int ia[3]; + public fixed int ja[3]; + public fixed double ar[3]; + } + [DllImport(glpkLibrary, SetLastError=true)] + static extern double* glp_create_prob(); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_add_rows(double* lp, int rows); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_add_cols(double* lp, int cols); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_col_bnds(double* lp, int col, int bound_type, double lower_bound, double upper_bound); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_col_kind(double* lp, int col, int kind); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_load_matrix(double* lp, int elements, int* ia, int* ja, double* ar); + public GLPK(int a, int b){ + this.a = a; + this.b = b; + lp = glp_create_prob(); + //Col 1 is x, Col 2 is y + glp_add_rows(lp, 1); + glp_add_cols(lp, 2); + glp_set_col_bnds(lp, 1, GLP_FR, 0.0, 0.0); + glp_set_col_bnds(lp, 2, GLP_FR, 0.0, 0.0); + glp_set_col_kind(lp, 1, GLP_IV); + glp_set_col_kind(lp, 2, GLP_IV); + //Row 1 is a*x + b*y + ConstraintMatrix CM = new ConstraintMatrix(); + CM.ia[1]=1; CM.ja[1]=1; CM.ar[1]=a; + CM.ia[2]=1; CM.ja[2]=2; CM.ar[2]=b; + glp_load_matrix(lp, 2, CM.ia, CM.ja, CM.ar); + Console.WriteLine("Hello Nigel"); + } + + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_set_row_bnds(double* lp, int row, int bound_type, double lower_bound, double upper_bound); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_simplex(double* lp, void* options); + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_intopt(double* lp, void* options); + [DllImport(glpkLibrary, SetLastError=true)] + static extern double glp_mip_col_val(double* lp, int col); + public int betterGuess(int upper_bound){ + //Find a new guess less than the old guess: 1 <= (a*x + b*y) <= (old guess - 1) + glp_set_row_bnds(lp, 1, GLP_DB, 1.0, ((double)upper_bound)-0.5); + glp_simplex(lp, null); + glp_intopt(lp, null); + int x = (int)glp_mip_col_val(lp, 1); + int y = (int)glp_mip_col_val(lp, 2); + int nextGuess = a*x + b*y; + Console.WriteLine("x = {0}, y = {1}, a*x + b*y = {2}",x,y,nextGuess); + return nextGuess; + } + + [DllImport(glpkLibrary, SetLastError=true)] + static extern void glp_delete_prob(double* lp); + ~GLPK(){ + glp_delete_prob(lp); + Console.WriteLine("Goodbye Nigel"); + } + +} + +class test{ + static bool isMinimum(int a, int b, int guess){ + Console.WriteLine("Trying {0}",guess); + if (a%guess > 0) return false; + if (b%guess > 0) return false; + Console.WriteLine("Solution is {0}",guess); + return true; + } + + public static void Main(string[] args){ + Console.WriteLine("a = {0}, b = {1}",args[0], args[1]); + GLPK lp = new GLPK(Int32.Parse(args[0]),Int32.Parse(args[1])); + int guess = (lp.a > lp.b) ? lp.b : lp.a; + while (!isMinimum(lp.a,lp.b,guess)) guess = lp.betterGuess(guess); + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tas.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/tas.mod new file mode 100644 index 000000000..dbb5ac2da --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tas.mod @@ -0,0 +1,486 @@ +/* TAS, Tail Assignment Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Tail Assignment Problem (TAS) is to construct rosters for a set + of aircrafts (tails), which cover all flights for a given scheduling + period. + + This model includes only flight connection constraints while other + constraints (for example, maintenance constraints) are ignored. Such + simplification allows using a single commodity network to model the + problem, where commodity corresponds to the set of aircrafts. + + Nodes of the network are activities. They include all flights plus + two dummy nodes (activities): source node, s, corresponding to + initial activity of each aircraft, and sink node t, corresponding to + final activity of each aircraft. Arc v->v' exists in the network if + and only if the same aircraft is able to operate activity v and then + immediately activity v'. In partucular, arcs s->f and f->t exist for + all flights f. Arcs f->f', where f and f' are some flights, exist + only if the connection time (which is the difference between the + departure time of f' and the arrival time of f) is not less than a + given minimal connection time. + + Reference: + M. Groenkvist, "The Tail Assignment Problem," Dept. of Comp. Sci. + and Eng., Chalmers University of Technology and Goeteborg University, + Goeteborg, Sweden, August 2005. */ + +######################################################################## + +param nf, integer, > 0; +/* number of flights */ + +set F := 1..nf; +/* set of flights (for a given period from timetable) */ + +param hub{f in F}, in {1, 2}; +/* hub[f] = 1: Sheremetyevo-1 + hub[f] = 2: Sheremetyevo-2 */ + +param dest{f in F}, symbolic; +/* destination airport (IATA code) */ + +param fno1{f in F}, integer; +/* first leg flight number */ + +param dep1{f in F}, integer, >= 0; +/* departure time from Sheremetyevo airport, in minutes */ + +check{f in F: f < nf}: dep1[f] <= dep1[f+1]; +/* all flights must be ordered by ascending of the departure time */ + +param arr1{f in F}, integer, >= 0; +/* arrival time to destination airport, in minutes */ + +param fno2{f in F}, integer; +/* second leg flight number */ + +param dep2{f in F}, integer, >= 0; +/* departure time from destination airport, in minutes */ + +param arr2{f in F}, integer, >= 0; +/* arrival time to Sheremetyevo airport, in minutes */ + +param mct1, integer, >= 0, default 80; +/* minimal connection time (within SVO1 or SVO2), in minutes */ + +param mct2, integer, >= 0, default 150; +/* minimal connection time (between SVO1 and SVO2), in minutes */ + +set E := setof{f in F, ff in F: arr2[f] + (if hub[f] = hub[ff] then + mct1 else mct2) <= dep1[ff]} (f, ff); +/* connection network; arc f->ff is in E, iff the same aircraft can be + assigned to flight f and then immediately to flight ff */ + +var s{f in F}, >= 0; +/* s[f] is a flow from source node to node f */ + +var x{(f,ff) in E}, >= 0; +/* x[f,ff] is a flow from node f to node ff */ + +var t{f in F}, >= 0; +/* t[f] is a flow from node f to sink node */ + +s.t. into{f in F}: s[f] + sum{(ff,f) in E} x[ff,f] = 1; +/* exactly one aircraft must come into each node f */ + +s.t. from{f in F}: t[f] + sum{(f,ff) in E} x[f,ff] = 1; +/* exactly one aircraft must come from each node f */ + +minimize obj: sum{f in F} s[f]; +/* minimize the number aircrafts sufficient to cover all flights */ + +solve; + +######################################################################## + +param na := floor(sum{f in F} s[f] + .5); +/* minimal number of aircrafts found */ + +printf "At least %d aircrafts needed\n", na; + +set A := 1..na; +/* set of aircrafts */ + +printf "Building rosters...\n"; + +param tail{f in F}, in A, := +/* tail[f] is the number of an aircraft assigned to flight f */ + + if f = 1 then 1 + /* assign aircraft 1 to the earliest flight */ + + else if s[f] >= 0.9 then (max{ff in 1..f-1} tail[ff]) + 1 + /* if f is the first flight in a roster, assign to it a next + aircraft */ + + else sum{(ff,f) in E} tail[ff] * (if x[ff,f] >= 0.9 then 1); + /* otherwise, assign to flight f the same aircraft, which is + assigned to a preceding flight in the roster */ + +######################################################################## + +param file, symbolic, default "tas.ps"; +/* file to output the assignment chart in postscript format */ + +param title, symbolic, default "(no title)"; +/* chart title */ + +param left, default 25; +/* left margin, in mm */ + +param top, default 25; +/* top margin, in mm */ + +param right, default 20; +/* right margin, in mm */ + +param bottom, default 15; +/* bottom margin, in mm */ + +param sx := 297 - left - right; +/* chart area horizontal size, in mm */ + +param sy := 210 - top - bottom; +/* chart area vertical size, in mm */ + +param gap, default sy / (na - 1); +/* gap between rosters, in mm */ + +printf "Writing assignment chart to %s...\n", file; + +printf "%%!PS-Adobe-3.0\n" > file; +printf "%%%%Title: Tail Assignment Chart\n" >> file; +printf "%%%%Creator: GLPK MathProg\n" >> file; +printf "%%%%BoundingBox: 0 0 595 842\n" >> file; +printf "%%%%EndComments\n" >> file; +printf "<> setpagedevice\n" >> file; +printf "72 25.4 div dup scale\n" >> file; +printf "210 %.3f sub %.3f translate\n", bottom, left >> file; +printf "90 rotate\n" >> file; + +printf "/HelveticaBold findfont 5 scalefont setfont\n" >> file; +printf "%.3f %.3f moveto (%s) dup show\n", 0, sy + 5, title >> file; + +param period := floor((max{f in F} arr2[f]) / 60. + .5); +/* period duration, in hours */ + +/* vertical bars */ +printf ".8 .8 .8 setrgbcolor\n" >> file; +for {tt in 0..period} +{ printf "%s setlinewidth\n", + if tt mod 24 = 0 then ".5" else "0" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + tt * (sx / period), 0, tt * (sx / period), + sy + (if tt mod 24 = 0 then 2) >> file; +} + +/* rosters */ +for {a in A} +{ printf "0 0 0 setrgbcolor\n" >> file; + printf "0 setlinewidth\n" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + 0, sy - gap * (a - 1), sx, sy - gap * (a - 1) >> file; + printf "/Dingbats findfont 4 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto <28> dup show\n", + -4, sy - gap * (a - 1) - 1.4, a >> file; + printf "/Helvetica findfont 3 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto (%2d) dup show\n", + -9, sy - gap * (a - 1) - 1.2, a >> file; + for {f in F: tail[f] == a} + { printf "0 0 %s setrgbcolor\n", + if hub[f] = 1 then "0" else ".8" >> file; + printf "1 setlinewidth\n" >> file; + printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1), + arr2[f] / 60 * (sx / period), sy - gap * (a - 1) >> file; + printf "/Helvetica findfont 1.8 scalefont setfont\n" >> file; + printf "%.3f %.3f moveto (%02d:%02d %s) dup show\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1) + .8, + (dep1[f] mod 1440) div 60, (dep1[f] mod 1440) mod 60, + dest[f] >> file; + printf "%.3f %.3f moveto (%d %02d:%02d) dup show\n", + dep1[f] / 60 * (sx / period), sy - gap * (a - 1) - 2.1, + fno1[f], + (arr2[f] mod 1440) div 60, (arr2[f] mod 1440) mod 60 >> file; + } +} + +printf "showpage\n" >> file; +printf "%%%%EOF\n" >> file; + +######################################################################## + +data; + +param title := "Tu-154 [from 2008-08-18 to 2008-08-24]"; + +param nf := 261; + +param : hub dest fno1 dep1 arr1 fno2 dep2 arr2 := + 1 1 IKT 743 195 520 744 610 970 + 2 1 OMS 815 205 405 816 485 700 + 3 1 CEK 897 205 360 898 430 595 + 4 1 KRR 763 260 400 764 480 610 + 5 2 SIP 133 280 420 134 500 620 + 6 2 BUD 131 290 450 132 520 675 + 7 1 AAQ 701 305 440 702 510 640 + 8 1 MRV 785 310 440 786 520 650 + 9 2 WAW 101 355 475 102 540 660 + 10 2 GYD 147 370 550 148 675 860 + 11 1 AER 869 385 530 870 655 795 + 12 1 KRR 765 430 560 766 630 760 + 13 1 AAQ 703 520 660 704 740 850 + 14 1 LED 845 530 620 846 690 775 + 15 1 KRR 767 540 675 768 765 895 + 16 2 KBP 183 665 760 184 850 940 + 17 1 MRV 787 755 905 788 985 1135 + 18 1 KRR 771 810 940 772 1030 1165 + 19 1 LED 849 825 900 850 960 1095 + 20 2 IST 209 880 1050 210 1120 1280 + 21 1 AER 873 885 1030 874 1760 1900 + 22 1 ASF 711 995 1145 712 1640 1795 + 23 2 ULN 563 995 1335 564 1415 1815 + 24 2 OTP 151 1020 1175 152 1800 1940 + 25 2 BEY 509 1025 1265 510 1350 1580 + 26 2 OSL 211 1060 1220 212 1860 2015 + 27 1 IKT 739 1085 1420 740 1510 1870 + 28 1 KRR 773 1095 1240 774 1620 1765 + 29 1 SGC 877 1120 1315 878 1395 1625 + 30 1 LED 857 1150 1230 858 1610 1690 + 31 1 CEK 899 1230 1385 900 1455 1620 + 32 1 PEE 821 1235 1390 822 1450 1600 + 33 2 TBS 197 1240 1405 198 1560 1715 + 34 1 UFA 891 1275 1405 892 1475 1610 + 35 1 KJA 781 1300 1570 782 1680 1990 + 36 1 IKT 743 1635 1960 744 2050 2410 + 37 1 OMS 815 1645 1845 816 1925 2140 + 38 1 CEK 897 1645 1800 898 1870 2035 + 39 1 KRR 763 1700 1840 764 1920 2050 + 40 2 SIP 133 1720 1860 134 1940 2060 + 41 2 BUD 131 1730 1890 132 1960 2115 + 42 1 AAQ 701 1745 1880 702 1950 2080 + 43 1 MRV 785 1750 1880 786 1960 2090 + 44 2 WAW 101 1795 1915 102 1980 2100 + 45 2 GYD 147 1810 1990 148 2115 2300 + 46 1 AER 869 1825 1970 870 2095 2235 + 47 2 EVN 193 1850 2030 194 2105 2275 + 48 1 KRR 765 1870 2000 766 2070 2200 + 49 1 AAQ 703 1960 2100 704 2180 2290 + 50 1 LED 845 1970 2060 846 2130 2215 + 51 1 KRR 767 1980 2115 768 2205 2335 + 52 2 KBP 183 2105 2200 184 2290 2380 + 53 1 MRV 787 2195 2345 788 2425 2575 + 54 1 KRR 771 2250 2380 772 2470 2605 + 55 1 LED 849 2265 2340 850 2400 2535 + 56 2 IST 209 2320 2490 210 2560 2720 + 57 1 AER 873 2325 2470 874 3200 3340 + 58 2 ULN 563 2435 2775 564 2855 3255 + 59 1 ASF 711 2435 2585 712 3080 3235 + 60 2 DAM 517 2465 2705 518 2790 3020 + 61 2 OSL 211 2500 2660 212 3300 3455 + 62 2 KBP 185 2510 2610 186 3160 3250 + 63 1 IKT 739 2525 2860 740 2950 3310 + 64 1 KRR 773 2535 2680 774 3060 3205 + 65 1 SGC 877 2560 2755 878 2835 3065 + 66 1 LED 857 2590 2670 858 3050 3130 + 67 1 CEK 899 2670 2825 900 2895 3060 + 68 1 PEE 821 2675 2830 822 2890 3040 + 69 2 TBS 197 2680 2845 198 3000 3155 + 70 1 UFA 891 2715 2845 892 2915 3050 + 71 1 KJA 781 2740 3010 782 3120 3430 + 72 1 IKT 743 3075 3400 744 3490 3850 + 73 1 CEK 897 3085 3240 898 3310 3475 + 74 1 OMS 815 3085 3285 816 3365 3580 + 75 1 KRR 763 3140 3280 764 3360 3490 + 76 2 SIP 133 3160 3300 134 3380 3500 + 77 2 BUD 131 3170 3330 132 3400 3555 + 78 1 AAQ 701 3185 3320 702 3390 3520 + 79 1 MRV 785 3190 3320 786 3400 3530 + 80 2 WAW 101 3235 3355 102 3420 3540 + 81 2 FRU 181 3245 3495 182 3590 3860 + 82 2 GYD 147 3250 3430 148 3555 3740 + 83 1 AER 869 3265 3410 870 3535 3675 + 84 1 KRR 765 3310 3440 766 3510 3640 + 85 1 AAQ 703 3400 3540 704 3620 3730 + 86 1 LED 845 3410 3500 846 3570 3655 + 87 1 KRR 767 3420 3555 768 3645 3775 + 88 2 KBP 183 3545 3640 184 3730 3820 + 89 1 MRV 787 3635 3785 788 3865 4015 + 90 1 KRR 771 3690 3820 772 3910 4045 + 91 1 LED 849 3705 3780 850 3840 3975 + 92 2 IST 209 3760 3930 210 4000 4160 + 93 1 AER 873 3765 3910 874 4640 4780 + 94 2 ULN 563 3875 4215 564 4295 4695 + 95 1 ASF 711 3875 4025 712 4520 4675 + 96 2 OTP 151 3900 4055 152 4680 4820 + 97 2 BEY 509 3905 4145 510 4230 4460 + 98 2 OSL 211 3940 4100 212 4740 4895 + 99 2 KBP 185 3950 4050 186 4600 4690 + 100 1 IKT 739 3965 4300 740 4390 4750 + 101 1 KRR 773 3975 4120 774 4500 4645 + 102 1 SGC 877 4000 4195 878 4275 4505 + 103 1 LED 857 4030 4110 858 4490 4570 + 104 1 CEK 899 4110 4265 900 4335 4500 + 105 1 PEE 821 4115 4270 822 4330 4480 + 106 2 TBS 197 4120 4285 198 4440 4595 + 107 1 UFA 891 4155 4285 892 4355 4490 + 108 1 KJA 781 4180 4450 782 4560 4870 + 109 1 IKT 743 4515 4840 744 4930 5290 + 110 1 OMS 815 4525 4725 816 4805 5020 + 111 1 CEK 897 4525 4680 898 4750 4915 + 112 1 KRR 763 4580 4720 764 4800 4930 + 113 2 SIP 133 4600 4740 134 4820 4940 + 114 2 BUD 131 4610 4770 132 4840 4995 + 115 1 AAQ 701 4625 4760 702 4830 4960 + 116 1 MRV 785 4630 4760 786 4840 4970 + 117 2 WAW 101 4675 4795 102 4860 4980 + 118 2 GYD 147 4690 4870 148 4995 5180 + 119 1 AER 869 4705 4850 870 4975 5115 + 120 2 EVN 193 4730 4910 194 4985 5155 + 121 1 KRR 765 4750 4880 766 4950 5080 + 122 1 AAQ 703 4840 4980 704 5060 5170 + 123 1 LED 845 4850 4940 846 5010 5095 + 124 1 KRR 767 4860 4995 768 5085 5215 + 125 2 KBP 183 4985 5080 184 5170 5260 + 126 1 MRV 787 5075 5225 788 5305 5455 + 127 1 KRR 771 5130 5260 772 5350 5485 + 128 1 LED 849 5145 5220 850 5280 5415 + 129 2 IST 209 5200 5370 210 5440 5600 + 130 1 AER 873 5205 5350 874 6080 6220 + 131 1 ASF 711 5315 5465 712 5960 6115 + 132 2 ULN 563 5315 5655 564 5735 6135 + 133 2 DAM 517 5345 5585 518 5670 5900 + 134 2 OSL 211 5380 5540 212 6180 6335 + 135 2 KBP 185 5390 5490 186 6040 6130 + 136 1 IKT 739 5405 5740 740 5830 6190 + 137 1 KRR 773 5415 5560 774 5940 6085 + 138 1 SGC 877 5440 5635 878 5715 5945 + 139 1 LED 857 5470 5550 858 5930 6010 + 140 1 CEK 899 5550 5705 900 5775 5940 + 141 1 PEE 821 5555 5710 822 5770 5920 + 142 2 TBS 197 5560 5725 198 5880 6035 + 143 1 UFA 891 5595 5725 892 5795 5930 + 144 1 KJA 781 5620 5890 782 6000 6310 + 145 1 IKT 743 5955 6280 744 6370 6730 + 146 1 OMS 815 5965 6165 816 6245 6460 + 147 1 CEK 897 5965 6120 898 6190 6355 + 148 1 KRR 763 6020 6160 764 6240 6370 + 149 2 SIP 133 6040 6180 134 6260 6380 + 150 2 BUD 131 6050 6210 132 6280 6435 + 151 1 AAQ 701 6065 6200 702 6270 6400 + 152 1 MRV 785 6070 6200 786 6280 6410 + 153 2 WAW 101 6115 6235 102 6300 6420 + 154 2 FRU 181 6125 6375 182 6470 6740 + 155 2 GYD 147 6130 6310 148 6435 6620 + 156 1 AER 869 6145 6290 870 6415 6555 + 157 2 EVN 193 6170 6350 194 6425 6595 + 158 1 KRR 765 6190 6320 766 6390 6520 + 159 1 AAQ 703 6280 6420 704 6500 6610 + 160 1 LED 845 6290 6380 846 6450 6535 + 161 1 KRR 767 6300 6435 768 6525 6655 + 162 2 KBP 183 6425 6520 184 6610 6700 + 163 2 AYT 223 6500 6690 224 6750 6940 + 164 1 AER 867 6510 6660 868 6730 6880 + 165 1 MRV 787 6515 6665 788 6745 6895 + 166 1 KRR 771 6570 6700 772 6790 6925 + 167 1 LED 849 6585 6660 850 6720 6855 + 168 2 IST 209 6640 6810 210 6880 7040 + 169 1 AER 873 6645 6790 874 7520 7660 + 170 1 ASF 711 6755 6905 712 7400 7555 + 171 2 ULN 563 6755 7095 564 7175 7575 + 172 2 OTP 151 6780 6935 152 7560 7700 + 173 2 BEY 509 6785 7025 510 7110 7340 + 174 2 OSL 211 6820 6980 212 7620 7775 + 175 2 KBP 185 6830 6930 186 7480 7570 + 176 1 IKT 739 6845 7180 740 7270 7630 + 177 1 KRR 773 6855 7000 774 7380 7525 + 178 1 SGC 877 6880 7075 878 7155 7385 + 179 1 LED 857 6910 6990 858 7370 7450 + 180 1 CEK 899 6990 7145 900 7215 7380 + 181 1 PEE 821 6995 7150 822 7210 7360 + 182 2 TBS 197 7000 7165 198 7320 7475 + 183 1 UFA 891 7035 7165 892 7235 7370 + 184 1 KJA 781 7060 7330 782 7440 7750 + 185 1 IKT 743 7395 7720 744 7810 8170 + 186 1 CEK 897 7405 7560 898 7630 7795 + 187 1 KRR 763 7460 7600 764 7680 7810 + 188 2 SIP 133 7480 7620 134 7700 7820 + 189 2 BUD 131 7490 7650 132 7720 7875 + 190 1 AAQ 701 7505 7640 702 7710 7840 + 191 1 MRV 785 7510 7640 786 7720 7850 + 192 2 IST 207 7545 7720 208 7795 7985 + 193 2 WAW 101 7555 7675 102 7740 7860 + 194 2 GYD 147 7570 7750 148 7875 8060 + 195 1 AER 869 7585 7730 870 7855 7995 + 196 2 AYT 221 7610 7800 222 7895 8085 + 197 2 EVN 193 7610 7790 194 7865 8035 + 198 1 KRR 765 7630 7760 766 7830 7960 + 199 1 AAQ 703 7720 7860 704 7940 8050 + 200 1 LED 845 7730 7820 846 7890 7975 + 201 1 KRR 767 7740 7875 768 7965 8095 + 202 2 KBP 183 7865 7960 184 8050 8140 + 203 2 AYT 223 7940 8130 224 8190 8380 + 204 1 MRV 787 7955 8105 788 8185 8335 + 205 1 KRR 771 8010 8140 772 8230 8365 + 206 1 LED 849 8025 8100 850 8160 8295 + 207 2 IST 209 8080 8250 210 8320 8480 + 208 1 AER 873 8085 8230 874 8960 9100 + 209 1 ASF 711 8195 8345 712 8840 8995 + 210 2 ULN 563 8195 8535 564 8615 9015 + 211 1 KJA 779 8230 8500 780 8575 8870 + 212 2 OSL 211 8260 8420 212 9060 9215 + 213 2 KBP 185 8270 8370 186 8920 9010 + 214 1 IKT 739 8285 8620 740 8710 9070 + 215 1 KRR 773 8295 8440 774 8820 8965 + 216 1 SGC 877 8320 8515 878 8595 8825 + 217 1 LED 857 8350 8430 858 8810 8890 + 218 1 CEK 899 8430 8585 900 8655 8820 + 219 1 PEE 821 8435 8590 822 8650 8800 + 220 2 TBS 197 8440 8605 198 8760 8915 + 221 1 UFA 891 8475 8605 892 8675 8810 + 222 1 KJA 781 8500 8770 782 8880 9190 + 223 1 IKT 743 8835 9160 744 9250 9610 + 224 1 OMS 815 8845 9045 816 9125 9340 + 225 1 CEK 897 8845 9000 898 9070 9235 + 226 1 KRR 763 8900 9040 764 9120 9250 + 227 2 SIP 133 8920 9060 134 9140 9260 + 228 2 BUD 131 8930 9090 132 9160 9315 + 229 1 AAQ 701 8945 9080 702 9150 9280 + 230 1 MRV 785 8950 9080 786 9160 9290 + 231 2 IST 207 8985 9160 208 9235 9425 + 232 2 WAW 101 8995 9115 102 9180 9300 + 233 2 FRU 181 9005 9255 182 9350 9620 + 234 2 GYD 147 9010 9190 148 9315 9500 + 235 1 AER 869 9025 9170 870 9295 9435 + 236 2 EVN 193 9050 9230 194 9305 9475 + 237 1 KRR 765 9070 9200 766 9270 9400 + 238 1 AAQ 703 9160 9300 704 9380 9490 + 239 1 LED 845 9170 9260 846 9330 9415 + 240 1 KRR 767 9180 9315 768 9405 9535 + 241 2 KBP 183 9305 9400 184 9490 9580 + 242 2 AYT 223 9380 9570 224 9630 9820 + 243 1 MRV 787 9395 9545 788 9625 9775 + 244 1 KRR 771 9450 9580 772 9670 9805 + 245 1 LED 849 9465 9540 850 9600 9735 + 246 2 IST 209 9520 9690 210 9760 9920 + 247 1 AER 873 9525 9670 874 10400 10540 + 248 1 ASF 711 9635 9785 712 10280 10435 + 249 2 ULN 563 9635 9975 564 10055 10455 + 250 2 OTP 151 9660 9815 152 10440 10580 + 251 2 DAM 517 9665 9905 518 9990 10220 + 252 2 OSL 211 9700 9860 212 10500 10655 + 253 2 KBP 185 9710 9810 186 10360 10450 + 254 1 IKT 739 9725 10060 740 10150 10510 + 255 1 KRR 773 9735 9880 774 10260 10405 + 256 1 SGC 877 9760 9955 878 10035 10265 + 257 1 LED 857 9790 9870 858 10250 10330 + 258 1 CEK 899 9870 10025 900 10095 10260 + 259 1 PEE 821 9875 10030 822 10090 10240 + 260 1 UFA 891 9915 10045 892 10115 10250 + 261 1 KJA 781 9940 10210 782 10320 10630 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Build_Multiseed.bat b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Build_Multiseed.bat new file mode 100644 index 000000000..34dd95f60 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Build_Multiseed.bat @@ -0,0 +1,12 @@ +rem Build GLPK DLL with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +set PATH=..\..\w64\ +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile new file mode 100644 index 000000000..61063d360 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile @@ -0,0 +1,5 @@ +all: + gcc multiseed.c -I. -lglpk -pthread -o multiseed + +check: + ./multiseed clustering.mod 20 diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile_VC b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile_VC new file mode 100644 index 000000000..5bb817941 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/Makefile_VC @@ -0,0 +1,26 @@ +## Build multiseed example with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\..\src \ +/I..\..\w64 \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: multiseed.exe + +multiseed.exe: multiseed.obj ..\..\w64\glpk_4_61.dll + cl.exe $(CFLAGS) /Fmultiseed.exe \ + multiseed.obj ..\..\w64\glpk_4_61.lib + +check: multiseed.exe + .\multiseed.exe clustering.mod 20 + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/README b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/README new file mode 100644 index 000000000..cb547f0ed --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/README @@ -0,0 +1,66 @@ +Thread local memory example +=========================== + +The GLPK library, when compiled with default options, uses a separate environment +for each thread that is executed. So each thread is isolated. The only exeption +is error handling. An error in any of the library functions will not only +terminate the active thread but the complete process. + +This can be circumvented by defining an error handling routine with +glp_error_hook(). This directory contains an example demonstrating running a +multithreaded application with error handling. + + +The example code +---------------- + +The program multiseed solves a MathProg model multiple times in separate parallel +threads. Each threads uses a different seed for the MathProg pseudo random number +generator. + +The MathProg model clustering.mod generates 50 randomly distributed "towns". Out +of the towns it selects 3 to be cluster centers and assign the other towns to the +clusters such that the sum of the population weighted euclidian distances between +towns and centers is minimized. + +The solution is written to a Scalable Vector File which can be viewed with a web +browser. + +For demonstration purposes at the end of every third thread the error handling +routine is triggered by calling glp_error(). This results in output like + + 18-00086 Model has been successfully processed + 18-00087 Voluntarily throwing an error in multiseed.c at line 147 + 18-00088 Error detected in file multiseed.c at line 146 + 18-00089 Error caught + +Terminal output is preceeded by numbers indicating the thread index and the +output line. You can pipe it through sort to get a better overiew, e.g. + + multiseed clustering.mod 20 | sort + + +Building and running the example code +------------------------------------- + +On Linux multiseed can be compiled with gcc by calling + + make + +The code can be executed with + + make check + +For compiling the example on 64bit Windows with Microsoft Visual Studio C++ run + + Build_Multiseed.bat + +You may have to adust the variable HOME in the batch file depending on the +installation path of Visual Studio. + +You can run multiseed with + + multiseed + +Where filename is the path to the model file and count is the number of parallel +threads. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/clustering.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/clustering.mod new file mode 100644 index 000000000..cd8cd372e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/clustering.mod @@ -0,0 +1,109 @@ +/* + * Author: Heinrich Schuchardt + * + * This model solves a clustering problem: + * + * Out of 50 towns select 3 to be cluster centers and assign the other + * towns to the clusters such that the sum of the population weighted + * euclidian distances between towns and centers is minimized. + * + * The solution is saved as a scalable vector graphic file with a + * pseudo-random file name. + */ + +# Output file +param fn, symbolic := "00000" & 100000 * Uniform01(); +param f, symbolic := "ct" & substr(fn, length(fn) - 4) & ".svg"; + +# Centers +param nc := 3; +set C := {1 .. nc}; + +# Towns +param nt := 50; +set T := {1 .. nt}; +param xt{T} := Uniform01(); +param yt{T} := Uniform01(); +param pt{T} := ceil(1000 * Uniform01()); + +# Image size +param scale := 1000; + +# Colors +# saturation [0, 255] +param sat := 192; +param hue{c in C} := 6 * (c - 1) / nc; +param red{c in C} := + if hue[c] <= 1 or hue[c] >= 5 then 255 + else (if hue[c] >=2 and hue[c] <= 4 then 255 - sat + else (if hue[c] <=2 then 255 - sat + sat * (2-hue[c]) + else 255 - sat + sat * (hue[c]-4) )); +param green{c in C} := + if hue[c] >= 1 and hue[c] <= 3 then 255 + else (if hue[c] >= 4 then 255 - sat + else (if hue[c] <=1 then 255 - sat + sat * hue[c] + else 255 - sat + sat * (4-hue[c]) )); +param blue{c in C} := + if hue[c] >= 3 and hue[c] <= 5 then 255 + else (if hue[c] <=2 then 255 - sat + else (if hue[c] <=3 then 255 - sat + sat * (hue[c]-2) + else 255 - sat + sat * (6-hue[c]) )); + +var x{T}; +var y{T,T}, binary; + +minimize obj : sum{c in T, t in T} y[c,t] * pt[t] + * sqrt((xt[c] - xt[t])^2 + (yt[c] - yt[t])^2); + +s.t. sumx : sum{c in T} x[c] = nc; +s.t. cxy{c in T, t in T} : y[c,t] <= x[c]; +s.t. sumy{t in T} : sum{c in T} y[c,t] = 1; + +solve; + +for {c in T : x[c] > .5} { + printf "Center %5.4f %5.4f\n", xt[c], yt[c]; + for {t in T : y[c,t] > .5} { + printf " Town %5.4f %5.4f (%5.0f)\n", xt[t], yt[t], pt[t]; + } +} + +# Output the solution as scalable vector graphic + +# header +printf "\n" > f; +printf "> f; +printf """http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"">\n" >> f; +printf "> f; +printf "xmlns=""http://www.w3.org/2000/svg"">\n" >> f; + +# background +printf "\n", + 1.2 * scale, 1.2 * scale>> f; + +# border +printf "\n", + .1 * scale, .1 * scale, scale, scale >> f; + +# circles for towns +for {t in T} + printf {s in T, c in C : y[s,t] > .5 + && c = floor( .5 + sum{u in T : u <= s} x[u])} + "\n", + (.1 + xt[t]) * scale, (.1 + yt[t]) * scale, .001 * sqrt(pt[t]) * scale, + red[c], green[c] , blue[c] >> f; + +# lines from towns to assigned centers +for {t in T, c in T : y[c,t] > .5} + printf "\n", + (.1 + xt[c]) * scale, (.1 + yt[c]) * scale, + (.1 + xt[t]) * scale, (.1 + yt[t]) * scale >> f; + +printf "\n" >> f; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/multiseed.c b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/multiseed.c new file mode 100644 index 000000000..9f8727a34 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/multiseed.c @@ -0,0 +1,259 @@ +/* multiseed.c (multithreading demo) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Heinrich Schuchardt +* +* Copyright (C) 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +/* + * This program demonstrates running the GLPK library with multiple threads. + * + * When called the program requires two arguments: + * + * filename - the name of the MathProg model to be solved + * threads - the count of parallel threads to be run. + * + * Each thread is run with a different seed for the random number generator + * provided by the GLPK library. + */ + +#include +#include +#include +#include +#include +#include + +#include "thread.h" + +#define BUFLEN 256 + +/* Task descriptor */ +struct task { + pthread_t tid; + char *filename; + int seed; + size_t pos; + char buf[BUFLEN + 1]; + int line; + jmp_buf jmp; +}; + +/* Mutex for console output */ +pthread_mutex_t mutex; + +/* Console output handler */ +int term_hook(void *info, const char *text) +{ + struct task *task = (struct task *) info; + size_t len = strlen(text); + + /* Lock mutex so this is the only task creating console output. */ + pthread_mutex_lock(&mutex); + + /* Append the new text to the buffer. */ + if (task->pos + len > BUFLEN) { + printf("%02d-%05d %s%s", task->seed, ++task->line, task->buf, text); + task->pos = 0; + task->buf[0] = 0; + } else { + strcpy(task->buf + task->pos, text); + task->pos += len; + } + + /* If a complete line is available, send it to the console. */ + if (strchr(task->buf, '\n')) { + printf("%02d-%05d %s", task->seed, ++task->line, task->buf); + task->pos = 0; + task->buf[0] = 0; + } + + /* Unlock the mutex. */ + pthread_mutex_unlock(&mutex); + + /* Disable default output. */ + return -1; +} + +/* Error handler */ +void error_hook(void *info) +{ + struct task *task = (struct task *) info; + + term_hook(task, "Error caught\n"); + glp_free_env(); + longjmp(task->jmp, 1); +} + +void worker(void *arg) +{ + struct task *task = (struct task *) arg; + int ret; + glp_prob *lp; + glp_tran *tran; + glp_iocp iocp; + + if (setjmp(task->jmp)) { + /* If an error is caught leave the function. */ + return; + } + + /* Set the error handler. */ + glp_error_hook(error_hook, task); + + /* Set the console output handler. */ + glp_term_hook(term_hook, arg); + + glp_printf("Seed %02d\n", task->seed); + + /* Create the problem object. */ + lp = glp_create_prob(); + if (!lp) { + glp_error("Out of memory\n"); + } + + /* Create the MathProg translator workspace. */ + tran = glp_mpl_alloc_wksp(); + if (!lp) { + glp_error("Out of memory\n"); + } + + /* Set the pseudo random number generator seed. */ + glp_mpl_init_rand(tran, task->seed); + + /* Read the model file. */ + ret = glp_mpl_read_model (tran, task->filename, GLP_OFF); + if (ret != 0) { + glp_error("Model %s is not valid\n", task->filename); + } + + /* Generate the model. */ + ret = glp_mpl_generate(tran, NULL); + if (ret != 0) { + glp_error("Cannot generate model %s\n", task->filename); + } + + /* Build the problem. */ + glp_mpl_build_prob(tran, lp); + + /* Solve the problem. */ + glp_init_iocp(&iocp); + iocp.presolve = GLP_ON; + ret = glp_intopt(lp, &iocp); + if (ret == 0) { + /* Execute the post solve part of the model. */ + glp_mpl_postsolve(tran, lp, GLP_MIP); + } + + /* Release the memory. */ + glp_mpl_free_wksp (tran); + glp_delete_prob(lp); + + if (0 == task->seed % 3) { + glp_error("Voluntarily throwing an error in %s at line %d\n", + __FILE__, __LINE__); + } + + glp_term_hook(NULL, NULL); + + glp_error_hook(NULL, NULL); + + glp_free_env(); +} + +#ifdef __WOE__ +DWORD run(void *arg) +{ +#else +void *run(void *arg) +{ +#endif + worker(arg); + pthread_exit(NULL); +} + +int main(int argc, char *argv[]) +{ + int i, n, rc; + struct task *tasks; + + /* Make sure thread local memory is used by the GLPK library. */ + if (!glp_config("TLS")) { + printf("The loaded GLPK library does not support thread local memory.\n" + "You need a version of the library configured with " + "--enable-reentrant=yes to run this program.\n"); + exit(EXIT_FAILURE); + } + + /* Check program arguments. */ + if (argc != 3) { + printf("Usage %s filename threads\n" + " filename - MathProg model file\n" + " threads - number of threads\n", + argv[0]); + exit(EXIT_FAILURE); + } + + /* Parse the arguments. */ + n = atoi(argv[2]); + if (n > 50) { + printf("Number of threads is to high (> 50).\n"); + exit(EXIT_FAILURE); + } + if (n <= 1) { + printf("Need positive number of threads\n"); + exit(EXIT_FAILURE); + } + + /* Allocate memory for the task descriptors. */ + tasks = calloc(n, sizeof(struct task)); + if (!tasks) { + printf("Out of memory"); + exit(EXIT_FAILURE); + } + + /* Create a mutex for console output. */ + pthread_mutex_init(&mutex, NULL); + + /* Create the threads. */ + for (i = 0; i < n; ++i) { + tasks[i].filename = argv[1]; + tasks[i].seed = i + 1; + tasks[i].pos = 0; + tasks[i].buf[0] = 0; + tasks[i].line = 0; + rc = pthread_create(&tasks[i].tid, NULL, run, &tasks[i]); + if (rc) { + printf("ERROR; return code from pthread_create() is %d\n", rc); + exit(EXIT_FAILURE); + } + } + + /* Wait for all threads to complete. */ + for (i = 0; i < n; ++i) { + pthread_join(tasks[i].tid, NULL); + } + + /* Destroy the mutex. */ + pthread_mutex_destroy(&mutex); + + return EXIT_SUCCESS; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/threads/thread.h b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/thread.h new file mode 100644 index 000000000..6ed779bcd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/threads/thread.h @@ -0,0 +1,49 @@ +/* thread.h (pthread emulation for Windows) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2011-2017, Heinrich Schuchardt +* +* Permission to use, copy, modify, and/or distribute this software for +* any purpose with or without fee is hereby granted. +* +* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA +* OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +***********************************************************************/ + +#ifndef THREAD_H + +#define THREAD_H 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#ifdef __WOE__ +#include +typedef CRITICAL_SECTION pthread_mutex_t; +typedef HANDLE pthread_t; +// @todo The return type of routine C is "DWORD" for Windows and +// "void *" for Posix. +#define pthread_create(A,B,C,D) \ + (int)((*A = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&C,D,0,NULL))==NULL) +#define pthread_exit(A) ExitThread(0) +#define pthread_mutex_destroy(A) DeleteCriticalSection(A) +#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) +#define pthread_mutex_lock(A) (EnterCriticalSection(A),0) +#define pthread_mutex_unlock(A) (LeaveCriticalSection(A),0) +#define pthread_self() GetCurrentThreadId() +#define pthread_join(A, B) \ + (WaitForSingleObject(A, INFINITE),CloseHandle(A),0) +#else +#include +#endif + +#endif // THREAD_H diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tiling.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/tiling.mod new file mode 100644 index 000000000..6e0cabd95 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tiling.mod @@ -0,0 +1,118 @@ +/* Rectifiable polyomino tilings generator */ + +/* Written and converted to GNU MathProg by NASZVADI, Peter, 2007-2017 + */ + +/* + This model searches for a maximal packing of a given polyomino + composed of unit squares in a given rectangle. In a feasible packing, a + placed polyomino and its intersection of a unit square's inner part in + the rectangle must be the square or empty. If there exists a packing + that covers totally the rectangle, then the polyomino is called + "rectifiable" + + Summary: + Decides if an Im * Jm rectangle could be tiled with given pattern + and prints a (sub)optimal solution if found + + Generated magic numbers are implicit tables, check them: + + # for magic in 3248 688 1660 3260 + do printf "Magic % 5d:" "$magic" + for e in 0 1 2 3 4 5 6 7 + do printf "% 3d" "$((-1 + ((magic / (3**e)) % 3)))" + done + echo + done + Magic 3248: 1 1 -1 -1 0 0 0 0 + Magic 688: 0 0 0 0 1 1 -1 -1 + Magic 1660: 0 0 0 0 1 -1 1 -1 + Magic 3260: 1 -1 1 -1 0 0 0 0 + # +*/ + +param Im, default 3; +/* vertical edge length of the box */ + +param Jm, default 3; +/* horizontal edge length of the box */ + +set S, default {(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2)}; +/* P-heptomino is the default shape. More info on this heptomino: + http://www.cflmath.com/Polyomino/7omino4_rect.html */ + +set I := 1..Im; +/* rows of rectangle */ + +set J := 1..Jm; +/* columns of rectangle */ + +set IJ := I cross J; +/* the rectangle itself */ + +set E := 0..7; +/* helper set to allow iterating on all transformations of the S shape */ + +set Shifts := setof{(i, j, e) in IJ cross E: + setof{(x, y) in S} + ((x * (-1 + floor(3248 / 3^e) mod 3)) + + (y * (-1 + floor(688 / 3^e) mod 3)) + i, + (x * (-1 + floor(1660 / 3^e) mod 3)) + + (y * (-1 + floor(3260 / 3^e) mod 3)) + j) within IJ}(i, j, e); +/* all shifted, flipped, rotated, mirrored mappings of polyomino that + contained by the rectangle */ + +var cell{IJ}, binary; +/* booleans denoting if a cell is covered in the rectangle */ + +var tile{Shifts}, binary; +/* booleans denoting usage of a shift */ + +var objvalue; + +s.t. covers{(i, j) in IJ}: sum{(k, l, e, a, b) in Shifts cross S: + i = k + a * (-1 + floor(3248 / 3^e) mod 3) + + b * (-1 + floor(688 / 3^e) mod 3) + and + j = l + a * (-1 + floor(1660 / 3^e) mod 3) + + b * (-1 + floor(3260 / 3^e) mod 3) + }tile[k, l, e] = cell[i, j]; + +s.t. objeval: sum{(i, j) in IJ}cell[i, j] - objvalue = 0; + +maximize obj: objvalue; + +solve; + +printf '\nCovered cells/all cells = %d/%d\n\n', objvalue.val, Im * Jm; +printf '\nA tiling:\n\n'; +for{i in I}{ + for{j in J}{ + printf '%s', if cell[i, j].val then '' else ' *** '; + for{(k, l, e, a, b) in Shifts cross S: + cell[i, j].val + and i = k + a * (-1 + floor(3248 / 3^e) mod 3) + + b * (-1 + floor(688 / 3^e) mod 3) + and j = l + a * (-1 + floor(1660 / 3^e) mod 3) + + b * (-1 + floor(3260 / 3^e) mod 3) + and tile[k, l, e].val + }{ + printf '% 5d', (k * Jm + l) * 8 + e; + } + } + printf '\n'; +} +printf '\n'; + +data; + +param Im := 14; +/* here can be set rectangle's one side */ + +param Jm := 14; +/* here can be set rectangle's other side */ + +set S := (0,0),(1,0),(2,0),(0,1),(1,1),(2,1),(0,2); +/* here you can specify arbitrary polyomino */ + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/todd.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/todd.mod new file mode 100644 index 000000000..c0ef44b4c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/todd.mod @@ -0,0 +1,36 @@ +/* TODD, a class of hard instances of zero-one knapsack problems */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* Chvatal describes a class of instances of zero-one knapsack problems + due to Todd. He shows that a wide class of algorithms - including all + based on branch and bound or dynamic programming - find it difficult + to solve problems in the Todd class. More exactly, the time required + by these algorithms to solve instances of problems that belong to the + Todd class grows as an exponential function of the problem size. + + Reference: + Chvatal V. (1980), Hard knapsack problems, Op. Res. 28, 1402-1411. */ + +param n > 0 integer; + +param log2_n := log(n) / log(2); + +param k := floor(log2_n); + +param a{j in 1..n} := 2 ** (k + n + 1) + 2 ** (k + n + 1 - j) + 1; + +param b := 0.5 * floor(sum{j in 1..n} a[j]); + +var x{1..n} binary; + +maximize obj: sum{j in 1..n} a[j] * x[j]; + +s.t. cap: sum{j in 1..n} a[j] * x[j] <= b; + +data; + +param n := 15; +/* change this parameter to choose a particular instance */ + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/toto.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/toto.mod new file mode 100644 index 000000000..6b4318edc --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/toto.mod @@ -0,0 +1,135 @@ +/* Covering code generator, especially for football pool systems */ + +/* Written and converted to GNU MathProg by NASZVADI, Peter, 199x-2017 + */ + +/* + Looks up for minimal covering codes in the specified Hamming-space. + Without specifying model data, by default it looks up for covering + for a mixed covering code in Hamming-space {X, 1, 2, 3}*{X, 1}^4 + with one layer. + + Hamming space is a set of finite words with all the same length over + a finite alphabet: the space could be decomposed to Cartesian + products of subsets of the alphabet, e.g. the first letter of an + element can be chosen from a 2-element set, the next from 6 letters, + and so on. + + There is a natural metric function in these spaces: the + Hamming-distance (hence the name, from now referred as: distance). + The distance of two (equal-length) words is the number of different + letter pairs in the corresponding positions. + + Covering Hamming-spaces with minimal number of spheres with given + radius - usually difficult problem excluding special cases. + + Relationship with sports: + Football pool system in Hungarian: "Toto'kulcs", so Toto, totogol and + other football pool systems are usually need mixed ternary/binary + code coverings in order to minimize loss of the gambler. + + See more at: + https://en.wikipedia.org/wiki/Covering_code + + A tricky workaround is used: + floor(), abs() and cosine() magic are used at 'coverings' constraints, + because GMPL lacks proper boolean<->integer evaluation/casting. +*/ + +param ArgNum1, >= 1, default 1; +param ArgNum2, >= 1, default 1; +param ArgNum3, >= 1, default 1; +param ArgNum4, >= 1, default 1; +param ArgNum5, >= 1, default 1; +param ArgNum6, >= 1, default 1; +param ArgNum7, >= 1, default 1; +param ArgNum8, >= 1, default 1; +param ArgNum9, >= 1, default 1; +param ArgNum10, >= 1, default 1; +param ArgNum11, >= 1, default 1; +param ArgNum12, >= 1, default 1; +param ArgNum13, >= 1, default 1; +/* at most 13 matches' outcomes */ + +param Radius, >= 1, default 1; +/* covering radius */ + +param Layer, >= 1, default 1; +/* each point of space must be covered at least Layer times */ + +set X := 0..ArgNum1 - 1 cross 0..ArgNum2 - 1 cross 0..ArgNum3 - 1 cross + 0..ArgNum4 - 1 cross 0..ArgNum5 - 1 cross 0..ArgNum6 - 1 cross + 0..ArgNum7 - 1 cross 0..ArgNum8 - 1 cross 0..ArgNum9 - 1 cross + 0..ArgNum10 - 1 cross 0..ArgNum11 - 1 cross 0..ArgNum12 - 1 cross + 0..ArgNum13 - 1; +/* the Hamming-space generated by the Cartesian-products of sets + with elements ArgNum[n] */ + +var x{X}, integer, >=0; +/* denotes each point's amount of containing covering sets */ + +var objvalue; + +s.t. coverings{(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13) in X}: + sum{(j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13) in X: + floor(abs(cos(i1 - j1))) + floor(abs(cos(i2 - j2))) + + floor(abs(cos(i3 - j3))) + floor(abs(cos(i4 - j4))) + + floor(abs(cos(i5 - j5))) + floor(abs(cos(i6 - j6))) + + floor(abs(cos(i7 - j7))) + floor(abs(cos(i8 - j8))) + + floor(abs(cos(i9 - j9))) + floor(abs(cos(i10 - j10))) + + floor(abs(cos(i11 - j11))) + floor(abs(cos(i12 - j12))) + + floor(abs(cos(i13 - j13))) >= 13 - Radius + } x[j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13] >= Layer; +/* covering constraints, select at least 'Layer' amount of spheres that cover + (i1,i2,...) and has radius 'Radius' */ + +s.t. oneisset: x[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] >= 1; +/* this does not violate symmetry nor excludes important solutions but + boosts the solving process */ + +s.t. objc: sum{(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13) in X} + x[i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13] = objvalue; +/* the total number of pools (covering sets) */ + +minimize obj: objvalue; +/* Also 'objc' could be used directly instead of 'obj', but for + experiments, it is useful to set up additional constraints for + introduced objvalue variable */ + +solve; + +printf 'Solution: %s\nRadius: %s\nLayer: %s\n', + objvalue.val, Radius, Layer; +/* report important scalars */ + +printf 'Selected bets:\n'; +for{(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13) in X: + x[i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13]}{ + printf ' Times %s:', + x[i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13].val; + printf '%s', if ArgNum1 == 1 then '' else ' ' & if i1 then i1 else 'X'; + printf '%s', if ArgNum2 == 1 then '' else '-' & if i2 then i2 else 'X'; + printf '%s', if ArgNum3 == 1 then '' else '-' & if i3 then i3 else 'X'; + printf '%s', if ArgNum4 == 1 then '' else '-' & if i4 then i4 else 'X'; + printf '%s', if ArgNum5 == 1 then '' else '-' & if i5 then i5 else 'X'; + printf '%s', if ArgNum6 == 1 then '' else '-' & if i6 then i6 else 'X'; + printf '%s', if ArgNum7 == 1 then '' else '-' & if i7 then i7 else 'X'; + printf '%s', if ArgNum8 == 1 then '' else '-' & if i8 then i8 else 'X'; + printf '%s', if ArgNum9 == 1 then '' else '-' & if i9 then i9 else 'X'; + printf '%s', if ArgNum10 == 1 then '' else '-' & if i10 then i10 else 'X'; + printf '%s', if ArgNum11 == 1 then '' else '-' & if i11 then i11 else 'X'; + printf '%s', if ArgNum12 == 1 then '' else '-' & if i12 then i12 else 'X'; + printf '%s', if ArgNum13 == 1 then '' else '-' & if i13 then i13 else 'X'; + printf '\n'; +} +/* pretty-print a generated football pool system (covering code) */ + +data; + +param ArgNum1 := 4; +param ArgNum2 := 2; +param ArgNum3 := 2; +param ArgNum4 := 2; +param ArgNum5 := 2; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/train.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/train.mod new file mode 100644 index 000000000..a17520ea1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/train.mod @@ -0,0 +1,281 @@ +# TRAIN, a model of railroad passenger car allocation +# +# References: +# Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language +# for Mathematical Programming." Management Science 36 (1990) 519-554. + +### SCHEDULE SETS AND PARAMETERS ### + +set cities; + +set links within {c1 in cities, c2 in cities: c1 <> c2}; + + # Set of cities, and set of intercity links + +param last > 0 integer; # Number of time intervals in a day + +set times := 1..last; # Set of time intervals in a day + +set schedule within + {c1 in cities, t1 in times, + c2 in cities, t2 in times: (c1,c2) in links}; + + # Member (c1,t1,c2,t2) of this set represents + # a train that leaves city c1 at time t1 + # and arrives in city c2 at time t2 + +### DEMAND PARAMETERS ### + +param section > 0 integer; + + # Maximum number of cars in one section of a train + +param demand {schedule} > 0; + + # For each scheduled train: + # the smallest number of cars that + # can meet demand for the train + +param low {(c1,t1,c2,t2) in schedule} := ceil(demand[c1,t1,c2,t2]); + + # Minimum number of cars needed to meet demand + +param high {(c1,t1,c2,t2) in schedule} + + := max (2, min (ceil(2*demand[c1,t1,c2,t2]), + section*ceil(demand[c1,t1,c2,t2]/section) )); + + # Maximum number of cars allowed on a train: + # 2 if demand is for less than one car; + # otherwise, lesser of + # number of cars needed to hold twice the demand, and + # number of cars in minimum number of sections needed + +### DISTANCE PARAMETERS ### + +param dist_table {links} >= 0 default 0.0; + +param distance {(c1,c2) in links} > 0 + := if dist_table[c1,c2] > 0 then dist_table[c1,c2] else dist_table[c2,c1]; + + # Inter-city distances: distance[c1,c2] is miles + # between city c1 and city c2 + +### VARIABLES ### + +var U 'cars stored' {cities,times} >= 0; + + # u[c,t] is the number of unused cars stored + # at city c in the interval beginning at time t + +var X 'cars in train' {schedule} >= 0; + + # x[c1,t1,c2,t2] is the number of cars assigned to + # the scheduled train that leaves c1 at t1 and + # arrives in c2 at t2 + +### OBJECTIVES ### + +minimize cars: + sum {c in cities} U[c,last] + + sum {(c1,t1,c2,t2) in schedule: t2 < t1} X[c1,t1,c2,t2]; + + # Number of cars in the system: + # sum of unused cars and cars in trains during + # the last time interval of the day + +minimize miles: + sum {(c1,t1,c2,t2) in schedule} distance[c1,c2] * X[c1,t1,c2,t2]; + + # Total car-miles run by all scheduled trains in a day + +### CONSTRAINTS ### + +account {c in cities, t in times}: + + U[c,t] = U[c, if t > 1 then t-1 else last] + + + sum {(c1,t1,c,t) in schedule} X[c1,t1,c,t] - + sum {(c,t,c2,t2) in schedule} X[c,t,c2,t2]; + + # For every city and time: + # unused cars in the present interval must equal + # unused cars in the previous interval, + # plus cars just arriving in trains, + # minus cars just leaving in trains + +satisfy {(c1,t1,c2,t2) in schedule}: + + low[c1,t1,c2,t2] <= X[c1,t1,c2,t2] <= high[c1,t1,c2,t2]; + + # For each scheduled train: + # number of cars must meet demand, + # but must not be so great that unnecessary + # sections are run + +### DATA ### + +data; + +set cities := BO NY PH WA ; + +set links := (BO,NY) (NY,PH) (PH,WA) + (NY,BO) (PH,NY) (WA,PH) ; + +param dist_table := [*,*] BO NY 232 + NY PH 90 + PH WA 135 ; + +param last := 48 ; + +param section := 14 ; + +set schedule := + + (WA,*,PH,*) 2 5 6 9 8 11 10 13 + 12 15 13 16 14 17 15 18 + 16 19 17 20 18 21 19 22 + 20 23 21 24 22 25 23 26 + 24 27 25 28 26 29 27 30 + 28 31 29 32 30 33 31 34 + 32 35 33 36 34 37 35 38 + 36 39 37 40 38 41 39 42 + 40 43 41 44 42 45 44 47 + 46 1 + + (PH,*,NY,*) 1 3 5 7 9 11 11 13 + 13 15 14 16 15 17 16 18 + 17 19 18 20 19 21 20 22 + 21 23 22 24 23 25 24 26 + 25 27 26 28 27 29 28 30 + 29 31 30 32 31 33 32 34 + 33 35 34 36 35 37 36 38 + 37 39 38 40 39 41 40 42 + 41 43 42 44 43 45 44 46 + 45 47 47 1 + + (NY,*,BO,*) 10 16 12 18 14 20 15 21 + 16 22 17 23 18 24 19 25 + 20 26 21 27 22 28 23 29 + 24 30 25 31 26 32 27 33 + 28 34 29 35 30 36 31 37 + 32 38 33 39 34 40 35 41 + 36 42 37 43 38 44 39 45 + 40 46 41 47 42 48 43 1 + 44 2 45 3 46 4 48 6 + + (BO,*,NY,*) 7 13 9 15 11 17 12 18 + 13 19 14 20 15 21 16 22 + 17 23 18 24 19 25 20 26 + 21 27 22 28 23 29 24 30 + 25 31 26 32 27 33 28 34 + 29 35 30 36 31 37 32 38 + 33 39 34 40 35 41 36 42 + 37 43 38 44 39 45 40 46 + 41 47 43 1 45 3 47 5 + + (NY,*,PH,*) 1 3 12 14 13 15 14 16 + 15 17 16 18 17 19 18 20 + 19 21 20 22 21 23 22 24 + 23 25 24 26 25 27 26 28 + 27 29 28 30 29 31 30 32 + 31 33 32 34 33 35 34 36 + 35 37 36 38 37 39 38 40 + 39 41 40 42 41 43 42 44 + 43 45 44 46 45 47 46 48 + 47 1 + + (PH,*,WA,*) 1 4 14 17 15 18 16 19 + 17 20 18 21 19 22 20 23 + 21 24 22 25 23 26 24 27 + 25 28 26 29 27 30 28 31 + 29 32 30 33 31 34 32 35 + 33 36 34 37 35 38 36 39 + 37 40 38 41 39 42 40 43 + 41 44 42 45 43 46 44 47 + 45 48 46 1 47 2 ; + +param demand := + + [WA,*,PH,*] 2 5 .55 6 9 .01 8 11 .01 + 10 13 .13 12 15 1.59 13 16 1.69 + 14 17 5.19 15 18 3.55 16 19 6.29 + 17 20 4.00 18 21 5.80 19 22 3.40 + 20 23 4.88 21 24 2.92 22 25 4.37 + 23 26 2.80 24 27 4.23 25 28 2.88 + 26 29 4.33 27 30 3.11 28 31 4.64 + 29 32 3.44 30 33 4.95 31 34 3.73 + 32 35 5.27 33 36 3.77 34 37 4.80 + 35 38 3.31 36 39 3.89 37 40 2.65 + 38 41 3.01 39 42 2.04 40 43 2.31 + 41 44 1.52 42 45 1.75 44 47 1.88 + 46 1 1.05 + + [PH,*,NY,*] 1 3 1.05 5 7 .43 9 11 .20 + 11 13 .21 13 15 .40 14 16 6.49 + 15 17 16.40 16 18 9.48 17 19 17.15 + 18 20 9.31 19 21 15.20 20 22 8.21 + 21 23 13.32 22 24 7.35 23 25 11.83 + 24 26 6.61 25 27 10.61 26 28 6.05 + 27 29 9.65 28 30 5.61 29 31 9.25 + 30 32 5.40 31 33 8.24 32 34 4.84 + 33 35 7.44 34 36 4.44 35 37 6.80 + 36 38 4.11 37 39 6.25 38 40 3.69 + 39 41 5.55 40 42 3.29 41 43 4.77 + 42 44 2.91 43 45 4.19 44 46 2.53 + 45 47 4.00 47 1 1.65 + + [NY,*,BO,*] 10 16 1.23 12 18 3.84 14 20 4.08 + 15 21 1.47 16 22 2.96 17 23 1.60 + 18 24 2.95 19 25 1.71 20 26 2.81 + 21 27 1.77 22 28 2.87 23 29 1.84 + 24 30 2.95 25 31 1.91 26 32 3.12 + 27 33 1.93 28 34 3.31 29 35 2.00 + 30 36 3.40 31 37 2.08 32 38 3.41 + 33 39 2.69 34 40 4.45 35 41 2.32 + 36 42 3.40 37 43 1.80 38 44 2.63 + 39 45 1.52 40 46 2.23 41 47 1.25 + 42 48 1.79 43 1 .97 44 2 1.28 + 45 3 .48 46 4 .68 48 6 .08 + + [BO,*,NY,*] 7 13 .03 9 15 1.29 11 17 4.59 + 12 18 2.56 13 19 3.92 14 20 2.37 + 15 21 3.81 16 22 2.24 17 23 3.51 + 18 24 2.13 19 25 3.28 20 26 2.05 + 21 27 3.15 22 28 1.99 23 29 3.09 + 24 30 1.93 25 31 3.19 26 32 1.91 + 27 33 3.21 28 34 1.85 29 35 3.21 + 30 36 1.71 31 37 3.04 32 38 2.08 + 33 39 3.13 34 40 1.96 35 41 2.53 + 36 42 1.43 37 43 2.04 38 44 1.12 + 39 45 1.71 40 46 .91 41 47 1.32 + 43 1 1.80 45 3 1.13 47 5 .23 + + [NY,*,PH,*] 1 3 .04 12 14 4.68 13 15 5.61 + 14 16 3.56 15 17 5.81 16 18 3.81 + 17 19 6.31 18 20 4.07 19 21 7.33 + 20 22 4.55 21 23 7.37 22 24 4.73 + 23 25 7.61 24 26 4.92 25 27 7.91 + 26 28 5.19 27 29 8.40 28 30 5.53 + 29 31 9.32 30 32 5.51 31 33 10.33 + 32 34 9.21 33 35 18.95 34 36 11.23 + 35 37 16.85 36 38 7.29 37 39 10.89 + 38 40 5.41 39 41 8.21 40 42 4.52 + 41 43 6.99 42 44 3.92 43 45 6.21 + 44 46 3.44 45 47 5.17 46 48 2.55 + 47 1 1.24 + + [PH,*,WA,*] 1 4 .20 14 17 4.49 15 18 3.53 + 16 19 2.67 17 20 3.83 18 21 3.01 + 19 22 4.12 20 23 3.15 21 24 4.67 + 22 25 3.20 23 26 4.23 24 27 2.87 + 25 28 3.84 26 29 2.60 27 30 3.80 + 28 31 2.77 29 32 4.31 30 33 3.16 + 31 34 4.88 32 35 3.45 33 36 5.55 + 34 37 3.52 35 38 6.11 36 39 3.32 + 37 40 5.53 38 41 3.03 39 42 4.51 + 40 43 2.53 41 44 3.39 42 45 1.93 + 43 46 2.52 44 47 1.20 45 48 1.75 + 46 1 .88 47 2 .87 ; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/transp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/transp.mod new file mode 100644 index 000000000..a7cb939ae --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/transp.mod @@ -0,0 +1,63 @@ +# A TRANSPORTATION PROBLEM +# +# This problem finds a least cost shipping schedule that meets +# requirements at markets and supplies at factories. +# +# References: +# Dantzig G B, "Linear Programming and Extensions." +# Princeton University Press, Princeton, New Jersey, 1963, +# Chapter 3-3. + +set I; +/* canning plants */ + +set J; +/* markets */ + +param a{i in I}; +/* capacity of plant i in cases */ + +param b{j in J}; +/* demand at market j in cases */ + +param d{i in I, j in J}; +/* distance in thousands of miles */ + +param f; +/* freight in dollars per case per thousand miles */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* transport cost in thousands of dollars per case */ + +var x{i in I, j in J} >= 0; +/* shipment quantities in cases */ + +minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; +/* total transportation costs in thousands of dollars */ + +s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observe supply limit at plant i */ + +s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfy demand at market j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/trick.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/trick.mod new file mode 100644 index 000000000..df5717b8a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/trick.mod @@ -0,0 +1,72 @@ +/* TRICK, A Transportation Design Problem */ + +/* Translated from the Mosel modeling language to GNU MathProg by + Andrew Makhorin */ + +/* This example model is described in the article "Formulations and + Reformulations in Integer Programming" by Michael Trick (it is + publicly available at http://mat.gsia.cmu.edu/trick/formul04.pdf). + + This model demonstrates an amazing effect when including in the + formulation an additional constraint, which is redundant even for + LP relaxation, makes the model easy for solving with the B&B. */ + +set TRUCKS := 1..10; + +set PACKAGES := 1..20; + +param capacity{TRUCKS}; + +param size{PACKAGES}; + +param cost{TRUCKS}; + +param can_use{PACKAGES, TRUCKS}; + +var x{PACKAGES, TRUCKS}, binary; + +var y{TRUCKS}, binary; + +minimize total: sum{i in TRUCKS} cost[i] * y[i]; + +f1{i in TRUCKS}: + sum{j in PACKAGES} size[j] * x[j,i] <= capacity[i] * y[i]; + +f2{i in TRUCKS, j in PACKAGES}: + x[j,i] <= y[i]; + +f3{j in PACKAGES}: + sum{i in TRUCKS} can_use[j,i] * x[j,i] = 1; + +redundant_constraint: + sum{i in TRUCKS} capacity[i] * y[i] >= sum{j in PACKAGES} size[j]; + +data; + +param capacity := + [1] 100 [2] 200 [3] 100 [4] 200 [5] 100 [6] 200 [7] 100 [8] 200 + [9] 100 [10] 200; + +param size := + [1] 17 [2] 21 [3] 54 [4] 45 [5] 87 [6] 34 [7] 23 [8] 45 [9] 12 + [10] 43 [11] 54 [12] 39 [13] 31 [14] 26 [15] 75 [16] 48 [17] 16 + [18] 32 [19] 45 [20] 55; + +param cost := + [1] 1 [2] 1.8 [3] 1 [4] 1.8 [5] 1 [6] 1.8 [7] 1 [8] 1.8 [9] 1 + [10] 1.8; + +param can_use (tr): + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 := + 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 + 2 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0 + 3 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 + 4 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 + 5 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 + 6 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 + 7 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 + 8 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 + 9 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 + 10 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp.mod new file mode 100644 index 000000000..358245dae --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp.mod @@ -0,0 +1,335 @@ +/* TSP, Traveling Salesman Problem */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +/* The Traveling Salesman Problem (TSP) is stated as follows. + Let a directed graph G = (V, E) be given, where V = {1, ..., n} is + a set of nodes, E <= V x V is a set of arcs. Let also each arc + e = (i,j) be assigned a number c[i,j], which is the length of the + arc e. The problem is to find a closed path of minimal length going + through each node of G exactly once. */ + +param n, integer, >= 3; +/* number of nodes */ + +set V := 1..n; +/* set of nodes */ + +set E, within V cross V; +/* set of arcs */ + +param c{(i,j) in E}; +/* distance from node i to node j */ + +var x{(i,j) in E}, binary; +/* x[i,j] = 1 means that the salesman goes from node i to node j */ + +minimize total: sum{(i,j) in E} c[i,j] * x[i,j]; +/* the objective is to make the path length as small as possible */ + +s.t. leave{i in V}: sum{(i,j) in E} x[i,j] = 1; +/* the salesman leaves each node i exactly once */ + +s.t. enter{j in V}: sum{(i,j) in E} x[i,j] = 1; +/* the salesman enters each node j exactly once */ + +/* Constraints above are not sufficient to describe valid tours, so we + need to add constraints to eliminate subtours, i.e. tours which have + disconnected components. Although there are many known ways to do + that, I invented yet another way. The general idea is the following. + Let the salesman sell, say, cars, starting the travel from node 1, + where he has n cars. If we require the salesman to sell exactly one + car in each node, he will need to go through all nodes to satisfy + this requirement, thus, all subtours will be eliminated. */ + +var y{(i,j) in E}, >= 0; +/* y[i,j] is the number of cars, which the salesman has after leaving + node i and before entering node j; in terms of the network analysis, + y[i,j] is a flow through arc (i,j) */ + +s.t. cap{(i,j) in E}: y[i,j] <= (n-1) * x[i,j]; +/* if arc (i,j) does not belong to the salesman's tour, its capacity + must be zero; it is obvious that on leaving a node, it is sufficient + to have not more than n-1 cars */ + +s.t. node{i in V}: +/* node[i] is a conservation constraint for node i */ + + sum{(j,i) in E} y[j,i] + /* summary flow into node i through all ingoing arcs */ + + + (if i = 1 then n) + /* plus n cars which the salesman has at starting node */ + + = /* must be equal to */ + + sum{(i,j) in E} y[i,j] + /* summary flow from node i through all outgoing arcs */ + + + 1; + /* plus one car which the salesman sells at node i */ + +solve; + +printf "Optimal tour has length %d\n", + sum{(i,j) in E} c[i,j] * x[i,j]; +printf("From node To node Distance\n"); +printf{(i,j) in E: x[i,j]} " %3d %3d %8g\n", + i, j, c[i,j]; + +data; + +/* These data correspond to the symmetric instance ulysses16 from: + + Reinelt, G.: TSPLIB - A travelling salesman problem library. + ORSA-Journal of the Computing 3 (1991) 376-84; + http://elib.zib.de/pub/Packages/mp-testdata/tsp/tsplib */ + +/* The optimal solution is 6859 */ + +param n := 16; + +param : E : c := + 1 2 509 + 1 3 501 + 1 4 312 + 1 5 1019 + 1 6 736 + 1 7 656 + 1 8 60 + 1 9 1039 + 1 10 726 + 1 11 2314 + 1 12 479 + 1 13 448 + 1 14 479 + 1 15 619 + 1 16 150 + 2 1 509 + 2 3 126 + 2 4 474 + 2 5 1526 + 2 6 1226 + 2 7 1133 + 2 8 532 + 2 9 1449 + 2 10 1122 + 2 11 2789 + 2 12 958 + 2 13 941 + 2 14 978 + 2 15 1127 + 2 16 542 + 3 1 501 + 3 2 126 + 3 4 541 + 3 5 1516 + 3 6 1184 + 3 7 1084 + 3 8 536 + 3 9 1371 + 3 10 1045 + 3 11 2728 + 3 12 913 + 3 13 904 + 3 14 946 + 3 15 1115 + 3 16 499 + 4 1 312 + 4 2 474 + 4 3 541 + 4 5 1157 + 4 6 980 + 4 7 919 + 4 8 271 + 4 9 1333 + 4 10 1029 + 4 11 2553 + 4 12 751 + 4 13 704 + 4 14 720 + 4 15 783 + 4 16 455 + 5 1 1019 + 5 2 1526 + 5 3 1516 + 5 4 1157 + 5 6 478 + 5 7 583 + 5 8 996 + 5 9 858 + 5 10 855 + 5 11 1504 + 5 12 677 + 5 13 651 + 5 14 600 + 5 15 401 + 5 16 1033 + 6 1 736 + 6 2 1226 + 6 3 1184 + 6 4 980 + 6 5 478 + 6 7 115 + 6 8 740 + 6 9 470 + 6 10 379 + 6 11 1581 + 6 12 271 + 6 13 289 + 6 14 261 + 6 15 308 + 6 16 687 + 7 1 656 + 7 2 1133 + 7 3 1084 + 7 4 919 + 7 5 583 + 7 6 115 + 7 8 667 + 7 9 455 + 7 10 288 + 7 11 1661 + 7 12 177 + 7 13 216 + 7 14 207 + 7 15 343 + 7 16 592 + 8 1 60 + 8 2 532 + 8 3 536 + 8 4 271 + 8 5 996 + 8 6 740 + 8 7 667 + 8 9 1066 + 8 10 759 + 8 11 2320 + 8 12 493 + 8 13 454 + 8 14 479 + 8 15 598 + 8 16 206 + 9 1 1039 + 9 2 1449 + 9 3 1371 + 9 4 1333 + 9 5 858 + 9 6 470 + 9 7 455 + 9 8 1066 + 9 10 328 + 9 11 1387 + 9 12 591 + 9 13 650 + 9 14 656 + 9 15 776 + 9 16 933 + 10 1 726 + 10 2 1122 + 10 3 1045 + 10 4 1029 + 10 5 855 + 10 6 379 + 10 7 288 + 10 8 759 + 10 9 328 + 10 11 1697 + 10 12 333 + 10 13 400 + 10 14 427 + 10 15 622 + 10 16 610 + 11 1 2314 + 11 2 2789 + 11 3 2728 + 11 4 2553 + 11 5 1504 + 11 6 1581 + 11 7 1661 + 11 8 2320 + 11 9 1387 + 11 10 1697 + 11 12 1838 + 11 13 1868 + 11 14 1841 + 11 15 1789 + 11 16 2248 + 12 1 479 + 12 2 958 + 12 3 913 + 12 4 751 + 12 5 677 + 12 6 271 + 12 7 177 + 12 8 493 + 12 9 591 + 12 10 333 + 12 11 1838 + 12 13 68 + 12 14 105 + 12 15 336 + 12 16 417 + 13 1 448 + 13 2 941 + 13 3 904 + 13 4 704 + 13 5 651 + 13 6 289 + 13 7 216 + 13 8 454 + 13 9 650 + 13 10 400 + 13 11 1868 + 13 12 68 + 13 14 52 + 13 15 287 + 13 16 406 + 14 1 479 + 14 2 978 + 14 3 946 + 14 4 720 + 14 5 600 + 14 6 261 + 14 7 207 + 14 8 479 + 14 9 656 + 14 10 427 + 14 11 1841 + 14 12 105 + 14 13 52 + 14 15 237 + 14 16 449 + 15 1 619 + 15 2 1127 + 15 3 1115 + 15 4 783 + 15 5 401 + 15 6 308 + 15 7 343 + 15 8 598 + 15 9 776 + 15 10 622 + 15 11 1789 + 15 12 336 + 15 13 287 + 15 14 237 + 15 16 636 + 16 1 150 + 16 2 542 + 16 3 499 + 16 4 455 + 16 5 1033 + 16 6 687 + 16 7 592 + 16 8 206 + 16 9 933 + 16 10 610 + 16 11 2248 + 16 12 417 + 16 13 406 + 16 14 449 + 16 15 636 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/README b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/README new file mode 100644 index 000000000..7d497e58f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/README @@ -0,0 +1,37 @@ +This subdirectory contains an example application program, TSPSOL, +which is a stand-alone solver intended to solve the Symmetric Traveling +Salesman Problem (TSP) with the GLPK integer optimizer. + +Please note that this program is only an illustrative example that +illustrates generating "lazy" constraints during the branch-and-bound +search. It is *not* a state-of-the-art code, so only small-sized TSP +instances (perhaps, having up to 150-200 nodes) can be solved with this +program in a reasonable time. For more details see comments in the +source code. + +To build TSPSOL executable you need to run 'build.sh' script. Note that +you should have the GLPK library properly installed. + +To run the TSPSOL program use the following command: + + tspsol tsp-file + +where tsp-file specifies an input text file containing TSP data in +TSPLIB 95 format. + +Detailed description of the input format recognized by TSPSOL is given +in the report: Gerhard Reinelt, "TSPLIB 95". This report as well as +TSPLIB, a library of sample TSP instances, are freely available for +research purposes; see: +. + +This subdirectory also includes the following example TSP instances: + +dantzig42.tsp 42 cities (Dantzig) [from TSPLIB] +gr120.tsp 120 cities in Germany (Groetschel) [from TSPLIB] +moscow.tsp 68 cities in Moscow region (Makhorin) +sample.tsp small example from D.Phillips and A.Garcia-Diaz +ulysses16.tsp Odyssey of Ulysses (Groetschel/Padberg) [from TSPLIB] +ulysses22.tsp Odyssey of Ulysses (Groetschel/Padberg) [from TSPLIB] + +Please send comments to the mailing list. diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/bench.txt b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/bench.txt new file mode 100644 index 000000000..4596b2e39 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/bench.txt @@ -0,0 +1,56 @@ +Solver: TSPSOL for GLPK 4.56 +Computer: Intel Celeron J1800 2.41 GHz +OS: Debian GNU/Linux 8.1.0 "Jessie" +Compiler: GCC 4.7.2 (options used: -O2) +Test set: TSPLIB 95 + +Instance N Solution Lower Bound Nodes Iters Time,s Mem,MB +------------ --- ------------ ------------ -------- ------- ------ ------ +att48 48 10628 opt 1 336 < 1 1.2 +bayg29 29 1610 opt 1 173 < 1 0.3 +bays29 29 2020 opt 1 166 < 1 0.3 +berlin52 52 7542 opt 1 253 < 1 0.7 +bier127 127 118282 opt 29 1330 14 19.1 +brazil58 58 25395 opt 1 458 1 2.0 +brg180 180 1950 opt 131 20012 83 52.0 +burma14 14 3323 opt 1 55 < 1 0.1 +ch130 130 6110 opt 45 2212 38 24.2 +ch150 150 6528 opt 271 4967 138 27.5 +d198 98 15780 opt 259 11371 719 92.3 +dantzig42 42 699 opt 1 171 < 1 0.8 +eil51 51 426 opt 115 1368 2 2.4 +eil76 76 538 opt 1 517 < 1 2.2 +eil101 101 629 opt 1 838 4 9.9 +fri26 26 937 opt 1 125 < 1 0.2 +gr17 17 2085 opt 1 93 < 1 0.1 +gr21 21 2707 opt 1 82 < 1 0.1 +gr24 24 1272 opt 1 137 < 1 0.2 +gr48 48 5046 opt 3 407 1 2.3 +gr96 96 55209 opt 367 5564 63 12.4 +gr120 120 6942 opt 121 2940 46 14.7 +gr137 137 69853 opt 97 1934 27 16.2 +gr202 202 40160 opt 183 4176 287 88.4 +hk48 48 11461 opt 1 322 < 1 1.1 +kroA100 100 21282 opt 57 2227 23 13.2 +kroB100 100 22141 opt 71 1891 27 15.6 +kroC100 100 20749 opt 9 1035 5 9.4 +kroD100 100 21294 opt 9 1203 10 12.3 +kroE100 100 22068 opt 323 5055 100 13.4 +kroA150 150 26524 opt 431 8069 487 50.2 +kroB150 150 26130 opt 309 12599 610 43.1 +lin105 105 14379 opt 5 910 4 7.3 +lin318 318 42029 opt 1527 25885 4972 286.4 +pr76 76 108159 opt 20537 636616 9218 128.7 * +pr107 107 44303 opt 1 3692 38 33.2 +pr124 124 59030 opt 19 1306 23 25.6 +pr136 136 96772 opt 93 2799 60 27.7 +pr144 144 58537 opt 11 1948 37 32.2 +pr152 152 73682 opt 125 3269 99 46.0 +pr226 226 80369 opt 1 6699 240 163.8 +rat99 99 1211 opt 11 467 2 5,6 +rd100 100 7910 opt 1 868 3 7.2 +st70 70 675 opt 1 688 1 3.2 +swiss42 42 1273 opt 1 231 < 1 0.8 +u159 159 42080 opt 9 1356 15 30.0 +ulysses16 16 6859 opt 1 72 < 1 0.1 +ulysses22 22 7013 opt 1 110 < 1 0.2 diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/build.sh b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/build.sh new file mode 100755 index 000000000..ab6abc1fb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# +# Run this script to build TSPSOL executable. +# +# NOTE: you need to have GLPK properly installed. +# +gcc -O2 -otspsol main.c maxflow.c mincut.c misc.c tsplib.c -lglpk -lm +./tspsol sample.tsp diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/dantzig42.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/dantzig42.tsp new file mode 100644 index 000000000..15567bff1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/dantzig42.tsp @@ -0,0 +1,103 @@ +NAME : dantzig42 +TYPE : TSP +COMMENT : 42 cities (Dantzig) +DIMENSION : 42 +EDGE_WEIGHT_TYPE : EXPLICIT +EDGE_WEIGHT_FORMAT : LOWER_DIAG_ROW +DISPLAY_DATA_TYPE : TWOD_DISPLAY +EDGE_WEIGHT_SECTION + 0 8 0 39 45 0 37 47 9 0 50 49 21 15 0 61 62 21 + 20 17 0 58 60 16 17 18 6 0 59 60 15 20 26 17 10 0 + 62 66 20 25 31 22 15 5 0 81 81 40 44 50 41 35 24 20 + 0 103 107 62 67 72 63 57 46 41 23 0 108 117 66 71 77 68 + 61 51 46 26 11 0 145 149 104 108 114 106 99 88 84 63 49 40 + 0 181 185 140 144 150 142 135 124 120 99 85 76 35 0 187 191 146 + 150 156 142 137 130 125 105 90 81 41 10 0 161 170 120 124 130 115 + 110 104 105 90 72 62 34 31 27 0 142 146 101 104 111 97 91 85 + 86 75 51 59 29 53 48 21 0 174 178 133 138 143 129 123 117 118 + 107 83 84 54 46 35 26 31 0 185 186 142 143 140 130 126 124 128 + 118 93 101 72 69 58 58 43 26 0 164 165 120 123 124 106 106 105 + 110 104 86 97 71 93 82 62 42 45 22 0 137 139 94 96 94 80 + 78 77 84 77 56 64 65 90 87 58 36 68 50 30 0 117 122 77 + 80 83 68 62 60 61 50 34 42 49 82 77 60 30 62 70 49 21 + 0 114 118 73 78 84 69 63 57 59 48 28 36 43 77 72 45 27 + 59 69 55 27 5 0 85 89 44 48 53 41 34 28 29 22 23 35 + 69 105 102 74 56 88 99 81 54 32 29 0 77 80 36 40 46 34 + 27 19 21 14 29 40 77 114 111 84 64 96 107 87 60 40 37 8 + 0 87 89 44 46 46 30 28 29 32 27 36 47 78 116 112 84 66 + 98 95 75 47 36 39 12 11 0 91 93 48 50 48 34 32 33 36 + 30 34 45 77 115 110 83 63 97 91 72 44 32 36 9 15 3 0 + 105 106 62 63 64 47 46 49 54 48 46 59 85 119 115 88 66 98 + 79 59 31 36 42 28 33 21 20 0 111 113 69 71 66 51 53 56 + 61 57 59 71 96 130 126 98 75 98 85 62 38 47 53 39 42 29 + 30 12 0 91 92 50 51 46 30 34 38 43 49 60 71 103 141 136 + 109 90 115 99 81 53 61 62 36 34 24 28 20 20 0 83 85 42 + 43 38 22 26 32 36 51 63 75 106 142 140 112 93 126 108 88 60 + 64 66 39 36 27 31 28 28 8 0 89 91 55 55 50 34 39 44 + 49 63 76 87 120 155 150 123 100 123 109 86 62 71 78 52 49 39 + 44 35 24 15 12 0 95 97 64 63 56 42 49 56 60 75 86 97 + 126 160 155 128 104 128 113 90 67 76 82 62 59 49 53 40 29 25 + 23 11 0 74 81 44 43 35 23 30 39 44 62 78 89 121 159 155 + 127 108 136 124 101 75 79 81 54 50 42 46 43 39 23 14 14 21 + 0 67 69 42 41 31 25 32 41 46 64 83 90 130 164 160 133 114 + 146 134 111 85 84 86 59 52 47 51 53 49 32 24 24 30 9 0 + 74 76 61 60 42 44 51 60 66 83 102 110 147 185 179 155 133 159 + 146 122 98 105 107 79 71 66 70 70 60 48 40 36 33 25 18 0 + 57 59 46 41 25 30 36 47 52 71 93 98 136 172 172 148 126 158 + 147 124 121 97 99 71 65 59 63 67 62 46 38 37 43 23 13 17 + 0 45 46 41 34 20 34 38 48 53 73 96 99 137 176 178 151 131 + 163 159 135 108 102 103 73 67 64 69 75 72 54 46 49 54 34 24 + 29 12 0 35 37 35 26 18 34 36 46 51 70 93 97 134 171 176 + 151 129 161 163 139 118 102 101 71 65 65 70 84 78 58 50 56 62 + 41 32 38 21 9 0 29 33 30 21 18 35 33 40 45 65 87 91 + 117 166 171 144 125 157 156 139 113 95 97 67 60 62 67 79 82 62 + 53 59 66 45 38 45 27 15 6 0 3 11 41 37 47 57 55 58 + 63 83 105 109 147 186 188 164 144 176 182 161 134 119 116 86 78 84 + 88 101 108 88 80 86 92 71 64 71 54 41 32 25 0 5 12 55 + 41 53 64 61 61 66 84 111 113 150 186 192 166 147 180 188 167 140 + 124 119 90 87 90 94 107 114 77 86 92 98 80 74 77 60 48 38 + 32 6 0 +DISPLAY_DATA_SECTION + 1 170.0 85.0 + 2 166.0 88.0 + 3 133.0 73.0 + 4 140.0 70.0 + 5 142.0 55.0 + 6 126.0 53.0 + 7 125.0 60.0 + 8 119.0 68.0 + 9 117.0 74.0 + 10 99.0 83.0 + 11 73.0 79.0 + 12 72.0 91.0 + 13 37.0 94.0 + 14 6.0 106.0 + 15 3.0 97.0 + 16 21.0 82.0 + 17 33.0 67.0 + 18 4.0 66.0 + 19 3.0 42.0 + 20 27.0 33.0 + 21 52.0 41.0 + 22 57.0 59.0 + 23 58.0 66.0 + 24 88.0 65.0 + 25 99.0 67.0 + 26 95.0 55.0 + 27 89.0 55.0 + 28 83.0 38.0 + 29 85.0 25.0 + 30 104.0 35.0 + 31 112.0 37.0 + 32 112.0 24.0 + 33 113.0 13.0 + 34 125.0 30.0 + 35 135.0 32.0 + 36 147.0 18.0 + 37 147.5 36.0 + 38 154.5 45.0 + 39 157.0 54.0 + 40 158.0 61.0 + 41 172.0 82.0 + 42 174.0 87.0 +EOF diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/gr120.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/gr120.tsp new file mode 100644 index 000000000..632248922 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/gr120.tsp @@ -0,0 +1,534 @@ +NAME: gr120 +TYPE: TSP +COMMENT: 120 cities in Germany (Groetschel) +DIMENSION: 120 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +DISPLAY_DATA_TYPE: TWOD_DISPLAY +EDGE_WEIGHT_SECTION + 0 534 0 434 107 0 294 241 148 0 593 190 137 374 0 409 351 240 + 190 258 0 332 320 232 139 494 310 0 232 354 261 113 372 188 208 0 + 464 124 88 171 202 328 188 284 0 566 508 397 347 331 171 467 345 485 + 0 552 80 127 259 234 365 249 372 61 522 0 802 316 336 509 222 470 + 588 584 392 502 386 0 633 432 479 552 586 723 417 621 411 874 354 738 + 0 257 641 541 407 706 522 184 391 372 679 433 915 390 0 187 577 477 + 337 636 452 375 321 507 609 595 845 572 196 0 91 450 357 210 509 325 + 248 141 380 482 468 718 661 228 158 0 412 624 531 384 690 506 210 408 + 398 663 459 892 227 169 351 383 0 400 752 659 512 818 634 338 536 526 + 791 587 1020 524 151 270 371 167 0 472 805 712 565 871 687 391 589 579 + 844 640 1073 413 257 342 443 220 57 0 389 665 572 425 731 547 251 449 + 439 704 500 933 274 146 328 360 53 112 165 0 610 76 183 317 192 442 + 396 430 202 515 141 233 492 723 653 526 700 828 881 741 0 340 730 630 + 490 789 605 394 474 582 762 643 998 444 125 185 311 223 67 139 168 806 + 0 510 152 134 217 248 370 175 330 46 527 72 438 380 359 553 426 385 + 513 566 426 213 569 0 153 447 354 207 470 280 246 113 377 437 465 715 + 659 345 275 98 500 488 560 477 523 428 423 0 511 844 751 604 910 726 + 430 628 618 883 679 1112 407 296 381 482 259 96 39 204 920 178 605 599 + 0 269 283 190 42 332 148 169 63 213 305 301 544 582 382 312 185 365 + 493 546 406 359 465 259 170 585 0 525 157 95 232 42 257 316 355 160 + 330 167 254 521 638 568 441 615 743 796 656 188 721 206 438 835 274 0 + 150 539 446 299 598 414 279 283 469 571 557 807 488 112 96 120 267 255 + 327 244 615 195 515 237 366 274 530 0 80 507 414 267 566 382 305 251 + 437 539 525 775 572 196 88 77 351 339 411 328 583 279 483 205 450 242 + 498 63 0 130 520 427 280 579 395 318 264 450 552 538 788 543 167 59 + 101 322 310 382 299 596 250 496 218 412 255 511 56 25 0 401 791 691 + 551 850 666 474 535 662 823 723 1059 524 238 238 372 303 138 126 248 867 + 101 649 489 165 526 782 256 340 311 0 134 524 431 284 583 399 314 268 + 454 556 542 792 530 154 63 105 309 297 369 286 600 237 500 222 408 259 + 515 34 29 22 298 0 666 942 849 702 1008 824 528 726 716 981 777 1210 + 446 423 605 637 357 280 217 279 1018 336 703 754 194 683 933 521 605 576 + 416 563 0 259 281 188 40 364 180 142 72 211 337 299 549 555 372 302 + 175 338 466 519 379 357 455 257 172 558 27 272 264 232 245 516 249 656 + 0 505 447 336 286 354 110 406 284 424 70 461 566 819 618 548 421 602 + 730 783 643 538 701 466 376 822 244 353 509 478 491 762 494 920 276 0 + 453 358 247 234 265 59 354 232 335 182 372 477 767 566 496 369 550 678 + 731 591 449 649 377 324 770 192 264 458 426 439 710 443 868 224 95 0 + 627 334 251 408 168 239 528 406 300 166 348 331 700 740 670 504 724 852 + 905 765 360 823 346 504 944 366 179 632 600 613 884 617 1042 398 162 177 + 0 339 275 187 94 313 281 45 184 143 438 204 543 458 229 382 250 255 + 350 436 296 351 439 130 248 475 136 271 286 312 325 519 321 573 102 377 + 325 425 0 710 283 254 491 117 375 611 489 319 354 351 202 679 823 753 + 626 807 935 988 848 272 906 365 587 1027 449 159 715 683 696 967 700 1125 + 481 345 337 183 430 0 243 353 260 113 419 235 89 133 283 392 368 621 + 502 209 286 159 285 413 466 326 429 439 226 157 505 94 344 190 216 229 + 500 225 603 67 331 279 453 96 536 0 376 520 427 280 586 402 106 300 + 294 559 355 788 340 146 322 306 112 240 293 153 596 296 281 338 332 261 + 511 220 322 293 376 253 430 234 498 446 620 151 703 181 0 449 594 501 + 354 660 476 180 378 368 633 429 862 256 206 388 420 45 204 257 101 670 + 260 355 537 296 335 585 304 388 359 340 346 394 308 572 520 694 225 777 + 255 82 0 505 781 688 541 847 663 367 565 555 820 616 1049 289 262 444 + 476 196 119 136 118 857 175 542 593 129 522 772 360 444 415 255 402 161 + 495 759 707 881 412 964 442 269 233 0 322 611 518 371 677 493 197 395 + 372 650 446 879 359 69 261 293 94 142 224 84 687 146 372 410 263 352 + 602 177 261 232 247 219 361 325 589 537 711 242 794 272 99 106 200 0 + 185 575 482 335 634 450 231 319 419 607 480 843 462 86 124 156 241 226 + 298 218 651 166 406 273 337 310 566 40 124 95 227 82 495 300 546 494 + 668 276 751 207 212 278 334 151 0 353 638 545 398 704 520 224 422 412 + 677 473 906 282 110 292 324 61 125 178 38 714 181 399 441 217 379 629 + 208 292 263 261 250 315 352 616 564 738 269 821 299 126 82 154 46 182 + 0 324 314 191 106 275 91 225 104 244 248 332 487 638 437 367 240 421 + 549 602 462 390 520 290 238 641 64 227 329 297 310 581 314 739 95 187 + 135 309 196 392 150 317 391 578 408 365 435 0 388 234 127 124 219 113 + 289 168 215 270 254 431 606 501 431 304 485 613 666 526 310 584 232 302 + 705 128 163 393 361 374 645 378 803 159 209 120 219 229 336 214 381 455 + 642 472 429 499 64 0 447 664 571 424 730 546 250 448 438 703 499 932 + 188 204 386 418 36 202 255 88 740 258 425 535 294 405 655 302 386 357 + 338 344 392 378 642 590 764 295 847 325 152 68 231 130 276 96 461 525 + 0 360 606 513 366 672 488 192 390 380 645 441 874 273 117 299 331 46 + 150 203 63 682 206 367 448 242 347 597 215 299 270 286 257 340 320 584 + 532 706 237 789 267 94 58 179 48 189 31 403 467 82 0 605 133 180 + 312 287 418 264 425 112 575 55 439 313 448 648 520 474 602 655 515 193 + 658 89 517 694 354 220 610 577 591 738 595 792 352 514 425 401 219 404 + 421 370 444 631 461 495 488 385 307 514 456 0 656 932 839 692 998 814 + 518 716 706 971 767 1200 444 413 595 627 347 270 200 269 1008 326 693 744 + 177 673 923 511 595 566 406 553 42 646 910 858 1032 563 1115 593 420 384 + 151 351 485 305 729 793 382 330 782 0 573 113 101 280 79 329 359 403 + 163 402 157 235 509 686 616 489 663 791 844 704 131 769 209 486 883 322 + 57 578 546 559 830 563 981 320 425 336 236 314 176 392 559 633 820 650 + 614 677 353 220 603 645 210 971 0 293 384 274 143 319 129 262 60 314 + 286 402 531 675 451 381 201 458 586 639 499 460 534 360 151 678 101 318 + 343 311 324 595 328 776 132 225 173 353 233 436 187 354 428 615 445 379 + 472 83 147 498 440 455 766 375 0 372 283 199 153 229 39 273 151 324 + 196 324 441 686 485 415 288 469 597 650 510 413 568 370 241 689 111 228 + 377 345 358 629 362 787 143 135 83 263 244 346 198 365 439 626 456 413 + 483 54 72 509 451 377 777 300 90 0 330 479 386 239 545 361 65 259 + 253 518 314 747 378 119 276 260 150 278 331 191 555 334 240 297 370 220 + 470 174 276 247 414 207 468 193 457 405 579 110 662 140 46 120 307 126 + 166 164 276 340 190 132 329 458 518 313 324 0 610 297 234 391 107 275 + 511 389 322 248 331 254 693 723 653 526 707 835 888 748 302 806 368 487 + 927 349 149 615 583 596 867 600 1025 381 239 231 77 408 106 436 603 677 + 864 694 651 721 292 236 747 689 384 1015 186 336 246 562 0 598 874 781 + 634 940 756 460 658 648 913 709 1142 370 355 537 569 289 212 197 211 950 + 268 635 686 157 615 865 453 537 508 348 495 84 588 852 800 974 505 1057 + 535 362 326 93 293 427 247 671 735 324 272 724 85 913 708 719 400 957 + 0 214 604 504 364 663 479 402 348 534 636 622 872 599 223 49 185 378 + 319 391 355 680 234 580 302 430 339 595 123 115 86 287 90 632 329 575 + 523 697 409 780 313 349 415 471 288 151 319 394 458 413 326 675 622 643 + 408 442 303 680 564 0 154 401 308 161 460 276 199 78 331 433 419 669 + 612 298 228 63 453 441 513 430 477 381 377 47 552 136 392 190 158 171 + 442 175 707 126 372 320 494 201 577 110 291 490 546 363 226 396 191 255 + 488 401 471 697 440 138 239 250 477 639 255 0 70 464 371 224 523 339 + 262 208 394 496 482 732 567 191 121 27 346 334 406 323 540 274 440 162 + 445 199 455 83 47 64 335 68 600 189 435 383 557 269 640 173 295 383 + 439 256 119 287 254 378 381 294 534 590 503 268 302 249 540 532 148 115 + 0 606 349 266 387 183 216 507 385 354 147 363 357 715 719 649 522 703 + 831 884 744 375 802 400 483 923 345 194 611 579 592 863 596 1021 377 139 + 154 22 447 209 432 599 673 860 690 647 717 288 232 743 685 416 1011 262 + 332 242 558 103 953 676 473 536 0 631 228 175 412 38 296 532 410 240 + 306 272 210 640 744 674 547 728 856 909 769 233 827 286 508 948 370 80 + 636 604 617 888 621 1046 402 293 261 138 351 79 457 624 698 885 715 672 + 742 313 257 768 710 325 1036 117 357 267 583 69 978 701 498 561 153 0 + 642 129 176 349 121 369 428 472 232 428 226 187 578 755 685 558 732 860 + 913 773 98 838 278 555 952 391 132 647 615 628 899 632 1050 389 465 376 + 260 383 161 461 628 702 889 719 683 746 422 330 772 714 279 1040 75 430 + 340 587 191 982 712 509 572 275 122 0 503 779 686 539 845 661 365 563 + 553 818 614 1047 245 260 442 474 141 151 168 116 855 207 540 591 162 520 + 770 358 442 413 287 400 201 493 757 705 879 410 962 440 267 231 44 198 + 332 152 576 640 174 177 629 199 818 613 624 305 862 125 469 544 437 858 + 883 887 0 372 762 662 522 821 637 456 506 644 794 705 1030 506 209 209 + 343 285 120 108 230 838 72 631 460 147 497 753 227 311 282 29 269 398 + 487 733 681 855 501 938 471 354 322 237 218 198 243 552 616 320 268 720 + 388 801 566 600 396 838 330 258 413 306 834 859 870 269 0 641 348 265 + 422 152 262 542 420 314 189 362 313 714 754 684 557 738 866 919 779 344 + 837 360 518 958 380 193 646 614 627 898 631 1056 412 185 200 23 439 165 + 467 634 708 895 725 682 752 323 233 778 720 415 1046 231 367 277 593 59 + 988 711 508 571 45 122 244 893 869 0 561 837 744 597 903 719 423 621 + 611 876 672 1105 311 318 500 532 252 175 192 174 913 231 598 649 186 578 + 828 416 500 471 311 458 154 551 815 763 937 468 1020 498 325 289 65 256 + 390 210 634 698 287 235 687 152 876 671 682 363 920 77 527 602 495 916 + 941 945 66 293 951 0 478 754 661 514 820 636 340 538 528 793 589 1022 + 261 235 417 449 116 132 149 91 830 188 515 566 159 495 745 333 417 388 + 268 375 226 468 732 680 854 385 937 415 242 206 55 173 307 127 551 615 + 149 152 604 224 793 588 599 280 837 150 444 519 412 833 858 862 25 250 + 868 91 0 247 316 223 76 360 176 170 39 246 333 334 572 583 360 290 + 163 366 494 547 407 392 443 292 133 586 37 307 252 220 233 504 237 684 + 34 272 220 394 146 477 95 262 336 523 353 288 380 92 156 406 348 387 + 674 355 83 139 221 377 616 317 92 177 373 398 424 521 475 408 579 496 + 0 317 336 212 95 289 105 218 79 266 262 354 501 631 430 360 233 414 + 542 595 455 412 513 312 213 634 53 248 397 290 378 574 382 732 88 201 + 149 323 189 406 143 310 384 571 401 358 428 21 85 454 396 407 722 375 + 62 68 269 306 664 387 184 247 302 327 444 569 545 337 627 544 70 0 + 272 382 289 142 448 264 84 162 234 421 295 650 497 180 315 188 280 408 + 461 321 458 464 221 186 500 123 373 193 245 258 544 228 598 96 360 308 + 482 91 565 29 142 250 437 267 159 294 179 243 320 262 310 588 421 216 + 227 96 465 530 342 139 209 461 486 490 435 526 496 493 410 124 172 0 + 575 276 199 356 86 240 476 354 287 250 296 266 672 688 618 491 672 800 + 853 713 289 771 333 452 892 314 127 580 548 561 832 565 990 346 237 205 + 82 373 141 401 568 642 829 659 616 686 257 201 712 654 349 980 165 301 + 211 527 35 922 645 442 505 97 56 178 827 803 66 885 802 342 271 430 + 0 219 479 386 239 545 361 167 259 317 518 378 747 474 83 172 149 253 + 235 339 230 555 228 304 263 378 220 470 79 139 134 289 112 507 193 457 + 405 579 174 662 126 154 290 346 136 621 194 276 340 288 201 393 497 518 + 313 324 108 562 439 199 216 153 558 583 587 344 260 593 402 319 221 269 + 97 527 0 293 683 583 443 742 558 238 427 426 715 487 951 352 50 232 + 264 131 101 174 108 759 105 413 381 213 418 674 148 232 203 206 190 385 + 408 654 602 776 283 859 248 140 168 224 41 122 72 473 537 166 89 502 + 375 722 487 521 167 759 317 259 334 227 755 780 791 222 177 790 280 197 + 396 466 219 724 134 0 54 529 429 289 588 404 327 273 459 561 547 797 + 595 219 92 82 374 362 434 351 605 302 505 227 473 264 520 119 31 43 + 363 58 628 254 500 448 622 334 705 238 327 411 467 284 147 315 319 383 + 409 322 600 618 568 333 367 281 605 560 84 180 53 601 626 637 465 334 + 636 523 440 242 312 267 570 170 255 0 648 188 182 355 68 316 434 430 + 238 362 232 154 584 761 691 564 738 866 919 779 177 844 284 561 958 390 + 100 653 621 634 905 638 1056 395 412 323 194 389 95 467 634 708 895 725 + 689 752 333 277 778 720 285 1046 81 377 287 593 125 988 718 515 578 209 + 56 66 893 876 178 951 868 418 347 496 112 593 797 643 0 211 601 501 + 361 660 476 231 345 479 633 480 869 466 74 81 182 243 189 261 220 677 + 129 406 299 300 336 592 105 150 121 190 108 497 326 572 520 694 276 777 + 310 204 280 336 143 37 184 391 455 278 191 495 487 640 405 439 166 677 + 429 160 252 145 673 698 709 334 161 708 392 309 314 384 196 642 99 125 + 173 715 0 568 844 751 604 910 726 430 628 618 883 679 1112 348 325 507 + 539 259 182 150 181 920 238 605 656 127 585 835 423 507 478 318 465 98 + 558 822 770 944 475 1027 505 332 296 63 263 397 217 641 705 294 242 694 + 96 883 678 689 370 927 30 534 609 502 923 948 952 103 300 958 56 120 + 586 634 500 892 409 287 530 958 399 0 497 150 67 204 70 257 288 327 + 155 335 164 282 516 610 540 413 587 715 768 628 216 693 201 410 807 246 + 28 502 470 483 754 487 905 244 353 264 184 243 187 316 483 557 744 574 + 538 601 199 135 627 569 217 895 85 292 228 442 167 837 567 364 427 199 + 108 160 742 725 198 800 717 279 220 345 132 442 646 492 128 564 807 0 + 290 680 580 440 739 555 317 424 505 712 566 948 506 139 98 261 285 155 + 227 229 756 88 492 378 266 415 671 144 176 164 140 136 424 405 651 599 + 773 362 856 389 290 322 263 195 116 226 470 534 320 243 581 414 719 484 + 518 252 756 356 147 331 224 752 777 788 295 111 787 319 276 393 463 275 + 721 178 154 190 794 79 326 643 0 475 65 42 182 137 282 261 295 65 + 439 85 321 437 588 518 391 565 693 746 606 141 671 111 388 785 224 95 + 480 448 461 732 465 883 222 378 289 272 216 254 294 461 535 722 552 516 + 579 255 169 605 547 138 873 92 325 241 420 255 815 545 342 405 287 175 + 161 720 703 286 778 695 257 277 323 220 420 624 470 167 542 785 88 621 + 0 654 341 278 435 151 319 555 433 366 266 375 298 755 767 697 570 751 + 879 932 792 346 850 412 531 971 393 193 659 627 640 911 644 1069 425 262 + 254 100 452 103 480 647 721 908 738 695 765 336 280 791 733 428 1059 230 + 380 290 606 44 1001 724 521 584 122 113 235 906 882 77 964 881 421 350 + 509 79 606 803 649 169 721 971 211 800 299 0 445 387 276 226 294 50 + 346 224 364 125 410 506 759 558 488 361 542 670 723 583 478 641 406 316 + 762 184 293 450 418 431 702 435 860 216 64 57 193 317 411 271 438 512 + 699 529 486 556 127 149 582 524 454 850 365 165 75 397 311 792 515 312 + 375 170 332 405 697 673 216 755 672 212 141 300 276 397 594 440 352 512 + 762 293 591 318 355 0 375 765 665 525 824 640 384 509 572 797 633 1033 + 434 160 245 346 213 48 59 158 841 42 559 463 98 500 756 230 314 285 + 90 272 326 490 736 684 858 429 941 474 286 250 165 169 201 171 555 619 + 248 196 648 316 804 569 603 324 841 258 294 416 309 837 862 873 197 72 + 872 221 178 478 548 454 832 263 128 337 879 164 228 728 130 706 885 676 + 0 268 658 558 418 717 533 231 402 419 690 480 926 420 53 138 239 199 + 132 204 202 734 72 406 356 243 393 649 123 207 178 185 165 401 383 629 + 577 751 276 834 367 204 236 240 109 86 140 448 512 234 157 495 391 697 + 462 496 166 734 333 187 309 202 730 755 766 272 156 765 296 253 371 441 + 227 699 130 68 230 772 57 303 627 86 599 778 569 107 0 261 519 426 + 279 585 401 141 299 329 558 390 787 422 43 200 232 211 183 294 178 595 + 162 316 342 333 260 510 98 200 171 275 131 455 233 497 445 619 186 702 + 166 114 248 294 67 90 142 316 380 246 159 405 445 558 353 364 76 602 + 387 227 295 195 598 623 627 292 246 633 350 267 261 309 137 567 69 82 + 223 633 90 357 482 176 460 646 437 197 90 0 710 184 271 417 239 487 + 496 530 300 546 249 168 616 823 753 626 800 928 981 841 108 906 321 623 +1020 459 241 715 683 696 967 700 1118 457 583 494 378 451 279 529 696 770 + 957 787 751 814 490 448 840 782 310 1108 184 560 458 655 309 1050 780 577 + 640 393 240 118 955 938 362 1013 930 492 512 558 296 655 859 705 179 777 +1020 269 856 229 353 523 941 834 695 0 396 291 180 177 198 53 297 175 + 268 218 305 410 710 509 439 312 493 621 674 534 382 592 310 273 713 135 + 197 401 369 382 653 386 811 167 157 67 215 268 315 222 389 463 650 480 + 437 507 78 53 533 475 358 801 269 122 32 348 215 743 466 263 326 206 + 236 309 648 624 238 706 623 163 92 251 180 348 545 391 256 463 713 197 + 542 222 259 97 627 520 388 427 0 295 424 278 183 308 118 302 100 354 + 275 442 520 715 491 421 241 498 626 679 539 500 574 400 191 718 141 307 + 383 351 364 635 368 816 172 214 162 342 273 425 227 394 468 655 485 419 + 512 114 151 538 480 495 806 364 40 79 353 325 748 448 178 308 321 346 + 419 653 606 356 711 628 123 93 256 290 353 527 373 366 445 718 281 524 + 365 369 154 609 502 393 537 111 0 651 927 834 687 993 809 513 711 701 + 966 762 1195 407 408 590 622 342 265 282 264 1003 321 688 739 276 668 918 + 506 590 561 401 548 174 641 905 853 1027 558 1110 588 415 379 155 346 480 + 300 724 788 377 325 777 173 966 761 772 453 1010 90 617 692 585 1006 1031 +1035 162 383 1041 96 187 669 717 583 975 492 370 613 1041 482 112 890 409 + 868 1054 845 311 386 440 1103 796 801 0 175 565 472 325 624 440 311 309 + 495 597 583 833 504 128 76 146 283 271 343 260 641 211 541 263 382 300 + 556 32 76 47 272 30 537 290 536 484 658 318 741 222 256 320 376 193 + 56 224 355 419 318 231 636 527 604 369 403 210 641 469 103 216 109 637 + 662 673 374 243 672 432 349 278 423 225 606 104 164 99 679 57 439 528 + 112 506 685 476 246 114 134 741 427 409 522 0 585 67 146 292 135 385 + 371 405 175 458 147 249 499 698 628 501 675 803 856 716 57 781 221 498 + 895 334 131 590 558 571 842 575 993 332 481 392 303 326 215 404 571 645 + 832 662 626 689 365 261 715 657 200 983 74 435 356 530 245 925 655 452 + 515 318 176 62 830 813 287 888 805 367 387 433 232 530 734 580 120 652 + 895 159 731 104 289 421 816 709 570 121 325 438 978 616 0 250 640 540 + 400 699 515 277 384 465 672 526 908 466 99 89 221 245 178 250 220 716 + 96 452 338 289 375 631 105 189 160 151 147 447 365 611 559 733 322 816 + 349 250 282 286 155 76 186 430 494 280 203 541 437 679 444 478 212 716 + 379 138 291 184 712 737 748 318 122 747 342 299 353 423 235 681 138 114 + 212 754 39 349 603 40 581 760 551 138 46 136 816 502 484 432 96 691 + 0 717 221 251 424 137 385 503 499 307 417 301 95 653 830 760 633 807 + 935 988 848 190 913 353 631 1027 459 169 722 690 703 974 707 1125 464 481 + 392 246 458 117 536 703 777 964 794 758 821 402 346 847 789 354 1115 150 + 446 356 662 169 1057 787 584 647 272 125 92 962 945 228 1020 937 487 416 + 565 181 662 866 712 69 784 1027 197 863 236 213 421 948 841 702 162 325 + 435 1110 748 154 823 0 246 454 361 213 373 183 332 130 384 340 472 585 + 745 472 402 237 528 656 709 569 530 555 430 167 748 171 372 364 332 345 + 616 349 846 202 279 227 407 303 490 257 424 498 685 515 400 542 157 221 + 568 510 525 836 429 70 144 383 390 778 429 174 289 386 411 484 683 587 + 421 741 658 153 132 286 355 383 508 354 431 426 748 346 505 395 434 219 + 590 483 423 630 176 65 831 390 505 465 500 0 788 302 322 495 208 456 + 574 570 378 488 372 23 724 901 831 704 818 1006 1059 919 203 984 424 701 +1098 530 240 793 761 774 1045 778 1196 535 552 463 317 529 188 607 774 848 +1035 865 829 892 473 417 918 860 425 1186 221 517 427 733 240 1128 858 655 + 718 343 196 173 1033 1016 299 1091 1008 558 487 636 252 733 937 783 154 855 +1098 268 934 307 284 492 1019 912 773 138 396 506 1181 819 235 894 81 571 + 0 426 596 503 356 662 478 182 380 370 635 431 864 253 183 365 397 27 + 181 234 82 672 237 357 514 273 337 587 281 365 336 317 323 371 310 574 + 522 696 227 779 257 84 19 210 83 255 67 393 457 65 35 446 361 635 + 430 441 122 679 303 392 467 360 675 700 704 208 299 710 266 183 338 386 + 252 644 267 145 388 710 257 273 559 299 537 723 514 227 213 225 772 465 + 470 355 297 647 259 779 500 850 0 596 575 330 377 237 179 497 375 552 + 100 589 407 941 709 639 512 693 821 874 734 421 792 460 467 913 335 236 + 601 569 582 853 586 1011 367 91 117 72 468 259 422 589 663 850 680 637 + 707 278 221 733 675 642 1001 308 316 212 548 153 943 666 463 526 47 212 + 334 848 824 95 906 823 363 292 451 156 548 745 591 268 663 913 241 742 + 506 172 133 827 720 588 452 185 305 996 627 364 702 322 370 393 665 0 + 634 910 817 670 976 792 496 694 684 949 745 1178 414 391 573 605 325 248 + 185 247 986 304 671 722 162 651 901 489 573 544 384 531 32 624 888 836 +1010 541 1093 571 398 362 129 329 463 283 707 771 360 308 760 33 949 744 + 755 436 983 52 600 675 568 989 1014 1018 169 366 1024 122 194 652 700 566 + 958 475 353 596 1024 465 66 873 392 851 1037 828 294 369 423 1086 779 784 + 142 505 961 415 1003 814 1164 339 979 0 507 209 111 201 139 172 408 286 + 213 329 223 351 575 620 550 423 604 732 785 645 275 703 259 384 824 202 + 87 512 480 493 764 497 922 278 268 141 173 252 256 333 500 574 761 591 + 548 618 138 74 644 586 276 912 144 233 143 459 156 854 577 374 437 208 + 177 219 759 735 187 817 734 274 159 362 121 459 656 502 197 574 824 59 + 653 147 200 208 738 631 499 328 112 222 907 538 218 613 266 287 337 576 + 208 890 0 463 186 79 155 157 161 251 216 167 318 206 369 558 576 506 + 379 553 681 734 594 262 659 213 376 773 176 115 468 436 449 720 453 871 + 210 257 168 219 206 274 282 449 523 710 540 504 567 112 48 593 535 259 + 861 172 195 120 408 202 803 533 330 393 254 195 247 708 691 233 766 683 + 204 133 311 167 408 612 458 215 530 773 87 609 121 246 197 694 587 448 + 350 101 199 856 494 225 569 284 269 355 525 251 839 46 0 408 169 105 + 116 242 298 131 229 57 455 118 437 468 315 451 325 341 469 522 382 245 + 525 72 322 561 158 200 413 382 394 605 398 659 155 394 305 344 86 359 + 228 237 311 498 328 362 355 188 160 381 323 169 649 208 259 269 196 327 + 591 478 276 339 391 280 277 496 587 358 554 471 191 211 177 292 260 369 + 403 283 362 561 172 448 110 371 334 515 362 272 345 238 299 644 439 220 + 408 352 329 423 313 388 627 183 137 0 529 389 278 310 236 127 430 308 + 366 125 403 447 755 642 572 445 626 754 807 667 420 725 408 400 846 268 + 235 534 502 515 786 519 944 300 80 68 112 401 299 355 522 596 783 613 + 570 640 211 169 666 608 456 934 307 249 225 481 193 876 599 396 459 89 + 231 353 781 757 135 839 756 296 225 384 175 481 678 524 287 596 846 240 + 675 320 212 84 760 653 521 471 133 238 929 560 363 635 362 303 433 598 + 52 912 156 199 336 0 192 412 319 172 477 293 160 154 342 450 430 680 + 573 228 235 108 383 371 443 360 488 311 388 167 482 153 403 119 165 178 + 372 154 637 126 389 337 511 162 594 71 207 420 476 232 136 324 209 273 + 418 331 482 627 451 246 256 161 494 569 262 120 110 490 515 590 474 343 + 525 532 449 127 202 74 459 96 264 187 526 182 539 375 261 353 538 329 + 346 239 165 588 280 286 622 151 463 221 595 294 666 397 480 605 391 341 + 287 413 0 529 286 231 310 177 165 430 308 319 182 328 379 680 642 572 + 445 626 754 807 667 344 725 365 406 846 268 159 534 502 515 786 519 944 + 300 137 106 75 370 231 355 522 596 783 613 570 640 211 155 666 608 381 + 934 231 255 165 481 125 876 599 396 459 77 155 247 781 757 89 839 756 + 296 225 384 99 481 678 524 211 596 846 164 675 252 148 168 760 653 521 + 365 137 244 929 560 287 635 294 309 365 598 80 912 131 177 314 87 413 + 0 434 710 617 470 776 592 296 494 484 749 545 978 346 191 373 405 125 + 82 142 47 786 145 471 522 145 451 701 289 373 344 225 331 238 424 688 + 636 810 341 893 371 198 162 77 129 263 83 507 571 160 108 560 228 749 + 544 555 236 793 170 400 475 368 789 814 818 76 207 824 133 51 452 500 + 366 758 275 153 396 824 265 140 673 233 651 837 628 135 210 223 886 579 + 584 223 305 761 241 893 614 964 139 779 206 690 639 427 712 405 712 0 + 535 811 718 571 877 693 397 595 585 850 646 1079 336 292 474 506 226 94 + 76 129 887 154 572 623 75 552 802 390 474 445 202 432 175 525 789 737 + 911 442 994 472 299 263 58 230 364 184 608 672 261 209 661 160 850 645 + 656 337 894 140 501 576 469 890 915 919 91 184 925 113 88 553 601 467 + 859 376 176 497 925 276 110 774 242 752 938 729 123 219 324 987 680 685 + 205 406 862 265 994 715 1065 240 880 143 791 740 528 813 506 813 82 0 + 630 108 191 337 165 424 416 450 220 483 188 190 540 743 673 546 720 848 + 901 761 43 826 266 543 940 379 161 635 603 616 887 620 1038 877 520 431 + 315 371 216 449 616 690 877 707 671 734 410 306 760 702 241 1028 104 480 + 395 575 246 970 700 497 560 348 177 55 875 858 299 933 850 412 432 478 + 233 575 779 625 121 697 940 189 776 149 290 460 861 754 615 80 364 474 +1023 661 41 736 147 550 160 692 394 1006 248 270 265 393 508 317 806 907 + 0 446 252 145 227 162 111 347 225 233 268 272 374 624 559 489 362 543 + 671 724 584 346 642 279 323 763 185 161 451 419 432 703 436 861 217 207 + 141 162 272 279 272 439 513 700 530 487 557 128 50 583 525 325 851 233 + 172 82 398 179 793 516 313 376 175 200 273 698 674 176 756 673 213 142 + 301 144 398 595 441 220 513 763 108 592 187 223 147 677 570 438 391 51 + 161 846 477 289 552 289 226 360 515 167 829 49 66 203 115 330 98 629 + 730 319 0 166 518 425 277 437 247 336 114 448 404 536 649 749 435 365 + 150 590 578 650 567 594 518 494 90 689 235 436 402 295 383 579 387 844 + 189 343 291 471 295 554 247 428 627 683 500 363 531 221 285 625 538 589 + 834 493 134 208 372 454 776 392 137 252 450 475 548 681 550 485 739 656 + 150 196 276 419 353 471 317 495 389 746 410 468 459 498 283 553 446 432 + 694 240 129 829 353 569 428 564 80 635 604 434 812 351 333 393 367 257 + 373 612 713 614 290 0 471 313 202 252 166 99 372 250 290 210 358 378 + 679 584 514 387 568 696 749 609 350 667 332 348 788 210 165 476 444 457 + 728 461 886 242 156 61 135 311 276 297 464 538 725 555 512 582 153 93 + 608 550 380 876 237 197 107 423 170 818 541 338 401 147 191 277 723 699 + 149 781 698 238 167 326 135 423 620 466 224 538 788 139 617 244 214 118 + 702 595 462 395 67 186 871 502 293 577 293 251 364 540 128 854 80 123 + 260 76 355 70 654 755 323 39 315 0 442 718 625 478 784 600 304 502 + 492 757 553 986 300 199 381 413 81 137 184 53 794 209 479 530 194 459 + 709 297 381 352 285 339 261 432 696 644 818 349 901 379 206 126 90 137 + 271 91 515 579 111 116 568 259 757 552 563 244 801 185 408 483 376 797 + 822 826 60 267 832 126 35 460 508 374 766 283 161 404 832 273 155 681 + 293 659 845 636 195 270 231 894 587 592 222 313 769 301 901 622 972 108 + 787 229 698 647 435 720 413 720 55 123 814 637 620 662 0 523 230 147 + 304 81 188 424 302 235 255 174 293 596 636 566 439 620 748 801 661 265 + 719 281 400 840 262 75 528 496 509 780 513 938 294 284 195 104 321 193 + 349 516 590 777 607 564 634 205 149 660 602 297 928 147 249 159 475 87 + 870 593 390 453 119 108 192 775 751 118 833 750 290 219 378 52 475 672 + 518 139 590 840 80 669 168 131 224 754 647 515 310 128 238 923 554 208 + 629 208 303 279 592 161 906 69 115 240 160 407 84 706 807 238 92 367 + 87 714 0 566 45 139 273 228 383 352 386 121 540 60 314 411 679 609 + 482 656 784 837 697 81 762 132 479 876 315 189 571 539 552 823 556 974 + 313 479 390 366 307 308 385 552 626 813 643 607 670 346 266 696 638 112 + 964 158 416 342 511 335 906 636 433 496 381 266 155 811 794 380 869 786 + 348 368 414 314 511 715 561 213 633 876 182 712 97 379 419 797 690 551 + 189 323 456 959 597 93 672 247 486 284 628 607 942 244 218 178 421 444 + 346 742 843 124 284 550 345 750 262 0 235 313 220 73 371 187 168 43 + 243 344 331 583 581 348 278 151 364 492 545 405 389 431 289 137 584 48 + 304 240 208 221 492 225 682 32 283 231 405 144 488 93 260 334 521 351 + 276 378 103 167 404 346 384 672 352 95 150 219 388 614 305 94 165 384 + 409 421 519 463 419 577 494 12 92 122 353 219 384 230 429 302 584 276 + 381 254 432 223 466 359 259 489 174 135 667 266 364 341 498 165 569 336 + 374 650 285 215 188 307 115 307 450 551 409 224 154 249 458 301 345 0 + 432 822 722 582 881 697 441 566 629 854 690 1090 491 217 302 403 270 105 + 69 215 898 99 616 520 108 557 813 287 371 342 77 329 383 547 793 741 + 915 486 998 531 343 307 222 226 258 228 612 676 305 253 705 373 861 626 + 660 381 898 315 351 473 366 894 919 930 254 66 929 278 235 535 605 511 + 863 320 185 394 936 221 285 785 177 763 942 733 57 164 254 998 684 666 + 368 303 873 195 1005 647 1076 284 884 351 795 751 572 817 403 817 192 145 + 819 734 610 759 252 811 854 523 0 435 653 560 413 719 535 239 437 427 + 692 488 921 220 192 374 406 29 190 243 64 729 246 414 523 282 394 644 + 290 374 345 326 332 380 367 631 579 753 284 836 314 141 78 219 123 264 + 84 450 514 34 75 503 370 692 487 498 179 736 312 401 476 369 732 757 + 761 137 308 767 275 112 395 443 309 701 276 154 397 767 266 282 616 308 + 594 780 571 236 222 234 829 522 527 365 306 704 268 836 557 907 56 722 + 348 633 582 370 655 406 655 148 249 749 572 613 597 77 649 685 393 293 + 0 369 167 79 77 205 259 153 190 97 416 185 435 537 482 412 286 459 + 587 640 500 243 555 111 283 679 119 163 375 343 356 626 360 777 116 355 + 266 305 108 322 189 356 429 616 446 411 473 149 121 499 441 238 767 206 + 220 230 315 288 709 439 237 300 352 243 275 614 587 319 672 589 152 172 + 218 253 315 518 364 281 436 679 135 515 108 332 295 600 493 355 343 199 + 260 762 401 218 475 350 290 421 431 349 745 144 98 39 297 248 275 545 + 646 263 164 354 221 553 201 199 149 657 488 0 121 511 418 271 570 386 + 309 255 441 543 529 779 518 142 99 84 297 285 357 274 587 225 487 209 + 396 246 502 35 29 42 286 36 551 236 482 430 604 316 687 220 268 334 + 390 207 70 238 301 365 332 245 581 541 550 315 349 222 587 483 126 162 + 55 583 608 619 388 257 618 446 363 224 294 249 552 104 178 60 625 96 + 453 474 175 452 631 422 260 153 146 687 373 355 536 47 562 135 694 336 + 765 311 573 519 484 440 386 506 169 506 319 520 607 423 299 448 327 500 + 543 212 317 320 347 0 +DISPLAY_DATA_SECTION + 1 8.0 124.0 + 2 125.0 80.0 + 3 97.0 74.0 + 4 69.0 96.0 + 5 106.0 46.0 + 6 49.0 57.0 + 7 80.0 125.0 + 8 42.0 93.0 + 9 104.0 94.0 + 10 35.0 17.0 + 11 118.0 96.0 + 12 151.0 22.0 + 13 154.0 182.0 + 14 57.0 165.0 + 15 18.0 159.0 + 16 27.0 123.0 + 17 96.0 170.0 + 18 63.0 198.0 + 19 59.0 211.0 + 20 88.0 182.0 + 21 142.0 72.0 + 22 48.0 190.0 + 23 106.0 106.0 + 24 28.0 102.0 + 25 63.0 224.0 + 26 58.0 93.0 + 27 103.0 56.0 + 28 38.0 149.0 + 29 23.0 138.0 + 30 22.0 146.0 + 31 32.0 208.0 + 32 27.0 144.0 + 33 75.0 258.0 + 34 59.0 101.0 + 35 41.0 32.0 + 36 53.0 46.0 + 37 76.0 19.0 + 38 79.0 115.0 + 39 109.0 13.0 + 40 59.0 118.0 + 41 84.0 147.0 + 42 95.0 160.0 + 43 87.0 213.0 + 44 73.0 166.0 + 45 43.0 153.0 + 46 81.0 175.0 + 47 59.0 77.0 + 48 70.0 68.0 + 49 106.0 169.0 + 50 86.0 168.0 + 51 127.0 109.0 + 52 68.0 243.0 + 53 116.0 57.0 + 54 39.0 78.0 + 55 54.0 65.0 + 56 77.0 141.0 + 57 95.0 24.0 + 58 89.0 238.0 + 59 9.0 158.0 + 60 39.0 109.0 + 61 25.0 129.0 + 62 69.0 20.0 + 63 104.0 34.0 + 64 132.0 51.0 + 65 98.0 207.0 + 66 37.0 203.0 + 67 80.0 16.0 + 68 103.0 224.0 + 69 94.0 202.0 + 70 49.0 96.0 + 71 55.0 80.0 + 72 62.0 123.0 + 73 91.0 31.0 + 74 51.0 142.0 + 75 64.0 172.0 + 76 14.0 138.0 + 77 120.0 37.0 + 78 38.0 160.0 + 79 86.0 230.0 + 80 96.0 59.0 + 81 33.0 177.0 + 82 108.0 78.0 + 83 93.0 12.0 + 84 43.0 47.0 + 85 52.0 200.0 + 86 48.0 171.0 + 87 62.0 153.0 + 88 159.0 53.0 + 89 60.0 60.0 + 90 36.0 73.0 + 91 111.0 243.0 + 92 31.0 150.0 + 93 130.0 67.0 + 94 36.0 172.0 + 95 132.0 28.0 + 96 29.0 73.0 + 97 150.0 28.0 + 98 89.0 166.0 + 99 58.0 21.0 + 100 78.0 244.0 + 101 82.0 58.0 + 102 81.0 68.0 + 103 92.0 98.0 + 104 56.0 33.0 + 105 47.0 126.0 + 106 70.0 34.0 + 107 78.0 195.0 + 108 77.0 215.0 + 109 140.0 62.0 + 110 70.0 57.0 + 111 16.0 89.0 + 112 66.0 50.0 + 113 98.0 194.0 + 114 87.0 45.0 + 115 132.0 87.0 + 116 52.0 99.0 + 117 50.0 212.0 + 118 103.0 176.0 + 119 84.0 91.0 + 120 31.0 140.0 +EOF diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/main.c b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/main.c new file mode 100644 index 000000000..06857421f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/main.c @@ -0,0 +1,535 @@ +/* main.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +/*********************************************************************** +* This program is a stand-alone solver intended for solving Symmetric +* Traveling Salesman Problem (TSP) with the branch-and-bound method. +* +* Please note that this program is only an illustrative example. It is +* *not* a state-of-the-art code, so only small TSP instances (perhaps, +* having up to 150-200 nodes) can be solved with this code. +* +* To run this program use the following command: +* +* tspsol tsp-file +* +* where tsp-file specifies an input text file containing TSP data in +* TSPLIB 95 format. +* +* Detailed description of the input format recognized by this program +* is given in the report: Gerhard Reinelt, "TSPLIB 95". This report as +* well as TSPLIB, a library of sample TSP instances (and other related +* problems), are freely available for research purposes at the webpage +* . +* +* Symmetric Traveling Salesman Problem +* ------------------------------------ +* Let a complete undirected graph be given: +* +* K = (V, E), (1) +* +* where V = {1, ..., n} is a set of nodes, E = V cross V is a set of +* edges. Let also each edge e = (i,j) be assigned a positive number +* c[i,j], which is the length of e. The Symmetric Traveling Salesman +* Problem (TSP) is to find a tour in K of minimal length. +* +* Integer programming formulation of TSP +* -------------------------------------- +* For a set of nodes W within V introduce the following notation: +* +* d(W) = {(i,j):i in W and j not in W or i not in W and j in W}, (2) +* +* i.e. d(W) is the set of edges which have exactly one endnode in W. +* If W = {v}, i.e. W consists of the only node, we write simply d(v). +* +* The integer programming formulation of TSP is the following: +* +* minimize sum c[i,j] * x[i,j] (3) +* i,j +* +* subject to sum x[i,j] = 2 for all v in V (4) +* (i,j) in d(v) +* +* sum x[i,j] >= 2 for all W within V, (5) +* (i,j) in d(W) W != empty, W != V +* +* x[i,j] in {0, 1} for all i, j (6) +* +* The binary variables x[i,j] have conventional meaning: if x[i,j] = 1, +* the edge (i,j) is included in the tour, otherwise, if x[i,j] = 0, the +* edge is not included in the tour. +* +* The constraints (4) are called degree constraints. They require that +* for each node v in V there must be exactly two edges included in the +* tour which are incident to v. +* +* The constraints (5) are called subtour elimination constraints. They +* are used to forbid subtours. Note that the number of the subtour +* elimination constraints grows exponentially on the size of the TSP +* instance, so these constraints are not included explicitly in the +* IP, but generated dynamically during the B&B search. +***********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include "maxflow.h" +#include "mincut.h" +#include "misc.h" +#include "tsplib.h" + +int n; +/* number of nodes in the problem, n >= 2 */ + +int *c; /* int c[1+n*(n-1)/2]; */ +/* upper triangle (without diagonal entries) of the (symmetric) matrix + * C = (c[i,j]) in row-wise format, where c[i,j] specifies a length of + * edge e = (i,j), 1 <= i < j <= n */ + +int *tour; /* int tour[1+n]; */ +/* solution to TSP, which is a tour specified by the list of node + * numbers tour[1] -> ... -> tour[nn] -> tour[1] in the order the nodes + * are visited; note that any tour is a permutation of node numbers */ + +glp_prob *P; +/* integer programming problem object */ + +/*********************************************************************** +* loc - determine reduced index of element of symmetric matrix +* +* Given indices i and j of an element of a symmetric nxn-matrix, +* 1 <= i, j <= n, i != j, this routine returns the index of that +* element in an array, which is the upper triangle (without diagonal +* entries) of the matrix in row-wise format. */ + +int loc(int i, int j) +{ xassert(1 <= i && i <= n); + xassert(1 <= j && j <= n); + xassert(i != j); + if (i < j) + return ((n - 1) + (n - i + 1)) * (i - 1) / 2 + (j - i); + else + return loc(j, i); +} + +/*********************************************************************** +* read_data - read TSP data +* +* This routine reads TSP data from a specified text file in TSPLIB 95 +* format. */ + +void read_data(const char *fname) +{ TSP *tsp; + int i, j; + tsp = tsp_read_data(fname); + if (tsp == NULL) + { xprintf("TSP data file processing error\n"); + exit(EXIT_FAILURE); + } + if (tsp->type != TSP_TSP) + { xprintf("Invalid TSP data type\n"); + exit(EXIT_FAILURE); + } + n = tsp->dimension; + xassert(n >= 2); + if (n > 32768) + { xprintf("TSP instance too large\n"); + exit(EXIT_FAILURE); + } + c = xalloc(1+loc(n-1, n), sizeof(int)); + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + c[loc(i, j)] = tsp_distance(tsp, i, j); + } + tsp_free_data(tsp); + return; +} + +/*********************************************************************** +* build_prob - build initial integer programming problem +* +* This routine builds the initial integer programming problem, which +* includes all variables (6), objective (3) and all degree constraints +* (4). Subtour elimination constraints (5) are considered "lazy" and +* not included in the initial problem. */ + +void build_prob(void) +{ int i, j, k, *ind; + double *val; + char name[50]; + /* create problem object */ + P = glp_create_prob(); + /* add all binary variables (6) */ + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { k = glp_add_cols(P, 1); + xassert(k == loc(i,j)); + sprintf(name, "x[%d,%d]", i, j); + glp_set_col_name(P, k, name); + glp_set_col_kind(P, k, GLP_BV); + /* set objective coefficient (3) */ + glp_set_obj_coef(P, k, c[k]); + } + } + /* add all degree constraints (4) */ + ind = xalloc(1+n, sizeof(int)); + val = xalloc(1+n, sizeof(double)); + for (i = 1; i <= n; i++) + { k = glp_add_rows(P, 1); + xassert(k == i); + sprintf(name, "v[%d]", i); + glp_set_row_name(P, i, name); + glp_set_row_bnds(P, i, GLP_FX, 2, 2); + k = 0; + for (j = 1; j <= n; j++) + { if (i != j) + k++, ind[k] = loc(i,j), val[k] = 1; + } + xassert(k == n-1); + glp_set_mat_row(P, i, n-1, ind, val); + } + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* build_tour - build tour for corresponding solution to IP +* +* Given a feasible solution to IP (3)-(6) this routine builds the +* corresponding solution to TSP, which is a tour specified by the list +* of node numbers tour[1] -> ... -> tour[nn] -> tour[1] in the order +* the nodes are to be visited */ + +void build_tour(void) +{ int i, j, k, kk, *beg, *end; + /* solution to MIP should be feasible */ + switch (glp_mip_status(P)) + { case GLP_FEAS: + case GLP_OPT: + break; + default: + xassert(P != P); + } + /* build the list of edges included in the tour */ + beg = xalloc(1+n, sizeof(int)); + end = xalloc(1+n, sizeof(int)); + k = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { double x; + x = glp_mip_col_val(P, loc(i,j)); + xassert(x == 0 || x == 1); + if (x) + { k++; + xassert(k <= n); + beg[k] = i, end[k] = j; + } + } + } + xassert(k == n); + /* reorder edges in the list as they follow in the tour */ + for (k = 1; k <= n; k++) + { /* find k-th edge of the tour */ + j = (k == 1 ? 1 : end[k-1]); + for (kk = k; kk <= n; kk++) + { if (beg[kk] == j) + break; + if (end[kk] == j) + { end[kk] = beg[kk], beg[kk] = j; + break; + } + } + xassert(kk <= n); + /* put the edge to k-th position in the list */ + i = beg[k], beg[k] = beg[kk], beg[kk] = i; + j = end[k], end[k] = end[kk], end[kk] = j; + } + /* build the tour starting from node 1 */ + xassert(beg[1] == 1); + for (k = 1; k <= n; k++) + { if (k > 1) + xassert(end[k-1] == beg[k]); + tour[k] = beg[k]; + } + xassert(end[n] == 1); + xfree(beg); + xfree(end); + return; +} + +/*********************************************************************** +* tour_length - calculate tour length +* +* This routine calculates the length of the specified tour, which is +* the sum of corresponding edge lengths. */ + +int tour_length(const int tour[/*1+n*/]) +{ int i, j, sum; + sum = 0; + for (i = 1; i <= n; i++) + { j = (i < n ? i+1 : 1); + sum += c[loc(tour[i], tour[j])]; + } + return sum; +} + +/*********************************************************************** +* write_tour - write tour to text file in TSPLIB format +* +* This routine writes the specified tour to a text file in TSPLIB +* format. */ + +void write_tour(const char *fname, const int tour[/*1+n*/]) +{ FILE *fp; + int i; + xprintf("Writing TSP solution to '%s'...\n", fname); + fp = fopen(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, + strerror(errno)); + return; + } + fprintf(fp, "NAME : %s\n", fname); + fprintf(fp, "COMMENT : Tour length is %d\n", tour_length(tour)); + fprintf(fp, "TYPE : TOUR\n"); + fprintf(fp, "DIMENSION : %d\n", n); + fprintf(fp, "TOUR_SECTION\n"); + for (i = 1; i <= n; i++) + fprintf(fp, "%d\n", tour[i]); + fprintf(fp, "-1\n"); + fprintf(fp, "EOF\n"); + fclose(fp); + return; +} + +/*********************************************************************** +* gen_subt_row - generate violated subtour elimination constraint +* +* This routine is called from the MIP solver to generate a violated +* subtour elimination constraint (5). +* +* Constraints of this class has the form: +* +* sum x[i,j] >= 2, i in W, j in V \ W, +* +* for all W, where W is a proper nonempty subset of V, V is the set of +* nodes of the given graph. +* +* In order to find a violated constraint of this class this routine +* finds a min cut in a capacitated network, which has the same sets of +* nodes and edges as the original graph, and where capacities of edges +* are values of variables x[i,j] in a basic solution to LP relaxation +* of the current subproblem. */ + +void gen_subt(glp_tree *T) +{ int i, j, ne, nz, *beg, *end, *cap, *cut, *ind; + double sum, *val; + /* MIP preprocessor should not be used */ + xassert(glp_ios_get_prob(T) == P); + /* if some variable x[i,j] is zero in basic solution, then the + * capacity of corresponding edge in the associated network is + * zero, so we may not include such edge in the network */ + /* count number of edges having non-zero capacity */ + ne = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (glp_get_col_prim(P, loc(i,j)) >= .001) + ne++; + } + } + /* build the capacitated network */ + beg = xalloc(1+ne, sizeof(int)); + end = xalloc(1+ne, sizeof(int)); + cap = xalloc(1+ne, sizeof(int)); + nz = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (glp_get_col_prim(P, loc(i,j)) >= .001) + { nz++; + xassert(nz <= ne); + beg[nz] = i, end[nz] = j; + /* scale all edge capacities to make them integral */ + cap[nz] = ceil(1000 * glp_get_col_prim(P, loc(i,j))); + } + } + } + xassert(nz == ne); + /* find minimal cut in the capacitated network */ + cut = xalloc(1+n, sizeof(int)); + min_cut(n, ne, beg, end, cap, cut); + /* determine the number of non-zero coefficients in the subtour + * elimination constraint and calculate its left-hand side which + * is the (unscaled) capacity of corresponding min cut */ + ne = 0, sum = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (cut[i] && !cut[j] || !cut[i] && cut[j]) + { ne++; + sum += glp_get_col_prim(P, loc(i,j)); + } + } + } + /* if the (unscaled) capacity of min cut is less than 2, the + * corresponding subtour elimination constraint is violated */ + if (sum <= 1.999) + { /* build the list of non-zero coefficients */ + ind = xalloc(1+ne, sizeof(int)); + val = xalloc(1+ne, sizeof(double)); + nz = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (cut[i] && !cut[j] || !cut[i] && cut[j]) + { nz++; + xassert(nz <= ne); + ind[nz] = loc(i,j); + val[nz] = 1; + } + } + } + xassert(nz == ne); + /* add violated tour elimination constraint to the current + * subproblem */ + i = glp_add_rows(P, 1); + glp_set_row_bnds(P, i, GLP_LO, 2, 0); + glp_set_mat_row(P, i, nz, ind, val); + xfree(ind); + xfree(val); + } + /* free working arrays */ + xfree(beg); + xfree(end); + xfree(cap); + xfree(cut); + return; +} + +/*********************************************************************** +* cb_func - application callback routine +* +* This routine is called from the MIP solver at various points of +* the branch-and-cut algorithm. */ + +void cb_func(glp_tree *T, void *info) +{ xassert(info == info); + switch (glp_ios_reason(T)) + { case GLP_IROWGEN: + /* generate one violated subtour elimination constraint */ + gen_subt(T); + break; + } + return; +} + +/*********************************************************************** +* main - TSP solver main program +* +* This main program parses command-line arguments, reads specified TSP +* instance from a text file, and calls the MIP solver to solve it. */ + +int main(int argc, char *argv[]) +{ int j; + char *in_file = NULL, *out_file = NULL; + time_t start; + glp_iocp iocp; + /* parse command-line arguments */ +# define p(str) (strcmp(argv[j], str) == 0) + for (j = 1; j < argc; j++) + { if (p("--output") || p("-o")) + { j++; + if (j == argc || argv[j][0] == '\0' || argv[j][0] == '-') + { xprintf("No solution output file specified\n"); + exit(EXIT_FAILURE); + } + if (out_file != NULL) + { xprintf("Only one solution output file allowed\n"); + exit(EXIT_FAILURE); + } + out_file = argv[j]; + } + else if (p("--help") || p("-h")) + { xprintf("Usage: %s [options...] tsp-file\n", argv[0]); + xprintf("\n"); + xprintf("Options:\n"); + xprintf(" -o filename, --output filename\n"); + xprintf(" write solution to filename\n") + ; + xprintf(" -h, --help display this help information" + " and exit\n"); + exit(EXIT_SUCCESS); + } + else if (argv[j][0] == '-' || + (argv[j][0] == '-' && argv[j][1] == '-')) + { xprintf("Invalid option '%s'; try %s --help\n", argv[j], + argv[0]); + exit(EXIT_FAILURE); + } + else + { if (in_file != NULL) + { xprintf("Only one input file allowed\n"); + exit(EXIT_FAILURE); + } + in_file = argv[j]; + } + } + if (in_file == NULL) + { xprintf("No input file specified; try %s --help\n", argv[0]); + exit(EXIT_FAILURE); + } +# undef p + /* display program banner */ + xprintf("TSP Solver for GLPK %s\n", glp_version()); + /* remove output solution file specified in command-line */ + if (out_file != NULL) + remove(out_file); + /* read TSP instance from input data file */ + read_data(in_file); + /* build initial IP problem */ + start = time(NULL); + build_prob(); + tour = xalloc(1+n, sizeof(int)); + /* solve LP relaxation of initial IP problem */ + xprintf("Solving initial LP relaxation...\n"); + xassert(glp_simplex(P, NULL) == 0); + xassert(glp_get_status(P) == GLP_OPT); + /* solve IP problem with "lazy" constraints */ + glp_init_iocp(&iocp); + iocp.br_tech = GLP_BR_MFV; /* most fractional variable */ + iocp.bt_tech = GLP_BT_BLB; /* best local bound */ + iocp.sr_heur = GLP_OFF; /* disable simple rounding heuristic */ + iocp.gmi_cuts = GLP_ON; /* enable Gomory cuts */ + iocp.cb_func = cb_func; + glp_intopt(P, &iocp); + build_tour(); + /* display some statistics */ + xprintf("Time used: %.1f secs\n", difftime(time(NULL), start)); + { size_t tpeak; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%.0f bytes)\n", + (double)tpeak / 1048576.0, (double)tpeak); + } + /* write solution to output file, if required */ + if (out_file != NULL) + write_tour(out_file, tour); + /* deallocate working objects */ + xfree(c); + xfree(tour); + glp_delete_prob(P); + /* check that no memory blocks are still allocated */ + { int count; + size_t total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(total == 0); + } + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.c b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.c new file mode 100644 index 000000000..c28f5274d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.c @@ -0,0 +1,170 @@ +/* maxflow.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include + +#include +#include "maxflow.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* max_flow - find max flow in undirected capacitated network +* +* SYNOPSIS +* +* #include "maxflow.h" +* int max_flow(int nn, int ne, const int beg[], const int end[], +* const int cap[], int s, int t, int x[]); +* +* DESCRIPTION +* +* This routine finds max flow in a given undirected network. +* +* The undirected capacitated network is specified by the parameters +* nn, ne, beg, end, and cap. The parameter nn specifies the number of +* vertices (nodes), nn >= 2, and the parameter ne specifies the number +* of edges, ne >= 0. The network edges are specified by triplets +* (beg[k], end[k], cap[k]) for k = 1, ..., ne, where beg[k] < end[k] +* are numbers of the first and second nodes of k-th edge, and +* cap[k] > 0 is a capacity of k-th edge. Loops and multiple edges are +* not allowed. +* +* The parameter s is the number of a source node, and the parameter t +* is the number of a sink node, s != t. +* +* On exit the routine computes elementary flows thru edges and stores +* their values to locations x[1], ..., x[ne]. Positive value of x[k] +* means that the elementary flow goes from node beg[k] to node end[k], +* and negative value means that the flow goes in opposite direction. +* +* RETURNS +* +* The routine returns the total maximum flow through the network. */ + +int max_flow(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]) +{ int k; + /* sanity checks */ + xassert(nn >= 2); + xassert(ne >= 0); + xassert(1 <= s && s <= nn); + xassert(1 <= t && t <= nn); + xassert(s != t); + for (k = 1; k <= ne; k++) + { xassert(1 <= beg[k] && beg[k] < end[k] && end[k] <= nn); + xassert(cap[k] > 0); + } + /* find max flow */ + return max_flow_lp(nn, ne, beg, end, cap, s, t, x); +} + +/*********************************************************************** +* NAME +* +* max_flow_lp - find max flow with simplex method +* +* SYNOPSIS +* +* #include "maxflow.h" +* int max_flow_lp(int nn, int ne, const int beg[], const int end[], +* const int cap[], int s, int t, int x[]); +* +* DESCRIPTION +* +* This routine finds max flow in a given undirected network with the +* simplex method. +* +* Parameters of this routine have the same meaning as for the routine +* max_flow (see above). +* +* RETURNS +* +* The routine returns the total maximum flow through the network. */ + +int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]) +{ glp_prob *lp; + glp_smcp smcp; + int i, k, nz, flow, *rn, *cn; + double temp, *aa; + /* create LP problem instance */ + lp = glp_create_prob(); + /* create LP rows; i-th row is the conservation condition of the + * flow at i-th node, i = 1, ..., nn */ + glp_add_rows(lp, nn); + for (i = 1; i <= nn; i++) + glp_set_row_bnds(lp, i, GLP_FX, 0.0, 0.0); + /* create LP columns; k-th column is the elementary flow thru + * k-th edge, k = 1, ..., ne; the last column with the number + * ne+1 is the total flow through the network, which goes along + * a dummy feedback edge from the sink to the source */ + glp_add_cols(lp, ne+1); + for (k = 1; k <= ne; k++) + { xassert(cap[k] > 0); + glp_set_col_bnds(lp, k, GLP_DB, -cap[k], +cap[k]); + } + glp_set_col_bnds(lp, ne+1, GLP_FR, 0.0, 0.0); + /* build the constraint matrix; structurally this matrix is the + * incidence matrix of the network, so each its column (including + * the last column for the dummy edge) has exactly two non-zero + * entries */ + rn = xalloc(1+2*(ne+1), sizeof(int)); + cn = xalloc(1+2*(ne+1), sizeof(int)); + aa = xalloc(1+2*(ne+1), sizeof(double)); + nz = 0; + for (k = 1; k <= ne; k++) + { /* x[k] > 0 means the elementary flow thru k-th edge goes from + * node beg[k] to node end[k] */ + nz++, rn[nz] = beg[k], cn[nz] = k, aa[nz] = -1.0; + nz++, rn[nz] = end[k], cn[nz] = k, aa[nz] = +1.0; + } + /* total flow thru the network goes from the sink to the source + * along the dummy feedback edge */ + nz++, rn[nz] = t, cn[nz] = ne+1, aa[nz] = -1.0; + nz++, rn[nz] = s, cn[nz] = ne+1, aa[nz] = +1.0; + /* check the number of non-zero entries */ + xassert(nz == 2*(ne+1)); + /* load the constraint matrix into the LP problem object */ + glp_load_matrix(lp, nz, rn, cn, aa); + xfree(rn); + xfree(cn); + xfree(aa); + /* objective function is the total flow through the network to + * be maximized */ + glp_set_obj_dir(lp, GLP_MAX); + glp_set_obj_coef(lp, ne + 1, 1.0); + /* solve LP instance with the (primal) simplex method */ + glp_term_out(0); + glp_adv_basis(lp, 0); + glp_term_out(1); + glp_init_smcp(&smcp); + smcp.msg_lev = GLP_MSG_ON; + smcp.out_dly = 5000; + xassert(glp_simplex(lp, &smcp) == 0); + xassert(glp_get_status(lp) == GLP_OPT); + /* obtain optimal elementary flows thru edges of the network */ + /* (note that the constraint matrix is unimodular and the data + * are integral, so all elementary flows in basic solution should + * also be integral) */ + for (k = 1; k <= ne; k++) + { temp = glp_get_col_prim(lp, k); + x[k] = (int)floor(temp + .5); + xassert(fabs(x[k] - temp) <= 1e-6); + } + /* obtain the maximum flow thru the original network which is the + * flow thru the dummy feedback edge */ + temp = glp_get_col_prim(lp, ne+1); + flow = (int)floor(temp + .5); + xassert(fabs(flow - temp) <= 1e-6); + /* delete LP problem instance */ + glp_delete_prob(lp); + /* return to the calling program */ + return flow; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.h b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.h new file mode 100644 index 000000000..245c5ec12 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/maxflow.h @@ -0,0 +1,20 @@ +/* maxflow.h */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MAXFLOW_H +#define MAXFLOW_H + +int max_flow(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]); +/* find max flow in undirected capacitated network */ + +int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]); +/* find max flow with simplex method */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.c b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.c new file mode 100644 index 000000000..225fb7f44 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.c @@ -0,0 +1,392 @@ +/* mincut.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include + +#include "maxflow.h" +#include "mincut.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* min_cut - find min cut in undirected capacitated network +* +* SYNOPSIS +* +* #include "mincut.h" +* int min_cut(int nn, int ne, const int beg[], const int end[], +* const cap[], int cut[]); +* +* DESCRIPTION +* +* This routine finds min cut in a given undirected network. +* +* The undirected capacitated network is specified by the parameters +* nn, ne, beg, end, and cap. The parameter nn specifies the number of +* vertices (nodes), nn >= 2, and the parameter ne specifies the number +* of edges, ne >= 0. The network edges are specified by triplets +* (beg[k], end[k], cap[k]) for k = 1, ..., ne, where beg[k] < end[k] +* are numbers of the first and second nodes of k-th edge, and +* cap[k] > 0 is a capacity of k-th edge. Loops and multiple edges are +* not allowed. +* +* Let V be the set of nodes of the network and let W be an arbitrary +* non-empty proper subset of V. A cut associated with the subset W is +* a subset of all the edges, one node of which belongs to W and other +* node belongs to V \ W. The capacity of a cut (W, V \ W) is the sum +* of the capacities of all the edges, which belong to the cut. Minimal +* cut is a cut, whose capacity is minimal. +* +* On exit the routine stores flags of nodes v[i], i = 1, ..., nn, to +* locations cut[i], where cut[i] = 1 means that v[i] belongs to W and +* cut[i] = 0 means that v[i] belongs to V \ W, where W corresponds to +* the minimal cut found. +* +* RETURNS +* +* The routine returns the capacity of the min cut found. */ + +int min_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]) +{ int k; + /* sanity checks */ + xassert(nn >= 2); + xassert(ne >= 0); + for (k = 1; k <= ne; k++) + { xassert(1 <= beg[k] && beg[k] < end[k] && end[k] <= nn); + xassert(cap[k] > 0); + } + /* find min cut */ + return min_cut_sw(nn, ne, beg, end, cap, cut); +} + +/*********************************************************************** +* NAME +* +* min_st_cut - find min (s,t)-cut for known max flow +* +* SYNOPSIS +* +* #include "mincut.h" +* +* DESCRIPTION +* +* This routine finds min (s,t)-cut in a given undirected network that +* corresponds to a known max flow from s to t in the network. +* +* Parameters nn, ne, beg, end, and cap specify the network in the same +* way as for the routine min_cut (see above). +* +* Parameters s and t specify, resp., the number of the source node +* and the number of the sink node, s != t, for which the min (s,t)-cut +* has to be found. +* +* Parameter x specifies the known max flow from s to t in the network, +* where locations x[1], ..., x[ne] contains elementary flow thru edges +* of the network (positive value of x[k] means that the elementary +* flow goes from node beg[k] to node end[k], and negative value means +* that the flow goes in opposite direction). +* +* This routine splits the set of nodes V of the network into two +* non-empty subsets V(s) and V(t) = V \ V(s), where the source node s +* belongs to V(s), the sink node t belongs to V(t), and all edges, one +* node of which belongs to V(s) and other one belongs to V(t), are +* saturated (that is, x[k] = +cap[k] or x[k] = -cap[k]). +* +* On exit the routine stores flags of the nodes v[i], i = 1, ..., nn, +* to locations cut[i], where cut[i] = 1 means that v[i] belongs to V(s) +* and cut[i] = 0 means that v[i] belongs to V(t) = V \ V(s). +* +* RETURNS +* +* The routine returns the capacity of min (s,t)-cut, which is the sum +* of the capacities of all the edges, which belong to the cut. (Note +* that due to theorem by Ford and Fulkerson this value is always equal +* to corresponding max flow.) +* +* ALGORITHM +* +* To determine the set V(s) the routine simply finds all nodes, which +* can be reached from the source node s via non-saturated edges. The +* set V(t) is determined as the complement V \ V(s). */ + +int min_st_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + const int x[/*1+ne*/], int cut[/*1+nn*/]) +{ int i, j, k, p, q, temp, *head1, *next1, *head2, *next2, *list; + /* head1[i] points to the first edge with beg[k] = i + * next1[k] points to the next edge with the same beg[k] + * head2[i] points to the first edge with end[k] = i + * next2[k] points to the next edge with the same end[k] */ + head1 = xalloc(1+nn, sizeof(int)); + head2 = xalloc(1+nn, sizeof(int)); + next1 = xalloc(1+ne, sizeof(int)); + next2 = xalloc(1+ne, sizeof(int)); + for (i = 1; i <= nn; i++) + head1[i] = head2[i] = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], next1[k] = head1[i], head1[i] = k; + j = end[k], next2[k] = head2[j], head2[j] = k; + } + /* on constructing the set V(s) list[1], ..., list[p-1] contain + * nodes, which can be reached from source node and have been + * visited, and list[p], ..., list[q] contain nodes, which can be + * reached from source node but havn't been visited yet */ + list = xalloc(1+nn, sizeof(int)); + for (i = 1; i <= nn; i++) + cut[i] = 0; + p = q = 1, list[1] = s, cut[s] = 1; + while (p <= q) + { /* pick next node, which is reachable from the source node and + * has not visited yet, and visit it */ + i = list[p++]; + /* walk through edges with beg[k] = i */ + for (k = head1[i]; k != 0; k = next1[k]) + { j = end[k]; + xassert(beg[k] == i); + /* from v[i] we can reach v[j], if the elementary flow from + * v[i] to v[j] is non-saturated */ + if (cut[j] == 0 && x[k] < +cap[k]) + list[++q] = j, cut[j] = 1; + } + /* walk through edges with end[k] = i */ + for (k = head2[i]; k != 0; k = next2[k]) + { j = beg[k]; + xassert(end[k] == i); + /* from v[i] we can reach v[j], if the elementary flow from + * v[i] to v[j] is non-saturated */ + if (cut[j] == 0 && x[k] > -cap[k]) + list[++q] = j, cut[j] = 1; + } + } + /* sink cannot belong to V(s) */ + xassert(!cut[t]); + /* free working arrays */ + xfree(head1); + xfree(head2); + xfree(next1); + xfree(next2); + xfree(list); + /* compute capacity of the minimal (s,t)-cut found */ + temp = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], j = end[k]; + if (cut[i] && !cut[j] || !cut[i] && cut[j]) + temp += cap[k]; + } + /* return to the calling program */ + return temp; +} + +/*********************************************************************** +* NAME +* +* min_cut_sw - find min cut with Stoer and Wagner algorithm +* +* SYNOPSIS +* +* #include "mincut.h" +* int min_cut_sw(int nn, int ne, const int beg[], const int end[], +* const cap[], int cut[]); +* +* DESCRIPTION +* +* This routine find min cut in a given undirected network with the +* algorithm proposed by Stoer and Wagner (see references below). +* +* Parameters of this routine have the same meaning as for the routine +* min_cut (see above). +* +* RETURNS +* +* The routine returns the capacity of the min cut found. +* +* ALGORITHM +* +* The basic idea of Stoer&Wagner algorithm is the following. Let G be +* a capacitated network, and G(s,t) be a network, in which the nodes s +* and t are merged into one new node, loops are deleted, but multiple +* edges are retained. It is obvious that a minimum cut in G is the +* minimum of two quantities: the minimum cut in G(s,t) and a minimum +* cut that separates s and t. This allows to find a minimum cut in the +* original network solving at most nn max flow problems. +* +* REFERENCES +* +* M. Stoer, F. Wagner. A Simple Min Cut Algorithm. Algorithms, ESA'94 +* LNCS 855 (1994), pp. 141-47. +* +* J. Cheriyan, R. Ravi. Approximation Algorithms for Network Problems. +* Univ. of Waterloo (1998), p. 147. */ + +int min_cut_sw(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]) +{ int i, j, k, min_cut, flow, temp, *head1, *next1, *head2, *next2; + int I, J, K, S, T, DEG, NV, NE, *HEAD, *NEXT, *NUMB, *BEG, *END, + *CAP, *X, *ADJ, *SUM, *CUT; + /* head1[i] points to the first edge with beg[k] = i + * next1[k] points to the next edge with the same beg[k] + * head2[i] points to the first edge with end[k] = i + * next2[k] points to the next edge with the same end[k] */ + head1 = xalloc(1+nn, sizeof(int)); + head2 = xalloc(1+nn, sizeof(int)); + next1 = xalloc(1+ne, sizeof(int)); + next2 = xalloc(1+ne, sizeof(int)); + for (i = 1; i <= nn; i++) + head1[i] = head2[i] = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], next1[k] = head1[i], head1[i] = k; + j = end[k], next2[k] = head2[j], head2[j] = k; + } + /* an auxiliary network used in the algorithm is resulted from + * the original network by merging some nodes into one supernode; + * all variables and arrays related to this auxiliary network are + * denoted in CAPS */ + /* HEAD[I] points to the first node of the original network that + * belongs to the I-th supernode + * NEXT[i] points to the next node of the original network that + * belongs to the same supernode as the i-th node + * NUMB[i] is a supernode, which the i-th node belongs to */ + /* initially the auxiliary network is equivalent to the original + * network, i.e. each supernode consists of one node */ + NV = nn; + HEAD = xalloc(1+nn, sizeof(int)); + NEXT = xalloc(1+nn, sizeof(int)); + NUMB = xalloc(1+nn, sizeof(int)); + for (i = 1; i <= nn; i++) + HEAD[i] = i, NEXT[i] = 0, NUMB[i] = i; + /* number of edges in the auxiliary network is never greater than + * in the original one */ + BEG = xalloc(1+ne, sizeof(int)); + END = xalloc(1+ne, sizeof(int)); + CAP = xalloc(1+ne, sizeof(int)); + X = xalloc(1+ne, sizeof(int)); + /* allocate some auxiliary arrays */ + ADJ = xalloc(1+nn, sizeof(int)); + SUM = xalloc(1+nn, sizeof(int)); + CUT = xalloc(1+nn, sizeof(int)); + /* currently no min cut is found so far */ + min_cut = INT_MAX; + /* main loop starts here */ + while (NV > 1) + { /* build the set of edges of the auxiliary network */ + NE = 0; + /* multiple edges are not allowed in the max flow algorithm, + * so we can replace each multiple edge, which is the result + * of merging nodes into supernodes, by a single edge, whose + * capacity is the sum of capacities of particular edges; + * these summary capacities will be stored in the array SUM */ + for (I = 1; I <= NV; I++) + SUM[I] = 0.0; + for (I = 1; I <= NV; I++) + { /* DEG is number of single edges, which connects I-th + * supernode and some J-th supernode, where I < J */ + DEG = 0; + /* walk thru nodes that belong to I-th supernode */ + for (i = HEAD[I]; i != 0; i = NEXT[i]) + { /* i-th node belongs to I-th supernode */ + /* walk through edges with beg[k] = i */ + for (k = head1[i]; k != 0; k = next1[k]) + { j = end[k]; + /* j-th node belongs to J-th supernode */ + J = NUMB[j]; + /* ignore loops and edges with I > J */ + if (I >= J) + continue; + /* add an edge that connects I-th and J-th supernodes + * (if not added yet) */ + if (SUM[J] == 0.0) + ADJ[++DEG] = J; + /* sum up the capacity of the original edge */ + xassert(cap[k] > 0.0); + SUM[J] += cap[k]; + } + /* walk through edges with end[k] = i */ + for (k = head2[i]; k != 0; k = next2[k]) + { j = beg[k]; + /* j-th node belongs to J-th supernode */ + J = NUMB[j]; + /* ignore loops and edges with I > J */ + if (I >= J) + continue; + /* add an edge that connects I-th and J-th supernodes + * (if not added yet) */ + if (SUM[J] == 0.0) + ADJ[++DEG] = J; + /* sum up the capacity of the original edge */ + xassert(cap[k] > 0.0); + SUM[J] += cap[k]; + } + } + /* add single edges connecting I-th supernode with other + * supernodes to the auxiliary network; restore the array + * SUM for subsequent use */ + for (K = 1; K <= DEG; K++) + { NE++; + xassert(NE <= ne); + J = ADJ[K]; + BEG[NE] = I, END[NE] = J, CAP[NE] = SUM[J]; + SUM[J] = 0.0; + } + } + /* choose two arbitrary supernodes of the auxiliary network, + * one of which is the source and other is the sink */ + S = 1, T = NV; + /* determine max flow from S to T */ + flow = max_flow(NV, NE, BEG, END, CAP, S, T, X); + /* if the min cut that separates supernodes S and T is less + * than the currently known, remember it */ + if (min_cut > flow) + { min_cut = flow; + /* find min (s,t)-cut in the auxiliary network */ + temp = min_st_cut(NV, NE, BEG, END, CAP, S, T, X, CUT); + /* (Ford and Fulkerson insist on this) */ + xassert(flow == temp); + /* build corresponding min cut in the original network */ + for (i = 1; i <= nn; i++) cut[i] = CUT[NUMB[i]]; + /* if the min cut capacity is zero (i.e. the network has + * unconnected components), the search can be prematurely + * terminated */ + if (min_cut == 0) + break; + } + /* now merge all nodes of the original network, which belong + * to the supernodes S and T, into one new supernode; this is + * attained by carrying all nodes from T to S (for the sake of + * convenience T should be the last supernode) */ + xassert(T == NV); + /* assign new references to nodes from T */ + for (i = HEAD[T]; i != 0; i = NEXT[i]) + NUMB[i] = S; + /* find last entry in the node list of S */ + i = HEAD[S]; + xassert(i != 0); + while (NEXT[i] != 0) + i = NEXT[i]; + /* and attach to it the node list of T */ + NEXT[i] = HEAD[T]; + /* decrease number of nodes in the auxiliary network */ + NV--; + } + /* free working arrays */ + xfree(HEAD); + xfree(NEXT); + xfree(NUMB); + xfree(BEG); + xfree(END); + xfree(CAP); + xfree(X); + xfree(ADJ); + xfree(SUM); + xfree(CUT); + xfree(head1); + xfree(head2); + xfree(next1); + xfree(next2); + /* return to the calling program */ + return min_cut; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.h b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.h new file mode 100644 index 000000000..aefdbb7dd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/mincut.h @@ -0,0 +1,23 @@ +/* mincut.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MINCUT_H +#define MINCUT_H + +int min_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]); +/* find min cut in undirected capacitated network */ + +int min_st_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + const int x[/*1+ne*/], int cut[/*1+nn*/]); +/* find min (s,t)-cut for known max flow */ + +int min_cut_sw(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]); +/* find min cut with Stoer and Wagner algorithm */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.c b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.c new file mode 100644 index 000000000..e0b08fb5b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.c @@ -0,0 +1,159 @@ +/* misc.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include +#include +#include +#include +#include "misc.h" + +/*********************************************************************** +* NAME +* +* str2int - convert character string to value of int type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2int(const char *str, int *val); +* +* DESCRIPTION +* +* The routine str2int converts the character string str to a value of +* integer type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2int(const char *str, int *val_) +{ int d, k, s, val = 0; + /* scan optional sign */ + if (str[0] == '+') + s = +1, k = 1; + else if (str[0] == '-') + s = -1, k = 1; + else + s = +1, k = 0; + /* check for the first digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan digits */ + while (isdigit((unsigned char)str[k])) + { d = str[k++] - '0'; + if (s > 0) + { if (val > INT_MAX / 10) + return 1; + val *= 10; + if (val > INT_MAX - d) + return 1; + val += d; + } + else /* s < 0 */ + { if (val < INT_MIN / 10) + return 1; + val *= 10; + if (val < INT_MIN + d) + return 1; + val -= d; + } + } + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/*********************************************************************** +* NAME +* +* str2num - convert character string to value of double type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2num(const char *str, double *val); +* +* DESCRIPTION +* +* The routine str2num converts the character string str to a value of +* double type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2num(const char *str, double *val_) +{ int k; + double val; + /* scan optional sign */ + k = (str[0] == '+' || str[0] == '-' ? 1 : 0); + /* check for decimal point */ + if (str[k] == '.') + { k++; + /* a digit should follow it */ + if (!isdigit((unsigned char)str[k])) + return 2; + k++; + goto frac; + } + /* integer part should start with a digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan integer part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal point */ + if (str[k] == '.') k++; +frac: /* scan optional fraction part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal exponent */ + if (str[k] == 'E' || str[k] == 'e') + { k++; + /* scan optional sign */ + if (str[k] == '+' || str[k] == '-') + k++; + /* a digit should follow E, E+ or E- */ + if (!isdigit((unsigned char)str[k])) + return 2; + } + /* scan optional exponent part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* perform conversion */ + { char *endptr; + val = strtod(str, &endptr); + if (*endptr != '\0') + return 2; + } + /* check for overflow */ + if (!(-DBL_MAX <= val && val <= +DBL_MAX)) + return 1; + /* check for underflow */ + if (-DBL_MIN < val && val < +DBL_MIN) + val = 0.0; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.h b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.h new file mode 100644 index 000000000..097383157 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/misc.h @@ -0,0 +1,24 @@ +/* misc.h */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MISC_H +#define MISC_H + +#include + +#define xprintf glp_printf +#define xerror glp_error +#define xassert glp_assert +#define xalloc glp_alloc +#define xfree glp_free + +int str2int(const char *str, int *val); +/* convert character string to value of int type */ + +int str2num(const char *str, double *val); +/* convert character string to value of double type */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/moscow.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/moscow.tsp new file mode 100644 index 000000000..a2d4ea2fa --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/moscow.tsp @@ -0,0 +1,200 @@ +NAME: MOSCOW +TYPE: TSP +COMMENT: 68 cities in Moscow region (Andrew Makhorin ) +DIMENSION: 68 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +EDGE_WEIGHT_SECTION +0 +80 0 +99 66 0 +73 153 156 0 +118 156 205 116 0 +136 103 37 190 242 0 +134 128 180 141 90 217 0 +72 75 127 126 81 164 86 0 +131 94 146 184 133 183 67 91 0 +75 38 90 136 126 127 94 45 56 0 +67 52 46 124 169 83 165 88 132 76 0 +134 66 69 207 219 68 189 138 136 101 106 0 +179 142 194 204 153 231 87 139 52 104 180 188 0 +145 98 63 216 240 26 212 159 178 122 109 53 226 0 +83 7 69 156 159 106 131 78 97 41 55 60 145 95 0 +85 38 68 158 180 105 152 99 118 62 57 74 166 100 41 0 +188 163 97 222 294 77 277 223 243 187 135 145 291 93 166 165 0 +38 101 125 92 80 162 96 34 101 71 93 164 149 176 104 116 214 0 +88 66 118 142 97 155 62 40 67 36 103 129 115 150 69 90 215 50 0 +113 50 102 174 164 139 136 83 92 46 88 94 140 134 53 74 199 109 74 0 +67 94 146 113 62 183 81 19 86 64 107 157 134 178 97 118 242 29 35 102 0 +133 132 96 167 239 91 245 168 212 156 80 159 260 117 135 137 55 159 183 + 168 187 0 +51 64 54 108 157 91 159 82 139 83 25 118 187 117 67 69 143 77 97 100 101 + 88 0 +122 116 168 129 78 205 12 74 55 82 153 177 75 200 119 140 265 84 50 124 + 69 233 147 0 +148 115 49 202 254 29 229 176 195 139 95 97 243 45 118 117 48 174 167 + 151 195 83 103 217 0 +95 32 84 156 146 121 118 65 84 28 70 95 132 116 35 56 181 91 56 18 84 + 150 82 106 133 0 +133 70 122 194 184 159 156 103 112 66 108 99 160 148 73 94 219 129 94 25 + 122 188 120 144 171 38 0 +57 58 110 118 98 147 103 17 84 28 71 121 132 142 61 82 206 43 42 66 36 + 151 65 91 159 48 86 0 +164 101 142 225 188 167 122 134 55 97 139 109 107 152 104 125 239 150 + 116 67 135 219 151 110 191 69 87 117 0 +145 93 78 218 240 41 212 159 153 122 117 27 205 26 87 100 118 176 150 + 121 178 132 129 200 70 116 126 142 126 0 +142 74 77 215 227 60 197 146 134 109 114 8 186 45 68 82 137 172 137 102 + 165 151 126 185 89 103 107 129 107 19 0 +85 48 100 146 119 137 84 55 63 10 86 111 111 132 51 72 197 72 38 56 57 + 166 93 72 149 38 76 38 107 132 119 0 +106 26 73 179 182 110 154 101 120 64 78 48 168 97 30 62 170 127 92 76 + 120 158 90 142 122 58 84 84 102 75 56 74 0 +171 138 72 225 277 52 252 199 218 162 118 120 266 68 141 140 25 197 190 + 174 218 80 126 240 23 156 194 182 214 93 112 172 145 0 +65 18 48 138 160 85 132 79 98 42 37 69 146 80 21 20 145 96 70 54 98 117 + 49 120 97 36 74 62 105 80 77 52 44 120 0 +90 163 173 17 99 207 124 111 167 138 141 217 187 228 166 168 239 77 127 + 176 96 184 125 112 219 158 196 120 222 228 225 148 189 242 148 0 +47 22 67 116 121 104 106 40 80 24 44 85 128 99 25 39 164 66 44 46 59 124 + 46 94 116 28 66 23 97 99 93 34 48 139 19 118 0 +89 26 78 150 140 115 112 59 78 22 64 89 126 110 29 50 175 85 50 24 78 + 144 76 100 127 6 44 42 75 110 97 32 52 150 30 152 22 0 +31 111 118 42 134 155 153 91 157 101 86 165 205 176 114 116 207 57 107 + 139 86 152 70 141 167 121 159 83 190 176 173 111 137 190 96 59 78 115 0 +115 35 56 188 191 93 158 110 111 73 87 31 159 80 42 45 153 136 101 63 + 129 152 99 146 105 65 68 93 86 58 39 83 17 128 53 198 57 61 146 0 +37 70 103 91 121 140 121 44 101 45 62 124 149 135 73 75 197 41 59 83 63 + 142 56 109 152 65 103 27 134 135 132 55 96 175 55 93 25 59 56 105 0 +143 142 106 177 249 101 255 178 222 166 90 169 270 127 145 147 65 169 + 193 178 197 10 98 243 93 160 198 161 229 142 161 176 168 90 127 194 134 + 154 162 162 152 0 +152 151 115 186 258 110 264 187 231 175 99 178 279 136 154 156 100 178 + 202 187 206 45 107 252 98 169 207 170 238 151 170 185 177 121 136 203 + 143 163 171 171 161 55 0 +146 74 81 219 230 70 191 149 124 112 118 12 176 55 72 84 147 175 140 102 + 168 161 130 179 99 104 107 132 97 29 10 122 56 122 81 229 96 100 177 39 + 136 171 180 0 +118 50 53 191 203 84 173 122 126 85 90 16 174 69 44 58 150 148 113 78 + 141 149 102 161 102 79 83 105 101 43 24 95 32 125 53 201 69 73 149 15 + 108 159 168 28 0 +50 56 62 107 155 99 151 74 131 75 17 110 179 121 59 61 151 76 89 92 93 + 96 8 139 111 74 112 57 143 121 118 85 82 134 41 124 38 68 69 91 48 106 + 115 122 94 0 +107 126 110 113 209 117 221 144 201 145 87 179 249 143 129 131 149 133 + 159 162 162 94 62 209 129 144 182 127 213 158 177 155 152 152 111 130 + 108 138 98 161 118 104 113 187 163 70 0 +105 42 94 166 156 131 128 75 84 38 80 86 132 126 45 66 191 101 66 8 94 + 160 92 116 143 10 28 58 59 113 94 48 68 166 46 168 38 16 131 55 75 170 + 179 94 70 84 154 0 +114 133 117 120 216 124 228 151 208 152 94 186 256 150 136 138 156 140 + 166 169 169 101 69 216 136 151 189 134 220 165 184 162 159 159 118 137 + 115 145 105 168 125 111 120 194 170 77 35 161 0 +89 42 72 162 184 109 156 103 122 66 61 70 170 104 45 4 169 120 94 78 122 + 141 73 144 121 60 98 86 127 97 78 76 58 144 24 172 43 54 120 41 79 151 + 160 80 54 65 135 70 142 0 +218 166 151 291 313 114 285 232 226 195 190 100 278 99 160 173 191 249 + 223 194 251 205 202 273 143 189 199 215 199 73 92 205 148 166 153 301 + 172 183 249 131 208 215 224 102 116 194 231 186 238 170 0 +81 147 168 48 68 205 93 80 136 117 136 208 156 219 150 159 250 46 96 155 + 65 195 120 81 217 137 175 89 191 219 216 118 173 240 139 31 109 131 66 + 182 84 205 214 220 192 119 141 147 148 163 292 0 +147 84 125 208 180 160 115 117 48 80 122 100 100 145 87 108 222 133 99 + 50 118 202 134 103 174 52 70 100 17 119 100 90 85 197 88 210 80 58 173 + 69 117 212 221 90 84 126 196 42 203 110 192 179 0 +93 112 96 99 195 103 207 130 187 131 73 165 235 129 115 117 135 119 145 + 148 148 80 48 195 115 130 168 113 199 144 163 141 138 138 97 116 94 124 + 84 147 104 90 99 173 149 56 14 140 21 121 217 127 182 0 +97 91 143 151 103 180 37 49 76 57 128 152 100 175 94 115 240 59 25 99 44 + 208 122 25 192 81 119 66 125 175 160 47 117 215 95 136 69 75 116 121 84 + 218 227 160 136 114 184 91 191 119 248 105 108 170 0 +122 121 85 156 228 80 234 157 201 145 69 148 249 106 124 126 70 148 172 + 157 176 15 77 222 68 139 177 140 208 121 140 155 147 91 106 173 113 133 + 141 141 131 25 30 150 138 85 83 149 90 130 194 184 191 69 197 0 +179 142 194 232 181 222 115 139 48 104 180 164 38 207 145 166 291 149 + 115 126 134 260 187 103 243 128 146 132 83 181 162 111 161 266 146 215 + 128 126 205 145 149 270 279 152 160 179 249 118 256 170 254 184 76 235 + 124 249 0 +38 67 82 99 144 119 146 69 126 70 50 121 174 132 70 72 171 64 84 103 88 + 116 34 134 131 85 123 52 154 132 129 80 93 154 52 116 40 79 57 102 43 + 126 135 133 105 33 90 95 97 76 205 107 137 76 109 105 174 0 +100 34 86 173 168 123 140 87 100 50 72 70 148 118 37 58 183 113 78 52 + 106 152 84 128 135 44 57 70 75 97 78 60 27 158 38 180 39 38 131 39 87 + 162 171 78 54 76 146 44 153 62 170 159 58 132 103 141 134 87 0 +69 46 98 130 117 135 82 39 72 16 83 109 120 130 49 70 195 65 20 54 55 + 163 77 70 147 36 74 22 105 130 117 26 72 170 50 132 24 30 95 81 39 173 + 182 120 93 69 139 46 146 74 203 111 88 125 45 152 120 64 58 0 +160 97 138 219 168 173 102 126 35 91 135 113 87 158 100 121 235 136 102 + 63 121 215 147 90 187 65 83 113 30 132 113 98 98 210 101 202 93 71 186 + 82 130 225 234 103 97 139 209 55 216 123 205 171 13 195 111 204 83 150 + 71 101 0 +70 89 73 110 176 104 184 107 164 108 50 142 212 130 92 94 136 96 122 125 + 125 81 25 172 116 107 145 90 176 145 150 118 115 139 74 127 71 101 89 + 124 81 91 100 154 126 33 37 117 44 98 218 138 159 23 147 70 212 53 109 + 102 172 0 +188 136 121 261 283 84 255 202 196 165 160 70 248 69 130 143 161 219 193 + 164 221 175 172 243 113 159 169 185 169 43 62 175 118 136 123 271 142 + 153 219 101 178 185 194 72 86 164 201 156 208 140 30 262 162 187 218 + 164 224 175 140 173 175 188 0 +94 28 80 167 162 117 134 81 100 44 66 69 148 112 31 52 177 107 72 56 100 + 146 78 122 129 38 63 64 81 96 77 54 21 152 32 174 33 32 125 38 81 156 + 165 77 53 70 140 48 147 56 169 153 64 126 97 135 140 81 6 52 77 103 139 + 0 +45 43 75 118 142 112 138 61 118 62 30 97 166 108 46 48 164 76 76 79 80 + 109 21 126 124 61 99 44 130 108 105 72 69 147 28 128 25 55 76 78 35 119 + 128 109 81 13 83 71 90 52 181 119 113 69 101 98 166 32 63 56 126 46 151 + 57 0 +113 35 48 186 191 85 163 110 119 73 85 37 167 72 39 37 145 136 101 71 + 129 144 97 151 97 67 76 93 94 64 45 83 25 120 48 196 57 61 144 8 103 + 154 163 47 21 89 158 63 165 33 137 182 77 144 126 133 153 100 47 81 90 + 121 107 46 76 0 +97 21 57 170 173 94 145 92 111 55 69 46 159 81 14 55 154 118 83 67 111 + 149 81 133 106 49 87 75 118 73 54 65 18 129 35 180 39 43 128 33 87 159 + 168 58 30 73 143 59 150 58 146 164 101 129 108 138 159 84 45 63 114 106 + 116 39 60 25 0 +116 79 131 177 133 168 98 76 51 41 117 127 63 163 82 103 228 86 52 77 71 + 197 124 86 180 69 97 69 100 154 135 48 105 203 83 163 65 63 142 96 86 + 207 216 135 111 116 186 69 193 107 227 132 83 172 61 186 63 111 85 57 + 86 149 197 85 103 104 96 0 +EOF + +Vertices of the graph: + 1 Aprelevka 35 Lyubertsy + 2 Balashikha 36 Mozhaysk + 3 Bronnitsy 37 Moskva + 4 Vereya 38 Mytischi + 5 Volokolamsk 39 Naro-Fominsk + 6 Voskresensk 40 Noginsk + 7 Vysokovsk 41 Odintsovo + 8 Dedovsk 42 Ozherel'ye + 9 Dmitrov 43 Ozyory +10 Dolgoprudny 44 Orekhovo-Zuevo +11 Domodedovo 45 Pavlovsky Posad +12 Drezna 46 Podol'sk +13 Dubna 47 Protvino +14 Egor'yevsk 48 Pushkino +15 Zheleznodorozhny 49 Puschino +16 Zhukovsky 50 Ramenskoye +17 Zaraysk 51 Roshal +18 Zvenigorod 52 Ruza +19 Zelenograd 53 Sergiyev Posad +20 Ivanteyevka 54 Serpukhov +21 Istra 55 Solnechnogorsk +22 Kashira 56 Stupino +23 Klimovsk 57 Taldom +24 Klin 58 Troitsk +25 Kolomna 59 Fryazino +26 Korolyov (Podlipki) 60 Khimki +27 Krasnoarmeysk 61 Khot'kovo +28 Krasnogorsk 62 Chekhov +29 Krasnozavodsk 63 Shatura +30 Kurovskoye 64 Schyolkovo +31 Likino-Dulyovo 65 Scherbinka +32 Lobnya 66 Elektrostal +33 Losino-Petrovsky 67 Elektrougli +34 Lukhovitsy 68 Yakhroma + +Optimal tour length is 1994 kilometers (obtained by glpk tspsol): +1 39 4 36 52 5 7 24 55 19 60 10 32 68 13 57 9 61 53 29 27 20 48 26 38 +59 64 33 67 15 2 35 16 50 66 40 45 12 44 31 63 51 30 14 6 3 25 34 17 22 +42 56 43 47 49 54 62 23 46 11 65 58 41 37 28 8 21 18 1 diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/sample.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/sample.tsp new file mode 100644 index 000000000..9e1367a33 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/sample.tsp @@ -0,0 +1,16 @@ +NAME: SAMPLE +TYPE: TSP +COMMENT: Example from D.Phillips, A.Garcia-Diaz, p.124 +DIMENSION: 8 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +EDGE_WEIGHT_SECTION +0 +190 0 +210 380 0 +680 760 890 0 +690 790 900 480 0 +460 610 340 760 890 0 +780 670 410 510 490 720 0 +750 450 600 250 560 600 500 0 +EOF diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.c b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.c new file mode 100644 index 000000000..189ff8aa5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.c @@ -0,0 +1,730 @@ +/* tsplib.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" +#include "tsplib.h" + +/*********************************************************************** +* NAME +* +* tsp_read_data - read TSP instance data +* +* SYNOPSIS +* +* #include "tsplib.h" +* TSP *tsp_read_data(const char *fname); +* +* DESCRIPTION +* +* The routine tsp_read_data reads a TSP (or related problem) instance +* data from a text file, whose name is the character string fname. +* +* For detailed description of the format recognized by the routine see +* the report: G.Reinelt, TSPLIB 95. +* +* RETURNS +* +* If no error occurred, the routine tsp_read_data returns a pointer to +* the TSP instance data block, which contains loaded data. In the case +* of error the routine prints an error message and returns NULL. */ + +struct csa +{ /* common storage area used by the routine tsp_read_data */ + const char *fname; + /* name of the input text file */ + FILE *fp; + /* stream assigned to the input text file */ + int seqn; + /* line sequential number */ + int c; + /* current character */ + char token[255+1]; + /* current token */ +}; + +static int get_char(struct csa *csa) +{ csa->c = fgetc(csa->fp); + if (ferror(csa->fp)) + { xprintf("%s:%d: read error - %s\n", csa->fname, csa->seqn, + strerror(errno)); + return 1; + } + if (feof(csa->fp)) + csa->c = EOF; + else if (csa->c == '\n') + csa->seqn++; + else if (isspace(csa->c)) + csa->c = ' '; + else if (iscntrl(csa->c)) + { xprintf("%s:%d: invalid control character 0x%02X\n", + csa->fname, csa->seqn, csa->c); + return 1; + } + return 0; +} + +static int skip_spaces(struct csa *csa, int across) +{ while (csa->c == ' ' || (across && csa->c == '\n')) + if (get_char(csa)) return 1; + return 0; +} + +static int scan_keyword(struct csa *csa) +{ int len = 0; + if (skip_spaces(csa, 0)) + return 1; + if (csa->c == EOF) + { xprintf("%s:%d: warning: missing EOF inserted\n", csa->fname, + csa->seqn); + strcpy(csa->token, "EOF"); + return 0; + } + csa->token[0] = '\0'; + while (isalnum(csa->c) || csa->c == '_') + { if (len == 31) + { xprintf("%s:%d: keyword '%s...' too long\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + if (len == 0) + { xprintf("%s:%d: missing keyword\n", csa->fname, csa->seqn); + return 1; + } + return 0; +} + +static int check_colon(struct csa *csa) +{ if (skip_spaces(csa, 0)) + return 1; + if (csa->c != ':') + { xprintf("%s:%d: missing colon after '%s'\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + if (get_char(csa)) + return 1; + return 0; +} + +static int scan_token(struct csa *csa, int across) +{ int len = 0; + if (skip_spaces(csa, across)) + return 1; + csa->token[0] = '\0'; + while (!(csa->c == EOF || csa->c == '\n' || csa->c == ' ')) + { if (len == 255) + { csa->token[31] = '\0'; + xprintf("%s:%d: token '%s...' too long\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + return 0; +} + +static int check_newline(struct csa *csa) +{ if (skip_spaces(csa, 0)) + return 1; + if (!(csa->c == EOF || csa->c == '\n')) + { xprintf("%s:%d: extra symbols detected\n", csa->fname, + csa->seqn); + return 1; + } + if (get_char(csa)) + return 1; + return 0; +} + +static int scan_comment(struct csa *csa) +{ int len = 0; + if (skip_spaces(csa, 0)) + return 1; + csa->token[0] = '\0'; + while (!(csa->c == EOF || csa->c == '\n')) + { if (len == 255) + { xprintf("%s:%d: comment too long\n", csa->fname, csa->seqn); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + return 0; +} + +static int scan_integer(struct csa *csa, int across, int *val) +{ if (scan_token(csa, across)) + return 1; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: missing integer\n", csa->fname, csa->seqn); + return 1; + } + if (str2int(csa->token, val)) + { xprintf("%s:%d: integer '%s' invalid\n", csa->fname, csa->seqn, + csa->token); + return 1; + } + return 0; +} + +static int scan_number(struct csa *csa, int across, double *val) +{ if (scan_token(csa, across)) + return 1; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: missing number\n", csa->fname, csa->seqn); + return 1; + } + if (str2num(csa->token, val)) + { xprintf("%s:%d: number '%s' invalid\n", csa->fname, csa->seqn, + csa->token); + return 1; + } + return 0; +} + +TSP *tsp_read_data(const char *fname) +{ struct csa _dsa, *csa = &_dsa; + TSP *tsp = NULL; + csa->fname = fname; + xprintf("Reading TSP data from '%s'...\n", csa->fname); + csa->fp = fopen(csa->fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", csa->fname, + strerror(errno)); + goto fail; + } + tsp = xalloc(1, sizeof(TSP)); + tsp->name = NULL; + tsp->type = TSP_UNDEF; + tsp->comment = NULL; + tsp->dimension = 0; + tsp->edge_weight_type = TSP_UNDEF; + tsp->edge_weight_format = TSP_UNDEF; + tsp->display_data_type = TSP_UNDEF; + tsp->node_x_coord = NULL; + tsp->node_y_coord = NULL; + tsp->dply_x_coord = NULL; + tsp->dply_y_coord = NULL; + tsp->tour = NULL; + tsp->edge_weight = NULL; + csa->seqn = 1; + if (get_char(csa)) + goto fail; +loop: if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "NAME") == 0) + { if (tsp->name != NULL) + { xprintf("%s:%d: NAME entry multiply defined\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_token(csa, 0)) + goto fail; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: NAME entry incomplete\n", csa->fname, + csa->seqn); + goto fail; + } + tsp->name = xalloc(strlen(csa->token)+1, sizeof(char)); + strcpy(tsp->name, csa->token); + xprintf("NAME: %s\n", tsp->name); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "TYPE") == 0) + { if (tsp->type != TSP_UNDEF) + { xprintf("%s:%d: TYPE entry multiply defined\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "TSP") == 0) + tsp->type = TSP_TSP; + else if (strcmp(csa->token, "ATSP") == 0) + tsp->type = TSP_ATSP; + else if (strcmp(csa->token, "TOUR") == 0) + tsp->type = TSP_TOUR; + else + { xprintf("%s:%d: data type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "COMMENT") == 0) + { if (check_colon(csa)) + goto fail; + if (scan_comment(csa)) + goto fail; + xprintf("COMMENT: %s\n", csa->token); + if (tsp->comment == NULL) + { tsp->comment = xalloc(strlen(csa->token)+1, sizeof(char)); + strcpy(tsp->comment, csa->token); + } + else + { xprintf("%s:%d: warning: extra COMMENT entry ignored\n", + csa->fname, csa->seqn); + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "DIMENSION") == 0) + { if (tsp->dimension != 0) + { xprintf("%s:%d: DIMENSION entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_integer(csa, 0, &tsp->dimension)) + goto fail; + if (tsp->dimension < 1) + { xprintf("%s:%d: invalid dimension\n", csa->fname, + csa->seqn); + goto fail; + } + xprintf("DIMENSION: %d\n", tsp->dimension); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_TYPE") == 0) + { if (tsp->edge_weight_type != TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_TYPE entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "GEO") == 0) + tsp->edge_weight_type = TSP_GEO; + else if (strcmp(csa->token, "EUC_2D") == 0) + tsp->edge_weight_type = TSP_EUC_2D; + else if (strcmp(csa->token, "ATT") == 0) + tsp->edge_weight_type = TSP_ATT; + else if (strcmp(csa->token, "EXPLICIT") == 0) + tsp->edge_weight_type = TSP_EXPLICIT; + else if (strcmp(csa->token, "CEIL_2D") == 0) + tsp->edge_weight_type = TSP_CEIL_2D; + else + { xprintf("%s:%d: edge weight type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("EDGE_WEIGHT_TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_FORMAT") == 0) + { if (tsp->edge_weight_format != TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry multiply defined\n" + , csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "UPPER_ROW") == 0) + tsp->edge_weight_format = TSP_UPPER_ROW; + else if (strcmp(csa->token, "FULL_MATRIX") == 0) + tsp->edge_weight_format = TSP_FULL_MATRIX; + else if (strcmp(csa->token, "FUNCTION") == 0) + tsp->edge_weight_format = TSP_FUNCTION; + else if (strcmp(csa->token, "LOWER_DIAG_ROW") == 0) + tsp->edge_weight_format = TSP_LOWER_DIAG_ROW; + else + { xprintf("%s:%d: edge weight format '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("EDGE_WEIGHT_FORMAT: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "DISPLAY_DATA_TYPE") == 0) + { if (tsp->display_data_type != TSP_UNDEF) + { xprintf("%s:%d: DISPLAY_DATA_TYPE entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "COORD_DISPLAY") == 0) + tsp->display_data_type = TSP_COORD_DISPLAY; + else if (strcmp(csa->token, "TWOD_DISPLAY") == 0) + tsp->display_data_type = TSP_TWOD_DISPLAY; + else + { xprintf("%s:%d: display data type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("DISPLAY_DATA_TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "NODE_COORD_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->node_x_coord != NULL) + { xprintf("%s:%d: NODE_COORD_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->node_x_coord = xalloc(1+n, sizeof(double)); + tsp->node_y_coord = xalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->node_x_coord[node] = tsp->node_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 0, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + if (tsp->node_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + csa->fname, csa->seqn, node); + goto fail; + } + if (scan_number(csa, 0, &tsp->node_x_coord[node])) + goto fail; + if (scan_number(csa, 0, &tsp->node_y_coord[node])) + goto fail; + if (check_newline(csa)) + goto fail; + } + } + else if (strcmp(csa->token, "DISPLAY_DATA_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->dply_x_coord != NULL) + { xprintf("%s:%d: DISPLAY_DATA_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->dply_x_coord = xalloc(1+n, sizeof(double)); + tsp->dply_y_coord = xalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->dply_x_coord[node] = tsp->dply_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 0, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + if (tsp->dply_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + csa->fname, csa->seqn, node); + goto fail; + } + if (scan_number(csa, 0, &tsp->dply_x_coord[node])) + goto fail; + if (scan_number(csa, 0, &tsp->dply_y_coord[node])) + goto fail; + if (check_newline(csa)) + goto fail; + } + } + else if (strcmp(csa->token, "TOUR_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->tour != NULL) + { xprintf("%s:%d: TOUR_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->tour = xalloc(1+n, sizeof(int)); + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 1, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + tsp->tour[k] = node; + } + if (scan_integer(csa, 1, &node)) + goto fail; + if (node != -1) + { xprintf("%s:%d: extra node(s) detected\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_SECTION") == 0) + { int n = tsp->dimension, i, j, temp; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->edge_weight_format == TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->edge_weight != NULL) + { xprintf("%s:%d: EDGE_WEIGHT_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->edge_weight = xalloc(1+n*n, sizeof(int)); + switch (tsp->edge_weight_format) + { case TSP_FULL_MATRIX: + for (i = 1; i <= n; i++) + { for (j = 1; j <= n; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + } + } + break; + case TSP_UPPER_ROW: + for (i = 1; i <= n; i++) + { tsp->edge_weight[(i - 1) * n + i] = 0; + for (j = i + 1; j <= n; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + case TSP_LOWER_DIAG_ROW: + for (i = 1; i <= n; i++) + { for (j = 1; j <= i; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + default: + goto fail; + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EOF") == 0) + { if (check_newline(csa)) + goto fail; + goto done; + } + else + { xprintf("%s:%d: keyword '%s' not recognized\n", csa->fname, + csa->seqn, csa->token); + goto fail; + } + goto loop; +done: xprintf("%d lines were read\n", csa->seqn-1); + fclose(csa->fp); + return tsp; +fail: if (tsp != NULL) + { if (tsp->name != NULL) + xfree(tsp->name); + if (tsp->comment != NULL) + xfree(tsp->comment); + if (tsp->node_x_coord != NULL) + xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) + xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) + xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) + xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) + xfree(tsp->tour); + if (tsp->edge_weight != NULL) + xfree(tsp->edge_weight); + xfree(tsp); + } + if (csa->fp != NULL) + fclose(csa->fp); + return NULL; +} + +/*********************************************************************** +* NAME +* +* tsp_distance - compute distance between two nodes +* +* SYNOPSIS +* +* #include "tsplib.h" +* int tsp_distance(TSP *tsp, int i, int j); +* +* DESCRIPTION +* +* The routine tsp_distance computes the distance between i-th and j-th +* nodes for the TSP instance, which tsp points to. +* +* RETURNS +* +* The routine tsp_distance returns the computed distance. */ + +#define nint(x) ((int)((x) + 0.5)) + +static double rad(double x) +{ /* convert input coordinate to longitude/latitude, in radians */ + double pi = 3.141592, deg, min; + deg = (int)x; + min = x - deg; + return pi * (deg + 5.0 * min / 3.0) / 180.0; +} + +int tsp_distance(const TSP *tsp, int i, int j) +{ int n = tsp->dimension, dij; + if (!(tsp->type == TSP_TSP || tsp->type == TSP_ATSP)) + xerror("tsp_distance: invalid TSP instance\n"); + if (!(1 <= i && i <= n && 1 <= j && j <= n)) + xerror("tsp_distance: node number out of range\n"); + switch (tsp->edge_weight_type) + { case TSP_UNDEF: + xerror("tsp_distance: edge weight type not specified\n"); + case TSP_EXPLICIT: + if (tsp->edge_weight == NULL) + xerror("tsp_distance: edge weights not specified\n"); + dij = tsp->edge_weight[(i - 1) * n + j]; + break; + case TSP_EUC_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = nint(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_CEIL_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = (int)ceil(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_GEO: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double rrr = 6378.388; + double latitude_i = rad(tsp->node_x_coord[i]); + double latitude_j = rad(tsp->node_x_coord[j]); + double longitude_i = rad(tsp->node_y_coord[i]); + double longitude_j = rad(tsp->node_y_coord[j]); + double q1 = cos(longitude_i - longitude_j); + double q2 = cos(latitude_i - latitude_j); + double q3 = cos(latitude_i + latitude_j); + dij = (int)(rrr * acos(0.5 * ((1.0 + q1) * q2 - + (1.0 - q1) *q3)) + 1.0); + } + break; + case TSP_ATT: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { int tij; + double xd, yd, rij; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + rij = sqrt((xd * xd + yd * yd) / 10.0); + tij = nint(rij); + if (tij < rij) dij = tij + 1; else dij = tij; + } + break; + default: + xassert(tsp->edge_weight_type != tsp->edge_weight_type); + } + return dij; +} + +/*********************************************************************** +* NAME +* +* tsp_free_data - free TSP instance data +* +* SYNOPSIS +* +* #include "tsplib.h" +* void tsp_free_data(TSP *tsp); +* +* DESCRIPTION +* +* The routine tsp_free_data frees all the memory allocated to the TSP +* instance data block, which the parameter tsp points to. */ + +void tsp_free_data(TSP *tsp) +{ if (tsp->name != NULL) + xfree(tsp->name); + if (tsp->comment != NULL) + xfree(tsp->comment); + if (tsp->node_x_coord != NULL) + xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) + xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) + xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) + xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) + xfree(tsp->tour); + if (tsp->edge_weight != NULL) + xfree(tsp->edge_weight); + xfree(tsp); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.h b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.h new file mode 100644 index 000000000..19936ad76 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/tsplib.h @@ -0,0 +1,80 @@ +/* tsplib.h */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef TSPLIB_H +#define TSPLIB_H + +typedef struct TSP TSP; + +struct TSP +{ /* TSP (or related problem) instance in the format described in + * [G.Reinelt, TSPLIB 95] */ + /*--------------------------------------------------------------*/ + /* specification part */ + char *name; + /* identifies the data file */ + int type; + /* specifies the type of data: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_TSP 1 /* symmetric TSP */ +#define TSP_ATSP 2 /* asymmetric TSP */ +#define TSP_TOUR 3 /* collection of tours */ + char *comment; + /* additional comments (usually the name of the contributor or + * creator of the problem instance is given here) */ + int dimension; + /* for a TSP or ATSP, the dimension is the number of its nodes + * for a TOUR it is the dimension of the corresponding problem */ + int edge_weight_type; + /* specifies how the edge weights (or distances) are given: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_EXPLICIT 1 /* listed explicitly */ +#define TSP_EUC_2D 2 /* Eucl. distances in 2-D */ +#define TSP_CEIL_2D 3 /* Eucl. distances in 2-D rounded up */ +#define TSP_GEO 4 /* geographical distances */ +#define TSP_ATT 5 /* special distance function */ + int edge_weight_format; + /* describes the format of the edge weights if they are given + * explicitly: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_FUNCTION 1 /* given by a function */ +#define TSP_FULL_MATRIX 2 /* given by a full matrix */ +#define TSP_UPPER_ROW 3 /* upper triangular matrix (row-wise + * without diagonal entries) */ +#define TSP_LOWER_DIAG_ROW 4 /* lower triangular matrix (row-wise + * including diagonal entries) */ + int display_data_type; + /* specifies how a graphical display of the nodes can be + * obtained: */ +#define TSP_UNDEF 0 /* undefined */ +#define TSP_COORD_DISPLAY 1 /* display is generated from the node + * coordinates */ +#define TSP_TWOD_DISPLAY 2 /* explicit coordinates in 2-D are + * given */ + /*--------------------------------------------------------------*/ + /* data part */ + /* NODE_COORD_SECTION: */ + double *node_x_coord; /* double node_x_coord[1+dimension]; */ + double *node_y_coord; /* double node_y_coord[1+dimension]; */ + /* DISPLAY_DATA_SECTION: */ + double *dply_x_coord; /* double dply_x_coord[1+dimension]; */ + double *dply_y_coord; /* double dply_y_coord[1+dimension]; */ + /* TOUR_SECTION: */ + int *tour; /* int tour[1+dimension]; */ + /* EDGE_WEIGHT_SECTION: */ + int *edge_weight; /* int edge_weight[1+dimension*dimension]; */ +}; + +TSP *tsp_read_data(const char *fname); +/* read TSP instance data */ + +int tsp_distance(const TSP *tsp, int i, int j); +/* compute distance between two nodes */ + +void tsp_free_data(TSP *tsp); +/* free TSP instance data */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses16.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses16.tsp new file mode 100644 index 000000000..4ce24a60e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses16.tsp @@ -0,0 +1,24 @@ +NAME: ulysses16.tsp +TYPE: TSP +COMMENT: Odyssey of Ulysses (Groetschel/Padberg) +DIMENSION: 16 +EDGE_WEIGHT_TYPE: GEO +DISPLAY_DATA_TYPE: COORD_DISPLAY +NODE_COORD_SECTION + 1 38.24 20.42 + 2 39.57 26.15 + 3 40.56 25.32 + 4 36.26 23.12 + 5 33.48 10.54 + 6 37.56 12.19 + 7 38.42 13.11 + 8 37.52 20.44 + 9 41.23 9.10 + 10 41.17 13.05 + 11 36.08 -5.21 + 12 38.47 15.13 + 13 38.15 15.35 + 14 37.51 15.17 + 15 35.49 14.32 + 16 39.36 19.56 + EOF diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses22.tsp b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses22.tsp new file mode 100644 index 000000000..9e95fb826 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/tsp/ulysses22.tsp @@ -0,0 +1,30 @@ +NAME: ulysses22.tsp +TYPE: TSP +COMMENT: Odyssey of Ulysses (Groetschel/Padberg) +DIMENSION: 22 +EDGE_WEIGHT_TYPE: GEO +DISPLAY_DATA_TYPE: COORD_DISPLAY +NODE_COORD_SECTION + 1 38.24 20.42 + 2 39.57 26.15 + 3 40.56 25.32 + 4 36.26 23.12 + 5 33.48 10.54 + 6 37.56 12.19 + 7 38.42 13.11 + 8 37.52 20.44 + 9 41.23 9.10 + 10 41.17 13.05 + 11 36.08 -5.21 + 12 38.47 15.13 + 13 38.15 15.35 + 14 37.51 15.17 + 15 35.49 14.32 + 16 39.36 19.56 + 17 38.09 24.36 + 18 36.09 23.00 + 19 40.44 13.57 + 20 40.33 14.15 + 21 40.37 14.23 + 22 37.57 22.56 +EOF diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.lp b/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.lp new file mode 100644 index 000000000..a3437d83f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.lp @@ -0,0 +1,596 @@ +\* Any Wolfram elementary CA in 6D eucl. Neumann CA grid emulator generator *\ + +\* Written and converted to *LP format by NASZVADI, Peter, 2016,2017 *\ +\* *\ + +\* Standalone version; GMPL version is in wolfra6d.mod *\ + +\* This model looks up for a subset of vertices in 6D euclyd. grid, *\ +\* which has the following properties: *\ +\* 1. each vertex' coordinate pairs' difference is at most 1 *\ +\* 2. contains the vertices in the main diagonal of the 6d space *\ +\* 3. connecting with directed graph edges from all selected vertices *\ +\* to all selected ones with greater coordinate sums with *\ +\* Hamming-distance 1, the following in-out edge numbers are *\ +\* allowed: (3,6), (1,2), (2,3), (1,2), (4,1), (3,1); according to *\ +\* the mod 6 sum of the coordinate values *\ +\* 4. Only vertices of the unit cube's with {0,1} coordinates are *\ +\* calculated, but the other cells could be obtained via shifting. *\ +\* Assume that the grid is a 6dim. cellular automaton grid with Neumann- *\ +\* -neighbourhood, now construct an outer-totalistic rule that emulates *\ +\* W110 cellular automaton on the selected vertices: *\ +\* Suppose that the 1D W110 cellspace cells are denoted with signed *\ +\* integers. Every 1D cell is assigned to (at most "6 over 2") selected *\ +\* vertices where each coordinate sums are the same with the integer *\ +\* assigned to the origin cell in the domain, they must have the same *\ +\* value. Rule-110 means that cell's value is being changed only when its *\ +\* neighbours are: (1,1,1), (1,0,1), (0,0,1), other cells remain unchanged. *\ +\* Let's denote the default cellstate with "2" in the 6D automaton, and *\ +\* the remaining 2 states with "0" and "1" respectively, which correspond *\ +\* with the states in W110. The selected vertices must be 0 or 1 of course, *\ +\* and the others are "2". *\ +\* Now, the transition rule for emulating W110 is the following: *\ +\* (x),{1,1,1,1,1,1,1,1,1,2,2,2}->(1-x), x!=2, *\ +\* (x),{1,1,1,2,2,2,2,2,2,2,2,2}->(1-x), x!=2, *\ +\* (x),{1,1,1,1,2,2,2,2,2,2,2,2}->(1-x), x!=2, *\ +\* (x),{1,1,1,1,1,2,2,2,2,2,2,2}->(1-x), x!=2, *\ +\* (1),{0,0,0,1,1,1,1,1,1,2,2,2}->(0), *\ +\* (1),{0,1,1,2,2,2,2,2,2,2,2,2}->(0), *\ +\* (1),{0,0,1,1,1,2,2,2,2,2,2,2}->(0), *\ +\* (1),{0,0,0,0,1,2,2,2,2,2,2,2}->(0), *\ +\* (1),{0,0,0,1,2,2,2,2,2,2,2,2}->(0); *\ +\* notation: (old state),{old neighbours - all permutations}->(new state) *\ +\* Other states won't change between two generations. And is known that W110 *\ +\* is Turing-complete. So there is a universal CA rule in 6+D eucl. gridS *\ +\* Result is in x****** binary variables (total 44 among the 64) *\ + +Minimize + obj: x000000 +x000001 +x000010 +x000011 +x000100 +x000101 +x000110 +x000111 + +x001000 +x001001 +x001010 +x001011 +x001100 +x001101 +x001110 +x001111 + +x010000 +x010001 +x010010 +x010011 +x010100 +x010101 +x010110 +x010111 + +x011000 +x011001 +x011010 +x011011 +x011100 +x011101 +x011110 +x011111 + +x100000 +x100001 +x100010 +x100011 +x100100 +x100101 +x100110 +x100111 + +x101000 +x101001 +x101010 +x101011 +x101100 +x101101 +x101110 +x101111 + +x110000 +x110001 +x110010 +x110011 +x110100 +x110101 +x110110 +x110111 + +x111000 +x111001 +x111010 +x111011 +x111100 +x111101 +x111110 +x111111 +Subject To + x000000 = 1 + x111111 = 1 + x111110 -x111101 >= 0 + x111101 -x111011 >= 0 + x111011 -x110111 >= 0 + x110111 -x101111 >= 0 + x101111 -x011111 >= 0 + dn000000 -dn111111 = 0 + up000000 -up111111 = 0 + cup000000: + x000001 +x000010 +x000100 +x001000 +x010000 +x100000 -up000000 = 0 + cup000001: + x000011 +x000101 +x001001 +x010001 +x100001 -up000001 = 0 + cup000010: + x000011 +x000110 +x001010 +x010010 +x100010 -up000010 = 0 + cup000011: + x000111 +x001011 +x010011 +x100011 -up000011 = 0 + cup000100: + x000101 +x000110 +x001100 +x010100 +x100100 -up000100 = 0 + cup000101: + x000111 +x001101 +x010101 +x100101 -up000101 = 0 + cup000110: + x000111 +x001110 +x010110 +x100110 -up000110 = 0 + cup000111: + x001111 +x010111 +x100111 -up000111 = 0 + cup001000: + x001001 +x001010 +x001100 +x011000 +x101000 -up001000 = 0 + cup001001: + x001011 +x001101 +x011001 +x101001 -up001001 = 0 + cup001010: + x001011 +x001110 +x011010 +x101010 -up001010 = 0 + cup001011: + x001111 +x011011 +x101011 -up001011 = 0 + cup001100: + x001101 +x001110 +x011100 +x101100 -up001100 = 0 + cup001101: + x001111 +x011101 +x101101 -up001101 = 0 + cup001110: + x001111 +x011110 +x101110 -up001110 = 0 + cup001111: + x011111 +x101111 -up001111 = 0 + cup010000: + x010001 +x010010 +x010100 +x011000 +x110000 -up010000 = 0 + cup010001: + x010011 +x010101 +x011001 +x110001 -up010001 = 0 + cup010010: + x010011 +x010110 +x011010 +x110010 -up010010 = 0 + cup010011: + x010111 +x011011 +x110011 -up010011 = 0 + cup010100: + x010101 +x010110 +x011100 +x110100 -up010100 = 0 + cup010101: + x010111 +x011101 +x110101 -up010101 = 0 + cup010110: + x010111 +x011110 +x110110 -up010110 = 0 + cup010111: + x011111 +x110111 -up010111 = 0 + cup011000: + x011001 +x011010 +x011100 +x111000 -up011000 = 0 + cup011001: + x011011 +x011101 +x111001 -up011001 = 0 + cup011010: + x011011 +x011110 +x111010 -up011010 = 0 + cup011011: + x011111 +x111011 -up011011 = 0 + cup011100: + x011101 +x011110 +x111100 -up011100 = 0 + cup011101: + x011111 +x111101 -up011101 = 0 + cup011110: + x011111 +x111110 -up011110 = 0 + cup011111: + x111111 -up011111 = 0 + cup100000: + x100001 +x100010 +x100100 +x101000 +x110000 -up100000 = 0 + cup100001: + x100011 +x100101 +x101001 +x110001 -up100001 = 0 + cup100010: + x100011 +x100110 +x101010 +x110010 -up100010 = 0 + cup100011: + x100111 +x101011 +x110011 -up100011 = 0 + cup100100: + x100101 +x100110 +x101100 +x110100 -up100100 = 0 + cup100101: + x100111 +x101101 +x110101 -up100101 = 0 + cup100110: + x100111 +x101110 +x110110 -up100110 = 0 + cup100111: + x101111 +x110111 -up100111 = 0 + cup101000: + x101001 +x101010 +x101100 +x111000 -up101000 = 0 + cup101001: + x101011 +x101101 +x111001 -up101001 = 0 + cup101010: + x101011 +x101110 +x111010 -up101010 = 0 + cup101011: + x101111 +x111011 -up101011 = 0 + cup101100: + x101101 +x101110 +x111100 -up101100 = 0 + cup101101: + x101111 +x111101 -up101101 = 0 + cup101110: + x101111 +x111110 -up101110 = 0 + cup101111: + x111111 -up101111 = 0 + cup110000: + x110001 +x110010 +x110100 +x111000 -up110000 = 0 + cup110001: + x110011 +x110101 +x111001 -up110001 = 0 + cup110010: + x110011 +x110110 +x111010 -up110010 = 0 + cup110011: + x110111 +x111011 -up110011 = 0 + cup110100: + x110101 +x110110 +x111100 -up110100 = 0 + cup110101: + x110111 +x111101 -up110101 = 0 + cup110110: + x110111 +x111110 -up110110 = 0 + cup110111: + x111111 -up110111 = 0 + cup111000: + x111001 +x111010 +x111100 -up111000 = 0 + cup111001: + x111011 +x111101 -up111001 = 0 + cup111010: + x111011 +x111110 -up111010 = 0 + cup111011: + x111111 -up111011 = 0 + cup111100: + x111101 +x111110 -up111100 = 0 + cup111101: + x111111 -up111101 = 0 + cup111110: + x111111 -up111110 = 0 + cdn000001: + x000000 -dn000001 = 0 + cdn000010: + x000000 -dn000010 = 0 + cdn000011: + x000001 +x000010 -dn000011 = 0 + cdn000100: + x000000 -dn000100 = 0 + cdn000101: + x000001 +x000100 -dn000101 = 0 + cdn000110: + x000010 +x000100 -dn000110 = 0 + cdn000111: + x000011 +x000101 +x000110 -dn000111 = 0 + cdn001000: + x000000 -dn001000 = 0 + cdn001001: + x000001 +x001000 -dn001001 = 0 + cdn001010: + x000010 +x001000 -dn001010 = 0 + cdn001011: + x000011 +x001001 +x001010 -dn001011 = 0 + cdn001100: + x000100 +x001000 -dn001100 = 0 + cdn001101: + x000101 +x001001 +x001100 -dn001101 = 0 + cdn001110: + x000110 +x001010 +x001100 -dn001110 = 0 + cdn001111: + x000111 +x001011 +x001101 +x001110 -dn001111 = 0 + cdn010000: + x000000 -dn010000 = 0 + cdn010001: + x000001 +x010000 -dn010001 = 0 + cdn010010: + x000010 +x010000 -dn010010 = 0 + cdn010011: + x000011 +x010001 +x010010 -dn010011 = 0 + cdn010100: + x000100 +x010000 -dn010100 = 0 + cdn010101: + x000101 +x010001 +x010100 -dn010101 = 0 + cdn010110: + x000110 +x010010 +x010100 -dn010110 = 0 + cdn010111: + x000111 +x010011 +x010101 +x010110 -dn010111 = 0 + cdn011000: + x001000 +x010000 -dn011000 = 0 + cdn011001: + x001001 +x010001 +x011000 -dn011001 = 0 + cdn011010: + x001010 +x010010 +x011000 -dn011010 = 0 + cdn011011: + x001011 +x010011 +x011001 +x011010 -dn011011 = 0 + cdn011100: + x001100 +x010100 +x011000 -dn011100 = 0 + cdn011101: + x001101 +x010101 +x011001 +x011100 -dn011101 = 0 + cdn011110: + x001110 +x010110 +x011010 +x011100 -dn011110 = 0 + cdn011111: + x001111 +x010111 +x011011 +x011101 +x011110 -dn011111 = 0 + cdn100000: + x000000 -dn100000 = 0 + cdn100001: + x000001 +x100000 -dn100001 = 0 + cdn100010: + x000010 +x100000 -dn100010 = 0 + cdn100011: + x000011 +x100001 +x100010 -dn100011 = 0 + cdn100100: + x000100 +x100000 -dn100100 = 0 + cdn100101: + x000101 +x100001 +x100100 -dn100101 = 0 + cdn100110: + x000110 +x100010 +x100100 -dn100110 = 0 + cdn100111: + x000111 +x100011 +x100101 +x100110 -dn100111 = 0 + cdn101000: + x001000 +x100000 -dn101000 = 0 + cdn101001: + x001001 +x100001 +x101000 -dn101001 = 0 + cdn101010: + x001010 +x100010 +x101000 -dn101010 = 0 + cdn101011: + x001011 +x100011 +x101001 +x101010 -dn101011 = 0 + cdn101100: + x001100 +x100100 +x101000 -dn101100 = 0 + cdn101101: + x001101 +x100101 +x101001 +x101100 -dn101101 = 0 + cdn101110: + x001110 +x100110 +x101010 +x101100 -dn101110 = 0 + cdn101111: + x001111 +x100111 +x101011 +x101101 +x101110 -dn101111 = 0 + cdn110000: + x010000 +x100000 -dn110000 = 0 + cdn110001: + x010001 +x100001 +x110000 -dn110001 = 0 + cdn110010: + x010010 +x100010 +x110000 -dn110010 = 0 + cdn110011: + x010011 +x100011 +x110001 +x110010 -dn110011 = 0 + cdn110100: + x010100 +x100100 +x110000 -dn110100 = 0 + cdn110101: + x010101 +x100101 +x110001 +x110100 -dn110101 = 0 + cdn110110: + x010110 +x100110 +x110010 +x110100 -dn110110 = 0 + cdn110111: + x010111 +x100111 +x110011 +x110101 +x110110 -dn110111 = 0 + cdn111000: + x011000 +x101000 +x110000 -dn111000 = 0 + cdn111001: + x011001 +x101001 +x110001 +x111000 -dn111001 = 0 + cdn111010: + x011010 +x101010 +x110010 +x111000 -dn111010 = 0 + cdn111011: + x011011 +x101011 +x110011 +x111001 +x111010 -dn111011 = 0 + cdn111100: + x011100 +x101100 +x110100 +x111000 -dn111100 = 0 + cdn111101: + x011101 +x101101 +x110101 +x111001 +x111100 -dn111101 = 0 + cdn111110: + x011110 +x101110 +x110110 +x111010 +x111100 -dn111110 = 0 + cdn111111: + x011111 +x101111 +x110111 +x111011 +x111101 +x111110 -dn111111 = 0 + up000000 -6 x000000 >= 0 + up000000 +64 x000000 <= 70 + up000001 -2 x000001 >= 0 + up000001 +64 x000001 <= 66 + up000010 -2 x000010 >= 0 + up000010 +64 x000010 <= 66 + up000011 -3 x000011 >= 0 + up000011 +64 x000011 <= 67 + up000100 -2 x000100 >= 0 + up000100 +64 x000100 <= 66 + up000101 -3 x000101 >= 0 + up000101 +64 x000101 <= 67 + up000110 -3 x000110 >= 0 + up000110 +64 x000110 <= 67 + up000111 -2 x000111 >= 0 + up000111 +64 x000111 <= 66 + up001000 -2 x001000 >= 0 + up001000 +64 x001000 <= 66 + up001001 -3 x001001 >= 0 + up001001 +64 x001001 <= 67 + up001010 -3 x001010 >= 0 + up001010 +64 x001010 <= 67 + up001011 -2 x001011 >= 0 + up001011 +64 x001011 <= 66 + up001100 -3 x001100 >= 0 + up001100 +64 x001100 <= 67 + up001101 -2 x001101 >= 0 + up001101 +64 x001101 <= 66 + up001110 -2 x001110 >= 0 + up001110 +64 x001110 <= 66 + up001111 -1 x001111 >= 0 + up001111 +64 x001111 <= 65 + up010000 -2 x010000 >= 0 + up010000 +64 x010000 <= 66 + up010001 -3 x010001 >= 0 + up010001 +64 x010001 <= 67 + up010010 -3 x010010 >= 0 + up010010 +64 x010010 <= 67 + up010011 -2 x010011 >= 0 + up010011 +64 x010011 <= 66 + up010100 -3 x010100 >= 0 + up010100 +64 x010100 <= 67 + up010101 -2 x010101 >= 0 + up010101 +64 x010101 <= 66 + up010110 -2 x010110 >= 0 + up010110 +64 x010110 <= 66 + up010111 -1 x010111 >= 0 + up010111 +64 x010111 <= 65 + up011000 -3 x011000 >= 0 + up011000 +64 x011000 <= 67 + up011001 -2 x011001 >= 0 + up011001 +64 x011001 <= 66 + up011010 -2 x011010 >= 0 + up011010 +64 x011010 <= 66 + up011011 -1 x011011 >= 0 + up011011 +64 x011011 <= 65 + up011100 -2 x011100 >= 0 + up011100 +64 x011100 <= 66 + up011101 -1 x011101 >= 0 + up011101 +64 x011101 <= 65 + up011110 -1 x011110 >= 0 + up011110 +64 x011110 <= 65 + up011111 -1 x011111 >= 0 + up011111 +64 x011111 <= 65 + up100000 -2 x100000 >= 0 + up100000 +64 x100000 <= 66 + up100001 -3 x100001 >= 0 + up100001 +64 x100001 <= 67 + up100010 -3 x100010 >= 0 + up100010 +64 x100010 <= 67 + up100011 -2 x100011 >= 0 + up100011 +64 x100011 <= 66 + up100100 -3 x100100 >= 0 + up100100 +64 x100100 <= 67 + up100101 -2 x100101 >= 0 + up100101 +64 x100101 <= 66 + up100110 -2 x100110 >= 0 + up100110 +64 x100110 <= 66 + up100111 -1 x100111 >= 0 + up100111 +64 x100111 <= 65 + up101000 -3 x101000 >= 0 + up101000 +64 x101000 <= 67 + up101001 -2 x101001 >= 0 + up101001 +64 x101001 <= 66 + up101010 -2 x101010 >= 0 + up101010 +64 x101010 <= 66 + up101011 -1 x101011 >= 0 + up101011 +64 x101011 <= 65 + up101100 -2 x101100 >= 0 + up101100 +64 x101100 <= 66 + up101101 -1 x101101 >= 0 + up101101 +64 x101101 <= 65 + up101110 -1 x101110 >= 0 + up101110 +64 x101110 <= 65 + up101111 -1 x101111 >= 0 + up101111 +64 x101111 <= 65 + up110000 -3 x110000 >= 0 + up110000 +64 x110000 <= 67 + up110001 -2 x110001 >= 0 + up110001 +64 x110001 <= 66 + up110010 -2 x110010 >= 0 + up110010 +64 x110010 <= 66 + up110011 -1 x110011 >= 0 + up110011 +64 x110011 <= 65 + up110100 -2 x110100 >= 0 + up110100 +64 x110100 <= 66 + up110101 -1 x110101 >= 0 + up110101 +64 x110101 <= 65 + up110110 -1 x110110 >= 0 + up110110 +64 x110110 <= 65 + up110111 -1 x110111 >= 0 + up110111 +64 x110111 <= 65 + up111000 -2 x111000 >= 0 + up111000 +64 x111000 <= 66 + up111001 -1 x111001 >= 0 + up111001 +64 x111001 <= 65 + up111010 -1 x111010 >= 0 + up111010 +64 x111010 <= 65 + up111011 -1 x111011 >= 0 + up111011 +64 x111011 <= 65 + up111100 -1 x111100 >= 0 + up111100 +64 x111100 <= 65 + up111101 -1 x111101 >= 0 + up111101 +64 x111101 <= 65 + up111110 -1 x111110 >= 0 + up111110 +64 x111110 <= 65 + dn000001 -1 x000001 >= 0 + dn000001 +64 x000001 <= 65 + dn000010 -1 x000010 >= 0 + dn000010 +64 x000010 <= 65 + dn000011 -2 x000011 >= 0 + dn000011 +64 x000011 <= 66 + dn000100 -1 x000100 >= 0 + dn000100 +64 x000100 <= 65 + dn000101 -2 x000101 >= 0 + dn000101 +64 x000101 <= 66 + dn000110 -2 x000110 >= 0 + dn000110 +64 x000110 <= 66 + dn000111 -1 x000111 >= 0 + dn000111 +64 x000111 <= 65 + dn001000 -1 x001000 >= 0 + dn001000 +64 x001000 <= 65 + dn001001 -2 x001001 >= 0 + dn001001 +64 x001001 <= 66 + dn001010 -2 x001010 >= 0 + dn001010 +64 x001010 <= 66 + dn001011 -1 x001011 >= 0 + dn001011 +64 x001011 <= 65 + dn001100 -2 x001100 >= 0 + dn001100 +64 x001100 <= 66 + dn001101 -1 x001101 >= 0 + dn001101 +64 x001101 <= 65 + dn001110 -1 x001110 >= 0 + dn001110 +64 x001110 <= 65 + dn001111 -4 x001111 >= 0 + dn001111 +64 x001111 <= 68 + dn010000 -1 x010000 >= 0 + dn010000 +64 x010000 <= 65 + dn010001 -2 x010001 >= 0 + dn010001 +64 x010001 <= 66 + dn010010 -2 x010010 >= 0 + dn010010 +64 x010010 <= 66 + dn010011 -1 x010011 >= 0 + dn010011 +64 x010011 <= 65 + dn010100 -2 x010100 >= 0 + dn010100 +64 x010100 <= 66 + dn010101 -1 x010101 >= 0 + dn010101 +64 x010101 <= 65 + dn010110 -1 x010110 >= 0 + dn010110 +64 x010110 <= 65 + dn010111 -4 x010111 >= 0 + dn010111 +64 x010111 <= 68 + dn011000 -2 x011000 >= 0 + dn011000 +64 x011000 <= 66 + dn011001 -1 x011001 >= 0 + dn011001 +64 x011001 <= 65 + dn011010 -1 x011010 >= 0 + dn011010 +64 x011010 <= 65 + dn011011 -4 x011011 >= 0 + dn011011 +64 x011011 <= 68 + dn011100 -1 x011100 >= 0 + dn011100 +64 x011100 <= 65 + dn011101 -4 x011101 >= 0 + dn011101 +64 x011101 <= 68 + dn011110 -4 x011110 >= 0 + dn011110 +64 x011110 <= 68 + dn011111 -3 x011111 >= 0 + dn011111 +64 x011111 <= 67 + dn100000 -1 x100000 >= 0 + dn100000 +64 x100000 <= 65 + dn100001 -2 x100001 >= 0 + dn100001 +64 x100001 <= 66 + dn100010 -2 x100010 >= 0 + dn100010 +64 x100010 <= 66 + dn100011 -1 x100011 >= 0 + dn100011 +64 x100011 <= 65 + dn100100 -2 x100100 >= 0 + dn100100 +64 x100100 <= 66 + dn100101 -1 x100101 >= 0 + dn100101 +64 x100101 <= 65 + dn100110 -1 x100110 >= 0 + dn100110 +64 x100110 <= 65 + dn100111 -4 x100111 >= 0 + dn100111 +64 x100111 <= 68 + dn101000 -2 x101000 >= 0 + dn101000 +64 x101000 <= 66 + dn101001 -1 x101001 >= 0 + dn101001 +64 x101001 <= 65 + dn101010 -1 x101010 >= 0 + dn101010 +64 x101010 <= 65 + dn101011 -4 x101011 >= 0 + dn101011 +64 x101011 <= 68 + dn101100 -1 x101100 >= 0 + dn101100 +64 x101100 <= 65 + dn101101 -4 x101101 >= 0 + dn101101 +64 x101101 <= 68 + dn101110 -4 x101110 >= 0 + dn101110 +64 x101110 <= 68 + dn101111 -3 x101111 >= 0 + dn101111 +64 x101111 <= 67 + dn110000 -2 x110000 >= 0 + dn110000 +64 x110000 <= 66 + dn110001 -1 x110001 >= 0 + dn110001 +64 x110001 <= 65 + dn110010 -1 x110010 >= 0 + dn110010 +64 x110010 <= 65 + dn110011 -4 x110011 >= 0 + dn110011 +64 x110011 <= 68 + dn110100 -1 x110100 >= 0 + dn110100 +64 x110100 <= 65 + dn110101 -4 x110101 >= 0 + dn110101 +64 x110101 <= 68 + dn110110 -4 x110110 >= 0 + dn110110 +64 x110110 <= 68 + dn110111 -3 x110111 >= 0 + dn110111 +64 x110111 <= 67 + dn111000 -1 x111000 >= 0 + dn111000 +64 x111000 <= 65 + dn111001 -4 x111001 >= 0 + dn111001 +64 x111001 <= 68 + dn111010 -4 x111010 >= 0 + dn111010 +64 x111010 <= 68 + dn111011 -3 x111011 >= 0 + dn111011 +64 x111011 <= 67 + dn111100 -4 x111100 >= 0 + dn111100 +64 x111100 <= 68 + dn111101 -3 x111101 >= 0 + dn111101 +64 x111101 <= 67 + dn111110 -3 x111110 >= 0 + dn111110 +64 x111110 <= 67 + dn111111 -3 x111111 >= 0 + dn111111 +64 x111111 <= 67 +binary + x000000 x000001 x000010 x000011 x000100 x000101 x000110 x000111 + x001000 x001001 x001010 x001011 x001100 x001101 x001110 x001111 + x010000 x010001 x010010 x010011 x010100 x010101 x010110 x010111 + x011000 x011001 x011010 x011011 x011100 x011101 x011110 x011111 + x100000 x100001 x100010 x100011 x100100 x100101 x100110 x100111 + x101000 x101001 x101010 x101011 x101100 x101101 x101110 x101111 + x110000 x110001 x110010 x110011 x110100 x110101 x110110 x110111 + x111000 x111001 x111010 x111011 x111100 x111101 x111110 x111111 +integer + dn000000 up000000 dn000001 up000001 dn000010 up000010 dn000011 up000011 + dn000100 up000100 dn000101 up000101 dn000110 up000110 dn000111 up000111 + dn001000 up001000 dn001001 up001001 dn001010 up001010 dn001011 up001011 + dn001100 up001100 dn001101 up001101 dn001110 up001110 dn001111 up001111 + dn010000 up010000 dn010001 up010001 dn010010 up010010 dn010011 up010011 + dn010100 up010100 dn010101 up010101 dn010110 up010110 dn010111 up010111 + dn011000 up011000 dn011001 up011001 dn011010 up011010 dn011011 up011011 + dn011100 up011100 dn011101 up011101 dn011110 up011110 dn011111 up011111 + dn100000 up100000 dn100001 up100001 dn100010 up100010 dn100011 up100011 + dn100100 up100100 dn100101 up100101 dn100110 up100110 dn100111 up100111 + dn101000 up101000 dn101001 up101001 dn101010 up101010 dn101011 up101011 + dn101100 up101100 dn101101 up101101 dn101110 up101110 dn101111 up101111 + dn110000 up110000 dn110001 up110001 dn110010 up110010 dn110011 up110011 + dn110100 up110100 dn110101 up110101 dn110110 up110110 dn110111 up110111 + dn111000 up111000 dn111001 up111001 dn111010 up111010 dn111011 up111011 + dn111100 up111100 dn111101 up111101 dn111110 up111110 dn111111 up111111 +End diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.mod new file mode 100644 index 000000000..c478487b5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/wolfra6d.mod @@ -0,0 +1,94 @@ +/* Any Wolfram elementary CA in 6D eucl. Neumann CA grid emulator generator */ + +/* Implemented, inspected, written and converted to GNU MathProg + by NASZVADI, Peter, 2016-2017 */ + +/* see background info and more details in wolfra6d.lp */ + +/* each axis has this two endpoints */ +set V := 0..1; + +/* this model processes a hypercube in 6d, so 6+1 parallel planes intersect */ +set H := 0..6; + +/* denoting all vertices in the 6d unit hypercube */ +set Cells := V cross V cross V cross V cross V cross V; + + +/* input parameters, bup/bdn = number of upper/lower neighbour 6d cells of a (cyclic) segment */ +param bup{i in H}, default 1; +param bdn{i in H}, default 2; + +/* boolean meaning if a vertex is chosen */ +var x{Cells}, binary; + +/* temporary calculations to enforce bup/bdn */ +var up{Cells}, >=0; +var dn{Cells}, >=0; + +/* the total weight of selected cells near the main diagonal */ +var obj; + +/* up/dn vars denote the number of selected upper/lower neighbours */ +s.t. cup{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6<6}: + sum{(w1,w2,w3,w4,w5,w6) in Cells: max(v1-w1,v2-w2,v3-w3,v4-w4,v5-w5,v6-w6)<=0} + if (w1+w2+w3+w4+w5+w6) = (1+v1+v2+v3+v4+v5+v6) then x[w1,w2,w3,w4,w5,w6] else 0 = + up[v1,v2,v3,v4,v5,v6]; + +s.t. cdn{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6>0}: + sum{(w1,w2,w3,w4,w5,w6) in Cells: min(v1-w1,v2-w2,v3-w3,v4-w4,v5-w5,v6-w6)>=0} + if (w1+w2+w3+w4+w5+w6) = (-1+v1+v2+v3+v4+v5+v6) then x[w1,w2,w3,w4,w5,w6] else 0 = + dn[v1,v2,v3,v4,v5,v6]; + +/* 4 helper constraints, hences the leading "c" */ +s.t. cbup1{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6<6}: + up[v1,v2,v3,v4,v5,v6] >= bup[v1+v2+v3+v4+v5+v6] * x[v1,v2,v3,v4,v5,v6]; + +s.t. cbup2{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6<6}: + up[v1,v2,v3,v4,v5,v6] + (2**6) * x[v1,v2,v3,v4,v5,v6] <= (2**6) + bup[v1+v2+v3+v4+v5+v6]; + +s.t. cbdn1{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6>0}: + dn[v1,v2,v3,v4,v5,v6] >= bdn[v1+v2+v3+v4+v5+v6] * x[v1,v2,v3,v4,v5,v6]; + +s.t. cbdn2{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6>0}: + dn[v1,v2,v3,v4,v5,v6] + (2**6) * x[v1,v2,v3,v4,v5,v6] <= (2**6) + bdn[v1+v2+v3+v4+v5+v6]; + +/* these two promoted points should be selected */ +s.t. initdiag: x[0,0,0,0,0,0] + x[1,1,1,1,1,1] = 2; + +/* obvious */ +s.t. sumx: sum{(v1,v2,v3,v4,v5,v6) in Cells} x[v1,v2,v3,v4,v5,v6] = obj; + +minimize cobj: obj; + +solve; + +/* pretty-printing hopefully nontrivial solution */ +printf "\nChosen vertex subset:\n"; +for{i in H}: { + printf "Weight=%s\n", i; + printf{(v1,v2,v3,v4,v5,v6) in Cells: v1+v2+v3+v4+v5+v6 = i+(8-8*x[v1,v2,v3,v4,v5,v6])} + " %s%s%s%s%s%s\n",v1,v2,v3,v4,v5,v6; +} +printf "\nTotal number of selected cells in the hypercube: %g\n\n", obj; + +data; + +/* these parameters were chosen in the first run that yielded a solution */ +param bup := 0 6 + 1 2 + 2 3 + 3 2 + 4 1 + 5 1 + 6 6; + +param bdn := 0 3 + 1 1 + 2 2 + 3 1 + 4 4 + 5 3 + 6 3; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/xyacfs.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/xyacfs.mod new file mode 100644 index 000000000..5a0b22e0e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/xyacfs.mod @@ -0,0 +1,56 @@ +/*Extended Yet Another Curve Fitting Solution (The poor man's RMA) + + An extension of yacfs.mod adding a Weight parameter: + When set to 1 the model produces best fit by least squares with all error in y and none in x (YonX); + When set to zero the model produces best fit by least squares with all error in x and none in y (XonY); + When set to 0.5 the model assumes equal error in x and y producing results similar to fitting by Reduced Major Axis Analysis. + + Nigel_Galloway@operamail.com + November 5th., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; +param Weight := 0.5; + +var a; +var b; +var p; +var q; + +XonY1 :sum{z in Sample} q*Sy[z]*Sy[z] + sum{z in Sample} p*Sy[z] = sum{z in Sample} Sy[z]*Sx[z]; +XonY2 :sum{z in Sample} q*Sy[z] + sum{z in Sample} p = sum{z in Sample} Sx[z]; +YonX1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +YonX2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; + +solve; + +param W := Weight*a + (1-Weight)*(1/q); +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b*Weight - (1-Weight)*(p/q), if W < 0 then "-" else "+", abs(W); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/yacfs.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/yacfs.mod new file mode 100644 index 000000000..270f2a083 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/yacfs.mod @@ -0,0 +1,48 @@ +/*Yet Another Curve Fitting Solution + + Obviously this solution produces the same answer + as examples/cflsq.mod + + Nigel_Galloway@operamail.com + February 1st., 2009 +*/ +set Sample; +param Sx {z in Sample}; +param Sy {z in Sample}; + +var a; +var b; + +equalz1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; +equalz2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; + +solve; + +printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b, if a < 0 then "-" else "+", abs(a); + +data; + +param: +Sample: Sx Sy := + 1 0 1 + 2 0.5 0.9 + 3 1 0.7 + 4 1.5 1.5 + 5 1.9 2 + 6 2.5 2.4 + 7 3 3.2 + 8 3.5 2 + 9 4 2.7 + 10 4.5 3.5 + 11 5 1 + 12 5.5 4 + 13 6 3.6 + 14 6.6 2.7 + 15 7 5.7 + 16 7.6 4.6 + 17 8.5 6 + 18 9 6.8 + 19 10 7.3 +; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/examples/zebra.mod b/WebAPP/SOLVERs/GLPK/glpk/examples/zebra.mod new file mode 100644 index 000000000..66f8c1aaf --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/examples/zebra.mod @@ -0,0 +1,151 @@ +/* ZEBRA, Who Owns the Zebra? */ + +/* Written in GNU MathProg by Andrew Makhorin */ + +######################################################################## +# The Zebra Puzzle is a well-known logic puzzle. +# +# It is often called "Einstein's Puzzle" or "Einstein's Riddle" +# because it is said to have been invented by Albert Einstein as a boy, +# with the common claim that Einstein said "only 2 percent of the +# world's population can solve". It is also sometimes attributed to +# Lewis Carroll. However, there is no known evidence for Einstein's or +# Carroll's authorship. +# +# There are several versions of this puzzle. The version below is +# quoted from the first known publication in Life International +# magazine on December 17, 1962. +# +# 1. There are five houses. +# 2. The Englishman lives in the red house. +# 3. The Spaniard owns the dog. +# 4. Coffee is drunk in the green house. +# 5. The Ukrainian drinks tea. +# 6. The green house is immediately to the right of the ivory house. +# 7. The Old Gold smoker owns snails. +# 8. Kools are smoked in the yellow house. +# 9. Milk is drunk in the middle house. +# 10. The Norwegian lives in the first house. +# 11. The man who smokes Chesterfields lives in the house next to the +# man with the fox. +# 12. Kools are smoked in the house next to the house where the horse +# is kept. +# 13. The Lucky Strike smoker drinks orange juice. +# 14. The Japanese smokes Parliaments. +# 15. The Norwegian lives next to the blue house. +# +# Now, who drinks water? Who owns the zebra? +# +# In the interest of clarity, it must be added that each of the five +# houses is painted a different color, and their inhabitants are of +# different national extractions, own different pets, drink different +# beverages and smoke different brands of American cigarettes. One +# other thing: In statement 6, right means your right. +# +# (From Wikipedia, the free encyclopedia.) +######################################################################## + +set HOUSE := { 1..5 }; + +set COLOR := { "blue", "green", "ivory", "red", "yellow" }; + +set NATIONALITY := { "Englishman", "Japanese", "Norwegian", "Spaniard", + "Ukranian" }; + +set DRINK := { "coffee", "milk", "orange_juice", "tea", "water" }; + +set SMOKE := { "Chesterfield", "Kools", "Lucky_Strike", "Old_Gold", + "Parliament" }; + +set PET := { "dog", "fox", "horse", "snails", "zebra" }; + +var color{HOUSE, COLOR}, binary; +c1{h in HOUSE}: sum{c in COLOR} color[h,c] = 1; +c2{c in COLOR}: sum{h in HOUSE} color[h,c] = 1; + +var nationality{HOUSE, NATIONALITY}, binary; +n1{h in HOUSE}: sum{n in NATIONALITY} nationality[h,n] = 1; +n2{n in NATIONALITY}: sum{h in HOUSE} nationality[h,n] = 1; + +var drink{HOUSE, DRINK}, binary; +d1{h in HOUSE}: sum{d in DRINK} drink[h,d] = 1; +d2{d in DRINK}: sum{h in HOUSE} drink[h,d] = 1; + +var smoke{HOUSE, SMOKE}, binary; +s1{h in HOUSE}: sum{s in SMOKE} smoke[h,s] = 1; +s2{s in SMOKE}: sum{h in HOUSE} smoke[h,s] = 1; + +var pet{HOUSE, PET}, binary; +p1{h in HOUSE}: sum{p in PET} pet[h,p] = 1; +p2{p in PET}: sum{h in HOUSE} pet[h,p] = 1; + +/* the Englishman lives in the red house */ +f2{h in HOUSE}: nationality[h,"Englishman"] = color[h,"red"]; + +/* the Spaniard owns the dog */ +f3{h in HOUSE}: nationality[h,"Spaniard"] = pet[h,"dog"]; + +/* coffee is drunk in the green house */ +f4{h in HOUSE}: drink[h,"coffee"] = color[h,"green"]; + +/* the Ukrainian drinks tea */ +f5{h in HOUSE}: nationality[h,"Ukranian"] = drink[h,"tea"]; + +/* the green house is immediately to the right of the ivory house */ +f6{h in HOUSE}: + color[h,"green"] = if h = 1 then 0 else color[h-1,"ivory"]; + +/* the Old Gold smoker owns snails */ +f7{h in HOUSE}: smoke[h,"Old_Gold"] = pet[h,"snails"]; + +/* Kools are smoked in the yellow house */ +f8{h in HOUSE}: smoke[h,"Kools"] = color[h,"yellow"]; + +/* milk is drunk in the middle house */ +f9: drink[3,"milk"] = 1; + +/* the Norwegian lives in the first house */ +f10: nationality[1,"Norwegian"] = 1; + +/* the man who smokes Chesterfields lives in the house next to the man + with the fox */ +f11{h in HOUSE}: + (1 - smoke[h,"Chesterfield"]) + + (if h = 1 then 0 else pet[h-1,"fox"]) + + (if h = 5 then 0 else pet[h+1,"fox"]) >= 1; + +/* Kools are smoked in the house next to the house where the horse is + kept */ +f12{h in HOUSE}: + (1 - smoke[h,"Kools"]) + + (if h = 1 then 0 else pet[h-1,"horse"]) + + (if h = 5 then 0 else pet[h+1,"horse"]) >= 1; + +/* the Lucky Strike smoker drinks orange juice */ +f13{h in HOUSE}: smoke[h,"Lucky_Strike"] = drink[h,"orange_juice"]; + +/* the Japanese smokes Parliaments */ +f14{h in HOUSE}: nationality[h,"Japanese"] = smoke[h,"Parliament"]; + +/* the Norwegian lives next to the blue house */ +f15{h in HOUSE}: + (1 - nationality[h,"Norwegian"]) + + (if h = 1 then 0 else color[h-1,"blue"]) + + (if h = 5 then 0 else color[h+1,"blue"]) >= 1; + +solve; + +printf "\n"; +printf "HOUSE COLOR NATIONALITY DRINK SMOKE PET\n"; +for {h in HOUSE} +{ printf "%5d", h; + printf{c in COLOR: color[h,c]} " %-6s", c; + printf{n in NATIONALITY: nationality[h,n]} " %-11s", n; + printf{d in DRINK: drink[h,d]} " %-12s", d; + printf{s in SMOKE: smoke[h,s]} " %-12s", s; + printf{p in PET: pet[h,p]} " %-6s", p; + printf "\n"; +} +printf "\n"; + +end; diff --git a/WebAPP/SOLVERs/GLPK/glpk/install-sh b/WebAPP/SOLVERs/GLPK/glpk/install-sh new file mode 100755 index 000000000..377bb8687 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/WebAPP/SOLVERs/GLPK/glpk/ltmain.sh b/WebAPP/SOLVERs/GLPK/glpk/ltmain.sh new file mode 100755 index 000000000..fcebbcb5f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/ltmain.sh @@ -0,0 +1,9687 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3294 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="/usr/bin/grep -E"} +: ${FGREP="/usr/bin/grep -F"} +: ${GREP="/usr/bin/grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="/usr/bin/sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_emit_exe_manifest +# emit a Win32 UAC manifest for executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_exe_manifest () +{ + cat < + + + + + + + + + + + + +EOF +} + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -{shared,static}-libgcc, -static-{libgfortran|libstdc++} + # link against specified runtime library + # -fstack-protector* stack protector flags for GCC + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin| \ + -shared-libgcc|-static-libgcc|-static-libgfortran|-static-libstdc++| \ + -fstack-protector*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper $cwrapper.manifest; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + # Create the UAC manifests first if necessary (but the + # manifest files must have executable permission regardless). + case $output_name in + *instal*|*patch*|*setup*|*update*) + func_emit_exe_manifest > $cwrapper.manifest + func_emit_exe_manifest > $output_path/$objdir/$output_name.exe.manifest + chmod +x $cwrapper.manifest + chmod +x $output_path/$objdir/$output_name.exe.manifest + ;; + esac + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + func_append rmfiles " ${name}.manifest $objdir/${name}.manifest" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name $objdir/lt-${name}.manifest" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/WebAPP/SOLVERs/GLPK/glpk/m4/libtool.m4 b/WebAPP/SOLVERs/GLPK/glpk/m4/libtool.m4 new file mode 100644 index 000000000..6aebb63b5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/m4/libtool.m4 @@ -0,0 +1,7831 @@ +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + +## ------------------------------------- ## +## Accumulate code for creating libtool. ## +## ------------------------------------- ## + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + +## ------------------------ ## +## FIXME: Eliminate VARNAME ## +## ------------------------ ## + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS diff --git a/WebAPP/SOLVERs/GLPK/glpk/m4/ltoptions.m4 b/WebAPP/SOLVERs/GLPK/glpk/m4/ltoptions.m4 new file mode 100644 index 000000000..17cfd51c0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/m4/ltoptions.m4 @@ -0,0 +1,369 @@ +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + +## --------------------------------- ## +## Macros to handle LT_INIT options. ## +## --------------------------------- ## + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + +## ----------------- ## +## LTDL_INIT Options ## +## ----------------- ## + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) diff --git a/WebAPP/SOLVERs/GLPK/glpk/m4/ltsugar.m4 b/WebAPP/SOLVERs/GLPK/glpk/m4/ltsugar.m4 new file mode 100644 index 000000000..9000a057d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/m4/ltsugar.m4 @@ -0,0 +1,123 @@ +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) diff --git a/WebAPP/SOLVERs/GLPK/glpk/m4/ltversion.m4 b/WebAPP/SOLVERs/GLPK/glpk/m4/ltversion.m4 new file mode 100644 index 000000000..9bf776f09 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/m4/ltversion.m4 @@ -0,0 +1,23 @@ +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3294 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4]) +m4_define([LT_PACKAGE_REVISION], [1.3294]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4' +macro_revision='1.3294' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) diff --git a/WebAPP/SOLVERs/GLPK/glpk/m4/lt~obsolete.m4 b/WebAPP/SOLVERs/GLPK/glpk/m4/lt~obsolete.m4 new file mode 100644 index 000000000..c573da90c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/m4/lt~obsolete.m4 @@ -0,0 +1,98 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/WebAPP/SOLVERs/GLPK/glpk/missing b/WebAPP/SOLVERs/GLPK/glpk/missing new file mode 100755 index 000000000..9a5564823 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/missing @@ -0,0 +1,330 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2012-01-06.18; # UTC + +# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, 'missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file 'aclocal.m4' + autoconf touch file 'configure' + autoheader touch file 'config.h.in' + autom4te touch the output file, or create a stub one + automake touch all 'Makefile.in' files + bison create 'y.tab.[ch]', if possible, from existing .[ch] + flex create 'lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create 'lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create 'y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running '$TOOL --version' or '$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acinclude.m4' or '${configure_ac}'. You might want + to install the Automake and Perl packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified '${configure_ac}'. You might want to install the + Autoconf and GNU m4 packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'acconfig.h' or '${configure_ac}'. You might want + to install the Autoconf and GNU m4 packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'. + You might want to install the Automake and Perl packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: '$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get '$1' as part of Autoconf from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: '$1' $msg. You should only need it if + you modified a '.y' file. You may need the Bison package + in order for those modifications to take effect. You can get + Bison from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.l' file. You may need the Flex package + in order for those modifications to take effect. You can get + Flex from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG=\${$#} + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + Help2man package in order for those modifications to take + effect. You can get Help2man from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: '$1' is $msg. You should only need it if + you modified a '.texi' or '.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy 'make' (AIX, + DU, IRIX). You might want to install the Texinfo package or + the GNU make package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: '$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the 'README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing '$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.am b/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.am new file mode 100644 index 000000000..eb5dc1bea --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.am @@ -0,0 +1,222 @@ +## Process this file with automake to produce Makefile.in ## + +include_HEADERS = glpk.h + +lib_LTLIBRARIES = libglpk.la + +libglpk_la_CPPFLAGS = \ +-I$(srcdir) \ +-I$(srcdir)/amd \ +-I$(srcdir)/api \ +-I$(srcdir)/bflib \ +-I$(srcdir)/colamd \ +-I$(srcdir)/draft \ +-I$(srcdir)/env \ +-I$(srcdir)/intopt \ +-I$(srcdir)/minisat \ +-I$(srcdir)/misc \ +-I$(srcdir)/mpl \ +-I$(srcdir)/npp \ +-I$(srcdir)/proxy \ +-I$(srcdir)/simplex \ +-I$(srcdir)/zlib + +libglpk_la_LDFLAGS = \ +-version-info 43:0:3 \ +-export-symbols-regex '^glp_*' \ +${NOUNDEFINED} + +libglpk_la_SOURCES = \ +amd/amd_1.c \ +amd/amd_2.c \ +amd/amd_aat.c \ +amd/amd_control.c \ +amd/amd_defaults.c \ +amd/amd_dump.c \ +amd/amd_info.c \ +amd/amd_order.c \ +amd/amd_post_tree.c \ +amd/amd_postorder.c \ +amd/amd_preprocess.c \ +amd/amd_valid.c \ +api/advbas.c \ +api/asnhall.c \ +api/asnlp.c \ +api/asnokalg.c \ +api/ckasn.c \ +api/ckcnf.c \ +api/cplex.c \ +api/cpp.c \ +api/cpxbas.c \ +api/graph.c \ +api/gridgen.c \ +api/intfeas1.c \ +api/maxffalg.c \ +api/maxflp.c \ +api/mcflp.c \ +api/mcfokalg.c \ +api/mcfrelax.c \ +api/minisat1.c \ +api/mpl.c \ +api/mps.c \ +api/netgen.c \ +api/npp.c \ +api/pript.c \ +api/prmip.c \ +api/prob1.c \ +api/prob2.c \ +api/prob3.c \ +api/prob4.c \ +api/prob5.c \ +api/prrngs.c \ +api/prsol.c \ +api/rdasn.c \ +api/rdcc.c \ +api/rdcnf.c \ +api/rdipt.c \ +api/rdmaxf.c \ +api/rdmcf.c \ +api/rdmip.c \ +api/rdprob.c \ +api/rdsol.c \ +api/rmfgen.c \ +api/strong.c \ +api/topsort.c \ +api/weak.c \ +api/wcliqex.c \ +api/wrasn.c \ +api/wrcc.c \ +api/wrcnf.c \ +api/wript.c \ +api/wrmaxf.c \ +api/wrmcf.c \ +api/wrmip.c \ +api/wrprob.c \ +api/wrsol.c \ +bflib/btf.c \ +bflib/btfint.c \ +bflib/fhv.c \ +bflib/fhvint.c \ +bflib/ifu.c \ +bflib/luf.c \ +bflib/lufint.c \ +bflib/scf.c \ +bflib/scfint.c \ +bflib/sgf.c \ +bflib/sva.c \ +colamd/colamd.c \ +draft/bfd.c \ +draft/bfx.c \ +draft/glpapi06.c \ +draft/glpapi07.c \ +draft/glpapi08.c \ +draft/glpapi09.c \ +draft/glpapi10.c \ +draft/glpapi12.c \ +draft/glpapi13.c \ +draft/glphbm.c \ +draft/glpios01.c \ +draft/glpios02.c \ +draft/glpios03.c \ +draft/glpios07.c \ +draft/glpios09.c \ +draft/glpios11.c \ +draft/glpios12.c \ +draft/glpipm.c \ +draft/glpmat.c \ +draft/glprgr.c \ +draft/glpscl.c \ +draft/glpspm.c \ +draft/glpssx01.c \ +draft/glpssx02.c \ +draft/lux.c \ +env/alloc.c \ +env/dlsup.c \ +env/env.c \ +env/error.c \ +env/stdc.c \ +env/stdout.c \ +env/stream.c \ +env/time.c \ +env/tls.c \ +intopt/cfg.c \ +intopt/cfg1.c \ +intopt/cfg2.c \ +intopt/clqcut.c \ +intopt/covgen.c \ +intopt/fpump.c \ +intopt/gmicut.c \ +intopt/gmigen.c \ +intopt/mirgen.c \ +intopt/spv.c \ +minisat/minisat.c \ +misc/avl.c \ +misc/bignum.c \ +misc/dimacs.c \ +misc/dmp.c \ +misc/ffalg.c \ +misc/fp2rat.c \ +misc/fvs.c \ +misc/gcd.c \ +misc/jd.c \ +misc/keller.c \ +misc/ks.c \ +misc/mc13d.c \ +misc/mc21a.c \ +misc/mt1.c \ +misc/mygmp.c \ +misc/okalg.c \ +misc/qmd.c \ +misc/relax4.c \ +misc/rng.c \ +misc/rng1.c \ +misc/round2n.c \ +misc/str2int.c \ +misc/str2num.c \ +misc/strspx.c \ +misc/strtrim.c \ +misc/triang.c \ +misc/wclique.c \ +misc/wclique1.c \ +mpl/mpl1.c \ +mpl/mpl2.c \ +mpl/mpl3.c \ +mpl/mpl4.c \ +mpl/mpl5.c \ +mpl/mpl6.c \ +mpl/mplsql.c \ +npp/npp1.c \ +npp/npp2.c \ +npp/npp3.c \ +npp/npp4.c \ +npp/npp5.c \ +npp/npp6.c \ +proxy/proxy.c \ +proxy/proxy1.c \ +simplex/spxat.c \ +simplex/spxchuzc.c \ +simplex/spxchuzr.c \ +simplex/spxlp.c \ +simplex/spxnt.c \ +simplex/spxprim.c \ +simplex/spxprob.c \ +simplex/spychuzc.c \ +simplex/spychuzr.c \ +simplex/spydual.c \ +zlib/adler32.c \ +zlib/compress.c \ +zlib/crc32.c \ +zlib/deflate.c \ +zlib/gzclose.c \ +zlib/gzlib.c \ +zlib/gzread.c \ +zlib/gzwrite.c \ +zlib/inffast.c \ +zlib/inflate.c \ +zlib/inftrees.c \ +zlib/trees.c \ +zlib/uncompr.c \ +zlib/zio.c \ +zlib/zutil.c + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.in b/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.in new file mode 100644 index 000000000..a06a2dcec --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/Makefile.in @@ -0,0 +1,2409 @@ +# Makefile.in generated by automake 1.12.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2012 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src +DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libglpk_la_LIBADD = +am_libglpk_la_OBJECTS = libglpk_la-amd_1.lo libglpk_la-amd_2.lo \ + libglpk_la-amd_aat.lo libglpk_la-amd_control.lo \ + libglpk_la-amd_defaults.lo libglpk_la-amd_dump.lo \ + libglpk_la-amd_info.lo libglpk_la-amd_order.lo \ + libglpk_la-amd_post_tree.lo libglpk_la-amd_postorder.lo \ + libglpk_la-amd_preprocess.lo libglpk_la-amd_valid.lo \ + libglpk_la-advbas.lo libglpk_la-asnhall.lo libglpk_la-asnlp.lo \ + libglpk_la-asnokalg.lo libglpk_la-ckasn.lo libglpk_la-ckcnf.lo \ + libglpk_la-cplex.lo libglpk_la-cpp.lo libglpk_la-cpxbas.lo \ + libglpk_la-graph.lo libglpk_la-gridgen.lo \ + libglpk_la-intfeas1.lo libglpk_la-maxffalg.lo \ + libglpk_la-maxflp.lo libglpk_la-mcflp.lo \ + libglpk_la-mcfokalg.lo libglpk_la-mcfrelax.lo \ + libglpk_la-minisat1.lo libglpk_la-mpl.lo libglpk_la-mps.lo \ + libglpk_la-netgen.lo libglpk_la-npp.lo libglpk_la-pript.lo \ + libglpk_la-prmip.lo libglpk_la-prob1.lo libglpk_la-prob2.lo \ + libglpk_la-prob3.lo libglpk_la-prob4.lo libglpk_la-prob5.lo \ + libglpk_la-prrngs.lo libglpk_la-prsol.lo libglpk_la-rdasn.lo \ + libglpk_la-rdcc.lo libglpk_la-rdcnf.lo libglpk_la-rdipt.lo \ + libglpk_la-rdmaxf.lo libglpk_la-rdmcf.lo libglpk_la-rdmip.lo \ + libglpk_la-rdprob.lo libglpk_la-rdsol.lo libglpk_la-rmfgen.lo \ + libglpk_la-strong.lo libglpk_la-topsort.lo libglpk_la-weak.lo \ + libglpk_la-wcliqex.lo libglpk_la-wrasn.lo libglpk_la-wrcc.lo \ + libglpk_la-wrcnf.lo libglpk_la-wript.lo libglpk_la-wrmaxf.lo \ + libglpk_la-wrmcf.lo libglpk_la-wrmip.lo libglpk_la-wrprob.lo \ + libglpk_la-wrsol.lo libglpk_la-btf.lo libglpk_la-btfint.lo \ + libglpk_la-fhv.lo libglpk_la-fhvint.lo libglpk_la-ifu.lo \ + libglpk_la-luf.lo libglpk_la-lufint.lo libglpk_la-scf.lo \ + libglpk_la-scfint.lo libglpk_la-sgf.lo libglpk_la-sva.lo \ + libglpk_la-colamd.lo libglpk_la-bfd.lo libglpk_la-bfx.lo \ + libglpk_la-glpapi06.lo libglpk_la-glpapi07.lo \ + libglpk_la-glpapi08.lo libglpk_la-glpapi09.lo \ + libglpk_la-glpapi10.lo libglpk_la-glpapi12.lo \ + libglpk_la-glpapi13.lo libglpk_la-glphbm.lo \ + libglpk_la-glpios01.lo libglpk_la-glpios02.lo \ + libglpk_la-glpios03.lo libglpk_la-glpios07.lo \ + libglpk_la-glpios09.lo libglpk_la-glpios11.lo \ + libglpk_la-glpios12.lo libglpk_la-glpipm.lo \ + libglpk_la-glpmat.lo libglpk_la-glprgr.lo libglpk_la-glpscl.lo \ + libglpk_la-glpspm.lo libglpk_la-glpssx01.lo \ + libglpk_la-glpssx02.lo libglpk_la-lux.lo libglpk_la-alloc.lo \ + libglpk_la-dlsup.lo libglpk_la-env.lo libglpk_la-error.lo \ + libglpk_la-stdc.lo libglpk_la-stdout.lo libglpk_la-stream.lo \ + libglpk_la-time.lo libglpk_la-tls.lo libglpk_la-cfg.lo \ + libglpk_la-cfg1.lo libglpk_la-cfg2.lo libglpk_la-clqcut.lo \ + libglpk_la-covgen.lo libglpk_la-fpump.lo libglpk_la-gmicut.lo \ + libglpk_la-gmigen.lo libglpk_la-mirgen.lo libglpk_la-spv.lo \ + libglpk_la-minisat.lo libglpk_la-avl.lo libglpk_la-bignum.lo \ + libglpk_la-dimacs.lo libglpk_la-dmp.lo libglpk_la-ffalg.lo \ + libglpk_la-fp2rat.lo libglpk_la-fvs.lo libglpk_la-gcd.lo \ + libglpk_la-jd.lo libglpk_la-keller.lo libglpk_la-ks.lo \ + libglpk_la-mc13d.lo libglpk_la-mc21a.lo libglpk_la-mt1.lo \ + libglpk_la-mygmp.lo libglpk_la-okalg.lo libglpk_la-qmd.lo \ + libglpk_la-relax4.lo libglpk_la-rng.lo libglpk_la-rng1.lo \ + libglpk_la-round2n.lo libglpk_la-str2int.lo \ + libglpk_la-str2num.lo libglpk_la-strspx.lo \ + libglpk_la-strtrim.lo libglpk_la-triang.lo \ + libglpk_la-wclique.lo libglpk_la-wclique1.lo \ + libglpk_la-mpl1.lo libglpk_la-mpl2.lo libglpk_la-mpl3.lo \ + libglpk_la-mpl4.lo libglpk_la-mpl5.lo libglpk_la-mpl6.lo \ + libglpk_la-mplsql.lo libglpk_la-npp1.lo libglpk_la-npp2.lo \ + libglpk_la-npp3.lo libglpk_la-npp4.lo libglpk_la-npp5.lo \ + libglpk_la-npp6.lo libglpk_la-proxy.lo libglpk_la-proxy1.lo \ + libglpk_la-spxat.lo libglpk_la-spxchuzc.lo \ + libglpk_la-spxchuzr.lo libglpk_la-spxlp.lo libglpk_la-spxnt.lo \ + libglpk_la-spxprim.lo libglpk_la-spxprob.lo \ + libglpk_la-spychuzc.lo libglpk_la-spychuzr.lo \ + libglpk_la-spydual.lo libglpk_la-adler32.lo \ + libglpk_la-compress.lo libglpk_la-crc32.lo \ + libglpk_la-deflate.lo libglpk_la-gzclose.lo \ + libglpk_la-gzlib.lo libglpk_la-gzread.lo libglpk_la-gzwrite.lo \ + libglpk_la-inffast.lo libglpk_la-inflate.lo \ + libglpk_la-inftrees.lo libglpk_la-trees.lo \ + libglpk_la-uncompr.lo libglpk_la-zio.lo libglpk_la-zutil.lo +libglpk_la_OBJECTS = $(am_libglpk_la_OBJECTS) +libglpk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libglpk_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libglpk_la_SOURCES) +DIST_SOURCES = $(libglpk_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUNDEFINED = @NOUNDEFINED@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +include_HEADERS = glpk.h +lib_LTLIBRARIES = libglpk.la +libglpk_la_CPPFLAGS = \ +-I$(srcdir) \ +-I$(srcdir)/amd \ +-I$(srcdir)/api \ +-I$(srcdir)/bflib \ +-I$(srcdir)/colamd \ +-I$(srcdir)/draft \ +-I$(srcdir)/env \ +-I$(srcdir)/intopt \ +-I$(srcdir)/minisat \ +-I$(srcdir)/misc \ +-I$(srcdir)/mpl \ +-I$(srcdir)/npp \ +-I$(srcdir)/proxy \ +-I$(srcdir)/simplex \ +-I$(srcdir)/zlib + +libglpk_la_LDFLAGS = \ +-version-info 43:0:3 \ +-export-symbols-regex '^glp_*' \ +${NOUNDEFINED} + +libglpk_la_SOURCES = \ +amd/amd_1.c \ +amd/amd_2.c \ +amd/amd_aat.c \ +amd/amd_control.c \ +amd/amd_defaults.c \ +amd/amd_dump.c \ +amd/amd_info.c \ +amd/amd_order.c \ +amd/amd_post_tree.c \ +amd/amd_postorder.c \ +amd/amd_preprocess.c \ +amd/amd_valid.c \ +api/advbas.c \ +api/asnhall.c \ +api/asnlp.c \ +api/asnokalg.c \ +api/ckasn.c \ +api/ckcnf.c \ +api/cplex.c \ +api/cpp.c \ +api/cpxbas.c \ +api/graph.c \ +api/gridgen.c \ +api/intfeas1.c \ +api/maxffalg.c \ +api/maxflp.c \ +api/mcflp.c \ +api/mcfokalg.c \ +api/mcfrelax.c \ +api/minisat1.c \ +api/mpl.c \ +api/mps.c \ +api/netgen.c \ +api/npp.c \ +api/pript.c \ +api/prmip.c \ +api/prob1.c \ +api/prob2.c \ +api/prob3.c \ +api/prob4.c \ +api/prob5.c \ +api/prrngs.c \ +api/prsol.c \ +api/rdasn.c \ +api/rdcc.c \ +api/rdcnf.c \ +api/rdipt.c \ +api/rdmaxf.c \ +api/rdmcf.c \ +api/rdmip.c \ +api/rdprob.c \ +api/rdsol.c \ +api/rmfgen.c \ +api/strong.c \ +api/topsort.c \ +api/weak.c \ +api/wcliqex.c \ +api/wrasn.c \ +api/wrcc.c \ +api/wrcnf.c \ +api/wript.c \ +api/wrmaxf.c \ +api/wrmcf.c \ +api/wrmip.c \ +api/wrprob.c \ +api/wrsol.c \ +bflib/btf.c \ +bflib/btfint.c \ +bflib/fhv.c \ +bflib/fhvint.c \ +bflib/ifu.c \ +bflib/luf.c \ +bflib/lufint.c \ +bflib/scf.c \ +bflib/scfint.c \ +bflib/sgf.c \ +bflib/sva.c \ +colamd/colamd.c \ +draft/bfd.c \ +draft/bfx.c \ +draft/glpapi06.c \ +draft/glpapi07.c \ +draft/glpapi08.c \ +draft/glpapi09.c \ +draft/glpapi10.c \ +draft/glpapi12.c \ +draft/glpapi13.c \ +draft/glphbm.c \ +draft/glpios01.c \ +draft/glpios02.c \ +draft/glpios03.c \ +draft/glpios07.c \ +draft/glpios09.c \ +draft/glpios11.c \ +draft/glpios12.c \ +draft/glpipm.c \ +draft/glpmat.c \ +draft/glprgr.c \ +draft/glpscl.c \ +draft/glpspm.c \ +draft/glpssx01.c \ +draft/glpssx02.c \ +draft/lux.c \ +env/alloc.c \ +env/dlsup.c \ +env/env.c \ +env/error.c \ +env/stdc.c \ +env/stdout.c \ +env/stream.c \ +env/time.c \ +env/tls.c \ +intopt/cfg.c \ +intopt/cfg1.c \ +intopt/cfg2.c \ +intopt/clqcut.c \ +intopt/covgen.c \ +intopt/fpump.c \ +intopt/gmicut.c \ +intopt/gmigen.c \ +intopt/mirgen.c \ +intopt/spv.c \ +minisat/minisat.c \ +misc/avl.c \ +misc/bignum.c \ +misc/dimacs.c \ +misc/dmp.c \ +misc/ffalg.c \ +misc/fp2rat.c \ +misc/fvs.c \ +misc/gcd.c \ +misc/jd.c \ +misc/keller.c \ +misc/ks.c \ +misc/mc13d.c \ +misc/mc21a.c \ +misc/mt1.c \ +misc/mygmp.c \ +misc/okalg.c \ +misc/qmd.c \ +misc/relax4.c \ +misc/rng.c \ +misc/rng1.c \ +misc/round2n.c \ +misc/str2int.c \ +misc/str2num.c \ +misc/strspx.c \ +misc/strtrim.c \ +misc/triang.c \ +misc/wclique.c \ +misc/wclique1.c \ +mpl/mpl1.c \ +mpl/mpl2.c \ +mpl/mpl3.c \ +mpl/mpl4.c \ +mpl/mpl5.c \ +mpl/mpl6.c \ +mpl/mplsql.c \ +npp/npp1.c \ +npp/npp2.c \ +npp/npp3.c \ +npp/npp4.c \ +npp/npp5.c \ +npp/npp6.c \ +proxy/proxy.c \ +proxy/proxy1.c \ +simplex/spxat.c \ +simplex/spxchuzc.c \ +simplex/spxchuzr.c \ +simplex/spxlp.c \ +simplex/spxnt.c \ +simplex/spxprim.c \ +simplex/spxprob.c \ +simplex/spychuzc.c \ +simplex/spychuzr.c \ +simplex/spydual.c \ +zlib/adler32.c \ +zlib/compress.c \ +zlib/crc32.c \ +zlib/deflate.c \ +zlib/gzclose.c \ +zlib/gzlib.c \ +zlib/gzread.c \ +zlib/gzwrite.c \ +zlib/inffast.c \ +zlib/inflate.c \ +zlib/inftrees.c \ +zlib/trees.c \ +zlib/uncompr.c \ +zlib/zio.c \ +zlib/zutil.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +libglpk.la: $(libglpk_la_OBJECTS) $(libglpk_la_DEPENDENCIES) $(EXTRA_libglpk_la_DEPENDENCIES) + $(libglpk_la_LINK) -rpath $(libdir) $(libglpk_la_OBJECTS) $(libglpk_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-adler32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-advbas.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-alloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_aat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_control.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_defaults.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_dump.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_info.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_order.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_post_tree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_postorder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_preprocess.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_valid.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-asnhall.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-asnlp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-asnokalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-avl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bignum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-btf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-btfint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ckasn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ckcnf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-clqcut.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-colamd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-compress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-covgen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cplex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cpp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cpxbas.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-crc32.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-deflate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dimacs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dlsup.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-env.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-error.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ffalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhvint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fp2rat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fpump.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fvs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gcd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi06.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi07.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi08.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi09.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi10.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi12.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi13.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glphbm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios03.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios07.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios09.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios12.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpipm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glprgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpscl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx01.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx02.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gmicut.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gmigen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-graph.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gridgen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzclose.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzlib.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzwrite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ifu.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inffast.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inflate.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inftrees.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-intfeas1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-jd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-keller.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-luf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-lufint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-lux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-maxffalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-maxflp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc13d.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc21a.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mcflp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mcfokalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mcfrelax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-minisat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-minisat1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mirgen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl3.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mpl6.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mplsql.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mps.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mt1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mygmp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-netgen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp3.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-npp6.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-okalg.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-pript.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prmip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prob1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prob2.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prob3.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prob4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prob5.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prrngs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-prsol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-qmd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdasn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdcc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdcnf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdipt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdmaxf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdmcf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdmip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdprob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rdsol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-relax4.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rmfgen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-round2n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-scf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-scfint.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sgf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxchuzc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxchuzr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxlp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxnt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxprim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxprob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spychuzc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spychuzr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spydual.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stdc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stdout.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2int.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2num.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stream.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-strong.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-strspx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-strtrim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sva.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-time.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-tls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-topsort.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-trees.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-triang.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-uncompr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wcliqex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique1.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-weak.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrasn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrcc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrcnf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wript.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrmaxf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrmcf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrmip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrprob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wrsol.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zutil.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libglpk_la-amd_1.lo: amd/amd_1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_1.Tpo -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_1.Tpo $(DEPDIR)/libglpk_la-amd_1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_1.c' object='libglpk_la-amd_1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c + +libglpk_la-amd_2.lo: amd/amd_2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_2.Tpo -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_2.Tpo $(DEPDIR)/libglpk_la-amd_2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_2.c' object='libglpk_la-amd_2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c + +libglpk_la-amd_aat.lo: amd/amd_aat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_aat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_aat.Tpo -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_aat.Tpo $(DEPDIR)/libglpk_la-amd_aat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_aat.c' object='libglpk_la-amd_aat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c + +libglpk_la-amd_control.lo: amd/amd_control.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_control.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_control.Tpo -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_control.Tpo $(DEPDIR)/libglpk_la-amd_control.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_control.c' object='libglpk_la-amd_control.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c + +libglpk_la-amd_defaults.lo: amd/amd_defaults.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_defaults.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_defaults.Tpo -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_defaults.Tpo $(DEPDIR)/libglpk_la-amd_defaults.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_defaults.c' object='libglpk_la-amd_defaults.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c + +libglpk_la-amd_dump.lo: amd/amd_dump.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_dump.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_dump.Tpo -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_dump.Tpo $(DEPDIR)/libglpk_la-amd_dump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_dump.c' object='libglpk_la-amd_dump.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c + +libglpk_la-amd_info.lo: amd/amd_info.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_info.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_info.Tpo -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_info.Tpo $(DEPDIR)/libglpk_la-amd_info.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_info.c' object='libglpk_la-amd_info.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c + +libglpk_la-amd_order.lo: amd/amd_order.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_order.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_order.Tpo -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_order.Tpo $(DEPDIR)/libglpk_la-amd_order.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_order.c' object='libglpk_la-amd_order.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c + +libglpk_la-amd_post_tree.lo: amd/amd_post_tree.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_post_tree.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_post_tree.Tpo -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_post_tree.Tpo $(DEPDIR)/libglpk_la-amd_post_tree.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_post_tree.c' object='libglpk_la-amd_post_tree.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c + +libglpk_la-amd_postorder.lo: amd/amd_postorder.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_postorder.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_postorder.Tpo -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_postorder.Tpo $(DEPDIR)/libglpk_la-amd_postorder.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_postorder.c' object='libglpk_la-amd_postorder.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c + +libglpk_la-amd_preprocess.lo: amd/amd_preprocess.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_preprocess.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_preprocess.Tpo -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_preprocess.Tpo $(DEPDIR)/libglpk_la-amd_preprocess.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_preprocess.c' object='libglpk_la-amd_preprocess.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c + +libglpk_la-amd_valid.lo: amd/amd_valid.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_valid.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_valid.Tpo -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_valid.Tpo $(DEPDIR)/libglpk_la-amd_valid.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_valid.c' object='libglpk_la-amd_valid.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c + +libglpk_la-advbas.lo: api/advbas.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-advbas.lo -MD -MP -MF $(DEPDIR)/libglpk_la-advbas.Tpo -c -o libglpk_la-advbas.lo `test -f 'api/advbas.c' || echo '$(srcdir)/'`api/advbas.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-advbas.Tpo $(DEPDIR)/libglpk_la-advbas.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/advbas.c' object='libglpk_la-advbas.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-advbas.lo `test -f 'api/advbas.c' || echo '$(srcdir)/'`api/advbas.c + +libglpk_la-asnhall.lo: api/asnhall.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-asnhall.lo -MD -MP -MF $(DEPDIR)/libglpk_la-asnhall.Tpo -c -o libglpk_la-asnhall.lo `test -f 'api/asnhall.c' || echo '$(srcdir)/'`api/asnhall.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-asnhall.Tpo $(DEPDIR)/libglpk_la-asnhall.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/asnhall.c' object='libglpk_la-asnhall.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-asnhall.lo `test -f 'api/asnhall.c' || echo '$(srcdir)/'`api/asnhall.c + +libglpk_la-asnlp.lo: api/asnlp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-asnlp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-asnlp.Tpo -c -o libglpk_la-asnlp.lo `test -f 'api/asnlp.c' || echo '$(srcdir)/'`api/asnlp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-asnlp.Tpo $(DEPDIR)/libglpk_la-asnlp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/asnlp.c' object='libglpk_la-asnlp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-asnlp.lo `test -f 'api/asnlp.c' || echo '$(srcdir)/'`api/asnlp.c + +libglpk_la-asnokalg.lo: api/asnokalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-asnokalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-asnokalg.Tpo -c -o libglpk_la-asnokalg.lo `test -f 'api/asnokalg.c' || echo '$(srcdir)/'`api/asnokalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-asnokalg.Tpo $(DEPDIR)/libglpk_la-asnokalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/asnokalg.c' object='libglpk_la-asnokalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-asnokalg.lo `test -f 'api/asnokalg.c' || echo '$(srcdir)/'`api/asnokalg.c + +libglpk_la-ckasn.lo: api/ckasn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ckasn.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ckasn.Tpo -c -o libglpk_la-ckasn.lo `test -f 'api/ckasn.c' || echo '$(srcdir)/'`api/ckasn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ckasn.Tpo $(DEPDIR)/libglpk_la-ckasn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/ckasn.c' object='libglpk_la-ckasn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ckasn.lo `test -f 'api/ckasn.c' || echo '$(srcdir)/'`api/ckasn.c + +libglpk_la-ckcnf.lo: api/ckcnf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ckcnf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ckcnf.Tpo -c -o libglpk_la-ckcnf.lo `test -f 'api/ckcnf.c' || echo '$(srcdir)/'`api/ckcnf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ckcnf.Tpo $(DEPDIR)/libglpk_la-ckcnf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/ckcnf.c' object='libglpk_la-ckcnf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ckcnf.lo `test -f 'api/ckcnf.c' || echo '$(srcdir)/'`api/ckcnf.c + +libglpk_la-cplex.lo: api/cplex.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cplex.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cplex.Tpo -c -o libglpk_la-cplex.lo `test -f 'api/cplex.c' || echo '$(srcdir)/'`api/cplex.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cplex.Tpo $(DEPDIR)/libglpk_la-cplex.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/cplex.c' object='libglpk_la-cplex.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cplex.lo `test -f 'api/cplex.c' || echo '$(srcdir)/'`api/cplex.c + +libglpk_la-cpp.lo: api/cpp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cpp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cpp.Tpo -c -o libglpk_la-cpp.lo `test -f 'api/cpp.c' || echo '$(srcdir)/'`api/cpp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cpp.Tpo $(DEPDIR)/libglpk_la-cpp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/cpp.c' object='libglpk_la-cpp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cpp.lo `test -f 'api/cpp.c' || echo '$(srcdir)/'`api/cpp.c + +libglpk_la-cpxbas.lo: api/cpxbas.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cpxbas.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cpxbas.Tpo -c -o libglpk_la-cpxbas.lo `test -f 'api/cpxbas.c' || echo '$(srcdir)/'`api/cpxbas.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cpxbas.Tpo $(DEPDIR)/libglpk_la-cpxbas.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/cpxbas.c' object='libglpk_la-cpxbas.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cpxbas.lo `test -f 'api/cpxbas.c' || echo '$(srcdir)/'`api/cpxbas.c + +libglpk_la-graph.lo: api/graph.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-graph.lo -MD -MP -MF $(DEPDIR)/libglpk_la-graph.Tpo -c -o libglpk_la-graph.lo `test -f 'api/graph.c' || echo '$(srcdir)/'`api/graph.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-graph.Tpo $(DEPDIR)/libglpk_la-graph.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/graph.c' object='libglpk_la-graph.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-graph.lo `test -f 'api/graph.c' || echo '$(srcdir)/'`api/graph.c + +libglpk_la-gridgen.lo: api/gridgen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gridgen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gridgen.Tpo -c -o libglpk_la-gridgen.lo `test -f 'api/gridgen.c' || echo '$(srcdir)/'`api/gridgen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gridgen.Tpo $(DEPDIR)/libglpk_la-gridgen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/gridgen.c' object='libglpk_la-gridgen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gridgen.lo `test -f 'api/gridgen.c' || echo '$(srcdir)/'`api/gridgen.c + +libglpk_la-intfeas1.lo: api/intfeas1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-intfeas1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-intfeas1.Tpo -c -o libglpk_la-intfeas1.lo `test -f 'api/intfeas1.c' || echo '$(srcdir)/'`api/intfeas1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-intfeas1.Tpo $(DEPDIR)/libglpk_la-intfeas1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/intfeas1.c' object='libglpk_la-intfeas1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-intfeas1.lo `test -f 'api/intfeas1.c' || echo '$(srcdir)/'`api/intfeas1.c + +libglpk_la-maxffalg.lo: api/maxffalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-maxffalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-maxffalg.Tpo -c -o libglpk_la-maxffalg.lo `test -f 'api/maxffalg.c' || echo '$(srcdir)/'`api/maxffalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-maxffalg.Tpo $(DEPDIR)/libglpk_la-maxffalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/maxffalg.c' object='libglpk_la-maxffalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-maxffalg.lo `test -f 'api/maxffalg.c' || echo '$(srcdir)/'`api/maxffalg.c + +libglpk_la-maxflp.lo: api/maxflp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-maxflp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-maxflp.Tpo -c -o libglpk_la-maxflp.lo `test -f 'api/maxflp.c' || echo '$(srcdir)/'`api/maxflp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-maxflp.Tpo $(DEPDIR)/libglpk_la-maxflp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/maxflp.c' object='libglpk_la-maxflp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-maxflp.lo `test -f 'api/maxflp.c' || echo '$(srcdir)/'`api/maxflp.c + +libglpk_la-mcflp.lo: api/mcflp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mcflp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mcflp.Tpo -c -o libglpk_la-mcflp.lo `test -f 'api/mcflp.c' || echo '$(srcdir)/'`api/mcflp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mcflp.Tpo $(DEPDIR)/libglpk_la-mcflp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/mcflp.c' object='libglpk_la-mcflp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mcflp.lo `test -f 'api/mcflp.c' || echo '$(srcdir)/'`api/mcflp.c + +libglpk_la-mcfokalg.lo: api/mcfokalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mcfokalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mcfokalg.Tpo -c -o libglpk_la-mcfokalg.lo `test -f 'api/mcfokalg.c' || echo '$(srcdir)/'`api/mcfokalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mcfokalg.Tpo $(DEPDIR)/libglpk_la-mcfokalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/mcfokalg.c' object='libglpk_la-mcfokalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mcfokalg.lo `test -f 'api/mcfokalg.c' || echo '$(srcdir)/'`api/mcfokalg.c + +libglpk_la-mcfrelax.lo: api/mcfrelax.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mcfrelax.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mcfrelax.Tpo -c -o libglpk_la-mcfrelax.lo `test -f 'api/mcfrelax.c' || echo '$(srcdir)/'`api/mcfrelax.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mcfrelax.Tpo $(DEPDIR)/libglpk_la-mcfrelax.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/mcfrelax.c' object='libglpk_la-mcfrelax.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mcfrelax.lo `test -f 'api/mcfrelax.c' || echo '$(srcdir)/'`api/mcfrelax.c + +libglpk_la-minisat1.lo: api/minisat1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-minisat1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-minisat1.Tpo -c -o libglpk_la-minisat1.lo `test -f 'api/minisat1.c' || echo '$(srcdir)/'`api/minisat1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-minisat1.Tpo $(DEPDIR)/libglpk_la-minisat1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/minisat1.c' object='libglpk_la-minisat1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-minisat1.lo `test -f 'api/minisat1.c' || echo '$(srcdir)/'`api/minisat1.c + +libglpk_la-mpl.lo: api/mpl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl.Tpo -c -o libglpk_la-mpl.lo `test -f 'api/mpl.c' || echo '$(srcdir)/'`api/mpl.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl.Tpo $(DEPDIR)/libglpk_la-mpl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/mpl.c' object='libglpk_la-mpl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl.lo `test -f 'api/mpl.c' || echo '$(srcdir)/'`api/mpl.c + +libglpk_la-mps.lo: api/mps.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mps.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mps.Tpo -c -o libglpk_la-mps.lo `test -f 'api/mps.c' || echo '$(srcdir)/'`api/mps.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mps.Tpo $(DEPDIR)/libglpk_la-mps.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/mps.c' object='libglpk_la-mps.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mps.lo `test -f 'api/mps.c' || echo '$(srcdir)/'`api/mps.c + +libglpk_la-netgen.lo: api/netgen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-netgen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-netgen.Tpo -c -o libglpk_la-netgen.lo `test -f 'api/netgen.c' || echo '$(srcdir)/'`api/netgen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-netgen.Tpo $(DEPDIR)/libglpk_la-netgen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/netgen.c' object='libglpk_la-netgen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-netgen.lo `test -f 'api/netgen.c' || echo '$(srcdir)/'`api/netgen.c + +libglpk_la-npp.lo: api/npp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp.Tpo -c -o libglpk_la-npp.lo `test -f 'api/npp.c' || echo '$(srcdir)/'`api/npp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp.Tpo $(DEPDIR)/libglpk_la-npp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/npp.c' object='libglpk_la-npp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp.lo `test -f 'api/npp.c' || echo '$(srcdir)/'`api/npp.c + +libglpk_la-pript.lo: api/pript.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-pript.lo -MD -MP -MF $(DEPDIR)/libglpk_la-pript.Tpo -c -o libglpk_la-pript.lo `test -f 'api/pript.c' || echo '$(srcdir)/'`api/pript.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-pript.Tpo $(DEPDIR)/libglpk_la-pript.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/pript.c' object='libglpk_la-pript.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-pript.lo `test -f 'api/pript.c' || echo '$(srcdir)/'`api/pript.c + +libglpk_la-prmip.lo: api/prmip.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prmip.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prmip.Tpo -c -o libglpk_la-prmip.lo `test -f 'api/prmip.c' || echo '$(srcdir)/'`api/prmip.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prmip.Tpo $(DEPDIR)/libglpk_la-prmip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prmip.c' object='libglpk_la-prmip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prmip.lo `test -f 'api/prmip.c' || echo '$(srcdir)/'`api/prmip.c + +libglpk_la-prob1.lo: api/prob1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prob1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prob1.Tpo -c -o libglpk_la-prob1.lo `test -f 'api/prob1.c' || echo '$(srcdir)/'`api/prob1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prob1.Tpo $(DEPDIR)/libglpk_la-prob1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prob1.c' object='libglpk_la-prob1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prob1.lo `test -f 'api/prob1.c' || echo '$(srcdir)/'`api/prob1.c + +libglpk_la-prob2.lo: api/prob2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prob2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prob2.Tpo -c -o libglpk_la-prob2.lo `test -f 'api/prob2.c' || echo '$(srcdir)/'`api/prob2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prob2.Tpo $(DEPDIR)/libglpk_la-prob2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prob2.c' object='libglpk_la-prob2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prob2.lo `test -f 'api/prob2.c' || echo '$(srcdir)/'`api/prob2.c + +libglpk_la-prob3.lo: api/prob3.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prob3.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prob3.Tpo -c -o libglpk_la-prob3.lo `test -f 'api/prob3.c' || echo '$(srcdir)/'`api/prob3.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prob3.Tpo $(DEPDIR)/libglpk_la-prob3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prob3.c' object='libglpk_la-prob3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prob3.lo `test -f 'api/prob3.c' || echo '$(srcdir)/'`api/prob3.c + +libglpk_la-prob4.lo: api/prob4.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prob4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prob4.Tpo -c -o libglpk_la-prob4.lo `test -f 'api/prob4.c' || echo '$(srcdir)/'`api/prob4.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prob4.Tpo $(DEPDIR)/libglpk_la-prob4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prob4.c' object='libglpk_la-prob4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prob4.lo `test -f 'api/prob4.c' || echo '$(srcdir)/'`api/prob4.c + +libglpk_la-prob5.lo: api/prob5.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prob5.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prob5.Tpo -c -o libglpk_la-prob5.lo `test -f 'api/prob5.c' || echo '$(srcdir)/'`api/prob5.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prob5.Tpo $(DEPDIR)/libglpk_la-prob5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prob5.c' object='libglpk_la-prob5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prob5.lo `test -f 'api/prob5.c' || echo '$(srcdir)/'`api/prob5.c + +libglpk_la-prrngs.lo: api/prrngs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prrngs.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prrngs.Tpo -c -o libglpk_la-prrngs.lo `test -f 'api/prrngs.c' || echo '$(srcdir)/'`api/prrngs.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prrngs.Tpo $(DEPDIR)/libglpk_la-prrngs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prrngs.c' object='libglpk_la-prrngs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prrngs.lo `test -f 'api/prrngs.c' || echo '$(srcdir)/'`api/prrngs.c + +libglpk_la-prsol.lo: api/prsol.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-prsol.lo -MD -MP -MF $(DEPDIR)/libglpk_la-prsol.Tpo -c -o libglpk_la-prsol.lo `test -f 'api/prsol.c' || echo '$(srcdir)/'`api/prsol.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-prsol.Tpo $(DEPDIR)/libglpk_la-prsol.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/prsol.c' object='libglpk_la-prsol.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-prsol.lo `test -f 'api/prsol.c' || echo '$(srcdir)/'`api/prsol.c + +libglpk_la-rdasn.lo: api/rdasn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdasn.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdasn.Tpo -c -o libglpk_la-rdasn.lo `test -f 'api/rdasn.c' || echo '$(srcdir)/'`api/rdasn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdasn.Tpo $(DEPDIR)/libglpk_la-rdasn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdasn.c' object='libglpk_la-rdasn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdasn.lo `test -f 'api/rdasn.c' || echo '$(srcdir)/'`api/rdasn.c + +libglpk_la-rdcc.lo: api/rdcc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdcc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdcc.Tpo -c -o libglpk_la-rdcc.lo `test -f 'api/rdcc.c' || echo '$(srcdir)/'`api/rdcc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdcc.Tpo $(DEPDIR)/libglpk_la-rdcc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdcc.c' object='libglpk_la-rdcc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdcc.lo `test -f 'api/rdcc.c' || echo '$(srcdir)/'`api/rdcc.c + +libglpk_la-rdcnf.lo: api/rdcnf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdcnf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdcnf.Tpo -c -o libglpk_la-rdcnf.lo `test -f 'api/rdcnf.c' || echo '$(srcdir)/'`api/rdcnf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdcnf.Tpo $(DEPDIR)/libglpk_la-rdcnf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdcnf.c' object='libglpk_la-rdcnf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdcnf.lo `test -f 'api/rdcnf.c' || echo '$(srcdir)/'`api/rdcnf.c + +libglpk_la-rdipt.lo: api/rdipt.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdipt.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdipt.Tpo -c -o libglpk_la-rdipt.lo `test -f 'api/rdipt.c' || echo '$(srcdir)/'`api/rdipt.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdipt.Tpo $(DEPDIR)/libglpk_la-rdipt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdipt.c' object='libglpk_la-rdipt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdipt.lo `test -f 'api/rdipt.c' || echo '$(srcdir)/'`api/rdipt.c + +libglpk_la-rdmaxf.lo: api/rdmaxf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdmaxf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdmaxf.Tpo -c -o libglpk_la-rdmaxf.lo `test -f 'api/rdmaxf.c' || echo '$(srcdir)/'`api/rdmaxf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdmaxf.Tpo $(DEPDIR)/libglpk_la-rdmaxf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdmaxf.c' object='libglpk_la-rdmaxf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdmaxf.lo `test -f 'api/rdmaxf.c' || echo '$(srcdir)/'`api/rdmaxf.c + +libglpk_la-rdmcf.lo: api/rdmcf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdmcf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdmcf.Tpo -c -o libglpk_la-rdmcf.lo `test -f 'api/rdmcf.c' || echo '$(srcdir)/'`api/rdmcf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdmcf.Tpo $(DEPDIR)/libglpk_la-rdmcf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdmcf.c' object='libglpk_la-rdmcf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdmcf.lo `test -f 'api/rdmcf.c' || echo '$(srcdir)/'`api/rdmcf.c + +libglpk_la-rdmip.lo: api/rdmip.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdmip.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdmip.Tpo -c -o libglpk_la-rdmip.lo `test -f 'api/rdmip.c' || echo '$(srcdir)/'`api/rdmip.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdmip.Tpo $(DEPDIR)/libglpk_la-rdmip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdmip.c' object='libglpk_la-rdmip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdmip.lo `test -f 'api/rdmip.c' || echo '$(srcdir)/'`api/rdmip.c + +libglpk_la-rdprob.lo: api/rdprob.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdprob.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdprob.Tpo -c -o libglpk_la-rdprob.lo `test -f 'api/rdprob.c' || echo '$(srcdir)/'`api/rdprob.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdprob.Tpo $(DEPDIR)/libglpk_la-rdprob.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdprob.c' object='libglpk_la-rdprob.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdprob.lo `test -f 'api/rdprob.c' || echo '$(srcdir)/'`api/rdprob.c + +libglpk_la-rdsol.lo: api/rdsol.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rdsol.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rdsol.Tpo -c -o libglpk_la-rdsol.lo `test -f 'api/rdsol.c' || echo '$(srcdir)/'`api/rdsol.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rdsol.Tpo $(DEPDIR)/libglpk_la-rdsol.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rdsol.c' object='libglpk_la-rdsol.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rdsol.lo `test -f 'api/rdsol.c' || echo '$(srcdir)/'`api/rdsol.c + +libglpk_la-rmfgen.lo: api/rmfgen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rmfgen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rmfgen.Tpo -c -o libglpk_la-rmfgen.lo `test -f 'api/rmfgen.c' || echo '$(srcdir)/'`api/rmfgen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rmfgen.Tpo $(DEPDIR)/libglpk_la-rmfgen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/rmfgen.c' object='libglpk_la-rmfgen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rmfgen.lo `test -f 'api/rmfgen.c' || echo '$(srcdir)/'`api/rmfgen.c + +libglpk_la-strong.lo: api/strong.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-strong.lo -MD -MP -MF $(DEPDIR)/libglpk_la-strong.Tpo -c -o libglpk_la-strong.lo `test -f 'api/strong.c' || echo '$(srcdir)/'`api/strong.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-strong.Tpo $(DEPDIR)/libglpk_la-strong.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/strong.c' object='libglpk_la-strong.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-strong.lo `test -f 'api/strong.c' || echo '$(srcdir)/'`api/strong.c + +libglpk_la-topsort.lo: api/topsort.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-topsort.lo -MD -MP -MF $(DEPDIR)/libglpk_la-topsort.Tpo -c -o libglpk_la-topsort.lo `test -f 'api/topsort.c' || echo '$(srcdir)/'`api/topsort.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-topsort.Tpo $(DEPDIR)/libglpk_la-topsort.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/topsort.c' object='libglpk_la-topsort.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-topsort.lo `test -f 'api/topsort.c' || echo '$(srcdir)/'`api/topsort.c + +libglpk_la-weak.lo: api/weak.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-weak.lo -MD -MP -MF $(DEPDIR)/libglpk_la-weak.Tpo -c -o libglpk_la-weak.lo `test -f 'api/weak.c' || echo '$(srcdir)/'`api/weak.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-weak.Tpo $(DEPDIR)/libglpk_la-weak.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/weak.c' object='libglpk_la-weak.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-weak.lo `test -f 'api/weak.c' || echo '$(srcdir)/'`api/weak.c + +libglpk_la-wcliqex.lo: api/wcliqex.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wcliqex.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wcliqex.Tpo -c -o libglpk_la-wcliqex.lo `test -f 'api/wcliqex.c' || echo '$(srcdir)/'`api/wcliqex.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wcliqex.Tpo $(DEPDIR)/libglpk_la-wcliqex.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wcliqex.c' object='libglpk_la-wcliqex.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wcliqex.lo `test -f 'api/wcliqex.c' || echo '$(srcdir)/'`api/wcliqex.c + +libglpk_la-wrasn.lo: api/wrasn.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrasn.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrasn.Tpo -c -o libglpk_la-wrasn.lo `test -f 'api/wrasn.c' || echo '$(srcdir)/'`api/wrasn.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrasn.Tpo $(DEPDIR)/libglpk_la-wrasn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrasn.c' object='libglpk_la-wrasn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrasn.lo `test -f 'api/wrasn.c' || echo '$(srcdir)/'`api/wrasn.c + +libglpk_la-wrcc.lo: api/wrcc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrcc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrcc.Tpo -c -o libglpk_la-wrcc.lo `test -f 'api/wrcc.c' || echo '$(srcdir)/'`api/wrcc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrcc.Tpo $(DEPDIR)/libglpk_la-wrcc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrcc.c' object='libglpk_la-wrcc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrcc.lo `test -f 'api/wrcc.c' || echo '$(srcdir)/'`api/wrcc.c + +libglpk_la-wrcnf.lo: api/wrcnf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrcnf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrcnf.Tpo -c -o libglpk_la-wrcnf.lo `test -f 'api/wrcnf.c' || echo '$(srcdir)/'`api/wrcnf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrcnf.Tpo $(DEPDIR)/libglpk_la-wrcnf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrcnf.c' object='libglpk_la-wrcnf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrcnf.lo `test -f 'api/wrcnf.c' || echo '$(srcdir)/'`api/wrcnf.c + +libglpk_la-wript.lo: api/wript.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wript.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wript.Tpo -c -o libglpk_la-wript.lo `test -f 'api/wript.c' || echo '$(srcdir)/'`api/wript.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wript.Tpo $(DEPDIR)/libglpk_la-wript.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wript.c' object='libglpk_la-wript.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wript.lo `test -f 'api/wript.c' || echo '$(srcdir)/'`api/wript.c + +libglpk_la-wrmaxf.lo: api/wrmaxf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrmaxf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrmaxf.Tpo -c -o libglpk_la-wrmaxf.lo `test -f 'api/wrmaxf.c' || echo '$(srcdir)/'`api/wrmaxf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrmaxf.Tpo $(DEPDIR)/libglpk_la-wrmaxf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrmaxf.c' object='libglpk_la-wrmaxf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrmaxf.lo `test -f 'api/wrmaxf.c' || echo '$(srcdir)/'`api/wrmaxf.c + +libglpk_la-wrmcf.lo: api/wrmcf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrmcf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrmcf.Tpo -c -o libglpk_la-wrmcf.lo `test -f 'api/wrmcf.c' || echo '$(srcdir)/'`api/wrmcf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrmcf.Tpo $(DEPDIR)/libglpk_la-wrmcf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrmcf.c' object='libglpk_la-wrmcf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrmcf.lo `test -f 'api/wrmcf.c' || echo '$(srcdir)/'`api/wrmcf.c + +libglpk_la-wrmip.lo: api/wrmip.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrmip.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrmip.Tpo -c -o libglpk_la-wrmip.lo `test -f 'api/wrmip.c' || echo '$(srcdir)/'`api/wrmip.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrmip.Tpo $(DEPDIR)/libglpk_la-wrmip.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrmip.c' object='libglpk_la-wrmip.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrmip.lo `test -f 'api/wrmip.c' || echo '$(srcdir)/'`api/wrmip.c + +libglpk_la-wrprob.lo: api/wrprob.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrprob.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrprob.Tpo -c -o libglpk_la-wrprob.lo `test -f 'api/wrprob.c' || echo '$(srcdir)/'`api/wrprob.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrprob.Tpo $(DEPDIR)/libglpk_la-wrprob.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrprob.c' object='libglpk_la-wrprob.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrprob.lo `test -f 'api/wrprob.c' || echo '$(srcdir)/'`api/wrprob.c + +libglpk_la-wrsol.lo: api/wrsol.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wrsol.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wrsol.Tpo -c -o libglpk_la-wrsol.lo `test -f 'api/wrsol.c' || echo '$(srcdir)/'`api/wrsol.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wrsol.Tpo $(DEPDIR)/libglpk_la-wrsol.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='api/wrsol.c' object='libglpk_la-wrsol.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wrsol.lo `test -f 'api/wrsol.c' || echo '$(srcdir)/'`api/wrsol.c + +libglpk_la-btf.lo: bflib/btf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-btf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-btf.Tpo -c -o libglpk_la-btf.lo `test -f 'bflib/btf.c' || echo '$(srcdir)/'`bflib/btf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-btf.Tpo $(DEPDIR)/libglpk_la-btf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/btf.c' object='libglpk_la-btf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-btf.lo `test -f 'bflib/btf.c' || echo '$(srcdir)/'`bflib/btf.c + +libglpk_la-btfint.lo: bflib/btfint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-btfint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-btfint.Tpo -c -o libglpk_la-btfint.lo `test -f 'bflib/btfint.c' || echo '$(srcdir)/'`bflib/btfint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-btfint.Tpo $(DEPDIR)/libglpk_la-btfint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/btfint.c' object='libglpk_la-btfint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-btfint.lo `test -f 'bflib/btfint.c' || echo '$(srcdir)/'`bflib/btfint.c + +libglpk_la-fhv.lo: bflib/fhv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhv.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhv.Tpo -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhv.Tpo $(DEPDIR)/libglpk_la-fhv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhv.c' object='libglpk_la-fhv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c + +libglpk_la-fhvint.lo: bflib/fhvint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhvint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhvint.Tpo -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhvint.Tpo $(DEPDIR)/libglpk_la-fhvint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhvint.c' object='libglpk_la-fhvint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c + +libglpk_la-ifu.lo: bflib/ifu.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ifu.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ifu.Tpo -c -o libglpk_la-ifu.lo `test -f 'bflib/ifu.c' || echo '$(srcdir)/'`bflib/ifu.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ifu.Tpo $(DEPDIR)/libglpk_la-ifu.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/ifu.c' object='libglpk_la-ifu.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ifu.lo `test -f 'bflib/ifu.c' || echo '$(srcdir)/'`bflib/ifu.c + +libglpk_la-luf.lo: bflib/luf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-luf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-luf.Tpo -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-luf.Tpo $(DEPDIR)/libglpk_la-luf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/luf.c' object='libglpk_la-luf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c + +libglpk_la-lufint.lo: bflib/lufint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lufint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lufint.Tpo -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lufint.Tpo $(DEPDIR)/libglpk_la-lufint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/lufint.c' object='libglpk_la-lufint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c + +libglpk_la-scf.lo: bflib/scf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-scf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-scf.Tpo -c -o libglpk_la-scf.lo `test -f 'bflib/scf.c' || echo '$(srcdir)/'`bflib/scf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-scf.Tpo $(DEPDIR)/libglpk_la-scf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/scf.c' object='libglpk_la-scf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-scf.lo `test -f 'bflib/scf.c' || echo '$(srcdir)/'`bflib/scf.c + +libglpk_la-scfint.lo: bflib/scfint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-scfint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-scfint.Tpo -c -o libglpk_la-scfint.lo `test -f 'bflib/scfint.c' || echo '$(srcdir)/'`bflib/scfint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-scfint.Tpo $(DEPDIR)/libglpk_la-scfint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/scfint.c' object='libglpk_la-scfint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-scfint.lo `test -f 'bflib/scfint.c' || echo '$(srcdir)/'`bflib/scfint.c + +libglpk_la-sgf.lo: bflib/sgf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sgf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sgf.Tpo -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sgf.Tpo $(DEPDIR)/libglpk_la-sgf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sgf.c' object='libglpk_la-sgf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c + +libglpk_la-sva.lo: bflib/sva.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sva.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sva.Tpo -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sva.Tpo $(DEPDIR)/libglpk_la-sva.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sva.c' object='libglpk_la-sva.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c + +libglpk_la-colamd.lo: colamd/colamd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-colamd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-colamd.Tpo -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-colamd.Tpo $(DEPDIR)/libglpk_la-colamd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colamd/colamd.c' object='libglpk_la-colamd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c + +libglpk_la-bfd.lo: draft/bfd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bfd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bfd.Tpo -c -o libglpk_la-bfd.lo `test -f 'draft/bfd.c' || echo '$(srcdir)/'`draft/bfd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bfd.Tpo $(DEPDIR)/libglpk_la-bfd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/bfd.c' object='libglpk_la-bfd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bfd.lo `test -f 'draft/bfd.c' || echo '$(srcdir)/'`draft/bfd.c + +libglpk_la-bfx.lo: draft/bfx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bfx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bfx.Tpo -c -o libglpk_la-bfx.lo `test -f 'draft/bfx.c' || echo '$(srcdir)/'`draft/bfx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bfx.Tpo $(DEPDIR)/libglpk_la-bfx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/bfx.c' object='libglpk_la-bfx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bfx.lo `test -f 'draft/bfx.c' || echo '$(srcdir)/'`draft/bfx.c + +libglpk_la-glpapi06.lo: draft/glpapi06.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi06.Tpo -c -o libglpk_la-glpapi06.lo `test -f 'draft/glpapi06.c' || echo '$(srcdir)/'`draft/glpapi06.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi06.Tpo $(DEPDIR)/libglpk_la-glpapi06.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi06.c' object='libglpk_la-glpapi06.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi06.lo `test -f 'draft/glpapi06.c' || echo '$(srcdir)/'`draft/glpapi06.c + +libglpk_la-glpapi07.lo: draft/glpapi07.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi07.Tpo -c -o libglpk_la-glpapi07.lo `test -f 'draft/glpapi07.c' || echo '$(srcdir)/'`draft/glpapi07.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi07.Tpo $(DEPDIR)/libglpk_la-glpapi07.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi07.c' object='libglpk_la-glpapi07.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi07.lo `test -f 'draft/glpapi07.c' || echo '$(srcdir)/'`draft/glpapi07.c + +libglpk_la-glpapi08.lo: draft/glpapi08.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi08.Tpo -c -o libglpk_la-glpapi08.lo `test -f 'draft/glpapi08.c' || echo '$(srcdir)/'`draft/glpapi08.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi08.Tpo $(DEPDIR)/libglpk_la-glpapi08.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi08.c' object='libglpk_la-glpapi08.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi08.lo `test -f 'draft/glpapi08.c' || echo '$(srcdir)/'`draft/glpapi08.c + +libglpk_la-glpapi09.lo: draft/glpapi09.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi09.Tpo -c -o libglpk_la-glpapi09.lo `test -f 'draft/glpapi09.c' || echo '$(srcdir)/'`draft/glpapi09.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi09.Tpo $(DEPDIR)/libglpk_la-glpapi09.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi09.c' object='libglpk_la-glpapi09.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi09.lo `test -f 'draft/glpapi09.c' || echo '$(srcdir)/'`draft/glpapi09.c + +libglpk_la-glpapi10.lo: draft/glpapi10.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi10.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi10.Tpo -c -o libglpk_la-glpapi10.lo `test -f 'draft/glpapi10.c' || echo '$(srcdir)/'`draft/glpapi10.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi10.Tpo $(DEPDIR)/libglpk_la-glpapi10.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi10.c' object='libglpk_la-glpapi10.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi10.lo `test -f 'draft/glpapi10.c' || echo '$(srcdir)/'`draft/glpapi10.c + +libglpk_la-glpapi12.lo: draft/glpapi12.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi12.Tpo -c -o libglpk_la-glpapi12.lo `test -f 'draft/glpapi12.c' || echo '$(srcdir)/'`draft/glpapi12.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi12.Tpo $(DEPDIR)/libglpk_la-glpapi12.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi12.c' object='libglpk_la-glpapi12.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi12.lo `test -f 'draft/glpapi12.c' || echo '$(srcdir)/'`draft/glpapi12.c + +libglpk_la-glpapi13.lo: draft/glpapi13.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi13.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi13.Tpo -c -o libglpk_la-glpapi13.lo `test -f 'draft/glpapi13.c' || echo '$(srcdir)/'`draft/glpapi13.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi13.Tpo $(DEPDIR)/libglpk_la-glpapi13.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpapi13.c' object='libglpk_la-glpapi13.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi13.lo `test -f 'draft/glpapi13.c' || echo '$(srcdir)/'`draft/glpapi13.c + +libglpk_la-glphbm.lo: draft/glphbm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glphbm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glphbm.Tpo -c -o libglpk_la-glphbm.lo `test -f 'draft/glphbm.c' || echo '$(srcdir)/'`draft/glphbm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glphbm.Tpo $(DEPDIR)/libglpk_la-glphbm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glphbm.c' object='libglpk_la-glphbm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glphbm.lo `test -f 'draft/glphbm.c' || echo '$(srcdir)/'`draft/glphbm.c + +libglpk_la-glpios01.lo: draft/glpios01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios01.Tpo -c -o libglpk_la-glpios01.lo `test -f 'draft/glpios01.c' || echo '$(srcdir)/'`draft/glpios01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios01.Tpo $(DEPDIR)/libglpk_la-glpios01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios01.c' object='libglpk_la-glpios01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios01.lo `test -f 'draft/glpios01.c' || echo '$(srcdir)/'`draft/glpios01.c + +libglpk_la-glpios02.lo: draft/glpios02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios02.Tpo -c -o libglpk_la-glpios02.lo `test -f 'draft/glpios02.c' || echo '$(srcdir)/'`draft/glpios02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios02.Tpo $(DEPDIR)/libglpk_la-glpios02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios02.c' object='libglpk_la-glpios02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios02.lo `test -f 'draft/glpios02.c' || echo '$(srcdir)/'`draft/glpios02.c + +libglpk_la-glpios03.lo: draft/glpios03.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios03.Tpo -c -o libglpk_la-glpios03.lo `test -f 'draft/glpios03.c' || echo '$(srcdir)/'`draft/glpios03.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios03.Tpo $(DEPDIR)/libglpk_la-glpios03.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios03.c' object='libglpk_la-glpios03.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios03.lo `test -f 'draft/glpios03.c' || echo '$(srcdir)/'`draft/glpios03.c + +libglpk_la-glpios07.lo: draft/glpios07.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios07.Tpo -c -o libglpk_la-glpios07.lo `test -f 'draft/glpios07.c' || echo '$(srcdir)/'`draft/glpios07.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios07.Tpo $(DEPDIR)/libglpk_la-glpios07.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios07.c' object='libglpk_la-glpios07.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios07.lo `test -f 'draft/glpios07.c' || echo '$(srcdir)/'`draft/glpios07.c + +libglpk_la-glpios09.lo: draft/glpios09.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios09.Tpo -c -o libglpk_la-glpios09.lo `test -f 'draft/glpios09.c' || echo '$(srcdir)/'`draft/glpios09.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios09.Tpo $(DEPDIR)/libglpk_la-glpios09.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios09.c' object='libglpk_la-glpios09.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios09.lo `test -f 'draft/glpios09.c' || echo '$(srcdir)/'`draft/glpios09.c + +libglpk_la-glpios11.lo: draft/glpios11.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios11.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios11.Tpo -c -o libglpk_la-glpios11.lo `test -f 'draft/glpios11.c' || echo '$(srcdir)/'`draft/glpios11.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios11.Tpo $(DEPDIR)/libglpk_la-glpios11.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios11.c' object='libglpk_la-glpios11.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios11.lo `test -f 'draft/glpios11.c' || echo '$(srcdir)/'`draft/glpios11.c + +libglpk_la-glpios12.lo: draft/glpios12.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios12.Tpo -c -o libglpk_la-glpios12.lo `test -f 'draft/glpios12.c' || echo '$(srcdir)/'`draft/glpios12.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios12.Tpo $(DEPDIR)/libglpk_la-glpios12.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpios12.c' object='libglpk_la-glpios12.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios12.lo `test -f 'draft/glpios12.c' || echo '$(srcdir)/'`draft/glpios12.c + +libglpk_la-glpipm.lo: draft/glpipm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpipm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpipm.Tpo -c -o libglpk_la-glpipm.lo `test -f 'draft/glpipm.c' || echo '$(srcdir)/'`draft/glpipm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpipm.Tpo $(DEPDIR)/libglpk_la-glpipm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpipm.c' object='libglpk_la-glpipm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpipm.lo `test -f 'draft/glpipm.c' || echo '$(srcdir)/'`draft/glpipm.c + +libglpk_la-glpmat.lo: draft/glpmat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmat.Tpo -c -o libglpk_la-glpmat.lo `test -f 'draft/glpmat.c' || echo '$(srcdir)/'`draft/glpmat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmat.Tpo $(DEPDIR)/libglpk_la-glpmat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpmat.c' object='libglpk_la-glpmat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmat.lo `test -f 'draft/glpmat.c' || echo '$(srcdir)/'`draft/glpmat.c + +libglpk_la-glprgr.lo: draft/glprgr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glprgr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glprgr.Tpo -c -o libglpk_la-glprgr.lo `test -f 'draft/glprgr.c' || echo '$(srcdir)/'`draft/glprgr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glprgr.Tpo $(DEPDIR)/libglpk_la-glprgr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glprgr.c' object='libglpk_la-glprgr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glprgr.lo `test -f 'draft/glprgr.c' || echo '$(srcdir)/'`draft/glprgr.c + +libglpk_la-glpscl.lo: draft/glpscl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpscl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpscl.Tpo -c -o libglpk_la-glpscl.lo `test -f 'draft/glpscl.c' || echo '$(srcdir)/'`draft/glpscl.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpscl.Tpo $(DEPDIR)/libglpk_la-glpscl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpscl.c' object='libglpk_la-glpscl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpscl.lo `test -f 'draft/glpscl.c' || echo '$(srcdir)/'`draft/glpscl.c + +libglpk_la-glpspm.lo: draft/glpspm.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspm.Tpo -c -o libglpk_la-glpspm.lo `test -f 'draft/glpspm.c' || echo '$(srcdir)/'`draft/glpspm.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspm.Tpo $(DEPDIR)/libglpk_la-glpspm.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpspm.c' object='libglpk_la-glpspm.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspm.lo `test -f 'draft/glpspm.c' || echo '$(srcdir)/'`draft/glpspm.c + +libglpk_la-glpssx01.lo: draft/glpssx01.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx01.Tpo -c -o libglpk_la-glpssx01.lo `test -f 'draft/glpssx01.c' || echo '$(srcdir)/'`draft/glpssx01.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx01.Tpo $(DEPDIR)/libglpk_la-glpssx01.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpssx01.c' object='libglpk_la-glpssx01.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx01.lo `test -f 'draft/glpssx01.c' || echo '$(srcdir)/'`draft/glpssx01.c + +libglpk_la-glpssx02.lo: draft/glpssx02.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx02.Tpo -c -o libglpk_la-glpssx02.lo `test -f 'draft/glpssx02.c' || echo '$(srcdir)/'`draft/glpssx02.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx02.Tpo $(DEPDIR)/libglpk_la-glpssx02.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/glpssx02.c' object='libglpk_la-glpssx02.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx02.lo `test -f 'draft/glpssx02.c' || echo '$(srcdir)/'`draft/glpssx02.c + +libglpk_la-lux.lo: draft/lux.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lux.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lux.Tpo -c -o libglpk_la-lux.lo `test -f 'draft/lux.c' || echo '$(srcdir)/'`draft/lux.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lux.Tpo $(DEPDIR)/libglpk_la-lux.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='draft/lux.c' object='libglpk_la-lux.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lux.lo `test -f 'draft/lux.c' || echo '$(srcdir)/'`draft/lux.c + +libglpk_la-alloc.lo: env/alloc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-alloc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-alloc.Tpo -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-alloc.Tpo $(DEPDIR)/libglpk_la-alloc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/alloc.c' object='libglpk_la-alloc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c + +libglpk_la-dlsup.lo: env/dlsup.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dlsup.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dlsup.Tpo -c -o libglpk_la-dlsup.lo `test -f 'env/dlsup.c' || echo '$(srcdir)/'`env/dlsup.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dlsup.Tpo $(DEPDIR)/libglpk_la-dlsup.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/dlsup.c' object='libglpk_la-dlsup.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dlsup.lo `test -f 'env/dlsup.c' || echo '$(srcdir)/'`env/dlsup.c + +libglpk_la-env.lo: env/env.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-env.lo -MD -MP -MF $(DEPDIR)/libglpk_la-env.Tpo -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-env.Tpo $(DEPDIR)/libglpk_la-env.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/env.c' object='libglpk_la-env.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c + +libglpk_la-error.lo: env/error.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-error.lo -MD -MP -MF $(DEPDIR)/libglpk_la-error.Tpo -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-error.Tpo $(DEPDIR)/libglpk_la-error.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/error.c' object='libglpk_la-error.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c + +libglpk_la-stdc.lo: env/stdc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stdc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stdc.Tpo -c -o libglpk_la-stdc.lo `test -f 'env/stdc.c' || echo '$(srcdir)/'`env/stdc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stdc.Tpo $(DEPDIR)/libglpk_la-stdc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stdc.c' object='libglpk_la-stdc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stdc.lo `test -f 'env/stdc.c' || echo '$(srcdir)/'`env/stdc.c + +libglpk_la-stdout.lo: env/stdout.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stdout.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stdout.Tpo -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stdout.Tpo $(DEPDIR)/libglpk_la-stdout.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stdout.c' object='libglpk_la-stdout.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c + +libglpk_la-stream.lo: env/stream.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stream.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stream.Tpo -c -o libglpk_la-stream.lo `test -f 'env/stream.c' || echo '$(srcdir)/'`env/stream.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stream.Tpo $(DEPDIR)/libglpk_la-stream.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stream.c' object='libglpk_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stream.lo `test -f 'env/stream.c' || echo '$(srcdir)/'`env/stream.c + +libglpk_la-time.lo: env/time.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-time.lo -MD -MP -MF $(DEPDIR)/libglpk_la-time.Tpo -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-time.Tpo $(DEPDIR)/libglpk_la-time.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/time.c' object='libglpk_la-time.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c + +libglpk_la-tls.lo: env/tls.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-tls.lo -MD -MP -MF $(DEPDIR)/libglpk_la-tls.Tpo -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-tls.Tpo $(DEPDIR)/libglpk_la-tls.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/tls.c' object='libglpk_la-tls.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c + +libglpk_la-cfg.lo: intopt/cfg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg.Tpo -c -o libglpk_la-cfg.lo `test -f 'intopt/cfg.c' || echo '$(srcdir)/'`intopt/cfg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg.Tpo $(DEPDIR)/libglpk_la-cfg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/cfg.c' object='libglpk_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg.lo `test -f 'intopt/cfg.c' || echo '$(srcdir)/'`intopt/cfg.c + +libglpk_la-cfg1.lo: intopt/cfg1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg1.Tpo -c -o libglpk_la-cfg1.lo `test -f 'intopt/cfg1.c' || echo '$(srcdir)/'`intopt/cfg1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg1.Tpo $(DEPDIR)/libglpk_la-cfg1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/cfg1.c' object='libglpk_la-cfg1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg1.lo `test -f 'intopt/cfg1.c' || echo '$(srcdir)/'`intopt/cfg1.c + +libglpk_la-cfg2.lo: intopt/cfg2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg2.Tpo -c -o libglpk_la-cfg2.lo `test -f 'intopt/cfg2.c' || echo '$(srcdir)/'`intopt/cfg2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg2.Tpo $(DEPDIR)/libglpk_la-cfg2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/cfg2.c' object='libglpk_la-cfg2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg2.lo `test -f 'intopt/cfg2.c' || echo '$(srcdir)/'`intopt/cfg2.c + +libglpk_la-clqcut.lo: intopt/clqcut.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-clqcut.lo -MD -MP -MF $(DEPDIR)/libglpk_la-clqcut.Tpo -c -o libglpk_la-clqcut.lo `test -f 'intopt/clqcut.c' || echo '$(srcdir)/'`intopt/clqcut.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-clqcut.Tpo $(DEPDIR)/libglpk_la-clqcut.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/clqcut.c' object='libglpk_la-clqcut.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-clqcut.lo `test -f 'intopt/clqcut.c' || echo '$(srcdir)/'`intopt/clqcut.c + +libglpk_la-covgen.lo: intopt/covgen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-covgen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-covgen.Tpo -c -o libglpk_la-covgen.lo `test -f 'intopt/covgen.c' || echo '$(srcdir)/'`intopt/covgen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-covgen.Tpo $(DEPDIR)/libglpk_la-covgen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/covgen.c' object='libglpk_la-covgen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-covgen.lo `test -f 'intopt/covgen.c' || echo '$(srcdir)/'`intopt/covgen.c + +libglpk_la-fpump.lo: intopt/fpump.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fpump.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fpump.Tpo -c -o libglpk_la-fpump.lo `test -f 'intopt/fpump.c' || echo '$(srcdir)/'`intopt/fpump.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fpump.Tpo $(DEPDIR)/libglpk_la-fpump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/fpump.c' object='libglpk_la-fpump.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fpump.lo `test -f 'intopt/fpump.c' || echo '$(srcdir)/'`intopt/fpump.c + +libglpk_la-gmicut.lo: intopt/gmicut.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gmicut.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gmicut.Tpo -c -o libglpk_la-gmicut.lo `test -f 'intopt/gmicut.c' || echo '$(srcdir)/'`intopt/gmicut.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gmicut.Tpo $(DEPDIR)/libglpk_la-gmicut.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/gmicut.c' object='libglpk_la-gmicut.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gmicut.lo `test -f 'intopt/gmicut.c' || echo '$(srcdir)/'`intopt/gmicut.c + +libglpk_la-gmigen.lo: intopt/gmigen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gmigen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gmigen.Tpo -c -o libglpk_la-gmigen.lo `test -f 'intopt/gmigen.c' || echo '$(srcdir)/'`intopt/gmigen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gmigen.Tpo $(DEPDIR)/libglpk_la-gmigen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/gmigen.c' object='libglpk_la-gmigen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gmigen.lo `test -f 'intopt/gmigen.c' || echo '$(srcdir)/'`intopt/gmigen.c + +libglpk_la-mirgen.lo: intopt/mirgen.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mirgen.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mirgen.Tpo -c -o libglpk_la-mirgen.lo `test -f 'intopt/mirgen.c' || echo '$(srcdir)/'`intopt/mirgen.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mirgen.Tpo $(DEPDIR)/libglpk_la-mirgen.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/mirgen.c' object='libglpk_la-mirgen.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mirgen.lo `test -f 'intopt/mirgen.c' || echo '$(srcdir)/'`intopt/mirgen.c + +libglpk_la-spv.lo: intopt/spv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spv.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spv.Tpo -c -o libglpk_la-spv.lo `test -f 'intopt/spv.c' || echo '$(srcdir)/'`intopt/spv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spv.Tpo $(DEPDIR)/libglpk_la-spv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='intopt/spv.c' object='libglpk_la-spv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spv.lo `test -f 'intopt/spv.c' || echo '$(srcdir)/'`intopt/spv.c + +libglpk_la-minisat.lo: minisat/minisat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-minisat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-minisat.Tpo -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-minisat.Tpo $(DEPDIR)/libglpk_la-minisat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='minisat/minisat.c' object='libglpk_la-minisat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c + +libglpk_la-avl.lo: misc/avl.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-avl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-avl.Tpo -c -o libglpk_la-avl.lo `test -f 'misc/avl.c' || echo '$(srcdir)/'`misc/avl.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-avl.Tpo $(DEPDIR)/libglpk_la-avl.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/avl.c' object='libglpk_la-avl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-avl.lo `test -f 'misc/avl.c' || echo '$(srcdir)/'`misc/avl.c + +libglpk_la-bignum.lo: misc/bignum.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bignum.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bignum.Tpo -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bignum.Tpo $(DEPDIR)/libglpk_la-bignum.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/bignum.c' object='libglpk_la-bignum.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c + +libglpk_la-dimacs.lo: misc/dimacs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dimacs.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dimacs.Tpo -c -o libglpk_la-dimacs.lo `test -f 'misc/dimacs.c' || echo '$(srcdir)/'`misc/dimacs.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dimacs.Tpo $(DEPDIR)/libglpk_la-dimacs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/dimacs.c' object='libglpk_la-dimacs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dimacs.lo `test -f 'misc/dimacs.c' || echo '$(srcdir)/'`misc/dimacs.c + +libglpk_la-dmp.lo: misc/dmp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dmp.Tpo -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dmp.Tpo $(DEPDIR)/libglpk_la-dmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/dmp.c' object='libglpk_la-dmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c + +libglpk_la-ffalg.lo: misc/ffalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ffalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ffalg.Tpo -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ffalg.Tpo $(DEPDIR)/libglpk_la-ffalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/ffalg.c' object='libglpk_la-ffalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c + +libglpk_la-fp2rat.lo: misc/fp2rat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fp2rat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fp2rat.Tpo -c -o libglpk_la-fp2rat.lo `test -f 'misc/fp2rat.c' || echo '$(srcdir)/'`misc/fp2rat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fp2rat.Tpo $(DEPDIR)/libglpk_la-fp2rat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/fp2rat.c' object='libglpk_la-fp2rat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fp2rat.lo `test -f 'misc/fp2rat.c' || echo '$(srcdir)/'`misc/fp2rat.c + +libglpk_la-fvs.lo: misc/fvs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fvs.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fvs.Tpo -c -o libglpk_la-fvs.lo `test -f 'misc/fvs.c' || echo '$(srcdir)/'`misc/fvs.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fvs.Tpo $(DEPDIR)/libglpk_la-fvs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/fvs.c' object='libglpk_la-fvs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fvs.lo `test -f 'misc/fvs.c' || echo '$(srcdir)/'`misc/fvs.c + +libglpk_la-gcd.lo: misc/gcd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gcd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gcd.Tpo -c -o libglpk_la-gcd.lo `test -f 'misc/gcd.c' || echo '$(srcdir)/'`misc/gcd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gcd.Tpo $(DEPDIR)/libglpk_la-gcd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/gcd.c' object='libglpk_la-gcd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gcd.lo `test -f 'misc/gcd.c' || echo '$(srcdir)/'`misc/gcd.c + +libglpk_la-jd.lo: misc/jd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-jd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-jd.Tpo -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-jd.Tpo $(DEPDIR)/libglpk_la-jd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/jd.c' object='libglpk_la-jd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c + +libglpk_la-keller.lo: misc/keller.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-keller.lo -MD -MP -MF $(DEPDIR)/libglpk_la-keller.Tpo -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-keller.Tpo $(DEPDIR)/libglpk_la-keller.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/keller.c' object='libglpk_la-keller.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c + +libglpk_la-ks.lo: misc/ks.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ks.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ks.Tpo -c -o libglpk_la-ks.lo `test -f 'misc/ks.c' || echo '$(srcdir)/'`misc/ks.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ks.Tpo $(DEPDIR)/libglpk_la-ks.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/ks.c' object='libglpk_la-ks.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ks.lo `test -f 'misc/ks.c' || echo '$(srcdir)/'`misc/ks.c + +libglpk_la-mc13d.lo: misc/mc13d.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc13d.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc13d.Tpo -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc13d.Tpo $(DEPDIR)/libglpk_la-mc13d.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc13d.c' object='libglpk_la-mc13d.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c + +libglpk_la-mc21a.lo: misc/mc21a.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc21a.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc21a.Tpo -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc21a.Tpo $(DEPDIR)/libglpk_la-mc21a.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc21a.c' object='libglpk_la-mc21a.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c + +libglpk_la-mt1.lo: misc/mt1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mt1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mt1.Tpo -c -o libglpk_la-mt1.lo `test -f 'misc/mt1.c' || echo '$(srcdir)/'`misc/mt1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mt1.Tpo $(DEPDIR)/libglpk_la-mt1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mt1.c' object='libglpk_la-mt1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mt1.lo `test -f 'misc/mt1.c' || echo '$(srcdir)/'`misc/mt1.c + +libglpk_la-mygmp.lo: misc/mygmp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mygmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mygmp.Tpo -c -o libglpk_la-mygmp.lo `test -f 'misc/mygmp.c' || echo '$(srcdir)/'`misc/mygmp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mygmp.Tpo $(DEPDIR)/libglpk_la-mygmp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mygmp.c' object='libglpk_la-mygmp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mygmp.lo `test -f 'misc/mygmp.c' || echo '$(srcdir)/'`misc/mygmp.c + +libglpk_la-okalg.lo: misc/okalg.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-okalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-okalg.Tpo -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-okalg.Tpo $(DEPDIR)/libglpk_la-okalg.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/okalg.c' object='libglpk_la-okalg.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c + +libglpk_la-qmd.lo: misc/qmd.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-qmd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-qmd.Tpo -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-qmd.Tpo $(DEPDIR)/libglpk_la-qmd.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/qmd.c' object='libglpk_la-qmd.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c + +libglpk_la-relax4.lo: misc/relax4.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-relax4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-relax4.Tpo -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-relax4.Tpo $(DEPDIR)/libglpk_la-relax4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/relax4.c' object='libglpk_la-relax4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c + +libglpk_la-rng.lo: misc/rng.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng.Tpo -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng.Tpo $(DEPDIR)/libglpk_la-rng.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng.c' object='libglpk_la-rng.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c + +libglpk_la-rng1.lo: misc/rng1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng1.Tpo -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng1.Tpo $(DEPDIR)/libglpk_la-rng1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng1.c' object='libglpk_la-rng1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c + +libglpk_la-round2n.lo: misc/round2n.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-round2n.lo -MD -MP -MF $(DEPDIR)/libglpk_la-round2n.Tpo -c -o libglpk_la-round2n.lo `test -f 'misc/round2n.c' || echo '$(srcdir)/'`misc/round2n.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-round2n.Tpo $(DEPDIR)/libglpk_la-round2n.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/round2n.c' object='libglpk_la-round2n.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-round2n.lo `test -f 'misc/round2n.c' || echo '$(srcdir)/'`misc/round2n.c + +libglpk_la-str2int.lo: misc/str2int.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-str2int.lo -MD -MP -MF $(DEPDIR)/libglpk_la-str2int.Tpo -c -o libglpk_la-str2int.lo `test -f 'misc/str2int.c' || echo '$(srcdir)/'`misc/str2int.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-str2int.Tpo $(DEPDIR)/libglpk_la-str2int.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/str2int.c' object='libglpk_la-str2int.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-str2int.lo `test -f 'misc/str2int.c' || echo '$(srcdir)/'`misc/str2int.c + +libglpk_la-str2num.lo: misc/str2num.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-str2num.lo -MD -MP -MF $(DEPDIR)/libglpk_la-str2num.Tpo -c -o libglpk_la-str2num.lo `test -f 'misc/str2num.c' || echo '$(srcdir)/'`misc/str2num.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-str2num.Tpo $(DEPDIR)/libglpk_la-str2num.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/str2num.c' object='libglpk_la-str2num.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-str2num.lo `test -f 'misc/str2num.c' || echo '$(srcdir)/'`misc/str2num.c + +libglpk_la-strspx.lo: misc/strspx.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-strspx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-strspx.Tpo -c -o libglpk_la-strspx.lo `test -f 'misc/strspx.c' || echo '$(srcdir)/'`misc/strspx.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-strspx.Tpo $(DEPDIR)/libglpk_la-strspx.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/strspx.c' object='libglpk_la-strspx.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-strspx.lo `test -f 'misc/strspx.c' || echo '$(srcdir)/'`misc/strspx.c + +libglpk_la-strtrim.lo: misc/strtrim.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-strtrim.lo -MD -MP -MF $(DEPDIR)/libglpk_la-strtrim.Tpo -c -o libglpk_la-strtrim.lo `test -f 'misc/strtrim.c' || echo '$(srcdir)/'`misc/strtrim.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-strtrim.Tpo $(DEPDIR)/libglpk_la-strtrim.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/strtrim.c' object='libglpk_la-strtrim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-strtrim.lo `test -f 'misc/strtrim.c' || echo '$(srcdir)/'`misc/strtrim.c + +libglpk_la-triang.lo: misc/triang.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-triang.lo -MD -MP -MF $(DEPDIR)/libglpk_la-triang.Tpo -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-triang.Tpo $(DEPDIR)/libglpk_la-triang.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/triang.c' object='libglpk_la-triang.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c + +libglpk_la-wclique.lo: misc/wclique.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique.Tpo -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique.Tpo $(DEPDIR)/libglpk_la-wclique.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique.c' object='libglpk_la-wclique.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c + +libglpk_la-wclique1.lo: misc/wclique1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique1.Tpo -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique1.Tpo $(DEPDIR)/libglpk_la-wclique1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique1.c' object='libglpk_la-wclique1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c + +libglpk_la-mpl1.lo: mpl/mpl1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl1.Tpo -c -o libglpk_la-mpl1.lo `test -f 'mpl/mpl1.c' || echo '$(srcdir)/'`mpl/mpl1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl1.Tpo $(DEPDIR)/libglpk_la-mpl1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl1.c' object='libglpk_la-mpl1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl1.lo `test -f 'mpl/mpl1.c' || echo '$(srcdir)/'`mpl/mpl1.c + +libglpk_la-mpl2.lo: mpl/mpl2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl2.Tpo -c -o libglpk_la-mpl2.lo `test -f 'mpl/mpl2.c' || echo '$(srcdir)/'`mpl/mpl2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl2.Tpo $(DEPDIR)/libglpk_la-mpl2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl2.c' object='libglpk_la-mpl2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl2.lo `test -f 'mpl/mpl2.c' || echo '$(srcdir)/'`mpl/mpl2.c + +libglpk_la-mpl3.lo: mpl/mpl3.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl3.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl3.Tpo -c -o libglpk_la-mpl3.lo `test -f 'mpl/mpl3.c' || echo '$(srcdir)/'`mpl/mpl3.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl3.Tpo $(DEPDIR)/libglpk_la-mpl3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl3.c' object='libglpk_la-mpl3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl3.lo `test -f 'mpl/mpl3.c' || echo '$(srcdir)/'`mpl/mpl3.c + +libglpk_la-mpl4.lo: mpl/mpl4.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl4.Tpo -c -o libglpk_la-mpl4.lo `test -f 'mpl/mpl4.c' || echo '$(srcdir)/'`mpl/mpl4.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl4.Tpo $(DEPDIR)/libglpk_la-mpl4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl4.c' object='libglpk_la-mpl4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl4.lo `test -f 'mpl/mpl4.c' || echo '$(srcdir)/'`mpl/mpl4.c + +libglpk_la-mpl5.lo: mpl/mpl5.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl5.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl5.Tpo -c -o libglpk_la-mpl5.lo `test -f 'mpl/mpl5.c' || echo '$(srcdir)/'`mpl/mpl5.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl5.Tpo $(DEPDIR)/libglpk_la-mpl5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl5.c' object='libglpk_la-mpl5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl5.lo `test -f 'mpl/mpl5.c' || echo '$(srcdir)/'`mpl/mpl5.c + +libglpk_la-mpl6.lo: mpl/mpl6.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mpl6.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mpl6.Tpo -c -o libglpk_la-mpl6.lo `test -f 'mpl/mpl6.c' || echo '$(srcdir)/'`mpl/mpl6.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mpl6.Tpo $(DEPDIR)/libglpk_la-mpl6.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mpl6.c' object='libglpk_la-mpl6.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mpl6.lo `test -f 'mpl/mpl6.c' || echo '$(srcdir)/'`mpl/mpl6.c + +libglpk_la-mplsql.lo: mpl/mplsql.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mplsql.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mplsql.Tpo -c -o libglpk_la-mplsql.lo `test -f 'mpl/mplsql.c' || echo '$(srcdir)/'`mpl/mplsql.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mplsql.Tpo $(DEPDIR)/libglpk_la-mplsql.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mpl/mplsql.c' object='libglpk_la-mplsql.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mplsql.lo `test -f 'mpl/mplsql.c' || echo '$(srcdir)/'`mpl/mplsql.c + +libglpk_la-npp1.lo: npp/npp1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp1.Tpo -c -o libglpk_la-npp1.lo `test -f 'npp/npp1.c' || echo '$(srcdir)/'`npp/npp1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp1.Tpo $(DEPDIR)/libglpk_la-npp1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp1.c' object='libglpk_la-npp1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp1.lo `test -f 'npp/npp1.c' || echo '$(srcdir)/'`npp/npp1.c + +libglpk_la-npp2.lo: npp/npp2.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp2.Tpo -c -o libglpk_la-npp2.lo `test -f 'npp/npp2.c' || echo '$(srcdir)/'`npp/npp2.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp2.Tpo $(DEPDIR)/libglpk_la-npp2.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp2.c' object='libglpk_la-npp2.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp2.lo `test -f 'npp/npp2.c' || echo '$(srcdir)/'`npp/npp2.c + +libglpk_la-npp3.lo: npp/npp3.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp3.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp3.Tpo -c -o libglpk_la-npp3.lo `test -f 'npp/npp3.c' || echo '$(srcdir)/'`npp/npp3.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp3.Tpo $(DEPDIR)/libglpk_la-npp3.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp3.c' object='libglpk_la-npp3.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp3.lo `test -f 'npp/npp3.c' || echo '$(srcdir)/'`npp/npp3.c + +libglpk_la-npp4.lo: npp/npp4.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp4.Tpo -c -o libglpk_la-npp4.lo `test -f 'npp/npp4.c' || echo '$(srcdir)/'`npp/npp4.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp4.Tpo $(DEPDIR)/libglpk_la-npp4.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp4.c' object='libglpk_la-npp4.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp4.lo `test -f 'npp/npp4.c' || echo '$(srcdir)/'`npp/npp4.c + +libglpk_la-npp5.lo: npp/npp5.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp5.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp5.Tpo -c -o libglpk_la-npp5.lo `test -f 'npp/npp5.c' || echo '$(srcdir)/'`npp/npp5.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp5.Tpo $(DEPDIR)/libglpk_la-npp5.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp5.c' object='libglpk_la-npp5.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp5.lo `test -f 'npp/npp5.c' || echo '$(srcdir)/'`npp/npp5.c + +libglpk_la-npp6.lo: npp/npp6.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-npp6.lo -MD -MP -MF $(DEPDIR)/libglpk_la-npp6.Tpo -c -o libglpk_la-npp6.lo `test -f 'npp/npp6.c' || echo '$(srcdir)/'`npp/npp6.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-npp6.Tpo $(DEPDIR)/libglpk_la-npp6.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='npp/npp6.c' object='libglpk_la-npp6.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-npp6.lo `test -f 'npp/npp6.c' || echo '$(srcdir)/'`npp/npp6.c + +libglpk_la-proxy.lo: proxy/proxy.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy.Tpo -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy.Tpo $(DEPDIR)/libglpk_la-proxy.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy.c' object='libglpk_la-proxy.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c + +libglpk_la-proxy1.lo: proxy/proxy1.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy1.Tpo -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy1.Tpo $(DEPDIR)/libglpk_la-proxy1.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy1.c' object='libglpk_la-proxy1.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c + +libglpk_la-spxat.lo: simplex/spxat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxat.Tpo -c -o libglpk_la-spxat.lo `test -f 'simplex/spxat.c' || echo '$(srcdir)/'`simplex/spxat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxat.Tpo $(DEPDIR)/libglpk_la-spxat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxat.c' object='libglpk_la-spxat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxat.lo `test -f 'simplex/spxat.c' || echo '$(srcdir)/'`simplex/spxat.c + +libglpk_la-spxchuzc.lo: simplex/spxchuzc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxchuzc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxchuzc.Tpo -c -o libglpk_la-spxchuzc.lo `test -f 'simplex/spxchuzc.c' || echo '$(srcdir)/'`simplex/spxchuzc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxchuzc.Tpo $(DEPDIR)/libglpk_la-spxchuzc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxchuzc.c' object='libglpk_la-spxchuzc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxchuzc.lo `test -f 'simplex/spxchuzc.c' || echo '$(srcdir)/'`simplex/spxchuzc.c + +libglpk_la-spxchuzr.lo: simplex/spxchuzr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxchuzr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxchuzr.Tpo -c -o libglpk_la-spxchuzr.lo `test -f 'simplex/spxchuzr.c' || echo '$(srcdir)/'`simplex/spxchuzr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxchuzr.Tpo $(DEPDIR)/libglpk_la-spxchuzr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxchuzr.c' object='libglpk_la-spxchuzr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxchuzr.lo `test -f 'simplex/spxchuzr.c' || echo '$(srcdir)/'`simplex/spxchuzr.c + +libglpk_la-spxlp.lo: simplex/spxlp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxlp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxlp.Tpo -c -o libglpk_la-spxlp.lo `test -f 'simplex/spxlp.c' || echo '$(srcdir)/'`simplex/spxlp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxlp.Tpo $(DEPDIR)/libglpk_la-spxlp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxlp.c' object='libglpk_la-spxlp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxlp.lo `test -f 'simplex/spxlp.c' || echo '$(srcdir)/'`simplex/spxlp.c + +libglpk_la-spxnt.lo: simplex/spxnt.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxnt.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxnt.Tpo -c -o libglpk_la-spxnt.lo `test -f 'simplex/spxnt.c' || echo '$(srcdir)/'`simplex/spxnt.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxnt.Tpo $(DEPDIR)/libglpk_la-spxnt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxnt.c' object='libglpk_la-spxnt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxnt.lo `test -f 'simplex/spxnt.c' || echo '$(srcdir)/'`simplex/spxnt.c + +libglpk_la-spxprim.lo: simplex/spxprim.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxprim.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxprim.Tpo -c -o libglpk_la-spxprim.lo `test -f 'simplex/spxprim.c' || echo '$(srcdir)/'`simplex/spxprim.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxprim.Tpo $(DEPDIR)/libglpk_la-spxprim.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxprim.c' object='libglpk_la-spxprim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxprim.lo `test -f 'simplex/spxprim.c' || echo '$(srcdir)/'`simplex/spxprim.c + +libglpk_la-spxprob.lo: simplex/spxprob.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxprob.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxprob.Tpo -c -o libglpk_la-spxprob.lo `test -f 'simplex/spxprob.c' || echo '$(srcdir)/'`simplex/spxprob.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxprob.Tpo $(DEPDIR)/libglpk_la-spxprob.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxprob.c' object='libglpk_la-spxprob.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxprob.lo `test -f 'simplex/spxprob.c' || echo '$(srcdir)/'`simplex/spxprob.c + +libglpk_la-spychuzc.lo: simplex/spychuzc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spychuzc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spychuzc.Tpo -c -o libglpk_la-spychuzc.lo `test -f 'simplex/spychuzc.c' || echo '$(srcdir)/'`simplex/spychuzc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spychuzc.Tpo $(DEPDIR)/libglpk_la-spychuzc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spychuzc.c' object='libglpk_la-spychuzc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spychuzc.lo `test -f 'simplex/spychuzc.c' || echo '$(srcdir)/'`simplex/spychuzc.c + +libglpk_la-spychuzr.lo: simplex/spychuzr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spychuzr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spychuzr.Tpo -c -o libglpk_la-spychuzr.lo `test -f 'simplex/spychuzr.c' || echo '$(srcdir)/'`simplex/spychuzr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spychuzr.Tpo $(DEPDIR)/libglpk_la-spychuzr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spychuzr.c' object='libglpk_la-spychuzr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spychuzr.lo `test -f 'simplex/spychuzr.c' || echo '$(srcdir)/'`simplex/spychuzr.c + +libglpk_la-spydual.lo: simplex/spydual.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spydual.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spydual.Tpo -c -o libglpk_la-spydual.lo `test -f 'simplex/spydual.c' || echo '$(srcdir)/'`simplex/spydual.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spydual.Tpo $(DEPDIR)/libglpk_la-spydual.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spydual.c' object='libglpk_la-spydual.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spydual.lo `test -f 'simplex/spydual.c' || echo '$(srcdir)/'`simplex/spydual.c + +libglpk_la-adler32.lo: zlib/adler32.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-adler32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-adler32.Tpo -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-adler32.Tpo $(DEPDIR)/libglpk_la-adler32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/adler32.c' object='libglpk_la-adler32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c + +libglpk_la-compress.lo: zlib/compress.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-compress.lo -MD -MP -MF $(DEPDIR)/libglpk_la-compress.Tpo -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-compress.Tpo $(DEPDIR)/libglpk_la-compress.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/compress.c' object='libglpk_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c + +libglpk_la-crc32.lo: zlib/crc32.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-crc32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-crc32.Tpo -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-crc32.Tpo $(DEPDIR)/libglpk_la-crc32.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/crc32.c' object='libglpk_la-crc32.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c + +libglpk_la-deflate.lo: zlib/deflate.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-deflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-deflate.Tpo -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-deflate.Tpo $(DEPDIR)/libglpk_la-deflate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/deflate.c' object='libglpk_la-deflate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c + +libglpk_la-gzclose.lo: zlib/gzclose.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzclose.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzclose.Tpo -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzclose.Tpo $(DEPDIR)/libglpk_la-gzclose.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzclose.c' object='libglpk_la-gzclose.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c + +libglpk_la-gzlib.lo: zlib/gzlib.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzlib.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzlib.Tpo -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzlib.Tpo $(DEPDIR)/libglpk_la-gzlib.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzlib.c' object='libglpk_la-gzlib.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c + +libglpk_la-gzread.lo: zlib/gzread.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzread.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzread.Tpo -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzread.Tpo $(DEPDIR)/libglpk_la-gzread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzread.c' object='libglpk_la-gzread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c + +libglpk_la-gzwrite.lo: zlib/gzwrite.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzwrite.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzwrite.Tpo -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzwrite.Tpo $(DEPDIR)/libglpk_la-gzwrite.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzwrite.c' object='libglpk_la-gzwrite.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c + +libglpk_la-inffast.lo: zlib/inffast.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inffast.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inffast.Tpo -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inffast.Tpo $(DEPDIR)/libglpk_la-inffast.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inffast.c' object='libglpk_la-inffast.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c + +libglpk_la-inflate.lo: zlib/inflate.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inflate.Tpo -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inflate.Tpo $(DEPDIR)/libglpk_la-inflate.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inflate.c' object='libglpk_la-inflate.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c + +libglpk_la-inftrees.lo: zlib/inftrees.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inftrees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inftrees.Tpo -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inftrees.Tpo $(DEPDIR)/libglpk_la-inftrees.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inftrees.c' object='libglpk_la-inftrees.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c + +libglpk_la-trees.lo: zlib/trees.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-trees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-trees.Tpo -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-trees.Tpo $(DEPDIR)/libglpk_la-trees.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/trees.c' object='libglpk_la-trees.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c + +libglpk_la-uncompr.lo: zlib/uncompr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-uncompr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-uncompr.Tpo -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-uncompr.Tpo $(DEPDIR)/libglpk_la-uncompr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/uncompr.c' object='libglpk_la-uncompr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c + +libglpk_la-zio.lo: zlib/zio.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zio.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zio.Tpo -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zio.Tpo $(DEPDIR)/libglpk_la-zio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zio.c' object='libglpk_la-zio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c + +libglpk_la-zutil.lo: zlib/zutil.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zutil.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zutil.Tpo -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zutil.Tpo $(DEPDIR)/libglpk_la-zutil.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zutil.c' object='libglpk_la-zutil.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +cscopelist: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-libLTLIBRARIES install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-includeHEADERS \ + uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/COPYING b/WebAPP/SOLVERs/GLPK/glpk/src/amd/COPYING new file mode 100644 index 000000000..84bba36d0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/README b/WebAPP/SOLVERs/GLPK/glpk/src/amd/README new file mode 100644 index 000000000..de950eb48 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/README @@ -0,0 +1,58 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin . +************************************************************************ +AMD Version 2.2, Copyright (C) 2007 by Timothy A. Davis, +Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. + +Description: + + AMD is a set of routines for pre-ordering sparse matrices prior to + Cholesky or LU factorization, using the approximate minimum degree + ordering algorithm. Written in ANSI/ISO C with a MATLAB interface, + and in Fortran 77. + +Authors: + + Timothy A. Davis (davis at cise.ufl.edu), University of Florida. + Patrick R. Amestoy, ENSEEIHT, Toulouse, France. + Iain S. Duff, Rutherford Appleton Laboratory, UK. + +AMD License: + + Your use or distribution of AMD or any modified version of AMD + implies that you agree to this License. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA. + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all + copies. User documentation of any code that uses this code or any + modified version of this code must cite the Copyright, this License, + the Availability note, and "Used by permission." Permission to + modify the code and to distribute modified code is granted, provided + the Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + AMD is available under alternate licences; contact T. Davis for + details. + +Availability: + + http://www.cise.ufl.edu/research/sparse/amd diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd.h b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd.h new file mode 100644 index 000000000..be662d954 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd.h @@ -0,0 +1,67 @@ +/* amd.h */ + +/* Written by Andrew Makhorin . */ + +#ifndef GLPAMD_H +#define GLPAMD_H + +#define AMD_DATE "May 31, 2007" +#define AMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) +#define AMD_MAIN_VERSION 2 +#define AMD_SUB_VERSION 2 +#define AMD_SUBSUB_VERSION 0 +#define AMD_VERSION AMD_VERSION_CODE(AMD_MAIN_VERSION, AMD_SUB_VERSION) + +#define AMD_CONTROL 5 +#define AMD_INFO 20 + +#define AMD_DENSE 0 +#define AMD_AGGRESSIVE 1 + +#define AMD_DEFAULT_DENSE 10.0 +#define AMD_DEFAULT_AGGRESSIVE 1 + +#define AMD_STATUS 0 +#define AMD_N 1 +#define AMD_NZ 2 +#define AMD_SYMMETRY 3 +#define AMD_NZDIAG 4 +#define AMD_NZ_A_PLUS_AT 5 +#define AMD_NDENSE 6 +#define AMD_MEMORY 7 +#define AMD_NCMPA 8 +#define AMD_LNZ 9 +#define AMD_NDIV 10 +#define AMD_NMULTSUBS_LDL 11 +#define AMD_NMULTSUBS_LU 12 +#define AMD_DMAX 13 + +#define AMD_OK 0 +#define AMD_OUT_OF_MEMORY (-1) +#define AMD_INVALID (-2) +#define AMD_OK_BUT_JUMBLED 1 + +#define amd_order _glp_amd_order +int amd_order(int n, const int Ap[], const int Ai[], int P[], + double Control[], double Info[]); + +#define amd_2 _glp_amd_2 +void amd_2(int n, int Pe[], int Iw[], int Len[], int iwlen, int pfree, + int Nv[], int Next[], int Last[], int Head[], int Elen[], + int Degree[], int W[], double Control[], double Info[]); + +#define amd_valid _glp_amd_valid +int amd_valid(int n_row, int n_col, const int Ap[], const int Ai[]); + +#define amd_defaults _glp_amd_defaults +void amd_defaults(double Control[]); + +#define amd_control _glp_amd_control +void amd_control(double Control[]); + +#define amd_info _glp_amd_info +void amd_info(double Info[]); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_1.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_1.c new file mode 100644 index 000000000..4f9b07d7c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_1.c @@ -0,0 +1,181 @@ +/* ========================================================================= */ +/* === AMD_1 =============================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering. + * + * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style + * compressed-column form, with sorted row indices in each column, and no + * duplicate entries. Diagonal entries may be present, but they are ignored. + * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. + * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The + * size of the matrix, n, must be greater than or equal to zero. + * + * This routine must be preceded by a call to AMD_aat, which computes the + * number of entries in each row/column in A+A', excluding the diagonal. + * Len [j], on input, is the number of entries in row/column j of A+A'. This + * routine constructs the matrix A+A' and then calls AMD_2. No error checking + * is performed (this was done in AMD_valid). + */ + +#include "amd_internal.h" + +GLOBAL void AMD_1 +( + Int n, /* n > 0 */ + const Int Ap [ ], /* input of size n+1, not modified */ + const Int Ai [ ], /* input of size nz = Ap [n], not modified */ + Int P [ ], /* size n output permutation */ + Int Pinv [ ], /* size n output inverse permutation */ + Int Len [ ], /* size n input, undefined on output */ + Int slen, /* slen >= sum (Len [0..n-1]) + 7n, + * ideally slen = 1.2 * sum (Len) + 8n */ + Int S [ ], /* size slen workspace */ + double Control [ ], /* input array of size AMD_CONTROL */ + double Info [ ] /* output array of size AMD_INFO */ +) +{ + Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, + *Elen, *Degree, *s, *W, *Sp, *Tp ; + + /* --------------------------------------------------------------------- */ + /* construct the matrix for AMD_2 */ + /* --------------------------------------------------------------------- */ + + ASSERT (n > 0) ; + + iwlen = slen - 6*n ; + s = S ; + Pe = s ; s += n ; + Nv = s ; s += n ; + Head = s ; s += n ; + Elen = s ; s += n ; + Degree = s ; s += n ; + W = s ; s += n ; + Iw = s ; s += iwlen ; + + ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; + + /* construct the pointers for A+A' */ + Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */ + Tp = W ; + pfree = 0 ; + for (j = 0 ; j < n ; j++) + { + Pe [j] = pfree ; + Sp [j] = pfree ; + pfree += Len [j] ; + } + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is strictly required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be very slow. For better performance, at + * least size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + +#ifndef NDEBUG + for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ; +#endif + + for (k = 0 ; k < n ; k++) + { + AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ; + p1 = Ap [k] ; + p2 = Ap [k+1] ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + ASSERT (j >= 0 && j < n) ; + if (j < k) + { + /* entry A (j,k) in the strictly upper triangular part */ + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ; + Iw [Sp [j]++] = k ; + Iw [Sp [k]++] = j ; + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + ASSERT (i >= 0 && i < n) ; + /* A (i,j) is only in the lower part, not in upper */ + ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; + ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; + Iw [Sp [i]++] = j ; + Iw [Sp [j]++] = i ; + } + } + +#ifndef NDEBUG + for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ; + ASSERT (Sp [n-1] == pfree) ; +#endif + + /* Tp and Sp no longer needed ] */ + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_2 (n, Pe, Iw, Len, iwlen, pfree, + Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_2.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_2.c new file mode 100644 index 000000000..36ae828ab --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_2.c @@ -0,0 +1,1842 @@ +/* ========================================================================= */ +/* === AMD_2 =============================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_2: performs the AMD ordering on a symmetric sparse matrix A, followed + * by a postordering (via depth-first search) of the assembly tree using the + * AMD_postorder routine. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === clear_flag ========================================================== */ +/* ========================================================================= */ + +static Int clear_flag (Int wflg, Int wbig, Int W [ ], Int n) +{ + Int x ; + if (wflg < 2 || wflg >= wbig) + { + for (x = 0 ; x < n ; x++) + { + if (W [x] != 0) W [x] = 1 ; + } + wflg = 2 ; + } + /* at this point, W [0..n-1] < wflg holds */ + return (wflg) ; +} + + +/* ========================================================================= */ +/* === AMD_2 =============================================================== */ +/* ========================================================================= */ + +GLOBAL void AMD_2 +( + Int n, /* A is n-by-n, where n > 0 */ + Int Pe [ ], /* Pe [0..n-1]: index in Iw of row i on input */ + Int Iw [ ], /* workspace of size iwlen. Iw [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* Len [0..n-1]: length for row/column i on input */ + Int iwlen, /* length of Iw. iwlen >= pfree + n */ + Int pfree, /* Iw [pfree ... iwlen-1] is empty on input */ + + /* 7 size-n workspaces, not defined on input: */ + Int Nv [ ], /* the size of each supernode on output */ + Int Next [ ], /* the output inverse permutation */ + Int Last [ ], /* the output permutation */ + Int Head [ ], + Int Elen [ ], /* the size columns of L for each supernode */ + Int Degree [ ], + Int W [ ], + + /* control parameters and output statistics */ + double Control [ ], /* array of size AMD_CONTROL */ + double Info [ ] /* array of size AMD_INFO */ +) +{ + +/* + * Given a representation of the nonzero pattern of a symmetric matrix, A, + * (excluding the diagonal) perform an approximate minimum (UMFPACK/MA38-style) + * degree ordering to compute a pivot order such that the introduction of + * nonzeros (fill-in) in the Cholesky factors A = LL' is kept low. At each + * step, the pivot selected is the one with the minimum UMFAPACK/MA38-style + * upper-bound on the external degree. This routine can optionally perform + * aggresive absorption (as done by MC47B in the Harwell Subroutine + * Library). + * + * The approximate degree algorithm implemented here is the symmetric analog of + * the degree update algorithm in MA38 and UMFPACK (the Unsymmetric-pattern + * MultiFrontal PACKage, both by Davis and Duff). The routine is based on the + * MA27 minimum degree ordering algorithm by Iain Duff and John Reid. + * + * This routine is a translation of the original AMDBAR and MC47B routines, + * in Fortran, with the following modifications: + * + * (1) dense rows/columns are removed prior to ordering the matrix, and placed + * last in the output order. The presence of a dense row/column can + * increase the ordering time by up to O(n^2), unless they are removed + * prior to ordering. + * + * (2) the minimum degree ordering is followed by a postordering (depth-first + * search) of the assembly tree. Note that mass elimination (discussed + * below) combined with the approximate degree update can lead to the mass + * elimination of nodes with lower exact degree than the current pivot + * element. No additional fill-in is caused in the representation of the + * Schur complement. The mass-eliminated nodes merge with the current + * pivot element. They are ordered prior to the current pivot element. + * Because they can have lower exact degree than the current element, the + * merger of two or more of these nodes in the current pivot element can + * lead to a single element that is not a "fundamental supernode". The + * diagonal block can have zeros in it. Thus, the assembly tree used here + * is not guaranteed to be the precise supernodal elemination tree (with + * "funadmental" supernodes), and the postordering performed by this + * routine is not guaranteed to be a precise postordering of the + * elimination tree. + * + * (3) input parameters are added, to control aggressive absorption and the + * detection of "dense" rows/columns of A. + * + * (4) additional statistical information is returned, such as the number of + * nonzeros in L, and the flop counts for subsequent LDL' and LU + * factorizations. These are slight upper bounds, because of the mass + * elimination issue discussed above. + * + * (5) additional routines are added to interface this routine to MATLAB + * to provide a simple C-callable user-interface, to check inputs for + * errors, compute the symmetry of the pattern of A and the number of + * nonzeros in each row/column of A+A', to compute the pattern of A+A', + * to perform the assembly tree postordering, and to provide debugging + * ouput. Many of these functions are also provided by the Fortran + * Harwell Subroutine Library routine MC47A. + * + * (6) both int and UF_long versions are provided. In the descriptions below + * and integer is and int or UF_long depending on which version is + * being used. + + ********************************************************************** + ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** + ********************************************************************** + ** If you want error checking, a more versatile input format, and a ** + ** simpler user interface, use amd_order or amd_l_order instead. ** + ** This routine is not meant to be user-callable. ** + ********************************************************************** + + * ---------------------------------------------------------------------------- + * References: + * ---------------------------------------------------------------------------- + * + * [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern multifrontal + * method for sparse LU factorization", SIAM J. Matrix Analysis and + * Applications, vol. 18, no. 1, pp. 140-158. Discusses UMFPACK / MA38, + * which first introduced the approximate minimum degree used by this + * routine. + * + * [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An approximate + * minimum degree ordering algorithm," SIAM J. Matrix Analysis and + * Applications, vol. 17, no. 4, pp. 886-905, 1996. Discusses AMDBAR and + * MC47B, which are the Fortran versions of this routine. + * + * [3] Alan George and Joseph Liu, "The evolution of the minimum degree + * ordering algorithm," SIAM Review, vol. 31, no. 1, pp. 1-19, 1989. + * We list below the features mentioned in that paper that this code + * includes: + * + * mass elimination: + * Yes. MA27 relied on supervariable detection for mass elimination. + * + * indistinguishable nodes: + * Yes (we call these "supervariables"). This was also in the MA27 + * code - although we modified the method of detecting them (the + * previous hash was the true degree, which we no longer keep track + * of). A supervariable is a set of rows with identical nonzero + * pattern. All variables in a supervariable are eliminated together. + * Each supervariable has as its numerical name that of one of its + * variables (its principal variable). + * + * quotient graph representation: + * Yes. We use the term "element" for the cliques formed during + * elimination. This was also in the MA27 code. The algorithm can + * operate in place, but it will work more efficiently if given some + * "elbow room." + * + * element absorption: + * Yes. This was also in the MA27 code. + * + * external degree: + * Yes. The MA27 code was based on the true degree. + * + * incomplete degree update and multiple elimination: + * No. This was not in MA27, either. Our method of degree update + * within MC47B is element-based, not variable-based. It is thus + * not well-suited for use with incomplete degree update or multiple + * elimination. + * + * Authors, and Copyright (C) 2004 by: + * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. + * + * Acknowledgements: This work (and the UMFPACK package) was supported by the + * National Science Foundation (ASC-9111263, DMS-9223088, and CCR-0203270). + * The UMFPACK/MA38 approximate degree update algorithm, the unsymmetric analog + * which forms the basis of AMD, was developed while Tim Davis was supported by + * CERFACS (Toulouse, France) in a post-doctoral position. This C version, and + * the etree postorder, were written while Tim Davis was on sabbatical at + * Stanford University and Lawrence Berkeley National Laboratory. + + * ---------------------------------------------------------------------------- + * INPUT ARGUMENTS (unaltered): + * ---------------------------------------------------------------------------- + + * n: The matrix order. Restriction: n >= 1. + * + * iwlen: The size of the Iw array. On input, the matrix is stored in + * Iw [0..pfree-1]. However, Iw [0..iwlen-1] should be slightly larger + * than what is required to hold the matrix, at least iwlen >= pfree + n. + * Otherwise, excessive compressions will take place. The recommended + * value of iwlen is 1.2 * pfree + n, which is the value used in the + * user-callable interface to this routine (amd_order.c). The algorithm + * will not run at all if iwlen < pfree. Restriction: iwlen >= pfree + n. + * Note that this is slightly more restrictive than the actual minimum + * (iwlen >= pfree), but AMD_2 will be very slow with no elbow room. + * Thus, this routine enforces a bare minimum elbow room of size n. + * + * pfree: On input the tail end of the array, Iw [pfree..iwlen-1], is empty, + * and the matrix is stored in Iw [0..pfree-1]. During execution, + * additional data is placed in Iw, and pfree is modified so that + * Iw [pfree..iwlen-1] is always the unused part of Iw. + * + * Control: A double array of size AMD_CONTROL containing input parameters + * that affect how the ordering is computed. If NULL, then default + * settings are used. + * + * Control [AMD_DENSE] is used to determine whether or not a given input + * row is "dense". A row is "dense" if the number of entries in the row + * exceeds Control [AMD_DENSE] times sqrt (n), except that rows with 16 or + * fewer entries are never considered "dense". To turn off the detection + * of dense rows, set Control [AMD_DENSE] to a negative number, or to a + * number larger than sqrt (n). The default value of Control [AMD_DENSE] + * is AMD_DEFAULT_DENSE, which is defined in amd.h as 10. + * + * Control [AMD_AGGRESSIVE] is used to determine whether or not aggressive + * absorption is to be performed. If nonzero, then aggressive absorption + * is performed (this is the default). + + * ---------------------------------------------------------------------------- + * INPUT/OUPUT ARGUMENTS: + * ---------------------------------------------------------------------------- + * + * Pe: An integer array of size n. On input, Pe [i] is the index in Iw of + * the start of row i. Pe [i] is ignored if row i has no off-diagonal + * entries. Thus Pe [i] must be in the range 0 to pfree-1 for non-empty + * rows. + * + * During execution, it is used for both supervariables and elements: + * + * Principal supervariable i: index into Iw of the description of + * supervariable i. A supervariable represents one or more rows of + * the matrix with identical nonzero pattern. In this case, + * Pe [i] >= 0. + * + * Non-principal supervariable i: if i has been absorbed into another + * supervariable j, then Pe [i] = FLIP (j), where FLIP (j) is defined + * as (-(j)-2). Row j has the same pattern as row i. Note that j + * might later be absorbed into another supervariable j2, in which + * case Pe [i] is still FLIP (j), and Pe [j] = FLIP (j2) which is + * < EMPTY, where EMPTY is defined as (-1) in amd_internal.h. + * + * Unabsorbed element e: the index into Iw of the description of element + * e, if e has not yet been absorbed by a subsequent element. Element + * e is created when the supervariable of the same name is selected as + * the pivot. In this case, Pe [i] >= 0. + * + * Absorbed element e: if element e is absorbed into element e2, then + * Pe [e] = FLIP (e2). This occurs when the pattern of e (which we + * refer to as Le) is found to be a subset of the pattern of e2 (that + * is, Le2). In this case, Pe [i] < EMPTY. If element e is "null" + * (it has no nonzeros outside its pivot block), then Pe [e] = EMPTY, + * and e is the root of an assembly subtree (or the whole tree if + * there is just one such root). + * + * Dense variable i: if i is "dense", then Pe [i] = EMPTY. + * + * On output, Pe holds the assembly tree/forest, which implicitly + * represents a pivot order with identical fill-in as the actual order + * (via a depth-first search of the tree), as follows. If Nv [i] > 0, + * then i represents a node in the assembly tree, and the parent of i is + * Pe [i], or EMPTY if i is a root. If Nv [i] = 0, then (i, Pe [i]) + * represents an edge in a subtree, the root of which is a node in the + * assembly tree. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Info: A double array of size AMD_INFO. If present, (that is, not NULL), + * then statistics about the ordering are returned in the Info array. + * See amd.h for a description. + + * ---------------------------------------------------------------------------- + * INPUT/MODIFIED (undefined on output): + * ---------------------------------------------------------------------------- + * + * Len: An integer array of size n. On input, Len [i] holds the number of + * entries in row i of the matrix, excluding the diagonal. The contents + * of Len are undefined on output. + * + * Iw: An integer array of size iwlen. On input, Iw [0..pfree-1] holds the + * description of each row i in the matrix. The matrix must be symmetric, + * and both upper and lower triangular parts must be present. The + * diagonal must not be present. Row i is held as follows: + * + * Len [i]: the length of the row i data structure in the Iw array. + * Iw [Pe [i] ... Pe [i] + Len [i] - 1]: + * the list of column indices for nonzeros in row i (simple + * supervariables), excluding the diagonal. All supervariables + * start with one row/column each (supervariable i is just row i). + * If Len [i] is zero on input, then Pe [i] is ignored on input. + * + * Note that the rows need not be in any particular order, and there + * may be empty space between the rows. + * + * During execution, the supervariable i experiences fill-in. This is + * represented by placing in i a list of the elements that cause fill-in + * in supervariable i: + * + * Len [i]: the length of supervariable i in the Iw array. + * Iw [Pe [i] ... Pe [i] + Elen [i] - 1]: + * the list of elements that contain i. This list is kept short + * by removing absorbed elements. + * Iw [Pe [i] + Elen [i] ... Pe [i] + Len [i] - 1]: + * the list of supervariables in i. This list is kept short by + * removing nonprincipal variables, and any entry j that is also + * contained in at least one of the elements (j in Le) in the list + * for i (e in row i). + * + * When supervariable i is selected as pivot, we create an element e of + * the same name (e=i): + * + * Len [e]: the length of element e in the Iw array. + * Iw [Pe [e] ... Pe [e] + Len [e] - 1]: + * the list of supervariables in element e. + * + * An element represents the fill-in that occurs when supervariable i is + * selected as pivot (which represents the selection of row i and all + * non-principal variables whose principal variable is i). We use the + * term Le to denote the set of all supervariables in element e. Absorbed + * supervariables and elements are pruned from these lists when + * computationally convenient. + * + * CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. + * The contents of Iw are undefined on output. + + * ---------------------------------------------------------------------------- + * OUTPUT (need not be set on input): + * ---------------------------------------------------------------------------- + * + * Nv: An integer array of size n. During execution, ABS (Nv [i]) is equal to + * the number of rows that are represented by the principal supervariable + * i. If i is a nonprincipal or dense variable, then Nv [i] = 0. + * Initially, Nv [i] = 1 for all i. Nv [i] < 0 signifies that i is a + * principal variable in the pattern Lme of the current pivot element me. + * After element me is constructed, Nv [i] is set back to a positive + * value. + * + * On output, Nv [i] holds the number of pivots represented by super + * row/column i of the original matrix, or Nv [i] = 0 for non-principal + * rows/columns. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Elen: An integer array of size n. See the description of Iw above. At the + * start of execution, Elen [i] is set to zero for all rows i. During + * execution, Elen [i] is the number of elements in the list for + * supervariable i. When e becomes an element, Elen [e] = FLIP (esize) is + * set, where esize is the size of the element (the number of pivots, plus + * the number of nonpivotal entries). Thus Elen [e] < EMPTY. + * Elen (i) = EMPTY set when variable i becomes nonprincipal. + * + * For variables, Elen (i) >= EMPTY holds until just before the + * postordering and permutation vectors are computed. For elements, + * Elen [e] < EMPTY holds. + * + * On output, Elen [i] is the degree of the row/column in the Cholesky + * factorization of the permuted matrix, corresponding to the original row + * i, if i is a super row/column. It is equal to EMPTY if i is + * non-principal. Note that i refers to a row/column in the original + * matrix, not the permuted matrix. + * + * Note that the contents of Elen on output differ from the Fortran + * version (Elen holds the inverse permutation in the Fortran version, + * which is instead returned in the Next array in this C version, + * described below). + * + * Last: In a degree list, Last [i] is the supervariable preceding i, or EMPTY + * if i is the head of the list. In a hash bucket, Last [i] is the hash + * key for i. + * + * Last [Head [hash]] is also used as the head of a hash bucket if + * Head [hash] contains a degree list (see the description of Head, + * below). + * + * On output, Last [0..n-1] holds the permutation. That is, if + * i = Last [k], then row i is the kth pivot row (where k ranges from 0 to + * n-1). Row Last [k] of A is the kth row in the permuted matrix, PAP'. + * + * Next: Next [i] is the supervariable following i in a link list, or EMPTY if + * i is the last in the list. Used for two kinds of lists: degree lists + * and hash buckets (a supervariable can be in only one kind of list at a + * time). + * + * On output Next [0..n-1] holds the inverse permutation. That is, if + * k = Next [i], then row i is the kth pivot row. Row i of A appears as + * the (Next[i])-th row in the permuted matrix, PAP'. + * + * Note that the contents of Next on output differ from the Fortran + * version (Next is undefined on output in the Fortran version). + + * ---------------------------------------------------------------------------- + * LOCAL WORKSPACE (not input or output - used only during execution): + * ---------------------------------------------------------------------------- + * + * Degree: An integer array of size n. If i is a supervariable, then + * Degree [i] holds the current approximation of the external degree of + * row i (an upper bound). The external degree is the number of nonzeros + * in row i, minus ABS (Nv [i]), the diagonal part. The bound is equal to + * the exact external degree if Elen [i] is less than or equal to two. + * + * We also use the term "external degree" for elements e to refer to + * |Le \ Lme|. If e is an element, then Degree [e] is |Le|, which is the + * degree of the off-diagonal part of the element e (not including the + * diagonal part). + * + * Head: An integer array of size n. Head is used for degree lists. + * Head [deg] is the first supervariable in a degree list. All + * supervariables i in a degree list Head [deg] have the same approximate + * degree, namely, deg = Degree [i]. If the list Head [deg] is empty then + * Head [deg] = EMPTY. + * + * During supervariable detection Head [hash] also serves as a pointer to + * a hash bucket. If Head [hash] >= 0, there is a degree list of degree + * hash. The hash bucket head pointer is Last [Head [hash]]. If + * Head [hash] = EMPTY, then the degree list and hash bucket are both + * empty. If Head [hash] < EMPTY, then the degree list is empty, and + * FLIP (Head [hash]) is the head of the hash bucket. After supervariable + * detection is complete, all hash buckets are empty, and the + * (Last [Head [hash]] = EMPTY) condition is restored for the non-empty + * degree lists. + * + * W: An integer array of size n. The flag array W determines the status of + * elements and variables, and the external degree of elements. + * + * for elements: + * if W [e] = 0, then the element e is absorbed. + * if W [e] >= wflg, then W [e] - wflg is the size of the set + * |Le \ Lme|, in terms of nonzeros (the sum of ABS (Nv [i]) for + * each principal variable i that is both in the pattern of + * element e and NOT in the pattern of the current pivot element, + * me). + * if wflg > W [e] > 0, then e is not absorbed and has not yet been + * seen in the scan of the element lists in the computation of + * |Le\Lme| in Scan 1 below. + * + * for variables: + * during supervariable detection, if W [j] != wflg then j is + * not in the pattern of variable i. + * + * The W array is initialized by setting W [i] = 1 for all i, and by + * setting wflg = 2. It is reinitialized if wflg becomes too large (to + * ensure that wflg+n does not cause integer overflow). + + * ---------------------------------------------------------------------------- + * LOCAL INTEGERS: + * ---------------------------------------------------------------------------- + */ + + Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, + jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, + nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, ok, ndense, ncmpa, + dense, aggressive ; + + unsigned Int hash ; /* unsigned, so that hash % n is well defined.*/ + +/* + * deg: the degree of a variable or element + * degme: size, |Lme|, of the current element, me (= Degree [me]) + * dext: external degree, |Le \ Lme|, of some element e + * lemax: largest |Le| seen so far (called dmax in Fortran version) + * e: an element + * elenme: the length, Elen [me], of element list of pivotal variable + * eln: the length, Elen [...], of an element list + * hash: the computed value of the hash function + * i: a supervariable + * ilast: the entry in a link list preceding i + * inext: the entry in a link list following i + * j: a supervariable + * jlast: the entry in a link list preceding j + * jnext: the entry in a link list, or path, following j + * k: the pivot order of an element or variable + * knt1: loop counter used during element construction + * knt2: loop counter used during element construction + * knt3: loop counter used during compression + * lenj: Len [j] + * ln: length of a supervariable list + * me: current supervariable being eliminated, and the current + * element created by eliminating that supervariable + * mindeg: current minimum degree + * nel: number of pivots selected so far + * nleft: n - nel, the number of nonpivotal rows/columns remaining + * nvi: the number of variables in a supervariable i (= Nv [i]) + * nvj: the number of variables in a supervariable j (= Nv [j]) + * nvpiv: number of pivots in current element + * slenme: number of variables in variable list of pivotal variable + * wbig: = INT_MAX - n for the int version, UF_long_max - n for the + * UF_long version. wflg is not allowed to be >= wbig. + * we: W [e] + * wflg: used for flagging the W array. See description of Iw. + * wnvi: wflg - Nv [i] + * x: either a supervariable or an element + * + * ok: true if supervariable j can be absorbed into i + * ndense: number of "dense" rows/columns + * dense: rows/columns with initial degree > dense are considered "dense" + * aggressive: true if aggressive absorption is being performed + * ncmpa: number of garbage collections + + * ---------------------------------------------------------------------------- + * LOCAL DOUBLES, used for statistical output only (except for alpha): + * ---------------------------------------------------------------------------- + */ + + double f, r, ndiv, s, nms_lu, nms_ldl, dmax, alpha, lnz, lnzme ; + +/* + * f: nvpiv + * r: degme + nvpiv + * ndiv: number of divisions for LU or LDL' factorizations + * s: number of multiply-subtract pairs for LU factorization, for the + * current element me + * nms_lu number of multiply-subtract pairs for LU factorization + * nms_ldl number of multiply-subtract pairs for LDL' factorization + * dmax: the largest number of entries in any column of L, including the + * diagonal + * alpha: "dense" degree ratio + * lnz: the number of nonzeros in L (excluding the diagonal) + * lnzme: the number of nonzeros in L (excl. the diagonal) for the + * current element me + + * ---------------------------------------------------------------------------- + * LOCAL "POINTERS" (indices into the Iw array) + * ---------------------------------------------------------------------------- +*/ + + Int p, p1, p2, p3, p4, pdst, pend, pj, pme, pme1, pme2, pn, psrc ; + +/* + * Any parameter (Pe [...] or pfree) or local variable starting with "p" (for + * Pointer) is an index into Iw, and all indices into Iw use variables starting + * with "p." The only exception to this rule is the iwlen input argument. + * + * p: pointer into lots of things + * p1: Pe [i] for some variable i (start of element list) + * p2: Pe [i] + Elen [i] - 1 for some variable i + * p3: index of first supervariable in clean list + * p4: + * pdst: destination pointer, for compression + * pend: end of memory to compress + * pj: pointer into an element or variable + * pme: pointer into the current element (pme1...pme2) + * pme1: the current element, me, is stored in Iw [pme1...pme2] + * pme2: the end of the current element + * pn: pointer into a "clean" variable, also used to compress + * psrc: source pointer, for compression +*/ + +/* ========================================================================= */ +/* INITIALIZATIONS */ +/* ========================================================================= */ + + /* Note that this restriction on iwlen is slightly more restrictive than + * what is actually required in AMD_2. AMD_2 can operate with no elbow + * room at all, but it will be slow. For better performance, at least + * size-n elbow room is enforced. */ + ASSERT (iwlen >= pfree + n) ; + ASSERT (n > 0) ; + + /* initialize output statistics */ + lnz = 0 ; + ndiv = 0 ; + nms_lu = 0 ; + nms_ldl = 0 ; + dmax = 1 ; + me = EMPTY ; + + mindeg = 0 ; + ncmpa = 0 ; + nel = 0 ; + lemax = 0 ; + + /* get control parameters */ + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = (Control [AMD_AGGRESSIVE] != 0) ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + /* Note: if alpha is NaN, this is undefined: */ + if (alpha < 0) + { + /* only remove completely dense rows/columns */ + dense = n-2 ; + } + else + { + dense = alpha * sqrt ((double) n) ; + } + dense = MAX (16, dense) ; + dense = MIN (n, dense) ; + AMD_DEBUG1 (("\n\nAMD (debug), alpha %g, aggr. "ID"\n", + alpha, aggressive)) ; + + for (i = 0 ; i < n ; i++) + { + Last [i] = EMPTY ; + Head [i] = EMPTY ; + Next [i] = EMPTY ; + /* if separate Hhead array is used for hash buckets: * + Hhead [i] = EMPTY ; + */ + Nv [i] = 1 ; + W [i] = 1 ; + Elen [i] = 0 ; + Degree [i] = Len [i] ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID" initial\n", nel)) ; + AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, + Head, Elen, Degree, W, -1) ; +#endif + + /* initialize wflg */ + wbig = Int_MAX - n ; + wflg = clear_flag (0, wbig, W, n) ; + + /* --------------------------------------------------------------------- */ + /* initialize degree lists and eliminate dense and empty rows */ + /* --------------------------------------------------------------------- */ + + ndense = 0 ; + + for (i = 0 ; i < n ; i++) + { + deg = Degree [i] ; + ASSERT (deg >= 0 && deg < n) ; + if (deg == 0) + { + + /* ------------------------------------------------------------- + * we have a variable that can be eliminated at once because + * there is no off-diagonal non-zero in its row. Note that + * Nv [i] = 1 for an empty variable i. It is treated just + * the same as an eliminated element i. + * ------------------------------------------------------------- */ + + Elen [i] = FLIP (1) ; + nel++ ; + Pe [i] = EMPTY ; + W [i] = 0 ; + + } + else if (deg > dense) + { + + /* ------------------------------------------------------------- + * Dense variables are not treated as elements, but as unordered, + * non-principal variables that have no parent. They do not take + * part in the postorder, since Nv [i] = 0. Note that the Fortran + * version does not have this option. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Dense node "ID" degree "ID"\n", i, deg)) ; + ndense++ ; + Nv [i] = 0 ; /* do not postorder this node */ + Elen [i] = EMPTY ; + nel++ ; + Pe [i] = EMPTY ; + + } + else + { + + /* ------------------------------------------------------------- + * place i in the degree list corresponding to its degree + * ------------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Head [deg] = i ; + + } + } + +/* ========================================================================= */ +/* WHILE (selecting pivots) DO */ +/* ========================================================================= */ + + while (nel < n) + { + +#ifndef NDEBUG + AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; + if (AMD_debug >= 2) + { + AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, + Last, Head, Elen, Degree, W, nel) ; + } +#endif + +/* ========================================================================= */ +/* GET PIVOT OF MINIMUM DEGREE */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- */ + /* find next supervariable for elimination */ + /* ----------------------------------------------------------------- */ + + ASSERT (mindeg >= 0 && mindeg < n) ; + for (deg = mindeg ; deg < n ; deg++) + { + me = Head [deg] ; + if (me != EMPTY) break ; + } + mindeg = deg ; + ASSERT (me >= 0 && me < n) ; + AMD_DEBUG1 (("=================me: "ID"\n", me)) ; + + /* ----------------------------------------------------------------- */ + /* remove chosen variable from link list */ + /* ----------------------------------------------------------------- */ + + inext = Next [me] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = EMPTY ; + Head [deg] = inext ; + + /* ----------------------------------------------------------------- */ + /* me represents the elimination of pivots nel to nel+Nv[me]-1. */ + /* place me itself as the first in this set. */ + /* ----------------------------------------------------------------- */ + + elenme = Elen [me] ; + nvpiv = Nv [me] ; + ASSERT (nvpiv > 0) ; + nel += nvpiv ; + +/* ========================================================================= */ +/* CONSTRUCT NEW ELEMENT */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * At this point, me is the pivotal supervariable. It will be + * converted into the current element. Scan list of the pivotal + * supervariable, me, setting tree pointers and constructing new list + * of supervariables for the new element, me. p is a pointer to the + * current position in the old list. + * ----------------------------------------------------------------- */ + + /* flag the variable "me" as being in Lme by negating Nv [me] */ + Nv [me] = -nvpiv ; + degme = 0 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + if (elenme == 0) + { + + /* ------------------------------------------------------------- */ + /* construct the new element in place */ + /* ------------------------------------------------------------- */ + + pme1 = Pe [me] ; + pme2 = pme1 - 1 ; + + for (p = pme1 ; p <= pme1 + Len [me] - 1 ; p++) + { + i = Iw [p] ; + ASSERT (i >= 0 && i < n && Nv [i] >= 0) ; + nvi = Nv [i] ; + if (nvi > 0) + { + + /* ----------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme. */ + /* store i in new list */ + /* ----------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [++pme2] = i ; + + /* ----------------------------------------------------- */ + /* remove variable i from degree list. */ + /* ----------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + } + else + { + + /* ------------------------------------------------------------- */ + /* construct the new element in empty space, Iw [pfree ...] */ + /* ------------------------------------------------------------- */ + + p = Pe [me] ; + pme1 = pfree ; + slenme = Len [me] - elenme ; + + for (knt1 = 1 ; knt1 <= elenme + 1 ; knt1++) + { + + if (knt1 > elenme) + { + /* search the supervariables in me. */ + e = me ; + pj = p ; + ln = slenme ; + AMD_DEBUG2 (("Search sv: "ID" "ID" "ID"\n", me,pj,ln)) ; + } + else + { + /* search the elements in me. */ + e = Iw [p++] ; + ASSERT (e >= 0 && e < n) ; + pj = Pe [e] ; + ln = Len [e] ; + AMD_DEBUG2 (("Search element e "ID" in me "ID"\n", e,me)) ; + ASSERT (Elen [e] < EMPTY && W [e] > 0 && pj >= 0) ; + } + ASSERT (ln >= 0 && (ln == 0 || (pj >= 0 && pj < iwlen))) ; + + /* --------------------------------------------------------- + * search for different supervariables and add them to the + * new list, compressing when necessary. this loop is + * executed once for each element in the list and once for + * all the supervariables in the list. + * --------------------------------------------------------- */ + + for (knt2 = 1 ; knt2 <= ln ; knt2++) + { + i = Iw [pj++] ; + ASSERT (i >= 0 && i < n && (i == me || Elen [i] >= EMPTY)); + nvi = Nv [i] ; + AMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", + i, Elen [i], Nv [i], wflg)) ; + + if (nvi > 0) + { + + /* ------------------------------------------------- */ + /* compress Iw, if necessary */ + /* ------------------------------------------------- */ + + if (pfree >= iwlen) + { + + AMD_DEBUG1 (("GARBAGE COLLECTION\n")) ; + + /* prepare for compressing Iw by adjusting pointers + * and lengths so that the lists being searched in + * the inner and outer loops contain only the + * remaining entries. */ + + Pe [me] = p ; + Len [me] -= knt1 ; + /* check if nothing left of supervariable me */ + if (Len [me] == 0) Pe [me] = EMPTY ; + Pe [e] = pj ; + Len [e] = ln - knt2 ; + /* nothing left of element e */ + if (Len [e] == 0) Pe [e] = EMPTY ; + + ncmpa++ ; /* one more garbage collection */ + + /* store first entry of each object in Pe */ + /* FLIP the first entry in each object */ + for (j = 0 ; j < n ; j++) + { + pn = Pe [j] ; + if (pn >= 0) + { + ASSERT (pn >= 0 && pn < iwlen) ; + Pe [j] = Iw [pn] ; + Iw [pn] = FLIP (j) ; + } + } + + /* psrc/pdst point to source/destination */ + psrc = 0 ; + pdst = 0 ; + pend = pme1 - 1 ; + + while (psrc <= pend) + { + /* search for next FLIP'd entry */ + j = FLIP (Iw [psrc++]) ; + if (j >= 0) + { + AMD_DEBUG2 (("Got object j: "ID"\n", j)) ; + Iw [pdst] = Pe [j] ; + Pe [j] = pdst++ ; + lenj = Len [j] ; + /* copy from source to destination */ + for (knt3 = 0 ; knt3 <= lenj - 2 ; knt3++) + { + Iw [pdst++] = Iw [psrc++] ; + } + } + } + + /* move the new partially-constructed element */ + p1 = pdst ; + for (psrc = pme1 ; psrc <= pfree-1 ; psrc++) + { + Iw [pdst++] = Iw [psrc] ; + } + pme1 = p1 ; + pfree = pdst ; + pj = Pe [e] ; + p = Pe [me] ; + + } + + /* ------------------------------------------------- */ + /* i is a principal variable not yet placed in Lme */ + /* store i in new list */ + /* ------------------------------------------------- */ + + /* flag i as being in Lme by negating Nv [i] */ + degme += nvi ; + Nv [i] = -nvi ; + Iw [pfree++] = i ; + AMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); + + /* ------------------------------------------------- */ + /* remove variable i from degree link list */ + /* ------------------------------------------------- */ + + ilast = Last [i] ; + inext = Next [i] ; + ASSERT (ilast >= EMPTY && ilast < n) ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = ilast ; + if (ilast != EMPTY) + { + Next [ilast] = inext ; + } + else + { + /* i is at the head of the degree list */ + ASSERT (Degree [i] >= 0 && Degree [i] < n) ; + Head [Degree [i]] = inext ; + } + } + } + + if (e != me) + { + /* set tree pointer and flag to indicate element e is + * absorbed into new element me (the parent of e is me) */ + AMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + + pme2 = pfree - 1 ; + } + + /* ----------------------------------------------------------------- */ + /* me has now been converted into an element in Iw [pme1..pme2] */ + /* ----------------------------------------------------------------- */ + + /* degme holds the external degree of new element */ + Degree [me] = degme ; + Pe [me] = pme1 ; + Len [me] = pme2 - pme1 + 1 ; + ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; + + Elen [me] = FLIP (nvpiv + degme) ; + /* FLIP (Elen (me)) is now the degree of pivot (including + * diagonal part). */ + +#ifndef NDEBUG + AMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; + for (pme = pme1 ; pme <= pme2 ; pme++) AMD_DEBUG3 ((" "ID"", Iw[pme])); + AMD_DEBUG3 (("\n")) ; +#endif + + /* ----------------------------------------------------------------- */ + /* make sure that wflg is not too large. */ + /* ----------------------------------------------------------------- */ + + /* With the current value of wflg, wflg+n must not cause integer + * overflow */ + + wflg = clear_flag (wflg, wbig, W, n) ; + +/* ========================================================================= */ +/* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 1: compute the external degrees of previous elements with + * respect to the current element. That is: + * (W [e] - wflg) = |Le \ Lme| + * for each element e that appears in any supervariable in Lme. The + * notation Le refers to the pattern (list of supervariables) of a + * previous element e, where e is not yet absorbed, stored in + * Iw [Pe [e] + 1 ... Pe [e] + Len [e]]. The notation Lme + * refers to the pattern of the current element (stored in + * Iw [pme1..pme2]). If aggressive absorption is enabled, and + * (W [e] - wflg) becomes zero, then the element e will be absorbed + * in Scan 2. + * ----------------------------------------------------------------- */ + + AMD_DEBUG2 (("me: ")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + eln = Elen [i] ; + AMD_DEBUG3 ((""ID" Elen "ID": \n", i, eln)) ; + if (eln > 0) + { + /* note that Nv [i] has been negated to denote i in Lme: */ + nvi = -Nv [i] ; + ASSERT (nvi > 0 && Pe [i] >= 0 && Pe [i] < iwlen) ; + wnvi = wflg - nvi ; + for (p = Pe [i] ; p <= Pe [i] + eln - 1 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + AMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; + if (we >= wflg) + { + /* unabsorbed element e has been seen in this loop */ + AMD_DEBUG4 ((" unabsorbed, first time seen")) ; + we -= nvi ; + } + else if (we != 0) + { + /* e is an unabsorbed element */ + /* this is the first we have seen e in all of Scan 1 */ + AMD_DEBUG4 ((" unabsorbed")) ; + we = Degree [e] + wnvi ; + } + AMD_DEBUG4 (("\n")) ; + W [e] = we ; + } + } + } + AMD_DEBUG2 (("\n")) ; + +/* ========================================================================= */ +/* DEGREE UPDATE AND ELEMENT ABSORPTION */ +/* ========================================================================= */ + + /* ----------------------------------------------------------------- + * Scan 2: for each i in Lme, sum up the degree of Lme (which is + * degme), plus the sum of the external degrees of each Le for the + * elements e appearing within i, plus the supervariables in i. + * Place i in hash list. + * ----------------------------------------------------------------- */ + + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n && Nv [i] < 0 && Elen [i] >= 0) ; + AMD_DEBUG2 (("Updating: i "ID" "ID" "ID"\n", i, Elen[i], Len [i])); + p1 = Pe [i] ; + p2 = p1 + Elen [i] - 1 ; + pn = p1 ; + hash = 0 ; + deg = 0 ; + ASSERT (p1 >= 0 && p1 < iwlen && p2 >= -1 && p2 < iwlen) ; + + /* ------------------------------------------------------------- */ + /* scan the element list associated with supervariable i */ + /* ------------------------------------------------------------- */ + + /* UMFPACK/MA38-style approximate degree: */ + if (aggressive) + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + /* dext = | Le \ Lme | */ + dext = we - wflg ; + if (dext > 0) + { + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + else + { + /* external degree of e is zero, absorb e into me*/ + AMD_DEBUG1 ((" Element "ID" =>"ID" (aggressive)\n", + e, me)) ; + ASSERT (dext == 0) ; + Pe [e] = FLIP (me) ; + W [e] = 0 ; + } + } + } + } + else + { + for (p = p1 ; p <= p2 ; p++) + { + e = Iw [p] ; + ASSERT (e >= 0 && e < n) ; + we = W [e] ; + if (we != 0) + { + /* e is an unabsorbed element */ + dext = we - wflg ; + ASSERT (dext >= 0) ; + deg += dext ; + Iw [pn++] = e ; + hash += e ; + AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; + } + } + } + + /* count the number of elements in i (including me): */ + Elen [i] = pn - p1 + 1 ; + + /* ------------------------------------------------------------- */ + /* scan the supervariables in the list associated with i */ + /* ------------------------------------------------------------- */ + + /* The bulk of the AMD run time is typically spent in this loop, + * particularly if the matrix has many dense rows that are not + * removed prior to ordering. */ + p3 = pn ; + p4 = p1 + Len [i] ; + for (p = p2 + 1 ; p < p4 ; p++) + { + j = Iw [p] ; + ASSERT (j >= 0 && j < n) ; + nvj = Nv [j] ; + if (nvj > 0) + { + /* j is unabsorbed, and not in Lme. */ + /* add to degree and add to new list */ + deg += nvj ; + Iw [pn++] = j ; + hash += j ; + AMD_DEBUG4 ((" s: "ID" hash "ID" Nv[j]= "ID"\n", + j, hash, nvj)) ; + } + } + + /* ------------------------------------------------------------- */ + /* update the degree and check for mass elimination */ + /* ------------------------------------------------------------- */ + + /* with aggressive absorption, deg==0 is identical to the + * Elen [i] == 1 && p3 == pn test, below. */ + ASSERT (IMPLIES (aggressive, (deg==0) == (Elen[i]==1 && p3==pn))) ; + + if (Elen [i] == 1 && p3 == pn) + { + + /* --------------------------------------------------------- */ + /* mass elimination */ + /* --------------------------------------------------------- */ + + /* There is nothing left of this node except for an edge to + * the current pivot element. Elen [i] is 1, and there are + * no variables adjacent to node i. Absorb i into the + * current pivot element, me. Note that if there are two or + * more mass eliminations, fillin due to mass elimination is + * possible within the nvpiv-by-nvpiv pivot block. It is this + * step that causes AMD's analysis to be an upper bound. + * + * The reason is that the selected pivot has a lower + * approximate degree than the true degree of the two mass + * eliminated nodes. There is no edge between the two mass + * eliminated nodes. They are merged with the current pivot + * anyway. + * + * No fillin occurs in the Schur complement, in any case, + * and this effect does not decrease the quality of the + * ordering itself, just the quality of the nonzero and + * flop count analysis. It also means that the post-ordering + * is not an exact elimination tree post-ordering. */ + + AMD_DEBUG1 ((" MASS i "ID" => parent e "ID"\n", i, me)) ; + Pe [i] = FLIP (me) ; + nvi = -Nv [i] ; + degme -= nvi ; + nvpiv += nvi ; + nel += nvi ; + Nv [i] = 0 ; + Elen [i] = EMPTY ; + + } + else + { + + /* --------------------------------------------------------- */ + /* update the upper-bound degree of i */ + /* --------------------------------------------------------- */ + + /* the following degree does not yet include the size + * of the current element, which is added later: */ + + Degree [i] = MIN (Degree [i], deg) ; + + /* --------------------------------------------------------- */ + /* add me to the list for i */ + /* --------------------------------------------------------- */ + + /* move first supervariable to end of list */ + Iw [pn] = Iw [p3] ; + /* move first element to end of element part of list */ + Iw [p3] = Iw [p1] ; + /* add new element, me, to front of list. */ + Iw [p1] = me ; + /* store the new length of the list in Len [i] */ + Len [i] = pn - p1 + 1 ; + + /* --------------------------------------------------------- */ + /* place in hash bucket. Save hash key of i in Last [i]. */ + /* --------------------------------------------------------- */ + + /* NOTE: this can fail if hash is negative, because the ANSI C + * standard does not define a % b when a and/or b are negative. + * That's why hash is defined as an unsigned Int, to avoid this + * problem. */ + hash = hash % n ; + ASSERT (((Int) hash) >= 0 && ((Int) hash) < n) ; + + /* if the Hhead array is not used: */ + j = Head [hash] ; + if (j <= EMPTY) + { + /* degree list is empty, hash head is FLIP (j) */ + Next [i] = FLIP (j) ; + Head [hash] = FLIP (i) ; + } + else + { + /* degree list is not empty, use Last [Head [hash]] as + * hash head. */ + Next [i] = Last [j] ; + Last [j] = i ; + } + + /* if a separate Hhead array is used: * + Next [i] = Hhead [hash] ; + Hhead [hash] = i ; + */ + + Last [i] = hash ; + } + } + + Degree [me] = degme ; + + /* ----------------------------------------------------------------- */ + /* Clear the counter array, W [...], by incrementing wflg. */ + /* ----------------------------------------------------------------- */ + + /* make sure that wflg+n does not cause integer overflow */ + lemax = MAX (lemax, degme) ; + wflg += lemax ; + wflg = clear_flag (wflg, wbig, W, n) ; + /* at this point, W [0..n-1] < wflg holds */ + +/* ========================================================================= */ +/* SUPERVARIABLE DETECTION */ +/* ========================================================================= */ + + AMD_DEBUG1 (("Detecting supervariables:\n")) ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + AMD_DEBUG2 (("Consider i "ID" nv "ID"\n", i, Nv [i])) ; + if (Nv [i] < 0) + { + /* i is a principal variable in Lme */ + + /* --------------------------------------------------------- + * examine all hash buckets with 2 or more variables. We do + * this by examing all unique hash keys for supervariables in + * the pattern Lme of the current element, me + * --------------------------------------------------------- */ + + /* let i = head of hash bucket, and empty the hash bucket */ + ASSERT (Last [i] >= 0 && Last [i] < n) ; + hash = Last [i] ; + + /* if Hhead array is not used: */ + j = Head [hash] ; + if (j == EMPTY) + { + /* hash bucket and degree list are both empty */ + i = EMPTY ; + } + else if (j < EMPTY) + { + /* degree list is empty */ + i = FLIP (j) ; + Head [hash] = EMPTY ; + } + else + { + /* degree list is not empty, restore Last [j] of head j */ + i = Last [j] ; + Last [j] = EMPTY ; + } + + /* if separate Hhead array is used: * + i = Hhead [hash] ; + Hhead [hash] = EMPTY ; + */ + + ASSERT (i >= EMPTY && i < n) ; + AMD_DEBUG2 (("----i "ID" hash "ID"\n", i, hash)) ; + + while (i != EMPTY && Next [i] != EMPTY) + { + + /* ----------------------------------------------------- + * this bucket has one or more variables following i. + * scan all of them to see if i can absorb any entries + * that follow i in hash bucket. Scatter i into w. + * ----------------------------------------------------- */ + + ln = Len [i] ; + eln = Elen [i] ; + ASSERT (ln >= 0 && eln >= 0) ; + ASSERT (Pe [i] >= 0 && Pe [i] < iwlen) ; + /* do not flag the first element in the list (me) */ + for (p = Pe [i] + 1 ; p <= Pe [i] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + W [Iw [p]] = wflg ; + } + + /* ----------------------------------------------------- */ + /* scan every other entry j following i in bucket */ + /* ----------------------------------------------------- */ + + jlast = i ; + j = Next [i] ; + ASSERT (j >= EMPTY && j < n) ; + + while (j != EMPTY) + { + /* ------------------------------------------------- */ + /* check if j and i have identical nonzero pattern */ + /* ------------------------------------------------- */ + + AMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; + + /* check if i and j have the same Len and Elen */ + ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; + ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; + ok = (Len [j] == ln) && (Elen [j] == eln) ; + /* skip the first element in the list (me) */ + for (p = Pe [j] + 1 ; ok && p <= Pe [j] + ln - 1 ; p++) + { + ASSERT (Iw [p] >= 0 && Iw [p] < n) ; + if (W [Iw [p]] != wflg) ok = 0 ; + } + if (ok) + { + /* --------------------------------------------- */ + /* found it! j can be absorbed into i */ + /* --------------------------------------------- */ + + AMD_DEBUG1 (("found it! j "ID" => i "ID"\n", j,i)); + Pe [j] = FLIP (i) ; + /* both Nv [i] and Nv [j] are negated since they */ + /* are in Lme, and the absolute values of each */ + /* are the number of variables in i and j: */ + Nv [i] += Nv [j] ; + Nv [j] = 0 ; + Elen [j] = EMPTY ; + /* delete j from hash bucket */ + ASSERT (j != Next [j]) ; + j = Next [j] ; + Next [jlast] = j ; + + } + else + { + /* j cannot be absorbed into i */ + jlast = j ; + ASSERT (j != Next [j]) ; + j = Next [j] ; + } + ASSERT (j >= EMPTY && j < n) ; + } + + /* ----------------------------------------------------- + * no more variables can be absorbed into i + * go to next i in bucket and clear flag array + * ----------------------------------------------------- */ + + wflg++ ; + i = Next [i] ; + ASSERT (i >= EMPTY && i < n) ; + + } + } + } + AMD_DEBUG2 (("detect done\n")) ; + +/* ========================================================================= */ +/* RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVARIABLES FROM ELEMENT */ +/* ========================================================================= */ + + p = pme1 ; + nleft = n - nel ; + for (pme = pme1 ; pme <= pme2 ; pme++) + { + i = Iw [pme] ; + ASSERT (i >= 0 && i < n) ; + nvi = -Nv [i] ; + AMD_DEBUG3 (("Restore i "ID" "ID"\n", i, nvi)) ; + if (nvi > 0) + { + /* i is a principal variable in Lme */ + /* restore Nv [i] to signify that i is principal */ + Nv [i] = nvi ; + + /* --------------------------------------------------------- */ + /* compute the external degree (add size of current element) */ + /* --------------------------------------------------------- */ + + deg = Degree [i] + degme - nvi ; + deg = MIN (deg, nleft - nvi) ; + ASSERT (IMPLIES (aggressive, deg > 0) && deg >= 0 && deg < n) ; + + /* --------------------------------------------------------- */ + /* place the supervariable at the head of the degree list */ + /* --------------------------------------------------------- */ + + inext = Head [deg] ; + ASSERT (inext >= EMPTY && inext < n) ; + if (inext != EMPTY) Last [inext] = i ; + Next [i] = inext ; + Last [i] = EMPTY ; + Head [deg] = i ; + + /* --------------------------------------------------------- */ + /* save the new degree, and find the minimum degree */ + /* --------------------------------------------------------- */ + + mindeg = MIN (mindeg, deg) ; + Degree [i] = deg ; + + /* --------------------------------------------------------- */ + /* place the supervariable in the element pattern */ + /* --------------------------------------------------------- */ + + Iw [p++] = i ; + + } + } + AMD_DEBUG2 (("restore done\n")) ; + +/* ========================================================================= */ +/* FINALIZE THE NEW ELEMENT */ +/* ========================================================================= */ + + AMD_DEBUG2 (("ME = "ID" DONE\n", me)) ; + Nv [me] = nvpiv ; + /* save the length of the list for the new element me */ + Len [me] = p - pme1 ; + if (Len [me] == 0) + { + /* there is nothing left of the current pivot element */ + /* it is a root of the assembly tree */ + Pe [me] = EMPTY ; + W [me] = 0 ; + } + if (elenme != 0) + { + /* element was not constructed in place: deallocate part of */ + /* it since newly nonprincipal variables may have been removed */ + pfree = p ; + } + + /* The new element has nvpiv pivots and the size of the contribution + * block for a multifrontal method is degme-by-degme, not including + * the "dense" rows/columns. If the "dense" rows/columns are included, + * the frontal matrix is no larger than + * (degme+ndense)-by-(degme+ndense). + */ + + if (Info != (double *) NULL) + { + f = nvpiv ; + r = degme + ndense ; + dmax = MAX (dmax, f + r) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = f*r + (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = f*r*r + r*(f-1)*f + (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + } + +#ifndef NDEBUG + AMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; + for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) + { + AMD_DEBUG3 ((" "ID"", Iw [pme])) ; + } + AMD_DEBUG3 (("\n")) ; +#endif + + } + +/* ========================================================================= */ +/* DONE SELECTING PIVOTS */ +/* ========================================================================= */ + + if (Info != (double *) NULL) + { + + /* count the work to factorize the ndense-by-ndense submatrix */ + f = ndense ; + dmax = MAX (dmax, (double) ndense) ; + + /* number of nonzeros in L (excluding the diagonal) */ + lnzme = (f-1)*f/2 ; + lnz += lnzme ; + + /* number of divide operations for LDL' and for LU */ + ndiv += lnzme ; + + /* number of multiply-subtract pairs for LU */ + s = (f-1)*f*(2*f-1)/6 ; + nms_lu += s ; + + /* number of multiply-subtract pairs for LDL' */ + nms_ldl += (s + lnzme)/2 ; + + /* number of nz's in L (excl. diagonal) */ + Info [AMD_LNZ] = lnz ; + + /* number of divide ops for LU and LDL' */ + Info [AMD_NDIV] = ndiv ; + + /* number of multiply-subtract pairs for LDL' */ + Info [AMD_NMULTSUBS_LDL] = nms_ldl ; + + /* number of multiply-subtract pairs for LU */ + Info [AMD_NMULTSUBS_LU] = nms_lu ; + + /* number of "dense" rows/columns */ + Info [AMD_NDENSE] = ndense ; + + /* largest front is dmax-by-dmax */ + Info [AMD_DMAX] = dmax ; + + /* number of garbage collections in AMD */ + Info [AMD_NCMPA] = ncmpa ; + + /* successful ordering */ + Info [AMD_STATUS] = AMD_OK ; + } + +/* ========================================================================= */ +/* POST-ORDERING */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- + * Variables at this point: + * + * Pe: holds the elimination tree. The parent of j is FLIP (Pe [j]), + * or EMPTY if j is a root. The tree holds both elements and + * non-principal (unordered) variables absorbed into them. + * Dense variables are non-principal and unordered. + * + * Elen: holds the size of each element, including the diagonal part. + * FLIP (Elen [e]) > 0 if e is an element. For unordered + * variables i, Elen [i] is EMPTY. + * + * Nv: Nv [e] > 0 is the number of pivots represented by the element e. + * For unordered variables i, Nv [i] is zero. + * + * Contents no longer needed: + * W, Iw, Len, Degree, Head, Next, Last. + * + * The matrix itself has been destroyed. + * + * n: the size of the matrix. + * No other scalars needed (pfree, iwlen, etc.) + * ------------------------------------------------------------------------- */ + + /* restore Pe */ + for (i = 0 ; i < n ; i++) + { + Pe [i] = FLIP (Pe [i]) ; + } + + /* restore Elen, for output information, and for postordering */ + for (i = 0 ; i < n ; i++) + { + Elen [i] = FLIP (Elen [i]) ; + } + +/* Now the parent of j is Pe [j], or EMPTY if j is a root. Elen [e] > 0 + * is the size of element e. Elen [i] is EMPTY for unordered variable i. */ + +#ifndef NDEBUG + AMD_DEBUG2 (("\nTree:\n")) ; + for (i = 0 ; i < n ; i++) + { + AMD_DEBUG2 ((" "ID" parent: "ID" ", i, Pe [i])) ; + ASSERT (Pe [i] >= EMPTY && Pe [i] < n) ; + if (Nv [i] > 0) + { + /* this is an element */ + e = i ; + AMD_DEBUG2 ((" element, size is "ID"\n", Elen [i])) ; + ASSERT (Elen [e] > 0) ; + } + AMD_DEBUG2 (("\n")) ; + } + AMD_DEBUG2 (("\nelements:\n")) ; + for (e = 0 ; e < n ; e++) + { + if (Nv [e] > 0) + { + AMD_DEBUG3 (("Element e= "ID" size "ID" nv "ID" \n", e, + Elen [e], Nv [e])) ; + } + } + AMD_DEBUG2 (("\nvariables:\n")) ; + for (i = 0 ; i < n ; i++) + { + Int cnt ; + if (Nv [i] == 0) + { + AMD_DEBUG3 (("i unordered: "ID"\n", i)) ; + j = Pe [i] ; + cnt = 0 ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + AMD_DEBUG3 ((" i is a dense variable\n")) ; + } + else + { + ASSERT (j >= 0 && j < n) ; + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + cnt++ ; + if (cnt > n) break ; + } + e = j ; + AMD_DEBUG3 ((" got to e: "ID"\n", e)) ; + } + } + } +#endif + +/* ========================================================================= */ +/* compress the paths of the variables */ +/* ========================================================================= */ + + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + + /* ------------------------------------------------------------- + * i is an un-ordered row. Traverse the tree from i until + * reaching an element, e. The element, e, was the principal + * supervariable of i and all nodes in the path from i to when e + * was selected as pivot. + * ------------------------------------------------------------- */ + + AMD_DEBUG1 (("Path compression, i unordered: "ID"\n", i)) ; + j = Pe [i] ; + ASSERT (j >= EMPTY && j < n) ; + AMD_DEBUG3 ((" j: "ID"\n", j)) ; + if (j == EMPTY) + { + /* Skip a dense variable. It has no parent. */ + AMD_DEBUG3 ((" i is a dense variable\n")) ; + continue ; + } + + /* while (j is a variable) */ + while (Nv [j] == 0) + { + AMD_DEBUG3 ((" j : "ID"\n", j)) ; + j = Pe [j] ; + AMD_DEBUG3 ((" j:: "ID"\n", j)) ; + ASSERT (j >= 0 && j < n) ; + } + /* got to an element e */ + e = j ; + AMD_DEBUG3 (("got to e: "ID"\n", e)) ; + + /* ------------------------------------------------------------- + * traverse the path again from i to e, and compress the path + * (all nodes point to e). Path compression allows this code to + * compute in O(n) time. + * ------------------------------------------------------------- */ + + j = i ; + /* while (j is a variable) */ + while (Nv [j] == 0) + { + jnext = Pe [j] ; + AMD_DEBUG3 (("j "ID" jnext "ID"\n", j, jnext)) ; + Pe [j] = e ; + j = jnext ; + ASSERT (j >= 0 && j < n) ; + } + } + } + +/* ========================================================================= */ +/* postorder the assembly tree */ +/* ========================================================================= */ + + AMD_postorder (n, Pe, Nv, Elen, + W, /* output order */ + Head, Next, Last) ; /* workspace */ + +/* ========================================================================= */ +/* compute output permutation and inverse permutation */ +/* ========================================================================= */ + + /* W [e] = k means that element e is the kth element in the new + * order. e is in the range 0 to n-1, and k is in the range 0 to + * the number of elements. Use Head for inverse order. */ + + for (k = 0 ; k < n ; k++) + { + Head [k] = EMPTY ; + Next [k] = EMPTY ; + } + for (e = 0 ; e < n ; e++) + { + k = W [e] ; + ASSERT ((k == EMPTY) == (Nv [e] == 0)) ; + if (k != EMPTY) + { + ASSERT (k >= 0 && k < n) ; + Head [k] = e ; + } + } + + /* construct output inverse permutation in Next, + * and permutation in Last */ + nel = 0 ; + for (k = 0 ; k < n ; k++) + { + e = Head [k] ; + if (e == EMPTY) break ; + ASSERT (e >= 0 && e < n && Nv [e] > 0) ; + Next [e] = nel ; + nel += Nv [e] ; + } + ASSERT (nel == n - ndense) ; + + /* order non-principal variables (dense, & those merged into supervar's) */ + for (i = 0 ; i < n ; i++) + { + if (Nv [i] == 0) + { + e = Pe [i] ; + ASSERT (e >= EMPTY && e < n) ; + if (e != EMPTY) + { + /* This is an unordered variable that was merged + * into element e via supernode detection or mass + * elimination of i when e became the pivot element. + * Place i in order just before e. */ + ASSERT (Next [i] == EMPTY && Nv [e] > 0) ; + Next [i] = Next [e] ; + Next [e]++ ; + } + else + { + /* This is a dense unordered variable, with no parent. + * Place it last in the output order. */ + Next [i] = nel++ ; + } + } + } + ASSERT (nel == n) ; + + AMD_DEBUG2 (("\n\nPerm:\n")) ; + for (i = 0 ; i < n ; i++) + { + k = Next [i] ; + ASSERT (k >= 0 && k < n) ; + Last [k] = i ; + AMD_DEBUG2 ((" perm ["ID"] = "ID"\n", k, i)) ; + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_aat.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_aat.c new file mode 100644 index 000000000..63bf55f52 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_aat.c @@ -0,0 +1,185 @@ +/* ========================================================================= */ +/* === AMD_aat ============================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* AMD_aat: compute the symmetry of the pattern of A, and count the number of + * nonzeros each column of A+A' (excluding the diagonal). Assumes the input + * matrix has no errors, with sorted columns and no duplicates + * (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not + * checked). + */ + +#include "amd_internal.h" + +GLOBAL size_t AMD_aat /* returns nz in A+A' */ +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/ + Int Tp [ ], /* workspace of size n */ + double Info [ ] +) +{ + Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz ; + double sym ; + size_t nzaat ; + +#ifndef NDEBUG + AMD_debug_init ("AMD AAT") ; + for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; + ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; +#endif + + if (Info != (double *) NULL) + { + /* clear the Info array, if it exists */ + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_STATUS] = AMD_OK ; + } + + for (k = 0 ; k < n ; k++) + { + Len [k] = 0 ; + } + + nzdiag = 0 ; + nzboth = 0 ; + nz = Ap [n] ; + + for (k = 0 ; k < n ; k++) + { + p1 = Ap [k] ; + p2 = Ap [k+1] ; + AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ; + + /* construct A+A' */ + for (p = p1 ; p < p2 ; ) + { + /* scan the upper triangular part of A */ + j = Ai [p] ; + if (j < k) + { + /* entry A (j,k) is in the strictly upper triangular part, + * add both A (j,k) and A (k,j) to the matrix A+A' */ + Len [j]++ ; + Len [k]++ ; + AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j)); + p++ ; + } + else if (j == k) + { + /* skip the diagonal */ + p++ ; + nzdiag++ ; + break ; + } + else /* j > k */ + { + /* first entry below the diagonal */ + break ; + } + /* scan lower triangular part of A, in column j until reaching + * row k. Start where last scan left off. */ + ASSERT (Tp [j] != EMPTY) ; + ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; + pj2 = Ap [j+1] ; + for (pj = Tp [j] ; pj < pj2 ; ) + { + i = Ai [pj] ; + if (i < k) + { + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + pj++ ; + } + else if (i == k) + { + /* entry A (k,j) in lower part and A (j,k) in upper */ + pj++ ; + nzboth++ ; + break ; + } + else /* i > k */ + { + /* consider this entry later, when k advances to i */ + break ; + } + } + Tp [j] = pj ; + } + /* Tp [k] points to the entry just below the diagonal in column k */ + Tp [k] = p ; + } + + /* clean up, for remaining mismatched entries */ + for (j = 0 ; j < n ; j++) + { + for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) + { + i = Ai [pj] ; + /* A (i,j) is only in the lower part, not in upper. + * add both A (i,j) and A (j,i) to the matrix A+A' */ + Len [i]++ ; + Len [j]++ ; + AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n", + i,j, j,i)) ; + } + } + + /* --------------------------------------------------------------------- */ + /* compute the symmetry of the nonzero pattern of A */ + /* --------------------------------------------------------------------- */ + + /* Given a matrix A, the symmetry of A is: + * B = tril (spones (A), -1) + triu (spones (A), 1) ; + * sym = nnz (B & B') / nnz (B) ; + * or 1 if nnz (B) is zero. + */ + + if (nz == nzdiag) + { + sym = 1 ; + } + else + { + sym = (2 * (double) nzboth) / ((double) (nz - nzdiag)) ; + } + + nzaat = 0 ; + for (k = 0 ; k < n ; k++) + { + nzaat += Len [k] ; + } + + AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = %g\n", + (double) nzaat)) ; + AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", + nzboth, nz, nzdiag, sym)) ; + + if (Info != (double *) NULL) + { + Info [AMD_STATUS] = AMD_OK ; + Info [AMD_N] = n ; + Info [AMD_NZ] = nz ; + Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ + Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ + Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ + } + + return (nzaat) ; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_control.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_control.c new file mode 100644 index 000000000..f4d4f0dfa --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_control.c @@ -0,0 +1,64 @@ +/* ========================================================================= */ +/* === AMD_control ========================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the control parameters for AMD. See amd.h + * for details. If the Control array is not present, the defaults are + * printed instead. + */ + +#include "amd_internal.h" + +GLOBAL void AMD_control +( + double Control [ ] +) +{ + double alpha ; + Int aggressive ; + + if (Control != (double *) NULL) + { + alpha = Control [AMD_DENSE] ; + aggressive = Control [AMD_AGGRESSIVE] != 0 ; + } + else + { + alpha = AMD_DEFAULT_DENSE ; + aggressive = AMD_DEFAULT_AGGRESSIVE ; + } + + PRINTF (("\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n" + " dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, + AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ; + + if (alpha < 0) + { + PRINTF ((" no rows treated as dense\n")) ; + } + else + { + PRINTF (( + " (rows with more than max (%g * sqrt (n), 16) entries are\n" + " considered \"dense\", and placed last in output permutation)\n", + alpha)) ; + } + + if (aggressive) + { + PRINTF ((" aggressive absorption: yes\n")) ; + } + else + { + PRINTF ((" aggressive absorption: no\n")) ; + } + + PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_defaults.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_defaults.c new file mode 100644 index 000000000..820e89420 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_defaults.c @@ -0,0 +1,38 @@ +/* ========================================================================= */ +/* === AMD_defaults ======================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Sets default control parameters for AMD. See amd.h + * for details. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD defaults ======================================================== */ +/* ========================================================================= */ + +GLOBAL void AMD_defaults +( + double Control [ ] +) +{ + Int i ; + + if (Control != (double *) NULL) + { + for (i = 0 ; i < AMD_CONTROL ; i++) + { + Control [i] = 0 ; + } + Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; + Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_dump.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_dump.c new file mode 100644 index 000000000..39bbe1d8e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_dump.c @@ -0,0 +1,180 @@ +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Debugging routines for AMD. Not used if NDEBUG is not defined at compile- + * time (the default). See comments in amd_internal.h on how to enable + * debugging. Not user-callable. + */ + +#include "amd_internal.h" + +#ifndef NDEBUG + +/* This global variable is present only when debugging */ +GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */ + +/* ========================================================================= */ +/* === AMD_debug_init ====================================================== */ +/* ========================================================================= */ + +/* Sets the debug print level, by reading the file debug.amd (if it exists) */ + +GLOBAL void AMD_debug_init ( char *s ) +{ + FILE *f ; + f = fopen ("debug.amd", "r") ; + if (f == (FILE *) NULL) + { + AMD_debug = -999 ; + } + else + { + fscanf (f, ID, &AMD_debug) ; + fclose (f) ; + } + if (AMD_debug >= 0) + { + printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug) ; + } +} + +/* ========================================================================= */ +/* === AMD_dump ============================================================ */ +/* ========================================================================= */ + +/* Dump AMD's data structure, except for the hash buckets. This routine + * cannot be called when the hash buckets are non-empty. + */ + +GLOBAL void AMD_dump ( + Int n, /* A is n-by-n */ + Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */ + Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1] + * holds the matrix on input */ + Int Len [ ], /* len [0..n-1]: length for row i */ + Int iwlen, /* length of iw */ + Int pfree, /* iw [pfree ... iwlen-1] is empty on input */ + Int Nv [ ], /* nv [0..n-1] */ + Int Next [ ], /* next [0..n-1] */ + Int Last [ ], /* last [0..n-1] */ + Int Head [ ], /* head [0..n-1] */ + Int Elen [ ], /* size n */ + Int Degree [ ], /* size n */ + Int W [ ], /* size n */ + Int nel +) +{ + Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; + + if (AMD_debug < 0) return ; + ASSERT (pfree <= iwlen) ; + AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ; + for (i = 0 ; i < n ; i++) + { + pe = Pe [i] ; + elen = Elen [i] ; + nv = Nv [i] ; + len = Len [i] ; + w = W [i] ; + + if (elen >= EMPTY) + { + if (nv == 0) + { + AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ; + ASSERT (elen == EMPTY) ; + if (pe == EMPTY) + { + AMD_DEBUG3 ((" dense node\n")) ; + ASSERT (w == 1) ; + } + else + { + ASSERT (pe < EMPTY) ; + AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); + } + } + else + { + AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i)); + AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; + ASSERT (elen >= 0) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" e/s: ")) ; + if (elen == 0) AMD_DEBUG3 ((" : ")) ; + ASSERT (pe + len <= pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + if (k == elen-1) AMD_DEBUG3 ((" : ")) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + else + { + e = i ; + if (w == 0) + { + AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe < 0) ; + AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; + } + else + { + AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; + ASSERT (nv > 0 && pe >= 0) ; + p = pe ; + AMD_DEBUG3 ((" : ")) ; + ASSERT (pe + len <= pfree) ; + for (k = 0 ; k < len ; k++) + { + j = Iw [p] ; + AMD_DEBUG3 ((" "ID"", j)) ; + ASSERT (j >= 0 && j < n) ; + p++ ; + } + AMD_DEBUG3 (("\n")) ; + } + } + } + + /* this routine cannot be called when the hash buckets are non-empty */ + AMD_DEBUG3 (("\nDegree lists:\n")) ; + if (nel >= 0) + { + cnt = 0 ; + for (deg = 0 ; deg < n ; deg++) + { + if (Head [deg] == EMPTY) continue ; + ilast = EMPTY ; + AMD_DEBUG3 ((ID": \n", deg)) ; + for (i = Head [deg] ; i != EMPTY ; i = Next [i]) + { + AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n", + i, Next [i], Last [i], Degree [i])) ; + ASSERT (i >= 0 && i < n && ilast == Last [i] && + deg == Degree [i]) ; + cnt += Nv [i] ; + ilast = i ; + } + AMD_DEBUG3 (("\n")) ; + } + ASSERT (cnt == n - nel) ; + } + +} + +#endif diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_info.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_info.c new file mode 100644 index 000000000..e7b806a97 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_info.c @@ -0,0 +1,120 @@ +/* ========================================================================= */ +/* === AMD_info ============================================================ */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable. Prints the output statistics for AMD. See amd.h + * for details. If the Info array is not present, nothing is printed. + */ + +#include "amd_internal.h" + +#define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }} + +GLOBAL void AMD_info +( + double Info [ ] +) +{ + double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; + + PRINTF (("\nAMD version %d.%d.%d, %s, results:\n", + AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ; + + if (!Info) + { + return ; + } + + n = Info [AMD_N] ; + ndiv = Info [AMD_NDIV] ; + nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ; + nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ; + lnz = Info [AMD_LNZ] ; + lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; + + /* AMD return status */ + PRINTF ((" status: ")) ; + if (Info [AMD_STATUS] == AMD_OK) + { + PRINTF (("OK\n")) ; + } + else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) + { + PRINTF (("out of memory\n")) ; + } + else if (Info [AMD_STATUS] == AMD_INVALID) + { + PRINTF (("invalid matrix\n")) ; + } + else if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED) + { + PRINTF (("OK, but jumbled\n")) ; + } + else + { + PRINTF (("unknown\n")) ; + } + + /* statistics about the input matrix */ + PRI (" n, dimension of A: %.20g\n", n); + PRI (" nz, number of nonzeros in A: %.20g\n", + Info [AMD_NZ]) ; + PRI (" symmetry of A: %.4f\n", + Info [AMD_SYMMETRY]) ; + PRI (" number of nonzeros on diagonal: %.20g\n", + Info [AMD_NZDIAG]) ; + PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", + Info [AMD_NZ_A_PLUS_AT]) ; + PRI (" # dense rows/columns of A+A': %.20g\n", + Info [AMD_NDENSE]) ; + + /* statistics about AMD's behavior */ + PRI (" memory used, in bytes: %.20g\n", + Info [AMD_MEMORY]) ; + PRI (" # of memory compactions: %.20g\n", + Info [AMD_NCMPA]) ; + + /* statistics about the ordering quality */ + PRINTF (("\n" + " The following approximate statistics are for a subsequent\n" + " factorization of A(P,P) + A(P,P)'. They are slight upper\n" + " bounds if there are no dense rows/columns in A+A', and become\n" + " looser if dense rows/columns exist.\n\n")) ; + + PRI (" nonzeros in L (excluding diagonal): %.20g\n", + lnz) ; + PRI (" nonzeros in L (including diagonal): %.20g\n", + lnzd) ; + PRI (" # divide operations for LDL' or LU: %.20g\n", + ndiv) ; + PRI (" # multiply-subtract operations for LDL': %.20g\n", + nmultsubs_ldl) ; + PRI (" # multiply-subtract operations for LU: %.20g\n", + nmultsubs_lu) ; + PRI (" max nz. in any column of L (incl. diagonal): %.20g\n", + Info [AMD_DMAX]) ; + + /* total flop counts for various factorizations */ + + if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) + { + PRINTF (("\n" + " chol flop count for real A, sqrt counted as 1 flop: %.20g\n" + " LDL' flop count for real A: %.20g\n" + " LDL' flop count for complex A: %.20g\n" + " LU flop count for real A (with no pivoting): %.20g\n" + " LU flop count for complex A (with no pivoting): %.20g\n\n", + n + ndiv + 2*nmultsubs_ldl, + ndiv + 2*nmultsubs_ldl, + 9*ndiv + 8*nmultsubs_ldl, + ndiv + 2*nmultsubs_lu, + 9*ndiv + 8*nmultsubs_lu)) ; + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_internal.h b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_internal.h new file mode 100644 index 000000000..b08f8436b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_internal.h @@ -0,0 +1,117 @@ +/* amd_internal.h */ + +/* Written by Andrew Makhorin . */ + +#ifndef AMD_INTERNAL_H +#define AMD_INTERNAL_H + +/* AMD will be exceedingly slow when running in debug mode. */ +#if 1 +#define NDEBUG +#endif + +#include "amd.h" +#define _GLPSTD_STDIO +#include "env.h" + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX + +#if 0 /* 15/II-2012 */ +/* now this macro is defined in glpenv.h; besides, the definiton below + depends on implementation, because size_t is an unsigned type */ +#define SIZE_T_MAX ((size_t)(-1)) +#endif + +#define EMPTY (-1) +#define FLIP(i) (-(i)-2) +#define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i)) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define IMPLIES(p, q) (!(p) || (q)) + +#define GLOBAL + +#define AMD_order amd_order +#define AMD_defaults amd_defaults +#define AMD_control amd_control +#define AMD_info amd_info +#define AMD_1 amd_1 +#define AMD_2 amd_2 +#define AMD_valid amd_valid +#define AMD_aat amd_aat +#define AMD_postorder amd_postorder +#define AMD_post_tree amd_post_tree +#define AMD_dump amd_dump +#define AMD_debug amd_debug +#define AMD_debug_init amd_debug_init +#define AMD_preprocess amd_preprocess + +#define amd_malloc xmalloc +#if 0 /* 24/V-2009 */ +#define amd_free xfree +#else +#define amd_free(ptr) { if ((ptr) != NULL) xfree(ptr); } +#endif +#define amd_printf xprintf + +#define PRINTF(params) { amd_printf params; } + +#ifndef NDEBUG +#define ASSERT(expr) xassert(expr) +#define AMD_DEBUG0(params) { PRINTF(params); } +#define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF(params); } +#define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF(params); } +#define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF(params); } +#define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF(params); } +#else +#define ASSERT(expression) +#define AMD_DEBUG0(params) +#define AMD_DEBUG1(params) +#define AMD_DEBUG2(params) +#define AMD_DEBUG3(params) +#define AMD_DEBUG4(params) +#endif + +#define amd_aat _glp_amd_aat +size_t AMD_aat(Int n, const Int Ap[], const Int Ai[], Int Len[], + Int Tp[], double Info[]); + +#define amd_1 _glp_amd_1 +void AMD_1(Int n, const Int Ap[], const Int Ai[], Int P[], Int Pinv[], + Int Len[], Int slen, Int S[], double Control[], double Info[]); + +#define amd_postorder _glp_amd_postorder +void AMD_postorder(Int nn, Int Parent[], Int Npiv[], Int Fsize[], + Int Order[], Int Child[], Int Sibling[], Int Stack[]); + +#define amd_post_tree _glp_amd_post_tree +#ifndef NDEBUG +Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], + Int Order[], Int Stack[], Int nn); +#else +Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], + Int Order[], Int Stack[]); +#endif + +#define amd_preprocess _glp_amd_preprocess +void AMD_preprocess(Int n, const Int Ap[], const Int Ai[], Int Rp[], + Int Ri[], Int W[], Int Flag[]); + +#define amd_debug _glp_amd_debug +extern Int AMD_debug; + +#define amd_debug_init _glp_amd_debug_init +void AMD_debug_init(char *s); + +#define amd_dump _glp_amd_dump +void AMD_dump(Int n, Int Pe[], Int Iw[], Int Len[], Int iwlen, + Int pfree, Int Nv[], Int Next[], Int Last[], Int Head[], + Int Elen[], Int Degree[], Int W[], Int nel); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_order.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_order.c new file mode 100644 index 000000000..332d56637 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_order.c @@ -0,0 +1,200 @@ +/* ========================================================================= */ +/* === AMD_order =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* User-callable AMD minimum degree ordering routine. See amd.h for + * documentation. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD_order =========================================================== */ +/* ========================================================================= */ + +GLOBAL Int AMD_order +( + Int n, + const Int Ap [ ], + const Int Ai [ ], + Int P [ ], + double Control [ ], + double Info [ ] +) +{ + Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; + size_t nzaat, slen ; + double mem = 0 ; + +#ifndef NDEBUG + AMD_debug_init ("amd") ; +#endif + + /* clear the Info array, if it exists */ + info = Info != (double *) NULL ; + if (info) + { + for (i = 0 ; i < AMD_INFO ; i++) + { + Info [i] = EMPTY ; + } + Info [AMD_N] = n ; + Info [AMD_STATUS] = AMD_OK ; + } + + /* make sure inputs exist and n is >= 0 */ + if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* arguments are invalid */ + } + + if (n == 0) + { + return (AMD_OK) ; /* n is 0 so there's nothing to do */ + } + + nz = Ap [n] ; + if (info) + { + Info [AMD_NZ] = nz ; + } + if (nz < 0) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; + } + + /* check if n or nz will cause size_t overflow */ + if (((size_t) n) >= SIZE_T_MAX / sizeof (Int) + || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int)) + { + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; /* problem too large */ + } + + /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */ + status = AMD_valid (n, n, Ap, Ai) ; + + if (status == AMD_INVALID) + { + if (info) Info [AMD_STATUS] = AMD_INVALID ; + return (AMD_INVALID) ; /* matrix is invalid */ + } + + /* allocate two size-n integer workspaces */ + Len = amd_malloc (n * sizeof (Int)) ; + Pinv = amd_malloc (n * sizeof (Int)) ; + mem += n ; + mem += n ; + if (!Len || !Pinv) + { + /* :: out of memory :: */ + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + + if (status == AMD_OK_BUT_JUMBLED) + { + /* sort the input matrix and remove duplicate entries */ + AMD_DEBUG1 (("Matrix is jumbled\n")) ; + Rp = amd_malloc ((n+1) * sizeof (Int)) ; + Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ; + mem += (n+1) ; + mem += MAX (nz,1) ; + if (!Rp || !Ri) + { + /* :: out of memory :: */ + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + /* use Len and Pinv as workspace to create R = A' */ + AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; + Cp = Rp ; + Ci = Ri ; + } + else + { + /* order the input matrix as-is. No need to compute R = A' first */ + Rp = NULL ; + Ri = NULL ; + Cp = (Int *) Ap ; + Ci = (Int *) Ai ; + } + + /* --------------------------------------------------------------------- */ + /* determine the symmetry and count off-diagonal nonzeros in A+A' */ + /* --------------------------------------------------------------------- */ + + nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ; + AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; + ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; + + /* --------------------------------------------------------------------- */ + /* allocate workspace for matrix, elbow room, and 6 size-n vectors */ + /* --------------------------------------------------------------------- */ + + S = NULL ; + slen = nzaat ; /* space for matrix */ + ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ + slen += nzaat/5 ; /* add elbow room */ + for (i = 0 ; ok && i < 7 ; i++) + { + ok = ((slen + n) > slen) ; /* check for size_t overflow */ + slen += n ; /* size-n elbow room, 6 size-n work */ + } + mem += slen ; + ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ + ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */ + if (ok) + { + S = amd_malloc (slen * sizeof (Int)) ; + } + AMD_DEBUG1 (("slen %g\n", (double) slen)) ; + if (!S) + { + /* :: out of memory :: (or problem too large) */ + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; + return (AMD_OUT_OF_MEMORY) ; + } + if (info) + { + /* memory usage, in bytes. */ + Info [AMD_MEMORY] = mem * sizeof (Int) ; + } + + /* --------------------------------------------------------------------- */ + /* order the matrix */ + /* --------------------------------------------------------------------- */ + + AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ; + + /* --------------------------------------------------------------------- */ + /* free the workspace */ + /* --------------------------------------------------------------------- */ + + amd_free (Rp) ; + amd_free (Ri) ; + amd_free (Len) ; + amd_free (Pinv) ; + amd_free (S) ; + if (info) Info [AMD_STATUS] = status ; + return (status) ; /* successful ordering */ +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_post_tree.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_post_tree.c new file mode 100644 index 000000000..bff0e263a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_post_tree.c @@ -0,0 +1,121 @@ +/* ========================================================================= */ +/* === AMD_post_tree ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Post-ordering of a supernodal elimination tree. */ + +#include "amd_internal.h" + +GLOBAL Int AMD_post_tree +( + Int root, /* root of the tree */ + Int k, /* start numbering at k */ + Int Child [ ], /* input argument of size nn, undefined on + * output. Child [i] is the head of a link + * list of all nodes that are children of node + * i in the tree. */ + const Int Sibling [ ], /* input argument of size nn, not modified. + * If f is a node in the link list of the + * children of node i, then Sibling [f] is the + * next child of node i. + */ + Int Order [ ], /* output order, of size nn. Order [i] = k + * if node i is the kth node of the reordered + * tree. */ + Int Stack [ ] /* workspace of size nn */ +#ifndef NDEBUG + , Int nn /* nodes are in the range 0..nn-1. */ +#endif +) +{ + Int f, head, h, i ; + +#if 0 + /* --------------------------------------------------------------------- */ + /* recursive version (Stack [ ] is not used): */ + /* --------------------------------------------------------------------- */ + + /* this is simple, but can caouse stack overflow if nn is large */ + i = root ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; + } + Order [i] = k++ ; + return (k) ; +#endif + + /* --------------------------------------------------------------------- */ + /* non-recursive version, using an explicit stack */ + /* --------------------------------------------------------------------- */ + + /* push root on the stack */ + head = 0 ; + Stack [0] = root ; + + while (head >= 0) + { + /* get head of stack */ + ASSERT (head < nn) ; + i = Stack [head] ; + AMD_DEBUG1 (("head of stack "ID" \n", i)) ; + ASSERT (i >= 0 && i < nn) ; + + if (Child [i] != EMPTY) + { + /* the children of i are not yet ordered */ + /* push each child onto the stack in reverse order */ + /* so that small ones at the head of the list get popped first */ + /* and the biggest one at the end of the list gets popped last */ + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + head++ ; + ASSERT (head < nn) ; + ASSERT (f >= 0 && f < nn) ; + } + h = head ; + ASSERT (head < nn) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (h > 0) ; + Stack [h--] = f ; + AMD_DEBUG1 (("push "ID" on stack\n", f)) ; + ASSERT (f >= 0 && f < nn) ; + } + ASSERT (Stack [h] == i) ; + + /* delete child list so that i gets ordered next time we see it */ + Child [i] = EMPTY ; + } + else + { + /* the children of i (if there were any) are already ordered */ + /* remove i from the stack and order it. Front i is kth front */ + head-- ; + AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; + Order [i] = k++ ; + ASSERT (k <= nn) ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("\nStack:")) ; + for (h = head ; h >= 0 ; h--) + { + Int j = Stack [h] ; + AMD_DEBUG1 ((" "ID, j)) ; + ASSERT (j >= 0 && j < nn) ; + } + AMD_DEBUG1 (("\n\n")) ; + ASSERT (head < nn) ; +#endif + + } + return (k) ; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_postorder.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_postorder.c new file mode 100644 index 000000000..a3ece915c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_postorder.c @@ -0,0 +1,207 @@ +/* ========================================================================= */ +/* === AMD_postorder ======================================================= */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Perform a postordering (via depth-first search) of an assembly tree. */ + +#include "amd_internal.h" + +GLOBAL void AMD_postorder +( + /* inputs, not modified on output: */ + Int nn, /* nodes are in the range 0..nn-1 */ + Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */ + Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j, + * or zero if j is not a node. */ + Int Fsize [ ], /* Fsize [j]: size of node j */ + + /* output, not defined on input: */ + Int Order [ ], /* output post-order */ + + /* workspaces of size nn: */ + Int Child [ ], + Int Sibling [ ], + Int Stack [ ] +) +{ + Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; + + for (j = 0 ; j < nn ; j++) + { + Child [j] = EMPTY ; + Sibling [j] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* place the children in link lists - bigger elements tend to be last */ + /* --------------------------------------------------------------------- */ + + for (j = nn-1 ; j >= 0 ; j--) + { + if (Nv [j] > 0) + { + /* this is an element */ + parent = Parent [j] ; + if (parent != EMPTY) + { + /* place the element in link list of the children its parent */ + /* bigger elements will tend to be at the end of the list */ + Sibling [j] = Child [parent] ; + Child [parent] = j ; + } + } + } + +#ifndef NDEBUG + { + Int nels, ff, nchild ; + AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n")); + nels = 0 ; + for (j = 0 ; j < nn ; j++) + { + if (Nv [j] > 0) + { + AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID + " parent "ID" maxfr "ID"\n", j, nels, + Nv [j], Fsize [j], Parent [j], Fsize [j])) ; + /* this is an element */ + /* dump the link list of children */ + nchild = 0 ; + AMD_DEBUG1 ((" Children: ")) ; + for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) + { + AMD_DEBUG1 ((ID" ", ff)) ; + ASSERT (Parent [ff] == j) ; + nchild++ ; + ASSERT (nchild < nn) ; + } + AMD_DEBUG1 (("\n")) ; + parent = Parent [j] ; + if (parent != EMPTY) + { + ASSERT (Nv [parent] > 0) ; + } + nels++ ; + } + } + } + AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n" + "the biggest child last in each list:\n")) ; +#endif + + /* --------------------------------------------------------------------- */ + /* place the largest child last in the list of children for each node */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + if (Nv [i] > 0 && Child [i] != EMPTY) + { + +#ifndef NDEBUG + Int nchild ; + AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ; + nchild = 0 ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; + nchild++ ; + ASSERT (nchild <= nn) ; + } +#endif + + /* find the biggest element in the child list */ + fprev = EMPTY ; + maxfrsize = EMPTY ; + bigfprev = EMPTY ; + bigf = EMPTY ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + frsize = Fsize [f] ; + if (frsize >= maxfrsize) + { + /* this is the biggest seen so far */ + maxfrsize = frsize ; + bigfprev = fprev ; + bigf = f ; + } + fprev = f ; + } + ASSERT (bigf != EMPTY) ; + + fnext = Sibling [bigf] ; + + AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID + " fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ; + + if (fnext != EMPTY) + { + /* if fnext is EMPTY then bigf is already at the end of list */ + + if (bigfprev == EMPTY) + { + /* delete bigf from the element of the list */ + Child [i] = fnext ; + } + else + { + /* delete bigf from the middle of the list */ + Sibling [bigfprev] = fnext ; + } + + /* put bigf at the end of the list */ + Sibling [bigf] = EMPTY ; + ASSERT (Child [i] != EMPTY) ; + ASSERT (fprev != bigf) ; + ASSERT (fprev != EMPTY) ; + Sibling [fprev] = bigf ; + } + +#ifndef NDEBUG + AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ; + for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) + { + ASSERT (f >= 0 && f < nn) ; + AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; + ASSERT (Nv [f] > 0) ; + nchild-- ; + } + ASSERT (nchild == 0) ; +#endif + + } + } + + /* --------------------------------------------------------------------- */ + /* postorder the assembly tree */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < nn ; i++) + { + Order [i] = EMPTY ; + } + + k = 0 ; + + for (i = 0 ; i < nn ; i++) + { + if (Parent [i] == EMPTY && Nv [i] > 0) + { + AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ; + k = AMD_post_tree (i, k, Child, Sibling, Order, Stack +#ifndef NDEBUG + , nn +#endif + ) ; + } + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_preprocess.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_preprocess.c new file mode 100644 index 000000000..fc223fb51 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_preprocess.c @@ -0,0 +1,119 @@ +/* ========================================================================= */ +/* === AMD_preprocess ====================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of + * a column-form matrix A, to obtain the matrix R. The input matrix can have + * duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be + * AMD_INVALID). + * + * This input condition is NOT checked. This routine is not user-callable. + */ + +#include "amd_internal.h" + +/* ========================================================================= */ +/* === AMD_preprocess ====================================================== */ +/* ========================================================================= */ + +/* AMD_preprocess does not check its input for errors or allocate workspace. + * On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold. + */ + +GLOBAL void AMD_preprocess +( + Int n, /* input matrix: A is n-by-n */ + const Int Ap [ ], /* size n+1 */ + const Int Ai [ ], /* size nz = Ap [n] */ + + /* output matrix R: */ + Int Rp [ ], /* size n+1 */ + Int Ri [ ], /* size nz (or less, if duplicates present) */ + + Int W [ ], /* workspace of size n */ + Int Flag [ ] /* workspace of size n */ +) +{ + + /* --------------------------------------------------------------------- */ + /* local variables */ + /* --------------------------------------------------------------------- */ + + Int i, j, p, p2 ; + + ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ; + + /* --------------------------------------------------------------------- */ + /* count the entries in each row of A (excluding duplicates) */ + /* --------------------------------------------------------------------- */ + + for (i = 0 ; i < n ; i++) + { + W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ + Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ + } + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + W [i]++ ; /* one more entry in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + + /* --------------------------------------------------------------------- */ + /* compute the row pointers for R */ + /* --------------------------------------------------------------------- */ + + Rp [0] = 0 ; + for (i = 0 ; i < n ; i++) + { + Rp [i+1] = Rp [i] + W [i] ; + } + for (i = 0 ; i < n ; i++) + { + W [i] = Rp [i] ; + Flag [i] = EMPTY ; + } + + /* --------------------------------------------------------------------- */ + /* construct the row form matrix R */ + /* --------------------------------------------------------------------- */ + + /* R = row form of pattern of A */ + for (j = 0 ; j < n ; j++) + { + p2 = Ap [j+1] ; + for (p = Ap [j] ; p < p2 ; p++) + { + i = Ai [p] ; + if (Flag [i] != j) + { + /* row index i has not yet appeared in column j */ + Ri [W [i]++] = j ; /* put col j in row i */ + Flag [i] = j ; /* flag row index i as appearing in col j*/ + } + } + } + +#ifndef NDEBUG + ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ; + for (j = 0 ; j < n ; j++) + { + ASSERT (W [j] == Rp [j+1]) ; + } +#endif +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_valid.c b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_valid.c new file mode 100644 index 000000000..e9e2e5ab6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/amd/amd_valid.c @@ -0,0 +1,93 @@ +/* ========================================================================= */ +/* === AMD_valid =========================================================== */ +/* ========================================================================= */ + +/* ------------------------------------------------------------------------- */ +/* AMD, Copyright (c) Timothy A. Davis, */ +/* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ +/* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ +/* web: http://www.cise.ufl.edu/research/sparse/amd */ +/* ------------------------------------------------------------------------- */ + +/* Check if a column-form matrix is valid or not. The matrix A is + * n_row-by-n_col. The row indices of entries in column j are in + * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: + * + * n_row >= 0 + * n_col >= 0 + * nz = Ap [n_col] >= 0 number of entries in the matrix + * Ap [0] == 0 + * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. + * Ai [0 ... nz-1] must be in the range 0 to n_row-1. + * + * If any of the above conditions hold, AMD_INVALID is returned. If the + * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning, + * not an error): + * + * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending + * order, and/or duplicate entries exist. + * + * Otherwise, AMD_OK is returned. + * + * In v1.2 and earlier, this function returned TRUE if the matrix was valid + * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or + * AMD_OK_BUT_JUMBLED). + */ + +#include "amd_internal.h" + +GLOBAL Int AMD_valid +( + /* inputs, not modified on output: */ + Int n_row, /* A is n_row-by-n_col */ + Int n_col, + const Int Ap [ ], /* column pointers of A, of size n_col+1 */ + const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ +) +{ + Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ; + + if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) + { + return (AMD_INVALID) ; + } + nz = Ap [n_col] ; + if (Ap [0] != 0 || nz < 0) + { + /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ + AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; + return (AMD_INVALID) ; + } + for (j = 0 ; j < n_col ; j++) + { + p1 = Ap [j] ; + p2 = Ap [j+1] ; + AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; + if (p1 > p2) + { + /* column pointers must be ascending */ + AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; + return (AMD_INVALID) ; + } + ilast = EMPTY ; + for (p = p1 ; p < p2 ; p++) + { + i = Ai [p] ; + AMD_DEBUG3 (("row: "ID"\n", i)) ; + if (i < 0 || i >= n_row) + { + /* row index out of range */ + AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); + return (AMD_INVALID) ; + } + if (i <= ilast) + { + /* row index unsorted, or duplicate entry present */ + AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); + result = AMD_OK_BUT_JUMBLED ; + } + ilast = i ; + } + } + return (result) ; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/advbas.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/advbas.c new file mode 100644 index 000000000..230676246 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/advbas.c @@ -0,0 +1,155 @@ +/* advbas.c (construct advanced initial LP basis) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" +#include "triang.h" + +/*********************************************************************** +* NAME +* +* glp_adv_basis - construct advanced initial LP basis +* +* SYNOPSIS +* +* void glp_adv_basis(glp_prob *P, int flags); +* +* DESCRIPTION +* +* The routine glp_adv_basis constructs an advanced initial LP basis +* for the specified problem object. +* +* The parameter flag is reserved for use in the future and should be +* specified as zero. +* +* NOTE +* +* The routine glp_adv_basis should be called after the constraint +* matrix has been scaled (if scaling is used). */ + +static int mat(void *info, int k, int ind[], double val[]) +{ glp_prob *P = info; + int m = P->m; + int n = P->n; + GLPROW **row = P->row; + GLPCOL **col = P->col; + GLPAIJ *aij; + int i, j, len; + if (k > 0) + { /* retrieve scaled row of constraint matrix */ + i = +k; + xassert(1 <= i && i <= m); + len = 0; + if (row[i]->type == GLP_FX) + { for (aij = row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + if (col[j]->type != GLP_FX) + { len++; + ind[len] = j; + val[len] = aij->row->rii * aij->val * aij->col->sjj; + } + } + } + } + else + { /* retrieve scaled column of constraint matrix */ + j = -k; + xassert(1 <= j && j <= n); + len = 0; + if (col[j]->type != GLP_FX) + { for (aij = col[j]->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row->i; + if (row[i]->type == GLP_FX) + { len++; + ind[len] = i; + val[len] = aij->row->rii * aij->val * aij->col->sjj; + } + } + } + } + return len; +} + +void glp_adv_basis(glp_prob *P, int flags) +{ int i, j, k, m, n, min_mn, size, *rn, *cn; + char *flag; + if (flags != 0) + xerror("glp_adv_basis: flags = %d; invalid flags\n", flags); + m = P->m; /* number of rows */ + n = P->n; /* number of columns */ + if (m == 0 || n == 0) + { /* trivial case */ + glp_std_basis(P); + goto done; + } + xprintf("Constructing initial basis...\n"); + /* allocate working arrays */ + min_mn = (m < n ? m : n); + rn = talloc(1+min_mn, int); + cn = talloc(1+min_mn, int); + flag = talloc(1+m, char); + /* make the basis empty */ + for (i = 1; i <= m; i++) + { flag[i] = 0; + glp_set_row_stat(P, i, GLP_NS); + } + for (j = 1; j <= n; j++) + glp_set_col_stat(P, j, GLP_NS); + /* find maximal triangular part of the constraint matrix; + to prevent including non-fixed rows and fixed columns in the + triangular part, such rows and columns are temporarily made + empty by the routine mat */ +#if 1 /* FIXME: tolerance */ + size = triang(m, n, mat, P, 0.001, rn, cn); +#endif + xassert(0 <= size && size <= min_mn); + /* include in the basis non-fixed structural variables, whose + columns constitute the triangular part */ + for (k = 1; k <= size; k++) + { i = rn[k]; + xassert(1 <= i && i <= m); + flag[i] = 1; + j = cn[k]; + xassert(1 <= j && j <= n); + glp_set_col_stat(P, j, GLP_BS); + } + /* include in the basis appropriate auxiliary variables, whose + unity columns preserve triangular form of the basis matrix */ + for (i = 1; i <= m; i++) + { if (flag[i] == 0) + { glp_set_row_stat(P, i, GLP_BS); + if (P->row[i]->type != GLP_FX) + size++; + } + } + /* size of triangular part = (number of rows) - (number of basic + fixed auxiliary variables) */ + xprintf("Size of triangular part is %d\n", size); + /* deallocate working arrays */ + tfree(rn); + tfree(cn); + tfree(flag); +done: return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/asnhall.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnhall.c new file mode 100644 index 000000000..d7112a102 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnhall.c @@ -0,0 +1,163 @@ +/* asnhall.c (find bipartite matching of maximum cardinality) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "mc21a.h" + +/*********************************************************************** +* NAME +* +* glp_asnprob_hall - find bipartite matching of maximum cardinality +* +* SYNOPSIS +* +* int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +* +* DESCRIPTION +* +* The routine glp_asnprob_hall finds a matching of maximal cardinality +* in the specified bipartite graph G. It uses a version of the Fortran +* routine MC21A developed by I.S.Duff [1], which implements Hall's +* algorithm [2]. +* +* RETURNS +* +* The routine glp_asnprob_hall returns the cardinality of the matching +* found. However, if the specified graph is incorrect (as detected by +* the routine glp_check_asnprob), the routine returns negative value. +* +* REFERENCES +* +* 1. I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM +* Trans. on Math. Softw. 7 (1981), 387-390. +* +* 2. M.Hall, "An Algorithm for distinct representatives," Amer. Math. +* Monthly 63 (1956), 716-717. */ + +int glp_asnprob_hall(glp_graph *G, int v_set, int a_x) +{ glp_vertex *v; + glp_arc *a; + int card, i, k, loc, n, n1, n2, xij; + int *num, *icn, *ip, *lenr, *iperm, *pr, *arp, *cv, *out; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_hall: v_set = %d; invalid offset\n", + v_set); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) + xerror("glp_asnprob_hall: a_x = %d; invalid offset\n", a_x); + if (glp_check_asnprob(G, v_set)) + return -1; + /* determine the number of vertices in sets R and S and renumber + vertices in S which correspond to columns of the matrix; skip + all isolated vertices */ + num = xcalloc(1+G->nv, sizeof(int)); + n1 = n2 = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v->in == NULL && v->out != NULL) + n1++, num[i] = 0; /* vertex in R */ + else if (v->in != NULL && v->out == NULL) + n2++, num[i] = n2; /* vertex in S */ + else + { xassert(v->in == NULL && v->out == NULL); + num[i] = -1; /* isolated vertex */ + } + } + /* the matrix must be square, thus, if it has more columns than + rows, extra rows will be just empty, and vice versa */ + n = (n1 >= n2 ? n1 : n2); + /* allocate working arrays */ + icn = xcalloc(1+G->na, sizeof(int)); + ip = xcalloc(1+n, sizeof(int)); + lenr = xcalloc(1+n, sizeof(int)); + iperm = xcalloc(1+n, sizeof(int)); + pr = xcalloc(1+n, sizeof(int)); + arp = xcalloc(1+n, sizeof(int)); + cv = xcalloc(1+n, sizeof(int)); + out = xcalloc(1+n, sizeof(int)); + /* build the adjacency matrix of the bipartite graph in row-wise + format (rows are vertices in R, columns are vertices in S) */ + k = 0, loc = 1; + for (i = 1; i <= G->nv; i++) + { if (num[i] != 0) continue; + /* vertex i in R */ + ip[++k] = loc; + v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { xassert(num[a->head->i] != 0); + icn[loc++] = num[a->head->i]; + } + lenr[k] = loc - ip[k]; + } + xassert(loc-1 == G->na); + /* make all extra rows empty (all extra columns are empty due to + the row-wise format used) */ + for (k++; k <= n; k++) + ip[k] = loc, lenr[k] = 0; + /* find a row permutation that maximizes the number of non-zeros + on the main diagonal */ + card = mc21a(n, icn, ip, lenr, iperm, pr, arp, cv, out); +#if 1 /* 18/II-2010 */ + /* FIXED: if card = n, arp remains clobbered on exit */ + for (i = 1; i <= n; i++) + arp[i] = 0; + for (i = 1; i <= card; i++) + { k = iperm[i]; + xassert(1 <= k && k <= n); + xassert(arp[k] == 0); + arp[k] = i; + } +#endif + /* store solution, if necessary */ + if (a_x < 0) goto skip; + k = 0; + for (i = 1; i <= G->nv; i++) + { if (num[i] != 0) continue; + /* vertex i in R */ + k++; + v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { /* arp[k] is the number of matched column or zero */ + if (arp[k] == num[a->head->i]) + { xassert(arp[k] != 0); + xij = 1; + } + else + xij = 0; + memcpy((char *)a->data + a_x, &xij, sizeof(int)); + } + } +skip: /* free working arrays */ + xfree(num); + xfree(icn); + xfree(ip); + xfree(lenr); + xfree(iperm); + xfree(pr); + xfree(arp); + xfree(cv); + xfree(out); + return card; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/asnlp.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnlp.c new file mode 100644 index 000000000..cfa925d0e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnlp.c @@ -0,0 +1,104 @@ +/* asnlp.c (convert assignment problem to LP) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_asnprob_lp - convert assignment problem to LP +* +* SYNOPSIS +* +* int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, +* int v_set, int a_cost); +* +* DESCRIPTION +* +* The routine glp_asnprob_lp builds an LP problem, which corresponds +* to the assignment problem on the specified graph G. +* +* RETURNS +* +* If the LP problem has been successfully built, the routine returns +* zero, otherwise, non-zero. */ + +int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, + int v_set, int a_cost) +{ glp_vertex *v; + glp_arc *a; + int i, j, ret, ind[1+2]; + double cost, val[1+2]; + if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || + form == GLP_ASN_MMP)) + xerror("glp_asnprob_lp: form = %d; invalid parameter\n", + form); + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_asnprob_lp: names = %d; invalid parameter\n", + names); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_lp: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n", + a_cost); + ret = glp_check_asnprob(G, v_set); + if (ret != 0) goto done; + glp_erase_prob(P); + if (names) glp_set_prob_name(P, G->name); + glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX); + if (G->nv > 0) glp_add_rows(P, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(P, i, v->name); + glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX, + 1.0, 1.0); + } + if (G->na > 0) glp_add_cols(P, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(P, j, name); + } + ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = +1.0; + glp_set_mat_col(P, j, 2, ind, val); + glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0); + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 1.0; + glp_set_obj_coef(P, j, cost); + } + } + xassert(j == G->na); +done: return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/asnokalg.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnokalg.c new file mode 100644 index 000000000..d55dbac7a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/asnokalg.c @@ -0,0 +1,154 @@ +/* asnokalg.c (solve assignment problem with out-of-kilter alg.) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "okalg.h" + +int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x) +{ /* solve assignment problem with out-of-kilter algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, *tail, *head, *low, *cap, *cost, *x, *pi, ret; + double temp; + if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || + form == GLP_ASN_MMP)) + xerror("glp_asnprob_okalg: form = %d; invalid parameter\n", + form); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_asnprob_okalg: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_asnprob_okalg: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) + xerror("glp_asnprob_okalg: a_x = %d; invalid offset\n", a_x); + if (glp_check_asnprob(G, v_set)) + return GLP_EDATA; + /* nv is the total number of nodes in the resulting network */ + nv = G->nv + 1; + /* na is the total number of arcs in the resulting network */ + na = G->na + G->nv; + /* allocate working arrays */ + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + low = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + cost = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + pi = xcalloc(1+nv, sizeof(int)); + /* construct the resulting network */ + k = 0; + /* (original arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + low[k] = 0; + cap[k] = 1; + if (a_cost >= 0) + memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); + else + temp = 1.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cost[k] = (int)temp; + if (form != GLP_ASN_MIN) cost[k] = - cost[k]; + } + } + /* (artificial arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + k++; + if (v->out == NULL) + tail[k] = i, head[k] = nv; + else if (v->in == NULL) + tail[k] = nv, head[k] = i; + else + xassert(v != v); + low[k] = (form == GLP_ASN_MMP ? 0 : 1); + cap[k] = 1; + cost[k] = 0; + } + xassert(k == na); + /* find minimal-cost circulation in the resulting network */ + ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); + switch (ret) + { case 0: + /* optimal circulation found */ + ret = 0; + break; + case 1: + /* no feasible circulation exists */ + ret = GLP_ENOPFS; + break; + case 2: + /* integer overflow occured */ + ret = GLP_ERANGE; + goto done; + case 3: + /* optimality test failed (logic error) */ + ret = GLP_EFAIL; + goto done; + default: + xassert(ret != ret); + } + /* store solution components */ + /* (objective function = the total cost) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + temp += (double)cost[k] * (double)x[k]; + if (form != GLP_ASN_MIN) temp = - temp; + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + if (ret == 0) + xassert(x[k] == 0 || x[k] == 1); + memcpy((char *)a->data + a_x, &x[k], sizeof(int)); + } + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(low); + xfree(cap); + xfree(cost); + xfree(x); + xfree(pi); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/ckasn.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/ckasn.c new file mode 100644 index 000000000..56221a8a9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/ckasn.c @@ -0,0 +1,78 @@ +/* ckasn.c (check correctness of assignment problem data) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_check_asnprob - check correctness of assignment problem data +* +* SYNOPSIS +* +* int glp_check_asnprob(glp_graph *G, int v_set); +* +* RETURNS +* +* If the specified assignment problem data are correct, the routine +* glp_check_asnprob returns zero, otherwise, non-zero. */ + +int glp_check_asnprob(glp_graph *G, int v_set) +{ glp_vertex *v; + int i, k, ret = 0; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_check_asnprob: v_set = %d; invalid offset\n", + v_set); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_set >= 0) + { memcpy(&k, (char *)v->data + v_set, sizeof(int)); + if (k == 0) + { if (v->in != NULL) + { ret = 1; + break; + } + } + else if (k == 1) + { if (v->out != NULL) + { ret = 2; + break; + } + } + else + { ret = 3; + break; + } + } + else + { if (v->in != NULL && v->out != NULL) + { ret = 4; + break; + } + } + } + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/ckcnf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/ckcnf.c new file mode 100644 index 000000000..0ee47ed96 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/ckcnf.c @@ -0,0 +1,82 @@ +/* ckcnf.c (check for CNF-SAT problem instance) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +int glp_check_cnfsat(glp_prob *P) +{ /* check for CNF-SAT problem instance */ + int m = P->m; + int n = P->n; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, neg; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_check_cnfsat: P = %p; invalid problem object\n", + P); +#endif + /* check columns */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* the variable should be binary */ + if (!(col->kind == GLP_IV && col->type == GLP_DB && + col->lb == 0.0 && col->ub == 1.0)) + return 1; + } + /* objective function should be zero */ + if (P->c0 != 0.0) + return 2; + for (j = 1; j <= n; j++) + { col = P->col[j]; + if (col->coef != 0.0) + return 3; + } + /* check rows */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* the row should be of ">=" type */ + if (row->type != GLP_LO) + return 4; + /* check constraint coefficients */ + neg = 0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { /* the constraint coefficient should be +1 or -1 */ + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + neg++; + else + return 5; + } + /* the right-hand side should be (1 - neg), where neg is the + number of negative constraint coefficients in the row */ + if (row->lb != (double)(1 - neg)) + return 6; + } + /* congratulations; this is CNF-SAT */ + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/cplex.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/cplex.c new file mode 100644 index 000000000..8403a6464 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/cplex.c @@ -0,0 +1,1283 @@ +/* cplex.c (CPLEX LP format routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_init_cpxcp - initialize CPLEX LP format control parameters +* +* SYNOPSIS +* +* void glp_init_cpxcp(glp_cpxcp *parm): +* +* The routine glp_init_cpxcp initializes control parameters used by +* the CPLEX LP input/output routines glp_read_lp and glp_write_lp with +* default values. +* +* Default values of the control parameters are stored in the glp_cpxcp +* structure, which the parameter parm points to. */ + +void glp_init_cpxcp(glp_cpxcp *parm) +{ xassert(parm != NULL); + return; +} + +static void check_parm(const char *func, const glp_cpxcp *parm) +{ /* check control parameters */ + xassert(func != NULL); + xassert(parm != NULL); + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_lp - read problem data in CPLEX LP format +* +* SYNOPSIS +* +* int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char +* *fname); +* +* DESCRIPTION +* +* The routine glp_read_lp reads problem data in CPLEX LP format from +* a text file. +* +* The parameter parm is a pointer to the structure glp_cpxcp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* read. +* +* Note that before reading data the current content of the problem +* object is completely erased with the routine glp_erase_prob. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_lp returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* LP/MIP problem object */ + const glp_cpxcp *parm; + /* pointer to control parameters */ + const char *fname; + /* name of input CPLEX LP file */ + glp_file *fp; + /* stream assigned to input CPLEX LP file */ + jmp_buf jump; + /* label for go to in case of error */ + int count; + /* line count */ + int c; + /* current character or EOF */ + int token; + /* current token: */ +#define T_EOF 0x00 /* end of file */ +#define T_MINIMIZE 0x01 /* keyword 'minimize' */ +#define T_MAXIMIZE 0x02 /* keyword 'maximize' */ +#define T_SUBJECT_TO 0x03 /* keyword 'subject to' */ +#define T_BOUNDS 0x04 /* keyword 'bounds' */ +#define T_GENERAL 0x05 /* keyword 'general' */ +#define T_INTEGER 0x06 /* keyword 'integer' */ +#define T_BINARY 0x07 /* keyword 'binary' */ +#define T_END 0x08 /* keyword 'end' */ +#define T_NAME 0x09 /* symbolic name */ +#define T_NUMBER 0x0A /* numeric constant */ +#define T_PLUS 0x0B /* delimiter '+' */ +#define T_MINUS 0x0C /* delimiter '-' */ +#define T_COLON 0x0D /* delimiter ':' */ +#define T_LE 0x0E /* delimiter '<=' */ +#define T_GE 0x0F /* delimiter '>=' */ +#define T_EQ 0x10 /* delimiter '=' */ + char image[255+1]; + /* image of current token */ + int imlen; + /* length of token image */ + double value; + /* value of numeric constant */ + int n_max; + /* length of the following five arrays (enlarged automatically, + if necessary) */ + int *ind; /* int ind[1+n_max]; */ + double *val; /* double val[1+n_max]; */ + char *flag; /* char flag[1+n_max]; */ + /* working arrays used to construct linear forms */ + double *lb; /* double lb[1+n_max]; */ + double *ub; /* double ub[1+n_max]; */ + /* lower and upper bounds of variables (columns) */ +#if 1 /* 27/VII-2013 */ + int lb_warn, ub_warn; + /* warning 'lower/upper bound redefined' already issued */ +#endif +}; + +#define CHAR_SET "!\"#$%&()/,.;?@_`'{}|~" +/* characters that may appear in symbolic names */ + +static void error(struct csa *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + longjmp(csa->jump, 1); + /* no return */ +} + +static void warning(struct csa *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + return; +} + +static void read_char(struct csa *csa) +{ /* read next character from input file */ + int c; + xassert(csa->c != EOF); + if (csa->c == '\n') csa->count++; + c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + error(csa, "read error - %s\n", get_err_msg()); + else if (csa->c == '\n') + { csa->count--; + c = EOF; + } + else + { warning(csa, "missing final end of line\n"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + error(csa, "invalid control character 0x%02X\n", c); + csa->c = c; + return; +} + +static void add_char(struct csa *csa) +{ /* append current character to current token */ + if (csa->imlen == sizeof(csa->image)-1) + error(csa, "token '%.15s...' too long\n", csa->image); + csa->image[csa->imlen++] = (char)csa->c; + csa->image[csa->imlen] = '\0'; + read_char(csa); + return; +} + +static int the_same(char *s1, char *s2) +{ /* compare two character strings ignoring case sensitivity */ + for (; *s1 != '\0'; s1++, s2++) + { if (tolower((unsigned char)*s1) != tolower((unsigned char)*s2)) + return 0; + } + return 1; +} + +static void scan_token(struct csa *csa) +{ /* scan next token */ + int flag; + csa->token = -1; + csa->image[0] = '\0'; + csa->imlen = 0; + csa->value = 0.0; +loop: flag = 0; + /* skip non-significant characters */ + while (csa->c == ' ') read_char(csa); + /* recognize and scan current token */ + if (csa->c == EOF) + csa->token = T_EOF; + else if (csa->c == '\n') + { read_char(csa); + /* if the next character is letter, it may begin a keyword */ + if (isalpha(csa->c)) + { flag = 1; + goto name; + } + goto loop; + } + else if (csa->c == '\\') + { /* comment; ignore everything until end-of-line */ + while (csa->c != '\n') read_char(csa); + goto loop; + } + else if (isalpha(csa->c) || csa->c != '.' && strchr(CHAR_SET, + csa->c) != NULL) +name: { /* symbolic name */ + csa->token = T_NAME; + while (isalnum(csa->c) || strchr(CHAR_SET, csa->c) != NULL) + add_char(csa); + if (flag) + { /* check for keyword */ + if (the_same(csa->image, "minimize")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "minimum")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "min")) + csa->token = T_MINIMIZE; + else if (the_same(csa->image, "maximize")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "maximum")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "max")) + csa->token = T_MAXIMIZE; + else if (the_same(csa->image, "subject")) + { if (csa->c == ' ') + { read_char(csa); + if (tolower(csa->c) == 't') + { csa->token = T_SUBJECT_TO; + csa->image[csa->imlen++] = ' '; + csa->image[csa->imlen] = '\0'; + add_char(csa); + if (tolower(csa->c) != 'o') + error(csa, "keyword 'subject to' incomplete\n"); + add_char(csa); + if (isalpha(csa->c)) + error(csa, "keyword '%s%c...' not recognized\n", + csa->image, csa->c); + } + } + } + else if (the_same(csa->image, "such")) + { if (csa->c == ' ') + { read_char(csa); + if (tolower(csa->c) == 't') + { csa->token = T_SUBJECT_TO; + csa->image[csa->imlen++] = ' '; + csa->image[csa->imlen] = '\0'; + add_char(csa); + if (tolower(csa->c) != 'h') +err: error(csa, "keyword 'such that' incomplete\n"); + add_char(csa); + if (tolower(csa->c) != 'a') goto err; + add_char(csa); + if (tolower(csa->c) != 't') goto err; + add_char(csa); + if (isalpha(csa->c)) + error(csa, "keyword '%s%c...' not recognized\n", + csa->image, csa->c); + } + } + } + else if (the_same(csa->image, "st")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "s.t.")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "st.")) + csa->token = T_SUBJECT_TO; + else if (the_same(csa->image, "bounds")) + csa->token = T_BOUNDS; + else if (the_same(csa->image, "bound")) + csa->token = T_BOUNDS; + else if (the_same(csa->image, "general")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "generals")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "gen")) + csa->token = T_GENERAL; + else if (the_same(csa->image, "integer")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "integers")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "int")) + csa->token = T_INTEGER; + else if (the_same(csa->image, "binary")) + csa->token = T_BINARY; + else if (the_same(csa->image, "binaries")) + csa->token = T_BINARY; + else if (the_same(csa->image, "bin")) + csa->token = T_BINARY; + else if (the_same(csa->image, "end")) + csa->token = T_END; + } + } + else if (isdigit(csa->c) || csa->c == '.') + { /* numeric constant */ + csa->token = T_NUMBER; + /* scan integer part */ + while (isdigit(csa->c)) add_char(csa); + /* scan optional fractional part (it is mandatory, if there is + no integer part) */ + if (csa->c == '.') + { add_char(csa); + if (csa->imlen == 1 && !isdigit(csa->c)) + error(csa, "invalid use of decimal point\n"); + while (isdigit(csa->c)) add_char(csa); + } + /* scan optional decimal exponent */ + if (csa->c == 'e' || csa->c == 'E') + { add_char(csa); + if (csa->c == '+' || csa->c == '-') add_char(csa); + if (!isdigit(csa->c)) + error(csa, "numeric constant '%s' incomplete\n", + csa->image); + while (isdigit(csa->c)) add_char(csa); + } + /* convert the numeric constant to floating-point */ + if (str2num(csa->image, &csa->value)) + error(csa, "numeric constant '%s' out of range\n", + csa->image); + } + else if (csa->c == '+') + csa->token = T_PLUS, add_char(csa); + else if (csa->c == '-') + csa->token = T_MINUS, add_char(csa); + else if (csa->c == ':') + csa->token = T_COLON, add_char(csa); + else if (csa->c == '<') + { csa->token = T_LE, add_char(csa); + if (csa->c == '=') add_char(csa); + } + else if (csa->c == '>') + { csa->token = T_GE, add_char(csa); + if (csa->c == '=') add_char(csa); + } + else if (csa->c == '=') + { csa->token = T_EQ, add_char(csa); + if (csa->c == '<') + csa->token = T_LE, add_char(csa); + else if (csa->c == '>') + csa->token = T_GE, add_char(csa); + } + else + error(csa, "character '%c' not recognized\n", csa->c); + /* skip non-significant characters */ + while (csa->c == ' ') read_char(csa); + return; +} + +static int find_col(struct csa *csa, char *name) +{ /* find column by its symbolic name */ + int j; + j = glp_find_col(csa->P, name); + if (j == 0) + { /* not found; create new column */ + j = glp_add_cols(csa->P, 1); + glp_set_col_name(csa->P, j, name); + /* enlarge working arrays, if necessary */ + if (csa->n_max < j) + { int n_max = csa->n_max; + int *ind = csa->ind; + double *val = csa->val; + char *flag = csa->flag; + double *lb = csa->lb; + double *ub = csa->ub; + csa->n_max += csa->n_max; + csa->ind = xcalloc(1+csa->n_max, sizeof(int)); + memcpy(&csa->ind[1], &ind[1], n_max * sizeof(int)); + xfree(ind); + csa->val = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->val[1], &val[1], n_max * sizeof(double)); + xfree(val); + csa->flag = xcalloc(1+csa->n_max, sizeof(char)); + memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); + memcpy(&csa->flag[1], &flag[1], n_max * sizeof(char)); + xfree(flag); + csa->lb = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->lb[1], &lb[1], n_max * sizeof(double)); + xfree(lb); + csa->ub = xcalloc(1+csa->n_max, sizeof(double)); + memcpy(&csa->ub[1], &ub[1], n_max * sizeof(double)); + xfree(ub); + } + csa->lb[j] = +DBL_MAX, csa->ub[j] = -DBL_MAX; + } + return j; +} + +/*********************************************************************** +* parse_linear_form - parse linear form +* +* This routine parses the linear form using the following syntax: +* +* ::= +* ::= +* ::= | +* ::= | + | - | +* + | - +* +* The routine returns the number of terms in the linear form. */ + +static int parse_linear_form(struct csa *csa) +{ int j, k, len = 0, newlen; + double s, coef; +loop: /* parse an optional sign */ + if (csa->token == T_PLUS) + s = +1.0, scan_token(csa); + else if (csa->token == T_MINUS) + s = -1.0, scan_token(csa); + else + s = +1.0; + /* parse an optional coefficient */ + if (csa->token == T_NUMBER) + coef = csa->value, scan_token(csa); + else + coef = 1.0; + /* parse a variable name */ + if (csa->token != T_NAME) + error(csa, "missing variable name\n"); + /* find the corresponding column */ + j = find_col(csa, csa->image); + /* check if the variable is already used in the linear form */ + if (csa->flag[j]) + error(csa, "multiple use of variable '%s' not allowed\n", + csa->image); + /* add new term to the linear form */ + len++, csa->ind[len] = j, csa->val[len] = s * coef; + /* and mark that the variable is used in the linear form */ + csa->flag[j] = 1; + scan_token(csa); + /* if the next token is a sign, there is another term */ + if (csa->token == T_PLUS || csa->token == T_MINUS) goto loop; + /* clear marks of the variables used in the linear form */ + for (k = 1; k <= len; k++) csa->flag[csa->ind[k]] = 0; + /* remove zero coefficients */ + newlen = 0; + for (k = 1; k <= len; k++) + { if (csa->val[k] != 0.0) + { newlen++; + csa->ind[newlen] = csa->ind[k]; + csa->val[newlen] = csa->val[k]; + } + } + return newlen; +} + +/*********************************************************************** +* parse_objective - parse objective function +* +* This routine parses definition of the objective function using the +* following syntax: +* +* ::= minimize | minimum | min | maximize | maximum | max +* ::= | : +* ::= */ + +static void parse_objective(struct csa *csa) +{ /* parse objective sense */ + int k, len; + /* parse the keyword 'minimize' or 'maximize' */ + if (csa->token == T_MINIMIZE) + glp_set_obj_dir(csa->P, GLP_MIN); + else if (csa->token == T_MAXIMIZE) + glp_set_obj_dir(csa->P, GLP_MAX); + else + xassert(csa != csa); + scan_token(csa); + /* parse objective name */ + if (csa->token == T_NAME && csa->c == ':') + { /* objective name is followed by a colon */ + glp_set_obj_name(csa->P, csa->image); + scan_token(csa); + xassert(csa->token == T_COLON); + scan_token(csa); + } + else + { /* objective name is not specified; use default */ + glp_set_obj_name(csa->P, "obj"); + } + /* parse linear form */ + len = parse_linear_form(csa); + for (k = 1; k <= len; k++) + glp_set_obj_coef(csa->P, csa->ind[k], csa->val[k]); + return; +} + +/*********************************************************************** +* parse_constraints - parse constraints section +* +* This routine parses the constraints section using the following +* syntax: +* +* ::= | : +* ::= < | <= | =< | > | >= | => | = +* ::= | + | +* - +* ::= +* +* ::= subject to | such that | st | s.t. | st. +* ::= | +* */ + +static void parse_constraints(struct csa *csa) +{ int i, len, type; + double s; + /* parse the keyword 'subject to' */ + xassert(csa->token == T_SUBJECT_TO); + scan_token(csa); +loop: /* create new row (constraint) */ + i = glp_add_rows(csa->P, 1); + /* parse row name */ + if (csa->token == T_NAME && csa->c == ':') + { /* row name is followed by a colon */ + if (glp_find_row(csa->P, csa->image) != 0) + error(csa, "constraint '%s' multiply defined\n", + csa->image); + glp_set_row_name(csa->P, i, csa->image); + scan_token(csa); + xassert(csa->token == T_COLON); + scan_token(csa); + } + else + { /* row name is not specified; use default */ + char name[50]; + sprintf(name, "r.%d", csa->count); + glp_set_row_name(csa->P, i, name); + } + /* parse linear form */ + len = parse_linear_form(csa); + glp_set_mat_row(csa->P, i, len, csa->ind, csa->val); + /* parse constraint sense */ + if (csa->token == T_LE) + type = GLP_UP, scan_token(csa); + else if (csa->token == T_GE) + type = GLP_LO, scan_token(csa); + else if (csa->token == T_EQ) + type = GLP_FX, scan_token(csa); + else + error(csa, "missing constraint sense\n"); + /* parse right-hand side */ + if (csa->token == T_PLUS) + s = +1.0, scan_token(csa); + else if (csa->token == T_MINUS) + s = -1.0, scan_token(csa); + else + s = +1.0; + if (csa->token != T_NUMBER) + error(csa, "missing right-hand side\n"); + glp_set_row_bnds(csa->P, i, type, s * csa->value, s * csa->value); + /* the rest of the current line must be empty */ + if (!(csa->c == '\n' || csa->c == EOF)) + error(csa, "invalid symbol(s) beyond right-hand side\n"); + scan_token(csa); + /* if the next token is a sign, numeric constant, or a symbolic + name, here is another constraint */ + if (csa->token == T_PLUS || csa->token == T_MINUS || + csa->token == T_NUMBER || csa->token == T_NAME) goto loop; + return; +} + +static void set_lower_bound(struct csa *csa, int j, double lb) +{ /* set lower bound of j-th variable */ + if (csa->lb[j] != +DBL_MAX && !csa->lb_warn) + { warning(csa, "lower bound of variable '%s' redefined\n", + glp_get_col_name(csa->P, j)); + csa->lb_warn = 1; + } + csa->lb[j] = lb; + return; +} + +static void set_upper_bound(struct csa *csa, int j, double ub) +{ /* set upper bound of j-th variable */ + if (csa->ub[j] != -DBL_MAX && !csa->ub_warn) + { warning(csa, "upper bound of variable '%s' redefined\n", + glp_get_col_name(csa->P, j)); + csa->ub_warn = 1; + } + csa->ub[j] = ub; + return; +} + +/*********************************************************************** +* parse_bounds - parse bounds section +* +* This routine parses the bounds section using the following syntax: +* +* ::= +* ::= infinity | inf +* ::= | + | +* - | + | - +* ::= < | <= | =< +* ::= > | >= | => +* ::= | +* | | +* | = | free +* ::= bounds | bound +* ::= | +* */ + +static void parse_bounds(struct csa *csa) +{ int j, lb_flag; + double lb, s; + /* parse the keyword 'bounds' */ + xassert(csa->token == T_BOUNDS); + scan_token(csa); +loop: /* bound definition can start with a sign, numeric constant, or + a symbolic name */ + if (!(csa->token == T_PLUS || csa->token == T_MINUS || + csa->token == T_NUMBER || csa->token == T_NAME)) goto done; + /* parse bound definition */ + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed lower bound */ + lb_flag = 1; + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + lb = s * csa->value, scan_token(csa); + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf")) + { if (s > 0.0) + error(csa, "invalid use of '+inf' as lower bound\n"); + lb = -DBL_MAX, scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned lower bound */ + lb_flag = 1; + lb = csa->value, scan_token(csa); + } + else + { /* lower bound is not specified */ + lb_flag = 0; + } + /* parse the token that should follow the lower bound */ + if (lb_flag) + { if (csa->token != T_LE) + error(csa, "missing '<', '<=', or '=<' after lower bound\n") + ; + scan_token(csa); + } + /* parse variable name */ + if (csa->token != T_NAME) + error(csa, "missing variable name\n"); + j = find_col(csa, csa->image); + /* set lower bound */ + if (lb_flag) set_lower_bound(csa, j, lb); + scan_token(csa); + /* parse the context that follows the variable name */ + if (csa->token == T_LE) + { /* parse upper bound */ + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed upper bound */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_upper_bound(csa, j, s * csa->value); + scan_token(csa); + } + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf")) + { if (s < 0.0) + error(csa, "invalid use of '-inf' as upper bound\n"); + set_upper_bound(csa, j, +DBL_MAX); + scan_token(csa); + } + else + error(csa, "missing upper bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned upper bound */ + set_upper_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing upper bound\n"); + } + else if (csa->token == T_GE) + { /* parse lower bound */ + if (lb_flag) + { /* the context '... <= x >= ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed lower bound */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_lower_bound(csa, j, s * csa->value); + scan_token(csa); + } + else if (the_same(csa->image, "infinity") || + the_same(csa->image, "inf") == 0) + { if (s > 0.0) + error(csa, "invalid use of '+inf' as lower bound\n"); + set_lower_bound(csa, j, -DBL_MAX); + scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned lower bound */ + set_lower_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing lower bound\n"); + } + else if (csa->token == T_EQ) + { /* parse fixed value */ + if (lb_flag) + { /* the context '... <= x = ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + scan_token(csa); + if (csa->token == T_PLUS || csa->token == T_MINUS) + { /* parse signed fixed value */ + s = (csa->token == T_PLUS ? +1.0 : -1.0); + scan_token(csa); + if (csa->token == T_NUMBER) + { set_lower_bound(csa, j, s * csa->value); + set_upper_bound(csa, j, s * csa->value); + scan_token(csa); + } + else + error(csa, "missing fixed value\n"); + } + else if (csa->token == T_NUMBER) + { /* parse unsigned fixed value */ + set_lower_bound(csa, j, csa->value); + set_upper_bound(csa, j, csa->value); + scan_token(csa); + } + else + error(csa, "missing fixed value\n"); + } + else if (the_same(csa->image, "free")) + { /* parse the keyword 'free' */ + if (lb_flag) + { /* the context '... <= x free ...' is invalid */ + error(csa, "invalid bound definition\n"); + } + set_lower_bound(csa, j, -DBL_MAX); + set_upper_bound(csa, j, +DBL_MAX); + scan_token(csa); + } + else if (!lb_flag) + { /* neither lower nor upper bounds are specified */ + error(csa, "invalid bound definition\n"); + } + goto loop; +done: return; +} + +/*********************************************************************** +* parse_integer - parse general, integer, or binary section +* +* ::= +* ::= general | generals | gen +* ::= integer | integers | int +* ::= binary | binaries | bin +*
::= +* ::=
| +* */ + +static void parse_integer(struct csa *csa) +{ int j, binary; + /* parse the keyword 'general', 'integer', or 'binary' */ + if (csa->token == T_GENERAL) + binary = 0, scan_token(csa); + else if (csa->token == T_INTEGER) + binary = 0, scan_token(csa); + else if (csa->token == T_BINARY) + binary = 1, scan_token(csa); + else + xassert(csa != csa); + /* parse list of variables (may be empty) */ + while (csa->token == T_NAME) + { /* find the corresponding column */ + j = find_col(csa, csa->image); + /* change kind of the variable */ + glp_set_col_kind(csa->P, j, GLP_IV); + /* set bounds for the binary variable */ + if (binary) +#if 0 /* 07/VIII-2013 */ + { set_lower_bound(csa, j, 0.0); + set_upper_bound(csa, j, 1.0); + } +#else + { set_lower_bound(csa, j, + csa->lb[j] == +DBL_MAX ? 0.0 : csa->lb[j]); + set_upper_bound(csa, j, + csa->ub[j] == -DBL_MAX ? 1.0 : csa->ub[j]); + } +#endif + scan_token(csa); + } + return; +} + +int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) +{ /* read problem data in CPLEX LP format */ + glp_cpxcp _parm; + struct csa _csa, *csa = &_csa; + int ret; + xprintf("Reading problem data from '%s'...\n", fname); + if (parm == NULL) + glp_init_cpxcp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_read_lp", parm); + /* initialize common storage area */ + csa->P = P; + csa->parm = parm; + csa->fname = fname; + csa->fp = NULL; + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->count = 0; + csa->c = '\n'; + csa->token = T_EOF; + csa->image[0] = '\0'; + csa->imlen = 0; + csa->value = 0.0; + csa->n_max = 100; + csa->ind = xcalloc(1+csa->n_max, sizeof(int)); + csa->val = xcalloc(1+csa->n_max, sizeof(double)); + csa->flag = xcalloc(1+csa->n_max, sizeof(char)); + memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); + csa->lb = xcalloc(1+csa->n_max, sizeof(double)); + csa->ub = xcalloc(1+csa->n_max, sizeof(double)); +#if 1 /* 27/VII-2013 */ + csa->lb_warn = csa->ub_warn = 0; +#endif + /* erase problem object */ + glp_erase_prob(P); + glp_create_index(P); + /* open input CPLEX LP file */ + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* scan very first token */ + scan_token(csa); + /* parse definition of the objective function */ + if (!(csa->token == T_MINIMIZE || csa->token == T_MAXIMIZE)) + error(csa, "'minimize' or 'maximize' keyword missing\n"); + parse_objective(csa); + /* parse constraints section */ + if (csa->token != T_SUBJECT_TO) + error(csa, "constraints section missing\n"); + parse_constraints(csa); + /* parse optional bounds section */ + if (csa->token == T_BOUNDS) parse_bounds(csa); + /* parse optional general, integer, and binary sections */ + while (csa->token == T_GENERAL || + csa->token == T_INTEGER || + csa->token == T_BINARY) parse_integer(csa); + /* check for the keyword 'end' */ + if (csa->token == T_END) + scan_token(csa); + else if (csa->token == T_EOF) + warning(csa, "keyword 'end' missing\n"); + else + error(csa, "symbol '%s' in wrong position\n", csa->image); + /* nothing must follow the keyword 'end' (except comments) */ + if (csa->token != T_EOF) + error(csa, "extra symbol(s) detected beyond 'end'\n"); + /* set bounds of variables */ + { int j, type; + double lb, ub; + for (j = 1; j <= P->n; j++) + { lb = csa->lb[j]; + ub = csa->ub[j]; + if (lb == +DBL_MAX) lb = 0.0; /* default lb */ + if (ub == -DBL_MAX) ub = +DBL_MAX; /* default ub */ + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = GLP_FR; + else if (ub == +DBL_MAX) + type = GLP_LO; + else if (lb == -DBL_MAX) + type = GLP_UP; + else if (lb != ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(csa->P, j, type, lb, ub); + } + } + /* print some statistics */ + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_delete_index(P); + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + xfree(csa->ind); + xfree(csa->val); + xfree(csa->flag); + xfree(csa->lb); + xfree(csa->ub); + if (ret != 0) glp_erase_prob(P); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_lp - write problem data in CPLEX LP format +* +* SYNOPSIS +* +* int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char +* *fname); +* +* DESCRIPTION +* +* The routine glp_write_lp writes problem data in CPLEX LP format to +* a text file. +* +* The parameter parm is a pointer to the structure glp_cpxcp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* written. +* +* RETURNS +* +* If the operation was successful, the routine glp_write_lp returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +#define csa csa1 + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + const glp_cpxcp *parm; + /* pointer to control parameters */ +}; + +static int check_name(char *name) +{ /* check if specified name is valid for CPLEX LP format */ + if (*name == '.') return 1; + if (isdigit((unsigned char)*name)) return 1; + for (; *name; name++) + { if (!isalnum((unsigned char)*name) && + strchr(CHAR_SET, (unsigned char)*name) == NULL) return 1; + } + return 0; /* name is ok */ +} + +static void adjust_name(char *name) +{ /* attempt to adjust specified name to make it valid for CPLEX LP + format */ + for (; *name; name++) + { if (*name == ' ') + *name = '_'; + else if (*name == '-') + *name = '~'; + else if (*name == '[') + *name = '('; + else if (*name == ']') + *name = ')'; + } + return; +} + +static char *row_name(struct csa *csa, int i, char rname[255+1]) +{ /* construct symbolic name of i-th row (constraint) */ + const char *name; + if (i == 0) + name = glp_get_obj_name(csa->P); + else + name = glp_get_row_name(csa->P, i); + if (name == NULL) goto fake; + strcpy(rname, name); + adjust_name(rname); + if (check_name(rname)) goto fake; + return rname; +fake: if (i == 0) + strcpy(rname, "obj"); + else + sprintf(rname, "r_%d", i); + return rname; +} + +static char *col_name(struct csa *csa, int j, char cname[255+1]) +{ /* construct symbolic name of j-th column (variable) */ + const char *name; + name = glp_get_col_name(csa->P, j); + if (name == NULL) goto fake; + strcpy(cname, name); + adjust_name(cname); + if (check_name(cname)) goto fake; + return cname; +#if 0 /* 18/I-2018 */ +fake: sprintf(cname, "x_%d", j); +#else +fake: /* construct fake name depending on column's attributes */ + { GLPCOL *col = csa->P->col[j]; + if (col->type == GLP_FX) + { /* fixed column */ + sprintf(cname, "s_%d", j); + } + else if (col->kind == GLP_CV) + { /* continuous variable */ + sprintf(cname, "x_%d", j); + } + else if (!(col->lb == 0 && col->ub == 1)) + { /* general (non-binary) integer variable */ + sprintf(cname, "y_%d", j); + } + else + { /* binary variable */ + sprintf(cname, "z_%d", j); + } + } +#endif + return cname; +} + +int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) +{ /* write problem data in CPLEX LP format */ + glp_cpxcp _parm; + struct csa _csa, *csa = &_csa; + glp_file *fp; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, len, flag, count, ret; + char line[1000+1], term[500+1], name[255+1]; + xprintf("Writing problem data to '%s'...\n", fname); + if (parm == NULL) + glp_init_cpxcp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_write_lp", parm); + /* initialize common storage area */ + csa->P = P; + csa->parm = parm; + /* create output CPLEX LP file */ + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write problem name */ + xfprintf(fp, "\\* Problem: %s *\\\n", + P->name == NULL ? "Unknown" : P->name), count++; + xfprintf(fp, "\n"), count++; + /* the problem should contain at least one row and one column */ + if (!(P->m > 0 && P->n > 0)) + { xprintf("Warning: problem has no rows/columns\n"); + xfprintf(fp, "\\* WARNING: PROBLEM HAS NO ROWS/COLUMNS *\\\n"), + count++; + xfprintf(fp, "\n"), count++; + goto skip; + } + /* write the objective function definition */ + if (P->dir == GLP_MIN) + xfprintf(fp, "Minimize\n"), count++; + else if (P->dir == GLP_MAX) + xfprintf(fp, "Maximize\n"), count++; + else + xassert(P != P); + row_name(csa, 0, name); + sprintf(line, " %s:", name); + len = 0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->coef != 0.0 || col->ptr == NULL) + { len++; + col_name(csa, j, name); + if (col->coef == 0.0) + sprintf(term, " + 0 %s", name); /* empty column */ + else if (col->coef == +1.0) + sprintf(term, " + %s", name); + else if (col->coef == -1.0) + sprintf(term, " - %s", name); + else if (col->coef > 0.0) + sprintf(term, " + %.*g %s", DBL_DIG, +col->coef, name); + else + sprintf(term, " - %.*g %s", DBL_DIG, -col->coef, name); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + } + if (len == 0) + { /* empty objective */ + sprintf(term, " 0 %s", col_name(csa, 1, name)); + strcat(line, term); + } + xfprintf(fp, "%s\n", line), count++; + if (P->c0 != 0.0) + xfprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG, P->c0), + count++; + xfprintf(fp, "\n"), count++; + /* write the constraints section */ + xfprintf(fp, "Subject To\n"), count++; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_FR) continue; /* skip free row */ + row_name(csa, i, name); + sprintf(line, " %s:", name); + /* linear form */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col_name(csa, aij->col->j, name); + if (aij->val == +1.0) + sprintf(term, " + %s", name); + else if (aij->val == -1.0) + sprintf(term, " - %s", name); + else if (aij->val > 0.0) + sprintf(term, " + %.*g %s", DBL_DIG, +aij->val, name); + else + sprintf(term, " - %.*g %s", DBL_DIG, -aij->val, name); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + if (row->type == GLP_DB) + { /* double-bounded (ranged) constraint */ + sprintf(term, " - ~r_%d", i); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + } + else if (row->ptr == NULL) + { /* empty constraint */ + sprintf(term, " 0 %s", col_name(csa, 1, name)); + strcat(line, term); + } + /* right hand-side */ + if (row->type == GLP_LO) + sprintf(term, " >= %.*g", DBL_DIG, row->lb); + else if (row->type == GLP_UP) + sprintf(term, " <= %.*g", DBL_DIG, row->ub); + else if (row->type == GLP_DB || row->type == GLP_FX) + sprintf(term, " = %.*g", DBL_DIG, row->lb); + else + xassert(row != row); + if (strlen(line) + strlen(term) > 72) + xfprintf(fp, "%s\n", line), line[0] = '\0', count++; + strcat(line, term); + xfprintf(fp, "%s\n", line), count++; + } + xfprintf(fp, "\n"), count++; + /* write the bounds section */ + flag = 0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type != GLP_DB) continue; + if (!flag) + xfprintf(fp, "Bounds\n"), flag = 1, count++; + xfprintf(fp, " 0 <= ~r_%d <= %.*g\n", + i, DBL_DIG, row->ub - row->lb), count++; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_LO && col->lb == 0.0) continue; + if (!flag) + xfprintf(fp, "Bounds\n"), flag = 1, count++; + col_name(csa, j, name); + if (col->type == GLP_FR) + xfprintf(fp, " %s free\n", name), count++; + else if (col->type == GLP_LO) + xfprintf(fp, " %s >= %.*g\n", + name, DBL_DIG, col->lb), count++; + else if (col->type == GLP_UP) + xfprintf(fp, " -Inf <= %s <= %.*g\n", + name, DBL_DIG, col->ub), count++; + else if (col->type == GLP_DB) + xfprintf(fp, " %.*g <= %s <= %.*g\n", + DBL_DIG, col->lb, name, DBL_DIG, col->ub), count++; + else if (col->type == GLP_FX) + xfprintf(fp, " %s = %.*g\n", + name, DBL_DIG, col->lb), count++; + else + xassert(col != col); + } + if (flag) xfprintf(fp, "\n"), count++; + /* write the integer section */ + flag = 0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->kind == GLP_CV) continue; + xassert(col->kind == GLP_IV); + if (!flag) + xfprintf(fp, "Generals\n"), flag = 1, count++; + xfprintf(fp, " %s\n", col_name(csa, j, name)), count++; + } + if (flag) xfprintf(fp, "\n"), count++; +skip: /* write the end keyword */ + xfprintf(fp, "End\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* problem data has been successfully written */ + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/cpp.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/cpp.c new file mode 100644 index 000000000..ac3d63ef8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/cpp.c @@ -0,0 +1,185 @@ +/* cpp.c (solve critical path problem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_cpp - solve critical path problem +* +* SYNOPSIS +* +* double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +* +* DESCRIPTION +* +* The routine glp_cpp solves the critical path problem represented in +* the form of the project network. +* +* The parameter G is a pointer to the graph object, which specifies +* the project network. This graph must be acyclic. Multiple arcs are +* allowed being considered as single arcs. +* +* The parameter v_t specifies an offset of the field of type double +* in the vertex data block, which contains time t[i] >= 0 needed to +* perform corresponding job j. If v_t < 0, it is assumed that t[i] = 1 +* for all jobs. +* +* The parameter v_es specifies an offset of the field of type double +* in the vertex data block, to which the routine stores earliest start +* time for corresponding job. If v_es < 0, this time is not stored. +* +* The parameter v_ls specifies an offset of the field of type double +* in the vertex data block, to which the routine stores latest start +* time for corresponding job. If v_ls < 0, this time is not stored. +* +* RETURNS +* +* The routine glp_cpp returns the minimal project duration, that is, +* minimal time needed to perform all jobs in the project. */ + +static void sorting(glp_graph *G, int list[]); + +double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls) +{ glp_vertex *v; + glp_arc *a; + int i, j, k, nv, *list; + double temp, total, *t, *es, *ls; + if (v_t >= 0 && v_t > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_t = %d; invalid offset\n", v_t); + if (v_es >= 0 && v_es > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_es = %d; invalid offset\n", v_es); + if (v_ls >= 0 && v_ls > G->v_size - (int)sizeof(double)) + xerror("glp_cpp: v_ls = %d; invalid offset\n", v_ls); + nv = G->nv; + if (nv == 0) + { total = 0.0; + goto done; + } + /* allocate working arrays */ + t = xcalloc(1+nv, sizeof(double)); + es = xcalloc(1+nv, sizeof(double)); + ls = xcalloc(1+nv, sizeof(double)); + list = xcalloc(1+nv, sizeof(int)); + /* retrieve job times */ + for (i = 1; i <= nv; i++) + { v = G->v[i]; + if (v_t >= 0) + { memcpy(&t[i], (char *)v->data + v_t, sizeof(double)); + if (t[i] < 0.0) + xerror("glp_cpp: t[%d] = %g; invalid time\n", i, t[i]); + } + else + t[i] = 1.0; + } + /* perform topological sorting to determine the list of nodes + (jobs) such that if list[k] = i and list[kk] = j and there + exists arc (i->j), then k < kk */ + sorting(G, list); + /* FORWARD PASS */ + /* determine earliest start times */ + for (k = 1; k <= nv; k++) + { j = list[k]; + es[j] = 0.0; + for (a = G->v[j]->in; a != NULL; a = a->h_next) + { i = a->tail->i; + /* there exists arc (i->j) in the project network */ + temp = es[i] + t[i]; + if (es[j] < temp) es[j] = temp; + } + } + /* determine the minimal project duration */ + total = 0.0; + for (i = 1; i <= nv; i++) + { temp = es[i] + t[i]; + if (total < temp) total = temp; + } + /* BACKWARD PASS */ + /* determine latest start times */ + for (k = nv; k >= 1; k--) + { i = list[k]; + ls[i] = total - t[i]; + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { j = a->head->i; + /* there exists arc (i->j) in the project network */ + temp = ls[j] - t[i]; + if (ls[i] > temp) ls[i] = temp; + } + /* avoid possible round-off errors */ + if (ls[i] < es[i]) ls[i] = es[i]; + } + /* store results, if necessary */ + if (v_es >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_es, &es[i], sizeof(double)); + } + } + if (v_ls >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_ls, &ls[i], sizeof(double)); + } + } + /* free working arrays */ + xfree(t); + xfree(es); + xfree(ls); + xfree(list); +done: return total; +} + +static void sorting(glp_graph *G, int list[]) +{ /* perform topological sorting to determine the list of nodes + (jobs) such that if list[k] = i and list[kk] = j and there + exists arc (i->j), then k < kk */ + int i, k, nv, v_size, *num; + void **save; + nv = G->nv; + v_size = G->v_size; + save = xcalloc(1+nv, sizeof(void *)); + num = xcalloc(1+nv, sizeof(int)); + G->v_size = sizeof(int); + for (i = 1; i <= nv; i++) + { save[i] = G->v[i]->data; + G->v[i]->data = &num[i]; + list[i] = 0; + } + if (glp_top_sort(G, 0) != 0) + xerror("glp_cpp: project network is not acyclic\n"); + G->v_size = v_size; + for (i = 1; i <= nv; i++) + { G->v[i]->data = save[i]; + k = num[i]; + xassert(1 <= k && k <= nv); + xassert(list[k] == 0); + list[k] = i; + } + xfree(save); + xfree(num); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/cpxbas.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/cpxbas.c new file mode 100644 index 000000000..e1c656a74 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/cpxbas.c @@ -0,0 +1,269 @@ +/* cpxbas.c (construct Bixby's initial LP basis) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +struct var +{ /* structural variable */ + int j; + /* ordinal number */ + double q; + /* penalty value */ +}; + +static int CDECL fcmp(const void *ptr1, const void *ptr2) +{ /* this routine is passed to the qsort() function */ + struct var *col1 = (void *)ptr1, *col2 = (void *)ptr2; + if (col1->q < col2->q) return -1; + if (col1->q > col2->q) return +1; + return 0; +} + +static int get_column(glp_prob *lp, int j, int ind[], double val[]) +{ /* Bixby's algorithm assumes that the constraint matrix is scaled + such that the maximum absolute value in every non-zero row and + column is 1 */ + int k, len; + double big; + len = glp_get_mat_col(lp, j, ind, val); + big = 0.0; + for (k = 1; k <= len; k++) + if (big < fabs(val[k])) big = fabs(val[k]); + if (big == 0.0) big = 1.0; + for (k = 1; k <= len; k++) val[k] /= big; + return len; +} + +static void cpx_basis(glp_prob *lp) +{ /* main routine */ + struct var *C, *C2, *C3, *C4; + int m, n, i, j, jk, k, l, ll, t, n2, n3, n4, type, len, *I, *r, + *ind; + double alpha, gamma, cmax, temp, *v, *val; + xprintf("Constructing initial basis...\n"); + /* determine the number of rows and columns */ + m = glp_get_num_rows(lp); + n = glp_get_num_cols(lp); + /* allocate working arrays */ + C = xcalloc(1+n, sizeof(struct var)); + I = xcalloc(1+m, sizeof(int)); + r = xcalloc(1+m, sizeof(int)); + v = xcalloc(1+m, sizeof(double)); + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + /* make all auxiliary variables non-basic */ + for (i = 1; i <= m; i++) + { if (glp_get_row_type(lp, i) != GLP_DB) + glp_set_row_stat(lp, i, GLP_NS); + else if (fabs(glp_get_row_lb(lp, i)) <= + fabs(glp_get_row_ub(lp, i))) + glp_set_row_stat(lp, i, GLP_NL); + else + glp_set_row_stat(lp, i, GLP_NU); + } + /* make all structural variables non-basic */ + for (j = 1; j <= n; j++) + { if (glp_get_col_type(lp, j) != GLP_DB) + glp_set_col_stat(lp, j, GLP_NS); + else if (fabs(glp_get_col_lb(lp, j)) <= + fabs(glp_get_col_ub(lp, j))) + glp_set_col_stat(lp, j, GLP_NL); + else + glp_set_col_stat(lp, j, GLP_NU); + } + /* C2 is a set of free structural variables */ + n2 = 0, C2 = C + 0; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_FR) + { n2++; + C2[n2].j = j; + C2[n2].q = 0.0; + } + } + /* C3 is a set of structural variables having excatly one (lower + or upper) bound */ + n3 = 0, C3 = C2 + n2; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_LO) + { n3++; + C3[n3].j = j; + C3[n3].q = + glp_get_col_lb(lp, j); + } + else if (type == GLP_UP) + { n3++; + C3[n3].j = j; + C3[n3].q = - glp_get_col_ub(lp, j); + } + } + /* C4 is a set of structural variables having both (lower and + upper) bounds */ + n4 = 0, C4 = C3 + n3; + for (j = 1; j <= n; j++) + { type = glp_get_col_type(lp, j); + if (type == GLP_DB) + { n4++; + C4[n4].j = j; + C4[n4].q = glp_get_col_lb(lp, j) - glp_get_col_ub(lp, j); + } + } + /* compute gamma = max{|c[j]|: 1 <= j <= n} */ + gamma = 0.0; + for (j = 1; j <= n; j++) + { temp = fabs(glp_get_obj_coef(lp, j)); + if (gamma < temp) gamma = temp; + } + /* compute cmax */ + cmax = (gamma == 0.0 ? 1.0 : 1000.0 * gamma); + /* compute final penalty for all structural variables within sets + C2, C3, and C4 */ + switch (glp_get_obj_dir(lp)) + { case GLP_MIN: temp = +1.0; break; + case GLP_MAX: temp = -1.0; break; + default: xassert(lp != lp); + } + for (k = 1; k <= n2+n3+n4; k++) + { j = C[k].j; + C[k].q += (temp * glp_get_obj_coef(lp, j)) / cmax; + } + /* sort structural variables within C2, C3, and C4 in ascending + order of penalty value */ + qsort(C2+1, n2, sizeof(struct var), fcmp); + for (k = 1; k < n2; k++) xassert(C2[k].q <= C2[k+1].q); + qsort(C3+1, n3, sizeof(struct var), fcmp); + for (k = 1; k < n3; k++) xassert(C3[k].q <= C3[k+1].q); + qsort(C4+1, n4, sizeof(struct var), fcmp); + for (k = 1; k < n4; k++) xassert(C4[k].q <= C4[k+1].q); + /*** STEP 1 ***/ + for (i = 1; i <= m; i++) + { type = glp_get_row_type(lp, i); + if (type != GLP_FX) + { /* row i is either free or inequality constraint */ + glp_set_row_stat(lp, i, GLP_BS); + I[i] = 1; + r[i] = 1; + } + else + { /* row i is equality constraint */ + I[i] = 0; + r[i] = 0; + } + v[i] = +DBL_MAX; + } + /*** STEP 2 ***/ + for (k = 1; k <= n2+n3+n4; k++) + { jk = C[k].j; + len = get_column(lp, jk, ind, val); + /* let alpha = max{|A[l,jk]|: r[l] = 0} and let l' be such + that alpha = |A[l',jk]| */ + alpha = 0.0, ll = 0; + for (t = 1; t <= len; t++) + { l = ind[t]; + if (r[l] == 0 && alpha < fabs(val[t])) + alpha = fabs(val[t]), ll = l; + } + if (alpha >= 0.99) + { /* B := B union {jk} */ + glp_set_col_stat(lp, jk, GLP_BS); + I[ll] = 1; + v[ll] = alpha; + /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (val[t] != 0.0) r[l]++; + } + /* continue to the next k */ + continue; + } + /* if |A[l,jk]| > 0.01 * v[l] for some l, continue to the + next k */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (fabs(val[t]) > 0.01 * v[l]) break; + } + if (t <= len) continue; + /* otherwise, let alpha = max{|A[l,jk]|: I[l] = 0} and let l' + be such that alpha = |A[l',jk]| */ + alpha = 0.0, ll = 0; + for (t = 1; t <= len; t++) + { l = ind[t]; + if (I[l] == 0 && alpha < fabs(val[t])) + alpha = fabs(val[t]), ll = l; + } + /* if alpha = 0, continue to the next k */ + if (alpha == 0.0) continue; + /* B := B union {jk} */ + glp_set_col_stat(lp, jk, GLP_BS); + I[ll] = 1; + v[ll] = alpha; + /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ + for (t = 1; t <= len; t++) + { l = ind[t]; + if (val[t] != 0.0) r[l]++; + } + } + /*** STEP 3 ***/ + /* add an artificial variable (auxiliary variable for equality + constraint) to cover each remaining uncovered row */ + for (i = 1; i <= m; i++) + if (I[i] == 0) glp_set_row_stat(lp, i, GLP_BS); + /* free working arrays */ + xfree(C); + xfree(I); + xfree(r); + xfree(v); + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_cpx_basis - construct Bixby's initial LP basis +* +* SYNOPSIS +* +* void glp_cpx_basis(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_cpx_basis constructs an advanced initial basis for +* the specified problem object. +* +* The routine is based on Bixby's algorithm described in the paper: +* +* Robert E. Bixby. Implementing the Simplex Method: The Initial Basis. +* ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84. */ + +void glp_cpx_basis(glp_prob *lp) +{ if (lp->m == 0 || lp->n == 0) + glp_std_basis(lp); + else + cpx_basis(lp); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/graph.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/graph.c new file mode 100644 index 000000000..82994c84f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/graph.c @@ -0,0 +1,504 @@ +/* graph.c (basic graph routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "avl.h" +#include "dmp.h" +#include "env.h" +#include "glpk.h" + +/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ + +#define NV_MAX 100000000 /* = 100*10^6 */ +/* maximal number of vertices in the graph */ + +#define NA_MAX 500000000 /* = 500*10^6 */ +/* maximal number of arcs in the graph */ + +/*********************************************************************** +* NAME +* +* glp_create_graph - create graph +* +* SYNOPSIS +* +* glp_graph *glp_create_graph(int v_size, int a_size); +* +* DESCRIPTION +* +* The routine creates a new graph, which initially is empty, i.e. has +* no vertices and arcs. +* +* The parameter v_size specifies the size of data associated with each +* vertex of the graph (0 to 256 bytes). +* +* The parameter a_size specifies the size of data associated with each +* arc of the graph (0 to 256 bytes). +* +* RETURNS +* +* The routine returns a pointer to the graph created. */ + +static void create_graph(glp_graph *G, int v_size, int a_size) +{ G->pool = dmp_create_pool(); + G->name = NULL; + G->nv_max = 50; + G->nv = G->na = 0; + G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); + G->index = NULL; + G->v_size = v_size; + G->a_size = a_size; + return; +} + +glp_graph *glp_create_graph(int v_size, int a_size) +{ glp_graph *G; + if (!(0 <= v_size && v_size <= 256)) + xerror("glp_create_graph: v_size = %d; invalid size of vertex " + "data\n", v_size); + if (!(0 <= a_size && a_size <= 256)) + xerror("glp_create_graph: a_size = %d; invalid size of arc dat" + "a\n", a_size); + G = xmalloc(sizeof(glp_graph)); + create_graph(G, v_size, a_size); + return G; +} + +/*********************************************************************** +* NAME +* +* glp_set_graph_name - assign (change) graph name +* +* SYNOPSIS +* +* void glp_set_graph_name(glp_graph *G, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_graph_name assigns a symbolic name specified by +* the character string name (1 to 255 chars) to the graph. +* +* If the parameter name is NULL or an empty string, the routine erases +* the existing symbolic name of the graph. */ + +void glp_set_graph_name(glp_graph *G, const char *name) +{ if (G->name != NULL) + { dmp_free_atom(G->pool, G->name, strlen(G->name)+1); + G->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int j; + for (j = 0; name[j] != '\0'; j++) + { if (j == 256) + xerror("glp_set_graph_name: graph name too long\n"); + if (iscntrl((unsigned char)name[j])) + xerror("glp_set_graph_name: graph name contains invalid " + "character(s)\n"); + } + G->name = dmp_get_atom(G->pool, strlen(name)+1); + strcpy(G->name, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_vertices - add new vertices to graph +* +* SYNOPSIS +* +* int glp_add_vertices(glp_graph *G, int nadd); +* +* DESCRIPTION +* +* The routine glp_add_vertices adds nadd vertices to the specified +* graph. New vertices are always added to the end of the vertex list, +* so ordinal numbers of existing vertices remain unchanged. +* +* Being added each new vertex is isolated (has no incident arcs). +* +* RETURNS +* +* The routine glp_add_vertices returns an ordinal number of the first +* new vertex added to the graph. */ + +int glp_add_vertices(glp_graph *G, int nadd) +{ int i, nv_new; + if (nadd < 1) + xerror("glp_add_vertices: nadd = %d; invalid number of vertice" + "s\n", nadd); + if (nadd > NV_MAX - G->nv) + xerror("glp_add_vertices: nadd = %d; too many vertices\n", + nadd); + /* determine new number of vertices */ + nv_new = G->nv + nadd; + /* increase the room, if necessary */ + if (G->nv_max < nv_new) + { glp_vertex **save = G->v; + while (G->nv_max < nv_new) + { G->nv_max += G->nv_max; + xassert(G->nv_max > 0); + } + G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); + memcpy(&G->v[1], &save[1], G->nv * sizeof(glp_vertex *)); + xfree(save); + } + /* add new vertices to the end of the vertex list */ + for (i = G->nv+1; i <= nv_new; i++) + { glp_vertex *v; + G->v[i] = v = dmp_get_atom(G->pool, sizeof(glp_vertex)); + v->i = i; + v->name = NULL; + v->entry = NULL; + if (G->v_size == 0) + v->data = NULL; + else + { v->data = dmp_get_atom(G->pool, G->v_size); + memset(v->data, 0, G->v_size); + } + v->temp = NULL; + v->in = v->out = NULL; + } + /* set new number of vertices */ + G->nv = nv_new; + /* return the ordinal number of the first vertex added */ + return nv_new - nadd + 1; +} + +/**********************************************************************/ + +void glp_set_vertex_name(glp_graph *G, int i, const char *name) +{ /* assign (change) vertex name */ + glp_vertex *v; + if (!(1 <= i && i <= G->nv)) + xerror("glp_set_vertex_name: i = %d; vertex number out of rang" + "e\n", i); + v = G->v[i]; + if (v->name != NULL) + { if (v->entry != NULL) + { xassert(G->index != NULL); + avl_delete_node(G->index, v->entry); + v->entry = NULL; + } + dmp_free_atom(G->pool, v->name, strlen(v->name)+1); + v->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_vertex_name: i = %d; vertex name too lon" + "g\n", i); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_vertex_name: i = %d; vertex name contain" + "s invalid character(s)\n", i); + } + v->name = dmp_get_atom(G->pool, strlen(name)+1); + strcpy(v->name, name); + if (G->index != NULL) + { xassert(v->entry == NULL); + v->entry = avl_insert_node(G->index, v->name); + avl_set_node_link(v->entry, v); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_arc - add new arc to graph +* +* SYNOPSIS +* +* glp_arc *glp_add_arc(glp_graph *G, int i, int j); +* +* DESCRIPTION +* +* The routine glp_add_arc adds a new arc to the specified graph. +* +* The parameters i and j specify the ordinal numbers of, resp., tail +* and head vertices of the arc. Note that self-loops and multiple arcs +* are allowed. +* +* RETURNS +* +* The routine glp_add_arc returns a pointer to the arc added. */ + +glp_arc *glp_add_arc(glp_graph *G, int i, int j) +{ glp_arc *a; + if (!(1 <= i && i <= G->nv)) + xerror("glp_add_arc: i = %d; tail vertex number out of range\n" + , i); + if (!(1 <= j && j <= G->nv)) + xerror("glp_add_arc: j = %d; head vertex number out of range\n" + , j); + if (G->na == NA_MAX) + xerror("glp_add_arc: too many arcs\n"); + a = dmp_get_atom(G->pool, sizeof(glp_arc)); + a->tail = G->v[i]; + a->head = G->v[j]; + if (G->a_size == 0) + a->data = NULL; + else + { a->data = dmp_get_atom(G->pool, G->a_size); + memset(a->data, 0, G->a_size); + } + a->temp = NULL; + a->t_prev = NULL; + a->t_next = G->v[i]->out; + if (a->t_next != NULL) a->t_next->t_prev = a; + a->h_prev = NULL; + a->h_next = G->v[j]->in; + if (a->h_next != NULL) a->h_next->h_prev = a; + G->v[i]->out = G->v[j]->in = a; + G->na++; + return a; +} + +/*********************************************************************** +* NAME +* +* glp_del_vertices - delete vertices from graph +* +* SYNOPSIS +* +* void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_vertices deletes vertices along with all +* incident arcs from the specified graph. Ordinal numbers of vertices +* to be deleted should be placed in locations num[1], ..., num[ndel], +* ndel > 0. +* +* Note that deleting vertices involves changing ordinal numbers of +* other vertices remaining in the graph. New ordinal numbers of the +* remaining vertices are assigned under the assumption that the +* original order of vertices is not changed. */ + +void glp_del_vertices(glp_graph *G, int ndel, const int num[]) +{ glp_vertex *v; + int i, k, nv_new; + /* scan the list of vertices to be deleted */ + if (!(1 <= ndel && ndel <= G->nv)) + xerror("glp_del_vertices: ndel = %d; invalid number of vertice" + "s\n", ndel); + for (k = 1; k <= ndel; k++) + { /* take the number of vertex to be deleted */ + i = num[k]; + /* obtain pointer to i-th vertex */ + if (!(1 <= i && i <= G->nv)) + xerror("glp_del_vertices: num[%d] = %d; vertex number out o" + "f range\n", k, i); + v = G->v[i]; + /* check that the vertex is not marked yet */ + if (v->i == 0) + xerror("glp_del_vertices: num[%d] = %d; duplicate vertex nu" + "mbers not allowed\n", k, i); + /* erase symbolic name assigned to the vertex */ + glp_set_vertex_name(G, i, NULL); + xassert(v->name == NULL); + xassert(v->entry == NULL); + /* free vertex data, if allocated */ + if (v->data != NULL) + dmp_free_atom(G->pool, v->data, G->v_size); + /* delete all incoming arcs */ + while (v->in != NULL) + glp_del_arc(G, v->in); + /* delete all outgoing arcs */ + while (v->out != NULL) + glp_del_arc(G, v->out); + /* mark the vertex to be deleted */ + v->i = 0; + } + /* delete all marked vertices from the vertex list */ + nv_new = 0; + for (i = 1; i <= G->nv; i++) + { /* obtain pointer to i-th vertex */ + v = G->v[i]; + /* check if the vertex is marked */ + if (v->i == 0) + { /* it is marked, delete it */ + dmp_free_atom(G->pool, v, sizeof(glp_vertex)); + } + else + { /* it is not marked, keep it */ + v->i = ++nv_new; + G->v[v->i] = v; + } + } + /* set new number of vertices in the graph */ + G->nv = nv_new; + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_arc - delete arc from graph +* +* SYNOPSIS +* +* void glp_del_arc(glp_graph *G, glp_arc *a); +* +* DESCRIPTION +* +* The routine glp_del_arc deletes an arc from the specified graph. +* The arc to be deleted must exist. */ + +void glp_del_arc(glp_graph *G, glp_arc *a) +{ /* some sanity checks */ + xassert(G->na > 0); + xassert(1 <= a->tail->i && a->tail->i <= G->nv); + xassert(a->tail == G->v[a->tail->i]); + xassert(1 <= a->head->i && a->head->i <= G->nv); + xassert(a->head == G->v[a->head->i]); + /* remove the arc from the list of incoming arcs */ + if (a->h_prev == NULL) + a->head->in = a->h_next; + else + a->h_prev->h_next = a->h_next; + if (a->h_next == NULL) + ; + else + a->h_next->h_prev = a->h_prev; + /* remove the arc from the list of outgoing arcs */ + if (a->t_prev == NULL) + a->tail->out = a->t_next; + else + a->t_prev->t_next = a->t_next; + if (a->t_next == NULL) + ; + else + a->t_next->t_prev = a->t_prev; + /* free arc data, if allocated */ + if (a->data != NULL) + dmp_free_atom(G->pool, a->data, G->a_size); + /* delete the arc from the graph */ + dmp_free_atom(G->pool, a, sizeof(glp_arc)); + G->na--; + return; +} + +/*********************************************************************** +* NAME +* +* glp_erase_graph - erase graph content +* +* SYNOPSIS +* +* void glp_erase_graph(glp_graph *G, int v_size, int a_size); +* +* DESCRIPTION +* +* The routine glp_erase_graph erases the content of the specified +* graph. The effect of this operation is the same as if the graph +* would be deleted with the routine glp_delete_graph and then created +* anew with the routine glp_create_graph, with exception that the +* handle (pointer) to the graph remains valid. */ + +static void delete_graph(glp_graph *G) +{ dmp_delete_pool(G->pool); + xfree(G->v); + if (G->index != NULL) avl_delete_tree(G->index); + return; +} + +void glp_erase_graph(glp_graph *G, int v_size, int a_size) +{ if (!(0 <= v_size && v_size <= 256)) + xerror("glp_erase_graph: v_size = %d; invalid size of vertex d" + "ata\n", v_size); + if (!(0 <= a_size && a_size <= 256)) + xerror("glp_erase_graph: a_size = %d; invalid size of arc data" + "\n", a_size); + delete_graph(G); + create_graph(G, v_size, a_size); + return; +} + +/*********************************************************************** +* NAME +* +* glp_delete_graph - delete graph +* +* SYNOPSIS +* +* void glp_delete_graph(glp_graph *G); +* +* DESCRIPTION +* +* The routine glp_delete_graph deletes the specified graph and frees +* all the memory allocated to this program object. */ + +void glp_delete_graph(glp_graph *G) +{ delete_graph(G); + xfree(G); + return; +} + +/**********************************************************************/ + +void glp_create_v_index(glp_graph *G) +{ /* create vertex name index */ + glp_vertex *v; + int i; + if (G->index == NULL) + { G->index = avl_create_tree(avl_strcmp, NULL); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + xassert(v->entry == NULL); + if (v->name != NULL) + { v->entry = avl_insert_node(G->index, v->name); + avl_set_node_link(v->entry, v); + } + } + } + return; +} + +int glp_find_vertex(glp_graph *G, const char *name) +{ /* find vertex by its name */ + AVLNODE *node; + int i = 0; + if (G->index == NULL) + xerror("glp_find_vertex: vertex name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(G->index, name); + if (node != NULL) + i = ((glp_vertex *)avl_get_node_link(node))->i; + } + return i; +} + +void glp_delete_v_index(glp_graph *G) +{ /* delete vertex name index */ + int i; + if (G->index != NULL) + { avl_delete_tree(G->index), G->index = NULL; + for (i = 1; i <= G->nv; i++) G->v[i]->entry = NULL; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/gridgen.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/gridgen.c new file mode 100644 index 000000000..8cd3517fa --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/gridgen.c @@ -0,0 +1,769 @@ +/* gridgen.c (grid-like network problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the program GRIDGEN, a grid-like +* network problem generator developed by Yusin Lee and Jim Orlin. +* The original code is publically available on the DIMACS ftp site at: +* . +* +* All changes concern only the program interface, so this modified +* version produces exactly the same instances as the original version. +* +* Changes were made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_gridgen - grid-like network problem generator +* +* SYNOPSIS +* +* int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, +* const int parm[1+14]); +* +* DESCRIPTION +* +* The routine glp_gridgen is a grid-like network problem generator +* developed by Yusin Lee and Jim Orlin. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The parameter v_rhs specifies an offset of the field of type double +* in the vertex data block, to which the routine stores the supply or +* demand value. If v_rhs < 0, the value is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The parameter a_cost specifies an offset of the field of type double +* in the arc data block, to which the routine stores the per-unit cost +* if the arc flow. If a_cost < 0, the cost is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] two-ways arcs indicator: +* 1 - if links in both direction should be generated +* 0 - otherwise +* parm[2] random number seed (a positive integer) +* parm[3] number of nodes (the number of nodes generated might be +* slightly different to make the network a grid) +* parm[4] grid width +* parm[5] number of sources +* parm[6] number of sinks +* parm[7] average degree +* parm[8] total flow +* parm[9] distribution of arc costs: +* 1 - uniform +* 2 - exponential +* parm[10] lower bound for arc cost (uniform) +* 100 * lambda (exponential) +* parm[11] upper bound for arc cost (uniform) +* not used (exponential) +* parm[12] distribution of arc capacities: +* 1 - uniform +* 2 - exponential +* parm[13] lower bound for arc capacity (uniform) +* 100 * lambda (exponential) +* parm[14] upper bound for arc capacity (uniform) +* not used (exponential) +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_gridgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* COMMENTS +* +* This network generator generates a grid-like network plus a super +* node. In additional to the arcs connecting the nodes in the grid, +* there is an arc from each supply node to the super node and from the +* super node to each demand node to guarantee feasiblity. These arcs +* have very high costs and very big capacities. +* +* The idea of this network generator is as follows: First, a grid of +* n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as +* 1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between +* adjacent nodes are generated. For these arcs, the user is allowed to +* specify either to generate two-way arcs or one-way arcs. If two-way +* arcs are to be generated, two arcs, one in each direction, will be +* generated between each adjacent node pairs. Otherwise, only one arc +* will be generated. If this is the case, the arcs will be generated +* in alterntive directions as shown below. +* +* 1 ---> 2 ---> 3 ---> 4 ---> 5 +* | ^ | ^ | +* | | | | | +* V | V | V +* 6 <--- 7 <--- 8 <--- 9 <--- 10 +* | ^ | ^ | +* | | | | | +* V | V | V +* 11 --->12 --->13 --->14 ---> 15 +* +* Then the arcs between the super node and the source/sink nodes are +* added as mentioned before. If the number of arcs still doesn't reach +* the requirement, additional arcs will be added by uniformly picking +* random node pairs. There is no checking to prevent multiple arcs +* between any pair of nodes. However, there will be no self-arcs (arcs +* that poins back to its tail node) in the network. +* +* The source and sink nodes are selected uniformly in the network, and +* the imbalances of each source/sink node are also assigned by uniform +* distribution. */ + +struct stat_para +{ /* structure for statistical distributions */ + int distribution; + /* the distribution: */ +#define UNIFORM 1 /* uniform distribution */ +#define EXPONENTIAL 2 /* exponential distribution */ + double parameter[5]; + /* the parameters of the distribution */ +}; + +struct arcs +{ int from; + /* the FROM node of that arc */ + int to; + /* the TO node of that arc */ + int cost; + /* original cost of that arc */ + int u; + /* capacity of the arc */ +}; + +struct imbalance +{ int node; + /* Node ID */ + int supply; + /* Supply of that node */ +}; + +struct csa +{ /* common storage area */ + glp_graph *G; + int v_rhs, a_cap, a_cost; + int seed; + /* random number seed */ + int seed_original; + /* the original seed from input */ + int two_way; + /* 0: generate arcs in both direction for the basic grid, except + for the arcs to/from the super node. 1: o/w */ + int n_node; + /* total number of nodes in the network, numbered 1 to n_node, + including the super node, which is the last one */ + int n_arc; + /* total number of arcs in the network, counting EVERY arc. */ + int n_grid_arc; + /* number of arcs in the basic grid, including the arcs to/from + the super node */ + int n_source, n_sink; + /* number of source and sink nodes */ + int avg_degree; + /* average degree, arcs to and from the super node are counted */ + int t_supply; + /* total supply in the network */ + int n1, n2; + /* the two edges of the network grid. n1 >= n2 */ + struct imbalance *source_list, *sink_list; + /* head of the array of source/sink nodes */ + struct stat_para arc_costs; + /* the distribution of arc costs */ + struct stat_para capacities; + /* distribution of the capacities of the arcs */ + struct arcs *arc_list; + /* head of the arc list array. Arcs in this array are in the + order of grid_arcs, arcs to/from super node, and other arcs */ +}; + +#define G (csa->G) +#define v_rhs (csa->v_rhs) +#define a_cap (csa->a_cap) +#define a_cost (csa->a_cost) +#define seed (csa->seed) +#define seed_original (csa->seed_original) +#define two_way (csa->two_way) +#define n_node (csa->n_node) +#define n_arc (csa->n_arc) +#define n_grid_arc (csa->n_grid_arc) +#define n_source (csa->n_source) +#define n_sink (csa->n_sink) +#define avg_degree (csa->avg_degree) +#define t_supply (csa->t_supply) +#define n1 (csa->n1) +#define n2 (csa->n2) +#define source_list (csa->source_list) +#define sink_list (csa->sink_list) +#define arc_costs (csa->arc_costs) +#define capacities (csa->capacities) +#define arc_list (csa->arc_list) + +static void assign_capacities(struct csa *csa); +static void assign_costs(struct csa *csa); +static void assign_imbalance(struct csa *csa); +static int exponential(struct csa *csa, double lambda[1]); +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs + *arc_ptr); +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs + *arc_ptr); +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr); +static void generate(struct csa *csa); +static void output(struct csa *csa); +static double randy(struct csa *csa); +static void select_source_sinks(struct csa *csa); +static int uniform(struct csa *csa, double a[2]); + +int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, + const int parm[1+14]) +{ struct csa _csa, *csa = &_csa; + int n, ret; + G = G_; + v_rhs = _v_rhs; + a_cap = _a_cap; + a_cost = _a_cost; + if (G != NULL) + { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost) + ; + } + /* Check the parameters for consistency. */ + if (!(parm[1] == 0 || parm[1] == 1)) + { ret = 1; + goto done; + } + if (parm[2] < 1) + { ret = 2; + goto done; + } + if (!(10 <= parm[3] && parm[3] <= 40000)) + { ret = 3; + goto done; + } + if (!(1 <= parm[4] && parm[4] <= 40000)) + { ret = 4; + goto done; + } + if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <= + parm[3])) + { ret = 5; + goto done; + } + if (!(1 <= parm[7] && parm[7] <= parm[3])) + { ret = 6; + goto done; + } + if (parm[8] < 0) + { ret = 7; + goto done; + } + if (!(parm[9] == 1 || parm[9] == 2)) + { ret = 8; + goto done; + } + if (parm[9] == 1 && parm[10] > parm[11] || + parm[9] == 2 && parm[10] < 1) + { ret = 9; + goto done; + } + if (!(parm[12] == 1 || parm[12] == 2)) + { ret = 10; + goto done; + } + if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) || + parm[12] == 2 && parm[13] < 1) + { ret = 11; + goto done; + } + /* Initialize the graph object. */ + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_set_graph_name(G, "GRIDGEN"); + } + /* Copy the generator parameters. */ + two_way = parm[1]; + seed_original = seed = parm[2]; + n_node = parm[3]; + n = parm[4]; + n_source = parm[5]; + n_sink = parm[6]; + avg_degree = parm[7]; + t_supply = parm[8]; + arc_costs.distribution = parm[9]; + if (parm[9] == 1) + { arc_costs.parameter[0] = parm[10]; + arc_costs.parameter[1] = parm[11]; + } + else + { arc_costs.parameter[0] = (double)parm[10] / 100.0; + arc_costs.parameter[1] = 0.0; + } + capacities.distribution = parm[12]; + if (parm[12] == 1) + { capacities.parameter[0] = parm[13]; + capacities.parameter[1] = parm[14]; + } + else + { capacities.parameter[0] = (double)parm[13] / 100.0; + capacities.parameter[1] = 0.0; + } + /* Calculate the edge lengths of the grid according to the + input. */ + if (n * n >= n_node) + { n1 = n; + n2 = (int)((double)n_node / (double)n + 0.5); + } + else + { n2 = n; + n1 = (int)((double)n_node / (double)n + 0.5); + } + /* Recalculate the total number of nodes and plus 1 for the super + node. */ + n_node = n1 * n2 + 1; + n_arc = n_node * avg_degree; + n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) + + n_source + n_sink; + if (n_grid_arc > n_arc) n_arc = n_grid_arc; + arc_list = xcalloc(n_arc, sizeof(struct arcs)); + source_list = xcalloc(n_source, sizeof(struct imbalance)); + sink_list = xcalloc(n_sink, sizeof(struct imbalance)); + /* Generate a random network. */ + generate(csa); + /* Output the network. */ + output(csa); + /* Free all allocated memory. */ + xfree(arc_list); + xfree(source_list); + xfree(sink_list); + /* The instance has been successfully generated. */ + ret = 0; +done: return ret; +} + +#undef random + +static void assign_capacities(struct csa *csa) +{ /* Assign a capacity to each arc. */ + struct arcs *arc_ptr = arc_list; + int (*random)(struct csa *csa, double *); + int i; + /* Determine the random number generator to use. */ + switch (arc_costs.distribution) + { case UNIFORM: + random = uniform; + break; + case EXPONENTIAL: + random = exponential; + break; + default: + xassert(csa != csa); + } + /* Assign capacities to grid arcs. */ + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->u = random(csa, capacities.parameter); + i = i - n_source - n_sink; + /* Assign capacities to arcs to/from supernode. */ + for (; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->u = t_supply; + /* Assign capacities to all other arcs. */ + for (; i < n_arc; i++, arc_ptr++) + arc_ptr->u = random(csa, capacities.parameter); + return; +} + +static void assign_costs(struct csa *csa) +{ /* Assign a cost to each arc. */ + struct arcs *arc_ptr = arc_list; + int (*random)(struct csa *csa, double *); + int i; + /* A high cost assigned to arcs to/from the supernode. */ + int high_cost; + /* The maximum cost assigned to arcs in the base grid. */ + int max_cost = 0; + /* Determine the random number generator to use. */ + switch (arc_costs.distribution) + { case UNIFORM: + random = uniform; + break; + case EXPONENTIAL: + random = exponential; + break; + default: + xassert(csa != csa); + } + /* Assign costs to arcs in the base grid. */ + for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) + { arc_ptr->cost = random(csa, arc_costs.parameter); + if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost; + } + i = i - n_source - n_sink; + /* Assign costs to arcs to/from the super node. */ + high_cost = max_cost * 2; + for (; i < n_grid_arc; i++, arc_ptr++) + arc_ptr->cost = high_cost; + /* Assign costs to all other arcs. */ + for (; i < n_arc; i++, arc_ptr++) + arc_ptr->cost = random(csa, arc_costs.parameter); + return; +} + +static void assign_imbalance(struct csa *csa) +{ /* Assign an imbalance to each node. */ + int total, i; + double avg; + struct imbalance *ptr; + /* assign the supply nodes */ + avg = 2.0 * t_supply / n_source; + do + { for (i = 1, total = t_supply, ptr = source_list + 1; + i < n_source; i++, ptr++) + { ptr->supply = (int)(randy(csa) * avg + 0.5); + total -= ptr->supply; + } + source_list->supply = total; + } + /* redo all if the assignment "overshooted" */ + while (total <= 0); + /* assign the demand nodes */ + avg = -2.0 * t_supply / n_sink; + do + { for (i = 1, total = t_supply, ptr = sink_list + 1; + i < n_sink; i++, ptr++) + { ptr->supply = (int)(randy(csa) * avg - 0.5); + total += ptr->supply; + } + sink_list->supply = - total; + } + while (total <= 0); + return; +} + +static int exponential(struct csa *csa, double lambda[1]) +{ /* Returns an "exponentially distributed" integer with parameter + lambda. */ + return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5)); +} + +static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs + *arc_ptr) +{ /* Generate an arc from each source to the supernode and from + supernode to each sink. */ + int i; + for (i = 0; i < n_source; i++, arc_ptr++) + { arc_ptr->from = source_list[i].node; + arc_ptr->to = n_node; + } + for (i = 0; i < n_sink; i++, arc_ptr++) + { arc_ptr->to = sink_list[i].node; + arc_ptr->from = n_node; + } + return arc_ptr; +} + +static struct arcs *gen_basic_grid(struct csa *csa, struct arcs + *arc_ptr) +{ /* Generate the basic grid. */ + int direction = 1, i, j, k; + if (two_way) + { /* Generate an arc in each direction. */ + for (i = 1; i < n_node; i += n1) + { for (j = i, k = j + n1 - 1; j < k; j++) + { arc_ptr->from = j; + arc_ptr->to = j + 1; + arc_ptr++; + arc_ptr->from = j + 1; + arc_ptr->to = j; + arc_ptr++; + } + } + for (i = 1; i <= n1; i++) + { for (j = i + n1; j < n_node; j += n1) + { arc_ptr->from = j; + arc_ptr->to = j - n1; + arc_ptr++; + arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + } + else + { /* Generate one arc in each direction. */ + for (i = 1; i < n_node; i += n1) + { if (direction == 1) + j = i; + else + j = i + 1; + for (k = j + n1 - 1; j < k; j++) + { arc_ptr->from = j; + arc_ptr->to = j + direction; + arc_ptr++; + } + direction = - direction; + } + for (i = 1; i <= n1; i++) + { j = i + n1; + if (direction == 1) + { for (; j < n_node; j += n1) + { arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + else + { for (; j < n_node; j += n1) + { arc_ptr->from = j - n1; + arc_ptr->to = j; + arc_ptr++; + } + } + direction = - direction; + } + } + return arc_ptr; +} + +static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr) +{ /* Generate random arcs to meet the specified density. */ + int i; + double ab[2]; + ab[0] = 0.9; + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the + supernode cannot be selected */ + for (i = n_grid_arc; i < n_arc; i++, arc_ptr++) + { arc_ptr->from = uniform(csa, ab); + arc_ptr->to = uniform(csa, ab); + if (arc_ptr->from == arc_ptr->to) + { arc_ptr--; + i--; + } + } + return; +} + +static void generate(struct csa *csa) +{ /* Generate a random network. */ + struct arcs *arc_ptr = arc_list; + arc_ptr = gen_basic_grid(csa, arc_ptr); + select_source_sinks(csa); + arc_ptr = gen_additional_arcs(csa, arc_ptr); + gen_more_arcs(csa, arc_ptr); + assign_costs(csa); + assign_capacities(csa); + assign_imbalance(csa); + return; +} + +static void output(struct csa *csa) +{ /* Output the network in DIMACS format. */ + struct arcs *arc_ptr; + struct imbalance *imb_ptr; + int i; + if (G != NULL) goto skip; + /* Output "c", "p" records. */ + xprintf("c generated by GRIDGEN\n"); + xprintf("c seed %d\n", seed_original); + xprintf("c nodes %d\n", n_node); + xprintf("c grid size %d X %d\n", n1, n2); + xprintf("c sources %d sinks %d\n", n_source, n_sink); + xprintf("c avg. degree %d\n", avg_degree); + xprintf("c supply %d\n", t_supply); + switch (arc_costs.distribution) + { case UNIFORM: + xprintf("c arc costs: UNIFORM distr. min %d max %d\n", + (int)arc_costs.parameter[0], + (int)arc_costs.parameter[1]); + break; + case EXPONENTIAL: + xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n", + (int)arc_costs.parameter[0]); + break; + default: + xassert(csa != csa); + } + switch (capacities.distribution) + { case UNIFORM: + xprintf("c arc caps : UNIFORM distr. min %d max %d\n", + (int)capacities.parameter[0], + (int)capacities.parameter[1]); + break; + case EXPONENTIAL: + xprintf("c arc caps : EXPONENTIAL distr. %d lambda %d\n", + (int)capacities.parameter[0]); + break; + default: + xassert(csa != csa); + } +skip: if (G == NULL) + xprintf("p min %d %d\n", n_node, n_arc); + else + { glp_add_vertices(G, n_node); + if (v_rhs >= 0) + { double zero = 0.0; + for (i = 1; i <= n_node; i++) + { glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); + } + } + } + /* Output "n node supply". */ + for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++) + { if (G == NULL) + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); + else + { if (v_rhs >= 0) + { double temp = (double)imb_ptr->supply; + glp_vertex *v = G->v[imb_ptr->node]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++) + { if (G == NULL) + xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); + else + { if (v_rhs >= 0) + { double temp = (double)imb_ptr->supply; + glp_vertex *v = G->v[imb_ptr->node]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Output "a from to lowcap=0 hicap cost". */ + for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++) + { if (G == NULL) + xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to, + arc_ptr->u, arc_ptr->cost); + else + { glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to); + if (a_cap >= 0) + { double temp = (double)arc_ptr->u; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)arc_ptr->cost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + } + return; +} + +static double randy(struct csa *csa) +{ /* Returns a random number between 0.0 and 1.0. + See Ward Cheney & David Kincaid, "Numerical Mathematics and + Computing," 2Ed, pp. 335. */ + seed = 16807 * seed % 2147483647; + if (seed < 0) seed = - seed; + return seed * 4.6566128752459e-10; +} + +static void select_source_sinks(struct csa *csa) +{ /* Randomly select the source nodes and sink nodes. */ + int i, *int_ptr; + int *temp_list; /* a temporary list of nodes */ + struct imbalance *ptr; + double ab[2]; /* parameter for random number generator */ + ab[0] = 0.9; + ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the + supernode cannot be selected */ + temp_list = xcalloc(n_node, sizeof(int)); + for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++) + *int_ptr = 0; + /* Select the source nodes. */ + for (i = 0, ptr = source_list; i < n_source; i++, ptr++) + { ptr->node = uniform(csa, ab); + if (temp_list[ptr->node] == 1) /* check for duplicates */ + { ptr--; + i--; + } + else + temp_list[ptr->node] = 1; + } + /* Select the sink nodes. */ + for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++) + { ptr->node = uniform(csa, ab); + if (temp_list[ptr->node] == 1) + { ptr--; + i--; + } + else + temp_list[ptr->node] = 1; + } + xfree(temp_list); + return; +} + +int uniform(struct csa *csa, double a[2]) +{ /* Generates an integer uniformly selected from [a[0],a[1]]. */ + return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5); +} + +/**********************************************************************/ + +#if 0 +int main(void) +{ int parm[1+14]; + double temp; + scanf("%d", &parm[1]); + scanf("%d", &parm[2]); + scanf("%d", &parm[3]); + scanf("%d", &parm[4]); + scanf("%d", &parm[5]); + scanf("%d", &parm[6]); + scanf("%d", &parm[7]); + scanf("%d", &parm[8]); + scanf("%d", &parm[9]); + if (parm[9] == 1) + { scanf("%d", &parm[10]); + scanf("%d", &parm[11]); + } + else + { scanf("%le", &temp); + parm[10] = (int)(100.0 * temp + .5); + parm[11] = 0; + } + scanf("%d", &parm[12]); + if (parm[12] == 1) + { scanf("%d", &parm[13]); + scanf("%d", &parm[14]); + } + else + { scanf("%le", &temp); + parm[13] = (int)(100.0 * temp + .5); + parm[14] = 0; + } + glp_gridgen(NULL, 0, 0, 0, parm); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/intfeas1.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/intfeas1.c new file mode 100644 index 000000000..430643517 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/intfeas1.c @@ -0,0 +1,267 @@ +/* intfeas1.c (solve integer feasibility problem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2011-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound) +{ /* solve integer feasibility problem */ + NPP *npp = NULL; + glp_prob *mip = NULL; + int *obj_ind = NULL; + double *obj_val = NULL; + int obj_row = 0; + int i, j, k, obj_len, temp, ret; +#if 0 /* 04/IV-2016 */ + /* check the problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_intfeas1: P = %p; invalid problem object\n", + P); +#endif + if (P->tree != NULL) + xerror("glp_intfeas1: operation not allowed\n"); + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; + /* check columns (variables) */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; +#if 0 /* binarization is not yet implemented */ + if (!(col->kind == GLP_IV || col->type == GLP_FX)) + { xprintf("glp_intfeas1: column %d: non-integer non-fixed var" + "iable not allowed\n", j); +#else + if (!((col->kind == GLP_IV && col->lb == 0.0 && col->ub == 1.0) + || col->type == GLP_FX)) + { xprintf("glp_intfeas1: column %d: non-binary non-fixed vari" + "able not allowed\n", j); +#endif + ret = GLP_EDATA; + goto done; + } + temp = (int)col->lb; + if ((double)temp != col->lb) + { if (col->type == GLP_FX) + xprintf("glp_intfeas1: column %d: fixed value %g is non-" + "integer or out of range\n", j, col->lb); + else + xprintf("glp_intfeas1: column %d: lower bound %g is non-" + "integer or out of range\n", j, col->lb); + ret = GLP_EDATA; + goto done; + } + temp = (int)col->ub; + if ((double)temp != col->ub) + { xprintf("glp_intfeas1: column %d: upper bound %g is non-int" + "eger or out of range\n", j, col->ub); + ret = GLP_EDATA; + goto done; + } + if (col->type == GLP_DB && col->lb > col->ub) + { xprintf("glp_intfeas1: column %d: lower bound %g is greater" + " than upper bound %g\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* check rows (constraints) */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + GLPAIJ *aij; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { temp = (int)aij->val; + if ((double)temp != aij->val) + { xprintf("glp_intfeas1: row = %d, column %d: constraint c" + "oefficient %g is non-integer or out of range\n", + i, aij->col->j, aij->val); + ret = GLP_EDATA; + goto done; + } + } + temp = (int)row->lb; + if ((double)temp != row->lb) + { if (row->type == GLP_FX) + xprintf("glp_intfeas1: row = %d: fixed value %g is non-i" + "nteger or out of range\n", i, row->lb); + else + xprintf("glp_intfeas1: row = %d: lower bound %g is non-i" + "nteger or out of range\n", i, row->lb); + ret = GLP_EDATA; + goto done; + } + temp = (int)row->ub; + if ((double)temp != row->ub) + { xprintf("glp_intfeas1: row = %d: upper bound %g is non-inte" + "ger or out of range\n", i, row->ub); + ret = GLP_EDATA; + goto done; + } + if (row->type == GLP_DB && row->lb > row->ub) + { xprintf("glp_intfeas1: row %d: lower bound %g is greater th" + "an upper bound %g\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* check the objective function */ +#if 1 /* 08/I-2017 by cmatraki & mao */ + if (!use_bound) + { /* skip check if no obj. bound is specified */ + goto skip; + } +#endif + temp = (int)P->c0; + if ((double)temp != P->c0) + { xprintf("glp_intfeas1: objective constant term %g is non-integ" + "er or out of range\n", P->c0); + ret = GLP_EDATA; + goto done; + } + for (j = 1; j <= P->n; j++) + { temp = (int)P->col[j]->coef; + if ((double)temp != P->col[j]->coef) + { xprintf("glp_intfeas1: column %d: objective coefficient is " + "non-integer or out of range\n", j, P->col[j]->coef); + ret = GLP_EDATA; + goto done; + } + } +#if 1 /* 08/I-2017 by cmatraki & mao */ +skip: ; +#endif + /* save the objective function and set it to zero */ + obj_ind = xcalloc(1+P->n, sizeof(int)); + obj_val = xcalloc(1+P->n, sizeof(double)); + obj_len = 0; + obj_ind[0] = 0; + obj_val[0] = P->c0; + P->c0 = 0.0; + for (j = 1; j <= P->n; j++) + { if (P->col[j]->coef != 0.0) + { obj_len++; + obj_ind[obj_len] = j; + obj_val[obj_len] = P->col[j]->coef; + P->col[j]->coef = 0.0; + } + } + /* add inequality to bound the objective function, if required */ + if (!use_bound) + xprintf("Will search for ANY feasible solution\n"); + else + { xprintf("Will search only for solution not worse than %d\n", + obj_bound); + obj_row = glp_add_rows(P, 1); + glp_set_mat_row(P, obj_row, obj_len, obj_ind, obj_val); + if (P->dir == GLP_MIN) + glp_set_row_bnds(P, obj_row, + GLP_UP, 0.0, (double)obj_bound - obj_val[0]); + else if (P->dir == GLP_MAX) + glp_set_row_bnds(P, obj_row, + GLP_LO, (double)obj_bound - obj_val[0], 0.0); + else + xassert(P != P); + } + /* create preprocessor workspace */ + xprintf("Translating to CNF-SAT...\n"); + xprintf("Original problem has %d row%s, %d column%s, and %d non-z" + "ero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : + "s", P->nnz, P->nnz == 1 ? "" : "s"); + npp = npp_create_wksp(); + /* load the original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); + /* perform translation to SAT-CNF problem instance */ + ret = npp_sat_encode_prob(npp); + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); + else if (ret == GLP_ERANGE) + xprintf("glp_intfeas1: translation to SAT-CNF failed because o" + "f integer overflow\n"); + else + xassert(ret != ret); + if (ret != 0) + goto done; + /* build SAT-CNF problem instance and try to solve it */ + mip = glp_create_prob(); + npp_build_prob(npp, mip); + ret = glp_minisat1(mip); + /* only integer feasible solution can be postprocessed */ + if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) + { P->mip_stat = mip->mip_stat; + goto done; + } + /* postprocess the solution found */ + npp_postprocess(npp, mip); + /* the transformed problem is no longer needed */ + glp_delete_prob(mip), mip = NULL; + /* store solution to the original problem object */ + npp_unload_sol(npp, P); + /* change the solution status to 'integer feasible' */ + P->mip_stat = GLP_FEAS; + /* check integer feasibility */ + for (i = 1; i <= P->m; i++) + { GLPROW *row; + GLPAIJ *aij; + double sum; + row = P->row[i]; + sum = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * aij->col->mipx; + xassert(sum == row->mipx); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xassert(sum >= row->lb); + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + xassert(sum <= row->ub); + } + /* compute value of the original objective function */ + P->mip_obj = obj_val[0]; + for (k = 1; k <= obj_len; k++) + P->mip_obj += obj_val[k] * P->col[obj_ind[k]]->mipx; + xprintf("Objective value = %17.9e\n", P->mip_obj); +done: /* delete the transformed problem, if it exists */ + if (mip != NULL) + glp_delete_prob(mip); + /* delete the preprocessor workspace, if it exists */ + if (npp != NULL) + npp_delete_wksp(npp); + /* remove inequality used to bound the objective function */ + if (obj_row > 0) + { int ind[1+1]; + ind[1] = obj_row; + glp_del_rows(P, 1, ind); + } + /* restore the original objective function */ + if (obj_ind != NULL) + { P->c0 = obj_val[0]; + for (k = 1; k <= obj_len; k++) + P->col[obj_ind[k]]->coef = obj_val[k]; + xfree(obj_ind); + xfree(obj_val); + } + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/maxffalg.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/maxffalg.c new file mode 100644 index 000000000..0f3f9b041 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/maxffalg.c @@ -0,0 +1,130 @@ +/* maxffalg.c (find maximal flow with Ford-Fulkerson algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ffalg.h" +#include "glpk.h" + +int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, + double *sol, int a_x, int v_cut) +{ /* find maximal flow with Ford-Fulkerson algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, flag, *tail, *head, *cap, *x, ret; + char *cut; + double temp; + if (!(1 <= s && s <= G->nv)) + xerror("glp_maxflow_ffalg: s = %d; source node number out of r" + "ange\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_maxflow_ffalg: t = %d: sink node number out of ran" + "ge\n", t); + if (s == t) + xerror("glp_maxflow_ffalg: s = t = %d; source and sink nodes m" + "ust be distinct\n", s); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_maxflow_ffalg: a_cap = %d; invalid offset\n", + a_cap); + if (v_cut >= 0 && v_cut > G->v_size - (int)sizeof(int)) + xerror("glp_maxflow_ffalg: v_cut = %d; invalid offset\n", + v_cut); + /* allocate working arrays */ + nv = G->nv; + na = G->na; + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + if (v_cut < 0) + cut = NULL; + else + cut = xcalloc(1+nv, sizeof(char)); + /* copy the flow network */ + k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + if (tail[k] == head[k]) + { ret = GLP_EDATA; + goto done; + } + if (a_cap >= 0) + memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); + else + temp = 1.0; + if (!(0.0 <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cap[k] = (int)temp; + } + } + xassert(k == na); + /* find maximal flow in the flow network */ + ffalg(nv, na, tail, head, s, t, cap, x, cut); + ret = 0; + /* store solution components */ + /* (objective function = total flow through the network) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + { if (tail[k] == s) + temp += (double)x[k]; + else if (head[k] == s) + temp -= (double)x[k]; + } + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { temp = (double)x[++k]; + memcpy((char *)a->data + a_x, &temp, sizeof(double)); + } + } + } + /* (node flags) */ + if (v_cut >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + flag = cut[i]; + memcpy((char *)v->data + v_cut, &flag, sizeof(int)); + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(cap); + xfree(x); + if (cut != NULL) xfree(cut); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/maxflp.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/maxflp.c new file mode 100644 index 000000000..1135b78cb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/maxflp.c @@ -0,0 +1,114 @@ +/* maxflp.c (convert maximum flow problem to LP) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_maxflow_lp - convert maximum flow problem to LP +* +* SYNOPSIS +* +* void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, +* int t, int a_cap); +* +* DESCRIPTION +* +* The routine glp_maxflow_lp builds an LP problem, which corresponds +* to the maximum flow problem on the specified network G. */ + +void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, + int t, int a_cap) +{ glp_vertex *v; + glp_arc *a; + int i, j, type, ind[1+2]; + double cap, val[1+2]; + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_maxflow_lp: names = %d; invalid parameter\n", + names); + if (!(1 <= s && s <= G->nv)) + xerror("glp_maxflow_lp: s = %d; source node number out of rang" + "e\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_maxflow_lp: t = %d: sink node number out of range " + "\n", t); + if (s == t) + xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must" + " be distinct\n", s); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap); + glp_erase_prob(lp); + if (names) glp_set_prob_name(lp, G->name); + glp_set_obj_dir(lp, GLP_MAX); + glp_add_rows(lp, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(lp, i, v->name); + if (i == s) + type = GLP_LO; + else if (i == t) + type = GLP_UP; + else + type = GLP_FX; + glp_set_row_bnds(lp, i, type, 0.0, 0.0); + } + if (G->na > 0) glp_add_cols(lp, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(lp, j, name); + } + if (a->tail->i != a->head->i) + { ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = -1.0; + glp_set_mat_col(lp, j, 2, ind, val); + } + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (cap == DBL_MAX) + type = GLP_LO; + else if (cap != 0.0) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp, j, type, 0.0, cap); + if (a->tail->i == s) + glp_set_obj_coef(lp, j, +1.0); + else if (a->head->i == s) + glp_set_obj_coef(lp, j, -1.0); + } + } + xassert(j == G->na); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/mcflp.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcflp.c new file mode 100644 index 000000000..5cd240602 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcflp.c @@ -0,0 +1,114 @@ +/* mcflp.c (convert minimum cost flow problem to LP) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_mincost_lp - convert minimum cost flow problem to LP +* +* SYNOPSIS +* +* void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, +* int v_rhs, int a_low, int a_cap, int a_cost); +* +* DESCRIPTION +* +* The routine glp_mincost_lp builds an LP problem, which corresponds +* to the minimum cost flow problem on the specified network G. */ + +void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost) +{ glp_vertex *v; + glp_arc *a; + int i, j, type, ind[1+2]; + double rhs, low, cap, cost, val[1+2]; + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_mincost_lp: names = %d; invalid parameter\n", + names); + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost) + ; + glp_erase_prob(lp); + if (names) glp_set_prob_name(lp, G->name); + if (G->nv > 0) glp_add_rows(lp, G->nv); + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (names) glp_set_row_name(lp, i, v->name); + if (v_rhs >= 0) + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + else + rhs = 0.0; + glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs); + } + if (G->na > 0) glp_add_cols(lp, G->na); + for (i = 1, j = 0; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { j++; + if (names) + { char name[50+1]; + sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); + xassert(strlen(name) < sizeof(name)); + glp_set_col_name(lp, j, name); + } + if (a->tail->i != a->head->i) + { ind[1] = a->tail->i, val[1] = +1.0; + ind[2] = a->head->i, val[2] = -1.0; + glp_set_mat_col(lp, j, 2, ind, val); + } + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (cap == DBL_MAX) + type = GLP_LO; + else if (low != cap) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(lp, j, type, low, cap); + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + glp_set_obj_coef(lp, j, cost); + } + } + xassert(j == G->na); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfokalg.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfokalg.c new file mode 100644 index 000000000..786dc71bc --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfokalg.c @@ -0,0 +1,221 @@ +/* mcfokalg.c (find minimum-cost flow with out-of-kilter algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "okalg.h" + +int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi) +{ /* find minimum-cost flow with out-of-kilter algorithm */ + glp_vertex *v; + glp_arc *a; + int nv, na, i, k, s, t, *tail, *head, *low, *cap, *cost, *x, *pi, + ret; + double sum, temp; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: a_x = %d; invalid offset\n", a_x); + if (v_pi >= 0 && v_pi > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_okalg: v_pi = %d; invalid offset\n", v_pi); + /* s is artificial source node */ + s = G->nv + 1; + /* t is artificial sink node */ + t = s + 1; + /* nv is the total number of nodes in the resulting network */ + nv = t; + /* na is the total number of arcs in the resulting network */ + na = G->na + 1; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_rhs >= 0) + memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); + else + temp = 0.0; + if (temp != 0.0) na++; + } + /* allocate working arrays */ + tail = xcalloc(1+na, sizeof(int)); + head = xcalloc(1+na, sizeof(int)); + low = xcalloc(1+na, sizeof(int)); + cap = xcalloc(1+na, sizeof(int)); + cost = xcalloc(1+na, sizeof(int)); + x = xcalloc(1+na, sizeof(int)); + pi = xcalloc(1+nv, sizeof(int)); + /* construct the resulting network */ + k = 0; + /* (original arcs) */ + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + tail[k] = a->tail->i; + head[k] = a->head->i; + if (tail[k] == head[k]) + { ret = GLP_EDATA; + goto done; + } + if (a_low >= 0) + memcpy(&temp, (char *)a->data + a_low, sizeof(double)); + else + temp = 0.0; + if (!(0.0 <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + low[k] = (int)temp; + if (a_cap >= 0) + memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); + else + temp = 1.0; + if (!((double)low[k] <= temp && temp <= (double)INT_MAX && + temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cap[k] = (int)temp; + if (a_cost >= 0) + memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); + else + temp = 0.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + cost[k] = (int)temp; + } + } + /* (artificial arcs) */ + sum = 0.0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_rhs >= 0) + memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); + else + temp = 0.0; + if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) + { ret = GLP_EDATA; + goto done; + } + if (temp > 0.0) + { /* artificial arc from s to original source i */ + k++; + tail[k] = s; + head[k] = i; + low[k] = cap[k] = (int)(+temp); /* supply */ + cost[k] = 0; + sum += (double)temp; + } + else if (temp < 0.0) + { /* artificial arc from original sink i to t */ + k++; + tail[k] = i; + head[k] = t; + low[k] = cap[k] = (int)(-temp); /* demand */ + cost[k] = 0; + } + } + /* (feedback arc from t to s) */ + k++; + xassert(k == na); + tail[k] = t; + head[k] = s; + if (sum > (double)INT_MAX) + { ret = GLP_EDATA; + goto done; + } + low[k] = cap[k] = (int)sum; /* total supply/demand */ + cost[k] = 0; + /* find minimal-cost circulation in the resulting network */ + ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); + switch (ret) + { case 0: + /* optimal circulation found */ + ret = 0; + break; + case 1: + /* no feasible circulation exists */ + ret = GLP_ENOPFS; + break; + case 2: + /* integer overflow occured */ + ret = GLP_ERANGE; + goto done; + case 3: + /* optimality test failed (logic error) */ + ret = GLP_EFAIL; + goto done; + default: + xassert(ret != ret); + } + /* store solution components */ + /* (objective function = the total cost) */ + if (sol != NULL) + { temp = 0.0; + for (k = 1; k <= na; k++) + temp += (double)cost[k] * (double)x[k]; + *sol = temp; + } + /* (arc flows) */ + if (a_x >= 0) + { k = 0; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { temp = (double)x[++k]; + memcpy((char *)a->data + a_x, &temp, sizeof(double)); + } + } + } + /* (node potentials = Lagrange multipliers) */ + if (v_pi >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + temp = - (double)pi[i]; + memcpy((char *)v->data + v_pi, &temp, sizeof(double)); + } + } +done: /* free working arrays */ + xfree(tail); + xfree(head); + xfree(low); + xfree(cap); + xfree(cost); + xfree(x); + xfree(pi); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfrelax.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfrelax.c new file mode 100644 index 000000000..9b34949a1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/mcfrelax.c @@ -0,0 +1,251 @@ +/* mcfrelax.c (find minimum-cost flow with RELAX-IV) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "relax4.h" + +static int overflow(int u, int v) +{ /* check for integer overflow on computing u + v */ + if (u > 0 && v > 0 && u + v < 0) return 1; + if (u < 0 && v < 0 && u + v > 0) return 1; + return 0; +} + +int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc) +{ /* find minimum-cost flow with Bertsekas-Tseng relaxation method + (RELAX-IV) */ + glp_vertex *v; + glp_arc *a; + struct relax4_csa csa; + int i, k, large, n, na, ret; + double cap, cost, low, rc, rhs, sum, x; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_cost = %d; invalid offset\n", + a_cost); + if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_x = %d; invalid offset\n", + a_x); + if (a_rc >= 0 && a_rc > G->a_size - (int)sizeof(double)) + xerror("glp_mincost_relax4: a_rc = %d; invalid offset\n", + a_rc); + csa.n = n = G->nv; /* number of nodes */ + csa.na = na = G->na; /* number of arcs */ + csa.large = large = INT_MAX / 4; + csa.repeat = 0; + csa.crash = crash; + /* allocate working arrays */ + csa.startn = xcalloc(1+na, sizeof(int)); + csa.endn = xcalloc(1+na, sizeof(int)); + csa.fou = xcalloc(1+n, sizeof(int)); + csa.nxtou = xcalloc(1+na, sizeof(int)); + csa.fin = xcalloc(1+n, sizeof(int)); + csa.nxtin = xcalloc(1+na, sizeof(int)); + csa.rc = xcalloc(1+na, sizeof(int)); + csa.u = xcalloc(1+na, sizeof(int)); + csa.dfct = xcalloc(1+n, sizeof(int)); + csa.x = xcalloc(1+na, sizeof(int)); + csa.label = xcalloc(1+n, sizeof(int)); + csa.prdcsr = xcalloc(1+n, sizeof(int)); + csa.save = xcalloc(1+na, sizeof(int)); + csa.tfstou = xcalloc(1+n, sizeof(int)); + csa.tnxtou = xcalloc(1+na, sizeof(int)); + csa.tfstin = xcalloc(1+n, sizeof(int)); + csa.tnxtin = xcalloc(1+na, sizeof(int)); + csa.nxtqueue = xcalloc(1+n, sizeof(int)); + csa.scan = xcalloc(1+n, sizeof(char)); + csa.mark = xcalloc(1+n, sizeof(char)); + if (crash) + { csa.extend_arc = xcalloc(1+n, sizeof(int)); + csa.sb_level = xcalloc(1+n, sizeof(int)); + csa.sb_arc = xcalloc(1+n, sizeof(int)); + } + else + { csa.extend_arc = NULL; + csa.sb_level = NULL; + csa.sb_arc = NULL; + } + /* scan nodes */ + for (i = 1; i <= n; i++) + { v = G->v[i]; + /* get supply at i-th node */ + if (v_rhs >= 0) + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + else + rhs = 0.0; + if (!(fabs(rhs) <= (double)large && rhs == floor(rhs))) + { ret = GLP_EDATA; + goto done; + } + /* set demand at i-th node */ + csa.dfct[i] = -(int)rhs; + } + /* scan arcs */ + k = 0; + for (i = 1; i <= n; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + /* set endpoints of k-th arc */ + if (a->tail->i == a->head->i) + { /* self-loops not allowed */ + ret = GLP_EDATA; + goto done; + } + csa.startn[k] = a->tail->i; + csa.endn[k] = a->head->i; + /* set per-unit cost for k-th arc flow */ + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + if (!(fabs(cost) <= (double)large && cost == floor(cost))) + { ret = GLP_EDATA; + goto done; + } + csa.rc[k] = (int)cost; + /* get lower bound for k-th arc flow */ + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (!(0.0 <= low && low <= (double)large && + low == floor(low))) + { ret = GLP_EDATA; + goto done; + } + /* get upper bound for k-th arc flow */ + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (!(low <= cap && cap <= (double)large && + cap == floor(cap))) + { ret = GLP_EDATA; + goto done; + } + /* substitute x = x' + low, where 0 <= x' <= cap - low */ + csa.u[k] = (int)(cap - low); + /* correct demands at endpoints of k-th arc */ + if (overflow(csa.dfct[a->tail->i], +low)) + { ret = GLP_ERANGE; + goto done; + } +#if 0 /* 29/IX-2017 */ + csa.dfct[a->tail->i] += low; +#else + csa.dfct[a->tail->i] += (int)low; +#endif + if (overflow(csa.dfct[a->head->i], -low)) + { ret = GLP_ERANGE; + goto done; + } +#if 0 /* 29/IX-2017 */ + csa.dfct[a->head->i] -= low; +#else + csa.dfct[a->head->i] -= (int)low; +#endif + } + } + /* construct linked list for network topology */ + relax4_inidat(&csa); + /* find minimum-cost flow */ + ret = relax4(&csa); + if (ret != 0) + { /* problem is found to be infeasible */ + xassert(1 <= ret && ret <= 8); + ret = GLP_ENOPFS; + goto done; + } + /* store solution */ + sum = 0.0; + k = 0; + for (i = 1; i <= n; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { k++; + /* get lower bound for k-th arc flow */ + if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + /* store original flow x = x' + low thru k-th arc */ + x = (double)csa.x[k] + low; + if (a_x >= 0) + memcpy((char *)a->data + a_x, &x, sizeof(double)); + /* store reduced cost for k-th arc flow */ + rc = (double)csa.rc[k]; + if (a_rc >= 0) + memcpy((char *)a->data + a_rc, &rc, sizeof(double)); + /* get per-unit cost for k-th arc flow */ + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + /* compute the total cost */ + sum += cost * x; + } + } + /* store the total cost */ + if (sol != NULL) + *sol = sum; +done: /* free working arrays */ + xfree(csa.startn); + xfree(csa.endn); + xfree(csa.fou); + xfree(csa.nxtou); + xfree(csa.fin); + xfree(csa.nxtin); + xfree(csa.rc); + xfree(csa.u); + xfree(csa.dfct); + xfree(csa.x); + xfree(csa.label); + xfree(csa.prdcsr); + xfree(csa.save); + xfree(csa.tfstou); + xfree(csa.tnxtou); + xfree(csa.tfstin); + xfree(csa.tnxtin); + xfree(csa.nxtqueue); + xfree(csa.scan); + xfree(csa.mark); + if (crash) + { xfree(csa.extend_arc); + xfree(csa.sb_level); + xfree(csa.sb_arc); + } + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/minisat1.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/minisat1.c new file mode 100644 index 000000000..a669c487e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/minisat1.c @@ -0,0 +1,161 @@ +/* minisat1.c (driver to MiniSat solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2011-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "minisat.h" +#include "prob.h" + +int glp_minisat1(glp_prob *P) +{ /* solve CNF-SAT problem with MiniSat solver */ + solver *s; + GLPAIJ *aij; + int i, j, len, ret, *ind; + double sum; +#if 0 /* 04/IV-2016 */ + /* check problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_minisat1: P = %p; invalid problem object\n", + P); +#endif + if (P->tree != NULL) + xerror("glp_minisat1: operation not allowed\n"); + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; + /* check that problem object encodes CNF-SAT instance */ + if (glp_check_cnfsat(P) != 0) + { xprintf("glp_minisat1: problem object does not encode CNF-SAT " + "instance\n"); + ret = GLP_EDATA; + goto done; + } +#if 0 /* 08/I-2017 by cmatraki */ +#if 1 /* 07/XI-2015 */ + if (sizeof(void *) != sizeof(int)) + { xprintf("glp_minisat1: sorry, MiniSat solver is not supported " + "on 64-bit platforms\n"); + ret = GLP_EFAIL; + goto done; + } +#endif +#else + if (sizeof(void *) != sizeof(size_t)) + { xprintf("glp_minisat1: sorry, MiniSat solver is not supported " + "on this platform\n"); + ret = GLP_EFAIL; + goto done; + } +#endif + /* solve CNF-SAT problem */ + xprintf("Solving CNF-SAT problem...\n"); + xprintf("Instance has %d variable%s, %d clause%s, and %d literal%" + "s\n", P->n, P->n == 1 ? "" : "s", P->m, P->m == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + /* if CNF-SAT has no clauses, it is satisfiable */ + if (P->m == 0) + { P->mip_stat = GLP_OPT; + for (j = 1; j <= P->n; j++) + P->col[j]->mipx = 0.0; + goto fini; + } + /* if CNF-SAT has an empty clause, it is unsatisfiable */ + for (i = 1; i <= P->m; i++) + { if (P->row[i]->ptr == NULL) + { P->mip_stat = GLP_NOFEAS; + goto fini; + } + } + /* prepare input data for the solver */ + s = solver_new(); + solver_setnvars(s, P->n); + ind = xcalloc(1+P->n, sizeof(int)); + for (i = 1; i <= P->m; i++) + { len = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { ind[++len] = toLit(aij->col->j-1); + if (aij->val < 0.0) + ind[len] = lit_neg(ind[len]); + } + xassert(len > 0); +#if 0 /* 08/I-2017 by cmatraki */ + xassert(solver_addclause(s, &ind[1], &ind[1+len])); +#else + if (!solver_addclause(s, &ind[1], &ind[1+len])) + { /* found trivial conflict */ + xfree(ind); + solver_delete(s); + P->mip_stat = GLP_NOFEAS; + goto fini; + } +#endif + } + xfree(ind); + /* call the solver */ + s->verbosity = 1; + if (solver_solve(s, 0, 0)) + { /* instance is reported as satisfiable */ + P->mip_stat = GLP_OPT; + /* copy solution to the problem object */ + xassert(s->model.size == P->n); + for (j = 1; j <= P->n; j++) + { P->col[j]->mipx = + s->model.ptr[j-1] == l_True ? 1.0 : 0.0; + } + /* compute row values */ + for (i = 1; i <= P->m; i++) + { sum = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * aij->col->mipx; + P->row[i]->mipx = sum; + } + /* check integer feasibility */ + for (i = 1; i <= P->m; i++) + { if (P->row[i]->mipx < P->row[i]->lb) + { /* solution is wrong */ + P->mip_stat = GLP_UNDEF; + break; + } + } + } + else + { /* instance is reported as unsatisfiable */ + P->mip_stat = GLP_NOFEAS; + } + solver_delete(s); +fini: /* report the instance status */ + if (P->mip_stat == GLP_OPT) + { xprintf("SATISFIABLE\n"); + ret = 0; + } + else if (P->mip_stat == GLP_NOFEAS) + { xprintf("UNSATISFIABLE\n"); + ret = 0; + } + else + { xprintf("glp_minisat1: solver failed\n"); + ret = GLP_EFAIL; + } +done: return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/mpl.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/mpl.c new file mode 100644 index 000000000..cfa6f75b6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/mpl.c @@ -0,0 +1,269 @@ +/* mpl.c (processing model in GNU MathProg language) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" +#include "prob.h" + +glp_tran *glp_mpl_alloc_wksp(void) +{ /* allocate the MathProg translator workspace */ + glp_tran *tran; + tran = mpl_initialize(); + return tran; +} + +void glp_mpl_init_rand(glp_tran *tran, int seed) +{ /* initialize pseudo-random number generator */ + if (tran->phase != 0) + xerror("glp_mpl_init_rand: invalid call sequence\n"); + rng_init_rand(tran->rand, seed); + return; +} + +int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip) +{ /* read and translate model section */ + int ret; + if (tran->phase != 0) + xerror("glp_mpl_read_model: invalid call sequence\n"); + ret = mpl_read_model(tran, (char *)fname, skip); + if (ret == 1 || ret == 2) + ret = 0; + else if (ret == 4) + ret = 1; + else + xassert(ret != ret); + return ret; +} + +int glp_mpl_read_data(glp_tran *tran, const char *fname) +{ /* read and translate data section */ + int ret; + if (!(tran->phase == 1 || tran->phase == 2)) + xerror("glp_mpl_read_data: invalid call sequence\n"); + ret = mpl_read_data(tran, (char *)fname); + if (ret == 2) + ret = 0; + else if (ret == 4) + ret = 1; + else + xassert(ret != ret); + return ret; +} + +int glp_mpl_generate(glp_tran *tran, const char *fname) +{ /* generate the model */ + int ret; + if (!(tran->phase == 1 || tran->phase == 2)) + xerror("glp_mpl_generate: invalid call sequence\n"); + ret = mpl_generate(tran, (char *)fname); + if (ret == 3) + ret = 0; + else if (ret == 4) + ret = 1; + return ret; +} + +void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob) +{ /* build LP/MIP problem instance from the model */ + int m, n, i, j, t, kind, type, len, *ind; + double lb, ub, *val; + if (tran->phase != 3) + xerror("glp_mpl_build_prob: invalid call sequence\n"); + /* erase the problem object */ + glp_erase_prob(prob); + /* set problem name */ + glp_set_prob_name(prob, mpl_get_prob_name(tran)); + /* build rows (constraints) */ + m = mpl_get_num_rows(tran); + if (m > 0) + glp_add_rows(prob, m); + for (i = 1; i <= m; i++) + { /* set row name */ + glp_set_row_name(prob, i, mpl_get_row_name(tran, i)); + /* set row bounds */ + type = mpl_get_row_bnds(tran, i, &lb, &ub); + switch (type) + { case MPL_FR: type = GLP_FR; break; + case MPL_LO: type = GLP_LO; break; + case MPL_UP: type = GLP_UP; break; + case MPL_DB: type = GLP_DB; break; + case MPL_FX: type = GLP_FX; break; + default: xassert(type != type); + } + if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) + { type = GLP_FX; + if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; + } + glp_set_row_bnds(prob, i, type, lb, ub); + /* warn about non-zero constant term */ + if (mpl_get_row_c0(tran, i) != 0.0) + xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig" + "nored\n", + mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i)); + } + /* build columns (variables) */ + n = mpl_get_num_cols(tran); + if (n > 0) + glp_add_cols(prob, n); + for (j = 1; j <= n; j++) + { /* set column name */ + glp_set_col_name(prob, j, mpl_get_col_name(tran, j)); + /* set column kind */ + kind = mpl_get_col_kind(tran, j); + switch (kind) + { case MPL_NUM: + break; + case MPL_INT: + case MPL_BIN: + glp_set_col_kind(prob, j, GLP_IV); + break; + default: + xassert(kind != kind); + } + /* set column bounds */ + type = mpl_get_col_bnds(tran, j, &lb, &ub); + switch (type) + { case MPL_FR: type = GLP_FR; break; + case MPL_LO: type = GLP_LO; break; + case MPL_UP: type = GLP_UP; break; + case MPL_DB: type = GLP_DB; break; + case MPL_FX: type = GLP_FX; break; + default: xassert(type != type); + } + if (kind == MPL_BIN) + { if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0; + if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0; + type = GLP_DB; + } + if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) + { type = GLP_FX; + if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; + } + glp_set_col_bnds(prob, j, type, lb, ub); + } + /* load the constraint matrix */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = 1; i <= m; i++) + { len = mpl_get_mat_row(tran, i, ind, val); + glp_set_mat_row(prob, i, len, ind, val); + } + /* build objective function (the first objective is used) */ + for (i = 1; i <= m; i++) + { kind = mpl_get_row_kind(tran, i); + if (kind == MPL_MIN || kind == MPL_MAX) + { /* set objective name */ + glp_set_obj_name(prob, mpl_get_row_name(tran, i)); + /* set optimization direction */ + glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX); + /* set constant term */ + glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i)); + /* set objective coefficients */ + len = mpl_get_mat_row(tran, i, ind, val); + for (t = 1; t <= len; t++) + glp_set_obj_coef(prob, ind[t], val[t]); + break; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + return; +} + +int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol) +{ /* postsolve the model */ + int i, j, m, n, stat, ret; + double prim, dual; + if (!(tran->phase == 3 && !tran->flag_p)) + xerror("glp_mpl_postsolve: invalid call sequence\n"); + if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) + xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n", + sol); + m = mpl_get_num_rows(tran); + n = mpl_get_num_cols(tran); + if (!(m == glp_get_num_rows(prob) && + n == glp_get_num_cols(prob))) + xerror("glp_mpl_postsolve: wrong problem object\n"); + if (!mpl_has_solve_stmt(tran)) + { ret = 0; + goto done; + } + for (i = 1; i <= m; i++) + { if (sol == GLP_SOL) + { stat = glp_get_row_stat(prob, i); + prim = glp_get_row_prim(prob, i); + dual = glp_get_row_dual(prob, i); + } + else if (sol == GLP_IPT) + { stat = 0; + prim = glp_ipt_row_prim(prob, i); + dual = glp_ipt_row_dual(prob, i); + } + else if (sol == GLP_MIP) + { stat = 0; + prim = glp_mip_row_val(prob, i); + dual = 0.0; + } + else + xassert(sol != sol); + if (fabs(prim) < 1e-9) prim = 0.0; + if (fabs(dual) < 1e-9) dual = 0.0; + mpl_put_row_soln(tran, i, stat, prim, dual); + } + for (j = 1; j <= n; j++) + { if (sol == GLP_SOL) + { stat = glp_get_col_stat(prob, j); + prim = glp_get_col_prim(prob, j); + dual = glp_get_col_dual(prob, j); + } + else if (sol == GLP_IPT) + { stat = 0; + prim = glp_ipt_col_prim(prob, j); + dual = glp_ipt_col_dual(prob, j); + } + else if (sol == GLP_MIP) + { stat = 0; + prim = glp_mip_col_val(prob, j); + dual = 0.0; + } + else + xassert(sol != sol); + if (fabs(prim) < 1e-9) prim = 0.0; + if (fabs(dual) < 1e-9) dual = 0.0; + mpl_put_col_soln(tran, j, stat, prim, dual); + } + ret = mpl_postsolve(tran); + if (ret == 3) + ret = 0; + else if (ret == 4) + ret = 1; +done: return ret; +} + +void glp_mpl_free_wksp(glp_tran *tran) +{ /* free the MathProg translator workspace */ + mpl_terminate(tran); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/mps.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/mps.c new file mode 100644 index 000000000..3bdc6db16 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/mps.c @@ -0,0 +1,1452 @@ +/* mps.c (MPS format routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_init_mpscp - initialize MPS format control parameters +* +* SYNOPSIS +* +* void glp_init_mpscp(glp_mpscp *parm); +* +* DESCRIPTION +* +* The routine glp_init_mpscp initializes control parameters, which are +* used by the MPS input/output routines glp_read_mps and glp_write_mps, +* with default values. +* +* Default values of the control parameters are stored in the glp_mpscp +* structure, which the parameter parm points to. */ + +void glp_init_mpscp(glp_mpscp *parm) +{ parm->blank = '\0'; + parm->obj_name = NULL; + parm->tol_mps = 1e-12; + return; +} + +static void check_parm(const char *func, const glp_mpscp *parm) +{ /* check control parameters */ + if (!(0x00 <= parm->blank && parm->blank <= 0xFF) || + !(parm->blank == '\0' || isprint(parm->blank))) + xerror("%s: blank = 0x%02X; invalid parameter\n", + func, parm->blank); + if (!(parm->obj_name == NULL || strlen(parm->obj_name) <= 255)) + xerror("%s: obj_name = \"%.12s...\"; parameter too long\n", + func, parm->obj_name); + if (!(0.0 <= parm->tol_mps && parm->tol_mps < 1.0)) + xerror("%s: tol_mps = %g; invalid parameter\n", + func, parm->tol_mps); + return; +} + +/*********************************************************************** +* NAME +* +* glp_read_mps - read problem data in MPS format +* +* SYNOPSIS +* +* int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mps reads problem data in MPS format from a +* text file. +* +* The parameter fmt specifies the version of MPS format: +* +* GLP_MPS_DECK - fixed (ancient) MPS format; +* GLP_MPS_FILE - free (modern) MPS format. +* +* The parameter parm is a pointer to the structure glp_mpscp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* read. +* +* Note that before reading data the current content of the problem +* object is completely erased with the routine glp_erase_prob. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_mps returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + int deck; + /* MPS format (0 - free, 1 - fixed) */ + const glp_mpscp *parm; + /* pointer to control parameters */ + const char *fname; + /* name of input MPS file */ + glp_file *fp; + /* stream assigned to input MPS file */ + jmp_buf jump; + /* label for go to in case of error */ + int recno; + /* current record (card) number */ + int recpos; + /* current record (card) position */ + int c; + /* current character */ + int fldno; + /* current field number */ + char field[255+1]; + /* current field content */ + int w80; + /* warning 'record must not be longer than 80 chars' issued */ + int wef; + /* warning 'extra fields detected beyond field 6' issued */ + int obj_row; + /* objective row number */ + void *work1, *work2, *work3; + /* working arrays */ +}; + +static void error(struct csa *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: ", csa->fname, csa->recno); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + longjmp(csa->jump, 1); + /* no return */ +} + +static void warning(struct csa *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->recno); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + return; +} + +static void read_char(struct csa *csa) +{ /* read next character */ + int c; + if (csa->c == '\n') + csa->recno++, csa->recpos = 0; + csa->recpos++; +read: c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + error(csa, "read error - %s\n", get_err_msg()); + else if (csa->c == '\n') + error(csa, "unexpected end of file\n"); + else + { warning(csa, "missing final end of line\n"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (csa->c == '\r') + { c = '\r'; + goto badc; + } + else if (csa->deck && c == '\r') + { csa->c = '\r'; + goto read; + } + else if (c == ' ') + ; + else if (isspace(c)) + { if (csa->deck) +badc: error(csa, "in fixed MPS format white-space character 0x%02" + "X is not allowed\n", c); + c = ' '; + } + else if (iscntrl(c)) + error(csa, "invalid control character 0x%02X\n", c); + if (csa->deck && csa->recpos == 81 && c != '\n' && csa->w80 < 1) + { warning(csa, "in fixed MPS format record must not be longer th" + "an 80 characters\n"); + csa->w80++; + } + csa->c = c; + return; +} + +static int indicator(struct csa *csa, int name) +{ /* skip comment records and read possible indicator record */ + int ret; + /* reset current field number */ + csa->fldno = 0; +loop: /* read the very first character of the next record */ + xassert(csa->c == '\n'); + read_char(csa); + if (csa->c == ' ' || csa->c == '\n') + { /* data record */ + ret = 0; + } + else if (csa->c == '*') + { /* comment record */ + while (csa->c != '\n') + read_char(csa); + goto loop; + } + else + { /* indicator record */ + int len = 0; + while (csa->c != ' ' && csa->c != '\n' && len < 12) + { csa->field[len++] = (char)csa->c; + read_char(csa); + } + csa->field[len] = '\0'; + if (!(strcmp(csa->field, "NAME") == 0 || + strcmp(csa->field, "ROWS") == 0 || + strcmp(csa->field, "COLUMNS") == 0 || + strcmp(csa->field, "RHS") == 0 || + strcmp(csa->field, "RANGES") == 0 || + strcmp(csa->field, "BOUNDS") == 0 || + strcmp(csa->field, "ENDATA") == 0)) + error(csa, "invalid indicator record\n"); + if (!name) + { while (csa->c != '\n') + read_char(csa); + } + ret = 1; + } + return ret; +} + +static void read_field(struct csa *csa) +{ /* read next field of the current data record */ + csa->fldno++; + if (csa->deck) + { /* fixed MPS format */ + int beg, end, pos; + /* determine predefined field positions */ + if (csa->fldno == 1) + beg = 2, end = 3; + else if (csa->fldno == 2) + beg = 5, end = 12; + else if (csa->fldno == 3) + beg = 15, end = 22; + else if (csa->fldno == 4) + beg = 25, end = 36; + else if (csa->fldno == 5) + beg = 40, end = 47; + else if (csa->fldno == 6) + beg = 50, end = 61; + else + xassert(csa != csa); + /* skip blanks preceding the current field */ + if (csa->c != '\n') + { pos = csa->recpos; + while (csa->recpos < beg) + { if (csa->c == ' ') + ; + else if (csa->c == '\n') + break; + else + error(csa, "in fixed MPS format positions %d-%d must " + "be blank\n", pos, beg-1); + read_char(csa); + } + } + /* skip possible comment beginning in the field 3 or 5 */ + if ((csa->fldno == 3 || csa->fldno == 5) && csa->c == '$') + { while (csa->c != '\n') + read_char(csa); + } + /* read the current field */ + for (pos = beg; pos <= end; pos++) + { if (csa->c == '\n') break; + csa->field[pos-beg] = (char)csa->c; + read_char(csa); + } + csa->field[pos-beg] = '\0'; + strtrim(csa->field); + /* skip blanks following the last field */ + if (csa->fldno == 6 && csa->c != '\n') + { while (csa->recpos <= 72) + { if (csa->c == ' ') + ; + else if (csa->c == '\n') + break; + else + error(csa, "in fixed MPS format positions 62-72 must " + "be blank\n"); + read_char(csa); + } + while (csa->c != '\n') + read_char(csa); + } + } + else + { /* free MPS format */ + int len; + /* skip blanks preceding the current field */ + while (csa->c == ' ') + read_char(csa); + /* skip possible comment */ + if (csa->c == '$') + { while (csa->c != '\n') + read_char(csa); + } + /* read the current field */ + len = 0; + while (!(csa->c == ' ' || csa->c == '\n')) + { if (len == 255) + error(csa, "length of field %d exceeds 255 characters\n", + csa->fldno++); + csa->field[len++] = (char)csa->c; + read_char(csa); + } + csa->field[len] = '\0'; + /* skip anything following the last field (any extra fields + are considered to be comments) */ + if (csa->fldno == 6) + { while (csa->c == ' ') + read_char(csa); + if (csa->c != '$' && csa->c != '\n' && csa->wef < 1) + { warning(csa, "some extra field(s) detected beyond field " + "6; field(s) ignored\n"); + csa->wef++; + } + while (csa->c != '\n') + read_char(csa); + } + } + return; +} + +static void patch_name(struct csa *csa, char *name) +{ /* process embedded blanks in symbolic name */ + int blank = csa->parm->blank; + if (blank == '\0') + { /* remove emedded blanks */ + strspx(name); + } + else + { /* replace embedded blanks by specified character */ + for (; *name != '\0'; name++) + if (*name == ' ') *name = (char)blank; + } + return; +} + +static double read_number(struct csa *csa) +{ /* read next field and convert it to floating-point number */ + double x; + char *s; + /* read next field */ + read_field(csa); + xassert(csa->fldno == 4 || csa->fldno == 6); + if (csa->field[0] == '\0') + error(csa, "missing numeric value in field %d\n", csa->fldno); + /* skip initial spaces of the field */ + for (s = csa->field; *s == ' '; s++); + /* perform conversion */ + if (str2num(s, &x) != 0) + error(csa, "cannot convert '%s' to floating-point number\n", + s); + return x; +} + +static void skip_field(struct csa *csa) +{ /* read and skip next field (assumed to be blank) */ + read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field %d must be blank\n", csa->fldno); + return; +} + +static void read_name(struct csa *csa) +{ /* read NAME indicator record */ + if (!(indicator(csa, 1) && strcmp(csa->field, "NAME") == 0)) + error(csa, "missing NAME indicator record\n"); + /* this indicator record looks like a data record; simulate that + fields 1 and 2 were read */ + csa->fldno = 2; + /* field 3: model name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + warning(csa, "missing model name in field 3\n"); + else + glp_set_prob_name(csa->P, csa->field); + /* skip anything following field 3 */ + while (csa->c != '\n') + read_char(csa); + return; +} + +static void read_rows(struct csa *csa) +{ /* read ROWS section */ + int i, type; +loop: if (indicator(csa, 0)) goto done; + /* field 1: row type */ + read_field(csa), strspx(csa->field); + if (strcmp(csa->field, "N") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "G") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "L") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "E") == 0) + type = GLP_FX; + else if (csa->field[0] == '\0') + error(csa, "missing row type in field 1\n"); + else + error(csa, "invalid row type in field 1\n"); + /* field 2: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + error(csa, "missing row name in field 2\n"); + if (glp_find_row(csa->P, csa->field) != 0) + error(csa, "row '%s' multiply specified\n", csa->field); + i = glp_add_rows(csa->P, 1); + glp_set_row_name(csa->P, i, csa->field); + glp_set_row_bnds(csa->P, i, type, 0.0, 0.0); + /* fields 3, 4, 5, and 6 must be blank */ + skip_field(csa); + skip_field(csa); + skip_field(csa); + skip_field(csa); + goto loop; +done: return; +} + +static void read_columns(struct csa *csa) +{ /* read COLUMNS section */ + int i, j, f, len, kind = GLP_CV, *ind; + double aij, *val; + char name[255+1], *flag; + /* allocate working arrays */ + csa->work1 = ind = xcalloc(1+csa->P->m, sizeof(int)); + csa->work2 = val = xcalloc(1+csa->P->m, sizeof(double)); + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current column exists */ + j = 0, len = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: column or kind name */ + read_field(csa), patch_name(csa, csa->field); + strcpy(name, csa->field); + /* field 3: row name or keyword 'MARKER' */ + read_field(csa), patch_name(csa, csa->field); + if (strcmp(csa->field, "'MARKER'") == 0) + { /* process kind data record */ + /* field 4 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 4 must be blank\n"); + } + else + csa->fldno++; + /* field 5: keyword 'INTORG' or 'INTEND' */ + read_field(csa), patch_name(csa, csa->field); + if (strcmp(csa->field, "'INTORG'") == 0) + kind = GLP_IV; + else if (strcmp(csa->field, "'INTEND'") == 0) + kind = GLP_CV; + else if (csa->field[0] == '\0') + error(csa, "missing keyword in field 5\n"); + else + error(csa, "invalid keyword in field 5\n"); + /* field 6 must be blank */ + skip_field(csa); + goto loop; + } + /* process column name specified in field 2 */ + if (name[0] == '\0') + { /* the same column as in previous data record */ + if (j == 0) + error(csa, "missing column name in field 2\n"); + } + else if (j != 0 && strcmp(name, csa->P->col[j]->name) == 0) + { /* the same column as in previous data record */ + xassert(j != 0); + } + else + { /* store the current column */ + if (j != 0) + { glp_set_mat_col(csa->P, j, len, ind, val); + while (len > 0) flag[ind[len--]] = 0; + } + /* create new column */ + if (glp_find_col(csa->P, name) != 0) + error(csa, "column '%s' multiply specified\n", name); + j = glp_add_cols(csa->P, 1); + glp_set_col_name(csa->P, j, name); + glp_set_col_kind(csa->P, j, kind); + if (kind == GLP_CV) + glp_set_col_bnds(csa->P, j, GLP_LO, 0.0, 0.0); + else if (kind == GLP_IV) + glp_set_col_bnds(csa->P, j, GLP_DB, 0.0, 1.0); + else + xassert(kind != kind); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + if (f == 3) + { if (csa->field[0] == '\0') + error(csa, "missing row name in field 3\n"); + } + else + { read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row '%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate coefficient in row '%s'\n", + csa->field); + /* field 4 or 6: coefficient value */ + aij = read_number(csa); + if (fabs(aij) < csa->parm->tol_mps) aij = 0.0; + len++, ind[len] = i, val[len] = aij, flag[i] = 1; + } + goto loop; +done: /* store the last column */ + if (j != 0) + glp_set_mat_col(csa->P, j, len, ind, val); + /* free working arrays */ + xfree(ind); + xfree(val); + xfree(flag); + csa->work1 = csa->work2 = csa->work3 = NULL; + return; +} + +static void read_rhs(struct csa *csa) +{ /* read RHS section */ + int i, f, v, type; + double rhs; + char name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current RHS vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: RHS vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same RHS vector as in previous data record */ + if (v == 0) + { warning(csa, "missing RHS vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same RHS vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new RHS vector */ + if (v != 0) + error(csa, "multiple RHS vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { if (f == 3) + error(csa, "missing row name in field 3\n"); + else + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row '%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate right-hand side for row '%s'\n", + csa->field); + /* field 4 or 6: right-hand side value */ + rhs = read_number(csa); + if (fabs(rhs) < csa->parm->tol_mps) rhs = 0.0; + type = csa->P->row[i]->type; + if (type == GLP_FR) + { if (i == csa->obj_row) + glp_set_obj_coef(csa->P, 0, rhs); + else if (rhs != 0.0) + warning(csa, "non-zero right-hand side for free row '%s'" + " ignored\n", csa->P->row[i]->name); + } + else + glp_set_row_bnds(csa->P, i, type, rhs, rhs); + flag[i] = 1; + } + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +static void read_ranges(struct csa *csa) +{ /* read RANGES section */ + int i, f, v, type; + double rhs, rng; + char name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); + memset(&flag[1], 0, csa->P->m); + /* no current RANGES vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1 must be blank */ + if (csa->deck) + { read_field(csa); + if (csa->field[0] != '\0') + error(csa, "field 1 must be blank\n"); + } + else + csa->fldno++; + /* field 2: RANGES vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same RANGES vector as in previous data record */ + if (v == 0) + { warning(csa, "missing RANGES vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same RANGES vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new RANGES vector */ + if (v != 0) + error(csa, "multiple RANGES vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* process fields 3-4 and 5-6 */ + for (f = 3; f <= 5; f += 2) + { /* field 3 or 5: row name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { if (f == 3) + error(csa, "missing row name in field 3\n"); + else + { /* if field 5 is blank, field 6 also must be blank */ + skip_field(csa); + continue; + } + } + i = glp_find_row(csa->P, csa->field); + if (i == 0) + error(csa, "row '%s' not found\n", csa->field); + if (flag[i]) + error(csa, "duplicate range for row '%s'\n", csa->field); + /* field 4 or 6: range value */ + rng = read_number(csa); + if (fabs(rng) < csa->parm->tol_mps) rng = 0.0; + type = csa->P->row[i]->type; + if (type == GLP_FR) + warning(csa, "range for free row '%s' ignored\n", + csa->P->row[i]->name); + else if (type == GLP_LO) + { rhs = csa->P->row[i]->lb; +#if 0 /* 26/V-2017 by cmatraki */ + glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, +#else + glp_set_row_bnds(csa->P, i, rng == 0.0 ? GLP_FX : GLP_DB, +#endif + rhs, rhs + fabs(rng)); + } + else if (type == GLP_UP) + { rhs = csa->P->row[i]->ub; +#if 0 /* 26/V-2017 by cmatraki */ + glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, +#else + glp_set_row_bnds(csa->P, i, rng == 0.0 ? GLP_FX : GLP_DB, +#endif + rhs - fabs(rng), rhs); + } + else if (type == GLP_FX) + { rhs = csa->P->row[i]->lb; + if (rng > 0.0) + glp_set_row_bnds(csa->P, i, GLP_DB, rhs, rhs + rng); + else if (rng < 0.0) + glp_set_row_bnds(csa->P, i, GLP_DB, rhs + rng, rhs); + } + else + xassert(type != type); + flag[i] = 1; + } + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +static void read_bounds(struct csa *csa) +{ /* read BOUNDS section */ + GLPCOL *col; + int j, v, mask, data; + double bnd, lb, ub; + char type[2+1], name[255+1], *flag; + /* allocate working array */ + csa->work3 = flag = xcalloc(1+csa->P->n, sizeof(char)); + memset(&flag[1], 0, csa->P->n); + /* no current BOUNDS vector exists */ + v = 0; +loop: if (indicator(csa, 0)) goto done; + /* field 1: bound type */ + read_field(csa); + if (strcmp(csa->field, "LO") == 0) + mask = 0x01, data = 1; + else if (strcmp(csa->field, "UP") == 0) + mask = 0x10, data = 1; + else if (strcmp(csa->field, "FX") == 0) + mask = 0x11, data = 1; + else if (strcmp(csa->field, "FR") == 0) + mask = 0x11, data = 0; + else if (strcmp(csa->field, "MI") == 0) + mask = 0x01, data = 0; + else if (strcmp(csa->field, "PL") == 0) + mask = 0x10, data = 0; + else if (strcmp(csa->field, "LI") == 0) + mask = 0x01, data = 1; + else if (strcmp(csa->field, "UI") == 0) + mask = 0x10, data = 1; + else if (strcmp(csa->field, "BV") == 0) + mask = 0x11, data = 0; + else if (csa->field[0] == '\0') + error(csa, "missing bound type in field 1\n"); + else + error(csa, "invalid bound type in field 1\n"); + strcpy(type, csa->field); + /* field 2: BOUNDS vector name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + { /* the same BOUNDS vector as in previous data record */ + if (v == 0) + { warning(csa, "missing BOUNDS vector name in field 2\n"); + goto blnk; + } + } + else if (v != 0 && strcmp(csa->field, name) == 0) + { /* the same BOUNDS vector as in previous data record */ + xassert(v != 0); + } + else +blnk: { /* new BOUNDS vector */ + if (v != 0) + error(csa, "multiple BOUNDS vectors not supported\n"); + v++; + strcpy(name, csa->field); + } + /* field 3: column name */ + read_field(csa), patch_name(csa, csa->field); + if (csa->field[0] == '\0') + error(csa, "missing column name in field 3\n"); + j = glp_find_col(csa->P, csa->field); + if (j == 0) + error(csa, "column '%s' not found\n", csa->field); + if ((flag[j] & mask) == 0x01) + error(csa, "duplicate lower bound for column '%s'\n", + csa->field); + if ((flag[j] & mask) == 0x10) + error(csa, "duplicate upper bound for column '%s'\n", + csa->field); + xassert((flag[j] & mask) == 0x00); + /* field 4: bound value */ + if (data) + { bnd = read_number(csa); + if (fabs(bnd) < csa->parm->tol_mps) bnd = 0.0; + } + else + read_field(csa), bnd = 0.0; + /* get current column bounds */ + col = csa->P->col[j]; + if (col->type == GLP_FR) + lb = -DBL_MAX, ub = +DBL_MAX; + else if (col->type == GLP_LO) + lb = col->lb, ub = +DBL_MAX; + else if (col->type == GLP_UP) + lb = -DBL_MAX, ub = col->ub; + else if (col->type == GLP_DB) + lb = col->lb, ub = col->ub; + else if (col->type == GLP_FX) + lb = ub = col->lb; + else + xassert(col != col); + /* change column bounds */ + if (strcmp(type, "LO") == 0) + lb = bnd; + else if (strcmp(type, "UP") == 0) + ub = bnd; + else if (strcmp(type, "FX") == 0) + lb = ub = bnd; + else if (strcmp(type, "FR") == 0) + lb = -DBL_MAX, ub = +DBL_MAX; + else if (strcmp(type, "MI") == 0) + lb = -DBL_MAX; + else if (strcmp(type, "PL") == 0) + ub = +DBL_MAX; + else if (strcmp(type, "LI") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + lb = ceil(bnd); +#if 1 /* 16/VII-2013 */ + /* if column upper bound has not been explicitly specified, + take it as +inf */ + if (!(flag[j] & 0x10)) + ub = +DBL_MAX; +#endif + } + else if (strcmp(type, "UI") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + ub = floor(bnd); + } + else if (strcmp(type, "BV") == 0) + { glp_set_col_kind(csa->P, j, GLP_IV); + lb = 0.0, ub = 1.0; + } + else + xassert(type != type); + /* set new column bounds */ + if (lb == -DBL_MAX && ub == +DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_FR, lb, ub); + else if (ub == +DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_LO, lb, ub); + else if (lb == -DBL_MAX) + glp_set_col_bnds(csa->P, j, GLP_UP, lb, ub); + else if (lb != ub) + glp_set_col_bnds(csa->P, j, GLP_DB, lb, ub); + else + glp_set_col_bnds(csa->P, j, GLP_FX, lb, ub); + flag[j] |= (char)mask; + /* fields 5 and 6 must be blank */ + skip_field(csa); + skip_field(csa); + goto loop; +done: /* free working array */ + xfree(flag); + csa->work3 = NULL; + return; +} + +int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname) +{ /* read problem data in MPS format */ + glp_mpscp _parm; + struct csa _csa, *csa = &_csa; + int ret; + xprintf("Reading problem data from '%s'...\n", fname); + if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) + xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt); + if (parm == NULL) + glp_init_mpscp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_read_mps", parm); + /* initialize common storage area */ + csa->P = P; + csa->deck = (fmt == GLP_MPS_DECK); + csa->parm = parm; + csa->fname = fname; + csa->fp = NULL; + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->recno = csa->recpos = 0; + csa->c = '\n'; + csa->fldno = 0; + csa->field[0] = '\0'; + csa->w80 = csa->wef = 0; + csa->obj_row = 0; + csa->work1 = csa->work2 = csa->work3 = NULL; + /* erase problem object */ + glp_erase_prob(P); + glp_create_index(P); + /* open input MPS file */ + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* read NAME indicator record */ + read_name(csa); + if (P->name != NULL) + xprintf("Problem: %s\n", P->name); + /* read ROWS section */ + if (!(indicator(csa, 0) && strcmp(csa->field, "ROWS") == 0)) + error(csa, "missing ROWS indicator record\n"); + read_rows(csa); + /* determine objective row */ + if (parm->obj_name == NULL || parm->obj_name[0] == '\0') + { /* use the first row of N type */ + int i; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + { csa->obj_row = i; + break; + } + } + if (csa->obj_row == 0) + warning(csa, "unable to determine objective row\n"); + } + else + { /* use a row with specified name */ + int i; + for (i = 1; i <= P->m; i++) + { xassert(P->row[i]->name != NULL); + if (strcmp(parm->obj_name, P->row[i]->name) == 0) + { csa->obj_row = i; + break; + } + } + if (csa->obj_row == 0) + error(csa, "objective row '%s' not found\n", + parm->obj_name); + } + if (csa->obj_row != 0) + { glp_set_obj_name(P, P->row[csa->obj_row]->name); + xprintf("Objective: %s\n", P->obj); + } + /* read COLUMNS section */ + if (strcmp(csa->field, "COLUMNS") != 0) + error(csa, "missing COLUMNS indicator record\n"); + read_columns(csa); + /* set objective coefficients */ + if (csa->obj_row != 0) + { GLPAIJ *aij; + for (aij = P->row[csa->obj_row]->ptr; aij != NULL; aij = + aij->r_next) glp_set_obj_coef(P, aij->col->j, aij->val); + } + /* read optional RHS section */ + if (strcmp(csa->field, "RHS") == 0) + read_rhs(csa); + /* read optional RANGES section */ + if (strcmp(csa->field, "RANGES") == 0) + read_ranges(csa); + /* read optional BOUNDS section */ + if (strcmp(csa->field, "BOUNDS") == 0) + read_bounds(csa); + /* read ENDATA indicator record */ + if (strcmp(csa->field, "ENDATA") != 0) + error(csa, "invalid use of %s indicator record\n", + csa->field); + /* print some statistics */ + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d records were read\n", csa->recno); +#if 1 /* 31/III-2016 */ + /* free (unbounded) row(s) in MPS file are intended to specify + * objective function(s), so all such rows can be removed */ +#if 1 /* 08/VIII-2013 */ + /* remove free rows */ + { int i, nrs, *num; + num = talloc(1+P->m, int); + nrs = 0; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + num[++nrs] = i; + } + if (nrs > 0) + { glp_del_rows(P, nrs, num); + if (nrs == 1) + xprintf("One free row was removed\n"); + else + xprintf("%d free rows were removed\n", nrs); + } + tfree(num); + } +#endif +#else + /* if objective function row is free, remove it */ + if (csa->obj_row != 0 && P->row[csa->obj_row]->type == GLP_FR) + { int num[1+1]; + num[1] = csa->obj_row; + glp_del_rows(P, 1, num); + xprintf("Free objective row was removed\n"); + } +#endif + /* problem data has been successfully read */ + glp_delete_index(P); + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + if (csa->work1 != NULL) xfree(csa->work1); + if (csa->work2 != NULL) xfree(csa->work2); + if (csa->work3 != NULL) xfree(csa->work3); + if (ret != 0) glp_erase_prob(P); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_write_mps - write problem data in MPS format +* +* SYNOPSIS +* +* int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mps writes problem data in MPS format to a +* text file. +* +* The parameter fmt specifies the version of MPS format: +* +* GLP_MPS_DECK - fixed (ancient) MPS format; +* GLP_MPS_FILE - free (modern) MPS format. +* +* The parameter parm is a pointer to the structure glp_mpscp, which +* specifies control parameters used by the routine. If parm is NULL, +* the routine uses default settings. +* +* The character string fname specifies a name of the text file to be +* written. +* +* RETURNS +* +* If the operation was successful, the routine glp_read_mps returns +* zero. Otherwise, it prints an error message and returns non-zero. */ + +#define csa csa1 + +struct csa +{ /* common storage area */ + glp_prob *P; + /* pointer to problem object */ + int deck; + /* MPS format (0 - free, 1 - fixed) */ + const glp_mpscp *parm; + /* pointer to control parameters */ + char field[255+1]; + /* field buffer */ +}; + +static char *mps_name(struct csa *csa) +{ /* make problem name */ + char *f; + if (csa->P->name == NULL) + csa->field[0] = '\0'; + else if (csa->deck) + { strncpy(csa->field, csa->P->name, 8); + csa->field[8] = '\0'; + } + else + strcpy(csa->field, csa->P->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + return csa->field; +} + +static char *row_name(struct csa *csa, int i) +{ /* make i-th row name */ + char *f; + xassert(0 <= i && i <= csa->P->m); + if (i == 0 || csa->P->row[i]->name == NULL || + csa->deck && strlen(csa->P->row[i]->name) > 8) + sprintf(csa->field, "R%07d", i); + else + { strcpy(csa->field, csa->P->row[i]->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + } + return csa->field; +} + +static char *col_name(struct csa *csa, int j) +{ /* make j-th column name */ + char *f; + xassert(1 <= j && j <= csa->P->n); + if (csa->P->col[j]->name == NULL || + csa->deck && strlen(csa->P->col[j]->name) > 8) + sprintf(csa->field, "C%07d", j); + else + { strcpy(csa->field, csa->P->col[j]->name); + for (f = csa->field; *f != '\0'; f++) + if (*f == ' ') *f = '_'; + } + return csa->field; +} + +static char *mps_numb(struct csa *csa, double val) +{ /* format floating-point number */ + int dig; + char *exp; + for (dig = 12; dig >= 6; dig--) + { if (val != 0.0 && fabs(val) < 0.002) + sprintf(csa->field, "%.*E", dig-1, val); + else + sprintf(csa->field, "%.*G", dig, val); + exp = strchr(csa->field, 'E'); + if (exp != NULL) + sprintf(exp+1, "%d", atoi(exp+1)); + if (strlen(csa->field) <= 12) break; + } + xassert(strlen(csa->field) <= 12); + return csa->field; +} + +int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname) +{ /* write problem data in MPS format */ + glp_mpscp _parm; + struct csa _csa, *csa = &_csa; + glp_file *fp; + int out_obj, one_col = 0, empty = 0; + int i, j, recno, marker, count, gap, ret; + xprintf("Writing problem data to '%s'...\n", fname); + if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) + xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt); + if (parm == NULL) + glp_init_mpscp(&_parm), parm = &_parm; + /* check control parameters */ + check_parm("glp_write_mps", parm); + /* initialize common storage area */ + csa->P = P; + csa->deck = (fmt == GLP_MPS_DECK); + csa->parm = parm; + /* create output MPS file */ + fp = glp_open(fname, "w"), recno = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write comment records */ + xfprintf(fp, "* %-*s%s\n", P->name == NULL ? 1 : 12, "Problem:", + P->name == NULL ? "" : P->name), recno++; + xfprintf(fp, "* %-12s%s\n", "Class:", glp_get_num_int(P) == 0 ? + "LP" : "MIP"), recno++; + xfprintf(fp, "* %-12s%d\n", "Rows:", P->m), recno++; + if (glp_get_num_int(P) == 0) + xfprintf(fp, "* %-12s%d\n", "Columns:", P->n), recno++; + else + xfprintf(fp, "* %-12s%d (%d integer, %d binary)\n", + "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)), + recno++; + xfprintf(fp, "* %-12s%d\n", "Non-zeros:", P->nnz), recno++; + xfprintf(fp, "* %-12s%s\n", "Format:", csa->deck ? "Fixed MPS" : + "Free MPS"), recno++; + xfprintf(fp, "*\n", recno++); + /* write NAME indicator record */ + xfprintf(fp, "NAME%*s%s\n", + P->name == NULL ? 0 : csa->deck ? 10 : 1, "", mps_name(csa)), + recno++; +#if 1 + /* determine whether to write the objective row */ + out_obj = 1; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + { out_obj = 0; + break; + } + } +#endif + /* write ROWS section */ + xfprintf(fp, "ROWS\n"), recno++; + for (i = (out_obj ? 0 : 1); i <= P->m; i++) + { int type; + type = (i == 0 ? GLP_FR : P->row[i]->type); + if (type == GLP_FR) + type = 'N'; + else if (type == GLP_LO) + type = 'G'; + else if (type == GLP_UP) + type = 'L'; + else if (type == GLP_DB || type == GLP_FX) + type = 'E'; + else + xassert(type != type); + xfprintf(fp, " %c%*s%s\n", type, csa->deck ? 2 : 1, "", + row_name(csa, i)), recno++; + } + /* write COLUMNS section */ + xfprintf(fp, "COLUMNS\n"), recno++; + marker = 0; + for (j = 1; j <= P->n; j++) + { GLPAIJ cj, *aij; + int kind; + kind = P->col[j]->kind; + if (kind == GLP_CV) + { if (marker % 2 == 1) + { /* close current integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } + } + else if (kind == GLP_IV) + { if (marker % 2 == 0) + { /* open new integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTORG'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } + } + else + xassert(kind != kind); + if (out_obj && P->col[j]->coef != 0.0) + { /* make fake objective coefficient */ + aij = &cj; + aij->row = NULL; + aij->val = P->col[j]->coef; + aij->c_next = P->col[j]->ptr; + } + else + aij = P->col[j]->ptr; +#if 1 /* FIXME */ + if (aij == NULL) + { /* empty column */ + empty++; + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + /* we need a row */ + xassert(P->m > 0); + xfprintf(fp, "%*s%-*s", + csa->deck ? 2 : 1, "", csa->deck ? 8 : 1, + row_name(csa, 1)); + xfprintf(fp, "%*s0%*s$ empty column\n", + csa->deck ? 13 : 1, "", csa->deck ? 3 : 1, ""), recno++; + } +#endif + count = 0; + for (aij = aij; aij != NULL; aij = aij->c_next) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, aij->row == NULL ? 0 : aij->row->i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, aij->val)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; + } + if (marker % 2 == 1) + { /* close last integer block */ + marker++; + xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", + csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", + csa->deck ? 17 : 1, ""), recno++; + } +#if 1 + if (empty > 0) + xprintf("Warning: problem has %d empty column(s)\n", empty); +#endif + /* write RHS section */ + xfprintf(fp, "RHS\n"), recno++; + count = 0; + for (i = (out_obj ? 0 : 1); i <= P->m; i++) + { int type; + double rhs; + if (i == 0) + rhs = P->c0; + else + { type = P->row[i]->type; + if (type == GLP_FR) + rhs = 0.0; + else if (type == GLP_LO) + rhs = P->row[i]->lb; + else if (type == GLP_UP) + rhs = P->row[i]->ub; + else if (type == GLP_DB || type == GLP_FX) + rhs = P->row[i]->lb; + else + xassert(type != type); + } + if (rhs != 0.0) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, "RHS1"); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, rhs)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; + /* write RANGES section */ + for (i = P->m; i >= 1; i--) + if (P->row[i]->type == GLP_DB) break; + if (i == 0) goto bnds; + xfprintf(fp, "RANGES\n"), recno++; + count = 0; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_DB) + { if (one_col || count % 2 == 0) + xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", + csa->deck ? 8 : 1, "RNG1"); + gap = (one_col || count % 2 == 0 ? 2 : 3); + xfprintf(fp, "%*s%-*s", + csa->deck ? gap : 1, "", csa->deck ? 8 : 1, + row_name(csa, i)); + xfprintf(fp, "%*s%*s", + csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, + mps_numb(csa, P->row[i]->ub - P->row[i]->lb)), count++; + if (one_col || count % 2 == 0) + xfprintf(fp, "\n"), recno++; + } + } + if (!(one_col || count % 2 == 0)) + xfprintf(fp, "\n"), recno++; +bnds: /* write BOUNDS section */ + for (j = P->n; j >= 1; j--) + if (!(P->col[j]->kind == GLP_CV && + P->col[j]->type == GLP_LO && P->col[j]->lb == 0.0)) + break; + if (j == 0) goto endt; + xfprintf(fp, "BOUNDS\n"), recno++; + for (j = 1; j <= P->n; j++) + { int type, data[2]; + double bnd[2]; + char *spec[2]; + spec[0] = spec[1] = NULL; + type = P->col[j]->type; + if (type == GLP_FR) + spec[0] = "FR", data[0] = 0; + else if (type == GLP_LO) + { if (P->col[j]->lb != 0.0) + spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; + if (P->col[j]->kind == GLP_IV) + spec[1] = "PL", data[1] = 0; + } + else if (type == GLP_UP) + { spec[0] = "MI", data[0] = 0; + spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; + } + else if (type == GLP_DB) + { if (P->col[j]->lb != 0.0) + spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; + spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; + } + else if (type == GLP_FX) + spec[0] = "FX", data[0] = 1, bnd[0] = P->col[j]->lb; + else + xassert(type != type); + for (i = 0; i <= 1; i++) + { if (spec[i] != NULL) + { xfprintf(fp, " %s %-*s%*s%-*s", spec[i], + csa->deck ? 8 : 1, "BND1", csa->deck ? 2 : 1, "", + csa->deck ? 8 : 1, col_name(csa, j)); + if (data[i]) + xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", + csa->deck ? 12 : 1, mps_numb(csa, bnd[i])); + xfprintf(fp, "\n"), recno++; + } + } + } +endt: /* write ENDATA indicator record */ + xfprintf(fp, "ENDATA\n"), recno++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* problem data has been successfully written */ + xprintf("%d records were written\n", recno); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/netgen.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/netgen.c new file mode 100644 index 000000000..519fd6096 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/netgen.c @@ -0,0 +1,1020 @@ +/* netgen.c (Klingman's network problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran program NETGEN +* developed by Dr. Darwin Klingman, which is publically available from +* NETLIB at . +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_netgen - Klingman's network problem generator +* +* SYNOPSIS +* +* int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, +* const int parm[1+15]); +* +* DESCRIPTION +* +* The routine glp_netgen is a network problem generator developed by +* Dr. Darwin Klingman. It can create capacitated and uncapacitated +* minimum cost flow (or transshipment), transportation, and assignment +* problems. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The parameter v_rhs specifies an offset of the field of type double +* in the vertex data block, to which the routine stores the supply or +* demand value. If v_rhs < 0, the value is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The parameter a_cost specifies an offset of the field of type double +* in the arc data block, to which the routine stores the per-unit cost +* if the arc flow. If a_cost < 0, the cost is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] (iseed) 8-digit positive random number seed +* parm[2] (nprob) 8-digit problem id number +* parm[3] (nodes) total number of nodes +* parm[4] (nsorc) total number of source nodes (including +* transshipment nodes) +* parm[5] (nsink) total number of sink nodes (including +* transshipment nodes) +* parm[6] (iarcs) number of arcs +* parm[7] (mincst) minimum cost for arcs +* parm[8] (maxcst) maximum cost for arcs +* parm[9] (itsup) total supply +* parm[10] (ntsorc) number of transshipment source nodes +* parm[11] (ntsink) number of transshipment sink nodes +* parm[12] (iphic) percentage of skeleton arcs to be given +* the maximum cost +* parm[13] (ipcap) percentage of arcs to be capacitated +* parm[14] (mincap) minimum upper bound for capacitated arcs +* parm[15] (maxcap) maximum upper bound for capacitated arcs +* +* The routine generates a transportation problem if: +* +* nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0. +* +* The routine generates an assignment problem if the requirements for +* a transportation problem are met and: +* +* nsorc = nsink and itsup = nsorc. +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_netgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* REFERENCES +* +* D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating +* large scale capacitated assignment, transportation, and minimum cost +* flow networks. Management Science 20 (1974), 814-20. */ + +struct csa +{ /* common storage area */ + glp_graph *G; + int v_rhs, a_cap, a_cost; + int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor, + nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl, + nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult, + modul, i15, i16, jran; +}; + +#define G (csa->G) +#define v_rhs (csa->v_rhs) +#define a_cap (csa->a_cap) +#define a_cost (csa->a_cost) +#define nodes (csa->nodes) +#define iarcs (csa->iarcs) +#define mincst (csa->mincst) +#define maxcst (csa->maxcst) +#define itsup (csa->itsup) +#define nsorc (csa->nsorc) +#define nsink (csa->nsink) +#define nonsor (csa->nonsor) +#define nfsink (csa->nfsink) +#define narcs (csa->narcs) +#define nsort (csa->nsort) +#define nftsor (csa->nftsor) +#define ipcap (csa->ipcap) +#define mincap (csa->mincap) +#define maxcap (csa->maxcap) +#define ktl (csa->ktl) +#define nodlft (csa->nodlft) +#if 0 +/* spent a day to find out this bug */ +#define ist (csa->ist) +#else +#define ist (ipred[0]) +#endif +#define ipred (csa->ipred) +#define ihead (csa->ihead) +#define itail (csa->itail) +#define iflag (csa->iflag) +#define isup (csa->isup) +#define lsinks (csa->lsinks) +#define mult (csa->mult) +#define modul (csa->modul) +#define i15 (csa->i15) +#define i16 (csa->i16) +#define jran (csa->jran) + +static void cresup(struct csa *csa); +static void chain(struct csa *csa, int lpick, int lsorc); +static void chnarc(struct csa *csa, int lsorc); +static void sort(struct csa *csa); +static void pickj(struct csa *csa, int it); +static void assign(struct csa *csa); +static void setran(struct csa *csa, int iseed); +static int iran(struct csa *csa, int ilow, int ihigh); + +int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, + const int parm[1+15]) +{ struct csa _csa, *csa = &_csa; + int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink, + ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick, + nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap, + jcap, icost, jcost, ret; + G = G_; + v_rhs = _v_rhs; + a_cap = _a_cap; + a_cost = _a_cost; + if (G != NULL) + { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost); + } + /* Input the user's random number seed and fix it if + non-positive. */ + iseed = parm[1]; + nprob = parm[2]; + if (iseed <= 0) iseed = 13502460; + setran(csa, iseed); + /* Input the user's problem characteristics. */ + nodes = parm[3]; + nsorc = parm[4]; + nsink = parm[5]; + iarcs = parm[6]; + mincst = parm[7]; + maxcst = parm[8]; + itsup = parm[9]; + ntsorc = parm[10]; + ntsink = parm[11]; + iphic = parm[12]; + ipcap = parm[13]; + mincap = parm[14]; + maxcap = parm[15]; + /* Check the size of the problem. */ + if (!(10 <= nodes && nodes <= 100000)) + { ret = 1; + goto done; + } + /* Check user supplied parameters for consistency. */ + if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes)) + { ret = 2; + goto done; + } + if (iarcs < 0) + { ret = 3; + goto done; + } + if (mincst > maxcst) + { ret = 4; + goto done; + } + if (itsup < 0) + { ret = 5; + goto done; + } + if (!(0 <= ntsorc && ntsorc <= nsorc)) + { ret = 6; + goto done; + } + if (!(0 <= ntsink && ntsink <= nsink)) + { ret = 7; + goto done; + } + if (!(0 <= iphic && iphic <= 100)) + { ret = 8; + goto done; + } + if (!(0 <= ipcap && ipcap <= 100)) + { ret = 9; + goto done; + } + if (mincap > maxcap) + { ret = 10; + goto done; + } + /* Initailize the graph object. */ + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_add_vertices(G, nodes); + if (v_rhs >= 0) + { double zero = 0.0; + for (i = 1; i <= nodes; i++) + { glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); + } + } + } + /* Allocate working arrays. */ + ipred = xcalloc(1+nodes, sizeof(int)); + ihead = xcalloc(1+nodes, sizeof(int)); + itail = xcalloc(1+nodes, sizeof(int)); + iflag = xcalloc(1+nodes, sizeof(int)); + isup = xcalloc(1+nodes, sizeof(int)); + lsinks = xcalloc(1+nodes, sizeof(int)); + /* Print the problem documentation records. */ + if (G == NULL) + { xprintf("BEGIN\n"); + xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n", + nprob, "", nodes, iarcs); + xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%" + "11d%11d\n", iseed, nsorc, nsink, mincst, + maxcst, itsup, ntsorc, ntsink, iphic, ipcap, + mincap, maxcap); + } + else + glp_set_graph_name(G, "NETGEN"); + /* Set various constants used in the program. */ + narcs = 0; + nskel = 0; + nltr = nodes - nsink; + ltsink = nltr + ntsink; + ntrans = nltr - nsorc; + nfsink = nltr + 1; + nonsor = nodes - nsorc + ntsorc; + npsink = nsink - ntsink; + nodlft = nodes - nsink + ntsink; + nftr = nsorc + 1; + nftsor = nsorc - ntsorc + 1; + npsorc = nsorc - ntsorc; + /* Randomly distribute the supply among the source nodes. */ + if (npsorc + npsink == nodes && npsorc == npsink && + itsup == nsorc) + { assign(csa); + nskel = nsorc; + goto L390; + } + cresup(csa); + /* Print the supply records. */ + if (G == NULL) + { xprintf("SUPPLY\n"); + for (i = 1; i <= nsorc; i++) + xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); + xprintf("ARCS\n"); + } + else + { if (v_rhs >= 0) + { for (i = 1; i <= nsorc; i++) + { double temp = (double)isup[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Make the sources point to themselves in ipred array. */ + for (i = 1; i <= nsorc; i++) + ipred[i] = i; + if (ntrans == 0) goto L170; + /* Chain the transshipment nodes together in the ipred array. */ + ist = nftr; + ipred[nltr] = 0; + for (i = nftr; i < nltr; i++) + ipred[i] = i+1; + /* Form even length chains for 60 percent of the transshipments.*/ + ntravl = 6 * ntrans / 10; + ntrrem = ntrans - ntravl; +L140: lsorc = 1; + while (ntravl != 0) + { lpick = iran(csa, 1, ntravl + ntrrem); + ntravl--; + chain(csa, lpick, lsorc); + if (lsorc == nsorc) goto L140; + lsorc++; + } + /* Add the remaining transshipments to the chains. */ + while (ntrrem != 0) + { + lpick = iran(csa, 1, ntrrem); + ntrrem--; + lsorc = iran(csa, 1, nsorc); + chain(csa, lpick, lsorc); + } +L170: /* Set all demands equal to zero. */ + for (i = nfsink; i <= nodes; i++) + ipred[i] = 0; + /* The following loop takes one chain at a time (through the use + of logic contained in the loop and calls to other routines) and + creates the remaining network arcs. */ + for (lsorc = 1; lsorc <= nsorc; lsorc++) + { chnarc(csa, lsorc); + for (i = nfsink; i <= nodes; i++) + iflag[i] = 0; + /* Choose the number of sinks to be hooked up to the current + chain. */ + if (ntrans != 0) + nsksr = (nsort * 2 * nsink) / ntrans; + else + nsksr = nsink / nsorc + 1; + if (nsksr < 2) nsksr = 2; + if (nsksr > nsink) nsksr = nsink; + nsrchn = nsort; + /* Randomly pick nsksr sinks and put their names in lsinks. */ + ktl = nsink; + for (j = 1; j <= nsksr; j++) + { item = iran(csa, 1, ktl); + ktl--; + for (l = nfsink; l <= nodes; l++) + { if (iflag[l] != 1) + { item--; + if (item == 0) goto L230; + } + } + break; +L230: lsinks[j] = l; + iflag[l] = 1; + } + /* If last source chain, add all sinks with zero demand to + lsinks list. */ + if (lsorc == nsorc) + { for (j = nfsink; j <= nodes; j++) + { if (ipred[j] == 0 && iflag[j] != 1) + { nsksr++; + lsinks[nsksr] = j; + iflag[j] = 1; + } + } + } + /* Create demands for group of sinks in lsinks. */ + ks = isup[lsorc] / nsksr; + k = ipred[lsorc]; + for (i = 1; i <= nsksr; i++) + { nsort++; + ksp = iran(csa, 1, ks); + j = iran(csa, 1, nsksr); + itail[nsort] = k; + li = lsinks[i]; + ihead[nsort] = li; + ipred[li] += ksp; + li = lsinks[j]; + ipred[li] += ks - ksp; + n = iran(csa, 1, nsrchn); + k = lsorc; + for (ii = 1; ii <= n; ii++) + k = ipred[k]; + } + li = lsinks[1]; + ipred[li] += isup[lsorc] - ks * nsksr; + nskel += nsort; + /* Sort the arcs in the chain from source lsorc using itail as + sort key. */ + sort(csa); + /* Print this part of skeleton and create the arcs for these + nodes. */ + i = 1; + itail[nsort+1] = 0; +L300: for (j = nftsor; j <= nodes; j++) + iflag[j] = 0; + ktl = nonsor - 1; + it = itail[i]; + iflag[it] = 1; +L320: ih = ihead[i]; + iflag[ih] = 1; + narcs++; + ktl--; + /* Determine if this skeleton arc should be capacitated. */ + icap = itsup; + jcap = iran(csa, 1, 100); + if (jcap <= ipcap) + { icap = isup[lsorc]; + if (mincap > icap) icap = mincap; + } + /* Determine if this skeleton arc should have the maximum + cost. */ + icost = maxcst; + jcost = iran(csa, 1, 100); + if (jcost > iphic) + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost, + icap); + else + { glp_arc *a = glp_add_arc(G, it, ih); + if (a_cap >= 0) + { double temp = (double)icap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + i++; + if (itail[i] == it) goto L320; + pickj(csa, it); + if (i <= nsort) goto L300; + } + /* Create arcs from the transshipment sinks. */ + if (ntsink != 0) + { for (i = nfsink; i <= ltsink; i++) + { for (j = nftsor; j <= nodes; j++) + iflag[j] = 0; + ktl = nonsor - 1; + iflag[i] = 1; + pickj(csa, i); + } + } +L390: /* Print the demand records and end record. */ + if (G == NULL) + { xprintf("DEMAND\n"); + for (i = nfsink; i <= nodes; i++) + xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]); + xprintf("END\n"); + } + else + { if (v_rhs >= 0) + { for (i = nfsink; i <= nodes; i++) + { double temp = - (double)ipred[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + /* Free working arrays. */ + xfree(ipred); + xfree(ihead); + xfree(itail); + xfree(iflag); + xfree(isup); + xfree(lsinks); + /* The instance has been successfully generated. */ + ret = 0; +done: return ret; +} + +/*********************************************************************** +* The routine cresup randomly distributes the total supply among the +* source nodes. */ + +static void cresup(struct csa *csa) +{ int i, j, ks, ksp; + xassert(itsup > nsorc); + ks = itsup / nsorc; + for (i = 1; i <= nsorc; i++) + isup[i] = 0; + for (i = 1; i <= nsorc; i++) + { ksp = iran(csa, 1, ks); + j = iran(csa, 1, nsorc); + isup[i] += ksp; + isup[j] += ks - ksp; + } + j = iran(csa, 1, nsorc); + isup[j] += itsup - ks * nsorc; + return; +} + +/*********************************************************************** +* The routine chain adds node lpick to the end of the chain with source +* node lsorc. */ + +static void chain(struct csa *csa, int lpick, int lsorc) +{ int i, j, k, l, m; + k = 0; + m = ist; + for (i = 1; i <= lpick; i++) + { l = k; + k = m; + m = ipred[k]; + } + ipred[l] = m; + j = ipred[lsorc]; + ipred[k] = j; + ipred[lsorc] = k; + return; +} + +/*********************************************************************** +* The routine chnarc puts the arcs in the chain from source lsorc into +* the ihead and itail arrays for sorting. */ + +static void chnarc(struct csa *csa, int lsorc) +{ int ito, ifrom; + nsort = 0; + ito = ipred[lsorc]; +L10: if (ito == lsorc) return; + nsort++; + ifrom = ipred[ito]; + ihead[nsort] = ito; + itail[nsort] = ifrom; + ito = ifrom; + goto L10; +} + +/*********************************************************************** +* The routine sort sorts the nsort arcs in the ihead and itail arrays. +* ihead is used as the sort key (i.e. forward star sort order). */ + +static void sort(struct csa *csa) +{ int i, j, k, l, m, n, it; + n = nsort; + m = n; +L10: m /= 2; + if (m == 0) return; + k = n - m; + j = 1; +L20: i = j; +L30: l = i + m; + if (itail[i] <= itail[l]) goto L40; + it = itail[i]; + itail[i] = itail[l]; + itail[l] = it; + it = ihead[i]; + ihead[i] = ihead[l]; + ihead[l] = it; + i -= m; + if (i >= 1) goto L30; +L40: j++; + if (j <= k) goto L20; + goto L10; +} + +/*********************************************************************** +* The routine pickj creates a random number of arcs out of node 'it'. +* Various parameters are dynamically adjusted in an attempt to ensure +* that the generated network has the correct number of arcs. */ + +static void pickj(struct csa *csa, int it) +{ int j, k, l, nn, nupbnd, icap, jcap, icost; + if ((nodlft - 1) * 2 > iarcs - narcs - 1) + { nodlft--; + return; + } + if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0) + k = nonsor; + else + { nupbnd = (iarcs - narcs - nodlft) / nodlft * 2; +L40: k = iran(csa, 1, nupbnd); + if (nodlft == 1) k = iarcs - narcs; + if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40; + } + nodlft--; + for (j = 1; j <= k; j++) + { nn = iran(csa, 1, ktl); + ktl--; + for (l = nftsor; l <= nodes; l++) + { if (iflag[l] != 1) + { nn--; + if (nn == 0) goto L70; + } + } + return; +L70: iflag[l] = 1; + icap = itsup; + jcap = iran(csa, 1, 100); + if (jcap <= ipcap) + icap = iran(csa, mincap, maxcap); + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost, + icap); + else + { glp_arc *a = glp_add_arc(G, it, l); + if (a_cap >= 0) + { double temp = (double)icap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + narcs++; + } + return; +} + +/*********************************************************************** +* The routine assign generate assignment problems. It defines the unit +* supplies, builds a skeleton, then calls pickj to create the arcs. */ + +static void assign(struct csa *csa) +{ int i, it, nn, l, ll, icost; + if (G == NULL) + xprintf("SUPPLY\n"); + for (i = 1; i <= nsorc; i++) + { isup[i] = 1; + iflag[i] = 0; + if (G == NULL) + xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); + else + { if (v_rhs >= 0) + { double temp = (double)isup[i]; + glp_vertex *v = G->v[i]; + memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); + } + } + } + if (G == NULL) + xprintf("ARCS\n"); + for (i = nfsink; i <= nodes; i++) + ipred[i] = 1; + for (it = 1; it <= nsorc; it++) + { for (i = nfsink; i <= nodes; i++) + iflag[i] = 0; + ktl = nsink - 1; + nn = iran(csa, 1, nsink - it + 1); + for (l = 1; l <= nsorc; l++) + { if (iflag[l] != 1) + { nn--; + if (nn == 0) break; + } + } + narcs++; + ll = nsorc + l; + icost = iran(csa, mincst, maxcst); + if (G == NULL) + xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost, + isup[1]); + else + { glp_arc *a = glp_add_arc(G, it, ll); + if (a_cap >= 0) + { double temp = (double)isup[1]; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + if (a_cost >= 0) + { double temp = (double)icost; + memcpy((char *)a->data + a_cost, &temp, sizeof(double)); + } + } + iflag[l] = 1; + iflag[ll] = 1; + pickj(csa, it); + } + return; +} + +/*********************************************************************** +* Portable congruential (uniform) random number generator: +* +* next_value = ((7**5) * previous_value) modulo ((2**31)-1) +* +* This generator consists of three routines: +* +* (1) setran - initializes constants and seed +* (2) iran - generates an integer random number +* (3) rran - generates a real random number +* +* The generator requires a machine with at least 32 bits of precision. +* The seed (iseed) must be in the range [1,(2**31)-1]. */ + +static void setran(struct csa *csa, int iseed) +{ xassert(iseed >= 1); + mult = 16807; + modul = 2147483647; + i15 = 1 << 15; + i16 = 1 << 16; + jran = iseed; + return; +} + +/*********************************************************************** +* The routine iran generates an integer random number between ilow and +* ihigh. If ilow > ihigh then iran returns ihigh. */ + +static int iran(struct csa *csa, int ilow, int ihigh) +{ int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover, + irthi, j; + ixhi = jran / i16; + ixlo = jran - ixhi * i16; + ixalo = ixlo * mult; + leftlo = ixalo / i16; + ixahi = ixhi * mult; + ifulhi = ixahi + leftlo; + irtlo = ixalo - leftlo * i16; + iover = ifulhi / i15; + irthi = ifulhi - iover * i15; + jran = ((irtlo - modul) + irthi * i16) + iover; + if (jran < 0) jran += modul; + j = ihigh - ilow + 1; + if (j > 0) + return jran % j + ilow; + else + return ihigh; +} + +/*********************************************************************** +* NAME +* +* glp_netgen_prob - Klingman's standard network problem instance +* +* SYNOPSIS +* +* void glp_netgen_prob(int nprob, int parm[1+15]); +* +* DESCRIPTION +* +* The routine glp_netgen_prob provides the set of parameters for +* Klingman's network problem generator (see the routine glp_netgen), +* which describe a standard network problem instance. +* +* The parameter nprob (101 <= nprob <= 150) specifies the problem +* instance number. +* +* The array parm contains description of the network, provided by the +* routine. (For detailed description of these parameters see comments +* to the routine glp_netgen.) +* +* PROBLEM CHARACTERISTICS +* +* The table below shows characteristics of Klingman's standard network +* problem instances. +* +* Problem Nodes Arcs Optimum +* ------- ----- ----- ---------- +* 101 5000 25336 6191726 +* 102 5000 25387 72337144 +* 103 5000 25355 218947553 +* 104 5000 25344 -19100371 +* 105 5000 25332 31192578 +* 106 5000 12870 4314276 +* 107 5000 37832 7393769 +* 108 5000 50309 8405738 +* 109 5000 75299 9190300 +* 110 5000 12825 8975048 +* 111 5000 37828 4747532 +* 112 5000 50325 4012671 +* 113 5000 75318 2979725 +* 114 5000 26514 5821181 +* 115 5000 25962 6353310 +* 116 5000 25304 5915426 +* 117 5000 12816 4420560 +* 118 5000 37797 7045842 +* 119 5000 50301 7724179 +* 120 5000 75330 8455200 +* 121 5000 25000 66366360 +* 122 5000 25000 30997529 +* 123 5000 25000 23388777 +* 124 5000 25000 17803443 +* 125 5000 25000 14119622 +* 126 5000 12500 18802218 +* 127 5000 37500 27674647 +* 128 5000 50000 30906194 +* 129 5000 75000 40905209 +* 130 5000 12500 38939608 +* 131 5000 37500 16752978 +* 132 5000 50000 13302951 +* 133 5000 75000 9830268 +* 134 1000 25000 3804874 +* 135 2500 25000 11729616 +* 136 7500 25000 33318101 +* 137 10000 25000 46426030 +* 138 5000 25000 60710879 +* 139 5000 25000 32729682 +* 140 5000 25000 27183831 +* 141 5000 25000 19963286 +* 142 5000 25000 20243457 +* 143 5000 25000 18586777 +* 144 5000 25000 2504591 +* 145 5000 25000 215956138 +* 146 5000 25000 2253113811 +* 147 5000 25000 -427908373 +* 148 5000 25000 -92965318 +* 149 5000 25000 86051224 +* 150 5000 25000 619314919 */ + +static const int data[50][1+15] = +{ { 0, 13502460, 101, 5000, 2500, 2500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4281922, 102, 5000, 2500, 2500, 25000, + 1, 100, 2500000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 44820113, 103, 5000, 2500, 2500, 25000, + 1, 100, 6250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 13450451, 104, 5000, 2500, 2500, 25000, + -100, -1, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 14719436, 105, 5000, 2500, 2500, 25000, + 101, 200, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 17365786, 106, 5000, 2500, 2500, 12500, + 1, 100, 125000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19540113, 107, 5000, 2500, 2500, 37500, + 1, 100, 375000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19560313, 108, 5000, 2500, 2500, 50000, + 1, 100, 500000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 2403509, 109, 5000, 2500, 2500, 75000, + 1, 100, 750000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 92480414, 110, 5000, 2500, 2500, 12500, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4230140, 111, 5000, 2500, 2500, 37500, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 10032490, 112, 5000, 2500, 2500, 50000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 17307474, 113, 5000, 2500, 2500, 75000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 4925114, 114, 5000, 500, 4500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 19842704, 115, 5000, 1500, 3500, 25000, + 1, 100, 250000, 0, 0, 0, 100, 1, 1000 + }, + { 0, 88392060, 116, 5000, 2500, 2500, 25000, + 1, 100, 250000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 12904407, 117, 5000, 2500, 2500, 12500, + 1, 100, 125000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 11811811, 118, 5000, 2500, 2500, 37500, + 1, 100, 375000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 90023593, 119, 5000, 2500, 2500, 50000, + 1, 100, 500000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 93028922, 120, 5000, 2500, 2500, 75000, + 1, 100, 750000, 0, 0, 0, 0, 1, 1000 + }, + { 0, 72707401, 121, 5000, 50, 50, 25000, + 1, 100, 250000, 50, 50, 0, 100, 1, 1000 + }, + { 0, 93040771, 122, 5000, 250, 250, 25000, + 1, 100, 250000, 250, 250, 0, 100, 1, 1000 + }, + { 0, 70220611, 123, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 52774811, 124, 5000, 1000, 1000, 25000, + 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000 + }, + { 0, 22492311, 125, 5000, 1500, 1500, 25000, + 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000 + }, + { 0, 35269337, 126, 5000, 500, 500, 12500, + 1, 100, 125000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 30140502, 127, 5000, 500, 500, 37500, + 1, 100, 375000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 49205455, 128, 5000, 500, 500, 50000, + 1, 100, 500000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 42958341, 129, 5000, 500, 500, 75000, + 1, 100, 750000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 25440925, 130, 5000, 500, 500, 12500, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 75294924, 131, 5000, 500, 500, 37500, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 4463965, 132, 5000, 500, 500, 50000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 13390427, 133, 5000, 500, 500, 75000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 95250971, 134, 1000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 54830522, 135, 2500, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 520593, 136, 7500, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 52900925, 137, 10000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 22603395, 138, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 50 + }, + { 0, 55253099, 139, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 250 + }, + { 0, 75357001, 140, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 500 + }, + { 0, 10072459, 141, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 2500 + }, + { 0, 55728492, 142, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 100, 1, 5000 + }, + { 0, 593043, 143, 5000, 500, 500, 25000, + 1, 100, 250000, 500, 500, 0, 0, 1, 1000 + }, + { 0, 94236572, 144, 5000, 500, 500, 25000, + 1, 10, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 94882955, 145, 5000, 500, 500, 25000, + 1, 1000, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 48489922, 146, 5000, 500, 500, 25000, + 1, 10000, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 75578374, 147, 5000, 500, 500, 25000, + -100, -1, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 44821152, 148, 5000, 500, 500, 25000, + -50, 49, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 45224103, 149, 5000, 500, 500, 25000, + 101, 200, 250000, 500, 500, 0, 100, 1, 1000 + }, + { 0, 63491741, 150, 5000, 500, 500, 25000, + 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000 + }, +}; + +void glp_netgen_prob(int nprob, int parm[1+15]) +{ int k; + if (!(101 <= nprob && nprob <= 150)) + xerror("glp_netgen_prob: nprob = %d; invalid problem instance " + "number\n", nprob); + for (k = 1; k <= 15; k++) + parm[k] = data[nprob-101][k]; + return; +} + +/**********************************************************************/ + +#if 0 +static int scan(char card[80+1], int pos, int len) +{ char buf[10+1]; + memcpy(buf, &card[pos-1], len); + buf[len] = '\0'; + return atoi(buf); +} + +int main(void) +{ int parm[1+15]; + char card[80+1]; + xassert(fgets(card, sizeof(card), stdin) == card); + parm[1] = scan(card, 1, 8); + parm[2] = scan(card, 9, 8); + xassert(fgets(card, sizeof(card), stdin) == card); + parm[3] = scan(card, 1, 5); + parm[4] = scan(card, 6, 5); + parm[5] = scan(card, 11, 5); + parm[6] = scan(card, 16, 5); + parm[7] = scan(card, 21, 5); + parm[8] = scan(card, 26, 5); + parm[9] = scan(card, 31, 10); + parm[10] = scan(card, 41, 5); + parm[11] = scan(card, 46, 5); + parm[12] = scan(card, 51, 5); + parm[13] = scan(card, 56, 5); + parm[14] = scan(card, 61, 10); + parm[15] = scan(card, 71, 10); + glp_netgen(NULL, 0, 0, 0, parm); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/npp.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/npp.c new file mode 100644 index 000000000..a7ae07c1a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/npp.c @@ -0,0 +1,143 @@ +/* npp.c (LP/MIP preprocessing) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +glp_prep *glp_npp_alloc_wksp(void) +{ /* allocate the preprocessor workspace */ + glp_prep *prep; + prep = npp_create_wksp(); + return prep; +} + +void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol, int names) +{ /* load original problem instance */ + if (prep->sol != 0) + xerror("glp_npp_load_prob: invalid call sequence (original ins" + "tance already loaded)\n"); + if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) + xerror("glp_npp_load_prob: sol = %d; invalid parameter\n", + sol); + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_npp_load_prob: names = %d; invalid parameter\n", + names); + npp_load_prob(prep, P, names, sol, GLP_OFF); + return; +} + +int glp_npp_preprocess1(glp_prep *prep, int hard) +{ /* perform basic LP/MIP preprocessing */ + if (prep->sol == 0) + xerror("glp_npp_preprocess1: invalid call sequence (original i" + "nstance not loaded yet)\n"); + if (prep->pool == NULL) + xerror("glp_npp_preprocess1: invalid call sequence (preprocess" + "ing already finished)\n"); + if (!(hard == GLP_ON || hard == GLP_OFF)) + xerror("glp_npp_preprocess1: hard = %d; invalid parameter\n", + hard); + return npp_process_prob(prep, hard); +} + +void glp_npp_build_prob(glp_prep *prep, glp_prob *Q) +{ /* build resultant problem instance */ + if (prep->sol == 0) + xerror("glp_npp_build_prob: invalid call sequence (original in" + "stance not loaded yet)\n"); + if (prep->pool == NULL) + xerror("glp_npp_build_prob: invalid call sequence (resultant i" + "nstance already built)\n"); + npp_build_prob(prep, Q); + return; +} + +void glp_npp_postprocess(glp_prep *prep, glp_prob *Q) +{ /* postprocess solution to resultant problem */ + if (prep->pool != NULL) + xerror("glp_npp_postprocess: invalid call sequence (resultant " + "instance not built yet)\n"); + if (!(prep->m == Q->m && prep->n == Q->n && prep->nnz == Q->nnz)) + xerror("glp_npp_postprocess: resultant instance mismatch\n"); + switch (prep->sol) + { case GLP_SOL: + if (glp_get_status(Q) != GLP_OPT) + xerror("glp_npp_postprocess: unable to recover non-optim" + "al basic solution\n"); + break; + case GLP_IPT: + if (glp_ipt_status(Q) != GLP_OPT) + xerror("glp_npp_postprocess: unable to recover non-optim" + "al interior-point solution\n"); + break; + case GLP_MIP: + if (!(glp_mip_status(Q) == GLP_OPT || glp_mip_status(Q) == + GLP_FEAS)) + xerror("glp_npp_postprocess: unable to recover integer n" + "on-feasible solution\n"); + break; + default: + xassert(prep != prep); + } + npp_postprocess(prep, Q); + return; +} + +void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P) +{ /* obtain solution to original problem */ + if (prep->pool != NULL) + xerror("glp_npp_obtain_sol: invalid call sequence (resultant i" + "nstance not built yet)\n"); + switch (prep->sol) + { case GLP_SOL: + if (prep->p_stat == 0 || prep->d_stat == 0) + xerror("glp_npp_obtain_sol: invalid call sequence (basic" + " solution not provided yet)\n"); + break; + case GLP_IPT: + if (prep->t_stat == 0) + xerror("glp_npp_obtain_sol: invalid call sequence (inter" + "ior-point solution not provided yet)\n"); + break; + case GLP_MIP: + if (prep->i_stat == 0) + xerror("glp_npp_obtain_sol: invalid call sequence (MIP s" + "olution not provided yet)\n"); + break; + default: + xassert(prep != prep); + } + if (!(prep->orig_dir == P->dir && prep->orig_m == P->m && + prep->orig_n == P->n && prep->orig_nnz == P->nnz)) + xerror("glp_npp_obtain_sol: original instance mismatch\n"); + npp_unload_sol(prep, P); + return; +} + +void glp_npp_free_wksp(glp_prep *prep) +{ /* free the preprocessor workspace */ + npp_delete_wksp(prep); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/pript.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/pript.c new file mode 100644 index 000000000..f123089df --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/pript.c @@ -0,0 +1,186 @@ +/* pript.c (write interior-point solution in printable format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +int glp_print_ipt(glp_prob *P, const char *fname) +{ /* write interior-point solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing interior-point solution to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_ipt_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "OPTIMAL" : + t == GLP_UNDEF ? "UNDEFINED" : + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->ipt_obj, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "------------- -------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(row->pval) <= 1e-9 ? 0.0 : row->pval); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + if (fabs(row->dval) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", row->dval); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "------------- -------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(col->pval) <= 1e-9 ? 0.0 : col->pval); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + if (fabs(col->dval) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", col->dval); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" + "E"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on column %d\n", + re_max, re_ind == 0 ? 0 : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") + ; + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prmip.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prmip.c new file mode 100644 index 000000000..885ed82ab --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prmip.c @@ -0,0 +1,155 @@ +/* prmip.c (write MIP solution in printable format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +int glp_print_mip(glp_prob *P, const char *fname) +{ /* write MIP solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing MIP solution to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:", + P->n, glp_get_num_int(P), glp_get_num_bin(P)); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_mip_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "INTEGER OPTIMAL" : + t == GLP_FEAS ? "INTEGER NON-OPTIMAL" : + t == GLP_NOFEAS ? "INTEGER EMPTY" : + t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->mip_obj, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name Activity Lower bound " + " Upper bound\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "-------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%3s", ""); + xfprintf(fp, "%13.6g ", + fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name Activity Lower bound " + " Upper bound\n"); + xfprintf(fp, "------ ------------ ------------- ------------- " + "-------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%s ", + col->kind == GLP_CV ? " " : + col->kind == GLP_IV ? "*" : "?"); + xfprintf(fp, "%13.6g ", + fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Integer feasibility conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE"); + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob.h b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob.h new file mode 100644 index 000000000..cc9389b57 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob.h @@ -0,0 +1,286 @@ +/* prob.h (LP/MIP problem object) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef PROB_H +#define PROB_H + +#include "avl.h" +#include "bfd.h" +#include "dmp.h" +#if 1 /* 28/III-2016 */ +#define GLP_UNDOC 1 +#endif +#include "glpk.h" + +typedef struct GLPROW GLPROW; +typedef struct GLPCOL GLPCOL; +typedef struct GLPAIJ GLPAIJ; + +#if 0 /* 04/IV-2016 */ +#define GLP_PROB_MAGIC 0xD7D9D6C2 +#endif + +struct glp_prob +{ /* LP/MIP problem object */ +#if 0 /* 04/IV-2016 */ + unsigned magic; + /* magic value used for debugging */ +#endif + DMP *pool; + /* memory pool to store problem object components */ + glp_tree *tree; + /* pointer to the search tree; set by the MIP solver when this + object is used in the tree as a core MIP object */ +#if 0 /* 08/III-2014 */ + void *parms; + /* reserved for backward compatibility */ +#endif + /*--------------------------------------------------------------*/ + /* LP/MIP data */ + char *name; + /* problem name (1 to 255 chars); NULL means no name is assigned + to the problem */ + char *obj; + /* objective function name (1 to 255 chars); NULL means no name + is assigned to the objective function */ + int dir; + /* optimization direction flag (objective "sense"): + GLP_MIN - minimization + GLP_MAX - maximization */ + double c0; + /* constant term of the objective function ("shift") */ + int m_max; + /* length of the array of rows (enlarged automatically) */ + int n_max; + /* length of the array of columns (enlarged automatically) */ + int m; + /* number of rows, 0 <= m <= m_max */ + int n; + /* number of columns, 0 <= n <= n_max */ + int nnz; + /* number of non-zero constraint coefficients, nnz >= 0 */ + GLPROW **row; /* GLPROW *row[1+m_max]; */ + /* row[i], 1 <= i <= m, is a pointer to i-th row */ + GLPCOL **col; /* GLPCOL *col[1+n_max]; */ + /* col[j], 1 <= j <= n, is a pointer to j-th column */ + AVL *r_tree; + /* row index to find rows by their names; NULL means this index + does not exist */ + AVL *c_tree; + /* column index to find columns by their names; NULL means this + index does not exist */ + /*--------------------------------------------------------------*/ + /* basis factorization (LP) */ + int valid; + /* the factorization is valid only if this flag is set */ + int *head; /* int head[1+m_max]; */ + /* basis header (valid only if the factorization is valid); + head[i] = k is the ordinal number of auxiliary (1 <= k <= m) + or structural (m+1 <= k <= m+n) variable which corresponds to + i-th basic variable xB[i], 1 <= i <= m */ +#if 0 /* 08/III-2014 */ + glp_bfcp *bfcp; + /* basis factorization control parameters; may be NULL */ +#endif + BFD *bfd; /* BFD bfd[1:m,1:m]; */ + /* basis factorization driver; may be NULL */ + /*--------------------------------------------------------------*/ + /* basic solution (LP) */ + int pbs_stat; + /* primal basic solution status: + GLP_UNDEF - primal solution is undefined + GLP_FEAS - primal solution is feasible + GLP_INFEAS - primal solution is infeasible + GLP_NOFEAS - no primal feasible solution exists */ + int dbs_stat; + /* dual basic solution status: + GLP_UNDEF - dual solution is undefined + GLP_FEAS - dual solution is feasible + GLP_INFEAS - dual solution is infeasible + GLP_NOFEAS - no dual feasible solution exists */ + double obj_val; + /* objective function value */ + int it_cnt; + /* simplex method iteration count; increases by one on performing + one simplex iteration */ + int some; + /* ordinal number of some auxiliary or structural variable having + certain property, 0 <= some <= m+n */ + /*--------------------------------------------------------------*/ + /* interior-point solution (LP) */ + int ipt_stat; + /* interior-point solution status: + GLP_UNDEF - interior solution is undefined + GLP_OPT - interior solution is optimal + GLP_INFEAS - interior solution is infeasible + GLP_NOFEAS - no feasible solution exists */ + double ipt_obj; + /* objective function value */ + /*--------------------------------------------------------------*/ + /* integer solution (MIP) */ + int mip_stat; + /* integer solution status: + GLP_UNDEF - integer solution is undefined + GLP_OPT - integer solution is optimal + GLP_FEAS - integer solution is feasible + GLP_NOFEAS - no integer solution exists */ + double mip_obj; + /* objective function value */ +}; + +struct GLPROW +{ /* LP/MIP row (auxiliary variable) */ + int i; + /* ordinal number (1 to m) assigned to this row */ + char *name; + /* row name (1 to 255 chars); NULL means no name is assigned to + this row */ + AVLNODE *node; + /* pointer to corresponding node in the row index; NULL means + that either the row index does not exist or this row has no + name assigned */ +#if 1 /* 20/IX-2008 */ + int level; + unsigned char origin; + unsigned char klass; +#endif + int type; + /* type of the auxiliary variable: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double lb; /* non-scaled */ + /* lower bound; if the row has no lower bound, lb is zero */ + double ub; /* non-scaled */ + /* upper bound; if the row has no upper bound, ub is zero */ + /* if the row type is GLP_FX, ub is equal to lb */ + GLPAIJ *ptr; /* non-scaled */ + /* pointer to doubly linked list of constraint coefficients which + are placed in this row */ + double rii; + /* diagonal element r[i,i] of scaling matrix R for this row; + if the scaling is not used, r[i,i] is 1 */ + int stat; + /* status of the auxiliary variable: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + int bind; + /* if the auxiliary variable is basic, head[bind] refers to this + row, otherwise, bind is 0; this attribute is valid only if the + basis factorization is valid */ + double prim; /* non-scaled */ + /* primal value of the auxiliary variable in basic solution */ + double dual; /* non-scaled */ + /* dual value of the auxiliary variable in basic solution */ + double pval; /* non-scaled */ + /* primal value of the auxiliary variable in interior solution */ + double dval; /* non-scaled */ + /* dual value of the auxiliary variable in interior solution */ + double mipx; /* non-scaled */ + /* primal value of the auxiliary variable in integer solution */ +}; + +struct GLPCOL +{ /* LP/MIP column (structural variable) */ + int j; + /* ordinal number (1 to n) assigned to this column */ + char *name; + /* column name (1 to 255 chars); NULL means no name is assigned + to this column */ + AVLNODE *node; + /* pointer to corresponding node in the column index; NULL means + that either the column index does not exist or the column has + no name assigned */ + int kind; + /* kind of the structural variable: + GLP_CV - continuous variable + GLP_IV - integer or binary variable */ + int type; + /* type of the structural variable: + GLP_FR - free variable + GLP_LO - variable with lower bound + GLP_UP - variable with upper bound + GLP_DB - double-bounded variable + GLP_FX - fixed variable */ + double lb; /* non-scaled */ + /* lower bound; if the column has no lower bound, lb is zero */ + double ub; /* non-scaled */ + /* upper bound; if the column has no upper bound, ub is zero */ + /* if the column type is GLP_FX, ub is equal to lb */ + double coef; /* non-scaled */ + /* objective coefficient at the structural variable */ + GLPAIJ *ptr; /* non-scaled */ + /* pointer to doubly linked list of constraint coefficients which + are placed in this column */ + double sjj; + /* diagonal element s[j,j] of scaling matrix S for this column; + if the scaling is not used, s[j,j] is 1 */ + int stat; + /* status of the structural variable: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + int bind; + /* if the structural variable is basic, head[bind] refers to + this column; otherwise, bind is 0; this attribute is valid only + if the basis factorization is valid */ + double prim; /* non-scaled */ + /* primal value of the structural variable in basic solution */ + double dual; /* non-scaled */ + /* dual value of the structural variable in basic solution */ + double pval; /* non-scaled */ + /* primal value of the structural variable in interior solution */ + double dval; /* non-scaled */ + /* dual value of the structural variable in interior solution */ + double mipx; /* non-scaled */ + /* primal value of the structural variable in integer solution */ +}; + +struct GLPAIJ +{ /* constraint coefficient a[i,j] */ + GLPROW *row; + /* pointer to row, where this coefficient is placed */ + GLPCOL *col; + /* pointer to column, where this coefficient is placed */ + double val; + /* numeric (non-zero) value of this coefficient */ + GLPAIJ *r_prev; + /* pointer to previous coefficient in the same row */ + GLPAIJ *r_next; + /* pointer to next coefficient in the same row */ + GLPAIJ *c_prev; + /* pointer to previous coefficient in the same column */ + GLPAIJ *c_next; + /* pointer to next coefficient in the same column */ +}; + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob1.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob1.c new file mode 100644 index 000000000..6afad442e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob1.c @@ -0,0 +1,1588 @@ +/* prob1.c (problem creating and modifying routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ + +#define M_MAX 100000000 /* = 100*10^6 */ +/* maximal number of rows in the problem object */ + +#define N_MAX 100000000 /* = 100*10^6 */ +/* maximal number of columns in the problem object */ + +#define NNZ_MAX 500000000 /* = 500*10^6 */ +/* maximal number of constraint coefficients in the problem object */ + +/*********************************************************************** +* NAME +* +* glp_create_prob - create problem object +* +* SYNOPSIS +* +* glp_prob *glp_create_prob(void); +* +* DESCRIPTION +* +* The routine glp_create_prob creates a new problem object, which is +* initially "empty", i.e. has no rows and columns. +* +* RETURNS +* +* The routine returns a pointer to the object created, which should be +* used in any subsequent operations on this object. */ + +static void create_prob(glp_prob *lp) +#if 0 /* 04/IV-2016 */ +{ lp->magic = GLP_PROB_MAGIC; +#else +{ +#endif + lp->pool = dmp_create_pool(); +#if 0 /* 08/III-2014 */ +#if 0 /* 17/XI-2009 */ + lp->cps = xmalloc(sizeof(struct LPXCPS)); + lpx_reset_parms(lp); +#else + lp->parms = NULL; +#endif +#endif + lp->tree = NULL; +#if 0 + lp->lwa = 0; + lp->cwa = NULL; +#endif + /* LP/MIP data */ + lp->name = NULL; + lp->obj = NULL; + lp->dir = GLP_MIN; + lp->c0 = 0.0; + lp->m_max = 100; + lp->n_max = 200; + lp->m = lp->n = 0; + lp->nnz = 0; + lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); + lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); + lp->r_tree = lp->c_tree = NULL; + /* basis factorization */ + lp->valid = 0; + lp->head = xcalloc(1+lp->m_max, sizeof(int)); +#if 0 /* 08/III-2014 */ + lp->bfcp = NULL; +#endif + lp->bfd = NULL; + /* basic solution (LP) */ + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->it_cnt = 0; + lp->some = 0; + /* interior-point solution (LP) */ + lp->ipt_stat = GLP_UNDEF; + lp->ipt_obj = 0.0; + /* integer solution (MIP) */ + lp->mip_stat = GLP_UNDEF; + lp->mip_obj = 0.0; + return; +} + +glp_prob *glp_create_prob(void) +{ glp_prob *lp; + lp = xmalloc(sizeof(glp_prob)); + create_prob(lp); + return lp; +} + +/*********************************************************************** +* NAME +* +* glp_set_prob_name - assign (change) problem name +* +* SYNOPSIS +* +* void glp_set_prob_name(glp_prob *lp, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_prob_name assigns a given symbolic name (1 up to +* 255 characters) to the specified problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing symbolic name of the problem object. */ + +void glp_set_prob_name(glp_prob *lp, const char *name) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_prob_name: operation not allowed\n"); + if (lp->name != NULL) + { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1); + lp->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_prob_name: problem name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_prob_name: problem name contains invalid" + " character(s)\n"); + } + lp->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(lp->name, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_name - assign (change) objective function name +* +* SYNOPSIS +* +* void glp_set_obj_name(glp_prob *lp, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_obj_name assigns a given symbolic name (1 up to +* 255 characters) to the objective function of the specified problem +* object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of the objective function. */ + +void glp_set_obj_name(glp_prob *lp, const char *name) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_name: operation not allowed\n"); + if (lp->obj != NULL) + { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1); + lp->obj = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_obj_name: objective name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_obj_name: objective name contains invali" + "d character(s)\n"); + } + lp->obj = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(lp->obj, name); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_dir - set (change) optimization direction flag +* +* SYNOPSIS +* +* void glp_set_obj_dir(glp_prob *lp, int dir); +* +* DESCRIPTION +* +* The routine glp_set_obj_dir sets (changes) optimization direction +* flag (i.e. "sense" of the objective function) as specified by the +* parameter dir: +* +* GLP_MIN - minimization; +* GLP_MAX - maximization. */ + +void glp_set_obj_dir(glp_prob *lp, int dir) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_dir: operation not allowed\n"); + if (!(dir == GLP_MIN || dir == GLP_MAX)) + xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n", + dir); + lp->dir = dir; + return; +} + +/*********************************************************************** +* NAME +* +* glp_add_rows - add new rows to problem object +* +* SYNOPSIS +* +* int glp_add_rows(glp_prob *lp, int nrs); +* +* DESCRIPTION +* +* The routine glp_add_rows adds nrs rows (constraints) to the specified +* problem object. New rows are always added to the end of the row list, +* so the ordinal numbers of existing rows remain unchanged. +* +* Being added each new row is initially free (unbounded) and has empty +* list of the constraint coefficients. +* +* RETURNS +* +* The routine glp_add_rows returns the ordinal number of the first new +* row added to the problem object. */ + +int glp_add_rows(glp_prob *lp, int nrs) +{ glp_tree *tree = lp->tree; + GLPROW *row; + int m_new, i; + /* determine new number of rows */ + if (nrs < 1) + xerror("glp_add_rows: nrs = %d; invalid number of rows\n", + nrs); + if (nrs > M_MAX - lp->m) + xerror("glp_add_rows: nrs = %d; too many rows\n", nrs); + m_new = lp->m + nrs; + /* increase the room, if necessary */ + if (lp->m_max < m_new) + { GLPROW **save = lp->row; + while (lp->m_max < m_new) + { lp->m_max += lp->m_max; + xassert(lp->m_max > 0); + } + lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); + memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *)); + xfree(save); + /* do not forget about the basis header */ + xfree(lp->head); + lp->head = xcalloc(1+lp->m_max, sizeof(int)); + } + /* add new rows to the end of the row list */ + for (i = lp->m+1; i <= m_new; i++) + { /* create row descriptor */ + lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW)); + row->i = i; + row->name = NULL; + row->node = NULL; +#if 1 /* 20/IX-2008 */ + row->level = 0; + row->origin = 0; + row->klass = 0; + if (tree != NULL) + { switch (tree->reason) + { case 0: + break; + case GLP_IROWGEN: + xassert(tree->curr != NULL); + row->level = tree->curr->level; + row->origin = GLP_RF_LAZY; + break; + case GLP_ICUTGEN: + xassert(tree->curr != NULL); + row->level = tree->curr->level; + row->origin = GLP_RF_CUT; + break; + default: + xassert(tree != tree); + } + } +#endif + row->type = GLP_FR; + row->lb = row->ub = 0.0; + row->ptr = NULL; + row->rii = 1.0; + row->stat = GLP_BS; +#if 0 + row->bind = -1; +#else + row->bind = 0; +#endif + row->prim = row->dual = 0.0; + row->pval = row->dval = 0.0; + row->mipx = 0.0; + } + /* set new number of rows */ + lp->m = m_new; + /* invalidate the basis factorization */ + lp->valid = 0; +#if 1 + if (tree != NULL && tree->reason != 0) tree->reopt = 1; +#endif + /* return the ordinal number of the first row added */ + return m_new - nrs + 1; +} + +/*********************************************************************** +* NAME +* +* glp_add_cols - add new columns to problem object +* +* SYNOPSIS +* +* int glp_add_cols(glp_prob *lp, int ncs); +* +* DESCRIPTION +* +* The routine glp_add_cols adds ncs columns (structural variables) to +* the specified problem object. New columns are always added to the end +* of the column list, so the ordinal numbers of existing columns remain +* unchanged. +* +* Being added each new column is initially fixed at zero and has empty +* list of the constraint coefficients. +* +* RETURNS +* +* The routine glp_add_cols returns the ordinal number of the first new +* column added to the problem object. */ + +int glp_add_cols(glp_prob *lp, int ncs) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + int n_new, j; + if (tree != NULL && tree->reason != 0) + xerror("glp_add_cols: operation not allowed\n"); + /* determine new number of columns */ + if (ncs < 1) + xerror("glp_add_cols: ncs = %d; invalid number of columns\n", + ncs); + if (ncs > N_MAX - lp->n) + xerror("glp_add_cols: ncs = %d; too many columns\n", ncs); + n_new = lp->n + ncs; + /* increase the room, if necessary */ + if (lp->n_max < n_new) + { GLPCOL **save = lp->col; + while (lp->n_max < n_new) + { lp->n_max += lp->n_max; + xassert(lp->n_max > 0); + } + lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); + memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *)); + xfree(save); + } + /* add new columns to the end of the column list */ + for (j = lp->n+1; j <= n_new; j++) + { /* create column descriptor */ + lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL)); + col->j = j; + col->name = NULL; + col->node = NULL; + col->kind = GLP_CV; + col->type = GLP_FX; + col->lb = col->ub = 0.0; + col->coef = 0.0; + col->ptr = NULL; + col->sjj = 1.0; + col->stat = GLP_NS; +#if 0 + col->bind = -1; +#else + col->bind = 0; /* the basis may remain valid */ +#endif + col->prim = col->dual = 0.0; + col->pval = col->dval = 0.0; + col->mipx = 0.0; + } + /* set new number of columns */ + lp->n = n_new; + /* return the ordinal number of the first column added */ + return n_new - ncs + 1; +} + +/*********************************************************************** +* NAME +* +* glp_set_row_name - assign (change) row name +* +* SYNOPSIS +* +* void glp_set_row_name(glp_prob *lp, int i, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_row_name assigns a given symbolic name (1 up to +* 255 characters) to i-th row (auxiliary variable) of the specified +* problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of i-th row. */ + +void glp_set_row_name(glp_prob *lp, int i, const char *name) +{ glp_tree *tree = lp->tree; + GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_name: i = %d; row number out of range\n", + i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { xassert(tree->curr != NULL); + xassert(row->level == tree->curr->level); + } + if (row->name != NULL) + { if (row->node != NULL) + { xassert(lp->r_tree != NULL); + avl_delete_node(lp->r_tree, row->node); + row->node = NULL; + } + dmp_free_atom(lp->pool, row->name, strlen(row->name)+1); + row->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_row_name: i = %d; row name too long\n", + i); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_row_name: i = %d: row name contains inva" + "lid character(s)\n", i); + } + row->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(row->name, name); + if (lp->r_tree != NULL) + { xassert(row->node == NULL); + row->node = avl_insert_node(lp->r_tree, row->name); + avl_set_node_link(row->node, row); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_name - assign (change) column name +* +* SYNOPSIS +* +* void glp_set_col_name(glp_prob *lp, int j, const char *name); +* +* DESCRIPTION +* +* The routine glp_set_col_name assigns a given symbolic name (1 up to +* 255 characters) to j-th column (structural variable) of the specified +* problem object. +* +* If the parameter name is NULL or empty string, the routine erases an +* existing name of j-th column. */ + +void glp_set_col_name(glp_prob *lp, int j, const char *name) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_col_name: operation not allowed\n"); + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_name: j = %d; column number out of range\n" + , j); + col = lp->col[j]; + if (col->name != NULL) + { if (col->node != NULL) + { xassert(lp->c_tree != NULL); + avl_delete_node(lp->c_tree, col->node); + col->node = NULL; + } + dmp_free_atom(lp->pool, col->name, strlen(col->name)+1); + col->name = NULL; + } + if (!(name == NULL || name[0] == '\0')) + { int k; + for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_set_col_name: j = %d; column name too long\n" + , j); + if (iscntrl((unsigned char)name[k])) + xerror("glp_set_col_name: j = %d: column name contains i" + "nvalid character(s)\n", j); + } + col->name = dmp_get_atom(lp->pool, strlen(name)+1); + strcpy(col->name, name); + if (lp->c_tree != NULL && col->name != NULL) + { xassert(col->node == NULL); + col->node = avl_insert_node(lp->c_tree, col->name); + avl_set_node_link(col->node, col); + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_row_bnds - set (change) row bounds +* +* SYNOPSIS +* +* void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, +* double ub); +* +* DESCRIPTION +* +* The routine glp_set_row_bnds sets (changes) the type and bounds of +* i-th row (auxiliary variable) of the specified problem object. +* +* Parameters type, lb, and ub specify the type, lower bound, and upper +* bound, respectively, as follows: +* +* Type Bounds Comments +* ------------------------------------------------------ +* GLP_FR -inf < x < +inf Free variable +* GLP_LO lb <= x < +inf Variable with lower bound +* GLP_UP -inf < x <= ub Variable with upper bound +* GLP_DB lb <= x <= ub Double-bounded variable +* GLP_FX x = lb Fixed variable +* +* where x is the auxiliary variable associated with i-th row. +* +* If the row has no lower bound, the parameter lb is ignored. If the +* row has no upper bound, the parameter ub is ignored. If the row is +* an equality constraint (i.e. the corresponding auxiliary variable is +* of fixed type), only the parameter lb is used while the parameter ub +* is ignored. */ + +void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, + double ub) +{ GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_bnds: i = %d; row number out of range\n", + i); + row = lp->row[i]; + row->type = type; + switch (type) + { case GLP_FR: + row->lb = row->ub = 0.0; + if (row->stat != GLP_BS) row->stat = GLP_NF; + break; + case GLP_LO: + row->lb = lb, row->ub = 0.0; + if (row->stat != GLP_BS) row->stat = GLP_NL; + break; + case GLP_UP: + row->lb = 0.0, row->ub = ub; + if (row->stat != GLP_BS) row->stat = GLP_NU; + break; + case GLP_DB: + row->lb = lb, row->ub = ub; + if (!(row->stat == GLP_BS || + row->stat == GLP_NL || row->stat == GLP_NU)) + row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); + break; + case GLP_FX: + row->lb = row->ub = lb; + if (row->stat != GLP_BS) row->stat = GLP_NS; + break; + default: + xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty" + "pe\n", i, type); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_bnds - set (change) column bounds +* +* SYNOPSIS +* +* void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, +* double ub); +* +* DESCRIPTION +* +* The routine glp_set_col_bnds sets (changes) the type and bounds of +* j-th column (structural variable) of the specified problem object. +* +* Parameters type, lb, and ub specify the type, lower bound, and upper +* bound, respectively, as follows: +* +* Type Bounds Comments +* ------------------------------------------------------ +* GLP_FR -inf < x < +inf Free variable +* GLP_LO lb <= x < +inf Variable with lower bound +* GLP_UP -inf < x <= ub Variable with upper bound +* GLP_DB lb <= x <= ub Double-bounded variable +* GLP_FX x = lb Fixed variable +* +* where x is the structural variable associated with j-th column. +* +* If the column has no lower bound, the parameter lb is ignored. If the +* column has no upper bound, the parameter ub is ignored. If the column +* is of fixed type, only the parameter lb is used while the parameter +* ub is ignored. */ + +void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, + double ub) +{ GLPCOL *col; + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_bnds: j = %d; column number out of range\n" + , j); + col = lp->col[j]; + col->type = type; + switch (type) + { case GLP_FR: + col->lb = col->ub = 0.0; + if (col->stat != GLP_BS) col->stat = GLP_NF; + break; + case GLP_LO: + col->lb = lb, col->ub = 0.0; + if (col->stat != GLP_BS) col->stat = GLP_NL; + break; + case GLP_UP: + col->lb = 0.0, col->ub = ub; + if (col->stat != GLP_BS) col->stat = GLP_NU; + break; + case GLP_DB: + col->lb = lb, col->ub = ub; + if (!(col->stat == GLP_BS || + col->stat == GLP_NL || col->stat == GLP_NU)) + col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); + break; + case GLP_FX: + col->lb = col->ub = lb; + if (col->stat != GLP_BS) col->stat = GLP_NS; + break; + default: + xerror("glp_set_col_bnds: j = %d; type = %d; invalid column" + " type\n", j, type); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_obj_coef - set (change) obj. coefficient or constant term +* +* SYNOPSIS +* +* void glp_set_obj_coef(glp_prob *lp, int j, double coef); +* +* DESCRIPTION +* +* The routine glp_set_obj_coef sets (changes) objective coefficient at +* j-th column (structural variable) of the specified problem object. +* +* If the parameter j is 0, the routine sets (changes) the constant term +* ("shift") of the objective function. */ + +void glp_set_obj_coef(glp_prob *lp, int j, double coef) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_obj_coef: operation not allowed\n"); + if (!(0 <= j && j <= lp->n)) + xerror("glp_set_obj_coef: j = %d; column number out of range\n" + , j); + if (j == 0) + lp->c0 = coef; + else + lp->col[j]->coef = coef; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_mat_row - set (replace) row of the constraint matrix +* +* SYNOPSIS +* +* void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine glp_set_mat_row stores (replaces) the contents of i-th +* row of the constraint matrix of the specified problem object. +* +* Column indices and numeric values of new row elements must be placed +* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where +* 0 <= len <= n is the new length of i-th row, n is the current number +* of columns in the problem object. Elements with identical column +* indices are not allowed. Zero elements are allowed, but they are not +* stored in the constraint matrix. +* +* If the parameter len is zero, the parameters ind and/or val can be +* specified as NULL. */ + +void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], + const double val[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int j, k; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_mat_row: i = %d; row number out of range\n", + i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { xassert(tree->curr != NULL); + xassert(row->level == tree->curr->level); + } + /* remove all existing elements from i-th row */ + while (row->ptr != NULL) + { /* take next element in the row */ + aij = row->ptr; + /* remove the element from the row list */ + row->ptr = aij->r_next; + /* obtain pointer to corresponding column */ + col = aij->col; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + /* if the corresponding column is basic, invalidate the basis + factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + } + /* store new contents of i-th row */ + if (!(0 <= len && len <= lp->n)) + xerror("glp_set_mat_row: i = %d; len = %d; invalid row length " + "\n", i, len); + if (len > NNZ_MAX - lp->nnz) + xerror("glp_set_mat_row: i = %d; len = %d; too many constraint" + " coefficients\n", i, len); + for (k = 1; k <= len; k++) + { /* take number j of corresponding column */ + j = ind[k]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index" + " out of range\n", i, k, j); + col = lp->col[j]; + /* if there is element with the same column index, it can only + be found in the beginning of j-th column list */ + if (col->ptr != NULL && col->ptr->row->i == i) + xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co" + "lumn indices not allowed\n", i, k, j); + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = val[k]; + /* add the new element to the beginning of i-th row and j-th + column lists */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + /* if the corresponding column is basic, invalidate the basis + factorization */ + if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0; + } + /* remove zero elements from i-th row */ + for (aij = row->ptr; aij != NULL; aij = next) + { next = aij->r_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = next; + else + aij->r_prev->r_next = next; + if (next == NULL) + ; + else + next->r_prev = aij->r_prev; + /* remove the element from the column list */ + xassert(aij->c_prev == NULL); + aij->col->ptr = aij->c_next; + if (aij->c_next != NULL) aij->c_next->c_prev = NULL; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_mat_col - set (replace) column of the constraint matrix +* +* SYNOPSIS +* +* void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], +* const double val[]); +* +* DESCRIPTION +* +* The routine glp_set_mat_col stores (replaces) the contents of j-th +* column of the constraint matrix of the specified problem object. +* +* Row indices and numeric values of new column elements must be placed +* in locations ind[1], ..., ind[len] and val[1], ..., val[len], where +* 0 <= len <= m is the new length of j-th column, m is the current +* number of rows in the problem object. Elements with identical column +* indices are not allowed. Zero elements are allowed, but they are not +* stored in the constraint matrix. +* +* If the parameter len is zero, the parameters ind and/or val can be +* specified as NULL. */ + +void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], + const double val[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int i, k; + if (tree != NULL && tree->reason != 0) + xerror("glp_set_mat_col: operation not allowed\n"); + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_mat_col: j = %d; column number out of range\n", + j); + col = lp->col[j]; + /* remove all existing elements from j-th column */ + while (col->ptr != NULL) + { /* take next element in the column */ + aij = col->ptr; + /* remove the element from the column list */ + col->ptr = aij->c_next; + /* obtain pointer to corresponding row */ + row = aij->row; + /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + /* store new contents of j-th column */ + if (!(0 <= len && len <= lp->m)) + xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng" + "th\n", j, len); + if (len > NNZ_MAX - lp->nnz) + xerror("glp_set_mat_col: j = %d; len = %d; too many constraint" + " coefficients\n", j, len); + for (k = 1; k <= len; k++) + { /* take number i of corresponding row */ + i = ind[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou" + "t of range\n", j, k, i); + row = lp->row[i]; + /* if there is element with the same row index, it can only be + found in the beginning of i-th row list */ + if (row->ptr != NULL && row->ptr->col->j == j) + xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro" + "w indices not allowed\n", j, k, i); + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = val[k]; + /* add the new element to the beginning of i-th row and j-th + column lists */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + } + /* remove zero elements from j-th column */ + for (aij = col->ptr; aij != NULL; aij = next) + { next = aij->c_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + xassert(aij->r_prev == NULL); + aij->row->ptr = aij->r_next; + if (aij->r_next != NULL) aij->r_next->r_prev = NULL; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + col->ptr = next; + else + aij->c_prev->c_next = next; + if (next == NULL) + ; + else + next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + /* if j-th column is basic, invalidate the basis factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_load_matrix - load (replace) the whole constraint matrix +* +* SYNOPSIS +* +* void glp_load_matrix(glp_prob *lp, int ne, const int ia[], +* const int ja[], const double ar[]); +* +* DESCRIPTION +* +* The routine glp_load_matrix loads the constraint matrix passed in +* the arrays ia, ja, and ar into the specified problem object. Before +* loading the current contents of the constraint matrix is destroyed. +* +* Constraint coefficients (elements of the constraint matrix) must be +* specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne, +* where ia[k] is the row index, ja[k] is the column index, ar[k] is a +* numeric value of corresponding constraint coefficient. The parameter +* ne specifies the total number of (non-zero) elements in the matrix +* to be loaded. Coefficients with identical indices are not allowed. +* Zero coefficients are allowed, however, they are not stored in the +* constraint matrix. +* +* If the parameter ne is zero, the parameters ia, ja, and ar can be +* specified as NULL. */ + +void glp_load_matrix(glp_prob *lp, int ne, const int ia[], + const int ja[], const double ar[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij, *next; + int i, j, k; + if (tree != NULL && tree->reason != 0) + xerror("glp_load_matrix: operation not allowed\n"); + /* clear the constraint matrix */ + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + xassert(lp->nnz == 0); + for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL; + /* load the new contents of the constraint matrix and build its + row lists */ + if (ne < 0) + xerror("glp_load_matrix: ne = %d; invalid number of constraint" + " coefficients\n", ne); + if (ne > NNZ_MAX) + xerror("glp_load_matrix: ne = %d; too many constraint coeffici" + "ents\n", ne); + for (k = 1; k <= ne; k++) + { /* take indices of new element */ + i = ia[k], j = ja[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_load_matrix: ia[%d] = %d; row index out of rang" + "e\n", k, i); + row = lp->row[i]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_load_matrix: ja[%d] = %d; column index out of r" + "ange\n", k, j); + col = lp->col[j]; + /* create new element */ + aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; + aij->row = row; + aij->col = col; + aij->val = ar[k]; + /* add the new element to the beginning of i-th row list */ + aij->r_prev = NULL; + aij->r_next = row->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + row->ptr = aij; + } + xassert(lp->nnz == ne); + /* build column lists of the constraint matrix and check elements + with identical indices */ + for (i = 1; i <= lp->m; i++) + { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { /* obtain pointer to corresponding column */ + col = aij->col; + /* if there is element with identical indices, it can only + be found in the beginning of j-th column list */ + if (col->ptr != NULL && col->ptr->row->i == i) + { for (k = 1; k <= ne; k++) + if (ia[k] == i && ja[k] == col->j) break; + xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat" + "e indices not allowed\n", k, i, k, col->j); + } + /* add the element to the beginning of j-th column list */ + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + col->ptr = aij; + } + } + /* remove zero elements from the constraint matrix */ + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + for (aij = row->ptr; aij != NULL; aij = next) + { next = aij->r_next; + if (aij->val == 0.0) + { /* remove the element from the row list */ + if (aij->r_prev == NULL) + row->ptr = next; + else + aij->r_prev->r_next = next; + if (next == NULL) + ; + else + next->r_prev = aij->r_prev; + /* remove the element from the column list */ + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + /* return the element to the memory pool */ + dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; + } + } + } + /* invalidate the basis factorization */ + lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_check_dup - check for duplicate elements in sparse matrix +* +* SYNOPSIS +* +* int glp_check_dup(int m, int n, int ne, const int ia[], +* const int ja[]); +* +* DESCRIPTION +* +* The routine glp_check_dup checks for duplicate elements (that is, +* elements with identical indices) in a sparse matrix specified in the +* coordinate format. +* +* The parameters m and n specifies, respectively, the number of rows +* and columns in the matrix, m >= 0, n >= 0. +* +* The parameter ne specifies the number of (structurally) non-zero +* elements in the matrix, ne >= 0. +* +* Elements of the matrix are specified as doublets (ia[k],ja[k]) for +* k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index. +* +* The routine glp_check_dup can be used prior to a call to the routine +* glp_load_matrix to check that the constraint matrix to be loaded has +* no duplicate elements. +* +* RETURNS +* +* The routine glp_check_dup returns one of the following values: +* +* 0 - the matrix has no duplicate elements; +* +* -k - indices ia[k] or/and ja[k] are out of range; +* +* +k - element (ia[k],ja[k]) is duplicate. */ + +int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]) +{ int i, j, k, *ptr, *next, ret; + char *flag; + if (m < 0) + xerror("glp_check_dup: m = %d; invalid parameter\n"); + if (n < 0) + xerror("glp_check_dup: n = %d; invalid parameter\n"); + if (ne < 0) + xerror("glp_check_dup: ne = %d; invalid parameter\n"); + if (ne > 0 && ia == NULL) + xerror("glp_check_dup: ia = %p; invalid parameter\n", ia); + if (ne > 0 && ja == NULL) + xerror("glp_check_dup: ja = %p; invalid parameter\n", ja); + for (k = 1; k <= ne; k++) + { i = ia[k], j = ja[k]; + if (!(1 <= i && i <= m && 1 <= j && j <= n)) + { ret = -k; + goto done; + } + } + if (m == 0 || n == 0) + { ret = 0; + goto done; + } + /* allocate working arrays */ + ptr = xcalloc(1+m, sizeof(int)); + next = xcalloc(1+ne, sizeof(int)); + flag = xcalloc(1+n, sizeof(char)); + /* build row lists */ + for (i = 1; i <= m; i++) + ptr[i] = 0; + for (k = 1; k <= ne; k++) + { i = ia[k]; + next[k] = ptr[i]; + ptr[i] = k; + } + /* clear column flags */ + for (j = 1; j <= n; j++) + flag[j] = 0; + /* check for duplicate elements */ + for (i = 1; i <= m; i++) + { for (k = ptr[i]; k != 0; k = next[k]) + { j = ja[k]; + if (flag[j]) + { /* find first element (i,j) */ + for (k = 1; k <= ne; k++) + if (ia[k] == i && ja[k] == j) break; + xassert(k <= ne); + /* find next (duplicate) element (i,j) */ + for (k++; k <= ne; k++) + if (ia[k] == i && ja[k] == j) break; + xassert(k <= ne); + ret = +k; + goto skip; + } + flag[j] = 1; + } + /* clear column flags */ + for (k = ptr[i]; k != 0; k = next[k]) + flag[ja[k]] = 0; + } + /* no duplicate element found */ + ret = 0; +skip: /* free working arrays */ + xfree(ptr); + xfree(next); + xfree(flag); +done: return ret; +} + +/*********************************************************************** +* NAME +* +* glp_sort_matrix - sort elements of the constraint matrix +* +* SYNOPSIS +* +* void glp_sort_matrix(glp_prob *P); +* +* DESCRIPTION +* +* The routine glp_sort_matrix sorts elements of the constraint matrix +* rebuilding its row and column linked lists. On exit from the routine +* the constraint matrix is not changed, however, elements in the row +* linked lists become ordered by ascending column indices, and the +* elements in the column linked lists become ordered by ascending row +* indices. */ + +void glp_sort_matrix(glp_prob *P) +{ GLPAIJ *aij; + int i, j; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_sort_matrix: P = %p; invalid problem object\n", + P); +#endif + /* rebuild row linked lists */ + for (i = P->m; i >= 1; i--) + P->row[i]->ptr = NULL; + for (j = P->n; j >= 1; j--) + { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row->i; + aij->r_prev = NULL; + aij->r_next = P->row[i]->ptr; + if (aij->r_next != NULL) aij->r_next->r_prev = aij; + P->row[i]->ptr = aij; + } + } + /* rebuild column linked lists */ + for (j = P->n; j >= 1; j--) + P->col[j]->ptr = NULL; + for (i = P->m; i >= 1; i--) + { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + aij->c_prev = NULL; + aij->c_next = P->col[j]->ptr; + if (aij->c_next != NULL) aij->c_next->c_prev = aij; + P->col[j]->ptr = aij; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_rows - delete rows from problem object +* +* SYNOPSIS +* +* void glp_del_rows(glp_prob *lp, int nrs, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_rows deletes rows from the specified problem +* object. Ordinal numbers of rows to be deleted should be placed in +* locations num[1], ..., num[nrs], where nrs > 0. +* +* Note that deleting rows involves changing ordinal numbers of other +* rows remaining in the problem object. New ordinal numbers of the +* remaining rows are assigned under the assumption that the original +* order of rows is not changed. */ + +void glp_del_rows(glp_prob *lp, int nrs, const int num[]) +{ glp_tree *tree = lp->tree; + GLPROW *row; + int i, k, m_new; + /* mark rows to be deleted */ + if (!(1 <= nrs && nrs <= lp->m)) + xerror("glp_del_rows: nrs = %d; invalid number of rows\n", + nrs); + for (k = 1; k <= nrs; k++) + { /* take the number of row to be deleted */ + i = num[k]; + /* obtain pointer to i-th row */ + if (!(1 <= i && i <= lp->m)) + xerror("glp_del_rows: num[%d] = %d; row number out of range" + "\n", k, i); + row = lp->row[i]; + if (tree != NULL && tree->reason != 0) + { if (!(tree->reason == GLP_IROWGEN || + tree->reason == GLP_ICUTGEN)) + xerror("glp_del_rows: operation not allowed\n"); + xassert(tree->curr != NULL); + if (row->level != tree->curr->level) + xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" + "elete row created not in current subproblem\n", k,i); + if (row->stat != GLP_BS) + xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" + "elete active row (constraint)\n", k, i); + tree->reinv = 1; + } + /* check that the row is not marked yet */ + if (row->i == 0) + xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n" + "ot allowed\n", k, i); + /* erase symbolic name assigned to the row */ + glp_set_row_name(lp, i, NULL); + xassert(row->node == NULL); + /* erase corresponding row of the constraint matrix */ + glp_set_mat_row(lp, i, 0, NULL, NULL); + xassert(row->ptr == NULL); + /* mark the row to be deleted */ + row->i = 0; + } + /* delete all marked rows from the row list */ + m_new = 0; + for (i = 1; i <= lp->m; i++) + { /* obtain pointer to i-th row */ + row = lp->row[i]; + /* check if the row is marked */ + if (row->i == 0) + { /* it is marked, delete it */ + dmp_free_atom(lp->pool, row, sizeof(GLPROW)); + } + else + { /* it is not marked; keep it */ + row->i = ++m_new; + lp->row[row->i] = row; + } + } + /* set new number of rows */ + lp->m = m_new; + /* invalidate the basis factorization */ + lp->valid = 0; + return; +} + +/*********************************************************************** +* NAME +* +* glp_del_cols - delete columns from problem object +* +* SYNOPSIS +* +* void glp_del_cols(glp_prob *lp, int ncs, const int num[]); +* +* DESCRIPTION +* +* The routine glp_del_cols deletes columns from the specified problem +* object. Ordinal numbers of columns to be deleted should be placed in +* locations num[1], ..., num[ncs], where ncs > 0. +* +* Note that deleting columns involves changing ordinal numbers of +* other columns remaining in the problem object. New ordinal numbers +* of the remaining columns are assigned under the assumption that the +* original order of columns is not changed. */ + +void glp_del_cols(glp_prob *lp, int ncs, const int num[]) +{ glp_tree *tree = lp->tree; + GLPCOL *col; + int j, k, n_new; + if (tree != NULL && tree->reason != 0) + xerror("glp_del_cols: operation not allowed\n"); + /* mark columns to be deleted */ + if (!(1 <= ncs && ncs <= lp->n)) + xerror("glp_del_cols: ncs = %d; invalid number of columns\n", + ncs); + for (k = 1; k <= ncs; k++) + { /* take the number of column to be deleted */ + j = num[k]; + /* obtain pointer to j-th column */ + if (!(1 <= j && j <= lp->n)) + xerror("glp_del_cols: num[%d] = %d; column number out of ra" + "nge", k, j); + col = lp->col[j]; + /* check that the column is not marked yet */ + if (col->j == 0) + xerror("glp_del_cols: num[%d] = %d; duplicate column number" + "s not allowed\n", k, j); + /* erase symbolic name assigned to the column */ + glp_set_col_name(lp, j, NULL); + xassert(col->node == NULL); + /* erase corresponding column of the constraint matrix */ + glp_set_mat_col(lp, j, 0, NULL, NULL); + xassert(col->ptr == NULL); + /* mark the column to be deleted */ + col->j = 0; + /* if it is basic, invalidate the basis factorization */ + if (col->stat == GLP_BS) lp->valid = 0; + } + /* delete all marked columns from the column list */ + n_new = 0; + for (j = 1; j <= lp->n; j++) + { /* obtain pointer to j-th column */ + col = lp->col[j]; + /* check if the column is marked */ + if (col->j == 0) + { /* it is marked; delete it */ + dmp_free_atom(lp->pool, col, sizeof(GLPCOL)); + } + else + { /* it is not marked; keep it */ + col->j = ++n_new; + lp->col[col->j] = col; + } + } + /* set new number of columns */ + lp->n = n_new; + /* if the basis header is still valid, adjust it */ + if (lp->valid) + { int m = lp->m; + int *head = lp->head; + for (j = 1; j <= n_new; j++) + { k = lp->col[j]->bind; + if (k != 0) + { xassert(1 <= k && k <= m); + head[k] = m + j; + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_copy_prob - copy problem object content +* +* SYNOPSIS +* +* void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +* +* DESCRIPTION +* +* The routine glp_copy_prob copies the content of the problem object +* prob to the problem object dest. +* +* The parameter names is a flag. If it is non-zero, the routine also +* copies all symbolic names; otherwise, if it is zero, symbolic names +* are not copied. */ + +void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names) +{ glp_tree *tree = dest->tree; + glp_bfcp bfcp; + int i, j, len, *ind; + double *val; + if (tree != NULL && tree->reason != 0) + xerror("glp_copy_prob: operation not allowed\n"); + if (dest == prob) + xerror("glp_copy_prob: copying problem object to itself not al" + "lowed\n"); + if (!(names == GLP_ON || names == GLP_OFF)) + xerror("glp_copy_prob: names = %d; invalid parameter\n", + names); + glp_erase_prob(dest); + if (names && prob->name != NULL) + glp_set_prob_name(dest, prob->name); + if (names && prob->obj != NULL) + glp_set_obj_name(dest, prob->obj); + dest->dir = prob->dir; + dest->c0 = prob->c0; + if (prob->m > 0) + glp_add_rows(dest, prob->m); + if (prob->n > 0) + glp_add_cols(dest, prob->n); + glp_get_bfcp(prob, &bfcp); + glp_set_bfcp(dest, &bfcp); + dest->pbs_stat = prob->pbs_stat; + dest->dbs_stat = prob->dbs_stat; + dest->obj_val = prob->obj_val; + dest->some = prob->some; + dest->ipt_stat = prob->ipt_stat; + dest->ipt_obj = prob->ipt_obj; + dest->mip_stat = prob->mip_stat; + dest->mip_obj = prob->mip_obj; + for (i = 1; i <= prob->m; i++) + { GLPROW *to = dest->row[i]; + GLPROW *from = prob->row[i]; + if (names && from->name != NULL) + glp_set_row_name(dest, i, from->name); + to->type = from->type; + to->lb = from->lb; + to->ub = from->ub; + to->rii = from->rii; + to->stat = from->stat; + to->prim = from->prim; + to->dual = from->dual; + to->pval = from->pval; + to->dval = from->dval; + to->mipx = from->mipx; + } + ind = xcalloc(1+prob->m, sizeof(int)); + val = xcalloc(1+prob->m, sizeof(double)); + for (j = 1; j <= prob->n; j++) + { GLPCOL *to = dest->col[j]; + GLPCOL *from = prob->col[j]; + if (names && from->name != NULL) + glp_set_col_name(dest, j, from->name); + to->kind = from->kind; + to->type = from->type; + to->lb = from->lb; + to->ub = from->ub; + to->coef = from->coef; + len = glp_get_mat_col(prob, j, ind, val); + glp_set_mat_col(dest, j, len, ind, val); + to->sjj = from->sjj; + to->stat = from->stat; + to->prim = from->prim; + to->dual = from->dual; + to->pval = from->pval; + to->dval = from->dval; + to->mipx = from->mipx; + } + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_erase_prob - erase problem object content +* +* SYNOPSIS +* +* void glp_erase_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_erase_prob erases the content of the specified +* problem object. The effect of this operation is the same as if the +* problem object would be deleted with the routine glp_delete_prob and +* then created anew with the routine glp_create_prob, with exception +* that the handle (pointer) to the problem object remains valid. */ + +static void delete_prob(glp_prob *lp); + +void glp_erase_prob(glp_prob *lp) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_erase_prob: operation not allowed\n"); + delete_prob(lp); + create_prob(lp); + return; +} + +/*********************************************************************** +* NAME +* +* glp_delete_prob - delete problem object +* +* SYNOPSIS +* +* void glp_delete_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_delete_prob deletes the specified problem object and +* frees all the memory allocated to it. */ + +static void delete_prob(glp_prob *lp) +#if 0 /* 04/IV-2016 */ +{ lp->magic = 0x3F3F3F3F; +#else +{ +#endif + dmp_delete_pool(lp->pool); +#if 0 /* 08/III-2014 */ +#if 0 /* 17/XI-2009 */ + xfree(lp->cps); +#else + if (lp->parms != NULL) xfree(lp->parms); +#endif +#endif + xassert(lp->tree == NULL); +#if 0 + if (lp->cwa != NULL) xfree(lp->cwa); +#endif + xfree(lp->row); + xfree(lp->col); + if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree); + if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree); + xfree(lp->head); +#if 0 /* 08/III-2014 */ + if (lp->bfcp != NULL) xfree(lp->bfcp); +#endif + if (lp->bfd != NULL) bfd_delete_it(lp->bfd); + return; +} + +void glp_delete_prob(glp_prob *lp) +{ glp_tree *tree = lp->tree; + if (tree != NULL && tree->reason != 0) + xerror("glp_delete_prob: operation not allowed\n"); + delete_prob(lp); + xfree(lp); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob2.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob2.c new file mode 100644 index 000000000..d352db128 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob2.c @@ -0,0 +1,491 @@ +/* prob2.c (problem retrieving routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_get_prob_name - retrieve problem name +* +* SYNOPSIS +* +* const char *glp_get_prob_name(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_prob_name returns a pointer to an internal +* buffer, which contains symbolic name of the problem. However, if the +* problem has no assigned name, the routine returns NULL. */ + +const char *glp_get_prob_name(glp_prob *lp) +{ char *name; + name = lp->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_name - retrieve objective function name +* +* SYNOPSIS +* +* const char *glp_get_obj_name(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_name returns a pointer to an internal +* buffer, which contains a symbolic name of the objective function. +* However, if the objective function has no assigned name, the routine +* returns NULL. */ + +const char *glp_get_obj_name(glp_prob *lp) +{ char *name; + name = lp->obj; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_dir - retrieve optimization direction flag +* +* SYNOPSIS +* +* int glp_get_obj_dir(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_dir returns the optimization direction flag +* (i.e. "sense" of the objective function): +* +* GLP_MIN - minimization; +* GLP_MAX - maximization. */ + +int glp_get_obj_dir(glp_prob *lp) +{ int dir = lp->dir; + return dir; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_rows - retrieve number of rows +* +* SYNOPSIS +* +* int glp_get_num_rows(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_rows returns the current number of rows in +* the specified problem object. */ + +int glp_get_num_rows(glp_prob *lp) +{ int m = lp->m; + return m; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_cols - retrieve number of columns +* +* SYNOPSIS +* +* int glp_get_num_cols(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_cols returns the current number of columns +* in the specified problem object. */ + +int glp_get_num_cols(glp_prob *lp) +{ int n = lp->n; + return n; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_name - retrieve row name +* +* SYNOPSIS +* +* const char *glp_get_row_name(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_name returns a pointer to an internal +* buffer, which contains symbolic name of i-th row. However, if i-th +* row has no assigned name, the routine returns NULL. */ + +const char *glp_get_row_name(glp_prob *lp, int i) +{ char *name; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_name: i = %d; row number out of range\n", + i); + name = lp->row[i]->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_name - retrieve column name +* +* SYNOPSIS +* +* const char *glp_get_col_name(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_name returns a pointer to an internal +* buffer, which contains symbolic name of j-th column. However, if j-th +* column has no assigned name, the routine returns NULL. */ + +const char *glp_get_col_name(glp_prob *lp, int j) +{ char *name; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_name: j = %d; column number out of range\n" + , j); + name = lp->col[j]->name; + return name; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_type - retrieve row type +* +* SYNOPSIS +* +* int glp_get_row_type(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_type returns the type of i-th row, i.e. the +* type of corresponding auxiliary variable, as follows: +* +* GLP_FR - free (unbounded) variable; +* GLP_LO - variable with lower bound; +* GLP_UP - variable with upper bound; +* GLP_DB - double-bounded variable; +* GLP_FX - fixed variable. */ + +int glp_get_row_type(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_type: i = %d; row number out of range\n", + i); + return lp->row[i]->type; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_lb - retrieve row lower bound +* +* SYNOPSIS +* +* double glp_get_row_lb(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_lb returns the lower bound of i-th row, i.e. +* the lower bound of corresponding auxiliary variable. However, if the +* row has no lower bound, the routine returns -DBL_MAX. */ + +double glp_get_row_lb(glp_prob *lp, int i) +{ double lb; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_lb: i = %d; row number out of range\n", i); + switch (lp->row[i]->type) + { case GLP_FR: + case GLP_UP: + lb = -DBL_MAX; break; + case GLP_LO: + case GLP_DB: + case GLP_FX: + lb = lp->row[i]->lb; break; + default: + xassert(lp != lp); + } + return lb; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_ub - retrieve row upper bound +* +* SYNOPSIS +* +* double glp_get_row_ub(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_ub returns the upper bound of i-th row, i.e. +* the upper bound of corresponding auxiliary variable. However, if the +* row has no upper bound, the routine returns +DBL_MAX. */ + +double glp_get_row_ub(glp_prob *lp, int i) +{ double ub; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_ub: i = %d; row number out of range\n", i); + switch (lp->row[i]->type) + { case GLP_FR: + case GLP_LO: + ub = +DBL_MAX; break; + case GLP_UP: + case GLP_DB: + case GLP_FX: + ub = lp->row[i]->ub; break; + default: + xassert(lp != lp); + } + return ub; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_type - retrieve column type +* +* SYNOPSIS +* +* int glp_get_col_type(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_type returns the type of j-th column, i.e. +* the type of corresponding structural variable, as follows: +* +* GLP_FR - free (unbounded) variable; +* GLP_LO - variable with lower bound; +* GLP_UP - variable with upper bound; +* GLP_DB - double-bounded variable; +* GLP_FX - fixed variable. */ + +int glp_get_col_type(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_type: j = %d; column number out of range\n" + , j); + return lp->col[j]->type; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_lb - retrieve column lower bound +* +* SYNOPSIS +* +* double glp_get_col_lb(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_lb returns the lower bound of j-th column, +* i.e. the lower bound of corresponding structural variable. However, +* if the column has no lower bound, the routine returns -DBL_MAX. */ + +double glp_get_col_lb(glp_prob *lp, int j) +{ double lb; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_lb: j = %d; column number out of range\n", + j); + switch (lp->col[j]->type) + { case GLP_FR: + case GLP_UP: + lb = -DBL_MAX; break; + case GLP_LO: + case GLP_DB: + case GLP_FX: + lb = lp->col[j]->lb; break; + default: + xassert(lp != lp); + } + return lb; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_ub - retrieve column upper bound +* +* SYNOPSIS +* +* double glp_get_col_ub(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_ub returns the upper bound of j-th column, +* i.e. the upper bound of corresponding structural variable. However, +* if the column has no upper bound, the routine returns +DBL_MAX. */ + +double glp_get_col_ub(glp_prob *lp, int j) +{ double ub; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_ub: j = %d; column number out of range\n", + j); + switch (lp->col[j]->type) + { case GLP_FR: + case GLP_LO: + ub = +DBL_MAX; break; + case GLP_UP: + case GLP_DB: + case GLP_FX: + ub = lp->col[j]->ub; break; + default: + xassert(lp != lp); + } + return ub; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_coef - retrieve obj. coefficient or constant term +* +* SYNOPSIS +* +* double glp_get_obj_coef(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_obj_coef returns the objective coefficient at +* j-th structural variable (column) of the specified problem object. +* +* If the parameter j is zero, the routine returns the constant term +* ("shift") of the objective function. */ + +double glp_get_obj_coef(glp_prob *lp, int j) +{ if (!(0 <= j && j <= lp->n)) + xerror("glp_get_obj_coef: j = %d; column number out of range\n" + , j); + return j == 0 ? lp->c0 : lp->col[j]->coef; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_nz - retrieve number of constraint coefficients +* +* SYNOPSIS +* +* int glp_get_num_nz(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_num_nz returns the number of (non-zero) elements +* in the constraint matrix of the specified problem object. */ + +int glp_get_num_nz(glp_prob *lp) +{ int nnz = lp->nnz; + return nnz; +} + +/*********************************************************************** +* NAME +* +* glp_get_mat_row - retrieve row of the constraint matrix +* +* SYNOPSIS +* +* int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_get_mat_row scans (non-zero) elements of i-th row +* of the constraint matrix of the specified problem object and stores +* their column indices and numeric values to locations ind[1], ..., +* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= n +* is the number of elements in i-th row, n is the number of columns. +* +* The parameter ind and/or val can be specified as NULL, in which case +* corresponding information is not stored. +* +* RETURNS +* +* The routine glp_get_mat_row returns the length len, i.e. the number +* of (non-zero) elements in i-th row. */ + +int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]) +{ GLPAIJ *aij; + int len; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_mat_row: i = %d; row number out of range\n", + i); + len = 0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { len++; + if (ind != NULL) ind[len] = aij->col->j; + if (val != NULL) val[len] = aij->val; + } + xassert(len <= lp->n); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_get_mat_col - retrieve column of the constraint matrix +* +* SYNOPSIS +* +* int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_get_mat_col scans (non-zero) elements of j-th column +* of the constraint matrix of the specified problem object and stores +* their row indices and numeric values to locations ind[1], ..., +* ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= m +* is the number of elements in j-th column, m is the number of rows. +* +* The parameter ind or/and val can be specified as NULL, in which case +* corresponding information is not stored. +* +* RETURNS +* +* The routine glp_get_mat_col returns the length len, i.e. the number +* of (non-zero) elements in j-th column. */ + +int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]) +{ GLPAIJ *aij; + int len; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_mat_col: j = %d; column number out of range\n", + j); + len = 0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { len++; + if (ind != NULL) ind[len] = aij->row->i; + if (val != NULL) val[len] = aij->val; + } + xassert(len <= lp->m); + return len; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob3.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob3.c new file mode 100644 index 000000000..d7edbd337 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob3.c @@ -0,0 +1,166 @@ +/* prob3.c (problem row/column searching routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_create_index - create the name index +* +* SYNOPSIS +* +* void glp_create_index(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_create_index creates the name index for the +* specified problem object. The name index is an auxiliary data +* structure, which is intended to quickly (i.e. for logarithmic time) +* find rows and columns by their names. +* +* This routine can be called at any time. If the name index already +* exists, the routine does nothing. */ + +void glp_create_index(glp_prob *lp) +{ GLPROW *row; + GLPCOL *col; + int i, j; + /* create row name index */ + if (lp->r_tree == NULL) + { lp->r_tree = avl_create_tree(avl_strcmp, NULL); + for (i = 1; i <= lp->m; i++) + { row = lp->row[i]; + xassert(row->node == NULL); + if (row->name != NULL) + { row->node = avl_insert_node(lp->r_tree, row->name); + avl_set_node_link(row->node, row); + } + } + } + /* create column name index */ + if (lp->c_tree == NULL) + { lp->c_tree = avl_create_tree(avl_strcmp, NULL); + for (j = 1; j <= lp->n; j++) + { col = lp->col[j]; + xassert(col->node == NULL); + if (col->name != NULL) + { col->node = avl_insert_node(lp->c_tree, col->name); + avl_set_node_link(col->node, col); + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_find_row - find row by its name +* +* SYNOPSIS +* +* int glp_find_row(glp_prob *lp, const char *name); +* +* RETURNS +* +* The routine glp_find_row returns the ordinal number of a row, +* which is assigned (by the routine glp_set_row_name) the specified +* symbolic name. If no such row exists, the routine returns 0. */ + +int glp_find_row(glp_prob *lp, const char *name) +{ AVLNODE *node; + int i = 0; + if (lp->r_tree == NULL) + xerror("glp_find_row: row name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(lp->r_tree, name); + if (node != NULL) + i = ((GLPROW *)avl_get_node_link(node))->i; + } + return i; +} + +/*********************************************************************** +* NAME +* +* glp_find_col - find column by its name +* +* SYNOPSIS +* +* int glp_find_col(glp_prob *lp, const char *name); +* +* RETURNS +* +* The routine glp_find_col returns the ordinal number of a column, +* which is assigned (by the routine glp_set_col_name) the specified +* symbolic name. If no such column exists, the routine returns 0. */ + +int glp_find_col(glp_prob *lp, const char *name) +{ AVLNODE *node; + int j = 0; + if (lp->c_tree == NULL) + xerror("glp_find_col: column name index does not exist\n"); + if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) + { node = avl_find_node(lp->c_tree, name); + if (node != NULL) + j = ((GLPCOL *)avl_get_node_link(node))->j; + } + return j; +} + +/*********************************************************************** +* NAME +* +* glp_delete_index - delete the name index +* +* SYNOPSIS +* +* void glp_delete_index(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_delete_index deletes the name index previously +* created by the routine glp_create_index and frees the memory +* allocated to this auxiliary data structure. +* +* This routine can be called at any time. If the name index does not +* exist, the routine does nothing. */ + +void glp_delete_index(glp_prob *lp) +{ int i, j; + /* delete row name index */ + if (lp->r_tree != NULL) + { for (i = 1; i <= lp->m; i++) lp->row[i]->node = NULL; + avl_delete_tree(lp->r_tree), lp->r_tree = NULL; + } + /* delete column name index */ + if (lp->c_tree != NULL) + { for (j = 1; j <= lp->n; j++) lp->col[j]->node = NULL; + avl_delete_tree(lp->c_tree), lp->c_tree = NULL; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob4.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob4.c new file mode 100644 index 000000000..8c2b5ae5d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob4.c @@ -0,0 +1,156 @@ +/* prob4.c (problem scaling routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_set_rii - set (change) row scale factor +* +* SYNOPSIS +* +* void glp_set_rii(glp_prob *lp, int i, double rii); +* +* DESCRIPTION +* +* The routine glp_set_rii sets (changes) the scale factor r[i,i] for +* i-th row of the specified problem object. */ + +void glp_set_rii(glp_prob *lp, int i, double rii) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_set_rii: i = %d; row number out of range\n", i); + if (rii <= 0.0) + xerror("glp_set_rii: i = %d; rii = %g; invalid scale factor\n", + i, rii); + if (lp->valid && lp->row[i]->rii != rii) + { GLPAIJ *aij; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { if (aij->col->stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + break; + } + } + } + lp->row[i]->rii = rii; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set sjj - set (change) column scale factor +* +* SYNOPSIS +* +* void glp_set_sjj(glp_prob *lp, int j, double sjj); +* +* DESCRIPTION +* +* The routine glp_set_sjj sets (changes) the scale factor s[j,j] for +* j-th column of the specified problem object. */ + +void glp_set_sjj(glp_prob *lp, int j, double sjj) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_set_sjj: j = %d; column number out of range\n", j); + if (sjj <= 0.0) + xerror("glp_set_sjj: j = %d; sjj = %g; invalid scale factor\n", + j, sjj); + if (lp->valid && lp->col[j]->sjj != sjj && lp->col[j]->stat == + GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + lp->col[j]->sjj = sjj; + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_rii - retrieve row scale factor +* +* SYNOPSIS +* +* double glp_get_rii(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_rii returns current scale factor r[i,i] for i-th +* row of the specified problem object. */ + +double glp_get_rii(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_rii: i = %d; row number out of range\n", i); + return lp->row[i]->rii; +} + +/*********************************************************************** +* NAME +* +* glp_get_sjj - retrieve column scale factor +* +* SYNOPSIS +* +* double glp_get_sjj(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_sjj returns current scale factor s[j,j] for j-th +* column of the specified problem object. */ + +double glp_get_sjj(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_sjj: j = %d; column number out of range\n", j); + return lp->col[j]->sjj; +} + +/*********************************************************************** +* NAME +* +* glp_unscale_prob - unscale problem data +* +* SYNOPSIS +* +* void glp_unscale_prob(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_unscale_prob performs unscaling of problem data for +* the specified problem object. +* +* "Unscaling" means replacing the current scaling matrices R and S by +* unity matrices that cancels the scaling effect. */ + +void glp_unscale_prob(glp_prob *lp) +{ int m = glp_get_num_rows(lp); + int n = glp_get_num_cols(lp); + int i, j; + for (i = 1; i <= m; i++) glp_set_rii(lp, i, 1.0); + for (j = 1; j <= n; j++) glp_set_sjj(lp, j, 1.0); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prob5.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob5.c new file mode 100644 index 000000000..1c1d3160a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prob5.c @@ -0,0 +1,168 @@ +/* prob5.c (LP problem basis constructing routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_set_row_stat - set (change) row status +* +* SYNOPSIS +* +* void glp_set_row_stat(glp_prob *lp, int i, int stat); +* +* DESCRIPTION +* +* The routine glp_set_row_stat sets (changes) status of the auxiliary +* variable associated with i-th row. +* +* The new status of the auxiliary variable should be specified by the +* parameter stat as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable; +* GLP_NU - non-basic variable on its upper bound; if the variable is +* not double-bounded, this means the same as GLP_NL (only in +* case of this routine); +* GLP_NF - the same as GLP_NL (only in case of this routine); +* GLP_NS - the same as GLP_NL (only in case of this routine). */ + +void glp_set_row_stat(glp_prob *lp, int i, int stat) +{ GLPROW *row; + if (!(1 <= i && i <= lp->m)) + xerror("glp_set_row_stat: i = %d; row number out of range\n", + i); + if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || + stat == GLP_NF || stat == GLP_NS)) + xerror("glp_set_row_stat: i = %d; stat = %d; invalid status\n", + i, stat); + row = lp->row[i]; + if (stat != GLP_BS) + { switch (row->type) + { case GLP_FR: stat = GLP_NF; break; + case GLP_LO: stat = GLP_NL; break; + case GLP_UP: stat = GLP_NU; break; + case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; + case GLP_FX: stat = GLP_NS; break; + default: xassert(row != row); + } + } + if (row->stat == GLP_BS && stat != GLP_BS || + row->stat != GLP_BS && stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + row->stat = stat; + return; +} + +/*********************************************************************** +* NAME +* +* glp_set_col_stat - set (change) column status +* +* SYNOPSIS +* +* void glp_set_col_stat(glp_prob *lp, int j, int stat); +* +* DESCRIPTION +* +* The routine glp_set_col_stat sets (changes) status of the structural +* variable associated with j-th column. +* +* The new status of the structural variable should be specified by the +* parameter stat as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable; +* GLP_NU - non-basic variable on its upper bound; if the variable is +* not double-bounded, this means the same as GLP_NL (only in +* case of this routine); +* GLP_NF - the same as GLP_NL (only in case of this routine); +* GLP_NS - the same as GLP_NL (only in case of this routine). */ + +void glp_set_col_stat(glp_prob *lp, int j, int stat) +{ GLPCOL *col; + if (!(1 <= j && j <= lp->n)) + xerror("glp_set_col_stat: j = %d; column number out of range\n" + , j); + if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || + stat == GLP_NF || stat == GLP_NS)) + xerror("glp_set_col_stat: j = %d; stat = %d; invalid status\n", + j, stat); + col = lp->col[j]; + if (stat != GLP_BS) + { switch (col->type) + { case GLP_FR: stat = GLP_NF; break; + case GLP_LO: stat = GLP_NL; break; + case GLP_UP: stat = GLP_NU; break; + case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; + case GLP_FX: stat = GLP_NS; break; + default: xassert(col != col); + } + } + if (col->stat == GLP_BS && stat != GLP_BS || + col->stat != GLP_BS && stat == GLP_BS) + { /* invalidate the basis factorization */ + lp->valid = 0; + } + col->stat = stat; + return; +} + +/*********************************************************************** +* NAME +* +* glp_std_basis - construct standard initial LP basis +* +* SYNOPSIS +* +* void glp_std_basis(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_std_basis builds the "standard" (trivial) initial +* basis for the specified problem object. +* +* In the "standard" basis all auxiliary variables are basic, and all +* structural variables are non-basic. */ + +void glp_std_basis(glp_prob *lp) +{ int i, j; + /* make all auxiliary variables basic */ + for (i = 1; i <= lp->m; i++) + glp_set_row_stat(lp, i, GLP_BS); + /* make all structural variables non-basic */ + for (j = 1; j <= lp->n; j++) + { GLPCOL *col = lp->col[j]; + if (col->type == GLP_DB && fabs(col->lb) > fabs(col->ub)) + glp_set_col_stat(lp, j, GLP_NU); + else + glp_set_col_stat(lp, j, GLP_NL); + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prrngs.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prrngs.c new file mode 100644 index 000000000..41a141ff7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prrngs.c @@ -0,0 +1,302 @@ +/* prrngs.c (print sensitivity analysis report) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +static char *format(char buf[13+1], double x) +{ /* format floating-point number in MPS/360-like style */ + if (x == -DBL_MAX) + strcpy(buf, " -Inf"); + else if (x == +DBL_MAX) + strcpy(buf, " +Inf"); + else if (fabs(x) <= 999999.99998) + { sprintf(buf, "%13.5f", x); +#if 1 + if (strcmp(buf, " 0.00000") == 0 || + strcmp(buf, " -0.00000") == 0) + strcpy(buf, " . "); + else if (memcmp(buf, " 0.", 8) == 0) + memcpy(buf, " .", 8); + else if (memcmp(buf, " -0.", 8) == 0) + memcpy(buf, " -.", 8); +#endif + } + else + sprintf(buf, "%13.6g", x); + return buf; +} + +int glp_print_ranges(glp_prob *P, int len, const int list[], + int flags, const char *fname) +{ /* print sensitivity analysis report */ + glp_file *fp = NULL; + GLPROW *row; + GLPCOL *col; + int m, n, pass, k, t, numb, type, stat, var1, var2, count, page, + ret; + double lb, ub, slack, coef, prim, dual, value1, value2, coef1, + coef2, obj1, obj2; + const char *name, *limit; + char buf[13+1]; + /* sanity checks */ +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_print_ranges: P = %p; invalid problem object\n", + P); +#endif + m = P->m, n = P->n; + if (len < 0) + xerror("glp_print_ranges: len = %d; invalid list length\n", + len); + if (len > 0) + { if (list == NULL) + xerror("glp_print_ranges: list = %p: invalid parameter\n", + list); + for (t = 1; t <= len; t++) + { k = list[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_print_ranges: list[%d] = %d; row/column numb" + "er out of range\n", t, k); + } + } + if (flags != 0) + xerror("glp_print_ranges: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_print_ranges: fname = %p; invalid parameter\n", + fname); + if (glp_get_status(P) != GLP_OPT) + { xprintf("glp_print_ranges: optimal basic solution required\n"); + ret = 1; + goto done; + } + if (!glp_bf_exists(P)) + { xprintf("glp_print_ranges: basis factorization required\n"); + ret = 2; + goto done; + } + /* start reporting */ + xprintf("Write sensitivity analysis report to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 3; + goto done; + } + page = count = 0; + for (pass = 1; pass <= 2; pass++) + for (t = 1; t <= (len == 0 ? m+n : len); t++) + { if (t == 1) count = 0; + k = (len == 0 ? t : list[t]); + if (pass == 1 && k > m || pass == 2 && k <= m) + continue; + if (count == 0) + { xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa" + "ge%4d\n", glp_version(), "", ++page); + xfprintf(fp, "\n"); + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->obj_val, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " + "%s\n", "No.", pass == 1 ? "Row name" : "Column name", + "St", "Activity", pass == 1 ? "Slack" : "Obj coef", + "Lower bound", "Activity", "Obj coef", "Obj value at", + "Limiting"); + xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " + "%s\n", "", "", "", "", "Marginal", "Upper bound", + "range", "range", "break point", "variable"); + xfprintf(fp, "------ ------------ -- ------------- --------" + "----- ------------- ------------- ------------- ------" + "------- ------------\n"); + } + if (pass == 1) + { numb = k; + xassert(1 <= numb && numb <= m); + row = P->row[numb]; + name = row->name; + type = row->type; + lb = glp_get_row_lb(P, numb); + ub = glp_get_row_ub(P, numb); + coef = 0.0; + stat = row->stat; + prim = row->prim; + if (type == GLP_FR) + slack = - prim; + else if (type == GLP_LO) + slack = lb - prim; + else if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + slack = ub - prim; + dual = row->dual; + } + else + { numb = k - m; + xassert(1 <= numb && numb <= n); + col = P->col[numb]; + name = col->name; + lb = glp_get_col_lb(P, numb); + ub = glp_get_col_ub(P, numb); + coef = col->coef; + stat = col->stat; + prim = col->prim; + slack = 0.0; + dual = col->dual; + } + if (stat != GLP_BS) + { glp_analyze_bound(P, k, &value1, &var1, &value2, &var2); + if (stat == GLP_NF) + coef1 = coef2 = coef; + else if (stat == GLP_NS) + coef1 = -DBL_MAX, coef2 = +DBL_MAX; + else if (stat == GLP_NL && P->dir == GLP_MIN || + stat == GLP_NU && P->dir == GLP_MAX) + coef1 = coef - dual, coef2 = +DBL_MAX; + else + coef1 = -DBL_MAX, coef2 = coef - dual; + if (value1 == -DBL_MAX) + { if (dual < -1e-9) + obj1 = +DBL_MAX; + else if (dual > +1e-9) + obj1 = -DBL_MAX; + else + obj1 = P->obj_val; + } + else + obj1 = P->obj_val + dual * (value1 - prim); + if (value2 == +DBL_MAX) + { if (dual < -1e-9) + obj2 = -DBL_MAX; + else if (dual > +1e-9) + obj2 = +DBL_MAX; + else + obj2 = P->obj_val; + } + else + obj2 = P->obj_val + dual * (value2 - prim); + } + else + { glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2, + &var2, &value2); + if (coef1 == -DBL_MAX) + { if (prim < -1e-9) + obj1 = +DBL_MAX; + else if (prim > +1e-9) + obj1 = -DBL_MAX; + else + obj1 = P->obj_val; + } + else + obj1 = P->obj_val + (coef1 - coef) * prim; + if (coef2 == +DBL_MAX) + { if (prim < -1e-9) + obj2 = -DBL_MAX; + else if (prim > +1e-9) + obj2 = +DBL_MAX; + else + obj2 = P->obj_val; + } + else + obj2 = P->obj_val + (coef2 - coef) * prim; + } + /*** first line ***/ + /* row/column number */ + xfprintf(fp, "%6d", numb); + /* row/column name */ + xfprintf(fp, " %-12.12s", name == NULL ? "" : name); + if (name != NULL && strlen(name) > 12) + xfprintf(fp, "%s\n%6s %12s", name+12, "", ""); + /* row/column status */ + xfprintf(fp, " %2s", + stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" : + stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" : + stat == GLP_NS ? "NS" : "??"); + /* row/column activity */ + xfprintf(fp, " %s", format(buf, prim)); + /* row slack, column objective coefficient */ + xfprintf(fp, " %s", format(buf, k <= m ? slack : coef)); + /* row/column lower bound */ + xfprintf(fp, " %s", format(buf, lb)); + /* row/column activity range */ + xfprintf(fp, " %s", format(buf, value1)); + /* row/column objective coefficient range */ + xfprintf(fp, " %s", format(buf, coef1)); + /* objective value at break point */ + xfprintf(fp, " %s", format(buf, obj1)); + /* limiting variable name */ + if (var1 != 0) + { if (var1 <= m) + limit = glp_get_row_name(P, var1); + else + limit = glp_get_col_name(P, var1 - m); + if (limit != NULL) + xfprintf(fp, " %s", limit); + } + xfprintf(fp, "\n"); + /*** second line ***/ + xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", ""); + /* row/column reduced cost */ + xfprintf(fp, " %s", format(buf, dual)); + /* row/column upper bound */ + xfprintf(fp, " %s", format(buf, ub)); + /* row/column activity range */ + xfprintf(fp, " %s", format(buf, value2)); + /* row/column objective coefficient range */ + xfprintf(fp, " %s", format(buf, coef2)); + /* objective value at break point */ + xfprintf(fp, " %s", format(buf, obj2)); + /* limiting variable name */ + if (var2 != 0) + { if (var2 <= m) + limit = glp_get_row_name(P, var2); + else + limit = glp_get_col_name(P, var2 - m); + if (limit != NULL) + xfprintf(fp, " %s", limit); + } + xfprintf(fp, "\n"); + xfprintf(fp, "\n"); + /* print 10 items per page */ + count = (count + 1) % 10; + } + xfprintf(fp, "End of report\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 4; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/prsol.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/prsol.c new file mode 100644 index 000000000..d785dc2e9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/prsol.c @@ -0,0 +1,202 @@ +/* prsol.c (write basic solution in printable format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +int glp_print_sol(glp_prob *P, const char *fname) +{ /* write basic solution in printable format */ + glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, t, ae_ind, re_ind, ret; + double ae_max, re_max; + xprintf("Writing basic solution to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "%-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name); + xfprintf(fp, "%-12s%d\n", "Rows:", P->m); + xfprintf(fp, "%-12s%d\n", "Columns:", P->n); + xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); + t = glp_get_status(P); + xfprintf(fp, "%-12s%s\n", "Status:", + t == GLP_OPT ? "OPTIMAL" : + t == GLP_FEAS ? "FEASIBLE" : + t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : + t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : + t == GLP_UNBND ? "UNBOUNDED" : + t == GLP_UNDEF ? "UNDEFINED" : "???"); + xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->obj_val, + P->dir == GLP_MIN ? "MINimum" : + P->dir == GLP_MAX ? "MAXimum" : "???"); + xfprintf(fp, "\n"); + xfprintf(fp, " No. Row name St Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ -- ------------- ------------- " + "------------- -------------\n"); + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + xfprintf(fp, "%6d ", i); + if (row->name == NULL || strlen(row->name) <= 12) + xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); + else + xfprintf(fp, "%s\n%20s", row->name, ""); + xfprintf(fp, "%s ", + row->stat == GLP_BS ? "B " : + row->stat == GLP_NL ? "NL" : + row->stat == GLP_NU ? "NU" : + row->stat == GLP_NF ? "NF" : + row->stat == GLP_NS ? "NS" : "??"); + xfprintf(fp, "%13.6g ", + fabs(row->prim) <= 1e-9 ? 0.0 : row->prim); + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + xfprintf(fp, "%13.6g ", row->lb); + else + xfprintf(fp, "%13s ", ""); + if (row->type == GLP_UP || row->type == GLP_DB) + xfprintf(fp, "%13.6g ", row->ub); + else + xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); + if (row->stat != GLP_BS) + { if (fabs(row->dual) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", row->dual); + } + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, " No. Column name St Activity Lower bound " + " Upper bound Marginal\n"); + xfprintf(fp, "------ ------------ -- ------------- ------------- " + "------------- -------------\n"); + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + xfprintf(fp, "%6d ", j); + if (col->name == NULL || strlen(col->name) <= 12) + xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); + else + xfprintf(fp, "%s\n%20s", col->name, ""); + xfprintf(fp, "%s ", + col->stat == GLP_BS ? "B " : + col->stat == GLP_NL ? "NL" : + col->stat == GLP_NU ? "NU" : + col->stat == GLP_NF ? "NF" : + col->stat == GLP_NS ? "NS" : "??"); + xfprintf(fp, "%13.6g ", + fabs(col->prim) <= 1e-9 ? 0.0 : col->prim); + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + xfprintf(fp, "%13.6g ", col->lb); + else + xfprintf(fp, "%13s ", ""); + if (col->type == GLP_UP || col->type == GLP_DB) + xfprintf(fp, "%13.6g ", col->ub); + else + xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); + if (col->stat != GLP_BS) + { if (fabs(col->dual) <= 1e-9) + xfprintf(fp, "%13s", "< eps"); + else + xfprintf(fp, "%13.6g ", col->dual); + } + xfprintf(fp, "\n"); + } + xfprintf(fp, "\n"); + xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", + ae_max, ae_ind); + xfprintf(fp, " max.rel.err = %.2e on row %d\n", + re_max, re_ind); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" + "E"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", + ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on column %d\n", + re_max, re_ind == 0 ? 0 : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); + xfprintf(fp, "\n"); + glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, + &re_ind); + xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", + ae_max, ae_ind <= P->m ? "row" : "column", + ae_ind <= P->m ? ae_ind : ae_ind - P->m); + xfprintf(fp, " max.rel.err = %.2e on %s %d\n", + re_max, re_ind <= P->m ? "row" : "column", + re_ind <= P->m ? re_ind : re_ind - P->m); + xfprintf(fp, "%8s%s\n", "", + re_max <= 1e-9 ? "High quality" : + re_max <= 1e-6 ? "Medium quality" : + re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") + ; + xfprintf(fp, "\n"); + xfprintf(fp, "End of output\n"); +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdasn.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdasn.c new file mode 100644 index 000000000..05dcb9fc2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdasn.c @@ -0,0 +1,164 @@ +/* rdasn.c (read assignment problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "glpk.h" +#include "misc.h" + +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +/*********************************************************************** +* NAME +* +* glp_read_asnprob - read assignment problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_asnprob reads assignment problem data in DIMACS +* format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname) +{ DMX _csa, *csa = &_csa; + glp_vertex *v; + glp_arc *a; + int nv, na, n1, i, j, k, ret = 0; + double cost; + char *flag = NULL; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_read_asnprob: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_read_asnprob: a_cost = %d; invalid offset\n", + a_cost); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading assignment problem data from '%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "asn") != 0) + error(csa, "wrong problem designator; 'asn' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + n1 = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of node %d", i); + flag[i] = 1, n1++; + end_of_line(csa); + } + xprintf( + "Assignment problem has %d + %d = %d node%s and %d arc%s\n", + n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (v_set >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + k = (flag[i] ? 0 : 1); + memcpy((char *)v->data + v_set, &k, sizeof(int)); + } + } + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; 'a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + if (!flag[i]) + error(csa, "node %d cannot be a starting node", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + if (flag[j]) + error(csa, "node %d cannot be an ending node", j); + read_field(csa); + if (str2num(csa->field, &cost) != 0) + error(csa, "arc cost missing or invalid"); + check_int(csa, cost); + a = glp_add_arc(G, i, j); + if (a_cost >= 0) + memcpy((char *)a->data + a_cost, &cost, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcc.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcc.c new file mode 100644 index 000000000..c63d60d86 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcc.c @@ -0,0 +1,162 @@ +/* rdcc.c (read graph in DIMACS clique/coloring format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "glpk.h" +#include "misc.h" + +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +/*********************************************************************** +* NAME +* +* glp_read_ccdata - read graph in DIMACS clique/coloring format +* +* SYNOPSIS +* +* int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_ccdata reads an (undirected) graph in DIMACS +* clique/coloring format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) +{ DMX _csa, *csa = &_csa; + glp_vertex *v; + int i, j, k, nv, ne, ret = 0; + double w; + char *flag = NULL; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n", + v_wgt); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading graph from '%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "edge") != 0) + error(csa, "wrong problem designator; 'edge' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of vertices missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &ne) == 0 && ne >= 0)) + error(csa, "number of edges missing or invalid"); + xprintf("Graph has %d vert%s and %d edge%s\n", + nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + if (v_wgt >= 0) + { w = 1.0; + for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_wgt, &w, sizeof(double)); + } + } + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "vertex number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "vertex number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of vertex %d", i); + read_field(csa); + if (str2num(csa->field, &w) != 0) + error(csa, "vertex weight missing or invalid"); + check_int(csa, w); + if (v_wgt >= 0) + { v = G->v[i]; + memcpy((char *)v->data + v_wgt, &w, sizeof(double)); + } + flag[i] = 1; + end_of_line(csa); + } + xfree(flag), flag = NULL; + /* read edge descriptor lines */ + for (k = 1; k <= ne; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "e") != 0) + error(csa, "wrong line designator; 'e' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "first vertex number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "first vertex number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "second vertex number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "second vertex number %d out of range", j); + glp_add_arc(G, i, j); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/**********************************************************************/ + +int glp_read_graph(glp_graph *G, const char *fname) +{ return + glp_read_ccdata(G, -1, fname); +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcnf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcnf.c new file mode 100644 index 000000000..acab50fe7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdcnf.c @@ -0,0 +1,136 @@ +/* rdcnf.c (read CNF-SAT problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +int glp_read_cnfsat(glp_prob *P, const char *fname) +{ /* read CNF-SAT problem data in DIMACS format */ + DMX _csa, *csa = &_csa; + int m, n, i, j, len, neg, rhs, ret = 0, *ind = NULL; + double *val = NULL; + char *map = NULL; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_cnfsat: P = %p; invalid problem object\n", + P); +#endif + if (fname == NULL) + xerror("glp_read_cnfsat: fname = %p; invalid parameter\n", + fname); + glp_erase_prob(P); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading CNF-SAT problem data from '%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "cnf") != 0) + error(csa, "wrong problem designator; 'cnf' expected\n"); + read_field(csa); + if (!(str2int(csa->field, &n) == 0 && n >= 0)) + error(csa, "number of variables missing or invalid\n"); + read_field(csa); + if (!(str2int(csa->field, &m) == 0 && m >= 0)) + error(csa, "number of clauses missing or invalid\n"); + xprintf("Instance has %d variable%s and %d clause%s\n", + n, n == 1 ? "" : "s", m, m == 1 ? "" : "s"); + end_of_line(csa); + if (m > 0) + glp_add_rows(P, m); + if (n > 0) + { glp_add_cols(P, n); + for (j = 1; j <= n; j++) + glp_set_col_kind(P, j, GLP_BV); + } + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + map = xcalloc(1+n, sizeof(char)); + for (j = 1; j <= n; j++) map[j] = 0; + /* read clauses */ + for (i = 1; i <= m; i++) + { /* read i-th clause */ + len = 0, rhs = 1; + for (;;) + { /* skip white-space characters */ + while (csa->c == ' ' || csa->c == '\n') + read_char(csa); + /* read term */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "variable number missing or invalid\n"); + if (j > 0) + neg = 0; + else if (j < 0) + neg = 1, j = -j, rhs--; + else + break; + if (!(1 <= j && j <= n)) + error(csa, "variable number out of range\n"); + if (map[j]) + error(csa, "duplicate variable number\n"); + len++, ind[len] = j, val[len] = (neg ? -1.0 : +1.0); + map[j] = 1; + } + glp_set_row_bnds(P, i, GLP_LO, (double)rhs, 0.0); + glp_set_mat_row(P, i, len, ind, val); + while (len > 0) map[ind[len--]] = 0; + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_sort_matrix(P); +done: if (csa->fp != NULL) glp_close(csa->fp); + if (ind != NULL) xfree(ind); + if (val != NULL) xfree(val); + if (map != NULL) xfree(map); + if (ret) glp_erase_prob(P); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdipt.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdipt.c new file mode 100644 index 000000000..aaf8e9d4b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdipt.c @@ -0,0 +1,185 @@ +/* rdipt.c (read interior-point solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "env.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_read_ipt - read interior-point solution in GLPK format +* +* SYNOPSIS +* +* int glp_read_ipt(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_ipt reads interior-point solution from a text +* file in GLPK format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_ipt(glp_prob *P, const char *fname) +{ DMX dmx_, *dmx = &dmx_; + int i, j, k, m, n, sst, ret = 1; + char *stat = NULL; + double obj, *prim = NULL, *dual = NULL; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_ipt: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_read_ipt: fname = %d; invalid parameter\n", fname); + if (setjmp(dmx->jump)) + goto done; + dmx->fname = fname; + dmx->fp = NULL; + dmx->count = 0; + dmx->c = '\n'; + dmx->field[0] = '\0'; + dmx->empty = dmx->nonint = 0; + xprintf("Reading interior-point solution from '%s'...\n", fname); + dmx->fp = glp_open(fname, "r"); + if (dmx->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* read solution line */ + dmx_read_designator(dmx); + if (strcmp(dmx->field, "s") != 0) + dmx_error(dmx, "solution line missing or invalid"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "ipt") != 0) + dmx_error(dmx, "wrong solution designator; 'ipt' expected"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &m) == 0 && m >= 0)) + dmx_error(dmx, "number of rows missing or invalid"); + if (m != P->m) + dmx_error(dmx, "number of rows mismatch"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &n) == 0 && n >= 0)) + dmx_error(dmx, "number of columns missing or invalid"); + if (n != P->n) + dmx_error(dmx, "number of columns mismatch"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "o") == 0) + sst = GLP_OPT; + else if (strcmp(dmx->field, "i") == 0) + sst = GLP_INFEAS; + else if (strcmp(dmx->field, "n") == 0) + sst = GLP_NOFEAS; + else if (strcmp(dmx->field, "u") == 0) + sst = GLP_UNDEF; + else + dmx_error(dmx, "solution status missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &obj) != 0) + dmx_error(dmx, "objective value missing or invalid"); + dmx_end_of_line(dmx); + /* allocate working arrays */ + stat = xalloc(1+m+n, sizeof(stat[0])); + for (k = 1; k <= m+n; k++) + stat[k] = '?'; + prim = xalloc(1+m+n, sizeof(prim[0])); + dual = xalloc(1+m+n, sizeof(dual[0])); + /* read solution descriptor lines */ + for (;;) + { dmx_read_designator(dmx); + if (strcmp(dmx->field, "i") == 0) + { /* row solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &i) != 0) + dmx_error(dmx, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + dmx_error(dmx, "row number out of range"); + if (stat[i] != '?') + dmx_error(dmx, "duplicate row solution descriptor"); + stat[i] = GLP_BS; + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[i]) != 0) + dmx_error(dmx, "row primal value missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &dual[i]) != 0) + dmx_error(dmx, "row dual value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "j") == 0) + { /* column solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &j) != 0) + dmx_error(dmx, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + dmx_error(dmx, "column number out of range"); + if (stat[m+j] != '?') + dmx_error(dmx, "duplicate column solution descriptor"); + stat[m+j] = GLP_BS; + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[m+j]) != 0) + dmx_error(dmx, "column primal value missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &dual[m+j]) != 0) + dmx_error(dmx, "column dual value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "e") == 0) + break; + else + dmx_error(dmx, "line designator missing or invalid"); + dmx_end_of_line(dmx); + } + /* store solution components into problem object */ + for (k = 1; k <= m+n; k++) + { if (stat[k] == '?') + dmx_error(dmx, "incomplete interior-point solution"); + } + P->ipt_stat = sst; + P->ipt_obj = obj; + for (i = 1; i <= m; i++) + { P->row[i]->pval = prim[i]; + P->row[i]->dval = dual[i]; + } + for (j = 1; j <= n; j++) + { P->col[j]->pval = prim[m+j]; + P->col[j]->dval = dual[m+j]; + } + /* interior-point solution has been successfully read */ + xprintf("%d lines were read\n", dmx->count); + ret = 0; +done: if (dmx->fp != NULL) + glp_close(dmx->fp); + if (stat != NULL) + xfree(stat); + if (prim != NULL) + xfree(prim); + if (dual != NULL) + xfree(dual); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmaxf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmaxf.c new file mode 100644 index 000000000..a45405c9e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmaxf.c @@ -0,0 +1,163 @@ +/* rdmaxf.c (read maximum flow problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "glpk.h" +#include "misc.h" + +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +/*********************************************************************** +* NAME +* +* glp_read_maxflow - read maximum flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_maxflow reads maximum flow problem data in +* DIMACS format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, + const char *fname) +{ DMX _csa, *csa = &_csa; + glp_arc *a; + int i, j, k, s, t, nv, na, ret = 0; + double cap; + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_read_maxflow: a_cap = %d; invalid offset\n", + a_cap); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading maximum flow problem data from '%s'...\n", + fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "max") != 0) + error(csa, "wrong problem designator; 'max' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 2)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + xprintf("Flow network has %d node%s and %d arc%s\n", + nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + s = t = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + read_field(csa); + if (strcmp(csa->field, "s") == 0) + { if (s > 0) + error(csa, "only one source node allowed"); + s = i; + } + else if (strcmp(csa->field, "t") == 0) + { if (t > 0) + error(csa, "only one sink node allowed"); + t = i; + } + else + error(csa, "wrong node designator; 's' or 't' expected"); + if (s > 0 && s == t) + error(csa, "source and sink nodes must be distinct"); + end_of_line(csa); + } + if (s == 0) + error(csa, "source node descriptor missing\n"); + if (t == 0) + error(csa, "sink node descriptor missing\n"); + if (_s != NULL) *_s = s; + if (_t != NULL) *_t = t; + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; 'a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + read_field(csa); + if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0)) + error(csa, "arc capacity missing or invalid"); + check_int(csa, cap); + a = glp_add_arc(G, i, j); + if (a_cap >= 0) + memcpy((char *)a->data + a_cap, &cap, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmcf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmcf.c new file mode 100644 index 000000000..bab1ec794 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmcf.c @@ -0,0 +1,186 @@ +/* rdmcf.c (read min-cost flow problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "glpk.h" +#include "misc.h" + +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +/*********************************************************************** +* NAME +* +* glp_read_mincost - read min-cost flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, +* int a_cost, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mincost reads minimum cost flow problem data in +* DIMACS format from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname) +{ DMX _csa, *csa = &_csa; + glp_vertex *v; + glp_arc *a; + int i, j, k, nv, na, ret = 0; + double rhs, low, cap, cost; + char *flag = NULL; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_read_mincost: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_read_mincost: a_cost = %d; invalid offset\n", + a_cost); + glp_erase_graph(G, G->v_size, G->a_size); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading min-cost flow problem data from '%s'...\n", + fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "min") != 0) + error(csa, "wrong problem designator; 'min' expected"); + read_field(csa); + if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) + error(csa, "number of nodes missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &na) == 0 && na >= 0)) + error(csa, "number of arcs missing or invalid"); + xprintf("Flow network has %d node%s and %d arc%s\n", + nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); + if (nv > 0) glp_add_vertices(G, nv); + end_of_line(csa); + /* read node descriptor lines */ + flag = xcalloc(1+nv, sizeof(char)); + memset(&flag[1], 0, nv * sizeof(char)); + if (v_rhs >= 0) + { rhs = 0.0; + for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); + } + } + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "n") != 0) break; + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "node number %d out of range", i); + if (flag[i]) + error(csa, "duplicate descriptor of node %d", i); + read_field(csa); + if (str2num(csa->field, &rhs) != 0) + error(csa, "node supply/demand missing or invalid"); + check_int(csa, rhs); + if (v_rhs >= 0) + { v = G->v[i]; + memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); + } + flag[i] = 1; + end_of_line(csa); + } + xfree(flag), flag = NULL; + /* read arc descriptor lines */ + for (k = 1; k <= na; k++) + { if (k > 1) read_designator(csa); + if (strcmp(csa->field, "a") != 0) + error(csa, "wrong line designator; 'a' expected"); + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "starting node number missing or invalid"); + if (!(1 <= i && i <= nv)) + error(csa, "starting node number %d out of range", i); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "ending node number missing or invalid"); + if (!(1 <= j && j <= nv)) + error(csa, "ending node number %d out of range", j); + read_field(csa); + if (!(str2num(csa->field, &low) == 0 && low >= 0.0)) + error(csa, "lower bound of arc flow missing or invalid"); + check_int(csa, low); + read_field(csa); + if (!(str2num(csa->field, &cap) == 0 && cap >= low)) + error(csa, "upper bound of arc flow missing or invalid"); + check_int(csa, cap); + read_field(csa); + if (str2num(csa->field, &cost) != 0) + error(csa, "per-unit cost of arc flow missing or invalid"); + check_int(csa, cost); + a = glp_add_arc(G, i, j); + if (a_low >= 0) + memcpy((char *)a->data + a_low, &low, sizeof(double)); + if (a_cap >= 0) + memcpy((char *)a->data + a_cap, &cap, sizeof(double)); + if (a_cost >= 0) + memcpy((char *)a->data + a_cost, &cost, sizeof(double)); + end_of_line(csa); + } + xprintf("%d lines were read\n", csa->count); +done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); + if (csa->fp != NULL) glp_close(csa->fp); + if (flag != NULL) xfree(flag); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmip.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmip.c new file mode 100644 index 000000000..7aec26b32 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdmip.c @@ -0,0 +1,172 @@ +/* rdmip.c (read MIP solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "env.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_read_mip - read MIP solution in GLPK format +* +* SYNOPSIS +* +* int glp_read_mip(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_mip reads MIP solution from a text file in GLPK +* format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_mip(glp_prob *P, const char *fname) +{ DMX dmx_, *dmx = &dmx_; + int i, j, k, m, n, sst, ret = 1; + char *stat = NULL; + double obj, *prim = NULL; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_mip: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_read_mip: fname = %d; invalid parameter\n", fname); + if (setjmp(dmx->jump)) + goto done; + dmx->fname = fname; + dmx->fp = NULL; + dmx->count = 0; + dmx->c = '\n'; + dmx->field[0] = '\0'; + dmx->empty = dmx->nonint = 0; + xprintf("Reading MIP solution from '%s'...\n", fname); + dmx->fp = glp_open(fname, "r"); + if (dmx->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* read solution line */ + dmx_read_designator(dmx); + if (strcmp(dmx->field, "s") != 0) + dmx_error(dmx, "solution line missing or invalid"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "mip") != 0) + dmx_error(dmx, "wrong solution designator; 'mip' expected"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &m) == 0 && m >= 0)) + dmx_error(dmx, "number of rows missing or invalid"); + if (m != P->m) + dmx_error(dmx, "number of rows mismatch"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &n) == 0 && n >= 0)) + dmx_error(dmx, "number of columns missing or invalid"); + if (n != P->n) + dmx_error(dmx, "number of columns mismatch"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "o") == 0) + sst = GLP_OPT; + else if (strcmp(dmx->field, "f") == 0) + sst = GLP_FEAS; + else if (strcmp(dmx->field, "n") == 0) + sst = GLP_NOFEAS; + else if (strcmp(dmx->field, "u") == 0) + sst = GLP_UNDEF; + else + dmx_error(dmx, "solution status missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &obj) != 0) + dmx_error(dmx, "objective value missing or invalid"); + dmx_end_of_line(dmx); + /* allocate working arrays */ + stat = xalloc(1+m+n, sizeof(stat[0])); + for (k = 1; k <= m+n; k++) + stat[k] = '?'; + prim = xalloc(1+m+n, sizeof(prim[0])); + /* read solution descriptor lines */ + for (;;) + { dmx_read_designator(dmx); + if (strcmp(dmx->field, "i") == 0) + { /* row solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &i) != 0) + dmx_error(dmx, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + dmx_error(dmx, "row number out of range"); + if (stat[i] != '?') + dmx_error(dmx, "duplicate row solution descriptor"); + stat[i] = GLP_BS; + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[i]) != 0) + dmx_error(dmx, "row value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "j") == 0) + { /* column solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &j) != 0) + dmx_error(dmx, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + dmx_error(dmx, "column number out of range"); + if (stat[m+j] != '?') + dmx_error(dmx, "duplicate column solution descriptor"); + stat[m+j] = GLP_BS; + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[m+j]) != 0) + dmx_error(dmx, "column value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "e") == 0) + break; + else + dmx_error(dmx, "line designator missing or invalid"); + dmx_end_of_line(dmx); + } + /* store solution components into problem object */ + for (k = 1; k <= m+n; k++) + { if (stat[k] == '?') + dmx_error(dmx, "incomplete MIP solution"); + } + P->mip_stat = sst; + P->mip_obj = obj; + for (i = 1; i <= m; i++) + P->row[i]->mipx = prim[i]; + for (j = 1; j <= n; j++) + P->col[j]->mipx = prim[m+j]; + /* MIP solution has been successfully read */ + xprintf("%d lines were read\n", dmx->count); + ret = 0; +done: if (dmx->fp != NULL) + glp_close(dmx->fp); + if (stat != NULL) + xfree(stat); + if (prim != NULL) + xfree(prim); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdprob.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdprob.c new file mode 100644 index 000000000..1ad544a59 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdprob.c @@ -0,0 +1,377 @@ +/* rdprob.c (read problem data in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "misc.h" +#include "prob.h" + +#define xfprintf glp_format +#define error dmx_error +#define warning dmx_warning +#define read_char dmx_read_char +#define read_designator dmx_read_designator +#define read_field dmx_read_field +#define end_of_line dmx_end_of_line +#define check_int dmx_check_int + +/*********************************************************************** +* NAME +* +* glp_read_prob - read problem data in GLPK format +* +* SYNOPSIS +* +* int glp_read_prob(glp_prob *P, int flags, const char *fname); +* +* The routine glp_read_prob reads problem data in GLPK LP/MIP format +* from a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_prob(glp_prob *P, int flags, const char *fname) +{ DMX _csa, *csa = &_csa; + int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL, + *ia = NULL, *ja = NULL; + double lb, ub, temp, *ar = NULL; + char *rf = NULL, *cf = NULL; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_prob: P = %p; invalid problem object\n", + P); +#endif + if (flags != 0) + xerror("glp_read_prob: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_read_prob: fname = %d; invalid parameter\n", + fname); + glp_erase_prob(P); + if (setjmp(csa->jump)) + { ret = 1; + goto done; + } + csa->fname = fname; + csa->fp = NULL; + csa->count = 0; + csa->c = '\n'; + csa->field[0] = '\0'; + csa->empty = csa->nonint = 0; + xprintf("Reading problem data from '%s'...\n", fname); + csa->fp = glp_open(fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + longjmp(csa->jump, 1); + } + /* read problem line */ + read_designator(csa); + if (strcmp(csa->field, "p") != 0) + error(csa, "problem line missing or invalid"); + read_field(csa); + if (strcmp(csa->field, "lp") == 0) + mip = 0; + else if (strcmp(csa->field, "mip") == 0) + mip = 1; + else + error(csa, "wrong problem designator; 'lp' or 'mip' expected"); + read_field(csa); + if (strcmp(csa->field, "min") == 0) + glp_set_obj_dir(P, GLP_MIN); + else if (strcmp(csa->field, "max") == 0) + glp_set_obj_dir(P, GLP_MAX); + else + error(csa, "objective sense missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &m) == 0 && m >= 0)) + error(csa, "number of rows missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &n) == 0 && n >= 0)) + error(csa, "number of columns missing or invalid"); + read_field(csa); + if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0)) + error(csa, "number of constraint coefficients missing or inval" + "id"); + if (m > 0) + { glp_add_rows(P, m); + for (i = 1; i <= m; i++) + glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0); + } + if (n > 0) + { glp_add_cols(P, n); + for (j = 1; j <= n; j++) + { if (!mip) + glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0); + else + glp_set_col_kind(P, j, GLP_BV); + } + } + end_of_line(csa); + /* allocate working arrays */ + rf = xcalloc(1+m, sizeof(char)); + memset(rf, 0, 1+m); + cf = xcalloc(1+n, sizeof(char)); + memset(cf, 0, 1+n); + ln = xcalloc(1+nnz, sizeof(int)); + ia = xcalloc(1+nnz, sizeof(int)); + ja = xcalloc(1+nnz, sizeof(int)); + ar = xcalloc(1+nnz, sizeof(double)); + /* read descriptor lines */ + ne = 0; + for (;;) + { read_designator(csa); + if (strcmp(csa->field, "i") == 0) + { /* row descriptor */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (strcmp(csa->field, "f") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "l") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "u") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "d") == 0) + type = GLP_DB; + else if (strcmp(csa->field, "s") == 0) + type = GLP_FX; + else + error(csa, "row type missing or invalid"); + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { read_field(csa); + if (str2num(csa->field, &lb) != 0) + error(csa, "row lower bound/fixed value missing or in" + "valid"); + } + else + lb = 0.0; + if (type == GLP_UP || type == GLP_DB) + { read_field(csa); + if (str2num(csa->field, &ub) != 0) + error(csa, "row upper bound missing or invalid"); + } + else + ub = 0.0; + if (rf[i] & 0x01) + error(csa, "duplicate row descriptor"); + glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01; + } + else if (strcmp(csa->field, "j") == 0) + { /* column descriptor */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + error(csa, "column number out of range"); + if (!mip) + kind = GLP_CV; + else + { read_field(csa); + if (strcmp(csa->field, "c") == 0) + kind = GLP_CV; + else if (strcmp(csa->field, "i") == 0) + kind = GLP_IV; + else if (strcmp(csa->field, "b") == 0) + { kind = GLP_IV; + type = GLP_DB, lb = 0.0, ub = 1.0; + goto skip; + } + else + error(csa, "column kind missing or invalid"); + } + read_field(csa); + if (strcmp(csa->field, "f") == 0) + type = GLP_FR; + else if (strcmp(csa->field, "l") == 0) + type = GLP_LO; + else if (strcmp(csa->field, "u") == 0) + type = GLP_UP; + else if (strcmp(csa->field, "d") == 0) + type = GLP_DB; + else if (strcmp(csa->field, "s") == 0) + type = GLP_FX; + else + error(csa, "column type missing or invalid"); + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { read_field(csa); + if (str2num(csa->field, &lb) != 0) + error(csa, "column lower bound/fixed value missing or" + " invalid"); + } + else + lb = 0.0; + if (type == GLP_UP || type == GLP_DB) + { read_field(csa); + if (str2num(csa->field, &ub) != 0) + error(csa, "column upper bound missing or invalid"); + } + else + ub = 0.0; +skip: if (cf[j] & 0x01) + error(csa, "duplicate column descriptor"); + glp_set_col_kind(P, j, kind); + glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01; + } + else if (strcmp(csa->field, "a") == 0) + { /* coefficient descriptor */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(0 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!((i == 0 ? 0 : 1) <= j && j <= n)) + error(csa, "column number out of range"); + read_field(csa); + if (i == 0) + { if (str2num(csa->field, &temp) != 0) + error(csa, "objective %s missing or invalid", + j == 0 ? "constant term" : "coefficient"); + if (cf[j] & 0x10) + error(csa, "duplicate objective %s", + j == 0 ? "constant term" : "coefficient"); + glp_set_obj_coef(P, j, temp), cf[j] |= 0x10; + } + else + { if (str2num(csa->field, &temp) != 0) + error(csa, "constraint coefficient missing or invalid" + ); + if (ne == nnz) + error(csa, "too many constraint coefficient descripto" + "rs"); + ln[++ne] = csa->count; + ia[ne] = i, ja[ne] = j, ar[ne] = temp; + } + } + else if (strcmp(csa->field, "n") == 0) + { /* symbolic name descriptor */ + read_field(csa); + if (strcmp(csa->field, "p") == 0) + { /* problem name */ + read_field(csa); + if (P->name != NULL) + error(csa, "duplicate problem name"); + glp_set_prob_name(P, csa->field); + } + else if (strcmp(csa->field, "z") == 0) + { /* objective name */ + read_field(csa); + if (P->obj != NULL) + error(csa, "duplicate objective name"); + glp_set_obj_name(P, csa->field); + } + else if (strcmp(csa->field, "i") == 0) + { /* row name */ + read_field(csa); + if (str2int(csa->field, &i) != 0) + error(csa, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + error(csa, "row number out of range"); + read_field(csa); + if (P->row[i]->name != NULL) + error(csa, "duplicate row name"); + glp_set_row_name(P, i, csa->field); + } + else if (strcmp(csa->field, "j") == 0) + { /* column name */ + read_field(csa); + if (str2int(csa->field, &j) != 0) + error(csa, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + error(csa, "column number out of range"); + read_field(csa); + if (P->col[j]->name != NULL) + error(csa, "duplicate column name"); + glp_set_col_name(P, j, csa->field); + } + else + error(csa, "object designator missing or invalid"); + } + else if (strcmp(csa->field, "e") == 0) + break; + else + error(csa, "line designator missing or invalid"); + end_of_line(csa); + } + if (ne < nnz) + error(csa, "too few constraint coefficient descriptors"); + xassert(ne == nnz); + k = glp_check_dup(m, n, ne, ia, ja); + xassert(0 <= k && k <= nnz); + if (k > 0) + { csa->count = ln[k]; + error(csa, "duplicate constraint coefficient"); + } + glp_load_matrix(P, ne, ia, ja, ar); + /* print some statistics */ + if (P->name != NULL) + xprintf("Problem: %s\n", P->name); + if (P->obj != NULL) + xprintf("Objective: %s\n", P->obj); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? + "" : "s"); + if (glp_get_num_int(P) > 0) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + if (ni == 1) + { if (nb == 0) + xprintf("One variable is integer\n"); + else + xprintf("One variable is binary\n"); + } + else + { xprintf("%d integer variables, ", ni); + if (nb == 0) + xprintf("none"); + else if (nb == 1) + xprintf("one"); + else if (nb == ni) + xprintf("all"); + else + xprintf("%d", nb); + xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); + } + } + xprintf("%d lines were read\n", csa->count); + /* problem data has been successfully read */ + glp_sort_matrix(P); + ret = 0; +done: if (csa->fp != NULL) glp_close(csa->fp); + if (rf != NULL) xfree(rf); + if (cf != NULL) xfree(cf); + if (ln != NULL) xfree(ln); + if (ia != NULL) xfree(ia); + if (ja != NULL) xfree(ja); + if (ar != NULL) xfree(ar); + if (ret) glp_erase_prob(P); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rdsol.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdsol.c new file mode 100644 index 000000000..d85a25626 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rdsol.c @@ -0,0 +1,225 @@ +/* rdsol.c (read basic solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" +#include "env.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_read_sol - read basic solution in GLPK format +* +* SYNOPSIS +* +* int glp_read_sol(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_read_sol reads basic solution from a text file in +* GLPK format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_read_sol(glp_prob *P, const char *fname) +{ DMX dmx_, *dmx = &dmx_; + int i, j, k, m, n, pst, dst, ret = 1; + char *stat = NULL; + double obj, *prim = NULL, *dual = NULL; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_read_sol: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_read_sol: fname = %d; invalid parameter\n", fname); + if (setjmp(dmx->jump)) + goto done; + dmx->fname = fname; + dmx->fp = NULL; + dmx->count = 0; + dmx->c = '\n'; + dmx->field[0] = '\0'; + dmx->empty = dmx->nonint = 0; + xprintf("Reading basic solution from '%s'...\n", fname); + dmx->fp = glp_open(fname, "r"); + if (dmx->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* read solution line */ + dmx_read_designator(dmx); + if (strcmp(dmx->field, "s") != 0) + dmx_error(dmx, "solution line missing or invalid"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "bas") != 0) + dmx_error(dmx, "wrong solution designator; 'bas' expected"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &m) == 0 && m >= 0)) + dmx_error(dmx, "number of rows missing or invalid"); + if (m != P->m) + dmx_error(dmx, "number of rows mismatch"); + dmx_read_field(dmx); + if (!(str2int(dmx->field, &n) == 0 && n >= 0)) + dmx_error(dmx, "number of columns missing or invalid"); + if (n != P->n) + dmx_error(dmx, "number of columns mismatch"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "u") == 0) + pst = GLP_UNDEF; + else if (strcmp(dmx->field, "f") == 0) + pst = GLP_FEAS; + else if (strcmp(dmx->field, "i") == 0) + pst = GLP_INFEAS; + else if (strcmp(dmx->field, "n") == 0) + pst = GLP_NOFEAS; + else + dmx_error(dmx, "primal solution status missing or invalid"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "u") == 0) + dst = GLP_UNDEF; + else if (strcmp(dmx->field, "f") == 0) + dst = GLP_FEAS; + else if (strcmp(dmx->field, "i") == 0) + dst = GLP_INFEAS; + else if (strcmp(dmx->field, "n") == 0) + dst = GLP_NOFEAS; + else + dmx_error(dmx, "dual solution status missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &obj) != 0) + dmx_error(dmx, "objective value missing or invalid"); + dmx_end_of_line(dmx); + /* allocate working arrays */ + stat = xalloc(1+m+n, sizeof(stat[0])); + for (k = 1; k <= m+n; k++) + stat[k] = '?'; + prim = xalloc(1+m+n, sizeof(prim[0])); + dual = xalloc(1+m+n, sizeof(dual[0])); + /* read solution descriptor lines */ + for (;;) + { dmx_read_designator(dmx); + if (strcmp(dmx->field, "i") == 0) + { /* row solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &i) != 0) + dmx_error(dmx, "row number missing or invalid"); + if (!(1 <= i && i <= m)) + dmx_error(dmx, "row number out of range"); + if (stat[i] != '?') + dmx_error(dmx, "duplicate row solution descriptor"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "b") == 0) + stat[i] = GLP_BS; + else if (strcmp(dmx->field, "l") == 0) + stat[i] = GLP_NL; + else if (strcmp(dmx->field, "u") == 0) + stat[i] = GLP_NU; + else if (strcmp(dmx->field, "f") == 0) + stat[i] = GLP_NF; + else if (strcmp(dmx->field, "s") == 0) + stat[i] = GLP_NS; + else + dmx_error(dmx, "row status missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[i]) != 0) + dmx_error(dmx, "row primal value missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &dual[i]) != 0) + dmx_error(dmx, "row dual value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "j") == 0) + { /* column solution descriptor */ + dmx_read_field(dmx); + if (str2int(dmx->field, &j) != 0) + dmx_error(dmx, "column number missing or invalid"); + if (!(1 <= j && j <= n)) + dmx_error(dmx, "column number out of range"); + if (stat[m+j] != '?') + dmx_error(dmx, "duplicate column solution descriptor"); + dmx_read_field(dmx); + if (strcmp(dmx->field, "b") == 0) + stat[m+j] = GLP_BS; + else if (strcmp(dmx->field, "l") == 0) + stat[m+j] = GLP_NL; + else if (strcmp(dmx->field, "u") == 0) + stat[m+j] = GLP_NU; + else if (strcmp(dmx->field, "f") == 0) + stat[m+j] = GLP_NF; + else if (strcmp(dmx->field, "s") == 0) + stat[m+j] = GLP_NS; + else + dmx_error(dmx, "column status missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &prim[m+j]) != 0) + dmx_error(dmx, "column primal value missing or invalid"); + dmx_read_field(dmx); + if (str2num(dmx->field, &dual[m+j]) != 0) + dmx_error(dmx, "column dual value missing or invalid"); + dmx_end_of_line(dmx); + } + else if (strcmp(dmx->field, "e") == 0) + break; + else + dmx_error(dmx, "line designator missing or invalid"); + dmx_end_of_line(dmx); + } + /* store solution components into problem object */ + for (k = 1; k <= m+n; k++) + { if (stat[k] == '?') + dmx_error(dmx, "incomplete basic solution"); + } + P->pbs_stat = pst; + P->dbs_stat = dst; + P->obj_val = obj; + P->it_cnt = 0; + P->some = 0; + for (i = 1; i <= m; i++) + { glp_set_row_stat(P, i, stat[i]); + P->row[i]->prim = prim[i]; + P->row[i]->dual = dual[i]; + } + for (j = 1; j <= n; j++) + { glp_set_col_stat(P, j, stat[m+j]); + P->col[j]->prim = prim[m+j]; + P->col[j]->dual = dual[m+j]; + } + /* basic solution has been successfully read */ + xprintf("%d lines were read\n", dmx->count); + ret = 0; +done: if (dmx->fp != NULL) + glp_close(dmx->fp); + if (stat != NULL) + xfree(stat); + if (prim != NULL) + xfree(prim); + if (dual != NULL) + xfree(dual); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/rmfgen.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/rmfgen.c new file mode 100644 index 000000000..a1ba27bb6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/rmfgen.c @@ -0,0 +1,368 @@ +/* rmfgen.c (Goldfarb's maximum flow problem generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the program RMFGEN, a maxflow +* problem generator developed by D.Goldfarb and M.Grigoriadis, and +* originally implemented by Tamas Badics . +* The original code is publically available on the DIMACS ftp site at: +* . +* +* All changes concern only the program interface, so this modified +* version produces exactly the same instances as the original version. +* +* Changes were made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* glp_rmfgen - Goldfarb's maximum flow problem generator +* +* SYNOPSIS +* +* int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, +* const int parm[1+5]); +* +* DESCRIPTION +* +* The routine glp_rmfgen is a maximum flow problem generator developed +* by D.Goldfarb and M.Grigoriadis. +* +* The parameter G specifies the graph object, to which the generated +* problem data have to be stored. Note that on entry the graph object +* is erased with the routine glp_erase_graph. +* +* The pointer s specifies a location, to which the routine stores the +* source node number. If s is NULL, the node number is not stored. +* +* The pointer t specifies a location, to which the routine stores the +* sink node number. If t is NULL, the node number is not stored. +* +* The parameter a_cap specifies an offset of the field of type double +* in the arc data block, to which the routine stores the arc capacity. +* If a_cap < 0, the capacity is not stored. +* +* The array parm contains description of the network to be generated: +* +* parm[0] not used +* parm[1] (seed) random number seed (a positive integer) +* parm[2] (a) frame size +* parm[3] (b) depth +* parm[4] (c1) minimal arc capacity +* parm[5] (c2) maximal arc capacity +* +* RETURNS +* +* If the instance was successfully generated, the routine glp_netgen +* returns zero; otherwise, if specified parameters are inconsistent, +* the routine returns a non-zero error code. +* +* COMMENTS +* +* The generated network is as follows. It has b pieces of frames of +* size a * a. (So alltogether the number of vertices is a * a * b) +* +* In each frame all the vertices are connected with their neighbours +* (forth and back). In addition the vertices of a frame are connected +* one to one with the vertices of next frame using a random permutation +* of those vertices. +* +* The source is the lower left vertex of the first frame, the sink is +* the upper right vertex of the b'th frame. +* +* t +* +-------+ +* | .| +* | . | +* / | / | +* +-------+/ -+ b +* | | |/. +* a | -v- |/ +* | | |/ +* +-------+ 1 +* s a +* +* The capacities are randomly chosen integers from the range of [c1,c2] +* in the case of interconnecting edges, and c2 * a * a for the in-frame +* edges. +* +* REFERENCES +* +* D.Goldfarb and M.D.Grigoriadis, "A computational comparison of the +* Dinic and network simplex methods for maximum flow." Annals of Op. +* Res. 13 (1988), pp. 83-123. +* +* U.Derigs and W.Meier, "Implementing Goldberg's max-flow algorithm: +* A computational investigation." Zeitschrift fuer Operations Research +* 33 (1989), pp. 383-403. */ + +typedef struct VERTEX +{ struct EDGE **edgelist; + /* Pointer to the list of pointers to the adjacent edges. + (No matter that to or from edges) */ + struct EDGE **current; + /* Pointer to the current edge */ + int degree; + /* Number of adjacent edges (both direction) */ + int index; +} vertex; + +typedef struct EDGE +{ int from; + int to; + int cap; + /* Capacity */ +} edge; + +typedef struct NETWORK +{ struct NETWORK *next, *prev; + int vertnum; + int edgenum; + vertex *verts; + /* Vertex array[1..vertnum] */ + edge *edges; + /* Edge array[1..edgenum] */ + int source; + /* Pointer to the source */ + int sink; + /* Pointer to the sink */ +} network; + +struct csa +{ /* common storage area */ + glp_graph *G; + int *s, *t, a_cap; + RNG *rand; + network *N; + int *Parr; + int A, AA, C2AA, Ec; +}; + +#define G (csa->G) +#define s (csa->s) +#define t (csa->t) +#define a_cap (csa->a_cap) +#define N (csa->N) +#define Parr (csa->Parr) +#define A (csa->A) +#define AA (csa->AA) +#define C2AA (csa->C2AA) +#define Ec (csa->Ec) + +#undef random +#define random(A) (int)(rng_unif_01(csa->rand) * (double)(A)) +#define RANDOM(A, B) (int)(random((B) - (A) + 1) + (A)) +#define sgn(A) (((A) > 0) ? 1 : ((A) == 0) ? 0 : -1) + +static void make_edge(struct csa *csa, int from, int to, int c1, int c2) +{ Ec++; + N->edges[Ec].from = from; + N->edges[Ec].to = to; + N->edges[Ec].cap = RANDOM(c1, c2); + return; +} + +static void permute(struct csa *csa) +{ int i, j, tmp; + for (i = 1; i < AA; i++) + { j = RANDOM(i, AA); + tmp = Parr[i]; + Parr[i] = Parr[j]; + Parr[j] = tmp; + } + return; +} + +static void connect(struct csa *csa, int offset, int cv, int x1, int y1) +{ int cv1; + cv1 = offset + (x1 - 1) * A + y1; + Ec++; + N->edges[Ec].from = cv; + N->edges[Ec].to = cv1; + N->edges[Ec].cap = C2AA; + return; +} + +static network *gen_rmf(struct csa *csa, int a, int b, int c1, int c2) +{ /* generates a network with a*a*b nodes and 6a*a*b-4ab-2a*a edges + random_frame network: + Derigs & Meier, Methods & Models of OR (1989), 33:383-403 */ + int x, y, z, offset, cv; + A = a; + AA = a * a; + C2AA = c2 * AA; + Ec = 0; + N = (network *)xmalloc(sizeof(network)); + N->vertnum = AA * b; + N->edgenum = 5 * AA * b - 4 * A * b - AA; + N->edges = (edge *)xcalloc(N->edgenum + 1, sizeof(edge)); + N->source = 1; + N->sink = N->vertnum; + Parr = (int *)xcalloc(AA + 1, sizeof(int)); + for (x = 1; x <= AA; x++) + Parr[x] = x; + for (z = 1; z <= b; z++) + { offset = AA * (z - 1); + if (z != b) + permute(csa); + for (x = 1; x <= A; x++) + { for (y = 1; y <= A; y++) + { cv = offset + (x - 1) * A + y; + if (z != b) + make_edge(csa, cv, offset + AA + Parr[cv - offset], + c1, c2); /* the intermediate edges */ + if (y < A) + connect(csa, offset, cv, x, y + 1); + if (y > 1) + connect(csa, offset, cv, x, y - 1); + if (x < A) + connect(csa, offset, cv, x + 1, y); + if (x > 1) + connect(csa, offset, cv, x - 1, y); + } + } + } + xfree(Parr); + return N; +} + +static void print_max_format(struct csa *csa, network *n, char *comm[], + int dim) +{ /* prints a network heading with dim lines of comments (no \n + needs at the ends) */ + int i, vnum, e_num; + edge *e; + vnum = n->vertnum; + e_num = n->edgenum; + if (G == NULL) + { for (i = 0; i < dim; i++) + xprintf("c %s\n", comm[i]); + xprintf("p max %7d %10d\n", vnum, e_num); + xprintf("n %7d s\n", n->source); + xprintf("n %7d t\n", n->sink); + } + else + { glp_add_vertices(G, vnum); + if (s != NULL) *s = n->source; + if (t != NULL) *t = n->sink; + } + for (i = 1; i <= e_num; i++) + { e = &n->edges[i]; + if (G == NULL) + xprintf("a %7d %7d %10d\n", e->from, e->to, (int)e->cap); + else + { glp_arc *a = glp_add_arc(G, e->from, e->to); + if (a_cap >= 0) + { double temp = (double)e->cap; + memcpy((char *)a->data + a_cap, &temp, sizeof(double)); + } + } + } + return; +} + +static void gen_free_net(network *n) +{ xfree(n->edges); + xfree(n); + return; +} + +int glp_rmfgen(glp_graph *G_, int *_s, int *_t, int _a_cap, + const int parm[1+5]) +{ struct csa _csa, *csa = &_csa; + network *n; + char comm[10][80], *com1[10]; + int seed, a, b, c1, c2, ret; + G = G_; + s = _s; + t = _t; + a_cap = _a_cap; + if (G != NULL) + { if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_rmfgen: a_cap = %d; invalid offset\n", a_cap); + } + seed = parm[1]; + a = parm[2]; + b = parm[3]; + c1 = parm[4]; + c2 = parm[5]; + if (!(seed > 0 && 1 <= a && a <= 1000 && 1 <= b && b <= 1000 && + 0 <= c1 && c1 <= c2 && c2 <= 1000)) + { ret = 1; + goto done; + } + if (G != NULL) + { glp_erase_graph(G, G->v_size, G->a_size); + glp_set_graph_name(G, "RMFGEN"); + } + csa->rand = rng_create_rand(); + rng_init_rand(csa->rand, seed); + n = gen_rmf(csa, a, b, c1, c2); + sprintf(comm[0], "This file was generated by genrmf."); + sprintf(comm[1], "The parameters are: a: %d b: %d c1: %d c2: %d", + a, b, c1, c2); + com1[0] = comm[0]; + com1[1] = comm[1]; + print_max_format(csa, n, com1, 2); + gen_free_net(n); + rng_delete_rand(csa->rand); + ret = 0; +done: return ret; +} + +/**********************************************************************/ + +#if 0 +int main(int argc, char *argv[]) +{ int seed, a, b, c1, c2, i, parm[1+5]; + seed = 123; + a = b = c1 = c2 = -1; + for (i = 1; i < argc; i++) + { if (strcmp(argv[i], "-seed") == 0) + seed = atoi(argv[++i]); + else if (strcmp(argv[i], "-a") == 0) + a = atoi(argv[++i]); + else if (strcmp(argv[i], "-b") == 0) + b = atoi(argv[++i]); + else if (strcmp(argv[i], "-c1") == 0) + c1 = atoi(argv[++i]); + else if (strcmp(argv[i], "-c2") == 0) + c2 = atoi(argv[++i]); + } + if (a < 0 || b < 0 || c1 < 0 || c2 < 0) + { xprintf("Usage:\n"); + xprintf("genrmf [-seed seed] -a frame_size -b depth\n"); + xprintf(" -c1 cap_range1 -c2 cap_range2\n"); + } + else + { parm[1] = seed; + parm[2] = a; + parm[3] = b; + parm[4] = c1; + parm[5] = c2; + glp_rmfgen(NULL, NULL, NULL, 0, parm); + } + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/strong.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/strong.c new file mode 100644 index 000000000..9ddcacfbc --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/strong.c @@ -0,0 +1,110 @@ +/* strong.c (find all strongly connected components of graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "mc13d.h" + +/*********************************************************************** +* NAME +* +* glp_strong_comp - find all strongly connected components of graph +* +* SYNOPSIS +* +* int glp_strong_comp(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_strong_comp finds all strongly connected components +* of the specified graph. +* +* The parameter v_num specifies an offset of the field of type int +* in the vertex data block, to which the routine stores the number of +* a strongly connected component containing that vertex. If v_num < 0, +* no component numbers are stored. +* +* The components are numbered in arbitrary order from 1 to nc, where +* nc is the total number of components found, 0 <= nc <= |V|. However, +* the component numbering has the property that for every arc (i->j) +* in the graph the condition num(i) >= num(j) holds. +* +* RETURNS +* +* The routine returns nc, the total number of components found. */ + +int glp_strong_comp(glp_graph *G, int v_num) +{ glp_vertex *v; + glp_arc *a; + int i, k, last, n, na, nc, *icn, *ip, *lenr, *ior, *ib, *lowl, + *numb, *prev; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_strong_comp: v_num = %d; invalid offset\n", + v_num); + n = G->nv; + if (n == 0) + { nc = 0; + goto done; + } + na = G->na; + icn = xcalloc(1+na, sizeof(int)); + ip = xcalloc(1+n, sizeof(int)); + lenr = xcalloc(1+n, sizeof(int)); + ior = xcalloc(1+n, sizeof(int)); + ib = xcalloc(1+n, sizeof(int)); + lowl = xcalloc(1+n, sizeof(int)); + numb = xcalloc(1+n, sizeof(int)); + prev = xcalloc(1+n, sizeof(int)); + k = 1; + for (i = 1; i <= n; i++) + { v = G->v[i]; + ip[i] = k; + for (a = v->out; a != NULL; a = a->t_next) + icn[k++] = a->head->i; + lenr[i] = k - ip[i]; + } + xassert(na == k-1); + nc = mc13d(n, icn, ip, lenr, ior, ib, lowl, numb, prev); + if (v_num >= 0) + { xassert(ib[1] == 1); + for (k = 1; k <= nc; k++) + { last = (k < nc ? ib[k+1] : n+1); + xassert(ib[k] < last); + for (i = ib[k]; i < last; i++) + { v = G->v[ior[i]]; + memcpy((char *)v->data + v_num, &k, sizeof(int)); + } + } + } + xfree(icn); + xfree(ip); + xfree(lenr); + xfree(ior); + xfree(ib); + xfree(lowl); + xfree(numb); + xfree(prev); +done: return nc; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/topsort.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/topsort.c new file mode 100644 index 000000000..971937f2e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/topsort.c @@ -0,0 +1,123 @@ +/* topsort.c (topological sorting of acyclic digraph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_top_sort - topological sorting of acyclic digraph +* +* SYNOPSIS +* +* int glp_top_sort(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_top_sort performs topological sorting of vertices of +* the specified acyclic digraph. +* +* The parameter v_num specifies an offset of the field of type int in +* the vertex data block, to which the routine stores the vertex number +* assigned. If v_num < 0, vertex numbers are not stored. +* +* The vertices are numbered from 1 to n, where n is the total number +* of vertices in the graph. The vertex numbering has the property that +* for every arc (i->j) in the graph the condition num(i) < num(j) +* holds. Special case num(i) = 0 means that vertex i is not assigned a +* number, because the graph is *not* acyclic. +* +* RETURNS +* +* If the graph is acyclic and therefore all the vertices have been +* assigned numbers, the routine glp_top_sort returns zero. Otherwise, +* if the graph is not acyclic, the routine returns the number of +* vertices which have not been numbered, i.e. for which num(i) = 0. */ + +static int top_sort(glp_graph *G, int num[]) +{ glp_arc *a; + int i, j, cnt, top, *stack, *indeg; + /* allocate working arrays */ + indeg = xcalloc(1+G->nv, sizeof(int)); + stack = xcalloc(1+G->nv, sizeof(int)); + /* determine initial indegree of each vertex; push into the stack + the vertices having zero indegree */ + top = 0; + for (i = 1; i <= G->nv; i++) + { num[i] = indeg[i] = 0; + for (a = G->v[i]->in; a != NULL; a = a->h_next) + indeg[i]++; + if (indeg[i] == 0) + stack[++top] = i; + } + /* assign numbers to vertices in the sorted order */ + cnt = 0; + while (top > 0) + { /* pull vertex i from the stack */ + i = stack[top--]; + /* it has zero indegree in the current graph */ + xassert(indeg[i] == 0); + /* so assign it a next number */ + xassert(num[i] == 0); + num[i] = ++cnt; + /* remove vertex i from the current graph, update indegree of + its adjacent vertices, and push into the stack new vertices + whose indegree becomes zero */ + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { j = a->head->i; + /* there exists arc (i->j) in the graph */ + xassert(indeg[j] > 0); + indeg[j]--; + if (indeg[j] == 0) + stack[++top] = j; + } + } + /* free working arrays */ + xfree(indeg); + xfree(stack); + return G->nv - cnt; +} + +int glp_top_sort(glp_graph *G, int v_num) +{ glp_vertex *v; + int i, cnt, *num; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_top_sort: v_num = %d; invalid offset\n", v_num); + if (G->nv == 0) + { cnt = 0; + goto done; + } + num = xcalloc(1+G->nv, sizeof(int)); + cnt = top_sort(G, num); + if (v_num >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_num, &num[i], sizeof(int)); + } + } + xfree(num); +done: return cnt; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wcliqex.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wcliqex.c new file mode 100644 index 000000000..53c2d5215 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wcliqex.c @@ -0,0 +1,122 @@ +/* wcliqex.c (find maximum weight clique with exact algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" +#include "wclique.h" + +static void set_edge(int nv, unsigned char a[], int i, int j) +{ int k; + xassert(1 <= j && j < i && i <= nv); + k = ((i - 1) * (i - 2)) / 2 + (j - 1); + a[k / CHAR_BIT] |= + (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); + return; +} + +int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set) +{ /* find maximum weight clique with exact algorithm */ + glp_arc *e; + int i, j, k, len, x, *w, *ind, ret = 0; + unsigned char *a; + double s, t; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_wclique_exact: v_wgt = %d; invalid parameter\n", + v_wgt); + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_wclique_exact: v_set = %d; invalid parameter\n", + v_set); + if (G->nv == 0) + { /* empty graph has only empty clique */ + if (sol != NULL) *sol = 0.0; + return 0; + } + /* allocate working arrays */ + w = xcalloc(1+G->nv, sizeof(int)); + ind = xcalloc(1+G->nv, sizeof(int)); + len = G->nv; /* # vertices */ + len = len * (len - 1) / 2; /* # entries in lower triangle */ + len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* # bytes needed */ + a = xcalloc(len, sizeof(char)); + memset(a, 0, len * sizeof(char)); + /* determine vertex weights */ + s = 0.0; + for (i = 1; i <= G->nv; i++) + { if (v_wgt >= 0) + { memcpy(&t, (char *)G->v[i]->data + v_wgt, sizeof(double)); + if (!(0.0 <= t && t <= (double)INT_MAX && t == floor(t))) + { ret = GLP_EDATA; + goto done; + } + w[i] = (int)t; + } + else + w[i] = 1; + s += (double)w[i]; + } + if (s > (double)INT_MAX) + { ret = GLP_EDATA; + goto done; + } + /* build the adjacency matrix */ + for (i = 1; i <= G->nv; i++) + { for (e = G->v[i]->in; e != NULL; e = e->h_next) + { j = e->tail->i; + /* there exists edge (j,i) in the graph */ + if (i > j) set_edge(G->nv, a, i, j); + } + for (e = G->v[i]->out; e != NULL; e = e->t_next) + { j = e->head->i; + /* there exists edge (i,j) in the graph */ + if (i > j) set_edge(G->nv, a, i, j); + } + } + /* find maximum weight clique in the graph */ + len = wclique(G->nv, w, a, ind); + /* compute the clique weight */ + s = 0.0; + for (k = 1; k <= len; k++) + { i = ind[k]; + xassert(1 <= i && i <= G->nv); + s += (double)w[i]; + } + if (sol != NULL) *sol = s; + /* mark vertices included in the clique */ + if (v_set >= 0) + { x = 0; + for (i = 1; i <= G->nv; i++) + memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); + x = 1; + for (k = 1; k <= len; k++) + { i = ind[k]; + memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); + } + } +done: /* free working arrays */ + xfree(w); + xfree(ind); + xfree(a); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/weak.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/weak.c new file mode 100644 index 000000000..027c09c14 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/weak.c @@ -0,0 +1,150 @@ +/* weak.c (find all weakly connected components of graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +/*********************************************************************** +* NAME +* +* glp_weak_comp - find all weakly connected components of graph +* +* SYNOPSIS +* +* int glp_weak_comp(glp_graph *G, int v_num); +* +* DESCRIPTION +* +* The routine glp_weak_comp finds all weakly connected components of +* the specified graph. +* +* The parameter v_num specifies an offset of the field of type int +* in the vertex data block, to which the routine stores the number of +* a (weakly) connected component containing that vertex. If v_num < 0, +* no component numbers are stored. +* +* The components are numbered in arbitrary order from 1 to nc, where +* nc is the total number of components found, 0 <= nc <= |V|. +* +* RETURNS +* +* The routine returns nc, the total number of components found. */ + +int glp_weak_comp(glp_graph *G, int v_num) +{ glp_vertex *v; + glp_arc *a; + int f, i, j, nc, nv, pos1, pos2, *prev, *next, *list; + if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) + xerror("glp_weak_comp: v_num = %d; invalid offset\n", v_num); + nv = G->nv; + if (nv == 0) + { nc = 0; + goto done; + } + /* allocate working arrays */ + prev = xcalloc(1+nv, sizeof(int)); + next = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* if vertex i is unlabelled, prev[i] is the index of previous + unlabelled vertex, and next[i] is the index of next unlabelled + vertex; if vertex i is labelled, then prev[i] < 0, and next[i] + is the connected component number */ + /* initially all vertices are unlabelled */ + f = 1; + for (i = 1; i <= nv; i++) + prev[i] = i - 1, next[i] = i + 1; + next[nv] = 0; + /* main loop (until all vertices have been labelled) */ + nc = 0; + while (f != 0) + { /* take an unlabelled vertex */ + i = f; + /* and remove it from the list of unlabelled vertices */ + f = next[i]; + if (f != 0) prev[f] = 0; + /* label the vertex; it begins a new component */ + prev[i] = -1, next[i] = ++nc; + /* breadth first search */ + list[1] = i, pos1 = pos2 = 1; + while (pos1 <= pos2) + { /* dequeue vertex i */ + i = list[pos1++]; + /* consider all arcs incoming to vertex i */ + for (a = G->v[i]->in; a != NULL; a = a->h_next) + { /* vertex j is adjacent to vertex i */ + j = a->tail->i; + if (prev[j] >= 0) + { /* vertex j is unlabelled */ + /* remove it from the list of unlabelled vertices */ + if (prev[j] == 0) + f = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* label the vertex */ + prev[j] = -1, next[j] = nc; + /* and enqueue it for further consideration */ + list[++pos2] = j; + } + } + /* consider all arcs outgoing from vertex i */ + for (a = G->v[i]->out; a != NULL; a = a->t_next) + { /* vertex j is adjacent to vertex i */ + j = a->head->i; + if (prev[j] >= 0) + { /* vertex j is unlabelled */ + /* remove it from the list of unlabelled vertices */ + if (prev[j] == 0) + f = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* label the vertex */ + prev[j] = -1, next[j] = nc; + /* and enqueue it for further consideration */ + list[++pos2] = j; + } + } + } + } + /* store component numbers */ + if (v_num >= 0) + { for (i = 1; i <= nv; i++) + { v = G->v[i]; + memcpy((char *)v->data + v_num, &next[i], sizeof(int)); + } + } + /* free working arrays */ + xfree(prev); + xfree(next); + xfree(list); +done: return nc; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrasn.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrasn.c new file mode 100644 index 000000000..81433da86 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrasn.c @@ -0,0 +1,107 @@ +/* wrasn.c (write assignment problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_write_asnprob - write assignment problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_asnprob writes assignment problem data in +* DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, k, count = 0, ret; + double cost; + if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) + xerror("glp_write_asnprob: v_set = %d; invalid offset\n", + v_set); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_write_asnprob: a_cost = %d; invalid offset\n", + a_cost); + xprintf("Writing assignment problem data to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + if (v_set >= 0) + memcpy(&k, (char *)v->data + v_set, sizeof(int)); + else + k = (v->out != NULL ? 0 : 1); + if (k == 0) + xfprintf(fp, "n %d\n", i), count++; + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 1.0; + xfprintf(fp, "a %d %d %.*g\n", + a->tail->i, a->head->i, DBL_DIG, cost), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcc.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcc.c new file mode 100644 index 000000000..2069c8ac2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcc.c @@ -0,0 +1,102 @@ +/* wrcc.c (write graph in DIMACS clique/coloring format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_write_ccdata - write graph in DIMACS clique/coloring format +* +* SYNOPSIS +* +* int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_ccdata writes the specified graph in DIMACS +* clique/coloring format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *e; + int i, count = 0, ret; + double w; + if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) + xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n", + v_wgt); + xprintf("Writing graph to '%s'\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++; + if (v_wgt >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy(&w, (char *)v->data + v_wgt, sizeof(double)); + if (w != 1.0) + xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++; + } + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (e = v->out; e != NULL; e = e->t_next) + xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++; + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/**********************************************************************/ + +int glp_write_graph(glp_graph *G, const char *fname) +{ return + glp_write_ccdata(G, -1, fname); +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcnf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcnf.c new file mode 100644 index 000000000..c7974386d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrcnf.c @@ -0,0 +1,87 @@ +/* wrcnf.c (write CNF-SAT problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +int glp_write_cnfsat(glp_prob *P, const char *fname) +{ /* write CNF-SAT problem data in DIMACS format */ + glp_file *fp = NULL; + GLPAIJ *aij; + int i, j, len, count = 0, ret; + char s[50]; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_cnfsat: P = %p; invalid problem object\n", + P); +#endif + if (glp_check_cnfsat(P) != 0) + { xprintf("glp_write_cnfsat: problem object does not encode CNF-" + "SAT instance\n"); + ret = 1; + goto done; + } + xprintf("Writing CNF-SAT problem data to '%s'...\n", fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + P->name == NULL ? "unknown" : P->name), count++; + xfprintf(fp, "p cnf %d %d\n", P->n, P->m), count++; + for (i = 1; i <= P->m; i++) + { len = 0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + { j = aij->col->j; + if (aij->val < 0.0) j = -j; + sprintf(s, "%d", j); + if (len > 0 && len + 1 + strlen(s) > 72) + xfprintf(fp, "\n"), count++, len = 0; + xfprintf(fp, "%s%s", len == 0 ? "" : " ", s); + if (len > 0) len++; + len += strlen(s); + } + if (len > 0 && len + 1 + 1 > 72) + xfprintf(fp, "\n"), count++, len = 0; + xfprintf(fp, "%s0\n", len == 0 ? "" : " "), count++; + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wript.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wript.c new file mode 100644 index 000000000..f2ca802c7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wript.c @@ -0,0 +1,124 @@ +/* wript.c (write interior-point solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_write_ipt - write interior-point solution in GLPK format +* +* SYNOPSIS +* +* int glp_write_ipt(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_ipt writes interior-point solution to a text +* file in GLPK format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_ipt(glp_prob *P, const char *fname) +{ glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, count, ret = 1; + char *s; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_ipt: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_write_ipt: fname = %d; invalid parameter\n", fname) + ; + xprintf("Writing interior-point solution to '%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* write comment lines */ + glp_format(fp, "c %-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name), count++; + glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++; + glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++; + glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++; + switch (P->ipt_stat) + { case GLP_OPT: s = "OPTIMAL"; break; + case GLP_INFEAS: s = "INFEASIBLE (INTERMEDIATE)"; break; + case GLP_NOFEAS: s = "INFEASIBLE (FINAL)"; break; + case GLP_UNDEF: s = "UNDEFINED"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s\n", "Status:", s), count++; + switch (P->dir) + { case GLP_MIN: s = "MINimum"; break; + case GLP_MAX: s = "MAXimum"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->ipt_obj, s), count++; + glp_format(fp, "c\n"), count++; + /* write solution line */ + glp_format(fp, "s ipt %d %d ", P->m, P->n), count++; + switch (P->ipt_stat) + { case GLP_OPT: glp_format(fp, "o"); break; + case GLP_INFEAS: glp_format(fp, "i"); break; + case GLP_NOFEAS: glp_format(fp, "n"); break; + case GLP_UNDEF: glp_format(fp, "u"); break; + default: glp_format(fp, "?"); break; + } + glp_format(fp, " %.*g\n", DBL_DIG, P->ipt_obj); + /* write row solution descriptor lines */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + glp_format(fp, "i %d %.*g %.*g\n", i, DBL_DIG, row->pval, + DBL_DIG, row->dval), count++; + } + /* write column solution descriptor lines */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + glp_format(fp, "j %d %.*g %.*g\n", j, DBL_DIG, col->pval, + DBL_DIG, col->dval), count++; + } + /* write end line */ + glp_format(fp, "e o f\n"), count++; + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* interior-point solution has been successfully written */ + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) + glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmaxf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmaxf.c new file mode 100644 index 000000000..d3101ca89 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmaxf.c @@ -0,0 +1,104 @@ +/* wrmaxf.c (write maximum flow problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_write_maxflow - write maximum flow problem data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, +* const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_maxflow writes maximum flow problem data in +* DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, count = 0, ret; + double cap; + if (!(1 <= s && s <= G->nv)) + xerror("glp_write_maxflow: s = %d; source node number out of r" + "ange\n", s); + if (!(1 <= t && t <= G->nv)) + xerror("glp_write_maxflow: t = %d: sink node number out of ran" + "ge\n", t); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cap = %d; invalid offset\n", + a_cap); + xprintf("Writing maximum flow problem data to '%s'...\n", + fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++; + xfprintf(fp, "n %d s\n", s), count++; + xfprintf(fp, "n %d t\n", t), count++; + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + xfprintf(fp, "a %d %d %.*g\n", + a->tail->i, a->head->i, DBL_DIG, cap), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmcf.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmcf.c new file mode 100644 index 000000000..0da37f421 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmcf.c @@ -0,0 +1,122 @@ +/* wrmcf.c (write min-cost flow problem data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpk.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_write_mincost - write min-cost flow probl. data in DIMACS format +* +* SYNOPSIS +* +* int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, +* int a_cost, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mincost writes minimum cost flow problem data +* in DIMACS format to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname) +{ glp_file *fp; + glp_vertex *v; + glp_arc *a; + int i, count = 0, ret; + double rhs, low, cap, cost; + if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) + xerror("glp_write_mincost: v_rhs = %d; invalid offset\n", + v_rhs); + if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_low = %d; invalid offset\n", + a_low); + if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cap = %d; invalid offset\n", + a_cap); + if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) + xerror("glp_write_mincost: a_cost = %d; invalid offset\n", + a_cost); + xprintf("Writing min-cost flow problem data to '%s'...\n", + fname); + fp = glp_open(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xfprintf(fp, "c %s\n", + G->name == NULL ? "unknown" : G->name), count++; + xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++; + if (v_rhs >= 0) + { for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); + if (rhs != 0.0) + xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++; + } + } + for (i = 1; i <= G->nv; i++) + { v = G->v[i]; + for (a = v->out; a != NULL; a = a->t_next) + { if (a_low >= 0) + memcpy(&low, (char *)a->data + a_low, sizeof(double)); + else + low = 0.0; + if (a_cap >= 0) + memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); + else + cap = 1.0; + if (a_cost >= 0) + memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); + else + cost = 0.0; + xfprintf(fp, "a %d %d %.*g %.*g %.*g\n", + a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap, + DBL_DIG, cost), count++; + } + } + xfprintf(fp, "c eof\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmip.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmip.c new file mode 100644 index 000000000..407a5fec6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrmip.c @@ -0,0 +1,122 @@ +/* wrmip.c (write MIP solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_write_mip - write MIP solution in GLPK format +* +* SYNOPSIS +* +* int glp_write_mip(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_mip writes MIP solution to a text file in GLPK +* format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_mip(glp_prob *P, const char *fname) +{ glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, count, ret = 1; + char *s; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_mip: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_write_mip: fname = %d; invalid parameter\n", fname) + ; + xprintf("Writing MIP solution to '%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* write comment lines */ + glp_format(fp, "c %-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name), count++; + glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++; + glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++; + glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++; + switch (P->mip_stat) + { case GLP_OPT: s = "INTEGER OPTIMAL"; break; + case GLP_FEAS: s = "INTEGER NON-OPTIMAL"; break; + case GLP_NOFEAS: s = "INTEGER EMPTY"; break; + case GLP_UNDEF: s = "INTEGER UNDEFINED"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s\n", "Status:", s), count++; + switch (P->dir) + { case GLP_MIN: s = "MINimum"; break; + case GLP_MAX: s = "MAXimum"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->mip_obj, s), count++; + glp_format(fp, "c\n"), count++; + /* write solution line */ + glp_format(fp, "s mip %d %d ", P->m, P->n), count++; + switch (P->mip_stat) + { case GLP_OPT: glp_format(fp, "o"); break; + case GLP_FEAS: glp_format(fp, "f"); break; + case GLP_NOFEAS: glp_format(fp, "n"); break; + case GLP_UNDEF: glp_format(fp, "u"); break; + default: glp_format(fp, "?"); break; + } + glp_format(fp, " %.*g\n", DBL_DIG, P->mip_obj); + /* write row solution descriptor lines */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + glp_format(fp, "i %d %.*g\n", i, DBL_DIG, row->mipx), count++; + } + /* write column solution descriptor lines */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + glp_format(fp, "j %d %.*g\n", j, DBL_DIG, col->mipx), count++; + } + /* write end line */ + glp_format(fp, "e o f\n"), count++; + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* MIP solution has been successfully written */ + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) + glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrprob.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrprob.c new file mode 100644 index 000000000..99983d35f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrprob.c @@ -0,0 +1,166 @@ +/* wrprob.c (write problem data in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +#define xfprintf glp_format + +/*********************************************************************** +* NAME +* +* glp_write_prob - write problem data in GLPK format +* +* SYNOPSIS +* +* int glp_write_prob(glp_prob *P, int flags, const char *fname); +* +* The routine glp_write_prob writes problem data in GLPK LP/MIP format +* to a text file. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_prob(glp_prob *P, int flags, const char *fname) +{ glp_file *fp; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int mip, i, j, count, ret; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_prob: P = %p; invalid problem object\n", + P); +#endif + if (flags != 0) + xerror("glp_write_prob: flags = %d; invalid parameter\n", + flags); + if (fname == NULL) + xerror("glp_write_prob: fname = %d; invalid parameter\n", + fname); + xprintf("Writing problem data to '%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + /* write problem line */ + mip = (glp_get_num_int(P) > 0); + xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip", + P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???", + P->m, P->n, P->nnz), count++; + if (P->name != NULL) + xfprintf(fp, "n p %s\n", P->name), count++; + if (P->obj != NULL) + xfprintf(fp, "n z %s\n", P->obj), count++; + /* write row descriptors */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_FX && row->lb == 0.0) + goto skip1; + xfprintf(fp, "i %d ", i), count++; + if (row->type == GLP_FR) + xfprintf(fp, "f\n"); + else if (row->type == GLP_LO) + xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb); + else if (row->type == GLP_UP) + xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub); + else if (row->type == GLP_DB) + xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG, + row->ub); + else if (row->type == GLP_FX) + xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb); + else + xassert(row != row); +skip1: if (row->name != NULL) + xfprintf(fp, "n i %d %s\n", i, row->name), count++; + } + /* write column descriptors */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (!mip && col->type == GLP_LO && col->lb == 0.0) + goto skip2; + if (mip && col->kind == GLP_IV && col->type == GLP_DB && + col->lb == 0.0 && col->ub == 1.0) + goto skip2; + xfprintf(fp, "j %d ", j), count++; + if (mip) + { if (col->kind == GLP_CV) + xfprintf(fp, "c "); + else if (col->kind == GLP_IV) + xfprintf(fp, "i "); + else + xassert(col != col); + } + if (col->type == GLP_FR) + xfprintf(fp, "f\n"); + else if (col->type == GLP_LO) + xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb); + else if (col->type == GLP_UP) + xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub); + else if (col->type == GLP_DB) + xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG, + col->ub); + else if (col->type == GLP_FX) + xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb); + else + xassert(col != col); +skip2: if (col->name != NULL) + xfprintf(fp, "n j %d %s\n", j, col->name), count++; + } + /* write objective coefficient descriptors */ + if (P->c0 != 0.0) + xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->coef != 0.0) + xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef), + count++; + } + /* write constraint coefficient descriptors */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG, + aij->val), count++; + } + /* write end line */ + xfprintf(fp, "e o f\n"), count++; +#if 0 /* FIXME */ + xfflush(fp); +#endif + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + ret = 1; + goto done; + } + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/api/wrsol.c b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrsol.c new file mode 100644 index 000000000..66c692337 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/api/wrsol.c @@ -0,0 +1,174 @@ +/* wrsol.c (write basic solution in GLPK format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2010-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_write_sol - write basic solution in GLPK format +* +* SYNOPSIS +* +* int glp_write_sol(glp_prob *P, const char *fname); +* +* DESCRIPTION +* +* The routine glp_write_sol writes basic solution to a text file in +* GLPK format. +* +* RETURNS +* +* If the operation was successful, the routine returns zero. Otherwise +* it prints an error message and returns non-zero. */ + +int glp_write_sol(glp_prob *P, const char *fname) +{ glp_file *fp; + GLPROW *row; + GLPCOL *col; + int i, j, count, ret = 1; + char *s; +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_write_sol: P = %p; invalid problem object\n", P); +#endif + if (fname == NULL) + xerror("glp_write_sol: fname = %d; invalid parameter\n", fname) + ; + xprintf("Writing basic solution to '%s'...\n", fname); + fp = glp_open(fname, "w"), count = 0; + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* write comment lines */ + glp_format(fp, "c %-12s%s\n", "Problem:", + P->name == NULL ? "" : P->name), count++; + glp_format(fp, "c %-12s%d\n", "Rows:", P->m), count++; + glp_format(fp, "c %-12s%d\n", "Columns:", P->n), count++; + glp_format(fp, "c %-12s%d\n", "Non-zeros:", P->nnz), count++; + switch (glp_get_status(P)) + { case GLP_OPT: s = "OPTIMAL"; break; + case GLP_FEAS: s = "FEASIBLE"; break; + case GLP_INFEAS: s = "INFEASIBLE (INTERMEDIATE)"; break; + case GLP_NOFEAS: s = "INFEASIBLE (FINAL)"; break; + case GLP_UNBND: s = "UNBOUNDED"; break; + case GLP_UNDEF: s = "UNDEFINED"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s\n", "Status:", s), count++; + switch (P->dir) + { case GLP_MIN: s = "MINimum"; break; + case GLP_MAX: s = "MAXimum"; break; + default: s = "???"; break; + } + glp_format(fp, "c %-12s%s%s%.10g (%s)\n", "Objective:", + P->obj == NULL ? "" : P->obj, + P->obj == NULL ? "" : " = ", P->obj_val, s), count++; + glp_format(fp, "c\n"), count++; + /* write solution line */ + glp_format(fp, "s bas %d %d ", P->m, P->n), count++; + switch (P->pbs_stat) + { case GLP_UNDEF: glp_format(fp, "u"); break; + case GLP_FEAS: glp_format(fp, "f"); break; + case GLP_INFEAS: glp_format(fp, "i"); break; + case GLP_NOFEAS: glp_format(fp, "n"); break; + default: glp_format(fp, "?"); break; + } + glp_format(fp, " "); + switch (P->dbs_stat) + { case GLP_UNDEF: glp_format(fp, "u"); break; + case GLP_FEAS: glp_format(fp, "f"); break; + case GLP_INFEAS: glp_format(fp, "i"); break; + case GLP_NOFEAS: glp_format(fp, "n"); break; + default: glp_format(fp, "?"); break; + } + glp_format(fp, " %.*g\n", DBL_DIG, P->obj_val); + /* write row solution descriptor lines */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + glp_format(fp, "i %d ", i), count++; + switch (row->stat) + { case GLP_BS: + glp_format(fp, "b"); + break; + case GLP_NL: + glp_format(fp, "l"); + break; + case GLP_NU: + glp_format(fp, "u"); + break; + case GLP_NF: + glp_format(fp, "f"); + break; + case GLP_NS: + glp_format(fp, "s"); + break; + default: + xassert(row != row); + } + glp_format(fp, " %.*g %.*g\n", DBL_DIG, row->prim, DBL_DIG, + row->dual); + } + /* write column solution descriptor lines */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + glp_format(fp, "j %d ", j), count++; + switch (col->stat) + { case GLP_BS: + glp_format(fp, "b"); + break; + case GLP_NL: + glp_format(fp, "l"); + break; + case GLP_NU: + glp_format(fp, "u"); + break; + case GLP_NF: + glp_format(fp, "f"); + break; + case GLP_NS: + glp_format(fp, "s"); + break; + default: + xassert(col != col); + } + glp_format(fp, " %.*g %.*g\n", DBL_DIG, col->prim, DBL_DIG, + col->dual); + } + /* write end line */ + glp_format(fp, "e o f\n"), count++; + if (glp_ioerr(fp)) + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); + goto done; + } + /* basic solution has been successfully written */ + xprintf("%d lines were written\n", count); + ret = 0; +done: if (fp != NULL) + glp_close(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.c new file mode 100644 index 000000000..993c9ca17 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.c @@ -0,0 +1,569 @@ +/* btf.c (sparse block triangular LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "btf.h" +#include "env.h" +#include "luf.h" +#include "mc13d.h" +#include "mc21a.h" + +/*********************************************************************** +* btf_store_a_cols - store pattern of matrix A in column-wise format +* +* This routine stores the pattern (that is, only indices of non-zero +* elements) of the original matrix A in column-wise format. +* +* On exit the routine returns the number of non-zeros in matrix A. */ + +int btf_store_a_cols(BTF *btf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int j, len, ptr, nnz; + nnz = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = col(info, j, ind, val); + xassert(0 <= len && len <= n); + /* reserve locations for j-th column */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + } + sva_reserve_cap(sva, ac_ref+(j-1), len); + } + /* store pattern of j-th column */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + ac_len[j] = len; + nnz += len; + } + return nnz; +} + +/*********************************************************************** +* btf_make_blocks - permutations to block triangular form +* +* This routine analyzes the pattern of the original matrix A and +* determines permutation matrices P and Q such that A = P * A~* Q, +* where A~ is an upper block triangular matrix. +* +* On exit the routine returns symbolic rank of matrix A. */ + +int btf_make_blocks(BTF *btf) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int *pp_ind = btf->pp_ind; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *qq_inv = btf->qq_inv; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, j, rank, *iperm, *pr, *arp, *cv, *out, *ip, *lenr, *lowl, + *numb, *prev; + /* determine column permutation matrix M such that matrix A * M + * has zero-free diagonal */ + iperm = qq_inv; /* matrix M */ + pr = btf->p1_ind; /* working array */ + arp = btf->p1_inv; /* working array */ + cv = btf->q1_ind; /* working array */ + out = btf->q1_inv; /* working array */ + rank = mc21a(n, sv_ind, ac_ptr, ac_len, iperm, pr, arp, cv, out); + xassert(0 <= rank && rank <= n); + if (rank < n) + { /* A is structurally singular (rank is its symbolic rank) */ + goto done; + } + /* build pattern of matrix A * M */ + ip = pp_ind; /* working array */ + lenr = qq_ind; /* working array */ + for (j = 1; j <= n; j++) + { ip[j] = ac_ptr[iperm[j]]; + lenr[j] = ac_len[iperm[j]]; + } + /* determine symmetric permutation matrix S such that matrix + * S * (A * M) * S' = A~ is upper block triangular */ + lowl = btf->p1_ind; /* working array */ + numb = btf->p1_inv; /* working array */ + prev = btf->q1_ind; /* working array */ + btf->num = + mc13d(n, sv_ind, ip, lenr, pp_inv, beg, lowl, numb, prev); + xassert(beg[1] == 1); + beg[btf->num+1] = n+1; + /* A * M = S' * A~ * S ==> A = S' * A~ * (S * M') */ + /* determine permutation matrix P = S' */ + for (j = 1; j <= n; j++) + pp_ind[pp_inv[j]] = j; + /* determine permutation matrix Q = S * M' = P' * M' */ + for (i = 1; i <= n; i++) + qq_ind[i] = iperm[pp_inv[i]]; + for (i = 1; i <= n; i++) + qq_inv[qq_ind[i]] = i; +done: return rank; +} + +/*********************************************************************** +* btf_check_blocks - check structure of matrix A~ +* +* This routine checks that structure of upper block triangular matrix +* A~ is correct. +* +* NOTE: For testing/debugging only. */ + +void btf_check_blocks(BTF *btf) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int *pp_ind = btf->pp_ind; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *qq_inv = btf->qq_inv; + int num = btf->num; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, ii, j, jj, k, size, ptr, end, diag; + xassert(n > 0); + /* check permutation matrices P and Q */ + for (k = 1; k <= n; k++) + { xassert(1 <= pp_ind[k] && pp_ind[k] <= n); + xassert(pp_inv[pp_ind[k]] == k); + xassert(1 <= qq_ind[k] && qq_ind[k] <= n); + xassert(qq_inv[qq_ind[k]] == k); + } + /* check that matrix A~ is upper block triangular with non-zero + * diagonal */ + xassert(1 <= num && num <= n); + xassert(beg[1] == 1); + xassert(beg[num+1] == n+1); + /* walk thru blocks of A~ */ + for (k = 1; k <= num; k++) + { /* determine size of k-th block */ + size = beg[k+1] - beg[k]; + xassert(size >= 1); + /* walk thru columns of k-th block */ + for (jj = beg[k]; jj < beg[k+1]; jj++) + { diag = 0; + /* jj-th column of A~ = j-th column of A */ + j = qq_ind[jj]; + /* walk thru elements of j-th column of A */ + ptr = ac_ptr[j]; + end = ptr + ac_len[j]; + for (; ptr < end; ptr++) + { /* determine row index of a[i,j] */ + i = sv_ind[ptr]; + /* i-th row of A = ii-th row of A~ */ + ii = pp_ind[i]; + /* a~[ii,jj] should not be below k-th block */ + xassert(ii < beg[k+1]); + if (ii == jj) + { /* non-zero diagonal element of A~ encountered */ + diag = 1; + } + } + xassert(diag); + } + } + return; +} + +/*********************************************************************** +* btf_build_a_rows - build matrix A in row-wise format +* +* This routine builds the row-wise representation of matrix A in the +* right part of SVA using its column-wise representation. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void btf_build_a_rows(BTF *btf, int len[/*1+n*/]) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix A and + * the total number of non-zeros */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += ac_len[j]; + for (end = (ptr = ac_ptr[j]) + ac_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix A */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_reserve_cap(sva, ar_ref-1+i, len[i]); + ar_len[i] = len[i]; + } + /* walk thru columns of matrix A and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = ac_ptr[j]) + ac_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = ar_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* btf_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where A is the original +* matrix. +* +* On entry the array b should contain elements of the right-hand size +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_a_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + double *bb = w1; + double *xx = w2; + LUF luf; + int i, j, jj, k, beg_k, flag; + double t; + for (k = num; k >= 1; k--) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* solve system A~[k,k] * X[k] = B[k] */ + t = x[qq_ind[beg_k]] = + b[pp_inv[beg_k]] / btf->vr_piv[beg_k]; + /* substitute X[k] into other equations */ + if (t != 0.0) + { int ptr = ac_ptr[qq_ind[beg_k]]; + int end = ptr + ac_len[qq_ind[beg_k]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + else + { /* general case */ + /* construct B[k] */ + flag = 0; + for (i = 1; i <= luf.n; i++) + { if ((bb[i] = b[pp_inv[i + (beg_k-1)]]) != 0.0) + flag = 1; + } + /* solve system A~[k,k] * X[k] = B[k] */ + if (!flag) + { /* B[k] = 0, so X[k] = 0 */ + for (j = 1; j <= luf.n; j++) + x[qq_ind[j + (beg_k-1)]] = 0.0; + continue; + } + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_f_solve(&luf, bb); + luf_v_solve(&luf, bb, xx); + /* store X[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + t = x[qq_ind[jj]] = xx[j]; + if (t != 0.0) + { int ptr = ac_ptr[qq_ind[jj]]; + int end = ptr + ac_len[qq_ind[jj]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + } + } + return; +} + +/*********************************************************************** +* btf_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the original matrix A. +* +* On entry the array b should contain elements of the right-hand size +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_at_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + double *bb = w1; + double *xx = w2; + LUF luf; + int i, j, jj, k, beg_k, flag; + double t; + for (k = 1; k <= num; k++) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* solve system A~'[k,k] * X[k] = B[k] */ + t = x[pp_inv[beg_k]] = + b[qq_ind[beg_k]] / btf->vr_piv[beg_k]; + /* substitute X[k] into other equations */ + if (t != 0.0) + { int ptr = ar_ptr[pp_inv[beg_k]]; + int end = ptr + ar_len[pp_inv[beg_k]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + else + { /* general case */ + /* construct B[k] */ + flag = 0; + for (i = 1; i <= luf.n; i++) + { if ((bb[i] = b[qq_ind[i + (beg_k-1)]]) != 0.0) + flag = 1; + } + /* solve system A~'[k,k] * X[k] = B[k] */ + if (!flag) + { /* B[k] = 0, so X[k] = 0 */ + for (j = 1; j <= luf.n; j++) + x[pp_inv[j + (beg_k-1)]] = 0.0; + continue; + } + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_vt_solve(&luf, bb, xx); + luf_ft_solve(&luf, xx); + /* store X[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + t = x[pp_inv[jj]] = xx[j]; + if (t != 0.0) + { int ptr = ar_ptr[pp_inv[jj]]; + int end = ptr + ar_len[pp_inv[jj]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + } + } + return; +} + +/*********************************************************************** +* btf_at_solve1 - solve system A'* y = e' to cause growth in y +* +* This routine is a special version of btf_at_solve. It solves the +* system A'* y = e' = e + delta e, where A' is a matrix transposed to +* the original matrix A, e is the specified right-hand side vector, +* and delta e is a vector of +1 and -1 chosen to cause growth in the +* solution vector y. +* +* On entry the array e should contain elements of the right-hand size +* vector e in locations e[1], ..., e[n], where n is the order of the +* matrix A. On exit the array y will contain elements of the solution +* vector in locations y[1], ..., y[n]. Note that the array e will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_at_solve1(BTF *btf, double e[/*1+n*/], double y[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + double *ee = w1; + double *yy = w2; + LUF luf; + int i, j, jj, k, beg_k, ptr, end; + double e_k, y_k; + for (k = 1; k <= num; k++) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* determine E'[k] = E[k] + delta E[k] */ + e_k = e[qq_ind[beg_k]]; + e_k = (e_k >= 0.0 ? e_k + 1.0 : e_k - 1.0); + /* solve system A~'[k,k] * Y[k] = E[k] */ + y_k = y[pp_inv[beg_k]] = e_k / btf->vr_piv[beg_k]; + /* substitute Y[k] into other equations */ + ptr = ar_ptr[pp_inv[beg_k]]; + end = ptr + ar_len[pp_inv[beg_k]]; + for (; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_k; + } + else + { /* general case */ + /* construct E[k] */ + for (i = 1; i <= luf.n; i++) + ee[i] = e[qq_ind[i + (beg_k-1)]]; + /* solve system A~'[k,k] * Y[k] = E[k] + delta E[k] */ + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_vt_solve1(&luf, ee, yy); + luf_ft_solve(&luf, yy); + /* store Y[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + y_k = y[pp_inv[jj]] = yy[j]; + ptr = ar_ptr[pp_inv[jj]]; + end = ptr + ar_len[pp_inv[jj]]; + for (; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_k; + } + } + } + return; +} + +/*********************************************************************** +* btf_estimate_norm - estimate 1-norm of inv(A) +* +* This routine estimates 1-norm of inv(A) by one step of inverse +* iteration for the small singular vector as described in [1]. This +* involves solving two systems of equations: +* +* A'* y = e, +* +* A * z = y, +* +* where A' is a matrix transposed to A, and e is a vector of +1 and -1 +* chosen to cause growth in y. Then +* +* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) +* +* REFERENCES +* +* 1. G.E.Forsythe, M.A.Malcolm, C.B.Moler. Computer Methods for +* Mathematical Computations. Prentice-Hall, Englewood Cliffs, N.J., +* pp. 30-62 (subroutines DECOMP and SOLVE). */ + +double btf_estimate_norm(BTF *btf, double w1[/*1+n*/], double + w2[/*1+n*/], double w3[/*1+n*/], double w4[/*1+n*/]) +{ int n = btf->n; + double *e = w1; + double *y = w2; + double *z = w1; + int i; + double y_norm, z_norm; + /* compute y = inv(A') * e to cause growth in y */ + for (i = 1; i <= n; i++) + e[i] = 0.0; + btf_at_solve1(btf, e, y, w3, w4); + /* compute 1-norm of y = sum |y[i]| */ + y_norm = 0.0; + for (i = 1; i <= n; i++) + y_norm += (y[i] >= 0.0 ? +y[i] : -y[i]); + /* compute z = inv(A) * y */ + btf_a_solve(btf, y, z, w3, w4); + /* compute 1-norm of z = sum |z[i]| */ + z_norm = 0.0; + for (i = 1; i <= n; i++) + z_norm += (z[i] >= 0.0 ? +z[i] : -z[i]); + /* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) */ + return z_norm / y_norm; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.h new file mode 100644 index 000000000..3f1b59265 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btf.h @@ -0,0 +1,207 @@ +/* btf.h (sparse block triangular LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BTF_H +#define BTF_H + +#include "sva.h" + +/*********************************************************************** +* The structure BTF describes BT-factorization, which is sparse block +* triangular LU-factorization. +* +* The BT-factorization has the following format: +* +* A = P * A~ * Q, (1) +* +* where A is a given (unsymmetric) square matrix, A~ is an upper block +* triangular matrix (see below), P and Q are permutation matrices. All +* the matrices have the same order n. +* +* The matrix A~, which is a permuted version of the original matrix A, +* has the following structure: +* +* A~[1,1] A~[1,2] ... A~[1,num-1] A~[1,num] +* +* A~[2,2] ... A~[2,num-1] A~[2,num] +* +* . . . . . . . . . (2) +* +* A~[num-1,num-1] A~[num-1,num] +* +* A~[num,num] +* +* where A~[i,j] is a submatrix called a "block," num is the number of +* blocks. Each diagonal block A~[k,k] is a non-singular square matrix, +* and each subdiagonal block A~[i,j], i > j, is a zero submatrix, thus +* A~ is an upper block triangular matrix. +* +* Permutation matrices P and Q are stored in ordinary arrays in both +* row- and column-like formats. +* +* The original matrix A is stored in both row- and column-wise sparse +* formats in the associated sparse vector area (SVA). Should note that +* elements of all diagonal blocks A~[k,k] in matrix A are set to zero +* (i.e. removed), so only elements of non-diagonal blocks are stored. +* +* Each diagonal block A~[k,k], 1 <= k <= num, is stored in the form of +* LU-factorization (see the module LUF). */ + +typedef struct BTF BTF; + +struct BTF +{ /* sparse block triangular LU-factorization */ + int n; + /* order of matrices A, A~, P, Q */ + SVA *sva; + /* associated sparse vector area used to store rows and columns + * of matrix A as well as sparse vectors for LU-factorizations of + * all diagonal blocks A~[k,k] */ + /*--------------------------------------------------------------*/ + /* matrix P */ + int *pp_ind; /* int pp_ind[1+n]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /* if i-th row of matrix A is i'-th row of matrix A~, then + * pp_ind[i] = i' and pp_inv[i'] = i */ + /*--------------------------------------------------------------*/ + /* matrix Q */ + int *qq_ind; /* int qq_ind[1+n]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ + /* if j-th column of matrix A is j'-th column of matrix A~, then + * qq_ind[j'] = j and qq_inv[j] = j' */ + /*--------------------------------------------------------------*/ + /* block triangular structure of matrix A~ */ + int num; + /* number of diagonal blocks, 1 <= num <= n */ + int *beg; /* int beg[1+num+1]; */ + /* beg[0] is not used; + * beg[k], 1 <= k <= num, is index of first row/column of k-th + * block of matrix A~; + * beg[num+1] is always n+1; + * note that order (size) of k-th diagonal block can be computed + * as beg[k+1] - beg[k] */ + /*--------------------------------------------------------------*/ + /* original matrix A in row-wise format */ + /* NOTE: elements of all diagonal blocks A~[k,k] are removed */ + int ar_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix A */ +#if 0 + 0 + int *ar_ptr = &sva->ptr[ar_ref-1]; + /* ar_ptr[0] is not used; + * ar_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *ar_len = &sva->ptr[ar_ref-1]; + /* ar_len[0] is not used; + * ar_len[i], 1 <= i <= n, is length of i-th row */ +#endif + /*--------------------------------------------------------------*/ + /* original matrix A in column-wise format */ + /* NOTE: elements of all diagonal blocks A~[k,k] are removed */ + int ac_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix A */ +#if 0 + 0 + int *ac_ptr = &sva->ptr[ac_ref-1]; + /* ac_ptr[0] is not used; + * ac_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *ac_len = &sva->ptr[ac_ref-1]; + /* ac_len[0] is not used; + * ac_len[j], 1 <= j <= n, is length of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* LU-factorizations of diagonal blocks A~[k,k] */ + /* to decrease overhead expenses similar arrays for all LUFs are + * packed into a single array; for example, elements fr_ptr[1], + * ..., fr_ptr[n1], where n1 = beg[2] - beg[1], are related to + * LUF for first diagonal block A~[1,1], elements fr_ptr[n1+1], + * ..., fr_ptr[n1+n2], where n2 = beg[3] - beg[2], are related to + * LUF for second diagonal block A~[2,2], etc.; in other words, + * elements related to LUF for k-th diagonal block A~[k,k] have + * indices beg[k], beg[k]+1, ..., beg[k+1]-1 */ + /* for details about LUF see description of the LUF module */ + int fr_ref; + /* reference number of sparse vector in SVA, which is the first + row of matrix F for first diagonal block A~[1,1] */ + int fc_ref; + /* reference number of sparse vector in SVA, which is the first + column of matrix F for first diagonal block A~[1,1] */ + int vr_ref; + /* reference number of sparse vector in SVA, which is the first + row of matrix V for first diagonal block A~[1,1] */ + double *vr_piv; /* double vr_piv[1+n]; */ + /* vr_piv[0] is not used; + vr_piv[1,...,n] are pivot elements for all diagonal blocks */ + int vc_ref; + /* reference number of sparse vector in SVA, which is the first + column of matrix V for first diagonal block A~[1,1] */ + int *p1_ind; /* int p1_ind[1+n]; */ + int *p1_inv; /* int p1_inv[1+n]; */ + int *q1_ind; /* int q1_ind[1+n]; */ + int *q1_inv; /* int q1_inv[1+n]; */ + /* permutation matrices P and Q for all diagonal blocks */ +}; + +#define btf_store_a_cols _glp_btf_store_a_cols +int btf_store_a_cols(BTF *btf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]); +/* store pattern of matrix A in column-wise format */ + +#define btf_make_blocks _glp_btf_make_blocks +int btf_make_blocks(BTF *btf); +/* permutations to block triangular form */ + +#define btf_check_blocks _glp_btf_check_blocks +void btf_check_blocks(BTF *btf); +/* check structure of matrix A~ */ + +#define btf_build_a_rows _glp_btf_build_a_rows +void btf_build_a_rows(BTF *btf, int len[/*1+n*/]); +/* build matrix A in row-wise format */ + +#define btf_a_solve _glp_btf_a_solve +void btf_a_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A * x = b */ + +#define btf_at_solve _glp_btf_at_solve +void btf_at_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A'* x = b */ + +#define btf_at_solve1 _glp_btf_at_solve1 +void btf_at_solve1(BTF *btf, double e[/*1+n*/], double y[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A'* y = e' to cause growth in y */ + +#define btf_estimate_norm _glp_btf_estimate_norm +double btf_estimate_norm(BTF *btf, double w1[/*1+n*/], double + w2[/*1+n*/], double w3[/*1+n*/], double w4[/*1+n*/]); +/* estimate 1-norm of inv(A) */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.c new file mode 100644 index 000000000..378d3a816 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.c @@ -0,0 +1,407 @@ +/* btfint.c (interface to BT-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "btfint.h" + +BTFINT *btfint_create(void) +{ /* create interface to BT-factorization */ + BTFINT *fi; + fi = talloc(1, BTFINT); + fi->n_max = 0; + fi->valid = 0; + fi->sva = NULL; + fi->btf = NULL; + fi->sgf = NULL; + fi->sva_n_max = fi->sva_size = 0; + fi->delta_n0 = fi->delta_n = 0; + fi->sgf_piv_tol = 0.10; + fi->sgf_piv_lim = 4; + fi->sgf_suhl = 1; + fi->sgf_eps_tol = DBL_EPSILON; + return fi; +} + +static void factorize_triv(BTFINT *fi, int k, int (*col)(void *info, + int j, int ind[], double val[]), void *info) +{ /* compute LU-factorization of diagonal block A~[k,k] and store + * corresponding columns of matrix A except elements of A~[k,k] + * (trivial case when the block has unity size) */ + SVA *sva = fi->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + BTF *btf = fi->btf; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + SGF *sgf = fi->sgf; + int *ind = (int *)sgf->vr_max; /* working array */ + double *val = sgf->work; /* working array */ + int i, j, t, len, ptr, beg_k; + /* diagonal block A~[k,k] has the only element in matrix A~, + * which is a~[beg[k],beg[k]] = a[i,j] */ + beg_k = beg[k]; + i = pp_inv[beg_k]; + j = qq_ind[beg_k]; + /* get j-th column of A */ + len = col(info, j, ind, val); + /* find element a[i,j] = a~[beg[k],beg[k]] in j-th column */ + for (t = 1; t <= len; t++) + { if (ind[t] == i) + break; + } + xassert(t <= len); + /* compute LU-factorization of diagonal block A~[k,k], where + * F = (1), V = (a[i,j]), P = Q = (1) (see the module LUF) */ +#if 1 /* FIXME */ + xassert(val[t] != 0.0); +#endif + btf->vr_piv[beg_k] = val[t]; + btf->p1_ind[beg_k] = btf->p1_inv[beg_k] = 1; + btf->q1_ind[beg_k] = btf->q1_inv[beg_k] = 1; + /* remove element a[i,j] = a~[beg[k],beg[k]] from j-th column */ + memmove(&ind[t], &ind[t+1], (len-t) * sizeof(int)); + memmove(&val[t], &val[t+1], (len-t) * sizeof(double)); + len--; + /* and store resulting j-th column of A into BTF */ + if (len > 0) + { /* reserve locations for j-th column of A */ + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ac_ref+(j-1), len); + /* store j-th column of A (except elements of A~[k,k]) */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + ac_len[j] = len; + } + return; +} + +static int factorize_block(BTFINT *fi, int k, int (*col)(void *info, + int j, int ind[], double val[]), void *info) +{ /* compute LU-factorization of diagonal block A~[k,k] and store + * corresponding columns of matrix A except elements of A~[k,k] + * (general case) */ + SVA *sva = fi->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + BTF *btf = fi->btf; + int *pp_ind = btf->pp_ind; + int *qq_ind = btf->qq_ind; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + SGF *sgf = fi->sgf; + int *ind = (int *)sgf->vr_max; /* working array */ + double *val = sgf->work; /* working array */ + LUF luf; + int *vc_ptr, *vc_len, *vc_cap; + int i, ii, j, jj, t, len, cnt, ptr, beg_k; + /* construct fake LUF for LU-factorization of A~[k,k] */ + sgf->luf = &luf; + luf.n = beg[k+1] - (beg_k = beg[k]); + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + /* process columns of k-th block of matrix A~ */ + vc_ptr = &sva->ptr[luf.vc_ref-1]; + vc_len = &sva->len[luf.vc_ref-1]; + vc_cap = &sva->cap[luf.vc_ref-1]; + for (jj = 1; jj <= luf.n; jj++) + { /* jj-th column of A~ = j-th column of A */ + j = qq_ind[jj + (beg_k-1)]; + /* get j-th column of A */ + len = col(info, j, ind, val); + /* move elements of diagonal block A~[k,k] to the beginning of + * the column list */ + cnt = 0; + for (t = 1; t <= len; t++) + { /* i = row index of element a[i,j] */ + i = ind[t]; + /* i-th row of A = ii-th row of A~ */ + ii = pp_ind[i]; + if (ii >= beg_k) + { /* a~[ii,jj] = a[i,j] is in diagonal block A~[k,k] */ + double temp; + cnt++; + ind[t] = ind[cnt]; + ind[cnt] = ii - (beg_k-1); /* local index */ + temp = val[t], val[t] = val[cnt], val[cnt] = temp; + } + } + /* first cnt elements in the column list give jj-th column of + * diagonal block A~[k,k], which is initial matrix V in LUF */ + /* enlarge capacity of jj-th column of V = A~[k,k] */ + if (vc_cap[jj] < cnt) + { if (sva->r_ptr - sva->m_ptr < cnt) + { sva_more_space(sva, cnt); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, luf.vc_ref+(jj-1), cnt, 0); + } + /* store jj-th column of V = A~[k,k] */ + ptr = vc_ptr[jj]; + memcpy(&sv_ind[ptr], &ind[1], cnt * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], cnt * sizeof(double)); + vc_len[jj] = cnt; + /* other (len-cnt) elements in the column list are stored in + * j-th column of the original matrix A */ + len -= cnt; + if (len > 0) + { /* reserve locations for j-th column of A */ + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ac_ref-1+j, len); + /* store j-th column of A (except elements of A~[k,k]) */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[cnt+1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[cnt+1], len * sizeof(double)); + ac_len[j] = len; + } + } + /* compute LU-factorization of diagonal block A~[k,k]; may note + * that A~[k,k] is irreducible (strongly connected), so singleton + * phase will have no effect */ + k = sgf_factorize(sgf, 0 /* disable singleton phase */); + /* now left (dynamic) part of SVA should be empty (wichtig!) */ + xassert(sva->m_ptr == 1); + return k; +} + +int btfint_factorize(BTFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute BT-factorization of specified matrix A */ + SVA *sva; + BTF *btf; + SGF *sgf; + int k, rank; + xassert(n > 0); + fi->valid = 0; + /* create sparse vector area (SVA), if necessary */ + sva = fi->sva; + if (sva == NULL) + { int sva_n_max = fi->sva_n_max; + int sva_size = fi->sva_size; + if (sva_n_max == 0) + sva_n_max = 6 * n; + if (sva_size == 0) + sva_size = 10 * n; + sva = fi->sva = sva_create_area(sva_n_max, sva_size); + } + /* allocate/reallocate underlying objects, if necessary */ + if (fi->n_max < n) + { int n_max = fi->n_max; + if (n_max == 0) + n_max = fi->n_max = n + fi->delta_n0; + else + n_max = fi->n_max = n + fi->delta_n; + xassert(n_max >= n); + /* allocate/reallocate block triangular factorization (BTF) */ + btf = fi->btf; + if (btf == NULL) + { btf = fi->btf = talloc(1, BTF); + memset(btf, 0, sizeof(BTF)); + btf->sva = sva; + } + else + { tfree(btf->pp_ind); + tfree(btf->pp_inv); + tfree(btf->qq_ind); + tfree(btf->qq_inv); + tfree(btf->beg); + tfree(btf->vr_piv); + tfree(btf->p1_ind); + tfree(btf->p1_inv); + tfree(btf->q1_ind); + tfree(btf->q1_inv); + } + btf->pp_ind = talloc(1+n_max, int); + btf->pp_inv = talloc(1+n_max, int); + btf->qq_ind = talloc(1+n_max, int); + btf->qq_inv = talloc(1+n_max, int); + btf->beg = talloc(1+n_max+1, int); + btf->vr_piv = talloc(1+n_max, double); + btf->p1_ind = talloc(1+n_max, int); + btf->p1_inv = talloc(1+n_max, int); + btf->q1_ind = talloc(1+n_max, int); + btf->q1_inv = talloc(1+n_max, int); + /* allocate/reallocate factorizer workspace (SGF) */ + /* (note that for SGF we could use the size of largest block + * rather than n_max) */ + sgf = fi->sgf; + sgf = fi->sgf; + if (sgf == NULL) + { sgf = fi->sgf = talloc(1, SGF); + memset(sgf, 0, sizeof(SGF)); + } + else + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + } + sgf->rs_head = talloc(1+n_max, int); + sgf->rs_prev = talloc(1+n_max, int); + sgf->rs_next = talloc(1+n_max, int); + sgf->cs_head = talloc(1+n_max, int); + sgf->cs_prev = talloc(1+n_max, int); + sgf->cs_next = talloc(1+n_max, int); + sgf->vr_max = talloc(1+n_max, double); + sgf->flag = talloc(1+n_max, char); + sgf->work = talloc(1+n_max, double); + } + btf = fi->btf; + btf->n = n; + sgf = fi->sgf; +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* store pattern of original matrix A in column-wise format */ + btf->ac_ref = sva_alloc_vecs(btf->sva, btf->n); + btf_store_a_cols(btf, col, info, btf->pp_ind, btf->vr_piv); +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* analyze pattern of original matrix A and determine permutation + * matrices P and Q such that A = P * A~* Q, where A~ is an upper + * block triangular matrix */ + rank = btf_make_blocks(btf); + if (rank != n) + { /* original matrix A is structurally singular */ + return 1; + } +#ifdef GLP_DEBUG + btf_check_blocks(btf); +#endif +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* allocate sparse vectors in SVA */ + btf->ar_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->ac_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->fr_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->fc_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->vr_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->vc_ref = sva_alloc_vecs(btf->sva, btf->n); + /* setup factorizer control parameters */ + sgf->updat = 0; /* wichtig! */ + sgf->piv_tol = fi->sgf_piv_tol; + sgf->piv_lim = fi->sgf_piv_lim; + sgf->suhl = fi->sgf_suhl; + sgf->eps_tol = fi->sgf_eps_tol; + /* compute LU-factorizations of diagonal blocks A~[k,k] and also + * store corresponding columns of matrix A except elements of all + * blocks A~[k,k] */ + for (k = 1; k <= btf->num; k++) + { if (btf->beg[k+1] - btf->beg[k] == 1) + { /* trivial case (A~[k,k] has unity order) */ + factorize_triv(fi, k, col, info); + } + else + { /* general case */ + if (factorize_block(fi, k, col, info) != 0) + return 2; /* factorization of A~[k,k] failed */ + } + } +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* build row-wise representation of matrix A */ + btf_build_a_rows(fi->btf, fi->sgf->rs_head); +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* BT-factorization has been successfully computed */ + fi->valid = 1; + return 0; +} + +void btfint_delete(BTFINT *fi) +{ /* delete interface to BT-factorization */ + SVA *sva = fi->sva; + BTF *btf = fi->btf; + SGF *sgf = fi->sgf; + if (sva != NULL) + sva_delete_area(sva); + if (btf != NULL) + { tfree(btf->pp_ind); + tfree(btf->pp_inv); + tfree(btf->qq_ind); + tfree(btf->qq_inv); + tfree(btf->beg); + tfree(btf->vr_piv); + tfree(btf->p1_ind); + tfree(btf->p1_inv); + tfree(btf->q1_ind); + tfree(btf->q1_inv); + tfree(btf); + } + if (sgf != NULL) + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + tfree(sgf); + } + tfree(fi); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.h new file mode 100644 index 000000000..8d0e70e21 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/btfint.h @@ -0,0 +1,73 @@ +/* btfint.h (interface to BT-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BTFINT_H +#define BTFINT_H + +#include "btf.h" +#include "sgf.h" + +typedef struct BTFINT BTFINT; + +struct BTFINT +{ /* interface to BT-factorization */ + int n_max; + /* maximal value of n (increased automatically) */ + int valid; + /* factorization is valid only if this flag is set */ + SVA *sva; + /* sparse vector area (SVA) */ + BTF *btf; + /* sparse block triangular LU-factorization */ + SGF *sgf; + /* sparse Gaussian factorizer workspace */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int sva_n_max, sva_size; + /* parameters passed to sva_create_area */ + int delta_n0, delta_n; + /* if n_max = 0, set n_max = n + delta_n0 + * if n_max < n, set n_max = n + delta_n */ + double sgf_piv_tol; + int sgf_piv_lim; + int sgf_suhl; + double sgf_eps_tol; + /* factorizer control parameters */ +}; + +#define btfint_create _glp_btfint_create +BTFINT *btfint_create(void); +/* create interface to BT-factorization */ + +#define btfint_factorize _glp_btfint_factorize +int btfint_factorize(BTFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute BT-factorization of specified matrix A */ + +#define btfint_delete _glp_btfint_delete +void btfint_delete(BTFINT *fi); +/* delete interface to BT-factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.c new file mode 100644 index 000000000..e4bdf8552 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.c @@ -0,0 +1,586 @@ +/* fhv.c (sparse updatable FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "fhv.h" + +/*********************************************************************** +* fhv_ft_update - update FHV-factorization (Forrest-Tomlin) +* +* This routine updates FHV-factorization of the original matrix A +* after replacing its j-th column by a new one. The routine is based +* on the method proposed by Forrest and Tomlin [1]. +* +* The parameter q specifies the number of column of A, which has been +* replaced, 1 <= q <= n, where n is the order of A. +* +* Row indices and numerical values of non-zero elements of the new +* j-th column of A should be placed in locations aq_ind[1], ..., +* aq_ind[aq_len] and aq_val[1], ..., aq_val[aq_len], respectively, +* where aq_len is the number of non-zeros. Neither zero nor duplicate +* elements are allowed. +* +* The working arrays ind, val, and work should have at least 1+n +* elements (0-th elements are not used). +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 New matrix U = P'* V * Q' is upper triangular with zero diagonal +* element u[s,s]. (Elimination was not performed.) +* +* 2 New matrix U = P'* V * Q' is upper triangular, and its diagonal +* element u[s,s] or u[t,t] is too small in magnitude. (Elimination +* was not performed.) +* +* 3 The same as 2, but after performing elimination. +* +* 4 The factorization has not been updated, because maximal number of +* updates has been reached. +* +* 5 Accuracy test failed for the updated factorization. +* +* BACKGROUND +* +* The routine is based on the updating method proposed by Forrest and +* Tomlin [1]. +* +* Let q-th column of the original matrix A have been replaced by new +* column A[q]. Then, to keep the equality A = F * H * V, q-th column +* of matrix V should be replaced by column V[q] = inv(F * H) * A[q]. +* From the standpoint of matrix U = P'* V * Q' such replacement is +* equivalent to replacement of s-th column of matrix U, where s is +* determined from q by permutation matrix Q. Thus, matrix U loses its +* upper triangular form and becomes the following: +* +* 1 s t n +* 1 x x * x x x x x x +* . x * x x x x x x +* s . . * x x x x x x +* . . * x x x x x x +* . . * . x x x x x +* . . * . . x x x x +* t . . * . . . x x x +* . . . . . . . x x +* n . . . . . . . . x +* +* where t is largest row index of a non-zero element in s-th column. +* +* The routine makes matrix U upper triangular as follows. First, it +* moves rows and columns s+1, ..., t by one position to the left and +* upwards, resp., and moves s-th row and s-th column to position t. +* Due to such symmetric permutations matrix U becomes the following +* (note that all diagonal elements remain on the diagonal, and element +* u[s,s] becomes u[t,t]): +* +* 1 s t n +* 1 x x x x x x * x x +* . x x x x x * x x +* s . . x x x x * x x +* . . . x x x * x x +* . . . . x x * x x +* . . . . . x * x x +* t . . x x x x * x x +* . . . . . . . x x +* n . . . . . . . . x +* +* Then the routine performs gaussian elimination to eliminate +* subdiagonal elements u[t,s], ..., u[t,t-1] using diagonal elements +* u[s,s], ..., u[t-1,t-1] as pivots. During the elimination process +* the routine permutes neither rows nor columns, so only t-th row is +* changed. Should note that actually all operations are performed on +* matrix V = P * U * Q, since matrix U is not stored. +* +* To keep the equality A = F * H * V, the routine appends new row-like +* factor H[k] to matrix H, and every time it applies elementary +* gaussian transformation to eliminate u[t,j'] = v[p,j] using pivot +* u[j',j'] = v[i,j], it also adds new element f[p,j] = v[p,j] / v[i,j] +* (gaussian multiplier) to factor H[k], which initially is a unity +* matrix. At the end of elimination process the row-like factor H[k] +* may look as follows: +* +* 1 n 1 s t n +* 1 1 . . . . . . . . 1 1 . . . . . . . . +* . 1 . . . . . . . . 1 . . . . . . . +* . . 1 . . . . . . s . . 1 . . . . . . +* p . x x 1 . x . x . . . . 1 . . . . . +* . . . . 1 . . . . . . . . 1 . . . . +* . . . . . 1 . . . . . . . . 1 . . . +* . . . . . . 1 . . t . . x x x x 1 . . +* . . . . . . . 1 . . . . . . . . 1 . +* n . . . . . . . . 1 n . . . . . . . . 1 +* +* H[k] inv(P) * H[k] * P +* +* If, however, s = t, no elimination is needed, in which case no new +* row-like factor is created. +* +* REFERENCES +* +* 1. J.J.H.Forrest and J.A.Tomlin, "Updated triangular factors of the +* basis to maintain sparsity in the product form simplex method," +* Math. Prog. 2 (1972), pp. 263-78. */ + +int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], + const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], + double work[/*1+n*/]) +{ LUF *luf = fhv->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; +#if 1 /* FIXME */ + const double eps_tol = DBL_EPSILON; + const double vpq_tol = 1e-5; + const double err_tol = 1e-10; +#endif + int end, i, i_end, i_ptr, j, j_end, j_ptr, k, len, nnz, p, p_end, + p_ptr, ptr, q_end, q_ptr, s, t; + double f, vpq, temp; + /*--------------------------------------------------------------*/ + /* replace current q-th column of matrix V by new one */ + /*--------------------------------------------------------------*/ + xassert(1 <= q && q <= n); + /* convert new q-th column of matrix A to dense format */ + for (i = 1; i <= n; i++) + val[i] = 0.0; + xassert(0 <= aq_len && aq_len <= n); + for (k = 1; k <= aq_len; k++) + { i = aq_ind[k]; + xassert(1 <= i && i <= n); + xassert(val[i] == 0.0); + xassert(aq_val[k] != 0.0); + val[i] = aq_val[k]; + } + /* compute new q-th column of matrix V: + * new V[q] = inv(F * H) * (new A[q]) */ + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_f_solve(luf, val); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + fhv_h_solve(fhv, val); + /* q-th column of V = s-th column of U */ + s = qq_inv[q]; + /* determine row number of element v[p,q] that corresponds to + * diagonal element u[s,s] */ + p = pp_inv[s]; + /* convert new q-th column of V to sparse format; + * element v[p,q] = u[s,s] is not included in the element list + * and stored separately */ + vpq = 0.0; + len = 0; + for (i = 1; i <= n; i++) + { temp = val[i]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) +#endif + /* nop */; + else if (i == p) + vpq = temp; + else + { ind[++len] = i; + val[len] = temp; + } + } + /* clear q-th column of matrix V */ + for (q_end = (q_ptr = vc_ptr[q]) + vc_len[q]; + q_ptr < q_end; q_ptr++) + { /* get row index of v[i,q] */ + i = sv_ind[q_ptr]; + /* find and remove v[i,q] from i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != q; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + sv_ind[i_ptr] = sv_ind[i_end-1]; + sv_val[i_ptr] = sv_val[i_end-1]; + vr_len[i]--; + } + /* now q-th column of matrix V is empty */ + vc_len[q] = 0; + /* put new q-th column of V (except element v[p,q] = u[s,s]) in + * column-wise format */ + if (len > 0) + { if (vc_cap[q] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+q, len, 0); + } + ptr = vc_ptr[q]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vc_len[q] = len; + } + /* put new q-th column of V (except element v[p,q] = u[s,s]) in + * row-wise format, and determine largest row number t such that + * u[s,t] != 0 */ + t = (vpq == 0.0 ? 0 : s); + for (k = 1; k <= len; k++) + { /* get row index of v[i,q] */ + i = ind[k]; + /* put v[i,q] to i-th row */ + if (vr_cap[i] == vr_len[i]) + { /* reserve extra locations in i-th row to reduce further + * relocations of that row */ +#if 1 /* FIXME */ + int need = vr_len[i] + 5; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+i, need, 0); + } + sv_ind[ptr = vr_ptr[i] + (vr_len[i]++)] = q; + sv_val[ptr] = val[k]; + /* v[i,q] is non-zero; increase t */ + if (t < pp_ind[i]) + t = pp_ind[i]; + } + /*--------------------------------------------------------------*/ + /* check if matrix U is already upper triangular */ + /*--------------------------------------------------------------*/ + /* check if there is a spike in s-th column of matrix U, which + * is q-th column of matrix V */ + if (s >= t) + { /* no spike; matrix U is already upper triangular */ + /* store its diagonal element u[s,s] = v[p,q] */ + vr_piv[p] = vpq; + if (s > t) + { /* matrix U is structurally singular, because its diagonal + * element u[s,s] = v[p,q] is exact zero */ + xassert(vpq == 0.0); + return 1; + } +#if 1 /* FIXME */ + else if (-vpq_tol < vpq && vpq < +vpq_tol) +#endif + { /* matrix U is not well conditioned, because its diagonal + * element u[s,s] = v[p,q] is too small in magnitude */ + return 2; + } + else + { /* normal case */ + return 0; + } + } + /*--------------------------------------------------------------*/ + /* perform implicit symmetric permutations of rows and columns */ + /* of matrix U */ + /*--------------------------------------------------------------*/ + /* currently v[p,q] = u[s,s] */ + xassert(p == pp_inv[s] && q == qq_ind[s]); + for (k = s; k < t; k++) + { pp_ind[pp_inv[k] = pp_inv[k+1]] = k; + qq_inv[qq_ind[k] = qq_ind[k+1]] = k; + } + /* now v[p,q] = u[t,t] */ + pp_ind[pp_inv[t] = p] = qq_inv[qq_ind[t] = q] = t; + /*--------------------------------------------------------------*/ + /* check if matrix U is already upper triangular */ + /*--------------------------------------------------------------*/ + /* check if there is a spike in t-th row of matrix U, which is + * p-th row of matrix V */ + for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; + p_ptr < p_end; p_ptr++) + { if (qq_inv[sv_ind[p_ptr]] < t) + break; /* spike detected */ + } + if (p_ptr == p_end) + { /* no spike; matrix U is already upper triangular */ + /* store its diagonal element u[t,t] = v[p,q] */ + vr_piv[p] = vpq; +#if 1 /* FIXME */ + if (-vpq_tol < vpq && vpq < +vpq_tol) +#endif + { /* matrix U is not well conditioned, because its diagonal + * element u[t,t] = v[p,q] is too small in magnitude */ + return 2; + } + else + { /* normal case */ + return 0; + } + } + /*--------------------------------------------------------------*/ + /* copy p-th row of matrix V, which is t-th row of matrix U, to */ + /* working array */ + /*--------------------------------------------------------------*/ + /* copy p-th row of matrix V, including element v[p,q] = u[t,t], + * to the working array in dense format and remove these elements + * from matrix V; since no pivoting is used, only this row will + * change during elimination */ + for (j = 1; j <= n; j++) + work[j] = 0.0; + work[q] = vpq; + for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; + p_ptr < p_end; p_ptr++) + { /* get column index of v[p,j] and store this element to the + * working array */ + work[j = sv_ind[p_ptr]] = sv_val[p_ptr]; + /* find and remove v[p,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != p; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + sv_val[j_ptr] = sv_val[j_end-1]; + vc_len[j]--; + } + /* now p-th row of matrix V is temporarily empty */ + vr_len[p] = 0; + /*--------------------------------------------------------------*/ + /* perform gaussian elimination */ + /*--------------------------------------------------------------*/ + /* transform p-th row of matrix V stored in working array, which + * is t-th row of matrix U, to eliminate subdiagonal elements + * u[t,s], ..., u[t,t-1]; corresponding gaussian multipliers will + * form non-trivial row of new row-like factor */ + nnz = 0; /* number of non-zero gaussian multipliers */ + for (k = s; k < t; k++) + { /* diagonal element u[k,k] = v[i,j] is used as pivot */ + i = pp_inv[k], j = qq_ind[k]; + /* take subdiagonal element u[t,k] = v[p,j] */ + temp = work[j]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) + continue; +#endif + /* compute and save gaussian multiplier: + * f := u[t,k] / u[k,k] = v[p,j] / v[i,j] */ + ind[++nnz] = i; + val[nnz] = f = work[j] / vr_piv[i]; + /* gaussian transformation to eliminate u[t,k] = v[p,j]: + * (p-th row of V) := (p-th row of V) - f * (i-th row of V) */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + work[sv_ind[i_ptr]] -= f * sv_val[i_ptr]; + } + /* now matrix U is again upper triangular */ +#if 1 /* FIXME */ + if (-vpq_tol < work[q] && work[q] < +vpq_tol) +#endif + { /* however, its new diagonal element u[t,t] = v[p,q] is too + * small in magnitude */ + return 3; + } + /*--------------------------------------------------------------*/ + /* create new row-like factor H[k] and add to eta file H */ + /*--------------------------------------------------------------*/ + /* (nnz = 0 means that all subdiagonal elements were too small + * in magnitude) */ + if (nnz > 0) + { if (fhv->nfs == fhv->nfs_max) + { /* maximal number of row-like factors has been reached */ + return 4; + } + k = ++(fhv->nfs); + hh_ind[k] = p; + /* store non-trivial row of H[k] in right (dynamic) part of + * SVA (diagonal unity element is not stored) */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fhv->hh_ref-1+k, nnz); + ptr = hh_ptr[k]; + memcpy(&sv_ind[ptr], &ind[1], nnz * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], nnz * sizeof(double)); + hh_len[k] = nnz; + } + /*--------------------------------------------------------------*/ + /* copy transformed p-th row of matrix V, which is t-th row of */ + /* matrix U, from working array back to matrix V */ + /*--------------------------------------------------------------*/ + /* copy elements of transformed p-th row of matrix V, which are + * non-diagonal elements u[t,t+1], ..., u[t,n] of matrix U, from + * working array to corresponding columns of matrix V (note that + * diagonal element u[t,t] = v[p,q] not copied); also transform + * p-th row of matrix V to sparse format */ + len = 0; + for (k = t+1; k <= n; k++) + { /* j-th column of V = k-th column of U */ + j = qq_ind[k]; + /* take non-diagonal element v[p,j] = u[t,k] */ + temp = work[j]; +#if 1 /* FIXME */ + if (-eps_tol < temp && temp < +eps_tol) + continue; +#endif + /* add v[p,j] to j-th column of matrix V */ + if (vc_cap[j] == vc_len[j]) + { /* reserve extra locations in j-th column to reduce further + * relocations of that column */ +#if 1 /* FIXME */ + int need = vc_len[j] + 5; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, need, 0); + } + sv_ind[ptr = vc_ptr[j] + (vc_len[j]++)] = p; + sv_val[ptr] = temp; + /* store element v[p,j] = u[t,k] to working sparse vector */ + ind[++len] = j; + val[len] = temp; + } + /* copy elements from working sparse vector to p-th row of matrix + * V (this row is currently empty) */ + if (vr_cap[p] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+p, len, 0); + } + ptr = vr_ptr[p]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vr_len[p] = len; + /* store new diagonal element u[t,t] = v[p,q] */ + vr_piv[p] = work[q]; + /*--------------------------------------------------------------*/ + /* perform accuracy test (only if new H[k] was added) */ + /*--------------------------------------------------------------*/ + if (nnz > 0) + { /* copy p-th (non-trivial) row of row-like factor H[k] (except + * unity diagonal element) to working array in dense format */ + for (j = 1; j <= n; j++) + work[j] = 0.0; + k = fhv->nfs; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + work[sv_ind[ptr]] = sv_val[ptr]; + /* compute inner product of p-th (non-trivial) row of matrix + * H[k] and q-th column of matrix V */ + temp = vr_piv[p]; /* 1 * v[p,q] */ + ptr = vc_ptr[q]; + end = ptr + vc_len[q]; + for (; ptr < end; ptr++) + temp += work[sv_ind[ptr]] * sv_val[ptr]; + /* inner product should be equal to element v[p,q] *before* + * matrix V was transformed */ + /* compute relative error */ + temp = fabs(vpq - temp) / (1.0 + fabs(vpq)); +#if 1 /* FIXME */ + if (temp > err_tol) +#endif + { /* relative error is too large */ + return 5; + } + } + /* factorization has been successfully updated */ + return 0; +} + +/*********************************************************************** +* fhv_h_solve - solve system H * x = b +* +* This routine solves the system H * x = b, where the matrix H is the +* middle factor of the sparse updatable FHV-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix H. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void fhv_h_solve(FHV *fhv, double x[/*1+n*/]) +{ SVA *sva = fhv->luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int nfs = fhv->nfs; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; + int i, k, end, ptr; + double x_i; + for (k = 1; k <= nfs; k++) + { x_i = x[i = hh_ind[k]]; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + x_i -= sv_val[ptr] * x[sv_ind[ptr]]; + x[i] = x_i; + } + return; +} + +/*********************************************************************** +* fhv_ht_solve - solve system H' * x = b +* +* This routine solves the system H' * x = b, where H' is a matrix +* transposed to the matrix H, which is the middle factor of the sparse +* updatable FHV-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix H. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]) +{ SVA *sva = fhv->luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int nfs = fhv->nfs; + int *hh_ind = fhv->hh_ind; + int hh_ref = fhv->hh_ref; + int *hh_ptr = &sva->ptr[hh_ref-1]; + int *hh_len = &sva->len[hh_ref-1]; + int k, end, ptr; + double x_j; + for (k = nfs; k >= 1; k--) + { if ((x_j = x[hh_ind[k]]) == 0.0) + continue; + for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.h new file mode 100644 index 000000000..df39ca5cb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhv.h @@ -0,0 +1,114 @@ +/* fhv.h (sparse updatable FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef FHV_H +#define FHV_H + +#include "luf.h" + +/*********************************************************************** +* The structure FHV describes sparse updatable FHV-factorization. +* +* The FHV-factorization has the following format: +* +* A = F * H * V, (1) +* +* F = P0 * L * P0', (2) +* +* H = H[1] * H[2] * ... * H[nfs], (3) +* +* V = P * U * Q, (4) +* +* where: A is a given (unsymmetric) square matrix; F, H, V are matrix +* factors actually computed; L is a lower triangular matrix with unity +* diagonal; U is an upper tringular matrix; H[k], k = 1, 2, ..., nfs, +* is a row-like factor, which differs from unity matrix only in one +* row called a non-trivial row; P0, P, Q are permutation matrices; and +* P0' is a matrix transposed to P0. +* +* Matrices F, V, P, Q are stored in the underlying LUF object. +* +* Non-trivial rows of factors H[k] are stored as sparse vectors in the +* right (static) part of the sparse vector area (SVA). Note that unity +* diagonal elements of non-trivial rows are not stored. +* +* Matrix P0 is stored in the same way as matrix P. +* +* Matrices L and U are completely defined by matrices F, V, P, and Q, +* and therefore not stored explicitly. */ + +typedef struct FHV FHV; + +struct FHV +{ /* FHV-factorization */ + LUF *luf; + /* LU-factorization (contains matrices F, V, P, Q) */ + /*--------------------------------------------------------------*/ + /* matrix H in the form of eta file */ + int nfs_max; + /* maximal number of row-like factors (this limits the number of + * updates of the factorization) */ + int nfs; + /* current number of row-like factors, 0 <= nfs <= nfs_max */ + int *hh_ind; /* int hh_ind[1+nfs_max]; */ + /* hh_ind[0] is not used; + * hh_ind[k], 1 <= k <= nfs, is number of non-trivial row of + * factor H[k] */ + int hh_ref; + /* reference number of sparse vector in SVA, which is non-trivial + * row of factor H[1] */ +#if 0 + 0 + int *hh_ptr = &sva->ptr[hh_ref-1]; + /* hh_ptr[0] is not used; + * hh_ptr[k], 1 <= k <= nfs, is pointer to non-trivial row of + * factor H[k] */ + int *hh_len = &sva->len[hh_ref-1]; + /* hh_len[0] is not used; + * hh_len[k], 1 <= k <= nfs, is number of non-zero elements in + * non-trivial row of factor H[k] */ +#endif + /*--------------------------------------------------------------*/ + /* matrix P0 */ + int *p0_ind; /* int p0_ind[1+n]; */ + /* p0_ind[i] = j means that P0[i,j] = 1 */ + int *p0_inv; /* int p0_inv[1+n]; */ + /* p0_inv[j] = i means that P0[i,j] = 1 */ +}; + +#define fhv_ft_update _glp_fhv_ft_update +int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], + const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], + double work[/*1+n*/]); +/* update FHV-factorization (Forrest-Tomlin) */ + +#define fhv_h_solve _glp_fhv_h_solve +void fhv_h_solve(FHV *fhv, double x[/*1+n*/]); +/* solve system H * x = b */ + +#define fhv_ht_solve _glp_fhv_ht_solve +void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]); +/* solve system H' * x = b */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.c new file mode 100644 index 000000000..a21b71c67 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.c @@ -0,0 +1,168 @@ +/* fhvint.c (interface to FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "fhvint.h" + +FHVINT *fhvint_create(void) +{ /* create interface to FHV-factorization */ + FHVINT *fi; + fi = talloc(1, FHVINT); + memset(fi, 0, sizeof(FHVINT)); + fi->lufi = lufint_create(); + return fi; +} + +int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute FHV-factorization of specified matrix A */ + int nfs_max, old_n_max, n_max, k, ret; + xassert(n > 0); + fi->valid = 0; + /* get required value of nfs_max */ + nfs_max = fi->nfs_max; + if (nfs_max == 0) + nfs_max = 100; + xassert(nfs_max > 0); + /* compute factorization of specified matrix A */ + old_n_max = fi->lufi->n_max; + fi->lufi->sva_n_max = 4 * n + nfs_max; + fi->lufi->sgf_updat = 1; + ret = lufint_factorize(fi->lufi, n, col, info); + n_max = fi->lufi->n_max; + /* allocate/reallocate arrays, if necessary */ + if (fi->fhv.nfs_max != nfs_max) + { if (fi->fhv.hh_ind != NULL) + tfree(fi->fhv.hh_ind); + fi->fhv.hh_ind = talloc(1+nfs_max, int); + } + if (old_n_max < n_max) + { if (fi->fhv.p0_ind != NULL) + tfree(fi->fhv.p0_ind); + if (fi->fhv.p0_inv != NULL) + tfree(fi->fhv.p0_inv); + fi->fhv.p0_ind = talloc(1+n_max, int); + fi->fhv.p0_inv = talloc(1+n_max, int); + } + /* initialize FHV-factorization */ + fi->fhv.luf = fi->lufi->luf; + fi->fhv.nfs_max = nfs_max; + /* H := I */ + fi->fhv.nfs = 0; + fi->fhv.hh_ref = sva_alloc_vecs(fi->lufi->sva, nfs_max); + /* P0 := P */ + for (k = 1; k <= n; k++) + { fi->fhv.p0_ind[k] = fi->fhv.luf->pp_ind[k]; + fi->fhv.p0_inv[k] = fi->fhv.luf->pp_inv[k]; + } + /* set validation flag */ + if (ret == 0) + fi->valid = 1; + return ret; +} + +int fhvint_update(FHVINT *fi, int j, int len, const int ind[], + const double val[]) +{ /* update FHV-factorization after replacing j-th column of A */ + SGF *sgf = fi->lufi->sgf; + int *ind1 = sgf->rs_next; + double *val1 = sgf->vr_max; + double *work = sgf->work; + int ret; + xassert(fi->valid); + ret = fhv_ft_update(&fi->fhv, j, len, ind, val, ind1, val1, work); + if (ret != 0) + fi->valid = 0; + return ret; +} + +void fhvint_ftran(FHVINT *fi, double x[]) +{ /* solve system A * x = b */ + FHV *fhv = &fi->fhv; + LUF *luf = fhv->luf; + int n = luf->n; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + SGF *sgf = fi->lufi->sgf; + double *work = sgf->work; + xassert(fi->valid); + /* A = F * H * V */ + /* x = inv(A) * b = inv(V) * inv(H) * inv(F) * b */ + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_f_solve(luf, x); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + fhv_h_solve(fhv, x); + luf_v_solve(luf, x, work); + memcpy(&x[1], &work[1], n * sizeof(double)); + return; +} + +void fhvint_btran(FHVINT *fi, double x[]) +{ /* solve system A'* x = b */ + FHV *fhv = &fi->fhv; + LUF *luf = fhv->luf; + int n = luf->n; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + SGF *sgf = fi->lufi->sgf; + double *work = sgf->work; + xassert(fi->valid); + /* A' = (F * H * V)' = V'* H'* F' */ + /* x = inv(A') * b = inv(F') * inv(H') * inv(V') * b */ + luf_vt_solve(luf, x, work); + fhv_ht_solve(fhv, work); + luf->pp_ind = fhv->p0_ind; + luf->pp_inv = fhv->p0_inv; + luf_ft_solve(luf, work); + luf->pp_ind = pp_ind; + luf->pp_inv = pp_inv; + memcpy(&x[1], &work[1], n * sizeof(double)); + return; +} + +double fhvint_estimate(FHVINT *fi) +{ /* estimate 1-norm of inv(A) */ + double norm; + xassert(fi->valid); + xassert(fi->fhv.nfs == 0); + norm = luf_estimate_norm(fi->fhv.luf, fi->lufi->sgf->vr_max, + fi->lufi->sgf->work); + return norm; +} + +void fhvint_delete(FHVINT *fi) +{ /* delete interface to FHV-factorization */ + lufint_delete(fi->lufi); + if (fi->fhv.hh_ind != NULL) + tfree(fi->fhv.hh_ind); + if (fi->fhv.p0_ind != NULL) + tfree(fi->fhv.p0_ind); + if (fi->fhv.p0_inv != NULL) + tfree(fi->fhv.p0_inv); + tfree(fi); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.h new file mode 100644 index 000000000..000829c6f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/fhvint.h @@ -0,0 +1,78 @@ +/* fhvint.h (interface to FHV-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef FHVINT_H +#define FHVINT_H + +#include "fhv.h" +#include "lufint.h" + +typedef struct FHVINT FHVINT; + +struct FHVINT +{ /* interface to FHV-factorization */ + int valid; + /* factorization is valid only if this flag is set */ + FHV fhv; + /* FHV-factorization */ + LUFINT *lufi; + /* interface to underlying LU-factorization */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int nfs_max; + /* required maximal number of row-like factors */ +}; + +#define fhvint_create _glp_fhvint_create +FHVINT *fhvint_create(void); +/* create interface to FHV-factorization */ + +#define fhvint_factorize _glp_fhvint_factorize +int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute FHV-factorization of specified matrix A */ + +#define fhvint_update _glp_fhvint_update +int fhvint_update(FHVINT *fi, int j, int len, const int ind[], + const double val[]); +/* update FHV-factorization after replacing j-th column of A */ + +#define fhvint_ftran _glp_fhvint_ftran +void fhvint_ftran(FHVINT *fi, double x[]); +/* solve system A * x = b */ + +#define fhvint_btran _glp_fhvint_btran +void fhvint_btran(FHVINT *fi, double x[]); +/* solve system A'* x = b */ + +#define fhvint_estimate _glp_fhvint_estimate +double fhvint_estimate(FHVINT *fi); +/* estimate 1-norm of inv(A) */ + +#define fhvint_delete _glp_fhvint_delete +void fhvint_delete(FHVINT *fi); +/* delete interface to FHV-factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.c new file mode 100644 index 000000000..aa47fb092 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.c @@ -0,0 +1,392 @@ +/* ifu.c (dense updatable IFU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ifu.h" + +/*********************************************************************** +* ifu_expand - expand IFU-factorization +* +* This routine expands the IFU-factorization of the matrix A according +* to the following expansion of A: +* +* ( A c ) +* new A = ( ) +* ( r' d ) +* +* where c[1,...,n] is a new column, r[1,...,n] is a new row, and d is +* a new diagonal element. +* +* From the main equality F * A = U it follows that: +* +* ( F 0 ) ( A c ) ( FA Fc ) ( U Fc ) +* ( ) ( ) = ( ) = ( ), +* ( 0 1 ) ( r' d ) ( r' d ) ( r' d ) +* +* thus, +* +* ( F 0 ) ( U Fc ) +* new F = ( ), new U = ( ). +* ( 0 1 ) ( r' d ) +* +* Note that the resulting matrix U loses its upper triangular form due +* to row spike r', which should be eliminated. */ + +void ifu_expand(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n < n_max); + /* adjust indexing */ + c++, r++; + /* set new zero column of matrix F */ + for (i = 0; i < n; i++) + f(i,n) = 0.0; + /* set new zero row of matrix F */ + for (j = 0; j < n; j++) + f(n,j) = 0.0; + /* set new unity diagonal element of matrix F */ + f(n,n) = 1.0; + /* set new column of matrix U to vector (old F) * c */ + for (i = 0; i < n; i++) + { /* u[i,n] := (i-th row of old F) * c */ + t = 0.0; + for (j = 0; j < n; j++) + t += f(i,j) * c[j]; + u(i,n) = t; + } + /* set new row of matrix U to vector r */ + for (j = 0; j < n; j++) + u(n,j) = r[j]; + /* set new diagonal element of matrix U to scalar d */ + u(n,n) = d; + /* increase factorization order */ + ifu->n++; +# undef f +# undef u + return; +} + +/*********************************************************************** +* ifu_bg_update - update IFU-factorization (Bartels-Golub) +* +* This routine updates IFU-factorization of the matrix A according to +* its expansion (see comments to the routine ifu_expand). The routine +* is based on the method proposed by Bartels and Golub [1]. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 On some elimination step diagional element u[k,k] to be used as +* pivot is too small in magnitude. +* +* 2 Diagonal element u[n,n] is too small in magnitude (at the end of +* update). +* +* REFERENCES +* +* 1. R.H.Bartels, G.H.Golub, "The Simplex Method of Linear Programming +* Using LU-decomposition", Comm. ACM, 12, pp. 266-68, 1969. */ + +int ifu_bg_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; +#if 1 /* FIXME */ + double tol = 1e-5; +#endif + int j, k; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + /* expand factorization */ + ifu_expand(ifu, c, r, d); + /* NOTE: n keeps its old value */ + /* eliminate spike (non-zero subdiagonal elements) in last row of + * matrix U */ + for (k = 0; k < n; k++) + { /* if |u[k,k]| < |u[n,k]|, interchange k-th and n-th rows to + * provide |u[k,k]| >= |u[n,k]| for numeric stability */ + if (fabs(u(k,k)) < fabs(u(n,k))) + { /* interchange k-th and n-th rows of matrix U */ + for (j = k; j <= n; j++) + t = u(k,j), u(k,j) = u(n,j), u(n,j) = t; + /* interchange k-th and n-th rows of matrix F to keep the + * main equality F * A = U */ + for (j = 0; j <= n; j++) + t = f(k,j), f(k,j) = f(n,j), f(n,j) = t; + } + /* now |u[k,k]| >= |u[n,k]| */ + /* check if diagonal element u[k,k] can be used as pivot */ + if (fabs(u(k,k)) < tol) + { /* u[k,k] is too small in magnitude */ + return 1; + } + /* if u[n,k] = 0, elimination is not needed */ + if (u(n,k) == 0.0) + continue; + /* compute gaussian multiplier t = u[n,k] / u[k,k] */ + t = u(n,k) / u(k,k); + /* apply gaussian transformation to eliminate u[n,k] */ + /* (n-th row of U) := (n-th row of U) - t * (k-th row of U) */ + for (j = k+1; j <= n; j++) + u(n,j) -= t * u(k,j); + /* apply the same transformation to matrix F to keep the main + * equality F * A = U */ + for (j = 0; j <= n; j++) + f(n,j) -= t * f(k,j); + } + /* now matrix U is upper triangular */ + if (fabs(u(n,n)) < tol) + { /* u[n,n] is too small in magnitude */ + return 2; + } +# undef f +# undef u + return 0; +} + +/*********************************************************************** +* The routine givens computes the parameters of Givens plane rotation +* c = cos(teta) and s = sin(teta) such that: +* +* ( c -s ) ( a ) ( r ) +* ( ) ( ) = ( ) , +* ( s c ) ( b ) ( 0 ) +* +* where a and b are given scalars. +* +* REFERENCES +* +* G.H.Golub, C.F.Van Loan, "Matrix Computations", 2nd ed. */ + +static void givens(double a, double b, double *c, double *s) +{ /* non-optimized version */ + double t; + if (b == 0.0) + (*c) = 1.0, (*s) = 0.0; + else if (fabs(a) <= fabs(b)) + t = - a / b, (*s) = 1.0 / sqrt(1.0 + t * t), (*c) = (*s) * t; + else + t = - b / a, (*c) = 1.0 / sqrt(1.0 + t * t), (*s) = (*c) * t; + return; +} + +/*********************************************************************** +* ifu_gr_update - update IFU-factorization (Givens rotations) +* +* This routine updates IFU-factorization of the matrix A according to +* its expansion (see comments to the routine ifu_expand). The routine +* is based on Givens plane rotations [1]. +* +* RETURNS +* +* 0 The factorization has been successfully updated. +* +* 1 On some elimination step both elements u[k,k] and u[n,k] are too +* small in magnitude. +* +* 2 Diagonal element u[n,n] is too small in magnitude (at the end of +* update). +* +* REFERENCES +* +* 1. G.H.Golub, C.F.Van Loan, "Matrix Computations", 2nd ed. */ + +int ifu_gr_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; +#if 1 /* FIXME */ + double tol = 1e-5; +#endif + int j, k; + double cs, sn; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + /* expand factorization */ + ifu_expand(ifu, c, r, d); + /* NOTE: n keeps its old value */ + /* eliminate spike (non-zero subdiagonal elements) in last row of + * matrix U */ + for (k = 0; k < n; k++) + { /* check if elements u[k,k] and u[n,k] are eligible */ + if (fabs(u(k,k)) < tol && fabs(u(n,k)) < tol) + { /* both u[k,k] and u[n,k] are too small in magnitude */ + return 1; + } + /* if u[n,k] = 0, elimination is not needed */ + if (u(n,k) == 0.0) + continue; + /* compute parameters of Givens plane rotation */ + givens(u(k,k), u(n,k), &cs, &sn); + /* apply Givens rotation to k-th and n-th rows of matrix U to + * eliminate u[n,k] */ + for (j = k; j <= n; j++) + { double ukj = u(k,j), unj = u(n,j); + u(k,j) = cs * ukj - sn * unj; + u(n,j) = sn * ukj + cs * unj; + } + /* apply the same transformation to matrix F to keep the main + * equality F * A = U */ + for (j = 0; j <= n; j++) + { double fkj = f(k,j), fnj = f(n,j); + f(k,j) = cs * fkj - sn * fnj; + f(n,j) = sn * fkj + cs * fnj; + } + } + /* now matrix U is upper triangular */ + if (fabs(u(n,n)) < tol) + { /* u[n,n] is too small in magnitude */ + return 2; + } +# undef f +# undef u + return 0; +} + +/*********************************************************************** +* ifu_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where the matrix A is +* specified by its IFU-factorization. +* +* Using the main equality F * A = U we have: +* +* A * x = b => F * A * x = F * b => U * x = F * b => +* +* x = inv(U) * F * b. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. +* +* The working array w should have at least 1+n elements (0-th element +* is not used). */ + +void ifu_a_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n <= n_max); + /* adjust indexing */ + x++, w++; + /* y := F * b */ + memcpy(w, x, n * sizeof(double)); + for (i = 0; i < n; i++) + { /* y[i] := (i-th row of F) * b */ + t = 0.0; + for (j = 0; j < n; j++) + t += f(i,j) * w[j]; + x[i] = t; + } + /* x := inv(U) * y */ + for (i = n-1; i >= 0; i--) + { t = x[i]; + for (j = i+1; j < n; j++) + t -= u(i,j) * x[j]; + x[i] = t / u(i,i); + } +# undef f +# undef u + return; +} + +/*********************************************************************** +* ifu_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the matrix A, specified by its IFU-factorization. +* +* Using the main equality F * A = U, from which it follows that +* A'* F' = U', we have: +* +* A'* x = b => A'* F'* inv(F') * x = b => +* +* U'* inv(F') * x = b => inv(F') * x = inv(U') * b => +* +* x = F' * inv(U') * b. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. +* +* The working array w should have at least 1+n elements (0-th element +* is not used). */ + +void ifu_at_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]) +{ /* non-optimized version */ + int n_max = ifu->n_max; + int n = ifu->n; + double *f_ = ifu->f; + double *u_ = ifu->u; + int i, j; + double t; +# define f(i,j) f_[(i)*n_max+(j)] +# define u(i,j) u_[(i)*n_max+(j)] + xassert(0 <= n && n <= n_max); + /* adjust indexing */ + x++, w++; + /* y := inv(U') * b */ + for (i = 0; i < n; i++) + { t = (x[i] /= u(i,i)); + for (j = i+1; j < n; j++) + x[j] -= u(i,j) * t; + } + /* x := F'* y */ + for (j = 0; j < n; j++) + { /* x[j] := (j-th column of F) * y */ + t = 0.0; + for (i = 0; i < n; i++) + t += f(i,j) * x[i]; + w[j] = t; + } + memcpy(x, w, n * sizeof(double)); +# undef f +# undef u + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.h new file mode 100644 index 000000000..1c67a8015 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/ifu.h @@ -0,0 +1,99 @@ +/* ifu.h (dense updatable IFU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef IFU_H +#define IFU_H + +/*********************************************************************** +* The structure IFU describes dense updatable IFU-factorization. +* +* The IFU-factorization has the following format: +* +* A = inv(F) * U, (1) +* +* where A is a given (unsymmetric) nxn square matrix, F is a square +* matrix, U is an upper triangular matrix. Obviously, the equality (1) +* is equivalent to the following equality: +* +* F * A = U. (2) +* +* It is assumed that matrix A is small and dense, so matrices F and U +* are stored by rows in dense format as follows: +* +* 1 n n_max 1 n n_max +* 1 * * * * * * x x x x 1 * * * * * * x x x x +* * * * * * * x x x x ? * * * * * x x x x +* * * * * * * x x x x ? ? * * * * x x x x +* * * * * * * x x x x ? ? ? * * * x x x x +* * * * * * * x x x x ? ? ? ? * * x x x x +* n * * * * * * x x x x n ? ? ? ? ? * x x x x +* x x x x x x x x x x x x x x x x x x x x +* x x x x x x x x x x x x x x x x x x x x +* x x x x x x x x x x x x x x x x x x x x +* n_max x x x x x x x x x x n_max x x x x x x x x x x +* +* matrix F matrix U +* +* where '*' are matrix elements, '?' are unused locations, 'x' are +* reserved locations. */ + +typedef struct IFU IFU; + +struct IFU +{ /* IFU-factorization */ + int n_max; + /* maximal order of matrices A, F, U; n_max >= 1 */ + int n; + /* current order of matrices A, F, U; 0 <= n <= n_max */ + double *f; /* double f[n_max*n_max]; */ + /* matrix F stored by rows */ + double *u; /* double u[n_max*n_max]; */ + /* matrix U stored by rows */ +}; + +#define ifu_expand _glp_ifu_expand +void ifu_expand(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* expand IFU-factorization */ + +#define ifu_bg_update _glp_ifu_bg_update +int ifu_bg_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* update IFU-factorization (Bartels-Golub) */ + +#define ifu_gr_update _glp_ifu_gr_update +int ifu_gr_update(IFU *ifu, double c[/*1+n*/], double r[/*1+n*/], + double d); +/* update IFU-factorization (Givens rotations) */ + +#define ifu_a_solve _glp_ifu_a_solve +void ifu_a_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]); +/* solve system A * x = b */ + +#define ifu_at_solve _glp_ifu_at_solve +void ifu_at_solve(IFU *ifu, double x[/*1+n*/], double w[/*1+n*/]); +/* solve system A'* x = b */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.c new file mode 100644 index 000000000..2797407d9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.c @@ -0,0 +1,713 @@ +/* luf.c (sparse LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "luf.h" + +/*********************************************************************** +* luf_store_v_cols - store matrix V = A in column-wise format +* +* This routine stores matrix V = A in column-wise format, where A is +* the original matrix to be factorized. +* +* On exit the routine returns the number of non-zeros in matrix V. */ + +int luf_store_v_cols(LUF *luf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int j, len, ptr, nnz; + nnz = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = col(info, j, ind, val); + xassert(0 <= len && len <= n); + /* enlarge j-th column capacity */ + if (vc_cap[j] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, len, 0); + } + /* store j-th column */ + ptr = vc_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vc_len[j] = len; + nnz += len; + } + return nnz; +} + +/*********************************************************************** +* luf_check_all - check LU-factorization before k-th elimination step +* +* This routine checks that before performing k-th elimination step, +* 1 <= k <= n+1, all components of the LU-factorization are correct. +* +* In case of k = n+1, i.e. after last elimination step, it is assumed +* that rows of F and columns of V are *not* built yet. +* +* NOTE: For testing/debugging only. */ + +void luf_check_all(LUF *luf, int k) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, ii, i_ptr, i_end, j, jj, j_ptr, j_end; + xassert(n > 0); + xassert(1 <= k && k <= n+1); + /* check permutation matrix P */ + for (i = 1; i <= n; i++) + { ii = pp_ind[i]; + xassert(1 <= ii && ii <= n); + xassert(pp_inv[ii] == i); + } + /* check permutation matrix Q */ + for (j = 1; j <= n; j++) + { jj = qq_inv[j]; + xassert(1 <= jj && jj <= n); + xassert(qq_ind[jj] == j); + } + /* check row-wise representation of matrix F */ + for (i = 1; i <= n; i++) + xassert(fr_len[i] == 0); + /* check column-wise representation of matrix F */ + for (j = 1; j <= n; j++) + { /* j-th column of F = jj-th column of L */ + jj = pp_ind[j]; + if (jj < k) + { j_ptr = fc_ptr[j]; + j_end = j_ptr + fc_len[j]; + for (; j_ptr < j_end; j_ptr++) + { i = sv_ind[j_ptr]; + xassert(1 <= i && i <= n); + ii = pp_ind[i]; /* f[i,j] = l[ii,jj] */ + xassert(ii > jj); + xassert(sv_val[j_ptr] != 0.0); + } + } + else /* jj >= k */ + xassert(fc_len[j] == 0); + } + /* check row-wise representation of matrix V */ + for (i = 1; i <= n; i++) + { /* i-th row of V = ii-th row of U */ + ii = pp_ind[i]; + i_ptr = vr_ptr[i]; + i_end = i_ptr + vr_len[i]; + for (; i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + xassert(1 <= j && j <= n); + jj = qq_inv[j]; /* v[i,j] = u[ii,jj] */ + if (ii < k) + xassert(jj > ii); + else /* ii >= k */ + { xassert(jj >= k); + /* find v[i,j] in j-th column */ + j_ptr = vc_ptr[j]; + j_end = j_ptr + vc_len[j]; + for (; sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + } + xassert(sv_val[i_ptr] != 0.0); + } + } + /* check column-wise representation of matrix V */ + for (j = 1; j <= n; j++) + { /* j-th column of V = jj-th column of U */ + jj = qq_inv[j]; + if (jj < k) + xassert(vc_len[j] == 0); + else /* jj >= k */ + { j_ptr = vc_ptr[j]; + j_end = j_ptr + vc_len[j]; + for (; j_ptr < j_end; j_ptr++) + { i = sv_ind[j_ptr]; + ii = pp_ind[i]; /* v[i,j] = u[ii,jj] */ + xassert(ii >= k); + /* find v[i,j] in i-th row */ + i_ptr = vr_ptr[i]; + i_end = i_ptr + vr_len[i]; + for (; sv_ind[i_ptr] != j; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + } + } + } + return; +} + +/*********************************************************************** +* luf_build_v_rows - build matrix V in row-wise format +* +* This routine builds the row-wise representation of matrix V in the +* left part of SVA using its column-wise representation. +* +* NOTE: On entry to the routine all rows of matrix V should have zero +* capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_v_rows(LUF *luf, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix V and + * the total number of non-zeros */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += vc_len[j]; + for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix V */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_enlarge_cap(sva, vr_ref-1+i, len[i], 0); + vr_len[i] = len[i]; + } + /* walk thru column of matrix V and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = vr_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_build_f_rows - build matrix F in row-wise format +* +* This routine builds the row-wise representation of matrix F in the +* right part of SVA using its column-wise representation. +* +* NOTE: On entry to the routine all rows of matrix F should have zero +* capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_f_rows(LUF *luf, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix F and + * the total number of non-zeros (except diagonal elements) */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += fc_len[j]; + for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix F */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_reserve_cap(sva, fr_ref-1+i, len[i]); + fr_len[i] = len[i]; + } + /* walk through columns of matrix F and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = fr_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_build_v_cols - build matrix V in column-wise format +* +* This routine builds the column-wise representation of matrix V in +* the left (if the flag updat is set) or right (if the flag updat is +* clear) part of SVA using its row-wise representation. +* +* NOTE: On entry to the routine all columns of matrix V should have +* zero capacity. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each column of matrix V + * and the total number of non-zeros (except pivot elements) */ + nnz = 0; + for (j = 1; j <= n; j++) + len[j] = 0; + for (i = 1; i <= n; i++) + { nnz += vr_len[i]; + for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for columns of matrix V */ + for (j = 1; j <= n; j++) + { if (len[j] > 0) + { if (updat) + sva_enlarge_cap(sva, vc_ref-1+j, len[j], 0); + else + sva_reserve_cap(sva, vc_ref-1+j, len[j]); + } + vc_len[j] = len[j]; + } + /* walk through rows of matrix V and build its columns */ + for (i = 1; i <= n; i++) + { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + { j = sv_ind[ptr]; + sv_ind[ptr1 = vc_ptr[j] + (--len[j])] = i; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* luf_check_f_rc - check rows and columns of matrix F +* +* This routine checks that the row- and column-wise representations +* of matrix F are identical. +* +* NOTE: For testing/debugging only. */ + +void luf_check_f_rc(LUF *luf) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int i, i_end, i_ptr, j, j_end, j_ptr; + /* walk thru rows of matrix F */ + for (i = 1; i <= n; i++) + { for (i_end = (i_ptr = fr_ptr[i]) + fr_len[i]; + i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + /* find element f[i,j] in j-th column of matrix F */ + for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + xassert(sv_val[i_ptr] == sv_val[j_ptr]); + /* mark element f[i,j] */ + sv_ind[j_ptr] = -i; + } + } + /* walk thru column of matix F and check that all elements has + been marked */ + for (j = 1; j <= n; j++) + { for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; + j_ptr < j_end; j_ptr++) + { xassert((i = sv_ind[j_ptr]) < 0); + /* unmark element f[i,j] */ + sv_ind[j_ptr] = -i; + } + } + return; +} + +/*********************************************************************** +* luf_check_v_rc - check rows and columns of matrix V +* +* This routine checks that the row- and column-wise representations +* of matrix V are identical. +* +* NOTE: For testing/debugging only. */ + +void luf_check_v_rc(LUF *luf) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int i, i_end, i_ptr, j, j_end, j_ptr; + /* walk thru rows of matrix V */ + for (i = 1; i <= n; i++) + { for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { j = sv_ind[i_ptr]; + /* find element v[i,j] in j-th column of matrix V */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + xassert(sv_val[i_ptr] == sv_val[j_ptr]); + /* mark element v[i,j] */ + sv_ind[j_ptr] = -i; + } + } + /* walk thru column of matix V and check that all elements has + been marked */ + for (j = 1; j <= n; j++) + { for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + j_ptr < j_end; j_ptr++) + { xassert((i = sv_ind[j_ptr]) < 0); + /* unmark element v[i,j] */ + sv_ind[j_ptr] = -i; + } + } + return; +} + +/*********************************************************************** +* luf_f_solve - solve system F * x = b +* +* This routine solves the system F * x = b, where the matrix F is the +* left factor of the sparse LU-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void luf_f_solve(LUF *luf, double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int *pp_inv = luf->pp_inv; + int j, k, ptr, end; + double x_j; + for (k = 1; k <= n; k++) + { /* k-th column of L = j-th column of F */ + j = pp_inv[k]; + /* x[j] is already computed */ + /* walk thru j-th column of matrix F and substitute x[j] into + * other equations */ + if ((x_j = x[j]) != 0.0) + { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + } + return; +} + +/*********************************************************************** +* luf_ft_solve - solve system F' * x = b +* +* This routine solves the system F' * x = b, where F' is a matrix +* transposed to the matrix F, which is the left factor of the sparse +* LU-factorization. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void luf_ft_solve(LUF *luf, double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fr_ref = luf->fr_ref; + int *fr_ptr = &sva->ptr[fr_ref-1]; + int *fr_len = &sva->len[fr_ref-1]; + int *pp_inv = luf->pp_inv; + int i, k, ptr, end; + double x_i; + for (k = n; k >= 1; k--) + { /* k-th column of L' = i-th row of F */ + i = pp_inv[k]; + /* x[i] is already computed */ + /* walk thru i-th row of matrix F and substitute x[i] into + * other equations */ + if ((x_i = x[i]) != 0.0) + { for (end = (ptr = fr_ptr[i]) + fr_len[i]; ptr < end; ptr++) + x[sv_ind[ptr]] -= sv_val[ptr] * x_i; + } + } + return; +} + +/*********************************************************************** +* luf_v_solve - solve system V * x = b +* +* This routine solves the system V * x = b, where the matrix V is the +* right factor of the sparse LU-factorization. +* +* On entry the array b should contain elements of the right-hand side +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix V. On exit the array x will contain elements of the solution +* vector x in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. */ + +void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double x_j; + for (k = n; k >= 1; k--) + { /* k-th row of U = i-th row of V */ + /* k-th column of U = j-th column of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* compute x[j] = b[i] / u[k,k], where u[k,k] = v[i,j]; + * walk through j-th column of matrix V and substitute x[j] + * into other equations */ + if ((x_j = x[j] = b[i] / vr_piv[i]) != 0.0) + { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * x_j; + } + } + return; +} + +/*********************************************************************** +* luf_vt_solve - solve system V' * x = b +* +* This routine solves the system V' * x = b, where V' is a matrix +* transposed to the matrix V, which is the right factor of the sparse +* LU-factorization. +* +* On entry the array b should contain elements of the right-hand side +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix V. On exit the array x will contain elements of the solution +* vector x in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. */ + +void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double x_i; + for (k = 1; k <= n; k++) + { /* k-th row of U' = j-th column of V */ + /* k-th column of U' = i-th row of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* compute x[i] = b[j] / u'[k,k], where u'[k,k] = v[i,j]; + * walk through i-th row of matrix V and substitute x[i] into + * other equations */ + if ((x_i = x[i] = b[j] / vr_piv[i]) != 0.0) + { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * x_i; + } + } + return; +} + +/*********************************************************************** +* luf_vt_solve1 - solve system V' * y = e' to cause growth in y +* +* This routine is a special version of luf_vt_solve. It solves the +* system V'* y = e' = e + delta e, where V' is a matrix transposed to +* the matrix V, e is the specified right-hand side vector, and delta e +* is a vector of +1 and -1 chosen to cause growth in the solution +* vector y. +* +* On entry the array e should contain elements of the right-hand side +* vector e in locations e[1], ..., e[n], where n is the order of the +* matrix V. On exit the array y will contain elements of the solution +* vector y in locations y[1], ..., y[n]. Note that the array e will be +* clobbered on exit. */ + +void luf_vt_solve1(LUF *luf, double e[/*1+n*/], double y[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double e_j, y_i; + for (k = 1; k <= n; k++) + { /* k-th row of U' = j-th column of V */ + /* k-th column of U' = i-th row of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* determine e'[j] = e[j] + delta e[j] */ + e_j = (e[j] >= 0.0 ? e[j] + 1.0 : e[j] - 1.0); + /* compute y[i] = e'[j] / u'[k,k], where u'[k,k] = v[i,j] */ + y_i = y[i] = e_j / vr_piv[i]; + /* walk through i-th row of matrix V and substitute y[i] into + * other equations */ + for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_i; + } + return; +} + +/*********************************************************************** +* luf_estimate_norm - estimate 1-norm of inv(A) +* +* This routine estimates 1-norm of inv(A) by one step of inverse +* iteration for the small singular vector as described in [1]. This +* involves solving two systems of equations: +* +* A'* y = e, +* +* A * z = y, +* +* where A' is a matrix transposed to A, and e is a vector of +1 and -1 +* chosen to cause growth in y. Then +* +* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) +* +* REFERENCES +* +* 1. G.E.Forsythe, M.A.Malcolm, C.B.Moler. Computer Methods for +* Mathematical Computations. Prentice-Hall, Englewood Cliffs, N.J., +* pp. 30-62 (subroutines DECOMP and SOLVE). */ + +double luf_estimate_norm(LUF *luf, double w1[/*1+n*/], double + w2[/*1+n*/]) +{ int n = luf->n; + double *e = w1; + double *y = w2; + double *z = w1; + int i; + double y_norm, z_norm; + /* y = inv(A') * e = inv(F') * inv(V') * e */ + /* compute y' = inv(V') * e to cause growth in y' */ + for (i = 1; i <= n; i++) + e[i] = 0.0; + luf_vt_solve1(luf, e, y); + /* compute y = inv(F') * y' */ + luf_ft_solve(luf, y); + /* compute 1-norm of y = sum |y[i]| */ + y_norm = 0.0; + for (i = 1; i <= n; i++) + y_norm += (y[i] >= 0.0 ? +y[i] : -y[i]); + /* z = inv(A) * y = inv(V) * inv(F) * y */ + /* compute z' = inv(F) * y */ + luf_f_solve(luf, y); + /* compute z = inv(V) * z' */ + luf_v_solve(luf, y, z); + /* compute 1-norm of z = sum |z[i]| */ + z_norm = 0.0; + for (i = 1; i <= n; i++) + z_norm += (z[i] >= 0.0 ? +z[i] : -z[i]); + /* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) */ + return z_norm / y_norm; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.h new file mode 100644 index 000000000..5634a7530 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/luf.h @@ -0,0 +1,227 @@ +/* luf.h (sparse LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef LUF_H +#define LUF_H + +#include "sva.h" + +/*********************************************************************** +* The structure LUF describes sparse LU-factorization. +* +* The LU-factorization has the following format: +* +* A = F * V = P * L * U * Q, (1) +* +* F = P * L * P', (2) +* +* V = P * U * Q, (3) +* +* where A is a given (unsymmetric) square matrix, F and V are matrix +* factors actually computed, L is a lower triangular matrix with unity +* diagonal, U is an upper triangular matrix, P and Q are permutation +* matrices, P' is a matrix transposed to P. All the matrices have the +* same order n. +* +* Matrices F and V are stored in both row- and column-wise sparse +* formats in the associated sparse vector area (SVA). Unity diagonal +* elements of matrix F are not stored. Pivot elements of matrix V +* (which correspond to diagonal elements of matrix U) are stored in +* a separate ordinary array. +* +* Permutation matrices P and Q are stored in ordinary arrays in both +* row- and column-like formats. +* +* Matrices L and U are completely defined by matrices F, V, P, and Q, +* and therefore not stored explicitly. */ + +typedef struct LUF LUF; + +struct LUF +{ /* sparse LU-factorization */ + int n; + /* order of matrices A, F, V, P, Q */ + SVA *sva; + /* associated sparse vector area (SVA) used to store rows and + * columns of matrices F and V; note that different objects may + * share the same SVA */ + /*--------------------------------------------------------------*/ + /* matrix F in row-wise format */ + /* during the factorization process this object is not used */ + int fr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix F */ +#if 0 + 0 + int *fr_ptr = &sva->ptr[fr_ref-1]; + /* fr_ptr[0] is not used; + * fr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *fr_len = &sva->len[fr_ref-1]; + /* fr_len[0] is not used; + * fr_len[i], 1 <= i <= n, is length of i-th row */ +#endif + /*--------------------------------------------------------------*/ + /* matrix F in column-wise format */ + /* during the factorization process this object is constructed + * by columns */ + int fc_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix F */ +#if 0 + 0 + int *fc_ptr = &sva->ptr[fc_ref-1]; + /* fc_ptr[0] is not used; + * fc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *fc_len = &sva->len[fc_ref-1]; + /* fc_len[0] is not used; + * fc_len[j], 1 <= j <= n, is length of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* matrix V in row-wise format */ + int vr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix V */ +#if 0 + 0 + int *vr_ptr = &sva->ptr[vr_ref-1]; + /* vr_ptr[0] is not used; + * vr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *vr_len = &sva->len[vr_ref-1]; + /* vr_len[0] is not used; + * vr_len[i], 1 <= i <= n, is length of i-th row */ + int *vr_cap = &sva->cap[vr_ref-1]; + /* vr_cap[0] is not used; + * vr_cap[i], 1 <= i <= n, is capacity of i-th row */ +#endif + double *vr_piv; /* double vr_piv[1+n]; */ + /* vr_piv[0] is not used; + * vr_piv[i], 1 <= i <= n, is pivot element of i-th row */ + /*--------------------------------------------------------------*/ + /* matrix V in column-wise format */ + /* during the factorization process this object contains only the + * patterns (row indices) of columns of the active submatrix */ + int vc_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix V */ +#if 0 + 0 + int *vc_ptr = &sva->ptr[vc_ref-1]; + /* vc_ptr[0] is not used; + * vc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *vc_len = &sva->len[vc_ref-1]; + /* vc_len[0] is not used; + * vc_len[j], 1 <= j <= n, is length of j-th column */ + int *vc_cap = &sva->cap[vc_ref-1]; + /* vc_cap[0] is not used; + * vc_cap[j], 1 <= j <= n, is capacity of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* matrix P */ + int *pp_ind; /* int pp_ind[1+n]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /* if i-th row or column of matrix F is i'-th row or column of + * matrix L, or if i-th row of matrix V is i'-th row of matrix U, + * then pp_ind[i] = i' and pp_inv[i'] = i */ + /*--------------------------------------------------------------*/ + /* matrix Q */ + int *qq_ind; /* int qq_ind[1+n]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ + /* if j-th column of matrix V is j'-th column of matrix U, then + * qq_ind[j'] = j and qq_inv[j] = j' */ +}; + +#define luf_swap_u_rows(i1, i2) \ + do \ + { int j1, j2; \ + j1 = pp_inv[i1], j2 = pp_inv[i2]; \ + pp_ind[j1] = i2, pp_inv[i2] = j1; \ + pp_ind[j2] = i1, pp_inv[i1] = j2; \ + } while (0) +/* swap rows i1 and i2 of matrix U = P'* V * Q' */ + +#define luf_swap_u_cols(j1, j2) \ + do \ + { int i1, i2; \ + i1 = qq_ind[j1], i2 = qq_ind[j2]; \ + qq_ind[j1] = i2, qq_inv[i2] = j1; \ + qq_ind[j2] = i1, qq_inv[i1] = j2; \ + } while (0) +/* swap columns j1 and j2 of matrix U = P'* V * Q' */ + +#define luf_store_v_cols _glp_luf_store_v_cols +int luf_store_v_cols(LUF *luf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]); +/* store matrix V = A in column-wise format */ + +#define luf_check_all _glp_luf_check_all +void luf_check_all(LUF *luf, int k); +/* check LU-factorization before k-th elimination step */ + +#define luf_build_v_rows _glp_luf_build_v_rows +void luf_build_v_rows(LUF *luf, int len[/*1+n*/]); +/* build matrix V in row-wise format */ + +#define luf_build_f_rows _glp_luf_build_f_rows +void luf_build_f_rows(LUF *luf, int len[/*1+n*/]); +/* build matrix F in row-wise format */ + +#define luf_build_v_cols _glp_luf_build_v_cols +void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]); +/* build matrix V in column-wise format */ + +#define luf_check_f_rc _glp_luf_check_f_rc +void luf_check_f_rc(LUF *luf); +/* check rows and columns of matrix F */ + +#define luf_check_v_rc _glp_luf_check_v_rc +void luf_check_v_rc(LUF *luf); +/* check rows and columns of matrix V */ + +#define luf_f_solve _glp_luf_f_solve +void luf_f_solve(LUF *luf, double x[/*1+n*/]); +/* solve system F * x = b */ + +#define luf_ft_solve _glp_luf_ft_solve +void luf_ft_solve(LUF *luf, double x[/*1+n*/]); +/* solve system F' * x = b */ + +#define luf_v_solve _glp_luf_v_solve +void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); +/* solve system V * x = b */ + +#define luf_vt_solve _glp_luf_vt_solve +void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); +/* solve system V' * x = b */ + +#define luf_vt_solve1 _glp_luf_vt_solve1 +void luf_vt_solve1(LUF *luf, double e[/*1+n*/], double y[/*1+n*/]); +/* solve system V' * y = e' to cause growth in y */ + +#define luf_estimate_norm _glp_luf_estimate_norm +double luf_estimate_norm(LUF *luf, double w1[/*1+n*/], double + w2[/*1+n*/]); +/* estimate 1-norm of inv(A) */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.c new file mode 100644 index 000000000..7cd00924f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.c @@ -0,0 +1,182 @@ +/* lufint.c (interface to LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "lufint.h" + +LUFINT *lufint_create(void) +{ /* create interface to LU-factorization */ + LUFINT *fi; + fi = talloc(1, LUFINT); + fi->n_max = 0; + fi->valid = 0; + fi->sva = NULL; + fi->luf = NULL; + fi->sgf = NULL; + fi->sva_n_max = fi->sva_size = 0; + fi->delta_n0 = fi->delta_n = 0; + fi->sgf_updat = 0; + fi->sgf_piv_tol = 0.10; + fi->sgf_piv_lim = 4; + fi->sgf_suhl = 1; + fi->sgf_eps_tol = DBL_EPSILON; + return fi; +} + +int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute LU-factorization of specified matrix A */ + SVA *sva; + LUF *luf; + SGF *sgf; + int k; + xassert(n > 0); + fi->valid = 0; + /* create sparse vector area (SVA), if necessary */ + sva = fi->sva; + if (sva == NULL) + { int sva_n_max = fi->sva_n_max; + int sva_size = fi->sva_size; + if (sva_n_max == 0) + sva_n_max = 4 * n; + if (sva_size == 0) + sva_size = 10 * n; + sva = fi->sva = sva_create_area(sva_n_max, sva_size); + } + /* allocate/reallocate underlying objects, if necessary */ + if (fi->n_max < n) + { int n_max = fi->n_max; + if (n_max == 0) + n_max = fi->n_max = n + fi->delta_n0; + else + n_max = fi->n_max = n + fi->delta_n; + xassert(n_max >= n); + /* allocate/reallocate LU-factorization (LUF) */ + luf = fi->luf; + if (luf == NULL) + { luf = fi->luf = talloc(1, LUF); + memset(luf, 0, sizeof(LUF)); + luf->sva = sva; + } + else + { tfree(luf->vr_piv); + tfree(luf->pp_ind); + tfree(luf->pp_inv); + tfree(luf->qq_ind); + tfree(luf->qq_inv); + } + luf->vr_piv = talloc(1+n_max, double); + luf->pp_ind = talloc(1+n_max, int); + luf->pp_inv = talloc(1+n_max, int); + luf->qq_ind = talloc(1+n_max, int); + luf->qq_inv = talloc(1+n_max, int); + /* allocate/reallocate factorizer workspace (SGF) */ + sgf = fi->sgf; + if (sgf == NULL) + { sgf = fi->sgf = talloc(1, SGF); + memset(sgf, 0, sizeof(SGF)); + sgf->luf = luf; + } + else + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + } + sgf->rs_head = talloc(1+n_max, int); + sgf->rs_prev = talloc(1+n_max, int); + sgf->rs_next = talloc(1+n_max, int); + sgf->cs_head = talloc(1+n_max, int); + sgf->cs_prev = talloc(1+n_max, int); + sgf->cs_next = talloc(1+n_max, int); + sgf->vr_max = talloc(1+n_max, double); + sgf->flag = talloc(1+n_max, char); + sgf->work = talloc(1+n_max, double); + } + luf = fi->luf; + sgf = fi->sgf; +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* allocate sparse vectors in SVA */ + luf->n = n; + luf->fr_ref = sva_alloc_vecs(sva, n); + luf->fc_ref = sva_alloc_vecs(sva, n); + luf->vr_ref = sva_alloc_vecs(sva, n); + luf->vc_ref = sva_alloc_vecs(sva, n); + /* store matrix V = A in column-wise format */ + luf_store_v_cols(luf, col, info, sgf->rs_prev, sgf->work); + /* setup factorizer control parameters */ + sgf->updat = fi->sgf_updat; + sgf->piv_tol = fi->sgf_piv_tol; + sgf->piv_lim = fi->sgf_piv_lim; + sgf->suhl = fi->sgf_suhl; + sgf->eps_tol = fi->sgf_eps_tol; + /* compute LU-factorization of specified matrix A */ + k = sgf_factorize(sgf, 1); + if (k == 0) + fi->valid = 1; + return k; +} + +void lufint_delete(LUFINT *fi) +{ /* delete interface to LU-factorization */ + SVA *sva = fi->sva; + LUF *luf = fi->luf; + SGF *sgf = fi->sgf; + if (sva != NULL) + sva_delete_area(sva); + if (luf != NULL) + { tfree(luf->vr_piv); + tfree(luf->pp_ind); + tfree(luf->pp_inv); + tfree(luf->qq_ind); + tfree(luf->qq_inv); + tfree(luf); + } + if (sgf != NULL) + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + tfree(sgf); + } + tfree(fi); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.h new file mode 100644 index 000000000..b3ad5b646 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/lufint.h @@ -0,0 +1,73 @@ +/* lufint.h (interface to LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef LUFINT_H +#define LUFINT_H + +#include "sgf.h" + +typedef struct LUFINT LUFINT; + +struct LUFINT +{ /* interface to LU-factorization */ + int n_max; + /* maximal value of n (increased automatically) */ + int valid; + /* factorization is valid only if this flag is set */ + SVA *sva; + /* sparse vector area (SVA) */ + LUF *luf; + /* sparse LU-factorization */ + SGF *sgf; + /* sparse Gaussian factorizer workspace */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int sva_n_max, sva_size; + /* parameters passed to sva_create_area */ + int delta_n0, delta_n; + /* if n_max = 0, set n_max = n + delta_n0 + * if n_max < n, set n_max = n + delta_n */ + int sgf_updat; + double sgf_piv_tol; + int sgf_piv_lim; + int sgf_suhl; + double sgf_eps_tol; + /* factorizer control parameters */ +}; + +#define lufint_create _glp_lufint_create +LUFINT *lufint_create(void); +/* create interface to LU-factorization */ + +#define lufint_factorize _glp_lufint_factorize +int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute LU-factorization of specified matrix A */ + +#define lufint_delete _glp_lufint_delete +void lufint_delete(LUFINT *fi); +/* delete interface to LU-factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.c new file mode 100644 index 000000000..556b19114 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.c @@ -0,0 +1,523 @@ +/* scf.c (sparse updatable Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "scf.h" + +/*********************************************************************** +* scf_r0_solve - solve system R0 * x = b or R0'* x = b +* +* This routine solves the system R0 * x = b (if tr is zero) or the +* system R0'* x = b (if tr is non-zero), where R0 is the left factor +* of the initial matrix A0 = R0 * S0. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n0], where n0 is the order of the +* matrix R0. On exit the array x will contain elements of the solution +* vector in the same locations. */ + +void scf_r0_solve(SCF *scf, int tr, double x[/*1+n0*/]) +{ switch (scf->type) + { case 1: + /* A0 = F0 * V0, so R0 = F0 */ + if (!tr) + luf_f_solve(scf->a0.luf, x); + else + luf_ft_solve(scf->a0.luf, x); + break; + case 2: + /* A0 = I * A0, so R0 = I */ + break; + default: + xassert(scf != scf); + } + return; +} + +/*********************************************************************** +* scf_s0_solve - solve system S0 * x = b or S0'* x = b +* +* This routine solves the system S0 * x = b (if tr is zero) or the +* system S0'* x = b (if tr is non-zero), where S0 is the right factor +* of the initial matrix A0 = R0 * S0. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n0], where n0 is the order of the +* matrix S0. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* The routine uses locations [1], ..., [n0] of three working arrays +* w1, w2, and w3. (In case of type = 1 arrays w2 and w3 are not used +* and can be specified as NULL.) */ + +void scf_s0_solve(SCF *scf, int tr, double x[/*1+n0*/], + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]) +{ int n0 = scf->n0; + switch (scf->type) + { case 1: + /* A0 = F0 * V0, so S0 = V0 */ + if (!tr) + luf_v_solve(scf->a0.luf, x, w1); + else + luf_vt_solve(scf->a0.luf, x, w1); + break; + case 2: + /* A0 = I * A0, so S0 = A0 */ + if (!tr) + btf_a_solve(scf->a0.btf, x, w1, w2, w3); + else + btf_at_solve(scf->a0.btf, x, w1, w2, w3); + break; + default: + xassert(scf != scf); + } + memcpy(&x[1], &w1[1], n0 * sizeof(double)); + return; +} + +/*********************************************************************** +* scf_r_prod - compute product y := y + alpha * R * x +* +* This routine computes the product y := y + alpha * R * x, where +* x is a n0-vector, alpha is a scalar, y is a nn-vector. +* +* Since matrix R is available by rows, the product components are +* computed as inner products: +* +* y[i] = y[i] + alpha * (i-th row of R) * x +* +* for i = 1, 2, ..., nn. */ + +void scf_r_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int i, ptr, end; + double t; + for (i = 1; i <= nn; i++) + { /* t := (i-th row of R) * x */ + t = 0.0; + for (end = (ptr = rr_ptr[i]) + rr_len[i]; ptr < end; ptr++) + t += sv_val[ptr] * x[sv_ind[ptr]]; + /* y[i] := y[i] + alpha * t */ + y[i] += a * t; + } + return; +} + +/*********************************************************************** +* scf_rt_prod - compute product y := y + alpha * R'* x +* +* This routine computes the product y := y + alpha * R'* x, where +* R' is a matrix transposed to R, x is a nn-vector, alpha is a scalar, +* y is a n0-vector. +* +* Since matrix R is available by rows, the product is computed as a +* linear combination: +* +* y := y + alpha * (R'[1] * x[1] + ... + R'[nn] * x[nn]), +* +* where R'[i] is i-th row of R. */ + +void scf_rt_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int i, ptr, end; + double t; + for (i = 1; i <= nn; i++) + { if (x[i] == 0.0) + continue; + /* y := y + alpha * R'[i] * x[i] */ + t = a * x[i]; + for (end = (ptr = rr_ptr[i]) + rr_len[i]; ptr < end; ptr++) + y[sv_ind[ptr]] += sv_val[ptr] * t; + } + return; +} + +/*********************************************************************** +* scf_s_prod - compute product y := y + alpha * S * x +* +* This routine computes the product y := y + alpha * S * x, where +* x is a nn-vector, alpha is a scalar, y is a n0 vector. +* +* Since matrix S is available by columns, the product is computed as +* a linear combination: +* +* y := y + alpha * (S[1] * x[1] + ... + S[nn] * x[nn]), +* +* where S[j] is j-th column of S. */ + +void scf_s_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int j, ptr, end; + double t; + for (j = 1; j <= nn; j++) + { if (x[j] == 0.0) + continue; + /* y := y + alpha * S[j] * x[j] */ + t = a * x[j]; + for (end = (ptr = ss_ptr[j]) + ss_len[j]; ptr < end; ptr++) + y[sv_ind[ptr]] += sv_val[ptr] * t; + } + return; +} + +/*********************************************************************** +* scf_st_prod - compute product y := y + alpha * S'* x +* +* This routine computes the product y := y + alpha * S'* x, where +* S' is a matrix transposed to S, x is a n0-vector, alpha is a scalar, +* y is a nn-vector. +* +* Since matrix S is available by columns, the product components are +* computed as inner products: +* +* y[j] := y[j] + alpha * (j-th column of S) * x +* +* for j = 1, 2, ..., nn. */ + +void scf_st_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int j, ptr, end; + double t; + for (j = 1; j <= nn; j++) + { /* t := (j-th column of S) * x */ + t = 0.0; + for (end = (ptr = ss_ptr[j]) + ss_len[j]; ptr < end; ptr++) + t += sv_val[ptr] * x[sv_ind[ptr]]; + /* y[j] := y[j] + alpha * t */ + y[j] += a * t; + } + return; +} + +/*********************************************************************** +* scf_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where A is the current +* matrix. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* For details see the program documentation. */ + +void scf_a_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]) +{ int n = scf->n; + int n0 = scf->n0; + int nn = scf->nn; + int *pp_ind = scf->pp_ind; + int *qq_inv = scf->qq_inv; + int i, ii; + /* (u1, u2) := inv(P) * (b, 0) */ + for (ii = 1; ii <= n0+nn; ii++) + { i = pp_ind[ii]; +#if 1 /* FIXME: currently P = I */ + xassert(i == ii); +#endif + w[ii] = (i <= n ? x[i] : 0.0); + } + /* v1 := inv(R0) * u1 */ + scf_r0_solve(scf, 0, &w[0]); + /* v2 := u2 - R * v1 */ + scf_r_prod(scf, &w[n0], -1.0, &w[0]); + /* w2 := inv(C) * v2 */ + ifu_a_solve(&scf->ifu, &w[n0], work1); + /* w1 := inv(S0) * (v1 - S * w2) */ + scf_s_prod(scf, &w[0], -1.0, &w[n0]); + scf_s0_solve(scf, 0, &w[0], work1, work2, work3); + /* (x, x~) := inv(Q) * (w1, w2); x~ is not needed */ + for (i = 1; i <= n; i++) + x[i] = w[qq_inv[i]]; + return; +} + +/*********************************************************************** +* scf_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the current matrix A. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* For details see the program documentation. */ + +void scf_at_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]) +{ int n = scf->n; + int n0 = scf->n0; + int nn = scf->nn; + int *pp_inv = scf->pp_inv; + int *qq_ind = scf->qq_ind; + int i, ii; + /* (u1, u2) := Q * (b, 0) */ + for (ii = 1; ii <= n0+nn; ii++) + { i = qq_ind[ii]; + w[ii] = (i <= n ? x[i] : 0.0); + } + /* v1 := inv(S0') * u1 */ + scf_s0_solve(scf, 1, &w[0], work1, work2, work3); + /* v2 := inv(C') * (u2 - S'* v1) */ + scf_st_prod(scf, &w[n0], -1.0, &w[0]); + ifu_at_solve(&scf->ifu, &w[n0], work1); + /* w2 := v2 */ + /* nop */ + /* w1 := inv(R0') * (v1 - R'* w2) */ + scf_rt_prod(scf, &w[0], -1.0, &w[n0]); + scf_r0_solve(scf, 1, &w[0]); + /* compute (x, x~) := P * (w1, w2); x~ is not needed */ + for (i = 1; i <= n; i++) + { +#if 1 /* FIXME: currently P = I */ + xassert(pp_inv[i] == i); +#endif + x[i] = w[pp_inv[i]]; + } + return; +} + +/*********************************************************************** +* scf_add_r_row - add new row to matrix R +* +* This routine adds new (nn+1)-th row to matrix R, whose elements are +* specified in locations w[1,...,n0]. */ + +void scf_add_r_row(SCF *scf, const double w[/*1+n0*/]) +{ int n0 = scf->n0; + int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int j, len, ptr; + xassert(0 <= nn && nn < scf->nn_max); + /* determine length of new row */ + len = 0; + for (j = 1; j <= n0; j++) + { if (w[j] != 0.0) + len++; + } + /* reserve locations for new row in static part of SVA */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, rr_ref + nn, len); + } + /* store new row in sparse format */ + ptr = rr_ptr[nn+1]; + for (j = 1; j <= n0; j++) + { if (w[j] != 0.0) + { sv_ind[ptr] = j; + sv_val[ptr] = w[j]; + ptr++; + } + } + xassert(ptr - rr_ptr[nn+1] == len); + rr_len[nn+1] = len; +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + return; +} + +/*********************************************************************** +* scf_add_s_col - add new column to matrix S +* +* This routine adds new (nn+1)-th column to matrix S, whose elements +* are specified in locations v[1,...,n0]. */ + +void scf_add_s_col(SCF *scf, const double v[/*1+n0*/]) +{ int n0 = scf->n0; + int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int i, len, ptr; + xassert(0 <= nn && nn < scf->nn_max); + /* determine length of new column */ + len = 0; + for (i = 1; i <= n0; i++) + { if (v[i] != 0.0) + len++; + } + /* reserve locations for new column in static part of SVA */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ss_ref + nn, len); + } + /* store new column in sparse format */ + ptr = ss_ptr[nn+1]; + for (i = 1; i <= n0; i++) + { if (v[i] != 0.0) + { sv_ind[ptr] = i; + sv_val[ptr] = v[i]; + ptr++; + } + } + xassert(ptr - ss_ptr[nn+1] == len); + ss_len[nn+1] = len; +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + return; +} + +/*********************************************************************** +* scf_update_aug - update factorization of augmented matrix +* +* Given factorization of the current augmented matrix: +* +* ( A0 A1 ) ( R0 ) ( S0 S ) +* ( ) = ( ) ( ), +* ( A2 A3 ) ( R I ) ( C ) +* +* this routine computes factorization of the new augmented matrix: +* +* ( A0 | A1 b ) +* ( ---+------ ) ( A0 A1^ ) ( R0 ) ( S0 S^ ) +* ( A2 | A3 f ) = ( ) = ( ) ( ), +* ( | ) ( A2^ A3^ ) ( R^ I ) ( C^ ) +* ( d' | g' h ) +* +* where b and d are specified n0-vectors, f and g are specified +* nn-vectors, and h is a specified scalar. (Note that corresponding +* arrays are clobbered on exit.) +* +* The parameter upd specifies how to update factorization of the Schur +* complement C: +* +* 1 Bartels-Golub updating. +* +* 2 Givens rotations updating. +* +* The working arrays w1, w2, and w3 are used in the same way as in the +* routine scf_s0_solve. +* +* RETURNS +* +* 0 Factorization has been successfully updated. +* +* 1 Updating limit has been reached. +* +* 2 Updating IFU-factorization of matrix C failed. +* +* For details see the program documentation. */ + +int scf_update_aug(SCF *scf, double b[/*1+n0*/], double d[/*1+n0*/], + double f[/*1+nn*/], double g[/*1+nn*/], double h, int upd, + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]) +{ int n0 = scf->n0; + int k, ret; + double *v, *w, *x, *y, z; + if (scf->nn == scf->nn_max) + { /* updating limit has been reached */ + return 1; + } + /* v := inv(R0) * b */ + scf_r0_solve(scf, 0, (v = b)); + /* w := inv(S0') * d */ + scf_s0_solve(scf, 1, (w = d), w1, w2, w3); + /* x := f - R * v */ + scf_r_prod(scf, (x = f), -1.0, v); + /* y := g - S'* w */ + scf_st_prod(scf, (y = g), -1.0, w); + /* z := h - v'* w */ + z = h; + for (k = 1; k <= n0; k++) + z -= v[k] * w[k]; + /* new R := R with row w added */ + scf_add_r_row(scf, w); + /* new S := S with column v added */ + scf_add_s_col(scf, v); + /* update IFU-factorization of C */ + switch (upd) + { case 1: + ret = ifu_bg_update(&scf->ifu, x, y, z); + break; + case 2: + ret = ifu_gr_update(&scf->ifu, x, y, z); + break; + default: + xassert(upd != upd); + } + if (ret != 0) + { /* updating IFU-factorization failed */ + return 2; + } + /* increase number of additional rows and columns */ + scf->nn++; + /* expand P and Q */ + k = n0 + scf->nn; + scf->pp_ind[k] = scf->pp_inv[k] = k; + scf->qq_ind[k] = scf->qq_inv[k] = k; + /* factorization has been successfully updated */ + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.h new file mode 100644 index 000000000..69d8cfc2a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scf.h @@ -0,0 +1,211 @@ +/* scf.h (sparse updatable Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SCF_H +#define SCF_H + +#include "btf.h" +#include "ifu.h" +#include "luf.h" + +/*********************************************************************** +* The structure SCF describes sparse updatable factorization based on +* Schur complement. +* +* The SCF-factorization has the following format: +* +* ( A A1~ ) ( A0 A1 ) ( R0 ) ( S0 S ) +* ( ) = P ( ) Q = P ( ) ( ) Q, (1) +* ( A2~ A3~ ) ( A2 A3 ) ( R I ) ( C ) +* +* where: +* +* A is current (unsymmetric) square matrix (not stored); +* +* A1~, A2~, A3~ are some additional matrices (not stored); +* +* A0 is initial (unsymmetric) square matrix (not stored); +* +* A1, A2, A3 are some additional matrices (not stored); +* +* R0 and S0 are matrices that define factorization of the initial +* matrix A0 = R0 * S0 (stored in an invertable form); +* +* R is a matrix defined from R * S0 = A2, so R = A2 * inv(S0) (stored +* in row-wise sparse format); +* +* S is a matrix defined from R0 * S = A1, so S = inv(R0) * A1 (stored +* in column-wise sparse format); +* +* C is Schur complement (to matrix A0) defined from R * S + C = A3, +* so C = A3 - R * S = A3 - A2 * inv(A0) * A1 (stored in an invertable +* form). +* +* P, Q are permutation matrices (stored in both row- and column-like +* formats). */ + +typedef struct SCF SCF; + +struct SCF +{ /* Schur-complement-based factorization */ + int n; + /* order of current matrix A */ + /*--------------------------------------------------------------*/ + /* initial matrix A0 = R0 * S0 of order n0 in invertable form */ + int n0; + /* order of matrix A0 */ + int type; + /* type of factorization used: + * 1 - LU-factorization (R0 = F0, S0 = V0) + * 2 - BT-factorization (R0 = I, S0 = A0) */ + union + { LUF *luf; /* type = 1 */ + BTF *btf; /* type = 2 */ + } a0; + /* factorization of matrix A0 */ + /*--------------------------------------------------------------*/ + /* augmented matrix (A0, A1; A2, A3) of order n0+nn */ + int nn_max; + /* maximal number of additional rows and columns in the augmented + * matrix (this limits the number of updates) */ + int nn; + /* current number of additional rows and columns in the augmented + * matrix, 0 <= nn <= nn_max */ + SVA *sva; + /* associated sparse vector area (SVA) used to store rows of + * matrix R and columns of matrix S */ + /*--------------------------------------------------------------*/ + /* nn*n0-matrix R in row-wise format */ + int rr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix R */ +#if 0 + 0 + int *rr_ptr = &sva->ptr[rr_ref-1]; + /* rr_ptr[0] is not used; + * rr_ptr[i], 1 <= i <= nn, is pointer to i-th row in SVA; + * rr_ptr[nn+1,...,nn_max] are reserved locations */ + int *rr_len = &sva->len[rr_ref-1]; + /* rr_len[0] is not used; + * rr_len[i], 1 <= i <= nn, is length of i-th row; + * rr_len[nn+1,...,nn_max] are reserved locations */ +#endif + /*--------------------------------------------------------------*/ + /* n0*nn-matrix S in column-wise format */ + int ss_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix S */ +#if 0 + 0 + int *ss_ptr = &sva->ptr[ss_ref-1]; + /* ss_ptr[0] is not used; + * ss_ptr[j], 1 <= j <= nn, is pointer to j-th column in SVA; + * ss_ptr[nn+1,...,nn_max] are reserved locations */ + int *ss_len = &sva->len[ss_ref-1]; + /* ss_len[0] is not used; + * ss_len[j], 1 <= j <= nn, is length of j-th column; + * ss_len[nn+1,...,nn_max] are reserved locations */ +#endif + /*--------------------------------------------------------------*/ + /* Schur complement C of order nn in invertable form */ + IFU ifu; + /* IFU-factorization of matrix C */ + /*--------------------------------------------------------------*/ + /* permutation matrix P of order n0+nn */ + int *pp_ind; /* int pp_ind[1+n0+nn_max]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n0+nn_max]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /*--------------------------------------------------------------*/ + /* permutation matrix Q of order n0+nn */ + int *qq_ind; /* int qq_ind[1+n0+nn_max]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n0+nn_max]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ +}; + +#define scf_swap_q_cols(j1, j2) \ + do \ + { int i1, i2; \ + i1 = qq_inv[j1], i2 = qq_inv[j2]; \ + qq_ind[i1] = j2, qq_inv[j2] = i1; \ + qq_ind[i2] = j1, qq_inv[j1] = i2; \ + } while (0) +/* swap columns j1 and j2 of permutation matrix Q */ + +#define scf_r0_solve _glp_scf_r0_solve +void scf_r0_solve(SCF *scf, int tr, double x[/*1+n0*/]); +/* solve system R0 * x = b or R0'* x = b */ + +#define scf_s0_solve _glp_scf_s0_solve +void scf_s0_solve(SCF *scf, int tr, double x[/*1+n0*/], + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]); +/* solve system S0 * x = b or S0'* x = b */ + +#define scf_r_prod _glp_scf_r_prod +void scf_r_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]); +/* compute product y := y + alpha * R * x */ + +#define scf_rt_prod _glp_scf_rt_prod +void scf_rt_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]); +/* compute product y := y + alpha * R'* x */ + +#define scf_s_prod _glp_scf_s_prod +void scf_s_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]); +/* compute product y := y + alpha * S * x */ + +#define scf_st_prod _glp_scf_st_prod +void scf_st_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]); +/* compute product y := y + alpha * S'* x */ + +#define scf_a_solve _glp_scf_a_solve +void scf_a_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]); +/* solve system A * x = b */ + +#define scf_at_solve _glp_scf_at_solve +void scf_at_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]); +/* solve system A'* x = b */ + +#define scf_add_r_row _glp_scf_add_r_row +void scf_add_r_row(SCF *scf, const double w[/*1+n0*/]); +/* add new row to matrix R */ + +#define scf_add_s_col _glp_scf_add_s_col +void scf_add_s_col(SCF *scf, const double v[/*1+n0*/]); +/* add new column to matrix S */ + +#define scf_update_aug _glp_scf_update_aug +int scf_update_aug(SCF *scf, double b[/*1+n0*/], double d[/*1+n0*/], + double f[/*1+nn*/], double g[/*1+nn*/], double h, int upd, + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]); +/* update factorization of augmented matrix */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.c new file mode 100644 index 000000000..06aa8f7d4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.c @@ -0,0 +1,255 @@ +/* scfint.c (interface to Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "scfint.h" + +SCFINT *scfint_create(int type) +{ /* create interface to SC-factorization */ + SCFINT *fi; + fi = talloc(1, SCFINT); + memset(fi, 0, sizeof(SCFINT)); + switch ((fi->scf.type = type)) + { case 1: + fi->u.lufi = lufint_create(); + break; + case 2: + fi->u.btfi = btfint_create(); + break; + default: + xassert(type != type); + } + return fi; +} + +int scfint_factorize(SCFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute SC-factorization of specified matrix A */ + int nn_max, old_n0_max, n0_max, k, ret; + xassert(n > 0); + fi->valid = 0; + /* get required value of nn_max */ + nn_max = fi->nn_max; + if (nn_max == 0) + nn_max = 100; + xassert(nn_max > 0); + /* compute factorization of specified matrix A */ + switch (fi->scf.type) + { case 1: + old_n0_max = fi->u.lufi->n_max; + fi->u.lufi->sva_n_max = 4 * n + 2 * nn_max; + ret = lufint_factorize(fi->u.lufi, n, col, info); + n0_max = fi->u.lufi->n_max; + fi->scf.sva = fi->u.lufi->sva; + fi->scf.a0.luf = fi->u.lufi->luf; + break; + case 2: + old_n0_max = fi->u.btfi->n_max; + fi->u.btfi->sva_n_max = 6 * n + 2 * nn_max; + ret = btfint_factorize(fi->u.btfi, n, col, info); + n0_max = fi->u.btfi->n_max; + fi->scf.sva = fi->u.btfi->sva; + fi->scf.a0.btf = fi->u.btfi->btf; + break; + default: + xassert(fi != fi); + } + /* allocate/reallocate arrays, if necessary */ + if (old_n0_max < n0_max) + { if (fi->w1 != NULL) + tfree(fi->w1); + if (fi->w2 != NULL) + tfree(fi->w2); + if (fi->w3 != NULL) + tfree(fi->w3); + fi->w1 = talloc(1+n0_max, double); + fi->w2 = talloc(1+n0_max, double); + fi->w3 = talloc(1+n0_max, double); + } + if (fi->scf.nn_max != nn_max) + { if (fi->scf.ifu.f != NULL) + tfree(fi->scf.ifu.f); + if (fi->scf.ifu.u != NULL) + tfree(fi->scf.ifu.u); + fi->scf.ifu.f = talloc(nn_max * nn_max, double); + fi->scf.ifu.u = talloc(nn_max * nn_max, double); + } + if (old_n0_max < n0_max || fi->scf.nn_max != nn_max) + { if (fi->scf.pp_ind != NULL) + tfree(fi->scf.pp_ind); + if (fi->scf.pp_inv != NULL) + tfree(fi->scf.pp_inv); + if (fi->scf.qq_ind != NULL) + tfree(fi->scf.qq_ind); + if (fi->scf.qq_inv != NULL) + tfree(fi->scf.qq_inv); + if (fi->w4 != NULL) + tfree(fi->w4); + if (fi->w5 != NULL) + tfree(fi->w5); + fi->scf.pp_ind = talloc(1+n0_max+nn_max, int); + fi->scf.pp_inv = talloc(1+n0_max+nn_max, int); + fi->scf.qq_ind = talloc(1+n0_max+nn_max, int); + fi->scf.qq_inv = talloc(1+n0_max+nn_max, int); + fi->w4 = talloc(1+n0_max+nn_max, double); + fi->w5 = talloc(1+n0_max+nn_max, double); + } + /* initialize SC-factorization */ + fi->scf.n = n; + fi->scf.n0 = n; + fi->scf.nn_max = nn_max; + fi->scf.nn = 0; + fi->scf.rr_ref = sva_alloc_vecs(fi->scf.sva, nn_max); + fi->scf.ss_ref = sva_alloc_vecs(fi->scf.sva, nn_max); + fi->scf.ifu.n_max = nn_max; + fi->scf.ifu.n = 0; + for (k = 1; k <= n; k++) + { fi->scf.pp_ind[k] = k; + fi->scf.pp_inv[k] = k; + fi->scf.qq_ind[k] = k; + fi->scf.qq_inv[k] = k; + } + /* set validation flag */ + if (ret == 0) + fi->valid = 1; + return ret; +} + +int scfint_update(SCFINT *fi, int upd, int j, int len, const int ind[], + const double val[]) +{ /* update SC-factorization after replacing j-th column of A */ + int n = fi->scf.n; + int n0 = fi->scf.n0; + int nn = fi->scf.nn; + int *pp_ind = fi->scf.pp_ind; + int *qq_ind = fi->scf.qq_ind; + int *qq_inv = fi->scf.qq_inv; + double *bf = fi->w4; + double *dg = fi->w5; + int k, t, ret; + xassert(fi->valid); + xassert(0 <= n && n <= n0+nn); + /* (b, f) := inv(P) * (beta, 0) */ + for (k = 1; k <= n0+nn; k++) + bf[k] = 0.0; + for (t = 1; t <= len; t++) + { k = ind[t]; + xassert(1 <= k && k <= n); +#if 1 /* FIXME: currently P = I */ + xassert(pp_ind[k] == k); +#endif + xassert(bf[k] == 0.0); + xassert(val[t] != 0.0); + bf[k] = val[t]; + } + /* (d, g) := Q * (cj, 0) */ + for (k = 1; k <= n0+nn; k++) + dg[k] = 0.0; + xassert(1 <= j && j <= n); + dg[fi->scf.qq_inv[j]] = 1; + /* update factorization of augmented matrix */ + ret = scf_update_aug(&fi->scf, &bf[0], &dg[0], &bf[n0], &dg[n0], + 0.0, upd, fi->w1, fi->w2, fi->w3); + if (ret == 0) + { /* swap j-th and last columns of new matrix Q */ + scf_swap_q_cols(j, n0+nn+1); + } + else + { /* updating failed */ + fi->valid = 0; + } + return ret; +} + +void scfint_ftran(SCFINT *fi, double x[]) +{ /* solve system A * x = b */ + xassert(fi->valid); + scf_a_solve(&fi->scf, x, fi->w4, fi->w5, fi->w1, fi->w2); + return; +} + +void scfint_btran(SCFINT *fi, double x[]) +{ /* solve system A'* x = b */ + xassert(fi->valid); + scf_at_solve(&fi->scf, x, fi->w4, fi->w5, fi->w1, fi->w2); + return; +} + +double scfint_estimate(SCFINT *fi) +{ /* estimate 1-norm of inv(A) */ + double norm; + xassert(fi->valid); + xassert(fi->scf.n == fi->scf.n0); + switch (fi->scf.type) + { case 1: + norm = luf_estimate_norm(fi->scf.a0.luf, fi->w1, fi->w2); + break; + case 2: + norm = btf_estimate_norm(fi->scf.a0.btf, fi->w1, fi->w2, + fi->w3, fi->w4); + break; + default: + xassert(fi != fi); + } + return norm; +} + +void scfint_delete(SCFINT *fi) +{ /* delete interface to SC-factorization */ + switch (fi->scf.type) + { case 1: + lufint_delete(fi->u.lufi); + break; + case 2: + btfint_delete(fi->u.btfi); + break; + default: + xassert(fi != fi); + } + if (fi->scf.ifu.f != NULL) + tfree(fi->scf.ifu.f); + if (fi->scf.ifu.u != NULL) + tfree(fi->scf.ifu.u); + if (fi->scf.pp_ind != NULL) + tfree(fi->scf.pp_ind); + if (fi->scf.pp_inv != NULL) + tfree(fi->scf.pp_inv); + if (fi->scf.qq_ind != NULL) + tfree(fi->scf.qq_ind); + if (fi->scf.qq_inv != NULL) + tfree(fi->scf.qq_inv); + if (fi->w1 != NULL) + tfree(fi->w1); + if (fi->w2 != NULL) + tfree(fi->w2); + if (fi->w3 != NULL) + tfree(fi->w3); + if (fi->w4 != NULL) + tfree(fi->w4); + if (fi->w5 != NULL) + tfree(fi->w5); + tfree(fi); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.h new file mode 100644 index 000000000..3e56355ba --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/scfint.h @@ -0,0 +1,89 @@ +/* scfint.h (interface to Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SCFINT_H +#define SCFINT_H + +#include "scf.h" +#include "lufint.h" +#include "btfint.h" + +typedef struct SCFINT SCFINT; + +struct SCFINT +{ /* interface to SC-factorization */ + int valid; + /* factorization is valid only if this flag is set */ + SCF scf; + /* Schur-complement based factorization */ + union + { LUFINT *lufi; /* scf.type = 1 */ + BTFINT *btfi; /* scf.type = 2 */ + } u; + /* interface to factorize initial matrix A0 */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *w1; /* double w1[1+n0_max]; */ + double *w2; /* double w2[1+n0_max]; */ + double *w3; /* double w3[1+n0_max]; */ + double *w4; /* double w4[1+n0_max+nn_max]; */ + double *w5; /* double w5[1+n0_max+nn_max]; */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int nn_max; + /* required maximal number of updates */ +}; + +#define scfint_create _glp_scfint_create +SCFINT *scfint_create(int type); +/* create interface to SC-factorization */ + +#define scfint_factorize _glp_scfint_factorize +int scfint_factorize(SCFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute SC-factorization of specified matrix A */ + +#define scfint_update _glp_scfint_update +int scfint_update(SCFINT *fi, int upd, int j, int len, const int ind[], + const double val[]); +/* update SC-factorization after replacing j-th column of A */ + +#define scfint_ftran _glp_scfint_ftran +void scfint_ftran(SCFINT *fi, double x[]); +/* solve system A * x = b */ + +#define scfint_btran _glp_scfint_btran +void scfint_btran(SCFINT *fi, double x[]); +/* solve system A'* x = b */ + +#define scfint_estimate _glp_scfint_estimate +double scfint_estimate(SCFINT *fi); +/* estimate 1-norm of inv(A) */ + +#define scfint_delete _glp_scfint_delete +void scfint_delete(SCFINT *fi); +/* delete interface to SC-factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.c new file mode 100644 index 000000000..1c1f49a63 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.c @@ -0,0 +1,1443 @@ +/* sgf.c (sparse Gaussian factorizer) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "sgf.h" + +/*********************************************************************** +* sgf_reduce_nuc - initial reordering to minimize nucleus size +* +* On entry to this routine it is assumed that V = A and F = P = Q = I, +* where A is the original matrix to be factorized. It is also assumed +* that matrix V = A is stored in both row- and column-wise formats. +* +* This routine performs (implicit) non-symmetric permutations of rows +* and columns of matrix U = P'* V * Q' to reduce it to the form: +* +* 1 k1 k2 n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* k1 . . . * * * * x x x +* . . . * * * * x x x +* . . . * * * * x x x +* k2 . . . * * * * x x x +* . . . . . . . x x x +* . . . . . . . . x x +* n . . . . . . . . . x +* +* where non-zeros in rows and columns k1, k1+1, ..., k2 constitute so +* called nucleus ('*'), whose size is minimized by the routine. +* +* The numbers k1 and k2 are returned by the routine on exit. Usually, +* if the nucleus exists, 1 <= k1 < k2 <= n. However, if the resultant +* matrix U is upper triangular (has no nucleus), k1 = n+1 and k2 = n. +* +* Note that the routines sgf_choose_pivot and sgf_eliminate perform +* exactly the same transformations (by processing row and columns +* singletons), so preliminary minimization of the nucleus may not be +* used. However, processing row and column singletons by the routines +* sgf_minimize_nuc and sgf_singl_phase is more efficient. */ + +#if 1 /* 21/II-2016 */ +/* Normally this routine returns zero. If the matrix is structurally +* singular, the routine returns non-zero. */ +#endif + +int sgf_reduce_nuc(LUF *luf, int *k1_, int *k2_, int cnt[/*1+n*/], + int list[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, ii, j, jj, k1, k2, ns, ptr, end; + /* initial nucleus is U = V = A */ + k1 = 1, k2 = n; + /*--------------------------------------------------------------*/ + /* process column singletons */ + /*--------------------------------------------------------------*/ + /* determine initial counts of columns of V and initialize list + * of active column singletons */ + ns = 0; /* number of active column singletons */ + for (j = 1; j <= n; j++) + { if ((cnt[j] = vc_len[j]) == 1) + list[++ns] = j; + } + /* process active column singletons */ + while (ns > 0) + { /* column singleton is in j-th column of V */ + j = list[ns--]; +#if 1 /* 21/II-2016 */ + if (cnt[j] == 0) + { /* j-th column in the current nucleus is actually empty */ + /* this happened because on a previous step in the nucleus + * there were two or more identical column singletons (that + * means structural singularity), so removing one of them + * from the nucleus made other columns empty */ + return 1; + } +#endif + /* find i-th row of V containing column singleton */ + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; pp_ind[i = sv_ind[ptr]] < k1; ptr++) + /* nop */; + xassert(ptr < end); + /* permute rows and columns of U to move column singleton to + * position u[k1,k1] */ + ii = pp_ind[i]; + luf_swap_u_rows(k1, ii); + jj = qq_inv[j]; + luf_swap_u_cols(k1, jj); + /* nucleus size decreased */ + k1++; + /* walk thru i-th row of V and decrease column counts; this + * may cause new column singletons to appear */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + { if (--(cnt[j = sv_ind[ptr]]) == 1) + list[++ns] = j; + } + } + /* nucleus begins at k1-th row/column of U */ + if (k1 > n) + { /* U is upper triangular; no nucleus exist */ + goto done; + } + /*--------------------------------------------------------------*/ + /* process row singletons */ + /*--------------------------------------------------------------*/ + /* determine initial counts of rows of V and initialize list of + * active row singletons */ + ns = 0; /* number of active row singletons */ + for (i = 1; i <= n; i++) + { if (pp_ind[i] < k1) + { /* corresponding row of U is above its k1-th row; set its + * count to zero to prevent including it in active list */ + cnt[i] = 0; + } + else if ((cnt[i] = vr_len[i]) == 1) + list[++ns] = i; + } + /* process active row singletons */ + while (ns > 0) + { /* row singleton is in i-th row of V */ + i = list[ns--]; +#if 1 /* 21/II-2016 */ + if (cnt[i] == 0) + { /* i-th row in the current nucleus is actually empty */ + /* (see comments above for similar case of empty column) */ + return 2; + } +#endif + /* find j-th column of V containing row singleton */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; qq_inv[j = sv_ind[ptr]] > k2; ptr++) + /* nop */; + xassert(ptr < end); + /* permute rows and columns of U to move row singleton to + * position u[k2,k2] */ + ii = pp_ind[i]; + luf_swap_u_rows(k2, ii); + jj = qq_inv[j]; + luf_swap_u_cols(k2, jj); + /* nucleus size decreased */ + k2--; + /* walk thru j-th column of V and decrease row counts; this + * may cause new row singletons to appear */ + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { if (--(cnt[i = sv_ind[ptr]]) == 1) + list[++ns] = i; + } + } + /* nucleus ends at k2-th row/column of U */ + xassert(k1 < k2); +done: *k1_ = k1, *k2_ = k2; + return 0; +} + +/*********************************************************************** +* sgf_singl_phase - compute LU-factorization (singleton phase) +* +* It is assumed that on entry to the routine L = P'* F * P = F = I +* and matrix U = P'* V * Q' has the following structure (provided by +* the routine sgf_reduce_nuc): +* +* 1 k1 k2 n +* 1 a a a b b b b c c c +* . a a b b b b c c c +* . . a b b b b c c c +* k1 . . . * * * * d d d +* . . . * * * * d d d +* . . . * * * * d d d +* k2 . . . * * * * d d d +* . . . . . . . e e e +* . . . . . . . . e e +* n . . . . . . . . . e +* +* First, the routine performs (implicit) symmetric permutations of +* rows and columns of matrix U to place them in the following order: +* +* 1, 2, ..., k1-1; n, n-1, ..., k2+1; k1, k1+1, ..., k2 +* +* This changes the structure of matrix U as follows: +* +* 1 k1 k2' n +* 1 a a a c c c b b b b +* . a a c c c b b b b +* . . a c c c b b b b +* k1 . . . e . . . . . . +* . . . e e . . . . . +* . . . e e e . . . . +* k2'. . . d d d * * * * +* . . . d d d * * * * +* . . . d d d * * * * +* n . . . d d d * * * * +* +* where k2' = n - k2 + k1. +* +* Then the routine performs elementary gaussian transformations to +* eliminate subdiagonal elements in columns k1, ..., k2'-1 of U. The +* effect is the same as if the routine sgf_eliminate would be called +* for k = 1, ..., k2'-1 using diagonal elements u[k,k] as pivots. +* +* After elimination matrices L and U becomes the following: +* +* 1 k1 k2' n 1 k1 k2' n +* 1 1 . . . . . . . . . 1 a a a c c c b b b b +* . 1 . . . . . . . . . a a c c c b b b b +* . . 1 . . . . . . . . . a c c c b b b b +* k1 . . . 1 . . . . . . k1 . . . e . . . . . . +* . . . e'1 . . . . . . . . . e . . . . . +* . . . e'e'1 . . . . . . . . . e . . . . +* k2'. . . d'd'd'1 . . . k2'. . . . . . * * * * +* . . . d'd'd'. 1 . . . . . . . . * * * * +* . . . d'd'd'. . 1 . . . . . . . * * * * +* n . . . d'd'd'. . . 1 n . . . . . . * * * * +* +* matrix L matrix U +* +* where columns k1, ..., k2'-1 of L consist of subdiagonal elements +* of initial matrix U divided by pivots u[k,k]. +* +* On exit the routine returns k2', the elimination step number, from +* which computing of the factorization should be continued. Note that +* k2' = n+1 means that matrix U is already upper triangular. */ + +int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, + int ind[/*1+n*/], double val[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int i, j, k, ptr, ptr1, end, len; + double piv; + /* (see routine sgf_reduce_nuc) */ + xassert((1 <= k1 && k1 < k2 && k2 <= n) + || (k1 == n+1 && k2 == n)); + /* perform symmetric permutations of rows/columns of U */ + for (k = k1; k <= k2; k++) + pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = k - k2 + n; + for (k = k2+1; k <= n; k++) + pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = n - k + k1; + for (k = 1; k <= n; k++) + pp_inv[pp_ind[k]] = qq_ind[qq_inv[k]] = k; + /* determine k2' */ + k2 = n - k2 + k1; + /* process rows and columns of V corresponding to rows and + * columns 1, ..., k1-1 of U */ + for (k = 1; k < k1; k++) + { /* k-th row of U = i-th row of V */ + i = pp_inv[k]; + /* find pivot u[k,k] = v[i,j] in i-th row of V */ + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; qq_inv[sv_ind[ptr]] != k; ptr++) + /* nop */; + xassert(ptr < end); + /* store pivot */ + vr_piv[i] = sv_val[ptr]; + /* and remove it from i-th row of V */ + sv_ind[ptr] = sv_ind[end-1]; + sv_val[ptr] = sv_val[end-1]; + vr_len[i]--; + /* clear column of V corresponding to k-th column of U */ + vc_len[qq_ind[k]] = 0; + } + /* clear rows of V corresponding to rows k1, ..., k2'-1 of U */ + for (k = k1; k < k2; k++) + vr_len[pp_inv[k]] = 0; + /* process rows and columns of V corresponding to rows and + * columns k2', ..., n of U */ + for (k = k2; k <= n; k++) + { /* k-th row of U = i-th row of V */ + i = pp_inv[k]; + /* remove elements from i-th row of V that correspond to + * elements u[k,k1], ..., u[k,k2'-1] */ + ptr = ptr1 = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + { if (qq_inv[sv_ind[ptr]] >= k2) + { sv_ind[ptr1] = sv_ind[ptr]; + sv_val[ptr1] = sv_val[ptr]; + ptr1++; + } + } + vr_len[i] = ptr1 - vr_ptr[i]; + /* k-th column of U = j-th column of V */ + j = qq_ind[k]; + /* remove elements from j-th column of V that correspond to + * elements u[1,k], ..., u[k1-1,k] */ + ptr = ptr1 = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { if (pp_ind[sv_ind[ptr]] >= k2) + /* element value is not needed in this case */ + sv_ind[ptr1++] = sv_ind[ptr]; + } + vc_len[j] = ptr1 - vc_ptr[j]; + } + /* process columns of V corresponding to columns k1, ..., k2'-1 + * of U, build columns of F */ + for (k = k1; k < k2; k++) + { /* k-th column of U = j-th column of V */ + j = qq_ind[k]; + /* remove elements from j-th column of V that correspond to + * pivot (diagonal) element u[k,k] and subdiagonal elements + * u[k+1,k], ..., u[n,k]; subdiagonal elements are stored for + * further addition to matrix F */ + len = 0; + piv = 0.0; + ptr = vc_ptr[j]; + end = ptr + vc_len[j]; + for (; ptr < end; ptr++) + { i = sv_ind[ptr]; /* v[i,j] */ + if (pp_ind[i] == k) + { /* store pivot v[i,j] = u[k,k] */ + piv = vr_piv[i] = sv_val[ptr]; + } + else if (pp_ind[i] > k) + { /* store subdiagonal element v[i,j] = u[i',k] */ + len++; + ind[len] = i; + val[len] = sv_val[ptr]; + } + } + /* clear j-th column of V = k-th column of U */ + vc_len[j] = 0; + /* build k-th column of L = j-th column of F */ + j = pp_inv[k]; + xassert(piv != 0.0); + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fc_ref-1+j, len); + for (ptr = fc_ptr[j], ptr1 = 1; ptr1 <= len; ptr++, ptr1++) + { sv_ind[ptr] = ind[ptr1]; + sv_val[ptr] = val[ptr1] / piv; + } + fc_len[j] = len; + } + } + /* if it is not planned to update matrix V, relocate all its + * non-active rows corresponding to rows 1, ..., k2'-1 of U to + * the right (static) part of SVA */ + if (!updat) + { for (k = 1; k < k2; k++) + { i = pp_inv[k]; + len = vr_len[i]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+i); + } + } + /* elimination steps 1, ..., k2'-1 have been performed */ + return k2; +} + +/*********************************************************************** +* sgf_choose_pivot - choose pivot element v[p,q] +* +* This routine chooses pivot element v[p,q], k <= p, q <= n, in the +* active submatrix of matrix V = P * U * Q, where k is the number of +* current elimination step, 1 <= k <= n. +* +* It is assumed that on entry to the routine matrix U = P'* V * Q' has +* the following partially triangularized form: +* +* 1 k n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* . . . x x x x x x x +* k . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* n . . . . * * * * * * +* +* where rows and columns k, k+1, ..., n belong to the active submatrix +* (its elements are marked by '*'). +* +* Since the matrix U is not stored, the routine works with the matrix +* V = P * U * Q. It is assumed that the row-wise representation +* corresponds to the matrix V, but the column-wise representation +* corresponds to the active submatrix of the matrix V, i.e. elements, +* which are not in the active submatrix, are not included in column +* vectors. It is also assumed that each active row of the matrix V is +* in the set R[len], where len is the number of non-zeros in the row, +* and each active column of the matrix V is in the set C[len], where +* len is the number of non-zeros in the column (in the latter case +* only elements of the active submatrix are counted; such elements are +* marked by '*' on the figure above). +* +* For the reason of numerical stability the routine applies so called +* threshold pivoting proposed by J.Reid. It is assumed that an element +* v[i,j] can be selected as a pivot candidate if it is not very small +* (in magnitude) among other elements in the same row, i.e. if it +* satisfies to the stability condition |v[i,j]| >= tol * max|v[i,*]|, +* where 0 < tol < 1 is a given tolerance. +* +* In order to keep sparsity of the matrix V the routine uses Markowitz +* strategy, trying to choose such element v[p,q], which satisfies to +* the stability condition (see above) and has smallest Markowitz cost +* (nr[p]-1) * (nc[q]-1), where nr[p] and nc[q] are, resp., numbers of +* non-zeros in p-th row and q-th column of the active submatrix. +* +* In order to reduce the search, i.e. not to walk through all elements +* of the active submatrix, the routine uses a technique proposed by +* I.Duff. This technique is based on using the sets R[len] and C[len] +* of active rows and columns. +* +* If the pivot element v[p,q] has been chosen, the routine stores its +* indices to locations *p and *q and returns zero. Otherwise, non-zero +* is returned. */ + +int sgf_choose_pivot(SGF *sgf, int *p_, int *q_) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *rs_head = sgf->rs_head; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + double piv_tol = sgf->piv_tol; + int piv_lim = sgf->piv_lim; + int suhl = sgf->suhl; + int i, i_ptr, i_end, j, j_ptr, j_end, len, min_i, min_j, min_len, + ncand, next_j, p, q; + double best, big, cost, temp; + /* no pivot candidate has been chosen so far */ + p = q = 0, best = DBL_MAX, ncand = 0; + /* if the active submatrix contains a column having the only + * non-zero element (column singleton), choose it as the pivot */ + j = cs_head[1]; + if (j != 0) + { xassert(vc_len[j] == 1); + p = sv_ind[vc_ptr[j]], q = j; + goto done; + } + /* if the active submatrix contains a row having the only + * non-zero element (row singleton), choose it as the pivot */ + i = rs_head[1]; + if (i != 0) + { xassert(vr_len[i] == 1); + p = i, q = sv_ind[vr_ptr[i]]; + goto done; + } + /* the active submatrix contains no singletons; walk thru its + * other non-empty rows and columns */ + for (len = 2; len <= n; len++) + { /* consider active columns containing len non-zeros */ + for (j = cs_head[len]; j != 0; j = next_j) + { /* save the number of next column of the same length */ + next_j = cs_next[j]; + /* find an element in j-th column, which is placed in the + * row with minimal number of non-zeros and satisfies to + * the stability condition (such element may not exist) */ + min_i = min_j = 0, min_len = INT_MAX; + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + j_ptr < j_end; j_ptr++) + { /* get row index of v[i,j] */ + i = sv_ind[j_ptr]; + /* if i-th row is not shorter, skip v[i,j] */ + if (vr_len[i] >= min_len) + continue; + /* big := max|v[i,*]| */ + if ((big = vr_max[i]) < 0.0) + { /* largest magnitude is unknown; compute it */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (big < temp) + big = temp; + } + xassert(big > 0.0); + vr_max[i] = big; + } + /* find v[i,j] in i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != j; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ + if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (temp < piv_tol * big) + continue; + /* v[i,j] is a better candidate */ + min_i = i, min_j = j, min_len = vr_len[i]; + /* if Markowitz cost of v[i,j] is not greater than + * (len-1)**2, v[i,j] can be chosen as the pivot right + * now; this heuristic reduces the search and works well + * in many cases */ + if (min_len <= len) + { p = min_i, q = min_j; + goto done; + } + } + /* j-th column has been scanned */ + if (min_i != 0) + { /* element v[min_i,min_j] is a next pivot candidate */ + ncand++; + /* compute its Markowitz cost */ + cost = (double)(min_len - 1) * (double)(len - 1); + /* if this element is better, choose it as the pivot */ + if (cost < best) + p = min_i, q = min_j, best = cost; + /* if piv_lim candidates were considered, terminate + * the search, because it is doubtful that a much better + * candidate will be found */ + if (ncand == piv_lim) + goto done; + } + else if (suhl) + { /* j-th column has no eligible elements that satisfy to + * the stability criterion; Uwe Suhl suggests to exclude + * such column from further considerations until it + * becomes a column singleton; in hard cases this may + * significantly reduce the time needed to choose the + * pivot element */ + sgf_deactivate_col(j); + cs_prev[j] = cs_next[j] = j; + } + } + /* consider active rows containing len non-zeros */ + for (i = rs_head[len]; i != 0; i = rs_next[i]) + { /* big := max|v[i,*]| */ + if ((big = vr_max[i]) < 0.0) + { /* largest magnitude is unknown; compute it */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (big < temp) + big = temp; + } + xassert(big > 0.0); + vr_max[i] = big; + } + /* find an element in i-th row, which is placed in the + * column with minimal number of non-zeros and satisfies to + * the stability condition (such element always exists) */ + min_i = min_j = 0, min_len = INT_MAX; + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[i,j] */ + j = sv_ind[i_ptr]; + /* if j-th column is not shorter, skip v[i,j] */ + if (vc_len[j] >= min_len) + continue; + /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ + if ((temp = sv_val[i_ptr]) < 0.0) + temp = -temp; + if (temp < piv_tol * big) + continue; + /* v[i,j] is a better candidate */ + min_i = i, min_j = j, min_len = vc_len[j]; + /* if Markowitz cost of v[i,j] is not greater than + * (len-1)**2, v[i,j] can be chosen as the pivot right + * now; this heuristic reduces the search and works well + * in many cases */ + if (min_len <= len) + { p = min_i, q = min_j; + goto done; + } + } + /* i-th row has been scanned */ + if (min_i != 0) + { /* element v[min_i,min_j] is a next pivot candidate */ + ncand++; + /* compute its Markowitz cost */ + cost = (double)(len - 1) * (double)(min_len - 1); + /* if this element is better, choose it as the pivot */ + if (cost < best) + p = min_i, q = min_j, best = cost; + /* if piv_lim candidates were considered, terminate + * the search, because it is doubtful that a much better + * candidate will be found */ + if (ncand == piv_lim) + goto done; + } + else + { /* this can never be */ + xassert(min_i != min_i); + } + } + } +done: /* report the pivot to the factorization routine */ + *p_ = p, *q_ = q; + return (p == 0); +} + +/*********************************************************************** +* sgf_eliminate - perform gaussian elimination +* +* This routine performs elementary gaussian transformations in order +* to eliminate subdiagonal elements in k-th column of matrix +* U = P'* V * Q' using pivot element u[k,k], where k is the number of +* current elimination step, 1 <= k <= n. +* +* The parameters p and q specify, resp., row and column indices of the +* pivot element v[p,q] = u[k,k]. +* +* On entry the routine assumes that partially triangularized matrices +* L = P'* F * P and U = P'* V * Q' have the following structure: +* +* 1 k n 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x _ 1 . . . . . . . . # * * * * * +* x x x x _ . 1 . . . . . . . # * * * * * +* x x x x _ . . 1 . . . . . . # * * * * * +* x x x x _ . . . 1 . . . . . # * * * * * +* n x x x x _ . . . . 1 n . . . . # * * * * * +* +* matrix L matrix U +* +* where rows and columns k, k+1, ..., n of matrix U constitute the +* active submatrix. Elements to be eliminated are marked by '#', and +* other elements of the active submatrix are marked by '*'. May note +* that each eliminated non-zero element u[i,k] of matrix U gives +* corresponding non-zero element l[i,k] of matrix L (marked by '_'). +* +* Actually all operations are performed on matrix V. It is assumed +* that the row-wise representation corresponds to matrix V, but the +* column-wise representation corresponds to the active submatrix of +* matrix V (or, more precisely, to its pattern, because only row +* indices for columns of the active submatrix are used on this stage). +* +* Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal +* elements u[i',k] = v[i,q], i'= k+1, k+2, ..., n, the routine applies +* the following elementary gaussian transformations: +* +* (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), +* +* where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier stored to +* p-th column of matrix F to keep the main equality A = F * V +* (corresponding elements l[i',k] of matrix L are marked by '_' on the +* figure above). +* +* NOTE: On entry to the routine the working arrays flag and work +* should contain zeros. This status is retained by the routine +* on exit. */ + +int sgf_eliminate(SGF *sgf, int p, int q) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int *rs_head = sgf->rs_head; + int *rs_prev = sgf->rs_prev; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + char *flag = sgf->flag; + double *work = sgf->work; + double eps_tol = sgf->eps_tol; + int nnz_diff = 0; + int fill, i, i_ptr, i_end, j, j_ptr, j_end, ptr, len, loc, loc1; + double vpq, fip, vij; + xassert(1 <= p && p <= n); + xassert(1 <= q && q <= n); + /* remove p-th row from the active set; this row will never + * return there */ + sgf_deactivate_row(p); + /* process p-th (pivot) row */ + ptr = 0; + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[p,j] */ + j = sv_ind[i_ptr]; + if (j == q) + { /* save pointer to pivot v[p,q] */ + ptr = i_ptr; + } + else + { /* store v[p,j], j != q, to working array */ + flag[j] = 1; + work[j] = sv_val[i_ptr]; + } + /* remove j-th column from the active set; q-th column will + * never return there while other columns will return to the + * active set with new length */ + if (cs_next[j] == j) + { /* j-th column was marked by the pivoting routine according + * to Uwe Suhl's suggestion and is already inactive */ + xassert(cs_prev[j] == j); + } + else + sgf_deactivate_col(j); + nnz_diff -= vc_len[j]; + /* find and remove v[p,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != p; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + vc_len[j]--; + } + /* save pivot v[p,q] and remove it from p-th row */ + xassert(ptr > 0); + vpq = vr_piv[p] = sv_val[ptr]; + sv_ind[ptr] = sv_ind[i_end-1]; + sv_val[ptr] = sv_val[i_end-1]; + vr_len[p]--; + /* if it is not planned to update matrix V, relocate p-th row to + * the right (static) part of SVA */ + if (!sgf->updat) + { len = vr_len[p]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+p); + } + /* copy the pattern (row indices) of q-th column of the active + * submatrix (from which v[p,q] has been just removed) to p-th + * column of matrix F (without unity diagonal element) */ + len = vc_len[q]; + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, fc_ref-1+p, len); + memcpy(&sv_ind[fc_ptr[p]], &sv_ind[vc_ptr[q]], + len * sizeof(int)); + fc_len[p] = len; + } + /* make q-th column of the active submatrix empty */ + vc_len[q] = 0; + /* transform non-pivot rows of the active submatrix */ + for (loc = fc_len[p]-1; loc >= 0; loc--) + { /* get row index of v[i,q] = row index of f[i,p] */ + i = sv_ind[fc_ptr[p] + loc]; + xassert(i != p); /* v[p,q] was removed */ + /* remove i-th row from the active set; this row will return + * there with new length */ + sgf_deactivate_row(i); + /* find v[i,q] in i-th row */ + for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; + sv_ind[i_ptr] != q; i_ptr++) + /* nop */; + xassert(i_ptr < i_end); + /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] */ + fip = sv_val[fc_ptr[p] + loc] = sv_val[i_ptr] / vpq; + /* remove v[i,q] from i-th row */ + sv_ind[i_ptr] = sv_ind[i_end-1]; + sv_val[i_ptr] = sv_val[i_end-1]; + vr_len[i]--; + /* perform elementary gaussian transformation: + * (i-th row) := (i-th row) - f[i,p] * (p-th row) + * note that p-th row of V, which is in the working array, + * doesn't contain pivot v[p,q], and i-th row of V doesn't + * contain v[i,q] to be eliminated */ + /* walk thru i-th row and transform existing elements */ + fill = vr_len[p]; + for (i_end = (i_ptr = ptr = vr_ptr[i]) + vr_len[i]; + i_ptr < i_end; i_ptr++) + { /* get column index and value of v[i,j] */ + j = sv_ind[i_ptr]; + vij = sv_val[i_ptr]; + if (flag[j]) + { /* v[p,j] != 0 */ + flag[j] = 0, fill--; + /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ + vij -= fip * work[j]; + if (-eps_tol < vij && vij < +eps_tol) + { /* new v[i,j] is close to zero; remove it from the + * active submatrix, i.e. replace it by exact zero */ + /* find and remove v[i,j] from j-th column */ + for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; + sv_ind[j_ptr] != i; j_ptr++) + /* nop */; + xassert(j_ptr < j_end); + sv_ind[j_ptr] = sv_ind[j_end-1]; + vc_len[j]--; + continue; + } + } + /* keep new v[i,j] in i-th row */ + sv_ind[ptr] = j; + sv_val[ptr] = vij; + ptr++; + } + /* (new length of i-th row may decrease because of numerical + * cancellation) */ + vr_len[i] = len = ptr - vr_ptr[i]; + /* now flag[*] is the pattern of the set v[p,*] \ v[i,*], and + * fill is the number of non-zeros in this set */ + if (fill == 0) + { /* no fill-in occurs */ + /* walk thru p-th row and restore the column flags */ + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + flag[sv_ind[i_ptr]] = 1; /* v[p,j] != 0 */ + goto skip; + } + /* up to fill new non-zero elements may appear in i-th row due + * to fill-in; reserve locations for these elements (note that + * actual length of i-th row is currently stored in len) */ + if (vr_cap[i] < len + fill) + { if (sva->r_ptr - sva->m_ptr < len + fill) + { sva_more_space(sva, len + fill); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vr_ref-1+i, len + fill, 0); + } + vr_len[i] += fill; + /* walk thru p-th row and add new elements to i-th row */ + for (loc1 = vr_len[p]-1; loc1 >= 0; loc1--) + { /* get column index of v[p,j] */ + j = sv_ind[vr_ptr[p] + loc1]; + if (!flag[j]) + { /* restore j-th column flag */ + flag[j] = 1; + /* v[i,j] was computed earlier on transforming existing + * elements of i-th row */ + continue; + } + /* v[i,j] := 0 - f[i,p] * v[p,j] */ + vij = - fip * work[j]; + if (-eps_tol < vij && vij < +eps_tol) + { /* new v[i,j] is close to zero; do not add it to the + * active submatrix, i.e. replace it by exact zero */ + continue; + } + /* add new v[i,j] to i-th row */ + sv_ind[ptr = vr_ptr[i] + (len++)] = j; + sv_val[ptr] = vij; + /* add new v[i,j] to j-th column */ + if (vc_cap[j] == vc_len[j]) + { /* we reserve extra locations in j-th column to reduce + * further relocations of that column */ +#if 1 /* FIXME */ + /* use control parameter to specify the number of extra + * locations reserved */ + int need = vc_len[j] + 10; +#endif + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, need, 1); + } + sv_ind[vc_ptr[j] + (vc_len[j]++)] = i; + } + /* set final length of i-th row just transformed */ + xassert(len <= vr_len[i]); + vr_len[i] = len; +skip: /* return i-th row to the active set with new length */ + sgf_activate_row(i); + /* since i-th row has been changed, largest magnitude of its + * elements becomes unknown */ + vr_max[i] = -1.0; + } + /* walk thru p-th (pivot) row */ + for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; + i_ptr < i_end; i_ptr++) + { /* get column index of v[p,j] */ + j = sv_ind[i_ptr]; + xassert(j != q); /* v[p,q] was removed */ + /* return j-th column to the active set with new length */ + if (cs_next[j] == j && vc_len[j] != 1) + { /* j-th column was marked by the pivoting routine and it is + * still not a column singleton, so leave it incative */ + xassert(cs_prev[j] == j); + } + else + sgf_activate_col(j); + nnz_diff += vc_len[j]; + /* restore zero content of the working arrays */ + flag[j] = 0; + work[j] = 0.0; + } + /* return the difference between the numbers of non-zeros in the + * active submatrix on entry and on exit, resp. */ + return nnz_diff; +} + +/*********************************************************************** +* sgf_dense_lu - compute dense LU-factorization with full pivoting +* +* This routine performs Gaussian elimination with full pivoting to +* compute dense LU-factorization of the specified matrix A of order n +* in the form: +* +* A = P * L * U * Q, (1) +* +* where L is lower triangular matrix with unit diagonal, U is upper +* triangular matrix, P and Q are permutation matrices. +* +* On entry to the routine elements of matrix A = (a[i,j]) should be +* placed in the array elements a[0], ..., a[n^2-1] in dense row-wise +* format. On exit from the routine matrix A is replaced by factors L +* and U as follows: +* +* u[1,1] u[1,2] ... u[1,n-1] u[1,n] +* l[2,1] u[2,2] ... u[2,n-1] u[2,n] +* . . . . . . . . . . . . . . +* l[n-1,1] l[n-1,2] u[n-1,n-1] u[n-1,n] +* l[n,1] l[n,2] ... l[n,n-1] u[n,n] +* +* The unit diagonal elements of L are not stored. +* +* Information on permutations of rows and columns of active submatrix +* during factorization is accumulated by the routine as follows. Every +* time the routine permutes rows i and i' or columns j and j', it also +* permutes elements r[i-1] and r[i'-1] or c[j-1] and c[j'-1], resp. +* Thus, on entry to the routine elements r[0], r[1], ..., r[n-1] and +* c[0], c[1], ..., c[n-1] should be initialized by some integers that +* identify rows and columns of the original matrix A. +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k, in which case a partial factorization is stored in the +* array a. */ + +int sgf_dense_lu(int n, double a_[], int r[], int c[], double eps) +{ /* non-optimized version */ + int i, j, k, p, q, ref; + double akk, big, temp; +# define a(i,j) a_[(i)*n+(j)] + /* initially U = A, L = P = Q = I */ + /* main elimination loop */ + for (k = 0; k < n; k++) + { /* choose pivot u[p,q], k <= p, q <= n */ + p = q = -1, big = eps; + for (i = k; i < n; i++) + { for (j = k; j < n; j++) + { /* temp = |u[i,j]| */ + if ((temp = a(i,j)) < 0.0) + temp = -temp; + if (big < temp) + p = i, q = j, big = temp; + } + } + if (p < 0) + { /* k-th elimination step failed */ + return k+1; + } + /* permute rows k and p */ + if (k != p) + { for (j = 0; j < n; j++) + temp = a(k,j), a(k,j) = a(p,j), a(p,j) = temp; + ref = r[k], r[k] = r[p], r[p] = ref; + } + /* permute columns k and q */ + if (k != q) + { for (i = 0; i < n; i++) + temp = a(i,k), a(i,k) = a(i,q), a(i,q) = temp; + ref = c[k], c[k] = c[q], c[q] = ref; + } + /* now pivot is in position u[k,k] */ + akk = a(k,k); + /* eliminate subdiagonal elements u[k+1,k], ..., u[n,k] */ + for (i = k+1; i < n; i++) + { if (a(i,k) != 0.0) + { /* gaussian multiplier l[i,k] := u[i,k] / u[k,k] */ + temp = (a(i,k) /= akk); + /* (i-th row) := (i-th row) - l[i,k] * (k-th row) */ + for (j = k+1; j < n; j++) + a(i,j) -= temp * a(k,j); + } + } + } +# undef a + return 0; +} + +/*********************************************************************** +* sgf_dense_phase - compute LU-factorization (dense phase) +* +* This routine performs dense phase of computing LU-factorization. +* +* The aim is two-fold. First, the main factorization routine switches +* to dense phase when the active submatrix is relatively dense, so +* using dense format allows significantly reduces overheads needed to +* maintain sparse data structures. And second, that is more important, +* on dense phase full pivoting is used (rather than partial pivoting) +* that allows improving numerical stability, since round-off errors +* tend to increase on last steps of the elimination process. +* +* On entry the routine assumes that elimination steps 1, 2, ..., k-1 +* have been performed, so partially transformed matrices L = P'* F * P +* and U = P'* V * Q' have the following structure: +* +* 1 k n 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x . 1 . . . . . . . . * * * * * * +* x x x x . . 1 . . . . . . . * * * * * * +* x x x x . . . 1 . . . . . . * * * * * * +* x x x x . . . . 1 . . . . . * * * * * * +* n x x x x . . . . . 1 n . . . . * * * * * * +* +* matrix L matrix U +* +* where rows and columns k, k+1, ..., n of matrix U constitute the +* active submatrix A~, whose elements are marked by '*'. +* +* The routine copies the active submatrix A~ to a working array in +* dense format, compute dense factorization A~ = P~* L~* U~* Q~ using +* full pivoting, and then copies non-zero elements of factors L~ and +* U~ back to factors L and U (more precisely, to factors F and V). +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k (information on linearly dependent rows/columns in this +* case is provided by matrices P and Q). */ + +int sgf_dense_phase(LUF *luf, int k, int updat) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int fc_ref = luf->fc_ref; + int *fc_ptr = &sva->ptr[fc_ref-1]; + int *fc_len = &sva->len[fc_ref-1]; + int *fc_cap = &sva->cap[fc_ref-1]; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *vr_cap = &sva->cap[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_inv = luf->pp_inv; + int *pp_ind = luf->pp_ind; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int a_end, a_ptr, end, i, ia, ii, j, ja, jj, ka, len, na, ne, + need, ptr; + double *a_; + xassert(1 <= k && k <= n); + /* active columns of V are not longer needed; make them empty */ + for (jj = k; jj <= n; jj++) + { /* jj is number of active column of U = P'* V * Q' */ + vc_len[qq_ind[jj]] = 0; + } + /* determine order of active submatrix A~ of matrix U */ + na = n - k + 1; + xassert(1 <= na && na <= n); + /* determine number of elements in dense triangular factor (L~ or + * U~), except diagonal elements */ + ne = na * (na - 1) / 2; + /* we allocate active submatrix A~ in free (middle) part of SVA; + * to avoid defragmentation that could destroy A~ we also should + * reserve ne locations to build rows of V from rows of U~ and ne + * locations to build columns of F from columns of L~ */ + need = na * na + ne + ne; + if (sva->r_ptr - sva->m_ptr < need) + { sva_more_space(sva, need); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* free (middle) part of SVA is structured as follows: + * end of left (dynamic) part + * ne free locations for new rows of V + * na free locations for active submatrix A~ + * unused locations, if any + * ne free locations for new columns of F + * beginning of right (static) part */ + a_ptr = sva->m_ptr + ne; + a_end = a_ptr + na * na; + /* copy active submatrix A~ from matrix V to working array in + * dense row-wise format */ + a_ = &sva->val[a_ptr]; +# define a(ia, ja) a_[((ia) - 1) * na + ((ja) - 1)] + for (ia = 1; ia <= na; ia++) + { /* clear ia-th row of A~ */ + for (ja = 1; ja <= na; ja++) + a(ia, ja) = 0.0; + /* ia-th row of A~ = (k-1+ia)-th row of U = i-th row of V */ + i = pp_inv[k-1+ia]; + ptr = vr_ptr[i]; + end = ptr + vr_len[i]; + for (; ptr < end; ptr++) + a(ia, qq_inv[sv_ind[ptr]]-k+1) = sv_val[ptr]; + /* i-th row of V is no longer needed; make it empty */ + vr_len[i] = 0; + } + /* compute dense factorization A~ = P~* L~* U~* Q~ */ +#if 1 /* FIXME: epsilon tolerance */ + ka = sgf_dense_lu(na, &a(1, 1), &pp_inv[k], &qq_ind[k], 1e-20); +#endif + /* rows of U with numbers pp_inv[k, k+1, ..., n] were permuted + * due to row permutations of A~; update matrix P using P~ */ + for (ii = k; ii <= n; ii++) + pp_ind[pp_inv[ii]] = ii; + /* columns of U with numbers qq_ind[k, k+1, ..., n] were permuted + * due to column permutations of A~; update matrix Q using Q~ */ + for (jj = k; jj <= n; jj++) + qq_inv[qq_ind[jj]] = jj; + /* check if dense factorization is complete */ + if (ka != 0) + { /* A~ is singular to working precision */ + /* information on linearly dependent rows/columns is provided + * by matrices P and Q */ + xassert(1 <= ka && ka <= na); + return k - 1 + ka; + } + /* build new rows of V from rows of U~ */ + for (ia = 1; ia <= na; ia++) + { /* ia-th row of U~ = (k-1+ia)-th row of U = i-th row of V */ + i = pp_inv[k-1+ia]; + xassert(vr_len[i] == 0); + /* store diagonal element u~[ia,ia] */ + vr_piv[i] = a(ia, ia); + /* determine number of non-zero non-diagonal elements in ia-th + * row of U~ */ + len = 0; + for (ja = ia+1; ja <= na; ja++) + { if (a(ia, ja) != 0.0) + len++; + } + /* reserve len locations for i-th row of matrix V in left + * (dynamic) part of SVA */ + if (vr_cap[i] < len) + { /* there should be enough room in free part of SVA */ + xassert(sva->r_ptr - sva->m_ptr >= len); + sva_enlarge_cap(sva, vr_ref-1+i, len, 0); + /* left part of SVA should not overlap matrix A~ */ + xassert(sva->m_ptr <= a_ptr); + } + /* copy non-zero non-diaginal elements of ia-th row of U~ to + * i-th row of V */ + ptr = vr_ptr[i]; + for (ja = ia+1; ja <= na; ja++) + { if (a(ia, ja) != 0.0) + { sv_ind[ptr] = qq_ind[k-1+ja]; + sv_val[ptr] = a(ia, ja); + ptr++; + } + } + xassert(ptr - vr_ptr[i] == len); + vr_len[i] = len; + } + /* build new columns of F from columns of L~ */ + for (ja = 1; ja <= na; ja++) + { /* ja-th column of L~ = (k-1+ja)-th column of L = j-th column + * of F */ + j = pp_inv[k-1+ja]; + xassert(fc_len[j] == 0); + xassert(fc_cap[j] == 0); + /* determine number of non-zero non-diagonal elements in ja-th + * column of L~ */ + len = 0; + for (ia = ja+1; ia <= na; ia++) + { if (a(ia, ja) != 0.0) + len++; + } + /* reserve len locations for j-th column of matrix F in right + * (static) part of SVA */ + /* there should be enough room in free part of SVA */ + xassert(sva->r_ptr - sva->m_ptr >= len); + if (len > 0) + sva_reserve_cap(sva, fc_ref-1+j, len); + /* right part of SVA should not overlap matrix A~ */ + xassert(a_end <= sva->r_ptr); + /* copy non-zero non-diagonal elements of ja-th column of L~ + * to j-th column of F */ + ptr = fc_ptr[j]; + for (ia = ja+1; ia <= na; ia++) + { if (a(ia, ja) != 0.0) + { sv_ind[ptr] = pp_inv[k-1+ia]; + sv_val[ptr] = a(ia, ja); + ptr++; + } + } + xassert(ptr - fc_ptr[j] == len); + fc_len[j] = len; + } + /* factors L~ and U~ are no longer needed */ +# undef a + /* if it is not planned to update matrix V, relocate all its new + * rows to the right (static) part of SVA */ + if (!updat) + { for (ia = 1; ia <= na; ia++) + { i = pp_inv[k-1+ia]; + len = vr_len[i]; + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_make_static(sva, vr_ref-1+i); + } + } + return 0; +} + +/*********************************************************************** +* sgf_factorize - compute LU-factorization (main routine) +* +* This routine computes sparse LU-factorization of specified matrix A +* using Gaussian elimination. +* +* On entry to the routine matrix V = A should be stored in column-wise +* format. +* +* If the factorization has been successfully computed, the routine +* returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, +* all elements of the active submatrix are close to zero, the routine +* returns k (information on linearly dependent rows/columns in this +* case is provided by matrices P and Q). */ + +#if 1 /* 21/II-2016 */ +/* If the matrix A is structurally singular, the routine returns -1. +* NOTE: This case can be detected only if the singl flag is set. */ +#endif + +int sgf_factorize(SGF *sgf, int singl) +{ LUF *luf = sgf->luf; + int n = luf->n; + SVA *sva = luf->sva; + int vr_ref = luf->vr_ref; + int *vr_len = &sva->len[vr_ref-1]; + double *vr_piv = luf->vr_piv; + int vc_ref = luf->vc_ref; + int *vc_len = &sva->len[vc_ref-1]; + int *pp_ind = luf->pp_ind; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int *qq_inv = luf->qq_inv; + int *rs_head = sgf->rs_head; + int *rs_prev = sgf->rs_prev; + int *rs_next = sgf->rs_next; + int *cs_head = sgf->cs_head; + int *cs_prev = sgf->cs_prev; + int *cs_next = sgf->cs_next; + double *vr_max = sgf->vr_max; + char *flag = sgf->flag; + double *work = sgf->work; + int i, j, k, k1, k2, p, q, nnz; + /* build matrix V = A in row-wise format */ + luf_build_v_rows(luf, rs_prev); + /* P := Q := I, so V = U = A, F = L = I */ + for (k = 1; k <= n; k++) + { vr_piv[k] = 0.0; + pp_ind[k] = pp_inv[k] = qq_ind[k] = qq_inv[k] = k; + } +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, 1); +#endif + /* perform singleton phase, if required */ + if (!singl) + { /* assume that nucleus is entire matrix U */ + k2 = 1; + } + else + { /* minimize nucleus size */ +#if 0 /* 21/II-2016 */ + sgf_reduce_nuc(luf, &k1, &k2, rs_prev, rs_next); +#else + if (sgf_reduce_nuc(luf, &k1, &k2, rs_prev, rs_next)) + return -1; +#endif +#ifdef GLP_DEBUG + xprintf("n = %d; k1 = %d; k2 = %d\n", n, k1, k2); +#endif + /* perform singleton phase */ + k2 = sgf_singl_phase(luf, k1, k2, sgf->updat, rs_prev, work); + } +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, k2); +#endif + /* initialize working arrays */ + rs_head[0] = cs_head[0] = 0; + for (k = 1; k <= n; k++) + { rs_head[k] = cs_head[k] = 0; + vr_max[k] = -1.0; + flag[k] = 0; + work[k] = 0.0; + } + /* build lists of active rows and columns of matrix V; determine + * number of non-zeros in initial active submatrix */ + nnz = 0; + for (k = k2; k <= n; k++) + { i = pp_inv[k]; + sgf_activate_row(i); + nnz += vr_len[i]; + j = qq_ind[k]; + sgf_activate_col(j); + } + /* main factorization loop */ + for (k = k2; k <= n; k++) + { int na; + double den; + /* calculate density of active submatrix */ + na = n - k + 1; /* order of active submatrix */ +#if 0 /* 21/VIII-2014 */ + den = (double)nnz / (double)(na * na); +#else + den = (double)nnz / ((double)(na) * (double)(na)); +#endif + /* if active submatrix is relatively dense, switch to dense + * phase */ +#if 1 /* FIXME */ + if (na >= 5 && den >= 0.71) + { +#ifdef GLP_DEBUG + xprintf("na = %d; nnz = %d; den = %g\n", na, nnz, den); +#endif + break; + } +#endif + /* choose pivot v[p,q] */ + if (sgf_choose_pivot(sgf, &p, &q) != 0) + return k; /* failure */ + /* u[i,j] = v[p,q], k <= i, j <= n */ + i = pp_ind[p]; + xassert(k <= i && i <= n); + j = qq_inv[q]; + xassert(k <= j && j <= n); + /* move u[i,j] to position u[k,k] by implicit permutations of + * rows and columns of matrix U */ + luf_swap_u_rows(k, i); + luf_swap_u_cols(k, j); + /* perform gaussian elimination */ + nnz += sgf_eliminate(sgf, p, q); + } +#if 1 /* FIXME */ + if (k <= n) + { /* continue computing factorization in dense mode */ +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, k); +#endif + k = sgf_dense_phase(luf, k, sgf->updat); + if (k != 0) + return k; /* failure */ + } +#endif +#ifdef GLP_DEBUG + sva_check_area(sva); + luf_check_all(luf, n+1); +#endif + /* defragment SVA; currently all columns of V are empty, so they + * will have zero capacity as required by luf_build_v_cols */ + sva_defrag_area(sva); + /* build matrix F in row-wise format */ + luf_build_f_rows(luf, rs_head); + /* build matrix V in column-wise format */ + luf_build_v_cols(luf, sgf->updat, rs_head); + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.h new file mode 100644 index 000000000..4f744610e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sgf.h @@ -0,0 +1,203 @@ +/* sgf.h (sparse Gaussian factorizer) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SGF_H +#define SGF_H + +#include "luf.h" + +typedef struct SGF SGF; + +struct SGF +{ /* sparse Gaussian factorizer workspace */ + LUF *luf; + /* LU-factorization being computed */ + /*--------------------------------------------------------------*/ + /* to efficiently choose pivot elements according to Markowitz + * strategy, the search technique proposed by Iain Duff is used; + * it is based on using two families of sets {R[0], ..., R[n]} + * and {C[0], ..., C[n]}, where R[k] and C[k], 0 <= k <= n, are, + * respectively, sets of rows and columns of the active submatrix + * of matrix V having k non-zeros (i.e. whose length is k); each + * set R[k] and C[k] is implemented as a doubly linked list */ + int *rs_head; /* int rs_head[1+n]; */ + /* rs_head[k], 0 <= k <= n, is the number of first row, which + * has k non-zeros in the active submatrix */ + int *rs_prev; /* int rs_prev[1+n]; */ + /* rs_prev[0] is not used; + * rs_prev[i], 1 <= i <= n, is the number of previous row, which + * has the same number of non-zeros as i-th row; + * rs_prev[i] < 0 means that i-th row is inactive */ + int *rs_next; /* int rs_next[1+n]; */ + /* rs_next[0] is not used; + * rs_next[i], 1 <= i <= n, is the number of next row, which has + * the same number of non-zeros as i-th row; + * rs_next[i] < 0 means that i-th row is inactive */ + int *cs_head; /* int cs_head[1+n]; */ + /* cs_head[k], 0 <= k <= n, is the number of first column, which + * has k non-zeros in the active submatrix */ + int *cs_prev; /* int cs_prev[1+n]; */ + /* cs_prev[0] is not used; + * cs_prev[j], 1 <= j <= n, is the number of previous column, + * which has the same number of non-zeros as j-th column; + * cs_prev[j] < 0 means that j-th column is inactive */ + int *cs_next; /* int cs_next[1+n]; */ + /* cs_next[0] is not used; + * cs_next[j], 1 <= j <= n, is the number of next column, which + * has the same number of non-zeros as j-th column; + * cs_next[j] < 0 means that j-th column is inactive */ + /* NOTE: cs_prev[j] = cs_next[j] = j means that j-th column was + * temporarily removed from corresponding set C[k] by the + * pivoting routine according to Uwe Suhl's heuristic */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *vr_max; /* int vr_max[1+n]; */ + /* vr_max[0] is not used; + * vr_max[i], 1 <= i <= n, is used only if i-th row of matrix V + * is active (i.e. belongs to the active submatrix), and is the + * largest magnitude of elements in that row; if vr_max[i] < 0, + * the largest magnitude is unknown yet */ + char *flag; /* char flag[1+n]; */ + /* boolean working array */ + double *work; /* double work[1+n]; */ + /* floating-point working array */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int updat; + /* if this flag is set, the matrix V is assumed to be updatable; + * in this case factorized (non-active) part of V is stored in + * the left part of SVA rather than in its right part */ + double piv_tol; + /* threshold pivoting tolerance, 0 < piv_tol < 1; element v[i,j] + * of the active submatrix fits to be pivot if it satisfies to + * the stability criterion |v[i,j]| >= piv_tol * max |v[i,*]|, + * i.e. if it is not very small in the magnitude among other + * elements in the same row; decreasing this parameter gives + * better sparsity at the expense of numerical accuracy and vice + * versa */ + int piv_lim; + /* maximal allowable number of pivot candidates to be considered; + * if piv_lim pivot candidates have been considered, the pivoting + * routine terminates the search with the best candidate found */ + int suhl; + /* if this flag is set, the pivoting routine applies a heuristic + * proposed by Uwe Suhl: if a column of the active submatrix has + * no eligible pivot candidates (i.e. all its elements do not + * satisfy to the stability criterion), the routine excludes it + * from futher consideration until it becomes column singleton; + * in many cases this allows reducing the time needed to choose + * the pivot */ + double eps_tol; + /* epsilon tolerance; each element of the active submatrix, whose + * magnitude is less than eps_tol, is replaced by exact zero */ +#if 0 /* FIXME */ + double den_lim; + /* density limit; if the density of the active submatrix reaches + * this limit, the factorization routine switches from sparse to + * dense mode */ +#endif +}; + +#define sgf_activate_row(i) \ + do \ + { int len = vr_len[i]; \ + rs_prev[i] = 0; \ + rs_next[i] = rs_head[len]; \ + if (rs_next[i] != 0) \ + rs_prev[rs_next[i]] = i; \ + rs_head[len] = i; \ + } while (0) +/* include i-th row of matrix V in active set R[len] */ + +#define sgf_deactivate_row(i) \ + do \ + { if (rs_prev[i] == 0) \ + rs_head[vr_len[i]] = rs_next[i]; \ + else \ + rs_next[rs_prev[i]] = rs_next[i]; \ + if (rs_next[i] == 0) \ + ; \ + else \ + rs_prev[rs_next[i]] = rs_prev[i]; \ + rs_prev[i] = rs_next[i] = -1; \ + } while (0) +/* remove i-th row of matrix V from active set R[len] */ + +#define sgf_activate_col(j) \ + do \ + { int len = vc_len[j]; \ + cs_prev[j] = 0; \ + cs_next[j] = cs_head[len]; \ + if (cs_next[j] != 0) \ + cs_prev[cs_next[j]] = j; \ + cs_head[len] = j; \ + } while (0) +/* include j-th column of matrix V in active set C[len] */ + +#define sgf_deactivate_col(j) \ + do \ + { if (cs_prev[j] == 0) \ + cs_head[vc_len[j]] = cs_next[j]; \ + else \ + cs_next[cs_prev[j]] = cs_next[j]; \ + if (cs_next[j] == 0) \ + ; \ + else \ + cs_prev[cs_next[j]] = cs_prev[j]; \ + cs_prev[j] = cs_next[j] = -1; \ + } while (0) +/* remove j-th column of matrix V from active set C[len] */ + +#define sgf_reduce_nuc _glp_sgf_reduce_nuc +int sgf_reduce_nuc(LUF *luf, int *k1, int *k2, int cnt[/*1+n*/], + int list[/*1+n*/]); +/* initial reordering to minimize nucleus size */ + +#define sgf_singl_phase _glp_sgf_singl_phase +int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, + int ind[/*1+n*/], double val[/*1+n*/]); +/* compute LU-factorization (singleton phase) */ + +#define sgf_choose_pivot _glp_sgf_choose_pivot +int sgf_choose_pivot(SGF *sgf, int *p, int *q); +/* choose pivot element v[p,q] */ + +#define sgf_eliminate _glp_sgf_eliminate +int sgf_eliminate(SGF *sgf, int p, int q); +/* perform gaussian elimination */ + +#define sgf_dense_lu _glp_sgf_dense_lu +int sgf_dense_lu(int n, double a[], int r[], int c[], double eps); +/* compute dense LU-factorization with full pivoting */ + +#define sgf_dense_phase _glp_sgf_dense_phase +int sgf_dense_phase(LUF *luf, int k, int updat); +/* compute LU-factorization (dense phase) */ + +#define sgf_factorize _glp_sgf_factorize +int sgf_factorize(SGF *sgf, int singl); +/* compute LU-factorization (main routine) */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.c b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.c new file mode 100644 index 000000000..e6a675ccb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.c @@ -0,0 +1,572 @@ +/* sva.c (sparse vector area) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "sva.h" + +/*********************************************************************** +* sva_create_area - create sparse vector area (SVA) +* +* This routine creates the sparse vector area (SVA), which initially +* is empty. +* +* The parameter n_max specifies the initial number of vectors that can +* be allocated in the SVA, n_max > 0. +* +* The parameter size specifies the initial number of free locations in +* the SVA, size > 0. +* +* On exit the routine returns a pointer to the SVA created. */ + +SVA *sva_create_area(int n_max, int size) +{ SVA *sva; + xassert(0 < n_max && n_max < INT_MAX); + xassert(0 < size && size < INT_MAX); + sva = talloc(1, SVA); + sva->n_max = n_max; + sva->n = 0; + sva->ptr = talloc(1+n_max, int); + sva->len = talloc(1+n_max, int); + sva->cap = talloc(1+n_max, int); + sva->size = size; + sva->m_ptr = 1; + sva->r_ptr = size+1; + sva->head = sva->tail = 0; + sva->prev = talloc(1+n_max, int); + sva->next = talloc(1+n_max, int); + sva->ind = talloc(1+size, int); + sva->val = talloc(1+size, double); + sva->talky = 0; + return sva; +} + +/*********************************************************************** +* sva_alloc_vecs - allocate new vectors in SVA +* +* This routine allocates nnn new empty vectors, nnn > 0, in the sparse +* vector area (SVA). +* +* The new vectors are assigned reference numbers k, k+1, ..., k+nnn-1, +* where k is a reference number assigned to the very first new vector, +* which is returned by the routine on exit. */ + +int sva_alloc_vecs(SVA *sva, int nnn) +{ int n = sva->n; + int n_max = sva->n_max; + int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int k, new_n; +#if 1 + if (sva->talky) + xprintf("sva_alloc_vecs: nnn = %d\n", nnn); +#endif + xassert(nnn > 0); + /* determine new number of vectors in SVA */ + new_n = n + nnn; + xassert(new_n > n); + if (n_max < new_n) + { /* enlarge the SVA arrays */ + while (n_max < new_n) + { n_max += n_max; + xassert(n_max > 0); + } + sva->n_max = n_max; + sva->ptr = ptr = trealloc(ptr, 1+n_max, int); + sva->len = len = trealloc(len, 1+n_max, int); + sva->cap = cap = trealloc(cap, 1+n_max, int); + sva->prev = prev = trealloc(prev, 1+n_max, int); + sva->next = next = trealloc(next, 1+n_max, int); + } + /* initialize new vectors */ + sva->n = new_n; + for (k = n+1; k <= new_n; k++) + { ptr[k] = len[k] = cap[k] = 0; + prev[k] = next[k] = -1; + } +#if 1 + if (sva->talky) + xprintf("now sva->n_max = %d, sva->n = %d\n", + sva->n_max, sva->n); +#endif + /* return reference number of very first new vector */ + return n+1; +} + +/*********************************************************************** +* sva_resize_area - change size of SVA storage +* +* This routine increases or decrases the size of the SVA storage by +* reallocating it. +* +* The parameter delta specifies the number of location by which the +* current size of the SVA storage should be increased (if delta > 0) +* or decreased (if delta < 0). Note that if delta is negative, it +* should not be less than the current size of the middle part. +* +* As a result of this operation the size of the middle part of SVA is +* increased/decreased by delta locations. +* +* NOTE: This operation changes ptr[k] for all vectors stored in the +* right part of SVA. */ + +void sva_resize_area(SVA *sva, int delta) +{ int n = sva->n; + int *ptr = sva->ptr; + int size = sva->size; + int m_ptr = sva->m_ptr; + int r_ptr = sva->r_ptr; + int k, r_size; +#if 1 + if (sva->talky) + xprintf("sva_resize_area: delta = %d\n", delta); +#endif + xassert(delta != 0); + /* determine size of the right part, in locations */ + r_size = size - r_ptr + 1; + /* relocate the right part in case of negative delta */ + if (delta < 0) + { xassert(delta >= m_ptr - r_ptr); + sva->r_ptr += delta; + memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], + r_size * sizeof(int)); + memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], + r_size * sizeof(double)); + } + /* reallocate the storage arrays */ + xassert(delta < INT_MAX - sva->size); + sva->size += delta; + sva->ind = trealloc(sva->ind, 1+sva->size, int); + sva->val = trealloc(sva->val, 1+sva->size, double); + /* relocate the right part in case of positive delta */ + if (delta > 0) + { sva->r_ptr += delta; + memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], + r_size * sizeof(int)); + memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], + r_size * sizeof(double)); + } + /* update pointers to vectors stored in the right part */ + for (k = 1; k <= n; k++) + { if (ptr[k] >= r_ptr) + ptr[k] += delta; + } +#if 1 + if (sva->talky) + xprintf("now sva->size = %d\n", sva->size); +#endif + return; +} + +/*********************************************************************** +* sva_defrag_area - defragment left part of SVA +* +* This routine performs "garbage" collection to defragment the left +* part of SVA. +* +* NOTE: This operation may change ptr[k] and cap[k] for all vectors +* stored in the left part of SVA. */ + +void sva_defrag_area(SVA *sva) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + int k, next_k, ptr_k, len_k, m_ptr, head, tail; +#if 1 + if (sva->talky) + { xprintf("sva_defrag_area:\n"); + xprintf("before defragmenting = %d %d %d\n", sva->m_ptr - 1, + sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); + } +#endif + m_ptr = 1; + head = tail = 0; + /* walk through the linked list of vectors stored in the left + * part of SVA */ + for (k = sva->head; k != 0; k = next_k) + { /* save number of next vector in the list */ + next_k = next[k]; + /* determine length of k-th vector */ + len_k = len[k]; + if (len_k == 0) + { /* k-th vector is empty; remove it from the left part */ + ptr[k] = cap[k] = 0; + prev[k] = next[k] = -1; + } + else + { /* determine pointer to first location of k-th vector */ + ptr_k = ptr[k]; + xassert(m_ptr <= ptr_k); + /* relocate k-th vector to the beginning of the left part, + * if necessary */ + if (m_ptr < ptr_k) + { memmove(&ind[m_ptr], &ind[ptr_k], + len_k * sizeof(int)); + memmove(&val[m_ptr], &val[ptr_k], + len_k * sizeof(double)); + ptr[k] = m_ptr; + } + /* remove unused locations from k-th vector */ + cap[k] = len_k; + /* the left part of SVA has been enlarged */ + m_ptr += len_k; + /* add k-th vector to the end of the new linked list */ + prev[k] = tail; + next[k] = 0; + if (head == 0) + head = k; + else + next[tail] = k; + tail = k; + } + } + /* set new pointer to the middle part of SVA */ + xassert(m_ptr <= sva->r_ptr); + sva->m_ptr = m_ptr; + /* set new head and tail of the linked list */ + sva->head = head; + sva->tail = tail; +#if 1 + if (sva->talky) + xprintf("after defragmenting = %d %d %d\n", sva->m_ptr - 1, + sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); +#endif + return; +} + +/*********************************************************************** +* sva_more_space - increase size of middle (free) part of SVA +* +* This routine increases the size of the middle (free) part of the +* sparse vector area (SVA). +* +* The parameter m_size specifies the minimal size, in locations, of +* the middle part to be provided. This new size should be greater than +* the current size of the middle part. +* +* First, the routine defragments the left part of SVA. Then, if the +* size of the left part has not sufficiently increased, the routine +* increases the total size of the SVA storage by reallocating it. */ + +void sva_more_space(SVA *sva, int m_size) +{ int size, delta; +#if 1 + if (sva->talky) + xprintf("sva_more_space: m_size = %d\n", m_size); +#endif + xassert(m_size > sva->r_ptr - sva->m_ptr); + /* defragment the left part */ + sva_defrag_area(sva); + /* set, heuristically, the minimal size of the middle part to be + * not less than the size of the defragmented left part */ + if (m_size < sva->m_ptr - 1) + m_size = sva->m_ptr - 1; + /* if there is still not enough room, increase the total size of + * the SVA storage */ + if (sva->r_ptr - sva->m_ptr < m_size) + { size = sva->size; /* new sva size */ + for (;;) + { delta = size - sva->size; + if (sva->r_ptr - sva->m_ptr + delta >= m_size) + break; + size += size; + xassert(size > 0); + } + sva_resize_area(sva, delta); + xassert(sva->r_ptr - sva->m_ptr >= m_size); + } + return; +} + +/*********************************************************************** +* sva_enlarge_cap - enlarge capacity of specified vector +* +* This routine enlarges the current capacity of the specified vector +* by relocating its content. +* +* The parameter k specifies the reference number of the vector whose +* capacity should be enlarged, 1 <= k <= n. This vector should either +* have zero capacity or be stored in the left (dynamic) part of SVA. +* +* The parameter new_cap specifies the new capacity of the vector, +* in locations. This new capacity should be greater than the current +* capacity of the vector. +* +* The parameter skip is a flag. If this flag is set, the routine does +* *not* copy numerical values of elements of the vector on relocating +* its content, i.e. only element indices are copied. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least new_cap free locations. */ + +void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + xassert(1 <= k && k <= sva->n); + xassert(new_cap > cap[k]); + /* there should be at least new_cap free locations */ + xassert(sva->r_ptr - sva->m_ptr >= new_cap); + /* relocate the vector */ + if (cap[k] == 0) + { /* the vector is empty */ + xassert(ptr[k] == 0); + xassert(len[k] == 0); + } + else + { /* the vector has non-zero capacity */ + xassert(ptr[k] + len[k] <= sva->m_ptr); + /* copy the current vector content to the beginning of the + * middle part */ + if (len[k] > 0) + { memcpy(&ind[sva->m_ptr], &ind[ptr[k]], + len[k] * sizeof(int)); + if (!skip) + memcpy(&val[sva->m_ptr], &val[ptr[k]], + len[k] * sizeof(double)); + } + /* remove the vector from the linked list */ + if (prev[k] == 0) + sva->head = next[k]; + else + { /* preceding vector exists; increase its capacity */ + cap[prev[k]] += cap[k]; + next[prev[k]] = next[k]; + } + if (next[k] == 0) + sva->tail = prev[k]; + else + prev[next[k]] = prev[k]; + } + /* set new pointer and capacity of the vector */ + ptr[k] = sva->m_ptr; + cap[k] = new_cap; + /* add the vector to the end of the linked list */ + prev[k] = sva->tail; + next[k] = 0; + if (sva->head == 0) + sva->head = k; + else + next[sva->tail] = k; + sva->tail = k; + /* new_cap free locations have been consumed */ + sva->m_ptr += new_cap; + xassert(sva->m_ptr <= sva->r_ptr); + return; +} + +/*********************************************************************** +* sva_reserve_cap - reserve locations for specified vector +* +* This routine reserves locations for the specified vector in the +* right (static) part of SVA. +* +* The parameter k specifies the reference number of the vector (this +* vector should have zero capacity), 1 <= k <= n. +* +* The parameter new_cap specifies a non-zero capacity of the vector, +* in locations. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least new_cap free locations. */ + +void sva_reserve_cap(SVA *sva, int k, int new_cap) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + xassert(1 <= k && k <= sva->n); + xassert(new_cap > 0); + xassert(ptr[k] == 0 && len[k] == 0 && cap[k] == 0); + /* there should be at least new_cap free locations */ + xassert(sva->r_ptr - sva->m_ptr >= new_cap); + /* set the pointer and capacity of the vector */ + ptr[k] = sva->r_ptr - new_cap; + cap[k] = new_cap; + /* new_cap free locations have been consumed */ + sva->r_ptr -= new_cap; + return; +} + +/*********************************************************************** +* sva_make_static - relocate specified vector to right part of SVA +* +* Assuming that the specified vector is stored in the left (dynamic) +* part of SVA, this routine makes the vector static by relocating its +* content to the right (static) part of SVA. However, if the specified +* vector has zero capacity, the routine does nothing. +* +* The parameter k specifies the reference number of the vector to be +* relocated, 1 <= k <= n. +* +* NOTE: On entry to the routine the middle part of SVA should have at +* least len[k] free locations, where len[k] is the length of the +* vector to be relocated. */ + +void sva_make_static(SVA *sva, int k) +{ int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int *prev = sva->prev; + int *next = sva->next; + int *ind = sva->ind; + double *val = sva->val; + int ptr_k, len_k; + xassert(1 <= k && k <= sva->n); + /* if the vector has zero capacity, do nothing */ + if (cap[k] == 0) + { xassert(ptr[k] == 0); + xassert(len[k] == 0); + goto done; + } + /* there should be at least len[k] free locations */ + len_k = len[k]; + xassert(sva->r_ptr - sva->m_ptr >= len_k); + /* remove the vector from the linked list */ + if (prev[k] == 0) + sva->head = next[k]; + else + { /* preceding vector exists; increase its capacity */ + cap[prev[k]] += cap[k]; + next[prev[k]] = next[k]; + } + if (next[k] == 0) + sva->tail = prev[k]; + else + prev[next[k]] = prev[k]; + /* if the vector has zero length, make it empty */ + if (len_k == 0) + { ptr[k] = cap[k] = 0; + goto done; + } + /* copy the vector content to the beginning of the right part */ + ptr_k = sva->r_ptr - len_k; + memcpy(&ind[ptr_k], &ind[ptr[k]], len_k * sizeof(int)); + memcpy(&val[ptr_k], &val[ptr[k]], len_k * sizeof(double)); + /* set new pointer and capacity of the vector */ + ptr[k] = ptr_k; + cap[k] = len_k; + /* len[k] free locations have been consumed */ + sva->r_ptr -= len_k; +done: return; +} + +/*********************************************************************** +* sva_check_area - check sparse vector area (SVA) +* +* This routine checks the SVA data structures for correctness. +* +* NOTE: For testing/debugging only. */ + +void sva_check_area(SVA *sva) +{ int n_max = sva->n_max; + int n = sva->n; + int *ptr = sva->ptr; + int *len = sva->len; + int *cap = sva->cap; + int size = sva->size; + int m_ptr = sva->m_ptr; + int r_ptr = sva->r_ptr; + int head = sva->head; + int tail = sva->tail; + int *prev = sva->prev; + int *next = sva->next; + int k; +#if 0 /* 16/II-2004; SVA may be empty */ + xassert(1 <= n && n <= n_max); +#else + xassert(0 <= n && n <= n_max); +#endif + xassert(1 <= m_ptr && m_ptr <= r_ptr && r_ptr <= size+1); + /* all vectors included the linked list should have non-zero + * capacity and be stored in the left part */ + for (k = head; k != 0; k = next[k]) + { xassert(1 <= k && k <= n); + xassert(cap[k] > 0); + xassert(0 <= len[k] && len[k] <= cap[k]); + if (prev[k] == 0) + xassert(k == head); + else + { xassert(1 <= prev[k] && prev[k] <= n); + xassert(next[prev[k]] == k); + } + if (next[k] == 0) + { xassert(k == tail); + xassert(ptr[k] + cap[k] <= m_ptr); + } + else + { xassert(1 <= next[k] && next[k] <= n); + xassert(prev[next[k]] == k); + xassert(ptr[k] + cap[k] <= ptr[next[k]]); + } + cap[k] = -cap[k]; + } + /* all other vectors should either have zero capacity or be + * stored in the right part */ + for (k = 1; k <= n; k++) + { if (cap[k] < 0) + { /* k-th vector is stored in the left part */ + cap[k] = -cap[k]; + } + else if (cap[k] == 0) + { /* k-th vector has zero capacity */ + xassert(ptr[k] == 0); + xassert(len[k] == 0); + } + else /* cap[k] > 0 */ + { /* k-th vector is stored in the right part */ + xassert(0 <= len[k] && len[k] <= cap[k]); + xassert(r_ptr <= ptr[k] && ptr[k] + cap[k] <= size+1); + } + } + return; +} + +/*********************************************************************** +* sva_delete_area - delete sparse vector area (SVA) +* +* This routine deletes the sparse vector area (SVA) freeing all the +* memory allocated to it. */ + +void sva_delete_area(SVA *sva) +{ tfree(sva->ptr); + tfree(sva->len); + tfree(sva->cap); + tfree(sva->prev); + tfree(sva->next); + tfree(sva->ind); + tfree(sva->val); + tfree(sva); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.h b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.h new file mode 100644 index 000000000..0eab317b5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/bflib/sva.h @@ -0,0 +1,161 @@ +/* sva.h (sparse vector area) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SVA_H +#define SVA_H + +/*********************************************************************** +* Sparse Vector Area (SVA) is a container for sparse vectors. This +* program object is used mainly on computing factorization, where the +* sparse vectors are rows and columns of sparse matrices. +* +* The SVA storage is a set of locations numbered 1, 2, ..., size, +* where size is the size of SVA, which is the total number of +* locations currently allocated. Each location is identified by its +* pointer p, 1 <= p <= size, and is the pair (ind[p], val[p]), where +* ind[p] and val[p] are, respectively, the index and value fields used +* to store the index and numeric value of a particular vector element. +* +* Each sparse vector is identified by its reference number k, +* 1 <= k <= n, where n is the total number of vectors currently stored +* in SVA, and defined by the triplet (ptr[k], len[k], cap[k]), where: +* ptr[k] is a pointer to the first location of the vector; len[k] is +* the vector length, which is the number of its non-zero elements, +* len[k] >= 0; and cap[k] is the capacity of the vector, which is the +* total number of adjacent locations allocated to that vector, +* cap[k] >= len[k]. Thus, non-zero elements of k-th vector are stored +* in locations ptr[k], ptr[k]+1, ..., ptr[k]+len[k]-1, and locations +* ptr[k]+len[k], ptr[k]+len[k]+1, ..., ptr[k]+cap[k]-1 are reserved. +* +* The SVA storage is divided into three parts as follows: +* +* Locations 1, 2, ..., m_ptr-1 constitute the left (dynamic) part of +* SVA. This part is used to store vectors, whose capacity may change. +* Note that all vectors stored in the left part are also included in +* a doubly linked list, where they are ordered by increasing their +* pointers ptr[k] (this list is needed for efficient implementation +* of the garbage collector used to defragment the left part of SVA); +* +* Locations m_ptr, m_ptr+1, ..., r_ptr-1 are free and constitute the +* middle (free) part of SVA. +* +* Locations r_ptr, r_ptr+1, ..., size constitute the right (static) +* part of SVA. This part is used to store vectors, whose capacity is +* not changed. */ + +typedef struct SVA SVA; + +struct SVA +{ /* sparse vector area */ + int n_max; + /* maximal value of n (enlarged automatically) */ + int n; + /* number of currently allocated vectors, 0 <= n <= n_max */ + int *ptr; /* int ptr[1+n_max]; */ + /* ptr[0] is not used; + * ptr[k], 1 <= i <= n, is pointer to first location of k-th + * vector in the arrays ind and val */ + int *len; /* int len[1+n_max]; */ + /* len[0] is not used; + * len[k], 1 <= k <= n, is length of k-th vector, len[k] >= 0 */ + int *cap; /* int cap[1+n_max]; */ + /* cap[0] is not used; + * cap[k], 1 <= k <= n, is capacity of k-th vector (the number + * of adjacent locations allocated to it), cap[k] >= len[k] */ + /* NOTE: if cap[k] = 0, then ptr[k] = 0 and len[k] = 0 */ + int size; + /* total number of locations in SVA */ + int m_ptr, r_ptr; + /* partitioning pointers that define the left, middle, and right + * parts of SVA (see above); 1 <= m_ptr <= r_ptr <= size+1 */ + int head; + /* number of first (leftmost) vector in the linked list */ + int tail; + /* number of last (rightmost) vector in the linked list */ + int *prev; /* int prev[1+n_max]; */ + /* prev[0] is not used; + * prev[k] is number of vector which precedes k-th vector in the + * linked list; + * prev[k] < 0 means that k-th vector is not in the list */ + int *next; /* int next[1+n_max]; */ + /* next[0] is not used; + * next[k] is number of vector which succedes k-th vector in the + * linked list; + * next[k] < 0 means that k-th vector is not in the list */ + /* NOTE: only vectors having non-zero capacity and stored in the + * left part of SVA are included in this linked list */ + int *ind; /* int ind[1+size]; */ + /* ind[0] is not used; + * ind[p], 1 <= p <= size, is index field of location p */ + double *val; /* double val[1+size]; */ + /* val[0] is not used; + * val[p], 1 <= p <= size, is value field of location p */ +#if 1 + int talky; + /* option to enable talky mode */ +#endif +}; + +#define sva_create_area _glp_sva_create_area +SVA *sva_create_area(int n_max, int size); +/* create sparse vector area (SVA) */ + +#define sva_alloc_vecs _glp_sva_alloc_vecs +int sva_alloc_vecs(SVA *sva, int nnn); +/* allocate new vectors in SVA */ + +#define sva_resize_area _glp_sva_resize_area +void sva_resize_area(SVA *sva, int delta); +/* change size of SVA storage */ + +#define sva_defrag_area _glp_sva_defrag_area +void sva_defrag_area(SVA *sva); +/* defragment left part of SVA */ + +#define sva_more_space _glp_sva_more_space +void sva_more_space(SVA *sva, int m_size); +/* increase size of middle (free) part of SVA */ + +#define sva_enlarge_cap _glp_sva_enlarge_cap +void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip); +/* enlarge capacity of specified vector */ + +#define sva_reserve_cap _glp_sva_reserve_cap +void sva_reserve_cap(SVA *sva, int k, int new_cap); +/* reserve locations for specified vector */ + +#define sva_make_static _glp_sva_make_static +void sva_make_static(SVA *sva, int k); +/* relocate specified vector to right part of SVA */ + +#define sva_check_area _glp_sva_check_area +void sva_check_area(SVA *sva); +/* check sparse vector area (SVA) */ + +#define sva_delete_area _glp_sva_delete_area +void sva_delete_area(SVA *sva); +/* delete sparse vector area (SVA) */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/colamd/COPYING b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/COPYING new file mode 100644 index 000000000..84bba36d0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/colamd/README b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/README new file mode 100644 index 000000000..a365059fe --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/README @@ -0,0 +1,98 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin . +************************************************************************ +COLAMD/SYMAMD Version 2.7, Copyright (C) 1998-2007, Timothy A. Davis, +All Rights Reserved. + +Description: + + colamd: an approximate minimum degree column ordering algorithm, + for LU factorization of symmetric or unsymmetric matrices, + QR factorization, least squares, interior point methods for + linear programming problems, and other related problems. + + symamd: an approximate minimum degree ordering algorithm for + Cholesky factorization of symmetric matrices. + +Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization + of (AQ)'(AQ) has less fill-in and requires fewer floating point + operations than A'A. This also provides a good ordering for sparse + partial pivoting methods, P(AQ) = LU, where Q is computed prior to + numerical factorization, and P is computed during numerical + factorization via conventional partial pivoting with row + interchanges. Colamd is the column ordering method used in SuperLU, + part of the ScaLAPACK library. It is also available as built-in + function in MATLAB Version 6, available from MathWorks, Inc. + (http://www.mathworks.com). This routine can be used in place of + colmmd in MATLAB. + + Symamd computes a permutation P of a symmetric matrix A such that + the Cholesky factorization of PAP' has less fill-in and requires + fewer floating point operations than A. Symamd constructs a matrix + M such that M'M has the same nonzero pattern of A, and then orders + the columns of M using colmmd. The column ordering of M is then + returned as the row and column ordering P of A. + +Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis at cise.ufl.edu), University of Florida. The algorithm + was developed in collaboration with John Gilbert, Xerox PARC, and + Esmond Ng, Oak Ridge National Laboratory. + +Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + +License: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA. + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all + copies. User documentation of any code that uses this code or any + modified version of this code must cite the Copyright, this License, + the Availability note, and "Used by permission." Permission to + modify the code and to distribute modified code is granted, provided + the Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + COLAMD is also available under alternate licenses, contact T. Davis + for details. + +Availability: + + The colamd/symamd library is available at: + + http://www.cise.ufl.edu/research/sparse/colamd/ + +References: + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate + column minimum degree ordering algorithm, ACM Transactions on + Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: + COLAMD, an approximate column minimum degree ordering algorithm, ACM + Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, + 2004. diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.c b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.c new file mode 100644 index 000000000..86ddd6b74 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.c @@ -0,0 +1,3622 @@ +/* ========================================================================== */ +/* === colamd/symamd - a sparse matrix column ordering algorithm ============ */ +/* ========================================================================== */ + +/* COLAMD / SYMAMD + + colamd: an approximate minimum degree column ordering algorithm, + for LU factorization of symmetric or unsymmetric matrices, + QR factorization, least squares, interior point methods for + linear programming problems, and other related problems. + + symamd: an approximate minimum degree ordering algorithm for Cholesky + factorization of symmetric matrices. + + Purpose: + + Colamd computes a permutation Q such that the Cholesky factorization of + (AQ)'(AQ) has less fill-in and requires fewer floating point operations + than A'A. This also provides a good ordering for sparse partial + pivoting methods, P(AQ) = LU, where Q is computed prior to numerical + factorization, and P is computed during numerical factorization via + conventional partial pivoting with row interchanges. Colamd is the + column ordering method used in SuperLU, part of the ScaLAPACK library. + It is also available as built-in function in MATLAB Version 6, + available from MathWorks, Inc. (http://www.mathworks.com). This + routine can be used in place of colmmd in MATLAB. + + Symamd computes a permutation P of a symmetric matrix A such that the + Cholesky factorization of PAP' has less fill-in and requires fewer + floating point operations than A. Symamd constructs a matrix M such + that M'M has the same nonzero pattern of A, and then orders the columns + of M using colmmd. The column ordering of M is then returned as the + row and column ordering P of A. + + Authors: + + The authors of the code itself are Stefan I. Larimore and Timothy A. + Davis (davis at cise.ufl.edu), University of Florida. The algorithm was + developed in collaboration with John Gilbert, Xerox PARC, and Esmond + Ng, Oak Ridge National Laboratory. + + Acknowledgements: + + This work was supported by the National Science Foundation, under + grants DMS-9504974 and DMS-9803599. + + Copyright and License: + + Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved. + COLAMD is also available under alternate licenses, contact T. Davis + for details. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + USA + + Permission is hereby granted to use or copy this program under the + terms of the GNU LGPL, provided that the Copyright, this License, + and the Availability of the original version is retained on all copies. + User documentation of any code that uses this code or any modified + version of this code must cite the Copyright, this License, the + Availability note, and "Used by permission." Permission to modify + the code and to distribute modified code is granted, provided the + Copyright, this License, and the Availability note are retained, + and a notice that the code was modified is included. + + Availability: + + The colamd/symamd library is available at + + http://www.cise.ufl.edu/research/sparse/colamd/ + + This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c + file. It requires the colamd.h file. It is required by the colamdmex.c + and symamdmex.c files, for the MATLAB interface to colamd and symamd. + Appears as ACM Algorithm 836. + + See the ChangeLog file for changes since Version 1.0. + + References: + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column + minimum degree ordering algorithm, ACM Transactions on Mathematical + Software, vol. 30, no. 3., pp. 353-376, 2004. + + T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, + an approximate column minimum degree ordering algorithm, ACM + Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, + 2004. + +*/ + +/* ========================================================================== */ +/* === Description of user-callable routines ================================ */ +/* ========================================================================== */ + +/* COLAMD includes both int and UF_long versions of all its routines. The + * description below is for the int version. For UF_long, all int arguments + * become UF_long. UF_long is normally defined as long, except for WIN64. + + ---------------------------------------------------------------------------- + colamd_recommended: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + size_t colamd_recommended (int nnz, int n_row, int n_col) ; + size_t colamd_l_recommended (UF_long nnz, UF_long n_row, + UF_long n_col) ; + + Purpose: + + Returns recommended value of Alen for use by colamd. Returns 0 + if any input argument is negative. The use of this routine + is optional. Not needed for symamd, which dynamically allocates + its own memory. + + Note that in v2.4 and earlier, these routines returned int or long. + They now return a value of type size_t. + + Arguments (all input arguments): + + int nnz ; Number of nonzeros in the matrix A. This must + be the same value as p [n_col] in the call to + colamd - otherwise you will get a wrong value + of the recommended memory to use. + + int n_row ; Number of rows in the matrix A. + + int n_col ; Number of columns in the matrix A. + + ---------------------------------------------------------------------------- + colamd_set_defaults: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; + colamd_l_set_defaults (double knobs [COLAMD_KNOBS]) ; + + Purpose: + + Sets the default parameters. The use of this routine is optional. + + Arguments: + + double knobs [COLAMD_KNOBS] ; Output only. + + NOTE: the meaning of the dense row/col knobs has changed in v2.4 + + knobs [0] and knobs [1] control dense row and col detection: + + Colamd: rows with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col)) + entries are removed prior to ordering. Columns with more than + max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) + entries are removed prior to + ordering, and placed last in the output column ordering. + + Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0]. + Rows and columns with more than + max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n)) + entries are removed prior to ordering, and placed last in the + output ordering. + + COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, + respectively, in colamd.h. Default values of these two knobs + are both 10. Currently, only knobs [0] and knobs [1] are + used, but future versions may use more knobs. If so, they will + be properly set to their defaults by the future version of + colamd_set_defaults, so that the code that calls colamd will + not need to change, assuming that you either use + colamd_set_defaults, or pass a (double *) NULL pointer as the + knobs array to colamd or symamd. + + knobs [2]: aggressive absorption + + knobs [COLAMD_AGGRESSIVE] controls whether or not to do + aggressive absorption during the ordering. Default is TRUE. + + + ---------------------------------------------------------------------------- + colamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int colamd (int n_row, int n_col, int Alen, int *A, int *p, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ; + UF_long colamd_l (UF_long n_row, UF_long n_col, UF_long Alen, + UF_long *A, UF_long *p, double knobs [COLAMD_KNOBS], + UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Computes a column ordering (Q) of A such that P(AQ)=LU or + (AQ)'AQ=LL' have less fill-in and require fewer floating point + operations than factorizing the unpermuted matrix A or A'A, + respectively. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n_row ; Input argument. + + Number of rows in the matrix A. + Restriction: n_row >= 0. + Colamd returns FALSE if n_row is negative. + + int n_col ; Input argument. + + Number of columns in the matrix A. + Restriction: n_col >= 0. + Colamd returns FALSE if n_col is negative. + + int Alen ; Input argument. + + Restriction (see note): + Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col + Colamd returns FALSE if these conditions are not met. + + Note: this restriction makes an modest assumption regarding + the size of the two typedef's structures in colamd.h. + We do, however, guarantee that + + Alen >= colamd_recommended (nnz, n_row, n_col) + + will be sufficient. Note: the macro version does not check + for integer overflow, and thus is not recommended. Use + the colamd_recommended routine instead. + + int A [Alen] ; Input argument, undefined on output. + + A is an integer array of size Alen. Alen must be at least as + large as the bare minimum value given above, but this is very + low, and can result in excessive run time. For best + performance, we recommend that Alen be greater than or equal to + colamd_recommended (nnz, n_row, n_col), which adds + nnz/5 to the bare minimum value given above. + + On input, the row indices of the entries in column c of the + matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices + in a given column c need not be in ascending order, and + duplicate row indices may be be present. However, colamd will + work a little faster if both of these conditions are met + (Colamd puts the matrix into this format, if it finds that the + the conditions are not met). + + The matrix is 0-based. That is, rows are in the range 0 to + n_row-1, and columns are in the range 0 to n_col-1. Colamd + returns FALSE if any row index is out of range. + + The contents of A are modified during ordering, and are + undefined on output. + + int p [n_col+1] ; Both input and output argument. + + p is an integer array of size n_col+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n_col-1. The value p [n_col] is + thus the total number of entries in the pattern of the matrix A. + Colamd returns FALSE if these conditions are not met. + + On output, if colamd returns TRUE, the array p holds the column + permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is + the first column index in the new ordering, and p [n_col-1] is + the last. That is, p [k] = j means that column j of A is the + kth pivot column, in AQ, where k is in the range 0 to n_col-1 + (p [0] = j means that column j of A is the first column in AQ). + + If colamd returns FALSE, then no permutation is returned, and + p is undefined on output. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Colamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty rows ignored. + + stats [1]: number of dense or empty columns ignored (and + ordered last in the output permutation p) + Note that a row can become "empty" if it + contains only "dense" and/or "empty" columns, + and similarly a column can become "empty" if it + only contains "dense" and/or "empty" rows. + + stats [2]: number of garbage collections performed. + This can be excessively high if Alen is close + to the minimum required value. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Colamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of colamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 n_row is negative + + stats [4]: n_row + + -4 n_col is negative + + stats [4]: n_col + + -5 number of nonzeros in matrix is negative + + stats [4]: number of nonzeros, p [n_col] + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 A is too small + + stats [4]: required size + stats [5]: actual size (Alen) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 (unused; see symamd.c) + + -999 (unused; see symamd.c) + + Future versions may return more statistics in the stats array. + + Example: + + See http://www.cise.ufl.edu/research/sparse/colamd/example.c + for a complete example. + + To order the columns of a 5-by-4 matrix with 11 nonzero entries in + the following nonzero pattern + + x 0 x 0 + x 0 x x + 0 x x 0 + 0 0 x x + x x 0 0 + + with default knobs and no output statistics, do the following: + + #include "colamd.h" + #define ALEN 100 + int A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; + int p [ ] = {0, 3, 5, 9, 11} ; + int stats [COLAMD_STATS] ; + colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; + + The permutation is returned in the array p, and A is destroyed. + + ---------------------------------------------------------------------------- + symamd: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + int symamd (int n, int *A, int *p, int *perm, + double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; + UF_long symamd_l (UF_long n, UF_long *A, UF_long *p, UF_long *perm, + double knobs [COLAMD_KNOBS], UF_long stats [COLAMD_STATS], + void (*allocate) (size_t, size_t), void (*release) (void *)) ; + + Purpose: + + The symamd routine computes an ordering P of a symmetric sparse + matrix A such that the Cholesky factorization PAP' = LL' remains + sparse. It is based on a column ordering of a matrix M constructed + so that the nonzero pattern of M'M is the same as A. The matrix A + is assumed to be symmetric; only the strictly lower triangular part + is accessed. You must pass your selected memory allocator (usually + calloc/free or mxCalloc/mxFree) to symamd, for it to allocate + memory for the temporary matrix M. + + Returns: + + TRUE (1) if successful, FALSE (0) otherwise. + + Arguments: + + int n ; Input argument. + + Number of rows and columns in the symmetrix matrix A. + Restriction: n >= 0. + Symamd returns FALSE if n is negative. + + int A [nnz] ; Input argument. + + A is an integer array of size nnz, where nnz = p [n]. + + The row indices of the entries in column c of the matrix are + held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a + given column c need not be in ascending order, and duplicate + row indices may be present. However, symamd will run faster + if the columns are in sorted order with no duplicate entries. + + The matrix is 0-based. That is, rows are in the range 0 to + n-1, and columns are in the range 0 to n-1. Symamd + returns FALSE if any row index is out of range. + + The contents of A are not modified. + + int p [n+1] ; Input argument. + + p is an integer array of size n+1. On input, it holds the + "pointers" for the column form of the matrix A. Column c of + the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first + entry, p [0], must be zero, and p [c] <= p [c+1] must hold + for all c in the range 0 to n-1. The value p [n] is + thus the total number of entries in the pattern of the matrix A. + Symamd returns FALSE if these conditions are not met. + + The contents of p are not modified. + + int perm [n+1] ; Output argument. + + On output, if symamd returns TRUE, the array perm holds the + permutation P, where perm [0] is the first index in the new + ordering, and perm [n-1] is the last. That is, perm [k] = j + means that row and column j of A is the kth column in PAP', + where k is in the range 0 to n-1 (perm [0] = j means + that row and column j of A are the first row and column in + PAP'). The array is used as a workspace during the ordering, + which is why it must be of length n+1, not just n. + + double knobs [COLAMD_KNOBS] ; Input argument. + + See colamd_set_defaults for a description. + + int stats [COLAMD_STATS] ; Output argument. + + Statistics on the ordering, and error status. + See colamd.h for related definitions. + Symamd returns FALSE if stats is not present. + + stats [0]: number of dense or empty row and columns ignored + (and ordered last in the output permutation + perm). Note that a row/column can become + "empty" if it contains only "dense" and/or + "empty" columns/rows. + + stats [1]: (same as stats [0]) + + stats [2]: number of garbage collections performed. + + stats [3]: status code. < 0 is an error code. + > 1 is a warning or notice. + + 0 OK. Each column of the input matrix contained + row indices in increasing order, with no + duplicates. + + 1 OK, but columns of input matrix were jumbled + (unsorted columns or duplicate entries). Symamd + had to do some extra work to sort the matrix + first and remove duplicate entries, but it + still was able to return a valid permutation + (return value of symamd was TRUE). + + stats [4]: highest numbered column that + is unsorted or has duplicate + entries. + stats [5]: last seen duplicate or + unsorted row index. + stats [6]: number of duplicate or + unsorted row indices. + + -1 A is a null pointer + + -2 p is a null pointer + + -3 (unused, see colamd.c) + + -4 n is negative + + stats [4]: n + + -5 number of nonzeros in matrix is negative + + stats [4]: # of nonzeros (p [n]). + + -6 p [0] is nonzero + + stats [4]: p [0] + + -7 (unused) + + -8 a column has a negative number of entries + + stats [4]: column with < 0 entries + stats [5]: number of entries in col + + -9 a row index is out of bounds + + stats [4]: column with bad row index + stats [5]: bad row index + stats [6]: n_row, # of rows of matrx + + -10 out of memory (unable to allocate temporary + workspace for M or count arrays using the + "allocate" routine passed into symamd). + + Future versions may return more statistics in the stats array. + + void * (*allocate) (size_t, size_t) + + A pointer to a function providing memory allocation. The + allocated memory must be returned initialized to zero. For a + C application, this argument should normally be a pointer to + calloc. For a MATLAB mexFunction, the routine mxCalloc is + passed instead. + + void (*release) (size_t, size_t) + + A pointer to a function that frees memory allocated by the + memory allocation routine above. For a C application, this + argument should normally be a pointer to free. For a MATLAB + mexFunction, the routine mxFree is passed instead. + + + ---------------------------------------------------------------------------- + colamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + colamd_report (int stats [COLAMD_STATS]) ; + colamd_l_report (UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from colamd. + + + ---------------------------------------------------------------------------- + symamd_report: + ---------------------------------------------------------------------------- + + C syntax: + + #include "colamd.h" + symamd_report (int stats [COLAMD_STATS]) ; + symamd_l_report (UF_long stats [COLAMD_STATS]) ; + + Purpose: + + Prints the error status and statistics recorded in the stats + array on the standard error output (for a standard C routine) + or on the MATLAB output (for a mexFunction). + + Arguments: + + int stats [COLAMD_STATS] ; Input only. Statistics from symamd. + + +*/ + +/* ========================================================================== */ +/* === Scaffolding code definitions ======================================== */ +/* ========================================================================== */ + +/* Ensure that debugging is turned off: */ +#ifndef NDEBUG +#define NDEBUG +#endif + +/* turn on debugging by uncommenting the following line + #undef NDEBUG +*/ + +/* + Our "scaffolding code" philosophy: In our opinion, well-written library + code should keep its "debugging" code, and just normally have it turned off + by the compiler so as not to interfere with performance. This serves + several purposes: + + (1) assertions act as comments to the reader, telling you what the code + expects at that point. All assertions will always be true (unless + there really is a bug, of course). + + (2) leaving in the scaffolding code assists anyone who would like to modify + the code, or understand the algorithm (by reading the debugging output, + one can get a glimpse into what the code is doing). + + (3) (gasp!) for actually finding bugs. This code has been heavily tested + and "should" be fully functional and bug-free ... but you never know... + + The code will become outrageously slow when debugging is + enabled. To control the level of debugging output, set an environment + variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, + you should see the following message on the standard output: + + colamd: debug version, D = 1 (THIS WILL BE SLOW!) + + or a similar message for symamd. If you don't, then debugging has not + been enabled. + +*/ + +/* ========================================================================== */ +/* === Include files ======================================================== */ +/* ========================================================================== */ + +#include "colamd.h" + +#if 0 /* by mao */ +#include +#include + +#ifdef MATLAB_MEX_FILE +#include "mex.h" +#include "matrix.h" +#endif /* MATLAB_MEX_FILE */ + +#if !defined (NPRINT) || !defined (NDEBUG) +#include +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif +#endif + +/* ========================================================================== */ +/* === int or UF_long ======================================================= */ +/* ========================================================================== */ + +#if 0 /* by mao */ +/* define UF_long */ +#include "UFconfig.h" +#endif + +#ifdef DLONG + +#define Int UF_long +#define ID UF_long_id +#define Int_MAX UF_long_max + +#define COLAMD_recommended colamd_l_recommended +#define COLAMD_set_defaults colamd_l_set_defaults +#define COLAMD_MAIN colamd_l +#define SYMAMD_MAIN symamd_l +#define COLAMD_report colamd_l_report +#define SYMAMD_report symamd_l_report + +#else + +#define Int int +#define ID "%d" +#define Int_MAX INT_MAX + +#define COLAMD_recommended colamd_recommended +#define COLAMD_set_defaults colamd_set_defaults +#define COLAMD_MAIN colamd +#define SYMAMD_MAIN symamd +#define COLAMD_report colamd_report +#define SYMAMD_report symamd_report + +#endif + +/* ========================================================================== */ +/* === Row and Column structures ============================================ */ +/* ========================================================================== */ + +/* User code that makes use of the colamd/symamd routines need not directly */ +/* reference these structures. They are used only for colamd_recommended. */ + +typedef struct Colamd_Col_struct +{ + Int start ; /* index for A of first row in this column, or DEAD */ + /* if column is dead */ + Int length ; /* number of rows in this column */ + union + { + Int thickness ; /* number of original columns represented by this */ + /* col, if the column is alive */ + Int parent ; /* parent in parent tree super-column structure, if */ + /* the column is dead */ + } shared1 ; + union + { + Int score ; /* the score used to maintain heap, if col is alive */ + Int order ; /* pivot ordering of this column, if col is dead */ + } shared2 ; + union + { + Int headhash ; /* head of a hash bucket, if col is at the head of */ + /* a degree list */ + Int hash ; /* hash value, if col is not in a degree list */ + Int prev ; /* previous column in degree list, if col is in a */ + /* degree list (but not at the head of a degree list) */ + } shared3 ; + union + { + Int degree_next ; /* next column, if col is in a degree list */ + Int hash_next ; /* next column, if col is in a hash list */ + } shared4 ; + +} Colamd_Col ; + +typedef struct Colamd_Row_struct +{ + Int start ; /* index for A of first col in this row */ + Int length ; /* number of principal columns in this row */ + union + { + Int degree ; /* number of principal & non-principal columns in row */ + Int p ; /* used as a row pointer in init_rows_cols () */ + } shared1 ; + union + { + Int mark ; /* for computing set differences and marking dead rows*/ + Int first_column ;/* first column in row (used in garbage collection) */ + } shared2 ; + +} Colamd_Row ; + +/* ========================================================================== */ +/* === Definitions ========================================================== */ +/* ========================================================================== */ + +/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */ +#define PUBLIC +#define PRIVATE static + +#define DENSE_DEGREE(alpha,n) \ + ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) + +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#define ONES_COMPLEMENT(r) (-(r)-1) + +/* -------------------------------------------------------------------------- */ +/* Change for version 2.1: define TRUE and FALSE only if not yet defined */ +/* -------------------------------------------------------------------------- */ + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +/* -------------------------------------------------------------------------- */ + +#define EMPTY (-1) + +/* Row and column status */ +#define ALIVE (0) +#define DEAD (-1) + +/* Column status */ +#define DEAD_PRINCIPAL (-1) +#define DEAD_NON_PRINCIPAL (-2) + +/* Macros for row and column status update and checking. */ +#define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) +#define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) +#define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) +#define COL_IS_DEAD(c) (Col [c].start < ALIVE) +#define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) +#define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) +#define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } +#define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } +#define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } + +/* ========================================================================== */ +/* === Colamd reporting mechanism =========================================== */ +/* ========================================================================== */ + +#if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) +/* In MATLAB, matrices are 1-based to the user, but 0-based internally */ +#define INDEX(i) ((i)+1) +#else +/* In C, matrices are 0-based and indices are reported as such in *_report */ +#define INDEX(i) (i) +#endif + +/* All output goes through the PRINTF macro. */ +#define PRINTF(params) { if (colamd_printf != NULL) (void) colamd_printf params ; } + +/* ========================================================================== */ +/* === Prototypes of PRIVATE routines ======================================= */ +/* ========================================================================== */ + +PRIVATE Int init_rows_cols +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int p [], + Int stats [COLAMD_STATS] +) ; + +PRIVATE void init_scoring +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + double knobs [COLAMD_KNOBS], + Int *p_n_row2, + Int *p_n_col2, + Int *p_max_deg +) ; + +PRIVATE Int find_ordering +( + Int n_row, + Int n_col, + Int Alen, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int head [], + Int n_col2, + Int max_deg, + Int pfree, + Int aggressive +) ; + +PRIVATE void order_children +( + Int n_col, + Colamd_Col Col [], + Int p [] +) ; + +PRIVATE void detect_super_cols +( + +#ifndef NDEBUG + Int n_col, + Colamd_Row Row [], +#endif /* NDEBUG */ + + Colamd_Col Col [], + Int A [], + Int head [], + Int row_start, + Int row_length +) ; + +PRIVATE Int garbage_collection +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int *pfree +) ; + +PRIVATE Int clear_mark +( + Int tag_mark, + Int max_mark, + Int n_row, + Colamd_Row Row [] +) ; + +PRIVATE void print_report +( + char *method, + Int stats [COLAMD_STATS] +) ; + +/* ========================================================================== */ +/* === Debugging prototypes and definitions ================================= */ +/* ========================================================================== */ + +#ifndef NDEBUG + +#if 0 /* by mao */ +#include +#endif + +/* colamd_debug is the *ONLY* global variable, and is only */ +/* present when debugging */ + +PRIVATE Int colamd_debug = 0 ; /* debug print level */ + +#define DEBUG0(params) { PRINTF (params) ; } +#define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; } +#define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; } +#define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; } +#define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; } + +#if 0 /* by mao */ +#ifdef MATLAB_MEX_FILE +#define ASSERT(expression) (mxAssert ((expression), "")) +#else +#define ASSERT(expression) (assert (expression)) +#endif /* MATLAB_MEX_FILE */ +#else +#define ASSERT xassert +#endif + +PRIVATE void colamd_get_debug /* gets the debug print level from getenv */ +( + char *method +) ; + +PRIVATE void debug_deg_lists +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) ; + +PRIVATE void debug_mark +( + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) ; + +PRIVATE void debug_matrix +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) ; + +PRIVATE void debug_structures +( + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) ; + +#else /* NDEBUG */ + +/* === No debugging ========================================================= */ + +#define DEBUG0(params) ; +#define DEBUG1(params) ; +#define DEBUG2(params) ; +#define DEBUG3(params) ; +#define DEBUG4(params) ; + +#define ASSERT(expression) + +#endif /* NDEBUG */ + +/* ========================================================================== */ +/* === USER-CALLABLE ROUTINES: ============================================== */ +/* ========================================================================== */ + +/* ========================================================================== */ +/* === colamd_recommended =================================================== */ +/* ========================================================================== */ + +/* + The colamd_recommended routine returns the suggested size for Alen. This + value has been determined to provide good balance between the number of + garbage collections and the memory requirements for colamd. If any + argument is negative, or if integer overflow occurs, a 0 is returned as an + error condition. 2*nnz space is required for the row and column + indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is + required for the Col and Row arrays, respectively, which are internal to + colamd (roughly 6*n_col + 4*n_row). An additional n_col space is the + minimal amount of "elbow room", and nnz/5 more space is recommended for + run time efficiency. + + Alen is approximately 2.2*nnz + 7*n_col + 4*n_row + 10. + + This function is not needed when using symamd. +*/ + +/* add two values of type size_t, and check for integer overflow */ +static size_t t_add (size_t a, size_t b, int *ok) +{ + (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ; + return ((*ok) ? (a + b) : 0) ; +} + +/* compute a*k where k is a small integer, and check for integer overflow */ +static size_t t_mult (size_t a, size_t k, int *ok) +{ + size_t i, s = 0 ; + for (i = 0 ; i < k ; i++) + { + s = t_add (s, a, ok) ; + } + return (s) ; +} + +/* size of the Col and Row structures */ +#define COLAMD_C(n_col,ok) \ + ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int))) + +#define COLAMD_R(n_row,ok) \ + ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int))) + + +PUBLIC size_t COLAMD_recommended /* returns recommended value of Alen. */ +( + /* === Parameters ======================================================= */ + + Int nnz, /* number of nonzeros in A */ + Int n_row, /* number of rows in A */ + Int n_col /* number of columns in A */ +) +{ + size_t s, c, r ; + int ok = TRUE ; + if (nnz < 0 || n_row < 0 || n_col < 0) + { + return (0) ; + } + s = t_mult (nnz, 2, &ok) ; /* 2*nnz */ + c = COLAMD_C (n_col, &ok) ; /* size of column structures */ + r = COLAMD_R (n_row, &ok) ; /* size of row structures */ + s = t_add (s, c, &ok) ; + s = t_add (s, r, &ok) ; + s = t_add (s, n_col, &ok) ; /* elbow room */ + s = t_add (s, nnz/5, &ok) ; /* elbow room */ + ok = ok && (s < Int_MAX) ; + return (ok ? s : 0) ; +} + + +/* ========================================================================== */ +/* === colamd_set_defaults ================================================== */ +/* ========================================================================== */ + +/* + The colamd_set_defaults routine sets the default values of the user- + controllable parameters for colamd and symamd: + + Colamd: rows with more than max (16, knobs [0] * sqrt (n_col)) + entries are removed prior to ordering. Columns with more than + max (16, knobs [1] * sqrt (MIN (n_row,n_col))) entries are removed + prior to ordering, and placed last in the output column ordering. + + Symamd: Rows and columns with more than max (16, knobs [0] * sqrt (n)) + entries are removed prior to ordering, and placed last in the + output ordering. + + knobs [0] dense row control + + knobs [1] dense column control + + knobs [2] if nonzero, do aggresive absorption + + knobs [3..19] unused, but future versions might use this + +*/ + +PUBLIC void COLAMD_set_defaults +( + /* === Parameters ======================================================= */ + + double knobs [COLAMD_KNOBS] /* knob array */ +) +{ + /* === Local variables ================================================== */ + + Int i ; + + if (!knobs) + { + return ; /* no knobs to initialize */ + } + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + knobs [i] = 0 ; + } + knobs [COLAMD_DENSE_ROW] = 10 ; + knobs [COLAMD_DENSE_COL] = 10 ; + knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ +} + + +/* ========================================================================== */ +/* === symamd =============================================================== */ +/* ========================================================================== */ + +PUBLIC Int SYMAMD_MAIN /* return TRUE if OK, FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + Int n, /* number of rows and columns of A */ + Int A [], /* row indices of A */ + Int p [], /* column pointers of A */ + Int perm [], /* output permutation, size n+1 */ + double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ + Int stats [COLAMD_STATS], /* output statistics and error codes */ + void * (*allocate) (size_t, size_t), + /* pointer to calloc (ANSI C) or */ + /* mxCalloc (for MATLAB mexFunction) */ + void (*release) (void *) + /* pointer to free (ANSI C) or */ + /* mxFree (for MATLAB mexFunction) */ +) +{ + /* === Local variables ================================================== */ + + Int *count ; /* length of each column of M, and col pointer*/ + Int *mark ; /* mark array for finding duplicate entries */ + Int *M ; /* row indices of matrix M */ + size_t Mlen ; /* length of M */ + Int n_row ; /* number of rows in M */ + Int nnz ; /* number of entries in A */ + Int i ; /* row index of A */ + Int j ; /* column index of A */ + Int k ; /* row index of M */ + Int mnz ; /* number of nonzeros in M */ + Int pp ; /* index into a column of A */ + Int last_row ; /* last row seen in the current column */ + Int length ; /* number of nonzeros in a column */ + + double cknobs [COLAMD_KNOBS] ; /* knobs for colamd */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs for colamd */ + +#ifndef NDEBUG + colamd_get_debug ("symamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("symamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("symamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("symamd: p not present\n")) ; + return (FALSE) ; + } + + if (n < 0) /* n must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n ; + DEBUG0 (("symamd: n negative %d\n", n)) ; + return (FALSE) ; + } + + nnz = p [n] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + COLAMD_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + /* === Allocate count and mark ========================================== */ + + count = (Int *) ((*allocate) (n+1, sizeof (Int))) ; + if (!count) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ; + if (!mark) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ; + return (FALSE) ; + } + + /* === Compute column counts of M, check if A is valid ================== */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + + for (j = 0 ; j < n ; j++) + { + last_row = -1 ; + + length = p [j+1] - p [j] ; + if (length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = length ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ; + return (FALSE) ; + } + + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + if (i < 0 || i >= n) + { + /* row index i, in column j, is out of bounds */ + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + stats [COLAMD_INFO3] = n ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ; + return (FALSE) ; + } + + if (i <= last_row || mark [i] == j) + { + /* row index is unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = j ; + stats [COLAMD_INFO2] = i ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ; + } + + if (i > j && mark [i] != j) + { + /* row k of M will contain column indices i and j */ + count [i]++ ; + count [j]++ ; + } + + /* mark the row as having been seen in this column */ + mark [i] = j ; + + last_row = i ; + } + } + + /* v2.4: removed free(mark) */ + + /* === Compute column pointers of M ===================================== */ + + /* use output permutation, perm, for column pointers of M */ + perm [0] = 0 ; + for (j = 1 ; j <= n ; j++) + { + perm [j] = perm [j-1] + count [j-1] ; + } + for (j = 0 ; j < n ; j++) + { + count [j] = perm [j] ; + } + + /* === Construct M ====================================================== */ + + mnz = perm [n] ; + n_row = mnz / 2 ; + Mlen = COLAMD_recommended (mnz, n_row, n) ; + M = (Int *) ((*allocate) (Mlen, sizeof (Int))) ; + DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %g\n", + n_row, n, mnz, (double) Mlen)) ; + + if (!M) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; + (*release) ((void *) count) ; + (*release) ((void *) mark) ; + DEBUG0 (("symamd: allocate M (size %g) failed\n", (double) Mlen)) ; + return (FALSE) ; + } + + k = 0 ; + + if (stats [COLAMD_STATUS] == COLAMD_OK) + { + /* Matrix is OK */ + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + } + } + } + } + else + { + /* Matrix is jumbled. Do not add duplicates to M. Unsorted cols OK. */ + DEBUG0 (("symamd: Duplicates in A.\n")) ; + for (i = 0 ; i < n ; i++) + { + mark [i] = -1 ; + } + for (j = 0 ; j < n ; j++) + { + ASSERT (p [j+1] - p [j] >= 0) ; + for (pp = p [j] ; pp < p [j+1] ; pp++) + { + i = A [pp] ; + ASSERT (i >= 0 && i < n) ; + if (i > j && mark [i] != j) + { + /* row k of M contains column indices i and j */ + M [count [i]++] = k ; + M [count [j]++] = k ; + k++ ; + mark [i] = j ; + } + } + } + /* v2.4: free(mark) moved below */ + } + + /* count and mark no longer needed */ + (*release) ((void *) count) ; + (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */ + ASSERT (k == n_row) ; + + /* === Adjust the knobs for M =========================================== */ + + for (i = 0 ; i < COLAMD_KNOBS ; i++) + { + cknobs [i] = knobs [i] ; + } + + /* there are no dense rows in M */ + cknobs [COLAMD_DENSE_ROW] = -1 ; + cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ; + + /* === Order the columns of M =========================================== */ + + /* v2.4: colamd cannot fail here, so the error check is removed */ + (void) COLAMD_MAIN (n_row, n, (Int) Mlen, M, perm, cknobs, stats) ; + + /* Note that the output permutation is now in perm */ + + /* === get the statistics for symamd from colamd ======================== */ + + /* a dense column in colamd means a dense row and col in symamd */ + stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ; + + /* === Free M =========================================================== */ + + (*release) ((void *) M) ; + DEBUG0 (("symamd: done.\n")) ; + return (TRUE) ; + +} + +/* ========================================================================== */ +/* === colamd =============================================================== */ +/* ========================================================================== */ + +/* + The colamd routine computes a column ordering Q of a sparse matrix + A such that the LU factorization P(AQ) = LU remains sparse, where P is + selected via partial pivoting. The routine can also be viewed as + providing a permutation Q such that the Cholesky factorization + (AQ)'(AQ) = LL' remains sparse. +*/ + +PUBLIC Int COLAMD_MAIN /* returns TRUE if successful, FALSE otherwise*/ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows in A */ + Int n_col, /* number of columns in A */ + Int Alen, /* length of A */ + Int A [], /* row indices of A */ + Int p [], /* pointers to columns in A */ + double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ + Int stats [COLAMD_STATS] /* output statistics and error codes */ +) +{ + /* === Local variables ================================================== */ + + Int i ; /* loop index */ + Int nnz ; /* nonzeros in A */ + size_t Row_size ; /* size of Row [], in integers */ + size_t Col_size ; /* size of Col [], in integers */ + size_t need ; /* minimum required length of A */ + Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ + Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int ngarbage ; /* number of garbage collections performed */ + Int max_deg ; /* maximum row degree */ + double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ + Int aggressive ; /* do aggressive absorption */ + int ok ; + +#ifndef NDEBUG + colamd_get_debug ("colamd") ; +#endif /* NDEBUG */ + + /* === Check the input arguments ======================================== */ + + if (!stats) + { + DEBUG0 (("colamd: stats not present\n")) ; + return (FALSE) ; + } + for (i = 0 ; i < COLAMD_STATS ; i++) + { + stats [i] = 0 ; + } + stats [COLAMD_STATUS] = COLAMD_OK ; + stats [COLAMD_INFO1] = -1 ; + stats [COLAMD_INFO2] = -1 ; + + if (!A) /* A is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; + DEBUG0 (("colamd: A not present\n")) ; + return (FALSE) ; + } + + if (!p) /* p is not present */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; + DEBUG0 (("colamd: p not present\n")) ; + return (FALSE) ; + } + + if (n_row < 0) /* n_row must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ; + stats [COLAMD_INFO1] = n_row ; + DEBUG0 (("colamd: nrow negative %d\n", n_row)) ; + return (FALSE) ; + } + + if (n_col < 0) /* n_col must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; + stats [COLAMD_INFO1] = n_col ; + DEBUG0 (("colamd: ncol negative %d\n", n_col)) ; + return (FALSE) ; + } + + nnz = p [n_col] ; + if (nnz < 0) /* nnz must be >= 0 */ + { + stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; + stats [COLAMD_INFO1] = nnz ; + DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ; + return (FALSE) ; + } + + if (p [0] != 0) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; + stats [COLAMD_INFO1] = p [0] ; + DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ; + return (FALSE) ; + } + + /* === If no knobs, set default knobs =================================== */ + + if (!knobs) + { + COLAMD_set_defaults (default_knobs) ; + knobs = default_knobs ; + } + + aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ; + + /* === Allocate the Row and Col arrays from array A ===================== */ + + ok = TRUE ; + Col_size = COLAMD_C (n_col, &ok) ; /* size of Col array of structs */ + Row_size = COLAMD_R (n_row, &ok) ; /* size of Row array of structs */ + + /* need = 2*nnz + n_col + Col_size + Row_size ; */ + need = t_mult (nnz, 2, &ok) ; + need = t_add (need, n_col, &ok) ; + need = t_add (need, Col_size, &ok) ; + need = t_add (need, Row_size, &ok) ; + + if (!ok || need > (size_t) Alen || need > Int_MAX) + { + /* not enough space in array A to perform the ordering */ + stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ; + stats [COLAMD_INFO1] = need ; + stats [COLAMD_INFO2] = Alen ; + DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen)); + return (FALSE) ; + } + + Alen -= Col_size + Row_size ; + Col = (Colamd_Col *) &A [Alen] ; + Row = (Colamd_Row *) &A [Alen + Col_size] ; + + /* === Construct the row and column data structures ===================== */ + + if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats)) + { + /* input matrix is invalid */ + DEBUG0 (("colamd: Matrix invalid\n")) ; + return (FALSE) ; + } + + /* === Initialize scores, kill dense rows/columns ======================= */ + + init_scoring (n_row, n_col, Row, Col, A, p, knobs, + &n_row2, &n_col2, &max_deg) ; + + /* === Order the supercolumns =========================================== */ + + ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, + n_col2, max_deg, 2*nnz, aggressive) ; + + /* === Order the non-principal columns ================================== */ + + order_children (n_col, Col, p) ; + + /* === Return statistics in stats ======================================= */ + + stats [COLAMD_DENSE_ROW] = n_row - n_row2 ; + stats [COLAMD_DENSE_COL] = n_col - n_col2 ; + stats [COLAMD_DEFRAG_COUNT] = ngarbage ; + DEBUG0 (("colamd: done.\n")) ; + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === colamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void COLAMD_report +( + Int stats [COLAMD_STATS] +) +{ + print_report ("colamd", stats) ; +} + + +/* ========================================================================== */ +/* === symamd_report ======================================================== */ +/* ========================================================================== */ + +PUBLIC void SYMAMD_report +( + Int stats [COLAMD_STATS] +) +{ + print_report ("symamd", stats) ; +} + + + +/* ========================================================================== */ +/* === NON-USER-CALLABLE ROUTINES: ========================================== */ +/* ========================================================================== */ + +/* There are no user-callable routines beyond this point in the file */ + + +/* ========================================================================== */ +/* === init_rows_cols ======================================================= */ +/* ========================================================================== */ + +/* + Takes the column form of the matrix in A and creates the row form of the + matrix. Also, row and column attributes are stored in the Col and Row + structs. If the columns are un-sorted or contain duplicate row indices, + this routine will also sort and remove duplicate row indices from the + column form of the matrix. Returns FALSE if the matrix is invalid, + TRUE otherwise. Not user-callable. +*/ + +PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A, of size Alen */ + Int p [], /* pointers to columns in A, of size n_col+1 */ + Int stats [COLAMD_STATS] /* colamd statistics */ +) +{ + /* === Local variables ================================================== */ + + Int col ; /* a column index */ + Int row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *rp ; /* a row pointer */ + Int *rp_end ; /* a pointer to the end of a row */ + Int last_row ; /* previous row */ + + /* === Initialize columns, and check column pointers ==================== */ + + for (col = 0 ; col < n_col ; col++) + { + Col [col].start = p [col] ; + Col [col].length = p [col+1] - p [col] ; + + if (Col [col].length < 0) + { + /* column pointers must be non-decreasing */ + stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = Col [col].length ; + DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ; + return (FALSE) ; + } + + Col [col].shared1.thickness = 1 ; + Col [col].shared2.score = 0 ; + Col [col].shared3.prev = EMPTY ; + Col [col].shared4.degree_next = EMPTY ; + } + + /* p [0..n_col] no longer needed, used as "head" in subsequent routines */ + + /* === Scan columns, compute row degrees, and check row indices ========= */ + + stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].length = 0 ; + Row [row].shared2.mark = -1 ; + } + + for (col = 0 ; col < n_col ; col++) + { + last_row = -1 ; + + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + + while (cp < cp_end) + { + row = *cp++ ; + + /* make sure row indices within range */ + if (row < 0 || row >= n_row) + { + stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + stats [COLAMD_INFO3] = n_row ; + DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ; + return (FALSE) ; + } + + if (row <= last_row || Row [row].shared2.mark == col) + { + /* row index are unsorted or repeated (or both), thus col */ + /* is jumbled. This is a notice, not an error condition. */ + stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; + stats [COLAMD_INFO1] = col ; + stats [COLAMD_INFO2] = row ; + (stats [COLAMD_INFO3]) ++ ; + DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col)); + } + + if (Row [row].shared2.mark != col) + { + Row [row].length++ ; + } + else + { + /* this is a repeated entry in the column, */ + /* it will be removed */ + Col [col].length-- ; + } + + /* mark the row as having been seen in this column */ + Row [row].shared2.mark = col ; + + last_row = row ; + } + } + + /* === Compute row pointers ============================================= */ + + /* row form of the matrix starts directly after the column */ + /* form of matrix in A */ + Row [0].start = p [n_col] ; + Row [0].shared1.p = Row [0].start ; + Row [0].shared2.mark = -1 ; + for (row = 1 ; row < n_row ; row++) + { + Row [row].start = Row [row-1].start + Row [row-1].length ; + Row [row].shared1.p = Row [row].start ; + Row [row].shared2.mark = -1 ; + } + + /* === Create row form ================================================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + /* if cols jumbled, watch for repeated row indices */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + row = *cp++ ; + if (Row [row].shared2.mark != col) + { + A [(Row [row].shared1.p)++] = col ; + Row [row].shared2.mark = col ; + } + } + } + } + else + { + /* if cols not jumbled, we don't need the mark (this is faster) */ + for (col = 0 ; col < n_col ; col++) + { + cp = &A [p [col]] ; + cp_end = &A [p [col+1]] ; + while (cp < cp_end) + { + A [(Row [*cp++].shared1.p)++] = col ; + } + } + } + + /* === Clear the row marks and set row degrees ========================== */ + + for (row = 0 ; row < n_row ; row++) + { + Row [row].shared2.mark = 0 ; + Row [row].shared1.degree = Row [row].length ; + } + + /* === See if we need to re-create columns ============================== */ + + if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) + { + DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ; + +#ifndef NDEBUG + /* make sure column lengths are correct */ + for (col = 0 ; col < n_col ; col++) + { + p [col] = Col [col].length ; + } + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + p [*rp++]-- ; + } + } + for (col = 0 ; col < n_col ; col++) + { + ASSERT (p [col] == 0) ; + } + /* now p is all zero (different than when debugging is turned off) */ +#endif /* NDEBUG */ + + /* === Compute col pointers ========================================= */ + + /* col form of the matrix starts at A [0]. */ + /* Note, we may have a gap between the col form and the row */ + /* form if there were duplicate entries, if so, it will be */ + /* removed upon the first garbage collection */ + Col [0].start = 0 ; + p [0] = Col [0].start ; + for (col = 1 ; col < n_col ; col++) + { + /* note that the lengths here are for pruned columns, i.e. */ + /* no duplicate row indices will exist for these columns */ + Col [col].start = Col [col-1].start + Col [col-1].length ; + p [col] = Col [col].start ; + } + + /* === Re-create col form =========================================== */ + + for (row = 0 ; row < n_row ; row++) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + A [(p [*rp++])++] = row ; + } + } + } + + /* === Done. Matrix is not (or no longer) jumbled ====================== */ + + return (TRUE) ; +} + + +/* ========================================================================== */ +/* === init_scoring ========================================================= */ +/* ========================================================================== */ + +/* + Kills dense or empty columns and rows, calculates an initial score for + each column, and places all columns in the degree lists. Not user-callable. +*/ + +PRIVATE void init_scoring +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + double knobs [COLAMD_KNOBS],/* parameters */ + Int *p_n_row2, /* number of non-dense, non-empty rows */ + Int *p_n_col2, /* number of non-dense, non-empty columns */ + Int *p_max_deg /* maximum row degree */ +) +{ + /* === Local variables ================================================== */ + + Int c ; /* a column index */ + Int r, row ; /* a row index */ + Int *cp ; /* a column pointer */ + Int deg ; /* degree of a row or column */ + Int *cp_end ; /* a pointer to the end of a column */ + Int *new_cp ; /* new column pointer */ + Int col_length ; /* length of pruned column */ + Int score ; /* current column score */ + Int n_col2 ; /* number of non-dense, non-empty columns */ + Int n_row2 ; /* number of non-dense, non-empty rows */ + Int dense_row_count ; /* remove rows with more entries than this */ + Int dense_col_count ; /* remove cols with more entries than this */ + Int min_score ; /* smallest column score */ + Int max_deg ; /* maximum row degree */ + Int next_col ; /* Used to add to degree list.*/ + +#ifndef NDEBUG + Int debug_count ; /* debug only. */ +#endif /* NDEBUG */ + + /* === Extract knobs ==================================================== */ + + /* Note: if knobs contains a NaN, this is undefined: */ + if (knobs [COLAMD_DENSE_ROW] < 0) + { + /* only remove completely dense rows */ + dense_row_count = n_col-1 ; + } + else + { + dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ; + } + if (knobs [COLAMD_DENSE_COL] < 0) + { + /* only remove completely dense columns */ + dense_col_count = n_row-1 ; + } + else + { + dense_col_count = + DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ; + } + + DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; + max_deg = 0 ; + n_col2 = n_col ; + n_row2 = n_row ; + + /* === Kill empty columns =============================================== */ + + /* Put the empty columns at the end in their natural order, so that LU */ + /* factorization can proceed as far as possible. */ + for (c = n_col-1 ; c >= 0 ; c--) + { + deg = Col [c].length ; + if (deg == 0) + { + /* this is a empty column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense columns =============================================== */ + + /* Put the dense columns at the end, in their natural order */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip any dead columns */ + if (COL_IS_DEAD (c)) + { + continue ; + } + deg = Col [c].length ; + if (deg > dense_col_count) + { + /* this is a dense column, kill and order it last */ + Col [c].shared2.order = --n_col2 ; + /* decrement the row degrees */ + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + Row [*cp++].shared1.degree-- ; + } + KILL_PRINCIPAL_COL (c) ; + } + } + DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ; + + /* === Kill dense and empty rows ======================================== */ + + for (r = 0 ; r < n_row ; r++) + { + deg = Row [r].shared1.degree ; + ASSERT (deg >= 0 && deg <= n_col) ; + if (deg > dense_row_count || deg == 0) + { + /* kill a dense or empty row */ + KILL_ROW (r) ; + --n_row2 ; + } + else + { + /* keep track of max degree of remaining rows */ + max_deg = MAX (max_deg, deg) ; + } + } + DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ; + + /* === Compute initial column scores ==================================== */ + + /* At this point the row degrees are accurate. They reflect the number */ + /* of "live" (non-dense) columns in each row. No empty rows exist. */ + /* Some "live" columns may contain only dead rows, however. These are */ + /* pruned in the code below. */ + + /* now find the initial matlab score for each column */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* skip dead column */ + if (COL_IS_DEAD (c)) + { + continue ; + } + score = 0 ; + cp = &A [Col [c].start] ; + new_cp = cp ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + /* skip if dead */ + if (ROW_IS_DEAD (row)) + { + continue ; + } + /* compact the column */ + *new_cp++ = row ; + /* add row's external degree */ + score += Row [row].shared1.degree - 1 ; + /* guard against integer overflow */ + score = MIN (score, n_col) ; + } + /* determine pruned column length */ + col_length = (Int) (new_cp - &A [Col [c].start]) ; + if (col_length == 0) + { + /* a newly-made null column (all rows in this col are "dense" */ + /* and have already been killed) */ + DEBUG2 (("Newly null killed: %d\n", c)) ; + Col [c].shared2.order = --n_col2 ; + KILL_PRINCIPAL_COL (c) ; + } + else + { + /* set column length and set score */ + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + Col [c].length = col_length ; + Col [c].shared2.score = score ; + } + } + DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n", + n_col-n_col2)) ; + + /* At this point, all empty rows and columns are dead. All live columns */ + /* are "clean" (containing no dead rows) and simplicial (no supercolumns */ + /* yet). Rows may contain dead columns, but all live rows contain at */ + /* least one live column. */ + +#ifndef NDEBUG + debug_structures (n_row, n_col, Row, Col, A, n_col2) ; +#endif /* NDEBUG */ + + /* === Initialize degree lists ========================================== */ + +#ifndef NDEBUG + debug_count = 0 ; +#endif /* NDEBUG */ + + /* clear the hash buckets */ + for (c = 0 ; c <= n_col ; c++) + { + head [c] = EMPTY ; + } + min_score = n_col ; + /* place in reverse order, so low column indices are at the front */ + /* of the lists. This is to encourage natural tie-breaking */ + for (c = n_col-1 ; c >= 0 ; c--) + { + /* only add principal columns to degree lists */ + if (COL_IS_ALIVE (c)) + { + DEBUG4 (("place %d score %d minscore %d ncol %d\n", + c, Col [c].shared2.score, min_score, n_col)) ; + + /* === Add columns score to DList =============================== */ + + score = Col [c].shared2.score ; + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (score >= 0) ; + ASSERT (score <= n_col) ; + ASSERT (head [score] >= EMPTY) ; + + /* now add this column to dList at proper score location */ + next_col = head [score] ; + Col [c].shared3.prev = EMPTY ; + Col [c].shared4.degree_next = next_col ; + + /* if there already was a column with the same score, set its */ + /* previous pointer to this new column */ + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = c ; + } + head [score] = c ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, score) ; + +#ifndef NDEBUG + debug_count++ ; +#endif /* NDEBUG */ + + } + } + +#ifndef NDEBUG + DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n", + debug_count, n_col, n_col-debug_count)) ; + ASSERT (debug_count == n_col2) ; + debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ; +#endif /* NDEBUG */ + + /* === Return number of remaining columns, and max row degree =========== */ + + *p_n_col2 = n_col2 ; + *p_n_row2 = n_row2 ; + *p_max_deg = max_deg ; +} + + +/* ========================================================================== */ +/* === find_ordering ======================================================== */ +/* ========================================================================== */ + +/* + Order the principal columns of the supercolumn form of the matrix + (no supercolumns on input). Uses a minimum approximate column minimum + degree ordering method. Not user-callable. +*/ + +PRIVATE Int find_ordering /* return the number of garbage collections */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows of A */ + Int n_col, /* number of columns of A */ + Int Alen, /* size of A, 2*nnz + n_col or larger */ + Colamd_Row Row [], /* of size n_row+1 */ + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* column form and row form of A */ + Int head [], /* of size n_col+1 */ + Int n_col2, /* Remaining columns to order */ + Int max_deg, /* Maximum row degree */ + Int pfree, /* index of first free slot (2*nnz on entry) */ + Int aggressive +) +{ + /* === Local variables ================================================== */ + + Int k ; /* current pivot ordering step */ + Int pivot_col ; /* current pivot column */ + Int *cp ; /* a column pointer */ + Int *rp ; /* a row pointer */ + Int pivot_row ; /* current pivot row */ + Int *new_cp ; /* modified column pointer */ + Int *new_rp ; /* modified row pointer */ + Int pivot_row_start ; /* pointer to start of pivot row */ + Int pivot_row_degree ; /* number of columns in pivot row */ + Int pivot_row_length ; /* number of supercolumns in pivot row */ + Int pivot_col_score ; /* score of pivot column */ + Int needed_memory ; /* free space needed for pivot row */ + Int *cp_end ; /* pointer to the end of a column */ + Int *rp_end ; /* pointer to the end of a row */ + Int row ; /* a row index */ + Int col ; /* a column index */ + Int max_score ; /* maximum possible score */ + Int cur_score ; /* score of current column */ + unsigned Int hash ; /* hash value for supernode detection */ + Int head_column ; /* head of hash bucket */ + Int first_col ; /* first column in hash bucket */ + Int tag_mark ; /* marker value for mark array */ + Int row_mark ; /* Row [row].shared2.mark */ + Int set_difference ; /* set difference size of row with pivot row */ + Int min_score ; /* smallest column score */ + Int col_thickness ; /* "thickness" (no. of columns in a supercol) */ + Int max_mark ; /* maximum value of tag_mark */ + Int pivot_col_thickness ; /* number of columns represented by pivot col */ + Int prev_col ; /* Used by Dlist operations. */ + Int next_col ; /* Used by Dlist operations. */ + Int ngarbage ; /* number of garbage collections performed */ + +#ifndef NDEBUG + Int debug_d ; /* debug loop counter */ + Int debug_step = 0 ; /* debug loop counter */ +#endif /* NDEBUG */ + + /* === Initialization and clear mark ==================================== */ + + max_mark = INT_MAX - n_col ; /* INT_MAX defined in */ + tag_mark = clear_mark (0, max_mark, n_row, Row) ; + min_score = 0 ; + ngarbage = 0 ; + DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ; + + /* === Order the columns ================================================ */ + + for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */) + { + +#ifndef NDEBUG + if (debug_step % 100 == 0) + { + DEBUG2 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + else + { + DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ; + } + debug_step++ ; + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + + /* === Select pivot column, and order it ============================ */ + + /* make sure degree list isn't empty */ + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (head [min_score] >= EMPTY) ; + +#ifndef NDEBUG + for (debug_d = 0 ; debug_d < min_score ; debug_d++) + { + ASSERT (head [debug_d] == EMPTY) ; + } +#endif /* NDEBUG */ + + /* get pivot column from head of minimum degree list */ + while (head [min_score] == EMPTY && min_score < n_col) + { + min_score++ ; + } + pivot_col = head [min_score] ; + ASSERT (pivot_col >= 0 && pivot_col <= n_col) ; + next_col = Col [pivot_col].shared4.degree_next ; + head [min_score] = next_col ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = EMPTY ; + } + + ASSERT (COL_IS_ALIVE (pivot_col)) ; + + /* remember score for defrag check */ + pivot_col_score = Col [pivot_col].shared2.score ; + + /* the pivot column is the kth column in the pivot order */ + Col [pivot_col].shared2.order = k ; + + /* increment order count by column thickness */ + pivot_col_thickness = Col [pivot_col].shared1.thickness ; + k += pivot_col_thickness ; + ASSERT (pivot_col_thickness > 0) ; + DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ; + + /* === Garbage_collection, if necessary ============================= */ + + needed_memory = MIN (pivot_col_score, n_col - k) ; + if (pfree + needed_memory >= Alen) + { + pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; + ngarbage++ ; + /* after garbage collection we will have enough */ + ASSERT (pfree + needed_memory < Alen) ; + /* garbage collection has wiped out the Row[].shared2.mark array */ + tag_mark = clear_mark (0, max_mark, n_row, Row) ; + +#ifndef NDEBUG + debug_matrix (n_row, n_col, Row, Col, A) ; +#endif /* NDEBUG */ + } + + /* === Compute pivot row pattern ==================================== */ + + /* get starting location for this new merged row */ + pivot_row_start = pfree ; + + /* initialize new row counts to zero */ + pivot_row_degree = 0 ; + + /* tag pivot column as having been visited so it isn't included */ + /* in merged pivot row */ + Col [pivot_col].shared1.thickness = -pivot_col_thickness ; + + /* pivot row is the union of all rows in the pivot column pattern */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ; + /* skip if row is dead */ + if (ROW_IS_ALIVE (row)) + { + rp = &A [Row [row].start] ; + rp_end = rp + Row [row].length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + /* add the column, if alive and untagged */ + col_thickness = Col [col].shared1.thickness ; + if (col_thickness > 0 && COL_IS_ALIVE (col)) + { + /* tag column in pivot row */ + Col [col].shared1.thickness = -col_thickness ; + ASSERT (pfree < Alen) ; + /* place column in pivot row */ + A [pfree++] = col ; + pivot_row_degree += col_thickness ; + } + } + } + } + + /* clear tag on pivot column */ + Col [pivot_col].shared1.thickness = pivot_col_thickness ; + max_deg = MAX (max_deg, pivot_row_degree) ; + +#ifndef NDEBUG + DEBUG3 (("check2\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Kill all rows used to construct pivot row ==================== */ + + /* also kill pivot row, temporarily */ + cp = &A [Col [pivot_col].start] ; + cp_end = cp + Col [pivot_col].length ; + while (cp < cp_end) + { + /* may be killing an already dead row */ + row = *cp++ ; + DEBUG3 (("Kill row in pivot col: %d\n", row)) ; + KILL_ROW (row) ; + } + + /* === Select a row index to use as the new pivot row =============== */ + + pivot_row_length = pfree - pivot_row_start ; + if (pivot_row_length > 0) + { + /* pick the "pivot" row arbitrarily (first row in col) */ + pivot_row = A [Col [pivot_col].start] ; + DEBUG3 (("Pivotal row is %d\n", pivot_row)) ; + } + else + { + /* there is no pivot row, since it is of zero length */ + pivot_row = EMPTY ; + ASSERT (pivot_row_length == 0) ; + } + ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ; + + /* === Approximate degree computation =============================== */ + + /* Here begins the computation of the approximate degree. The column */ + /* score is the sum of the pivot row "length", plus the size of the */ + /* set differences of each row in the column minus the pattern of the */ + /* pivot row itself. The column ("thickness") itself is also */ + /* excluded from the column score (we thus use an approximate */ + /* external degree). */ + + /* The time taken by the following code (compute set differences, and */ + /* add them up) is proportional to the size of the data structure */ + /* being scanned - that is, the sum of the sizes of each column in */ + /* the pivot row. Thus, the amortized time to compute a column score */ + /* is proportional to the size of that column (where size, in this */ + /* context, is the column "length", or the number of row indices */ + /* in that column). The number of row indices in a column is */ + /* monotonically non-decreasing, from the length of the original */ + /* column on input to colamd. */ + + /* === Compute set differences ====================================== */ + + DEBUG3 (("** Computing set differences phase. **\n")) ; + + /* pivot row is currently dead - it will be revived later. */ + + DEBUG3 (("Pivot row: ")) ; + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + DEBUG3 (("Col: %d\n", col)) ; + + /* clear tags used to construct pivot row pattern */ + col_thickness = -Col [col].shared1.thickness ; + ASSERT (col_thickness > 0) ; + Col [col].shared1.thickness = col_thickness ; + + /* === Remove column from degree list =========================== */ + + cur_score = Col [col].shared2.score ; + prev_col = Col [col].shared3.prev ; + next_col = Col [col].shared4.degree_next ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (cur_score >= EMPTY) ; + if (prev_col == EMPTY) + { + head [cur_score] = next_col ; + } + else + { + Col [prev_col].shared4.degree_next = next_col ; + } + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = prev_col ; + } + + /* === Scan the column ========================================== */ + + cp = &A [Col [col].start] ; + cp_end = cp + Col [col].length ; + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + continue ; + } + ASSERT (row != pivot_row) ; + set_difference = row_mark - tag_mark ; + /* check if the row has been seen yet */ + if (set_difference < 0) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + set_difference = Row [row].shared1.degree ; + } + /* subtract column thickness from this row's set difference */ + set_difference -= col_thickness ; + ASSERT (set_difference >= 0) ; + /* absorb this row if the set difference becomes zero */ + if (set_difference == 0 && aggressive) + { + DEBUG3 (("aggressive absorption. Row: %d\n", row)) ; + KILL_ROW (row) ; + } + else + { + /* save the new mark */ + Row [row].shared2.mark = set_difference + tag_mark ; + } + } + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k-pivot_row_degree, max_deg) ; +#endif /* NDEBUG */ + + /* === Add up set differences for each column ======================= */ + + DEBUG3 (("** Adding set differences phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + /* get a column */ + col = *rp++ ; + ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; + hash = 0 ; + cur_score = 0 ; + cp = &A [Col [col].start] ; + /* compact the column */ + new_cp = cp ; + cp_end = cp + Col [col].length ; + + DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ; + + while (cp < cp_end) + { + /* get a row */ + row = *cp++ ; + ASSERT(row >= 0 && row < n_row) ; + row_mark = Row [row].shared2.mark ; + /* skip if dead */ + if (ROW_IS_MARKED_DEAD (row_mark)) + { + DEBUG4 ((" Row %d, dead\n", row)) ; + continue ; + } + DEBUG4 ((" Row %d, set diff %d\n", row, row_mark-tag_mark)); + ASSERT (row_mark >= tag_mark) ; + /* compact the column */ + *new_cp++ = row ; + /* compute hash function */ + hash += row ; + /* add set difference */ + cur_score += row_mark - tag_mark ; + /* integer overflow... */ + cur_score = MIN (cur_score, n_col) ; + } + + /* recompute the column's length */ + Col [col].length = (Int) (new_cp - &A [Col [col].start]) ; + + /* === Further mass elimination ================================= */ + + if (Col [col].length == 0) + { + DEBUG4 (("further mass elimination. Col: %d\n", col)) ; + /* nothing left but the pivot row in this column */ + KILL_PRINCIPAL_COL (col) ; + pivot_row_degree -= Col [col].shared1.thickness ; + ASSERT (pivot_row_degree >= 0) ; + /* order it */ + Col [col].shared2.order = k ; + /* increment order count by column thickness */ + k += Col [col].shared1.thickness ; + } + else + { + /* === Prepare for supercolumn detection ==================== */ + + DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ; + + /* save score so far */ + Col [col].shared2.score = cur_score ; + + /* add column to hash table, for supercolumn detection */ + hash %= n_col + 1 ; + + DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ; + ASSERT (((Int) hash) <= n_col) ; + + head_column = head [hash] ; + if (head_column > EMPTY) + { + /* degree list "hash" is non-empty, use prev (shared3) of */ + /* first column in degree list as head of hash bucket */ + first_col = Col [head_column].shared3.headhash ; + Col [head_column].shared3.headhash = col ; + } + else + { + /* degree list "hash" is empty, use head as hash bucket */ + first_col = - (head_column + 2) ; + head [hash] = - (col + 2) ; + } + Col [col].shared4.hash_next = first_col ; + + /* save hash function in Col [col].shared3.hash */ + Col [col].shared3.hash = (Int) hash ; + ASSERT (COL_IS_ALIVE (col)) ; + } + } + + /* The approximate external column degree is now computed. */ + + /* === Supercolumn detection ======================================== */ + + DEBUG3 (("** Supercolumn detection phase. **\n")) ; + + detect_super_cols ( + +#ifndef NDEBUG + n_col, Row, +#endif /* NDEBUG */ + + Col, A, head, pivot_row_start, pivot_row_length) ; + + /* === Kill the pivotal column ====================================== */ + + KILL_PRINCIPAL_COL (pivot_col) ; + + /* === Clear mark =================================================== */ + + tag_mark = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ; + +#ifndef NDEBUG + DEBUG3 (("check3\n")) ; + debug_mark (n_row, Row, tag_mark, max_mark) ; +#endif /* NDEBUG */ + + /* === Finalize the new pivot row, and column scores ================ */ + + DEBUG3 (("** Finalize scores phase. **\n")) ; + + /* for each column in pivot row */ + rp = &A [pivot_row_start] ; + /* compact the pivot row */ + new_rp = rp ; + rp_end = rp + pivot_row_length ; + while (rp < rp_end) + { + col = *rp++ ; + /* skip dead columns */ + if (COL_IS_DEAD (col)) + { + continue ; + } + *new_rp++ = col ; + /* add new pivot row to column */ + A [Col [col].start + (Col [col].length++)] = pivot_row ; + + /* retrieve score so far and add on pivot row's degree. */ + /* (we wait until here for this in case the pivot */ + /* row's degree was reduced due to mass elimination). */ + cur_score = Col [col].shared2.score + pivot_row_degree ; + + /* calculate the max possible score as the number of */ + /* external columns minus the 'k' value minus the */ + /* columns thickness */ + max_score = n_col - k - Col [col].shared1.thickness ; + + /* make the score the external degree of the union-of-rows */ + cur_score -= Col [col].shared1.thickness ; + + /* make sure score is less or equal than the max score */ + cur_score = MIN (cur_score, max_score) ; + ASSERT (cur_score >= 0) ; + + /* store updated score */ + Col [col].shared2.score = cur_score ; + + /* === Place column back in degree list ========================= */ + + ASSERT (min_score >= 0) ; + ASSERT (min_score <= n_col) ; + ASSERT (cur_score >= 0) ; + ASSERT (cur_score <= n_col) ; + ASSERT (head [cur_score] >= EMPTY) ; + next_col = head [cur_score] ; + Col [col].shared4.degree_next = next_col ; + Col [col].shared3.prev = EMPTY ; + if (next_col != EMPTY) + { + Col [next_col].shared3.prev = col ; + } + head [cur_score] = col ; + + /* see if this score is less than current min */ + min_score = MIN (min_score, cur_score) ; + + } + +#ifndef NDEBUG + debug_deg_lists (n_row, n_col, Row, Col, head, + min_score, n_col2-k, max_deg) ; +#endif /* NDEBUG */ + + /* === Resurrect the new pivot row ================================== */ + + if (pivot_row_degree > 0) + { + /* update pivot row length to reflect any cols that were killed */ + /* during super-col detection and mass elimination */ + Row [pivot_row].start = pivot_row_start ; + Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ; + ASSERT (Row [pivot_row].length > 0) ; + Row [pivot_row].shared1.degree = pivot_row_degree ; + Row [pivot_row].shared2.mark = 0 ; + /* pivot row is no longer dead */ + + DEBUG1 (("Resurrect Pivot_row %d deg: %d\n", + pivot_row, pivot_row_degree)) ; + } + } + + /* === All principal columns have now been ordered ====================== */ + + return (ngarbage) ; +} + + +/* ========================================================================== */ +/* === order_children ======================================================= */ +/* ========================================================================== */ + +/* + The find_ordering routine has ordered all of the principal columns (the + representatives of the supercolumns). The non-principal columns have not + yet been ordered. This routine orders those columns by walking up the + parent tree (a column is a child of the column which absorbed it). The + final permutation vector is then placed in p [0 ... n_col-1], with p [0] + being the first column, and p [n_col-1] being the last. It doesn't look + like it at first glance, but be assured that this routine takes time linear + in the number of columns. Although not immediately obvious, the time + taken by this routine is O (n_col), that is, linear in the number of + columns. Not user-callable. +*/ + +PRIVATE void order_children +( + /* === Parameters ======================================================= */ + + Int n_col, /* number of columns of A */ + Colamd_Col Col [], /* of size n_col+1 */ + Int p [] /* p [0 ... n_col-1] is the column permutation*/ +) +{ + /* === Local variables ================================================== */ + + Int i ; /* loop counter for all columns */ + Int c ; /* column index */ + Int parent ; /* index of column's parent */ + Int order ; /* column's order */ + + /* === Order each non-principal column ================================== */ + + for (i = 0 ; i < n_col ; i++) + { + /* find an un-ordered non-principal column */ + ASSERT (COL_IS_DEAD (i)) ; + if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY) + { + parent = i ; + /* once found, find its principal parent */ + do + { + parent = Col [parent].shared1.parent ; + } while (!COL_IS_DEAD_PRINCIPAL (parent)) ; + + /* now, order all un-ordered non-principal columns along path */ + /* to this parent. collapse tree at the same time */ + c = i ; + /* get order of parent */ + order = Col [parent].shared2.order ; + + do + { + ASSERT (Col [c].shared2.order == EMPTY) ; + + /* order this column */ + Col [c].shared2.order = order++ ; + /* collaps tree */ + Col [c].shared1.parent = parent ; + + /* get immediate parent of this column */ + c = Col [c].shared1.parent ; + + /* continue until we hit an ordered column. There are */ + /* guarranteed not to be anymore unordered columns */ + /* above an ordered column */ + } while (Col [c].shared2.order == EMPTY) ; + + /* re-order the super_col parent to largest order for this group */ + Col [parent].shared2.order = order ; + } + } + + /* === Generate the permutation ========================================= */ + + for (c = 0 ; c < n_col ; c++) + { + p [Col [c].shared2.order] = c ; + } +} + + +/* ========================================================================== */ +/* === detect_super_cols ==================================================== */ +/* ========================================================================== */ + +/* + Detects supercolumns by finding matches between columns in the hash buckets. + Check amongst columns in the set A [row_start ... row_start + row_length-1]. + The columns under consideration are currently *not* in the degree lists, + and have already been placed in the hash buckets. + + The hash bucket for columns whose hash function is equal to h is stored + as follows: + + if head [h] is >= 0, then head [h] contains a degree list, so: + + head [h] is the first column in degree bucket h. + Col [head [h]].headhash gives the first column in hash bucket h. + + otherwise, the degree list is empty, and: + + -(head [h] + 2) is the first column in hash bucket h. + + For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous + column" pointer. Col [c].shared3.hash is used instead as the hash number + for that column. The value of Col [c].shared4.hash_next is the next column + in the same hash bucket. + + Assuming no, or "few" hash collisions, the time taken by this routine is + linear in the sum of the sizes (lengths) of each column whose score has + just been computed in the approximate degree computation. + Not user-callable. +*/ + +PRIVATE void detect_super_cols +( + /* === Parameters ======================================================= */ + +#ifndef NDEBUG + /* these two parameters are only needed when debugging is enabled: */ + Int n_col, /* number of columns of A */ + Colamd_Row Row [], /* of size n_row+1 */ +#endif /* NDEBUG */ + + Colamd_Col Col [], /* of size n_col+1 */ + Int A [], /* row indices of A */ + Int head [], /* head of degree lists and hash buckets */ + Int row_start, /* pointer to set of columns to check */ + Int row_length /* number of columns to check */ +) +{ + /* === Local variables ================================================== */ + + Int hash ; /* hash value for a column */ + Int *rp ; /* pointer to a row */ + Int c ; /* a column index */ + Int super_c ; /* column index of the column to absorb into */ + Int *cp1 ; /* column pointer for column super_c */ + Int *cp2 ; /* column pointer for column c */ + Int length ; /* length of column super_c */ + Int prev_c ; /* column preceding c in hash bucket */ + Int i ; /* loop counter */ + Int *rp_end ; /* pointer to the end of the row */ + Int col ; /* a column index in the row to check */ + Int head_column ; /* first column in hash bucket or degree list */ + Int first_col ; /* first column in hash bucket */ + + /* === Consider each column in the row ================================== */ + + rp = &A [row_start] ; + rp_end = rp + row_length ; + while (rp < rp_end) + { + col = *rp++ ; + if (COL_IS_DEAD (col)) + { + continue ; + } + + /* get hash number for this column */ + hash = Col [col].shared3.hash ; + ASSERT (hash <= n_col) ; + + /* === Get the first column in this hash bucket ===================== */ + + head_column = head [hash] ; + if (head_column > EMPTY) + { + first_col = Col [head_column].shared3.headhash ; + } + else + { + first_col = - (head_column + 2) ; + } + + /* === Consider each column in the hash bucket ====================== */ + + for (super_c = first_col ; super_c != EMPTY ; + super_c = Col [super_c].shared4.hash_next) + { + ASSERT (COL_IS_ALIVE (super_c)) ; + ASSERT (Col [super_c].shared3.hash == hash) ; + length = Col [super_c].length ; + + /* prev_c is the column preceding column c in the hash bucket */ + prev_c = super_c ; + + /* === Compare super_c with all columns after it ================ */ + + for (c = Col [super_c].shared4.hash_next ; + c != EMPTY ; c = Col [c].shared4.hash_next) + { + ASSERT (c != super_c) ; + ASSERT (COL_IS_ALIVE (c)) ; + ASSERT (Col [c].shared3.hash == hash) ; + + /* not identical if lengths or scores are different */ + if (Col [c].length != length || + Col [c].shared2.score != Col [super_c].shared2.score) + { + prev_c = c ; + continue ; + } + + /* compare the two columns */ + cp1 = &A [Col [super_c].start] ; + cp2 = &A [Col [c].start] ; + + for (i = 0 ; i < length ; i++) + { + /* the columns are "clean" (no dead rows) */ + ASSERT (ROW_IS_ALIVE (*cp1)) ; + ASSERT (ROW_IS_ALIVE (*cp2)) ; + /* row indices will same order for both supercols, */ + /* no gather scatter nessasary */ + if (*cp1++ != *cp2++) + { + break ; + } + } + + /* the two columns are different if the for-loop "broke" */ + if (i != length) + { + prev_c = c ; + continue ; + } + + /* === Got it! two columns are identical =================== */ + + ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ; + + Col [super_c].shared1.thickness += Col [c].shared1.thickness ; + Col [c].shared1.parent = super_c ; + KILL_NON_PRINCIPAL_COL (c) ; + /* order c later, in order_children() */ + Col [c].shared2.order = EMPTY ; + /* remove c from hash bucket */ + Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ; + } + } + + /* === Empty this hash bucket ======================================= */ + + if (head_column > EMPTY) + { + /* corresponding degree list "hash" is not empty */ + Col [head_column].shared3.headhash = EMPTY ; + } + else + { + /* corresponding degree list "hash" is empty */ + head [hash] = EMPTY ; + } + } +} + + +/* ========================================================================== */ +/* === garbage_collection =================================================== */ +/* ========================================================================== */ + +/* + Defragments and compacts columns and rows in the workspace A. Used when + all avaliable memory has been used while performing row merging. Returns + the index of the first free position in A, after garbage collection. The + time taken by this routine is linear is the size of the array A, which is + itself linear in the number of nonzeros in the input matrix. + Not user-callable. +*/ + +PRIVATE Int garbage_collection /* returns the new value of pfree */ +( + /* === Parameters ======================================================= */ + + Int n_row, /* number of rows */ + Int n_col, /* number of columns */ + Colamd_Row Row [], /* row info */ + Colamd_Col Col [], /* column info */ + Int A [], /* A [0 ... Alen-1] holds the matrix */ + Int *pfree /* &A [0] ... pfree is in use */ +) +{ + /* === Local variables ================================================== */ + + Int *psrc ; /* source pointer */ + Int *pdest ; /* destination pointer */ + Int j ; /* counter */ + Int r ; /* a row index */ + Int c ; /* a column index */ + Int length ; /* length of a row or column */ + +#ifndef NDEBUG + Int debug_rows ; + DEBUG2 (("Defrag..\n")) ; + for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; + debug_rows = 0 ; +#endif /* NDEBUG */ + + /* === Defragment the columns =========================================== */ + + pdest = &A[0] ; + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + psrc = &A [Col [c].start] ; + + /* move and compact the column */ + ASSERT (pdest <= psrc) ; + Col [c].start = (Int) (pdest - &A [0]) ; + length = Col [c].length ; + for (j = 0 ; j < length ; j++) + { + r = *psrc++ ; + if (ROW_IS_ALIVE (r)) + { + *pdest++ = r ; + } + } + Col [c].length = (Int) (pdest - &A [Col [c].start]) ; + } + } + + /* === Prepare to defragment the rows =================================== */ + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_DEAD (r) || (Row [r].length == 0)) + { + /* This row is already dead, or is of zero length. Cannot compact + * a row of zero length, so kill it. NOTE: in the current version, + * there are no zero-length live rows. Kill the row (for the first + * time, or again) just to be safe. */ + KILL_ROW (r) ; + } + else + { + /* save first column index in Row [r].shared2.first_column */ + psrc = &A [Row [r].start] ; + Row [r].shared2.first_column = *psrc ; + ASSERT (ROW_IS_ALIVE (r)) ; + /* flag the start of the row with the one's complement of row */ + *psrc = ONES_COMPLEMENT (r) ; +#ifndef NDEBUG + debug_rows++ ; +#endif /* NDEBUG */ + } + } + + /* === Defragment the rows ============================================== */ + + psrc = pdest ; + while (psrc < pfree) + { + /* find a negative number ... the start of a row */ + if (*psrc++ < 0) + { + psrc-- ; + /* get the row index */ + r = ONES_COMPLEMENT (*psrc) ; + ASSERT (r >= 0 && r < n_row) ; + /* restore first column index */ + *psrc = Row [r].shared2.first_column ; + ASSERT (ROW_IS_ALIVE (r)) ; + ASSERT (Row [r].length > 0) ; + /* move and compact the row */ + ASSERT (pdest <= psrc) ; + Row [r].start = (Int) (pdest - &A [0]) ; + length = Row [r].length ; + for (j = 0 ; j < length ; j++) + { + c = *psrc++ ; + if (COL_IS_ALIVE (c)) + { + *pdest++ = c ; + } + } + Row [r].length = (Int) (pdest - &A [Row [r].start]) ; + ASSERT (Row [r].length > 0) ; +#ifndef NDEBUG + debug_rows-- ; +#endif /* NDEBUG */ + } + } + /* ensure we found all the rows */ + ASSERT (debug_rows == 0) ; + + /* === Return the new value of pfree ==================================== */ + + return ((Int) (pdest - &A [0])) ; +} + + +/* ========================================================================== */ +/* === clear_mark =========================================================== */ +/* ========================================================================== */ + +/* + Clears the Row [].shared2.mark array, and returns the new tag_mark. + Return value is the new tag_mark. Not user-callable. +*/ + +PRIVATE Int clear_mark /* return the new value for tag_mark */ +( + /* === Parameters ======================================================= */ + + Int tag_mark, /* new value of tag_mark */ + Int max_mark, /* max allowed value of tag_mark */ + + Int n_row, /* number of rows in A */ + Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */ +) +{ + /* === Local variables ================================================== */ + + Int r ; + + if (tag_mark <= 0 || tag_mark >= max_mark) + { + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + Row [r].shared2.mark = 0 ; + } + } + tag_mark = 1 ; + } + + return (tag_mark) ; +} + + +/* ========================================================================== */ +/* === print_report ========================================================= */ +/* ========================================================================== */ + +PRIVATE void print_report +( + char *method, + Int stats [COLAMD_STATS] +) +{ + + Int i1, i2, i3 ; + + PRINTF (("\n%s version %d.%d, %s: ", method, + COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE)) ; + + if (!stats) + { + PRINTF (("No statistics available.\n")) ; + return ; + } + + i1 = stats [COLAMD_INFO1] ; + i2 = stats [COLAMD_INFO2] ; + i3 = stats [COLAMD_INFO3] ; + + if (stats [COLAMD_STATUS] >= 0) + { + PRINTF (("OK. ")) ; + } + else + { + PRINTF (("ERROR. ")) ; + } + + switch (stats [COLAMD_STATUS]) + { + + case COLAMD_OK_BUT_JUMBLED: + + PRINTF(("Matrix has unsorted or duplicate row indices.\n")) ; + + PRINTF(("%s: number of duplicate or out-of-order row indices: %d\n", + method, i3)) ; + + PRINTF(("%s: last seen duplicate or out-of-order row index: %d\n", + method, INDEX (i2))) ; + + PRINTF(("%s: last seen in column: %d", + method, INDEX (i1))) ; + + /* no break - fall through to next case instead */ + + case COLAMD_OK: + + PRINTF(("\n")) ; + + PRINTF(("%s: number of dense or empty rows ignored: %d\n", + method, stats [COLAMD_DENSE_ROW])) ; + + PRINTF(("%s: number of dense or empty columns ignored: %d\n", + method, stats [COLAMD_DENSE_COL])) ; + + PRINTF(("%s: number of garbage collections performed: %d\n", + method, stats [COLAMD_DEFRAG_COUNT])) ; + break ; + + case COLAMD_ERROR_A_not_present: + + PRINTF(("Array A (row indices of matrix) not present.\n")) ; + break ; + + case COLAMD_ERROR_p_not_present: + + PRINTF(("Array p (column pointers for matrix) not present.\n")) ; + break ; + + case COLAMD_ERROR_nrow_negative: + + PRINTF(("Invalid number of rows (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_ncol_negative: + + PRINTF(("Invalid number of columns (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_nnz_negative: + + PRINTF(("Invalid number of nonzero entries (%d).\n", i1)) ; + break ; + + case COLAMD_ERROR_p0_nonzero: + + PRINTF(("Invalid column pointer, p [0] = %d, must be zero.\n", i1)); + break ; + + case COLAMD_ERROR_A_too_small: + + PRINTF(("Array A too small.\n")) ; + PRINTF((" Need Alen >= %d, but given only Alen = %d.\n", + i1, i2)) ; + break ; + + case COLAMD_ERROR_col_length_negative: + + PRINTF + (("Column %d has a negative number of nonzero entries (%d).\n", + INDEX (i1), i2)) ; + break ; + + case COLAMD_ERROR_row_index_out_of_bounds: + + PRINTF + (("Row index (row %d) out of bounds (%d to %d) in column %d.\n", + INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ; + break ; + + case COLAMD_ERROR_out_of_memory: + + PRINTF(("Out of memory.\n")) ; + break ; + + /* v2.4: internal-error case deleted */ + } +} + + + + +/* ========================================================================== */ +/* === colamd debugging routines ============================================ */ +/* ========================================================================== */ + +/* When debugging is disabled, the remainder of this file is ignored. */ + +#ifndef NDEBUG + + +/* ========================================================================== */ +/* === debug_structures ===================================================== */ +/* ========================================================================== */ + +/* + At this point, all empty rows and columns are dead. All live columns + are "clean" (containing no dead rows) and simplicial (no supercolumns + yet). Rows may contain dead columns, but all live rows contain at + least one live column. +*/ + +PRIVATE void debug_structures +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [], + Int n_col2 +) +{ + /* === Local variables ================================================== */ + + Int i ; + Int c ; + Int *cp ; + Int *cp_end ; + Int len ; + Int score ; + Int r ; + Int *rp ; + Int *rp_end ; + Int deg ; + + /* === Check A, Row, and Col ============================================ */ + + for (c = 0 ; c < n_col ; c++) + { + if (COL_IS_ALIVE (c)) + { + len = Col [c].length ; + score = Col [c].shared2.score ; + DEBUG4 (("initial live col %5d %5d %5d\n", c, len, score)) ; + ASSERT (len > 0) ; + ASSERT (score >= 0) ; + ASSERT (Col [c].shared1.thickness == 1) ; + cp = &A [Col [c].start] ; + cp_end = cp + len ; + while (cp < cp_end) + { + r = *cp++ ; + ASSERT (ROW_IS_ALIVE (r)) ; + } + } + else + { + i = Col [c].shared2.order ; + ASSERT (i >= n_col2 && i < n_col) ; + } + } + + for (r = 0 ; r < n_row ; r++) + { + if (ROW_IS_ALIVE (r)) + { + i = 0 ; + len = Row [r].length ; + deg = Row [r].shared1.degree ; + ASSERT (len > 0) ; + ASSERT (deg > 0) ; + rp = &A [Row [r].start] ; + rp_end = rp + len ; + while (rp < rp_end) + { + c = *rp++ ; + if (COL_IS_ALIVE (c)) + { + i++ ; + } + } + ASSERT (i > 0) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_deg_lists ====================================================== */ +/* ========================================================================== */ + +/* + Prints the contents of the degree lists. Counts the number of columns + in the degree list and compares it to the total it should have. Also + checks the row degrees. +*/ + +PRIVATE void debug_deg_lists +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int head [], + Int min_score, + Int should, + Int max_deg +) +{ + /* === Local variables ================================================== */ + + Int deg ; + Int col ; + Int have ; + Int row ; + + /* === Check the degree lists =========================================== */ + + if (n_col > 10000 && colamd_debug <= 0) + { + return ; + } + have = 0 ; + DEBUG4 (("Degree lists: %d\n", min_score)) ; + for (deg = 0 ; deg <= n_col ; deg++) + { + col = head [deg] ; + if (col == EMPTY) + { + continue ; + } + DEBUG4 (("%d:", deg)) ; + while (col != EMPTY) + { + DEBUG4 ((" %d", col)) ; + have += Col [col].shared1.thickness ; + ASSERT (COL_IS_ALIVE (col)) ; + col = Col [col].shared4.degree_next ; + } + DEBUG4 (("\n")) ; + } + DEBUG4 (("should %d have %d\n", should, have)) ; + ASSERT (should == have) ; + + /* === Check the row degrees ============================================ */ + + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (row = 0 ; row < n_row ; row++) + { + if (ROW_IS_ALIVE (row)) + { + ASSERT (Row [row].shared1.degree <= max_deg) ; + } + } +} + + +/* ========================================================================== */ +/* === debug_mark =========================================================== */ +/* ========================================================================== */ + +/* + Ensures that the tag_mark is less that the maximum and also ensures that + each entry in the mark array is less than the tag mark. +*/ + +PRIVATE void debug_mark +( + /* === Parameters ======================================================= */ + + Int n_row, + Colamd_Row Row [], + Int tag_mark, + Int max_mark +) +{ + /* === Local variables ================================================== */ + + Int r ; + + /* === Check the Row marks ============================================== */ + + ASSERT (tag_mark > 0 && tag_mark <= max_mark) ; + if (n_row > 10000 && colamd_debug <= 0) + { + return ; + } + for (r = 0 ; r < n_row ; r++) + { + ASSERT (Row [r].shared2.mark < tag_mark) ; + } +} + + +/* ========================================================================== */ +/* === debug_matrix ========================================================= */ +/* ========================================================================== */ + +/* + Prints out the contents of the columns and the rows. +*/ + +PRIVATE void debug_matrix +( + /* === Parameters ======================================================= */ + + Int n_row, + Int n_col, + Colamd_Row Row [], + Colamd_Col Col [], + Int A [] +) +{ + /* === Local variables ================================================== */ + + Int r ; + Int c ; + Int *rp ; + Int *rp_end ; + Int *cp ; + Int *cp_end ; + + /* === Dump the rows and columns of the matrix ========================== */ + + if (colamd_debug < 3) + { + return ; + } + DEBUG3 (("DUMP MATRIX:\n")) ; + for (r = 0 ; r < n_row ; r++) + { + DEBUG3 (("Row %d alive? %d\n", r, ROW_IS_ALIVE (r))) ; + if (ROW_IS_DEAD (r)) + { + continue ; + } + DEBUG3 (("start %d length %d degree %d\n", + Row [r].start, Row [r].length, Row [r].shared1.degree)) ; + rp = &A [Row [r].start] ; + rp_end = rp + Row [r].length ; + while (rp < rp_end) + { + c = *rp++ ; + DEBUG4 ((" %d col %d\n", COL_IS_ALIVE (c), c)) ; + } + } + + for (c = 0 ; c < n_col ; c++) + { + DEBUG3 (("Col %d alive? %d\n", c, COL_IS_ALIVE (c))) ; + if (COL_IS_DEAD (c)) + { + continue ; + } + DEBUG3 (("start %d length %d shared1 %d shared2 %d\n", + Col [c].start, Col [c].length, + Col [c].shared1.thickness, Col [c].shared2.score)) ; + cp = &A [Col [c].start] ; + cp_end = cp + Col [c].length ; + while (cp < cp_end) + { + r = *cp++ ; + DEBUG4 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ; + } + } +} + +PRIVATE void colamd_get_debug +( + char *method +) +{ + FILE *f ; + colamd_debug = 0 ; /* no debug printing */ + f = fopen ("debug", "r") ; + if (f == (FILE *) NULL) + { + colamd_debug = 0 ; + } + else + { + fscanf (f, "%d", &colamd_debug) ; + fclose (f) ; + } + DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", + method, colamd_debug)) ; +} + +#endif /* NDEBUG */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.h b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.h new file mode 100644 index 000000000..511735e5c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/colamd/colamd.h @@ -0,0 +1,69 @@ +/* colamd.h */ + +/* Written by Andrew Makhorin . */ + +#ifndef COLAMD_H +#define COLAMD_H + +#define _GLPSTD_STDIO +#include "env.h" + +#define COLAMD_DATE "Nov 1, 2007" +#define COLAMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) +#define COLAMD_MAIN_VERSION 2 +#define COLAMD_SUB_VERSION 7 +#define COLAMD_SUBSUB_VERSION 1 +#define COLAMD_VERSION \ + COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION) + +#define COLAMD_KNOBS 20 +#define COLAMD_STATS 20 +#define COLAMD_DENSE_ROW 0 +#define COLAMD_DENSE_COL 1 +#define COLAMD_AGGRESSIVE 2 +#define COLAMD_DEFRAG_COUNT 2 +#define COLAMD_STATUS 3 +#define COLAMD_INFO1 4 +#define COLAMD_INFO2 5 +#define COLAMD_INFO3 6 + +#define COLAMD_OK (0) +#define COLAMD_OK_BUT_JUMBLED (1) +#define COLAMD_ERROR_A_not_present (-1) +#define COLAMD_ERROR_p_not_present (-2) +#define COLAMD_ERROR_nrow_negative (-3) +#define COLAMD_ERROR_ncol_negative (-4) +#define COLAMD_ERROR_nnz_negative (-5) +#define COLAMD_ERROR_p0_nonzero (-6) +#define COLAMD_ERROR_A_too_small (-7) +#define COLAMD_ERROR_col_length_negative (-8) +#define COLAMD_ERROR_row_index_out_of_bounds (-9) +#define COLAMD_ERROR_out_of_memory (-10) +#define COLAMD_ERROR_internal_error (-999) + +#define colamd_recommended _glp_colamd_recommended +size_t colamd_recommended(int nnz, int n_row, int n_col); + +#define colamd_set_defaults _glp_colamd_set_defaults +void colamd_set_defaults(double knobs [COLAMD_KNOBS]); + +#define colamd _glp_colamd +int colamd(int n_row, int n_col, int Alen, int A[], int p[], + double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS]); + +#define symamd _glp_symamd +int symamd(int n, int A[], int p[], int perm[], + double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS], + void *(*allocate)(size_t, size_t), void(*release)(void *)); + +#define colamd_report _glp_colamd_report +void colamd_report(int stats[COLAMD_STATS]); + +#define symamd_report _glp_symamd_report +void symamd_report(int stats[COLAMD_STATS]); + +#define colamd_printf xprintf + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.c new file mode 100644 index 000000000..dece376ca --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.c @@ -0,0 +1,544 @@ +/* bfd.c (LP basis factorization driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2007, 2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "bfd.h" +#include "fhvint.h" +#include "scfint.h" +#ifdef GLP_DEBUG +#include "glpspm.h" +#endif + +struct BFD +{ /* LP basis factorization driver */ + int valid; + /* factorization is valid only if this flag is set */ + int type; + /* type of factorization used: + 0 - interface not established yet + 1 - FHV-factorization + 2 - Schur-complement-based factorization */ + union + { void *none; /* type = 0 */ + FHVINT *fhvi; /* type = 1 */ + SCFINT *scfi; /* type = 2 */ + } u; + /* interface to factorization of LP basis */ + glp_bfcp parm; + /* factorization control parameters */ +#ifdef GLP_DEBUG + SPM *B; + /* current basis (for testing/debugging only) */ +#endif + int upd_cnt; + /* factorization update count */ +#if 1 /* 21/IV-2014 */ + double b_norm; + /* 1-norm of matrix B */ + double i_norm; + /* estimated 1-norm of matrix inv(B) */ +#endif +}; + +BFD *bfd_create_it(void) +{ /* create LP basis factorization */ + BFD *bfd; +#ifdef GLP_DEBUG + xprintf("bfd_create_it: warning: debugging version used\n"); +#endif + bfd = talloc(1, BFD); + bfd->valid = 0; + bfd->type = 0; + bfd->u.none = NULL; + bfd_set_bfcp(bfd, NULL); +#ifdef GLP_DEBUG + bfd->B = NULL; +#endif + bfd->upd_cnt = 0; + return bfd; +} + +#if 0 /* 08/III-2014 */ +void bfd_set_parm(BFD *bfd, const void *parm) +{ /* change LP basis factorization control parameters */ + memcpy(&bfd->parm, parm, sizeof(glp_bfcp)); + return; +} +#endif + +void bfd_get_bfcp(BFD *bfd, void /* glp_bfcp */ *parm) +{ /* retrieve LP basis factorization control parameters */ + memcpy(parm, &bfd->parm, sizeof(glp_bfcp)); + return; +} + +void bfd_set_bfcp(BFD *bfd, const void /* glp_bfcp */ *parm) +{ /* change LP basis factorization control parameters */ + if (parm == NULL) + { /* reset to default */ + memset(&bfd->parm, 0, sizeof(glp_bfcp)); + bfd->parm.type = GLP_BF_LUF + GLP_BF_FT; + bfd->parm.piv_tol = 0.10; + bfd->parm.piv_lim = 4; + bfd->parm.suhl = 1; + bfd->parm.eps_tol = DBL_EPSILON; + bfd->parm.nfs_max = 100; + bfd->parm.nrs_max = 70; + } + else + memcpy(&bfd->parm, parm, sizeof(glp_bfcp)); + return; +} + +#if 1 /* 21/IV-2014 */ +struct bfd_info +{ BFD *bfd; + int (*col)(void *info, int j, int ind[], double val[]); + void *info; +}; + +static int bfd_col(void *info_, int j, int ind[], double val[]) +{ struct bfd_info *info = info_; + int t, len; + double sum; + len = info->col(info->info, j, ind, val); + sum = 0.0; + for (t = 1; t <= len; t++) + { if (val[t] >= 0.0) + sum += val[t]; + else + sum -= val[t]; + } + if (info->bfd->b_norm < sum) + info->bfd->b_norm = sum; + return len; +} +#endif + +int bfd_factorize(BFD *bfd, int m, /*const int bh[],*/ int (*col1) + (void *info, int j, int ind[], double val[]), void *info1) +{ /* compute LP basis factorization */ +#if 1 /* 21/IV-2014 */ + struct bfd_info info; +#endif + int type, ret; + /*xassert(bh == bh);*/ + /* invalidate current factorization */ + bfd->valid = 0; + /* determine required factorization type */ + switch (bfd->parm.type) + { case GLP_BF_LUF + GLP_BF_FT: + type = 1; + break; + case GLP_BF_LUF + GLP_BF_BG: + case GLP_BF_LUF + GLP_BF_GR: + case GLP_BF_BTF + GLP_BF_BG: + case GLP_BF_BTF + GLP_BF_GR: + type = 2; + break; + default: + xassert(bfd != bfd); + } + /* delete factorization interface, if necessary */ + switch (bfd->type) + { case 0: + break; + case 1: + if (type != 1) + { bfd->type = 0; + fhvint_delete(bfd->u.fhvi); + bfd->u.fhvi = NULL; + } + break; + case 2: + if (type != 2) + { bfd->type = 0; + scfint_delete(bfd->u.scfi); + bfd->u.scfi = NULL; + } + break; + default: + xassert(bfd != bfd); + } + /* establish factorization interface, if necessary */ + if (bfd->type == 0) + { switch (type) + { case 1: + bfd->type = 1; + xassert(bfd->u.fhvi == NULL); + bfd->u.fhvi = fhvint_create(); + break; + case 2: + bfd->type = 2; + xassert(bfd->u.scfi == NULL); + if (!(bfd->parm.type & GLP_BF_BTF)) + bfd->u.scfi = scfint_create(1); + else + bfd->u.scfi = scfint_create(2); + break; + default: + xassert(type != type); + } + } + /* try to compute factorization */ +#if 1 /* 21/IV-2014 */ + bfd->b_norm = bfd->i_norm = 0.0; + info.bfd = bfd; + info.col = col1; + info.info = info1; +#endif + switch (bfd->type) + { case 1: + bfd->u.fhvi->lufi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.fhvi->lufi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.fhvi->lufi->sgf_suhl = bfd->parm.suhl; + bfd->u.fhvi->lufi->sgf_eps_tol = bfd->parm.eps_tol; + bfd->u.fhvi->nfs_max = bfd->parm.nfs_max; + ret = fhvint_factorize(bfd->u.fhvi, m, bfd_col, &info); +#if 1 /* FIXME */ + if (ret == 0) + bfd->i_norm = fhvint_estimate(bfd->u.fhvi); + else + ret = BFD_ESING; +#endif + break; + case 2: + if (bfd->u.scfi->scf.type == 1) + { bfd->u.scfi->u.lufi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.scfi->u.lufi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.scfi->u.lufi->sgf_suhl = bfd->parm.suhl; + bfd->u.scfi->u.lufi->sgf_eps_tol = bfd->parm.eps_tol; + } + else if (bfd->u.scfi->scf.type == 2) + { bfd->u.scfi->u.btfi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.scfi->u.btfi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.scfi->u.btfi->sgf_suhl = bfd->parm.suhl; + bfd->u.scfi->u.btfi->sgf_eps_tol = bfd->parm.eps_tol; + } + else + xassert(bfd != bfd); + bfd->u.scfi->nn_max = bfd->parm.nrs_max; + ret = scfint_factorize(bfd->u.scfi, m, bfd_col, &info); +#if 1 /* FIXME */ + if (ret == 0) + bfd->i_norm = scfint_estimate(bfd->u.scfi); + else + ret = BFD_ESING; +#endif + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + /* save specified LP basis */ + if (bfd->B != NULL) + spm_delete_mat(bfd->B); + bfd->B = spm_create_mat(m, m); + { int *ind = talloc(1+m, int); + double *val = talloc(1+m, double); + int j, k, len; + for (j = 1; j <= m; j++) + { len = col(info, j, ind, val); + for (k = 1; k <= len; k++) + spm_new_elem(bfd->B, ind[k], j, val[k]); + } + tfree(ind); + tfree(val); + } +#endif + if (ret == 0) + { /* factorization has been successfully computed */ + double cond; + bfd->valid = 1; +#ifdef GLP_DEBUG + cond = bfd_condest(bfd); + if (cond > 1e9) + xprintf("bfd_factorize: warning: cond(B) = %g\n", cond); +#endif + } +#ifdef GLP_DEBUG + xprintf("bfd_factorize: m = %d; ret = %d\n", m, ret); +#endif + bfd->upd_cnt = 0; + return ret; +} + +#if 0 /* 21/IV-2014 */ +double bfd_estimate(BFD *bfd) +{ /* estimate 1-norm of inv(B) */ + double norm; + xassert(bfd->valid); + xassert(bfd->upd_cnt == 0); + switch (bfd->type) + { case 1: + norm = fhvint_estimate(bfd->u.fhvi); + break; + case 2: + norm = scfint_estimate(bfd->u.scfi); + break; + default: + xassert(bfd != bfd); + } + return norm; +} +#endif + +#if 1 /* 21/IV-2014 */ +double bfd_condest(BFD *bfd) +{ /* estimate condition of B */ + double cond; + xassert(bfd->valid); + /*xassert(bfd->upd_cnt == 0);*/ + cond = bfd->b_norm * bfd->i_norm; + if (cond < 1.0) + cond = 1.0; + return cond; +} +#endif + +void bfd_ftran(BFD *bfd, double x[]) +{ /* perform forward transformation (solve system B * x = b) */ +#ifdef GLP_DEBUG + SPM *B = bfd->B; + int m = B->m; + double *b = talloc(1+m, double); + SPME *e; + int k; + double s, relerr, maxerr; + for (k = 1; k <= m; k++) + b[k] = x[k]; +#endif + xassert(bfd->valid); + switch (bfd->type) + { case 1: + fhvint_ftran(bfd->u.fhvi, x); + break; + case 2: + scfint_ftran(bfd->u.scfi, x); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + maxerr = 0.0; + for (k = 1; k <= m; k++) + { s = 0.0; + for (e = B->row[k]; e != NULL; e = e->r_next) + s += e->val * x[e->j]; + relerr = (b[k] - s) / (1.0 + fabs(b[k])); + if (maxerr < relerr) + maxerr = relerr; + } + if (maxerr > 1e-8) + xprintf("bfd_ftran: maxerr = %g; relative error too large\n", + maxerr); + tfree(b); +#endif + return; +} + +#if 1 /* 30/III-2016 */ +void bfd_ftran_s(BFD *bfd, FVS *x) +{ /* sparse version of bfd_ftran */ + /* (sparse mode is not implemented yet) */ + int n = x->n; + int *ind = x->ind; + double *vec = x->vec; + int j, nnz = 0; + bfd_ftran(bfd, vec); + for (j = n; j >= 1; j--) + { if (vec[j] != 0.0) + ind[++nnz] = j; + } + x->nnz = nnz; + return; +} +#endif + +void bfd_btran(BFD *bfd, double x[]) +{ /* perform backward transformation (solve system B'* x = b) */ +#ifdef GLP_DEBUG + SPM *B = bfd->B; + int m = B->m; + double *b = talloc(1+m, double); + SPME *e; + int k; + double s, relerr, maxerr; + for (k = 1; k <= m; k++) + b[k] = x[k]; +#endif + xassert(bfd->valid); + switch (bfd->type) + { case 1: + fhvint_btran(bfd->u.fhvi, x); + break; + case 2: + scfint_btran(bfd->u.scfi, x); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + maxerr = 0.0; + for (k = 1; k <= m; k++) + { s = 0.0; + for (e = B->col[k]; e != NULL; e = e->c_next) + s += e->val * x[e->i]; + relerr = (b[k] - s) / (1.0 + fabs(b[k])); + if (maxerr < relerr) + maxerr = relerr; + } + if (maxerr > 1e-8) + xprintf("bfd_btran: maxerr = %g; relative error too large\n", + maxerr); + tfree(b); +#endif + return; +} + +#if 1 /* 30/III-2016 */ +void bfd_btran_s(BFD *bfd, FVS *x) +{ /* sparse version of bfd_btran */ + /* (sparse mode is not implemented yet) */ + int n = x->n; + int *ind = x->ind; + double *vec = x->vec; + int j, nnz = 0; + bfd_btran(bfd, vec); + for (j = n; j >= 1; j--) + { if (vec[j] != 0.0) + ind[++nnz] = j; + } + x->nnz = nnz; + return; +} +#endif + +int bfd_update(BFD *bfd, int j, int len, const int ind[], const double + val[]) +{ /* update LP basis factorization */ + int ret; + xassert(bfd->valid); + switch (bfd->type) + { case 1: + ret = fhvint_update(bfd->u.fhvi, j, len, ind, val); +#if 1 /* FIXME */ + switch (ret) + { case 0: + break; + case 1: + ret = BFD_ESING; + break; + case 2: + case 3: + ret = BFD_ECOND; + break; + case 4: + ret = BFD_ELIMIT; + break; + case 5: + ret = BFD_ECHECK; + break; + default: + xassert(ret != ret); + } +#endif + break; + case 2: + switch (bfd->parm.type & 0x0F) + { case GLP_BF_BG: + ret = scfint_update(bfd->u.scfi, 1, j, len, ind, val); + break; + case GLP_BF_GR: + ret = scfint_update(bfd->u.scfi, 2, j, len, ind, val); + break; + default: + xassert(bfd != bfd); + } +#if 1 /* FIXME */ + switch (ret) + { case 0: + break; + case 1: + ret = BFD_ELIMIT; + break; + case 2: + ret = BFD_ECOND; + break; + default: + xassert(ret != ret); + } +#endif + break; + default: + xassert(bfd != bfd); + } + if (ret != 0) + { /* updating factorization failed */ + bfd->valid = 0; + } +#ifdef GLP_DEBUG + /* save updated LP basis */ + { SPME *e; + int k; + for (e = bfd->B->col[j]; e != NULL; e = e->c_next) + e->val = 0.0; + spm_drop_zeros(bfd->B, 0.0); + for (k = 1; k <= len; k++) + spm_new_elem(bfd->B, ind[k], j, val[k]); + } +#endif + if (ret == 0) + bfd->upd_cnt++; + return ret; +} + +int bfd_get_count(BFD *bfd) +{ /* determine factorization update count */ + return bfd->upd_cnt; +} + +void bfd_delete_it(BFD *bfd) +{ /* delete LP basis factorization */ + switch (bfd->type) + { case 0: + break; + case 1: + fhvint_delete(bfd->u.fhvi); + break; + case 2: + scfint_delete(bfd->u.scfi); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + if (bfd->B != NULL) + spm_delete_mat(bfd->B); +#endif + tfree(bfd); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.h new file mode 100644 index 000000000..0ef4c0238 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfd.h @@ -0,0 +1,107 @@ +/* bfd.h (LP basis factorization driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BFD_H +#define BFD_H + +#if 1 /* 30/III-2016 */ +#include "fvs.h" +#endif + +typedef struct BFD BFD; + +/* return codes: */ +#define BFD_ESING 1 /* singular matrix */ +#define BFD_ECOND 2 /* ill-conditioned matrix */ +#define BFD_ECHECK 3 /* insufficient accuracy */ +#define BFD_ELIMIT 4 /* update limit reached */ +#if 0 /* 05/III-2014 */ +#define BFD_EROOM 5 /* SVA overflow */ +#endif + +#define bfd_create_it _glp_bfd_create_it +BFD *bfd_create_it(void); +/* create LP basis factorization */ + +#if 0 /* 08/III-2014 */ +#define bfd_set_parm _glp_bfd_set_parm +void bfd_set_parm(BFD *bfd, const void *parm); +/* change LP basis factorization control parameters */ +#endif + +#define bfd_get_bfcp _glp_bfd_get_bfcp +void bfd_get_bfcp(BFD *bfd, void /* glp_bfcp */ *parm); +/* retrieve LP basis factorization control parameters */ + +#define bfd_set_bfcp _glp_bfd_set_bfcp +void bfd_set_bfcp(BFD *bfd, const void /* glp_bfcp */ *parm); +/* change LP basis factorization control parameters */ + +#define bfd_factorize _glp_bfd_factorize +int bfd_factorize(BFD *bfd, int m, /*const int bh[],*/ int (*col) + (void *info, int j, int ind[], double val[]), void *info); +/* compute LP basis factorization */ + +#if 1 /* 21/IV-2014 */ +#define bfd_condest _glp_bfd_condest +double bfd_condest(BFD *bfd); +/* estimate condition of B */ +#endif + +#define bfd_ftran _glp_bfd_ftran +void bfd_ftran(BFD *bfd, double x[]); +/* perform forward transformation (solve system B*x = b) */ + +#if 1 /* 30/III-2016 */ +#define bfd_ftran_s _glp_bfd_ftran_s +void bfd_ftran_s(BFD *bfd, FVS *x); +/* sparse version of bfd_ftran */ +#endif + +#define bfd_btran _glp_bfd_btran +void bfd_btran(BFD *bfd, double x[]); +/* perform backward transformation (solve system B'*x = b) */ + +#if 1 /* 30/III-2016 */ +#define bfd_btran_s _glp_bfd_btran_s +void bfd_btran_s(BFD *bfd, FVS *x); +/* sparse version of bfd_btran */ +#endif + +#define bfd_update _glp_bfd_update +int bfd_update(BFD *bfd, int j, int len, const int ind[], const double + val[]); +/* update LP basis factorization */ + +#define bfd_get_count _glp_bfd_get_count +int bfd_get_count(BFD *bfd); +/* determine factorization update count */ + +#define bfd_delete_it _glp_bfd_delete_it +void bfd_delete_it(BFD *bfd); +/* delete LP basis factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.c new file mode 100644 index 000000000..565480b6f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.c @@ -0,0 +1,89 @@ +/* bfx.c (LP basis factorization driver, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "bfx.h" +#include "env.h" +#include "lux.h" + +struct BFX +{ int valid; + LUX *lux; +}; + +BFX *bfx_create_binv(void) +{ /* create factorization of the basis matrix */ + BFX *bfx; + bfx = xmalloc(sizeof(BFX)); + bfx->valid = 0; + bfx->lux = NULL; + return bfx; +} + +int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info) +{ /* compute factorization of the basis matrix */ + int ret; + xassert(m > 0); + if (binv->lux != NULL && binv->lux->n != m) + { lux_delete(binv->lux); + binv->lux = NULL; + } + if (binv->lux == NULL) + binv->lux = lux_create(m); + ret = lux_decomp(binv->lux, col, info); + binv->valid = (ret == 0); + return ret; +} + +void bfx_ftran(BFX *binv, mpq_t x[], int save) +{ /* perform forward transformation (FTRAN) */ + xassert(binv->valid); + lux_solve(binv->lux, 0, x); + xassert(save == save); + return; +} + +void bfx_btran(BFX *binv, mpq_t x[]) +{ /* perform backward transformation (BTRAN) */ + xassert(binv->valid); + lux_solve(binv->lux, 1, x); + return; +} + +int bfx_update(BFX *binv, int j) +{ /* update factorization of the basis matrix */ + xassert(binv->valid); + xassert(1 <= j && j <= binv->lux->n); + return 1; +} + +void bfx_delete_binv(BFX *binv) +{ /* delete factorization of the basis matrix */ + if (binv->lux != NULL) + lux_delete(binv->lux); + xfree(binv); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.h new file mode 100644 index 000000000..c67d5ea44 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/bfx.h @@ -0,0 +1,67 @@ +/* bfx.h (LP basis factorization driver, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BFX_H +#define BFX_H + +#include "mygmp.h" + +typedef struct BFX BFX; + +#define bfx_create_binv _glp_bfx_create_binv +BFX *bfx_create_binv(void); +/* create factorization of the basis matrix */ + +#define bfx_is_valid _glp_bfx_is_valid +int bfx_is_valid(BFX *binv); +/* check if factorization is valid */ + +#define bfx_invalidate _glp_bfx_invalidate +void bfx_invalidate(BFX *binv); +/* invalidate factorization of the basis matrix */ + +#define bfx_factorize _glp_bfx_factorize +int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info); +/* compute factorization of the basis matrix */ + +#define bfx_ftran _glp_bfx_ftran +void bfx_ftran(BFX *binv, mpq_t x[], int save); +/* perform forward transformation (FTRAN) */ + +#define bfx_btran _glp_bfx_btran +void bfx_btran(BFX *binv, mpq_t x[]); +/* perform backward transformation (BTRAN) */ + +#define bfx_update _glp_bfx_update +int bfx_update(BFX *binv, int j); +/* update factorization of the basis matrix */ + +#define bfx_delete_binv _glp_bfx_delete_binv +void bfx_delete_binv(BFX *binv); +/* delete factorization of the basis matrix */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/draft.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/draft.h new file mode 100644 index 000000000..cefd21248 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/draft.h @@ -0,0 +1,22 @@ +/* draft.h */ + +/* (reserved for copyright notice) */ + +#ifndef DRAFT_H +#define DRAFT_H + +#if 1 /* 28/III-2016 */ +#define GLP_UNDOC 1 +#endif +#include "glpk.h" + +#if 1 /* 28/XI-2009 */ +int _glp_analyze_row(glp_prob *P, int len, const int ind[], + const double val[], int type, double rhs, double eps, int *_piv, + double *_x, double *_dx, double *_y, double *_dy, double *_dz); +/* simulate one iteration of dual simplex method */ +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi06.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi06.c new file mode 100644 index 000000000..a31e39681 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi06.c @@ -0,0 +1,860 @@ +/* glpapi06.c (simplex method routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" +#include "npp.h" +#if 0 /* 07/XI-2015 */ +#include "glpspx.h" +#else +#include "simplex.h" +#define spx_dual spy_dual +#endif + +/*********************************************************************** +* NAME +* +* glp_simplex - solve LP problem with the simplex method +* +* SYNOPSIS +* +* int glp_simplex(glp_prob *P, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_simplex is a driver to the LP solver based on the +* simplex method. This routine retrieves problem data from the +* specified problem object, calls the solver to solve the problem +* instance, and stores results of computations back into the problem +* object. +* +* The simplex solver has a set of control parameters. Values of the +* control parameters can be passed in a structure glp_smcp, which the +* parameter parm points to. +* +* The parameter parm can be specified as NULL, in which case the LP +* solver uses default settings. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBADB +* Unable to start the search, because the initial basis specified +* in the problem object is invalid--the number of basic (auxiliary +* and structural) variables is not the same as the number of rows in +* the problem object. +* +* GLP_ESING +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is singular within the working precision. +* +* GLP_ECOND +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is ill-conditioned, i.e. its condition number +* is too large. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EOBJLL +* The search was prematurely terminated, because the objective +* function being maximized has reached its lower limit and continues +* decreasing (dual simplex only). +* +* GLP_EOBJUL +* The search was prematurely terminated, because the objective +* function being minimized has reached its upper limit and continues +* increasing (dual simplex only). +* +* GLP_EITLIM +* The search was prematurely terminated, because the simplex +* iteration limit has been exceeded. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ENOPFS +* The LP problem instance has no primal feasible solution (only if +* the LP presolver is used). +* +* GLP_ENODFS +* The LP problem instance has no dual feasible solution (only if the +* LP presolver is used). */ + +static void trivial_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve trivial LP which has empty constraint matrix */ + GLPROW *row; + GLPCOL *col; + int i, j; + double p_infeas, d_infeas, zeta; + P->valid = 0; + P->pbs_stat = P->dbs_stat = GLP_FEAS; + P->obj_val = P->c0; + P->some = 0; + p_infeas = d_infeas = 0.0; + /* make all auxiliary variables basic */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + row->stat = GLP_BS; + row->prim = row->dual = 0.0; + /* check primal feasibility */ + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + { /* row has lower bound */ + if (row->lb > + parm->tol_bnd) + { P->pbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth != GLP_PRIMAL) + P->some = i; + } + if (p_infeas < + row->lb) + p_infeas = + row->lb; + } + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + { /* row has upper bound */ + if (row->ub < - parm->tol_bnd) + { P->pbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth != GLP_PRIMAL) + P->some = i; + } + if (p_infeas < - row->ub) + p_infeas = - row->ub; + } + } + /* determine scale factor for the objective row */ + zeta = 1.0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (zeta < fabs(col->coef)) zeta = fabs(col->coef); + } + zeta = (P->dir == GLP_MIN ? +1.0 : -1.0) / zeta; + /* make all structural variables non-basic */ + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_FR) + col->stat = GLP_NF, col->prim = 0.0; + else if (col->type == GLP_LO) +lo: col->stat = GLP_NL, col->prim = col->lb; + else if (col->type == GLP_UP) +up: col->stat = GLP_NU, col->prim = col->ub; + else if (col->type == GLP_DB) + { if (zeta * col->coef > 0.0) + goto lo; + else if (zeta * col->coef < 0.0) + goto up; + else if (fabs(col->lb) <= fabs(col->ub)) + goto lo; + else + goto up; + } + else if (col->type == GLP_FX) + col->stat = GLP_NS, col->prim = col->lb; + col->dual = col->coef; + P->obj_val += col->coef * col->prim; + /* check dual feasibility */ + if (col->type == GLP_FR || col->type == GLP_LO) + { /* column has no upper bound */ + if (zeta * col->dual < - parm->tol_dj) + { P->dbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth == GLP_PRIMAL) + P->some = P->m + j; + } + if (d_infeas < - zeta * col->dual) + d_infeas = - zeta * col->dual; + } + if (col->type == GLP_FR || col->type == GLP_UP) + { /* column has no lower bound */ + if (zeta * col->dual > + parm->tol_dj) + { P->dbs_stat = GLP_NOFEAS; + if (P->some == 0 && parm->meth == GLP_PRIMAL) + P->some = P->m + j; + } + if (d_infeas < + zeta * col->dual) + d_infeas = + zeta * col->dual; + } + } + /* simulate the simplex solver output */ + if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) + { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, + P->obj_val, parm->meth == GLP_PRIMAL ? p_infeas : d_infeas); + } + if (parm->msg_lev >= GLP_MSG_ALL && parm->out_dly == 0) + { if (P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS) + xprintf("OPTIMAL SOLUTION FOUND\n"); + else if (P->pbs_stat == GLP_NOFEAS) + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); + else if (parm->meth == GLP_PRIMAL) + xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); + else + xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); + } + return; +} + +static int solve_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve LP directly without using the preprocessor */ + int ret; + if (!glp_bf_exists(P)) + { ret = glp_factorize(P); + if (ret == 0) + ; + else if (ret == GLP_EBADB) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: initial basis is invalid\n"); + } + else if (ret == GLP_ESING) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: initial basis is singular\n"); + } + else if (ret == GLP_ECOND) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf( + "glp_simplex: initial basis is ill-conditioned\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + } + if (parm->meth == GLP_PRIMAL) + ret = spx_primal(P, parm); + else if (parm->meth == GLP_DUALP) + { ret = spx_dual(P, parm); + if (ret == GLP_EFAIL && P->valid) + ret = spx_primal(P, parm); + } + else if (parm->meth == GLP_DUAL) + ret = spx_dual(P, parm); + else + xassert(parm != parm); +done: return ret; +} + +static int preprocess_and_solve_lp(glp_prob *P, const glp_smcp *parm) +{ /* solve LP using the preprocessor */ + NPP *npp; + glp_prob *lp = NULL; + glp_bfcp bfcp; + int ret; + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Preprocessing...\n"); + /* create preprocessor workspace */ + npp = npp_create_wksp(); + /* load original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_SOL, GLP_OFF); + /* process LP prior to applying primal/dual simplex method */ + ret = npp_simplex(npp, parm); + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); + } + else if (ret == GLP_ENODFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + /* build transformed LP */ + lp = glp_create_prob(); + npp_build_prob(npp, lp); + /* if the transformed LP is empty, it has empty solution, which + is optimal */ + if (lp->m == 0 && lp->n == 0) + { lp->pbs_stat = lp->dbs_stat = GLP_FEAS; + lp->obj_val = lp->c0; + if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) + { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, + lp->obj_val, 0.0); + } + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL SOLUTION FOUND BY LP PREPROCESSOR\n"); + goto post; + } + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("%d row%s, %d column%s, %d non-zero%s\n", + lp->m, lp->m == 1 ? "" : "s", lp->n, lp->n == 1 ? "" : "s", + lp->nnz, lp->nnz == 1 ? "" : "s"); + } + /* inherit basis factorization control parameters */ + glp_get_bfcp(P, &bfcp); + glp_set_bfcp(lp, &bfcp); + /* scale the transformed problem */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_scale_prob(lp, GLP_SF_AUTO); + env->term_out = term_out; + } + /* build advanced initial basis */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_adv_basis(lp, 0); + env->term_out = term_out; + } + /* solve the transformed LP */ + lp->it_cnt = P->it_cnt; + ret = solve_lp(lp, parm); + P->it_cnt = lp->it_cnt; + /* only optimal solution can be postprocessed */ + if (!(ret == 0 && lp->pbs_stat == GLP_FEAS && lp->dbs_stat == + GLP_FEAS)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: unable to recover undefined or non-op" + "timal solution\n"); + if (ret == 0) + { if (lp->pbs_stat == GLP_NOFEAS) + ret = GLP_ENOPFS; + else if (lp->dbs_stat == GLP_NOFEAS) + ret = GLP_ENODFS; + else + xassert(lp != lp); + } + goto done; + } +post: /* postprocess solution from the transformed LP */ + npp_postprocess(npp, lp); + /* the transformed LP is no longer needed */ + glp_delete_prob(lp), lp = NULL; + /* store solution to the original problem */ + npp_unload_sol(npp, P); + /* the original LP has been successfully solved */ + ret = 0; +done: /* delete the transformed LP, if it exists */ + if (lp != NULL) glp_delete_prob(lp); + /* delete preprocessor workspace */ + npp_delete_wksp(npp); + return ret; +} + +int glp_simplex(glp_prob *P, const glp_smcp *parm) +{ /* solve LP problem with the simplex method */ + glp_smcp _parm; + int i, j, ret; + /* check problem object */ +#if 0 /* 04/IV-2016 */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_simplex: P = %p; invalid problem object\n", P); +#endif + if (P->tree != NULL && P->tree->reason != 0) + xerror("glp_simplex: operation not allowed\n"); + /* check control parameters */ + if (parm == NULL) + parm = &_parm, glp_init_smcp((glp_smcp *)parm); + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL || + parm->msg_lev == GLP_MSG_DBG)) + xerror("glp_simplex: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->meth == GLP_PRIMAL || + parm->meth == GLP_DUALP || + parm->meth == GLP_DUAL)) + xerror("glp_simplex: meth = %d; invalid parameter\n", + parm->meth); + if (!(parm->pricing == GLP_PT_STD || + parm->pricing == GLP_PT_PSE)) + xerror("glp_simplex: pricing = %d; invalid parameter\n", + parm->pricing); + if (!(parm->r_test == GLP_RT_STD || +#if 1 /* 16/III-2016 */ + parm->r_test == GLP_RT_FLIP || +#endif + parm->r_test == GLP_RT_HAR)) + xerror("glp_simplex: r_test = %d; invalid parameter\n", + parm->r_test); + if (!(0.0 < parm->tol_bnd && parm->tol_bnd < 1.0)) + xerror("glp_simplex: tol_bnd = %g; invalid parameter\n", + parm->tol_bnd); + if (!(0.0 < parm->tol_dj && parm->tol_dj < 1.0)) + xerror("glp_simplex: tol_dj = %g; invalid parameter\n", + parm->tol_dj); + if (!(0.0 < parm->tol_piv && parm->tol_piv < 1.0)) + xerror("glp_simplex: tol_piv = %g; invalid parameter\n", + parm->tol_piv); + if (parm->it_lim < 0) + xerror("glp_simplex: it_lim = %d; invalid parameter\n", + parm->it_lim); + if (parm->tm_lim < 0) + xerror("glp_simplex: tm_lim = %d; invalid parameter\n", + parm->tm_lim); +#if 0 /* 15/VII-2017 */ + if (parm->out_frq < 1) +#else + if (parm->out_frq < 0) +#endif + xerror("glp_simplex: out_frq = %d; invalid parameter\n", + parm->out_frq); + if (parm->out_dly < 0) + xerror("glp_simplex: out_dly = %d; invalid parameter\n", + parm->out_dly); + if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) + xerror("glp_simplex: presolve = %d; invalid parameter\n", + parm->presolve); +#if 1 /* 11/VII-2017 */ + if (!(parm->excl == GLP_ON || parm->excl == GLP_OFF)) + xerror("glp_simplex: excl = %d; invalid parameter\n", + parm->excl); + if (!(parm->shift == GLP_ON || parm->shift == GLP_OFF)) + xerror("glp_simplex: shift = %d; invalid parameter\n", + parm->shift); + if (!(parm->aorn == GLP_USE_AT || parm->aorn == GLP_USE_NT)) + xerror("glp_simplex: aorn = %d; invalid parameter\n", + parm->aorn); +#endif + /* basic solution is currently undefined */ + P->pbs_stat = P->dbs_stat = GLP_UNDEF; + P->obj_val = 0.0; + P->some = 0; + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: row %d: lb = %g, ub = %g; incorrec" + "t bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_simplex: column %d: lb = %g, ub = %g; incor" + "rect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* solve LP problem */ + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("GLPK Simplex Optimizer, v%s\n", glp_version()); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + } + if (P->nnz == 0) + trivial_lp(P, parm), ret = 0; + else if (!parm->presolve) + ret = solve_lp(P, parm); + else + ret = preprocess_and_solve_lp(P, parm); +done: /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_smcp - initialize simplex method control parameters +* +* SYNOPSIS +* +* void glp_init_smcp(glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_init_smcp initializes control parameters, which are +* used by the simplex solver, with default values. +* +* Default values of the control parameters are stored in a glp_smcp +* structure, which the parameter parm points to. */ + +void glp_init_smcp(glp_smcp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->meth = GLP_PRIMAL; + parm->pricing = GLP_PT_PSE; + parm->r_test = GLP_RT_HAR; + parm->tol_bnd = 1e-7; + parm->tol_dj = 1e-7; +#if 0 /* 07/XI-2015 */ + parm->tol_piv = 1e-10; +#else + parm->tol_piv = 1e-9; +#endif + parm->obj_ll = -DBL_MAX; + parm->obj_ul = +DBL_MAX; + parm->it_lim = INT_MAX; + parm->tm_lim = INT_MAX; +#if 0 /* 15/VII-2017 */ + parm->out_frq = 500; +#else + parm->out_frq = 5000; /* 5 seconds */ +#endif + parm->out_dly = 0; + parm->presolve = GLP_OFF; +#if 1 /* 11/VII-2017 */ + parm->excl = GLP_ON; + parm->shift = GLP_ON; + parm->aorn = GLP_USE_NT; +#endif + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_status - retrieve generic status of basic solution +* +* SYNOPSIS +* +* int glp_get_status(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_status reports the generic status of the basic +* solution for the specified problem object as follows: +* +* GLP_OPT - solution is optimal; +* GLP_FEAS - solution is feasible; +* GLP_INFEAS - solution is infeasible; +* GLP_NOFEAS - problem has no feasible solution; +* GLP_UNBND - problem has unbounded solution; +* GLP_UNDEF - solution is undefined. */ + +int glp_get_status(glp_prob *lp) +{ int status; + status = glp_get_prim_stat(lp); + switch (status) + { case GLP_FEAS: + switch (glp_get_dual_stat(lp)) + { case GLP_FEAS: + status = GLP_OPT; + break; + case GLP_NOFEAS: + status = GLP_UNBND; + break; + case GLP_UNDEF: + case GLP_INFEAS: + status = status; + break; + default: + xassert(lp != lp); + } + break; + case GLP_UNDEF: + case GLP_INFEAS: + case GLP_NOFEAS: + status = status; + break; + default: + xassert(lp != lp); + } + return status; +} + +/*********************************************************************** +* NAME +* +* glp_get_prim_stat - retrieve status of primal basic solution +* +* SYNOPSIS +* +* int glp_get_prim_stat(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_prim_stat reports the status of the primal basic +* solution for the specified problem object as follows: +* +* GLP_UNDEF - primal solution is undefined; +* GLP_FEAS - primal solution is feasible; +* GLP_INFEAS - primal solution is infeasible; +* GLP_NOFEAS - no primal feasible solution exists. */ + +int glp_get_prim_stat(glp_prob *lp) +{ int pbs_stat = lp->pbs_stat; + return pbs_stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_dual_stat - retrieve status of dual basic solution +* +* SYNOPSIS +* +* int glp_get_dual_stat(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_dual_stat reports the status of the dual basic +* solution for the specified problem object as follows: +* +* GLP_UNDEF - dual solution is undefined; +* GLP_FEAS - dual solution is feasible; +* GLP_INFEAS - dual solution is infeasible; +* GLP_NOFEAS - no dual feasible solution exists. */ + +int glp_get_dual_stat(glp_prob *lp) +{ int dbs_stat = lp->dbs_stat; + return dbs_stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_obj_val - retrieve objective value (basic solution) +* +* SYNOPSIS +* +* double glp_get_obj_val(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_obj_val returns value of the objective function +* for basic solution. */ + +double glp_get_obj_val(glp_prob *lp) +{ /*struct LPXCPS *cps = lp->cps;*/ + double z; + z = lp->obj_val; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_stat - retrieve row status +* +* SYNOPSIS +* +* int glp_get_row_stat(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_stat returns current status assigned to the +* auxiliary variable associated with i-th row as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable on its lower bound; +* GLP_NU - non-basic variable on its upper bound; +* GLP_NF - non-basic free (unbounded) variable; +* GLP_NS - non-basic fixed variable. */ + +int glp_get_row_stat(glp_prob *lp, int i) +{ if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_stat: i = %d; row number out of range\n", + i); + return lp->row[i]->stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_prim - retrieve row primal value (basic solution) +* +* SYNOPSIS +* +* double glp_get_row_prim(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_prim returns primal value of the auxiliary +* variable associated with i-th row. */ + +double glp_get_row_prim(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double prim; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_prim: i = %d; row number out of range\n", + i); + prim = lp->row[i]->prim; + /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ + return prim; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_dual - retrieve row dual value (basic solution) +* +* SYNOPSIS +* +* double glp_get_row_dual(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_dual returns dual value (i.e. reduced cost) +* of the auxiliary variable associated with i-th row. */ + +double glp_get_row_dual(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dual; + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_dual: i = %d; row number out of range\n", + i); + dual = lp->row[i]->dual; + /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ + return dual; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_stat - retrieve column status +* +* SYNOPSIS +* +* int glp_get_col_stat(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_stat returns current status assigned to the +* structural variable associated with j-th column as follows: +* +* GLP_BS - basic variable; +* GLP_NL - non-basic variable on its lower bound; +* GLP_NU - non-basic variable on its upper bound; +* GLP_NF - non-basic free (unbounded) variable; +* GLP_NS - non-basic fixed variable. */ + +int glp_get_col_stat(glp_prob *lp, int j) +{ if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_stat: j = %d; column number out of range\n" + , j); + return lp->col[j]->stat; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_prim - retrieve column primal value (basic solution) +* +* SYNOPSIS +* +* double glp_get_col_prim(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_prim returns primal value of the structural +* variable associated with j-th column. */ + +double glp_get_col_prim(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double prim; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_prim: j = %d; column number out of range\n" + , j); + prim = lp->col[j]->prim; + /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ + return prim; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_dual - retrieve column dual value (basic solution) +* +* SYNOPSIS +* +* double glp_get_col_dual(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_dual returns dual value (i.e. reduced cost) +* of the structural variable associated with j-th column. */ + +double glp_get_col_dual(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dual; + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_dual: j = %d; column number out of range\n" + , j); + dual = lp->col[j]->dual; + /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ + return dual; +} + +/*********************************************************************** +* NAME +* +* glp_get_unbnd_ray - determine variable causing unboundedness +* +* SYNOPSIS +* +* int glp_get_unbnd_ray(glp_prob *lp); +* +* RETURNS +* +* The routine glp_get_unbnd_ray returns the number k of a variable, +* which causes primal or dual unboundedness. If 1 <= k <= m, it is +* k-th auxiliary variable, and if m+1 <= k <= m+n, it is (k-m)-th +* structural variable, where m is the number of rows, n is the number +* of columns in the problem object. If such variable is not defined, +* the routine returns 0. +* +* COMMENTS +* +* If it is not exactly known which version of the simplex solver +* detected unboundedness, i.e. whether the unboundedness is primal or +* dual, it is sufficient to check the status of the variable reported +* with the routine glp_get_row_stat or glp_get_col_stat. If the +* variable is non-basic, the unboundedness is primal, otherwise, if +* the variable is basic, the unboundedness is dual (the latter case +* means that the problem has no primal feasible dolution). */ + +int glp_get_unbnd_ray(glp_prob *lp) +{ int k; + k = lp->some; + xassert(k >= 0); + if (k > lp->m + lp->n) k = 0; + return k; +} + +#if 1 /* 08/VIII-2013 */ +int glp_get_it_cnt(glp_prob *P) +{ /* get simplex solver iteration count */ + return P->it_cnt; +} +#endif + +#if 1 /* 08/VIII-2013 */ +void glp_set_it_cnt(glp_prob *P, int it_cnt) +{ /* set simplex solver iteration count */ + P->it_cnt = it_cnt; + return; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi07.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi07.c new file mode 100644 index 000000000..9ac294bdd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi07.c @@ -0,0 +1,499 @@ +/* glpapi07.c (exact simplex solver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "draft.h" +#include "glpssx.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_exact - solve LP problem in exact arithmetic +* +* SYNOPSIS +* +* int glp_exact(glp_prob *lp, const glp_smcp *parm); +* +* DESCRIPTION +* +* The routine glp_exact is a tentative implementation of the primal +* two-phase simplex method based on exact (rational) arithmetic. It is +* similar to the routine glp_simplex, however, for all internal +* computations it uses arithmetic of rational numbers, which is exact +* in mathematical sense, i.e. free of round-off errors unlike floating +* point arithmetic. +* +* Note that the routine glp_exact uses inly two control parameters +* passed in the structure glp_smcp, namely, it_lim and tm_lim. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBADB +* Unable to start the search, because the initial basis specified +* in the problem object is invalid--the number of basic (auxiliary +* and structural) variables is not the same as the number of rows in +* the problem object. +* +* GLP_ESING +* Unable to start the search, because the basis matrix correspodning +* to the initial basis is exactly singular. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds. +* +* GLP_EFAIL +* The problem has no rows/columns. +* +* GLP_EITLIM +* The search was prematurely terminated, because the simplex +* iteration limit has been exceeded. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. */ + +static void set_d_eps(mpq_t x, double val) +{ /* convert double val to rational x obtaining a more adequate + fraction than provided by mpq_set_d due to allowing a small + approximation error specified by a given relative tolerance; + for example, mpq_set_d would give the following + 1/3 ~= 0.333333333333333314829616256247391... -> + -> 6004799503160661/18014398509481984 + while this routine gives exactly 1/3 */ + int s, n, j; + double f, p, q, eps = 1e-9; + mpq_t temp; + xassert(-DBL_MAX <= val && val <= +DBL_MAX); +#if 1 /* 30/VII-2008 */ + if (val == floor(val)) + { /* if val is integral, do not approximate */ + mpq_set_d(x, val); + goto done; + } +#endif + if (val > 0.0) + s = +1; + else if (val < 0.0) + s = -1; + else + { mpq_set_si(x, 0, 1); + goto done; + } + f = frexp(fabs(val), &n); + /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ + fp2rat(f, 0.1 * eps, &p, &q); + /* f ~= p / q, where p and q are integers */ + mpq_init(temp); + mpq_set_d(x, p); + mpq_set_d(temp, q); + mpq_div(x, x, temp); + mpq_set_si(temp, 1, 1); + for (j = 1; j <= abs(n); j++) + mpq_add(temp, temp, temp); + if (n > 0) + mpq_mul(x, x, temp); + else if (n < 0) + mpq_div(x, x, temp); + mpq_clear(temp); + if (s < 0) mpq_neg(x, x); + /* check that the desired tolerance has been attained */ + xassert(fabs(val - mpq_get_d(x)) <= eps * (1.0 + fabs(val))); +done: return; +} + +static void load_data(SSX *ssx, glp_prob *lp) +{ /* load LP problem data into simplex solver workspace */ + int m = ssx->m; + int n = ssx->n; + int nnz = ssx->A_ptr[n+1]-1; + int j, k, type, loc, len, *ind; + double lb, ub, coef, *val; + xassert(lp->m == m); + xassert(lp->n == n); + xassert(lp->nnz == nnz); + /* types and bounds of rows and columns */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + { type = lp->row[k]->type; + lb = lp->row[k]->lb; + ub = lp->row[k]->ub; + } + else + { type = lp->col[k-m]->type; + lb = lp->col[k-m]->lb; + ub = lp->col[k-m]->ub; + } + switch (type) + { case GLP_FR: type = SSX_FR; break; + case GLP_LO: type = SSX_LO; break; + case GLP_UP: type = SSX_UP; break; + case GLP_DB: type = SSX_DB; break; + case GLP_FX: type = SSX_FX; break; + default: xassert(type != type); + } + ssx->type[k] = type; + set_d_eps(ssx->lb[k], lb); + set_d_eps(ssx->ub[k], ub); + } + /* optimization direction */ + switch (lp->dir) + { case GLP_MIN: ssx->dir = SSX_MIN; break; + case GLP_MAX: ssx->dir = SSX_MAX; break; + default: xassert(lp != lp); + } + /* objective coefficients */ + for (k = 0; k <= m+n; k++) + { if (k == 0) + coef = lp->c0; + else if (k <= m) + coef = 0.0; + else + coef = lp->col[k-m]->coef; + set_d_eps(ssx->coef[k], coef); + } + /* constraint coefficients */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + loc = 0; + for (j = 1; j <= n; j++) + { ssx->A_ptr[j] = loc+1; + len = glp_get_mat_col(lp, j, ind, val); + for (k = 1; k <= len; k++) + { loc++; + ssx->A_ind[loc] = ind[k]; + set_d_eps(ssx->A_val[loc], val[k]); + } + } + xassert(loc == nnz); + xfree(ind); + xfree(val); + return; +} + +static int load_basis(SSX *ssx, glp_prob *lp) +{ /* load current LP basis into simplex solver workspace */ + int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + int *stat = ssx->stat; + int *Q_row = ssx->Q_row; + int *Q_col = ssx->Q_col; + int i, j, k; + xassert(lp->m == m); + xassert(lp->n == n); + /* statuses of rows and columns */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + stat[k] = lp->row[k]->stat; + else + stat[k] = lp->col[k-m]->stat; + switch (stat[k]) + { case GLP_BS: + stat[k] = SSX_BS; + break; + case GLP_NL: + stat[k] = SSX_NL; + xassert(type[k] == SSX_LO || type[k] == SSX_DB); + break; + case GLP_NU: + stat[k] = SSX_NU; + xassert(type[k] == SSX_UP || type[k] == SSX_DB); + break; + case GLP_NF: + stat[k] = SSX_NF; + xassert(type[k] == SSX_FR); + break; + case GLP_NS: + stat[k] = SSX_NS; + xassert(type[k] == SSX_FX); + break; + default: + xassert(stat != stat); + } + } + /* build permutation matix Q */ + i = j = 0; + for (k = 1; k <= m+n; k++) + { if (stat[k] == SSX_BS) + { i++; + if (i > m) return 1; + Q_row[k] = i, Q_col[i] = k; + } + else + { j++; + if (j > n) return 1; + Q_row[k] = m+j, Q_col[m+j] = k; + } + } + xassert(i == m && j == n); + return 0; +} + +int glp_exact(glp_prob *lp, const glp_smcp *parm) +{ glp_smcp _parm; + SSX *ssx; + int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int i, j, k, type, pst, dst, ret, stat; + double lb, ub, prim, dual, sum; + if (parm == NULL) + parm = &_parm, glp_init_smcp((glp_smcp *)parm); + /* check control parameters */ +#if 1 /* 25/XI-2017 */ + switch (parm->msg_lev) + { case GLP_MSG_OFF: + case GLP_MSG_ERR: + case GLP_MSG_ON: + case GLP_MSG_ALL: + case GLP_MSG_DBG: + break; + default: + xerror("glp_exact: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + } +#endif + if (parm->it_lim < 0) + xerror("glp_exact: it_lim = %d; invalid parameter\n", + parm->it_lim); + if (parm->tm_lim < 0) + xerror("glp_exact: tm_lim = %d; invalid parameter\n", + parm->tm_lim); + /* the problem must have at least one row and one column */ + if (!(m > 0 && n > 0)) +#if 0 /* 25/XI-2017 */ + { xprintf("glp_exact: problem has no rows/columns\n"); +#else + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_exact: problem has no rows/columns\n"); +#endif + return GLP_EFAIL; + } +#if 1 + /* basic solution is currently undefined */ + lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; + lp->obj_val = 0.0; + lp->some = 0; +#endif + /* check that all double-bounded variables have correct bounds */ + for (k = 1; k <= m+n; k++) + { if (k <= m) + { type = lp->row[k]->type; + lb = lp->row[k]->lb; + ub = lp->row[k]->ub; + } + else + { type = lp->col[k-m]->type; + lb = lp->col[k-m]->lb; + ub = lp->col[k-m]->ub; + } + if (type == GLP_DB && lb >= ub) +#if 0 /* 25/XI-2017 */ + { xprintf("glp_exact: %s %d has invalid bounds\n", + k <= m ? "row" : "column", k <= m ? k : k-m); +#else + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_exact: %s %d has invalid bounds\n", + k <= m ? "row" : "column", k <= m ? k : k-m); +#endif + return GLP_EBOUND; + } + } + /* create the simplex solver workspace */ +#if 1 /* 25/XI-2017 */ + if (parm->msg_lev >= GLP_MSG_ALL) + { +#endif + xprintf("glp_exact: %d rows, %d columns, %d non-zeros\n", + m, n, nnz); +#ifdef HAVE_GMP + xprintf("GNU MP bignum library is being used\n"); +#else + xprintf("GLPK bignum module is being used\n"); + xprintf("(Consider installing GNU MP to attain a much better perf" + "ormance.)\n"); +#endif +#if 1 /* 25/XI-2017 */ + } +#endif + ssx = ssx_create(m, n, nnz); + /* load LP problem data into the workspace */ + load_data(ssx, lp); + /* load current LP basis into the workspace */ + if (load_basis(ssx, lp)) +#if 0 /* 25/XI-2017 */ + { xprintf("glp_exact: initial LP basis is invalid\n"); +#else + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_exact: initial LP basis is invalid\n"); +#endif + ret = GLP_EBADB; + goto done; + } +#if 0 + /* inherit some control parameters from the LP object */ + ssx->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); + ssx->it_cnt = lpx_get_int_parm(lp, LPX_K_ITCNT); + ssx->tm_lim = lpx_get_real_parm(lp, LPX_K_TMLIM); +#else +#if 1 /* 25/XI-2017 */ + ssx->msg_lev = parm->msg_lev; +#endif + ssx->it_lim = parm->it_lim; + ssx->it_cnt = lp->it_cnt; + ssx->tm_lim = (double)parm->tm_lim / 1000.0; +#endif + ssx->out_frq = 5.0; + ssx->tm_beg = xtime(); +#if 0 /* 10/VI-2013 */ + ssx->tm_lag = xlset(0); +#else + ssx->tm_lag = 0.0; +#endif + /* solve LP */ + ret = ssx_driver(ssx); +#if 0 + /* copy back some statistics to the LP object */ + lpx_set_int_parm(lp, LPX_K_ITLIM, ssx->it_lim); + lpx_set_int_parm(lp, LPX_K_ITCNT, ssx->it_cnt); + lpx_set_real_parm(lp, LPX_K_TMLIM, ssx->tm_lim); +#else + lp->it_cnt = ssx->it_cnt; +#endif + /* analyze the return code */ + switch (ret) + { case 0: + /* optimal solution found */ + ret = 0; + pst = dst = GLP_FEAS; + break; + case 1: + /* problem has no feasible solution */ + ret = 0; + pst = GLP_NOFEAS, dst = GLP_INFEAS; + break; + case 2: + /* problem has unbounded solution */ + ret = 0; + pst = GLP_FEAS, dst = GLP_NOFEAS; +#if 1 + xassert(1 <= ssx->q && ssx->q <= n); + lp->some = ssx->Q_col[m + ssx->q]; + xassert(1 <= lp->some && lp->some <= m+n); +#endif + break; + case 3: + /* iteration limit exceeded (phase I) */ + ret = GLP_EITLIM; + pst = dst = GLP_INFEAS; + break; + case 4: + /* iteration limit exceeded (phase II) */ + ret = GLP_EITLIM; + pst = GLP_FEAS, dst = GLP_INFEAS; + break; + case 5: + /* time limit exceeded (phase I) */ + ret = GLP_ETMLIM; + pst = dst = GLP_INFEAS; + break; + case 6: + /* time limit exceeded (phase II) */ + ret = GLP_ETMLIM; + pst = GLP_FEAS, dst = GLP_INFEAS; + break; + case 7: + /* initial basis matrix is singular */ + ret = GLP_ESING; + goto done; + default: + xassert(ret != ret); + } + /* store final basic solution components into LP object */ + lp->pbs_stat = pst; + lp->dbs_stat = dst; + sum = lp->c0; + for (k = 1; k <= m+n; k++) + { if (ssx->stat[k] == SSX_BS) + { i = ssx->Q_row[k]; /* x[k] = xB[i] */ + xassert(1 <= i && i <= m); + stat = GLP_BS; + prim = mpq_get_d(ssx->bbar[i]); + dual = 0.0; + } + else + { j = ssx->Q_row[k] - m; /* x[k] = xN[j] */ + xassert(1 <= j && j <= n); + switch (ssx->stat[k]) + { case SSX_NF: + stat = GLP_NF; + prim = 0.0; + break; + case SSX_NL: + stat = GLP_NL; + prim = mpq_get_d(ssx->lb[k]); + break; + case SSX_NU: + stat = GLP_NU; + prim = mpq_get_d(ssx->ub[k]); + break; + case SSX_NS: + stat = GLP_NS; + prim = mpq_get_d(ssx->lb[k]); + break; + default: + xassert(ssx != ssx); + } + dual = mpq_get_d(ssx->cbar[j]); + } + if (k <= m) + { glp_set_row_stat(lp, k, stat); + lp->row[k]->prim = prim; + lp->row[k]->dual = dual; + } + else + { glp_set_col_stat(lp, k-m, stat); + lp->col[k-m]->prim = prim; + lp->col[k-m]->dual = dual; + sum += lp->col[k-m]->coef * prim; + } + } + lp->obj_val = sum; +done: /* delete the simplex solver workspace */ + ssx_delete(ssx); +#if 1 /* 23/XI-2015 */ + xassert(gmp_pool_count() == 0); + gmp_free_mem(); +#endif + /* return to the application program */ + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi08.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi08.c new file mode 100644 index 000000000..652292cbb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi08.c @@ -0,0 +1,388 @@ +/* glpapi08.c (interior-point method routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpipm.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* glp_interior - solve LP problem with the interior-point method +* +* SYNOPSIS +* +* int glp_interior(glp_prob *P, const glp_iptcp *parm); +* +* The routine glp_interior is a driver to the LP solver based on the +* interior-point method. +* +* The interior-point solver has a set of control parameters. Values of +* the control parameters can be passed in a structure glp_iptcp, which +* the parameter parm points to. +* +* Currently this routine implements an easy variant of the primal-dual +* interior-point method based on Mehrotra's technique. +* +* This routine transforms the original LP problem to an equivalent LP +* problem in the standard formulation (all constraints are equalities, +* all variables are non-negative), calls the routine ipm_main to solve +* the transformed problem, and then transforms an obtained solution to +* the solution of the original problem. +* +* RETURNS +* +* 0 The LP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EFAIL +* The problem has no rows/columns. +* +* GLP_ENOCVG +* Very slow convergence or divergence. +* +* GLP_EITLIM +* Iteration limit exceeded. +* +* GLP_EINSTAB +* Numerical instability on solving Newtonian system. */ + +static void transform(NPP *npp) +{ /* transform LP to the standard formulation */ + NPPROW *row, *prev_row; + NPPCOL *col, *prev_col; + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + npp_free_row(npp, row); + else if (row->lb == -DBL_MAX) + npp_leq_row(npp, row); + else if (row->ub == +DBL_MAX) + npp_geq_row(npp, row); + else if (row->lb != row->ub) + { if (fabs(row->lb) < fabs(row->ub)) + npp_geq_row(npp, row); + else + npp_leq_row(npp, row); + } + } + for (col = npp->c_tail; col != NULL; col = prev_col) + { prev_col = col->prev; + if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) + npp_free_col(npp, col); + else if (col->lb == -DBL_MAX) + npp_ubnd_col(npp, col); + else if (col->ub == +DBL_MAX) + { if (col->lb != 0.0) + npp_lbnd_col(npp, col); + } + else if (col->lb != col->ub) + { if (fabs(col->lb) < fabs(col->ub)) + { if (col->lb != 0.0) + npp_lbnd_col(npp, col); + } + else + npp_ubnd_col(npp, col); + npp_dbnd_col(npp, col); + } + else + npp_fixed_col(npp, col); + } + for (row = npp->r_head; row != NULL; row = row->next) + xassert(row->lb == row->ub); + for (col = npp->c_head; col != NULL; col = col->next) + xassert(col->lb == 0.0 && col->ub == +DBL_MAX); + return; +} + +int glp_interior(glp_prob *P, const glp_iptcp *parm) +{ glp_iptcp _parm; + GLPROW *row; + GLPCOL *col; + NPP *npp = NULL; + glp_prob *prob = NULL; + int i, j, ret; + /* check control parameters */ + if (parm == NULL) + glp_init_iptcp(&_parm), parm = &_parm; + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL)) + xerror("glp_interior: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->ord_alg == GLP_ORD_NONE || + parm->ord_alg == GLP_ORD_QMD || + parm->ord_alg == GLP_ORD_AMD || + parm->ord_alg == GLP_ORD_SYMAMD)) + xerror("glp_interior: ord_alg = %d; invalid parameter\n", + parm->ord_alg); + /* interior-point solution is currently undefined */ + P->ipt_stat = GLP_UNDEF; + P->ipt_obj = 0.0; + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: row %d: lb = %g, ub = %g; incorre" + "ct bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: column %d: lb = %g, ub = %g; inco" + "rrect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* transform LP to the standard formulation */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Original LP has %d row(s), %d column(s), and %d non-z" + "ero(s)\n", P->m, P->n, P->nnz); + npp = npp_create_wksp(); + npp_load_prob(npp, P, GLP_OFF, GLP_IPT, GLP_ON); + transform(npp); + prob = glp_create_prob(); + npp_build_prob(npp, prob); + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Working LP has %d row(s), %d column(s), and %d non-ze" + "ro(s)\n", prob->m, prob->n, prob->nnz); +#if 1 + /* currently empty problem cannot be solved */ + if (!(prob->m > 0 && prob->n > 0)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_interior: unable to solve empty problem\n"); + ret = GLP_EFAIL; + goto done; + } +#endif + /* scale the resultant LP */ + { ENV *env = get_env_ptr(); + int term_out = env->term_out; + env->term_out = GLP_OFF; + glp_scale_prob(prob, GLP_SF_EQ); + env->term_out = term_out; + } + /* warn about dense columns */ + if (parm->msg_lev >= GLP_MSG_ON && prob->m >= 200) + { int len, cnt = 0; + for (j = 1; j <= prob->n; j++) + { len = glp_get_mat_col(prob, j, NULL, NULL); + if ((double)len >= 0.20 * (double)prob->m) cnt++; + } + if (cnt == 1) + xprintf("WARNING: PROBLEM HAS ONE DENSE COLUMN\n"); + else if (cnt > 0) + xprintf("WARNING: PROBLEM HAS %d DENSE COLUMNS\n", cnt); + } + /* solve the transformed LP */ + ret = ipm_solve(prob, parm); + /* postprocess solution from the transformed LP */ + npp_postprocess(npp, prob); + /* and store solution to the original LP */ + npp_unload_sol(npp, P); +done: /* free working program objects */ + if (npp != NULL) npp_delete_wksp(npp); + if (prob != NULL) glp_delete_prob(prob); + /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_iptcp - initialize interior-point solver control parameters +* +* SYNOPSIS +* +* void glp_init_iptcp(glp_iptcp *parm); +* +* DESCRIPTION +* +* The routine glp_init_iptcp initializes control parameters, which are +* used by the interior-point solver, with default values. +* +* Default values of the control parameters are stored in the glp_iptcp +* structure, which the parameter parm points to. */ + +void glp_init_iptcp(glp_iptcp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->ord_alg = GLP_ORD_AMD; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_status - retrieve status of interior-point solution +* +* SYNOPSIS +* +* int glp_ipt_status(glp_prob *lp); +* +* RETURNS +* +* The routine glp_ipt_status reports the status of solution found by +* the interior-point solver as follows: +* +* GLP_UNDEF - interior-point solution is undefined; +* GLP_OPT - interior-point solution is optimal; +* GLP_INFEAS - interior-point solution is infeasible; +* GLP_NOFEAS - no feasible solution exists. */ + +int glp_ipt_status(glp_prob *lp) +{ int ipt_stat = lp->ipt_stat; + return ipt_stat; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_obj_val - retrieve objective value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_obj_val(glp_prob *lp); +* +* RETURNS +* +* The routine glp_ipt_obj_val returns value of the objective function +* for interior-point solution. */ + +double glp_ipt_obj_val(glp_prob *lp) +{ /*struct LPXCPS *cps = lp->cps;*/ + double z; + z = lp->ipt_obj; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_row_prim - retrieve row primal value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_row_prim(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_ipt_row_prim returns primal value of the auxiliary +* variable associated with i-th row. */ + +double glp_ipt_row_prim(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double pval; + if (!(1 <= i && i <= lp->m)) + xerror("glp_ipt_row_prim: i = %d; row number out of range\n", + i); + pval = lp->row[i]->pval; + /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ + return pval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_row_dual - retrieve row dual value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_row_dual(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_ipt_row_dual returns dual value (i.e. reduced cost) +* of the auxiliary variable associated with i-th row. */ + +double glp_ipt_row_dual(glp_prob *lp, int i) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dval; + if (!(1 <= i && i <= lp->m)) + xerror("glp_ipt_row_dual: i = %d; row number out of range\n", + i); + dval = lp->row[i]->dval; + /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ + return dval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_col_prim - retrieve column primal value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_col_prim(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_ipt_col_prim returns primal value of the structural +* variable associated with j-th column. */ + +double glp_ipt_col_prim(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double pval; + if (!(1 <= j && j <= lp->n)) + xerror("glp_ipt_col_prim: j = %d; column number out of range\n" + , j); + pval = lp->col[j]->pval; + /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ + return pval; +} + +/*********************************************************************** +* NAME +* +* glp_ipt_col_dual - retrieve column dual value (interior point) +* +* SYNOPSIS +* +* double glp_ipt_col_dual(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_ipt_col_dual returns dual value (i.e. reduced cost) +* of the structural variable associated with j-th column. */ + +double glp_ipt_col_dual(glp_prob *lp, int j) +{ /*struct LPXCPS *cps = lp->cps;*/ + double dval; + if (!(1 <= j && j <= lp->n)) + xerror("glp_ipt_col_dual: j = %d; column number out of range\n" + , j); + dval = lp->col[j]->dval; + /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ + return dval; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi09.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi09.c new file mode 100644 index 000000000..0d3ab57b5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi09.c @@ -0,0 +1,798 @@ +/* glpapi09.c (mixed integer programming routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "ios.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* glp_set_col_kind - set (change) column kind +* +* SYNOPSIS +* +* void glp_set_col_kind(glp_prob *mip, int j, int kind); +* +* DESCRIPTION +* +* The routine glp_set_col_kind sets (changes) the kind of j-th column +* (structural variable) as specified by the parameter kind: +* +* GLP_CV - continuous variable; +* GLP_IV - integer variable; +* GLP_BV - binary variable. */ + +void glp_set_col_kind(glp_prob *mip, int j, int kind) +{ GLPCOL *col; + if (!(1 <= j && j <= mip->n)) + xerror("glp_set_col_kind: j = %d; column number out of range\n" + , j); + col = mip->col[j]; + switch (kind) + { case GLP_CV: + col->kind = GLP_CV; + break; + case GLP_IV: + col->kind = GLP_IV; + break; + case GLP_BV: + col->kind = GLP_IV; + if (!(col->type == GLP_DB && col->lb == 0.0 && col->ub == + 1.0)) glp_set_col_bnds(mip, j, GLP_DB, 0.0, 1.0); + break; + default: + xerror("glp_set_col_kind: j = %d; kind = %d; invalid column" + " kind\n", j, kind); + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_kind - retrieve column kind +* +* SYNOPSIS +* +* int glp_get_col_kind(glp_prob *mip, int j); +* +* RETURNS +* +* The routine glp_get_col_kind returns the kind of j-th column, i.e. +* the kind of corresponding structural variable, as follows: +* +* GLP_CV - continuous variable; +* GLP_IV - integer variable; +* GLP_BV - binary variable */ + +int glp_get_col_kind(glp_prob *mip, int j) +{ GLPCOL *col; + int kind; + if (!(1 <= j && j <= mip->n)) + xerror("glp_get_col_kind: j = %d; column number out of range\n" + , j); + col = mip->col[j]; + kind = col->kind; + switch (kind) + { case GLP_CV: + break; + case GLP_IV: + if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) + kind = GLP_BV; + break; + default: + xassert(kind != kind); + } + return kind; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_int - retrieve number of integer columns +* +* SYNOPSIS +* +* int glp_get_num_int(glp_prob *mip); +* +* RETURNS +* +* The routine glp_get_num_int returns the current number of columns, +* which are marked as integer. */ + +int glp_get_num_int(glp_prob *mip) +{ GLPCOL *col; + int j, count = 0; + for (j = 1; j <= mip->n; j++) + { col = mip->col[j]; + if (col->kind == GLP_IV) count++; + } + return count; +} + +/*********************************************************************** +* NAME +* +* glp_get_num_bin - retrieve number of binary columns +* +* SYNOPSIS +* +* int glp_get_num_bin(glp_prob *mip); +* +* RETURNS +* +* The routine glp_get_num_bin returns the current number of columns, +* which are marked as binary. */ + +int glp_get_num_bin(glp_prob *mip) +{ GLPCOL *col; + int j, count = 0; + for (j = 1; j <= mip->n; j++) + { col = mip->col[j]; + if (col->kind == GLP_IV && col->type == GLP_DB && col->lb == + 0.0 && col->ub == 1.0) count++; + } + return count; +} + +/*********************************************************************** +* NAME +* +* glp_intopt - solve MIP problem with the branch-and-bound method +* +* SYNOPSIS +* +* int glp_intopt(glp_prob *P, const glp_iocp *parm); +* +* DESCRIPTION +* +* The routine glp_intopt is a driver to the MIP solver based on the +* branch-and-bound method. +* +* On entry the problem object should contain optimal solution to LP +* relaxation (which can be obtained with the routine glp_simplex). +* +* The MIP solver has a set of control parameters. Values of the control +* parameters can be passed in a structure glp_iocp, which the parameter +* parm points to. +* +* The parameter parm can be specified as NULL, in which case the MIP +* solver uses default settings. +* +* RETURNS +* +* 0 The MIP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EBOUND +* Unable to start the search, because some double-bounded variables +* have incorrect bounds or some integer variables have non-integer +* (fractional) bounds. +* +* GLP_EROOT +* Unable to start the search, because optimal basis for initial LP +* relaxation is not provided. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EMIPGAP +* The search was prematurely terminated, because the relative mip +* gap tolerance has been reached. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ENOPFS +* The MIP problem instance has no primal feasible solution (only if +* the MIP presolver is used). +* +* GLP_ENODFS +* LP relaxation of the MIP problem instance has no dual feasible +* solution (only if the MIP presolver is used). +* +* GLP_ESTOP +* The search was prematurely terminated by application. */ + +#if 0 /* 11/VII-2013 */ +static int solve_mip(glp_prob *P, const glp_iocp *parm) +#else +static int solve_mip(glp_prob *P, const glp_iocp *parm, + glp_prob *P0 /* problem passed to glp_intopt */, + NPP *npp /* preprocessor workspace or NULL */) +#endif +{ /* solve MIP directly without using the preprocessor */ + glp_tree *T; + int ret; + /* optimal basis to LP relaxation must be provided */ + if (glp_get_status(P) != GLP_OPT) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: optimal basis to initial LP relaxation" + " not provided\n"); + ret = GLP_EROOT; + goto done; + } + /* it seems all is ok */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Integer optimization begins...\n"); + /* create the branch-and-bound tree */ + T = ios_create_tree(P, parm); +#if 1 /* 11/VII-2013 */ + T->P = P0; + T->npp = npp; +#endif + /* solve the problem instance */ + ret = ios_driver(T); + /* delete the branch-and-bound tree */ + ios_delete_tree(T); + /* analyze exit code reported by the mip driver */ + if (ret == 0) + { if (P->mip_stat == GLP_FEAS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("INTEGER OPTIMAL SOLUTION FOUND\n"); + P->mip_stat = GLP_OPT; + } + else + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); + P->mip_stat = GLP_NOFEAS; + } + } + else if (ret == GLP_EMIPGAP) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("RELATIVE MIP GAP TOLERANCE REACHED; SEARCH TERMINA" + "TED\n"); + } + else if (ret == GLP_ETMLIM) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + } + else if (ret == GLP_EFAIL) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: cannot solve current LP relaxation\n"); + } + else if (ret == GLP_ESTOP) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("SEARCH TERMINATED BY APPLICATION\n"); + } + else + xassert(ret != ret); +done: return ret; +} + +static int preprocess_and_solve_mip(glp_prob *P, const glp_iocp *parm) +{ /* solve MIP using the preprocessor */ + ENV *env = get_env_ptr(); + int term_out = env->term_out; + NPP *npp; + glp_prob *mip = NULL; + glp_bfcp bfcp; + glp_smcp smcp; + int ret; + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Preprocessing...\n"); + /* create preprocessor workspace */ + npp = npp_create_wksp(); + /* load original problem into the preprocessor workspace */ + npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); + /* process MIP prior to applying the branch-and-bound method */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + ret = npp_integer(npp, parm); + env->term_out = term_out; + if (ret == 0) + ; + else if (ret == GLP_ENOPFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); + } + else if (ret == GLP_ENODFS) + { if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION\n"); + } + else + xassert(ret != ret); + if (ret != 0) goto done; + /* build transformed MIP */ + mip = glp_create_prob(); + npp_build_prob(npp, mip); + /* if the transformed MIP is empty, it has empty solution, which + is optimal */ + if (mip->m == 0 && mip->n == 0) + { mip->mip_stat = GLP_OPT; + mip->mip_obj = mip->c0; + if (parm->msg_lev >= GLP_MSG_ALL) + { xprintf("Objective value = %17.9e\n", mip->mip_obj); + xprintf("INTEGER OPTIMAL SOLUTION FOUND BY MIP PREPROCESSOR" + "\n"); + } + goto post; + } + /* display some statistics */ + if (parm->msg_lev >= GLP_MSG_ALL) + { int ni = glp_get_num_int(mip); + int nb = glp_get_num_bin(mip); + char s[50]; + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + mip->m, mip->m == 1 ? "" : "s", mip->n, mip->n == 1 ? "" : + "s", mip->nnz, mip->nnz == 1 ? "" : "s"); + if (nb == 0) + strcpy(s, "none of"); + else if (ni == 1 && nb == 1) + strcpy(s, ""); + else if (nb == 1) + strcpy(s, "one of"); + else if (nb == ni) + strcpy(s, "all of"); + else + sprintf(s, "%d of", nb); + xprintf("%d integer variable%s, %s which %s binary\n", + ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); + } + /* inherit basis factorization control parameters */ + glp_get_bfcp(P, &bfcp); + glp_set_bfcp(mip, &bfcp); + /* scale the transformed problem */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_scale_prob(mip, + GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP); + env->term_out = term_out; + /* build advanced initial basis */ + if (!term_out || parm->msg_lev < GLP_MSG_ALL) + env->term_out = GLP_OFF; + else + env->term_out = GLP_ON; + glp_adv_basis(mip, 0); + env->term_out = term_out; + /* solve initial LP relaxation */ + if (parm->msg_lev >= GLP_MSG_ALL) + xprintf("Solving LP relaxation...\n"); + glp_init_smcp(&smcp); + smcp.msg_lev = parm->msg_lev; + /* respect time limit */ + smcp.tm_lim = parm->tm_lim; + mip->it_cnt = P->it_cnt; + ret = glp_simplex(mip, &smcp); + P->it_cnt = mip->it_cnt; + if (ret == GLP_ETMLIM) + goto done; + else if (ret != 0) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: cannot solve LP relaxation\n"); + ret = GLP_EFAIL; + goto done; + } + /* check status of the basic solution */ + ret = glp_get_status(mip); + if (ret == GLP_OPT) + ret = 0; + else if (ret == GLP_NOFEAS) + ret = GLP_ENOPFS; + else if (ret == GLP_UNBND) + ret = GLP_ENODFS; + else + xassert(ret != ret); + if (ret != 0) goto done; + /* solve the transformed MIP */ + mip->it_cnt = P->it_cnt; +#if 0 /* 11/VII-2013 */ + ret = solve_mip(mip, parm); +#else + if (parm->use_sol) + { mip->mip_stat = P->mip_stat; + mip->mip_obj = P->mip_obj; + } + ret = solve_mip(mip, parm, P, npp); +#endif + P->it_cnt = mip->it_cnt; + /* only integer feasible solution can be postprocessed */ + if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) + { P->mip_stat = mip->mip_stat; + goto done; + } + /* postprocess solution from the transformed MIP */ +post: npp_postprocess(npp, mip); + /* the transformed MIP is no longer needed */ + glp_delete_prob(mip), mip = NULL; + /* store solution to the original problem */ + npp_unload_sol(npp, P); +done: /* delete the transformed MIP, if it exists */ + if (mip != NULL) glp_delete_prob(mip); + /* delete preprocessor workspace */ + npp_delete_wksp(npp); + return ret; +} + +#ifndef HAVE_ALIEN_SOLVER /* 28/V-2010 */ +int _glp_intopt1(glp_prob *P, const glp_iocp *parm) +{ xassert(P == P); + xassert(parm == parm); + xprintf("glp_intopt: no alien solver is available\n"); + return GLP_EFAIL; +} +#endif + +int glp_intopt(glp_prob *P, const glp_iocp *parm) +{ /* solve MIP problem with the branch-and-bound method */ + glp_iocp _parm; + int i, j, ret; +#if 0 /* 04/IV-2016 */ + /* check problem object */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_intopt: P = %p; invalid problem object\n", P); +#endif + if (P->tree != NULL) + xerror("glp_intopt: operation not allowed\n"); + /* check control parameters */ + if (parm == NULL) + parm = &_parm, glp_init_iocp((glp_iocp *)parm); + if (!(parm->msg_lev == GLP_MSG_OFF || + parm->msg_lev == GLP_MSG_ERR || + parm->msg_lev == GLP_MSG_ON || + parm->msg_lev == GLP_MSG_ALL || + parm->msg_lev == GLP_MSG_DBG)) + xerror("glp_intopt: msg_lev = %d; invalid parameter\n", + parm->msg_lev); + if (!(parm->br_tech == GLP_BR_FFV || + parm->br_tech == GLP_BR_LFV || + parm->br_tech == GLP_BR_MFV || + parm->br_tech == GLP_BR_DTH || + parm->br_tech == GLP_BR_PCH)) + xerror("glp_intopt: br_tech = %d; invalid parameter\n", + parm->br_tech); + if (!(parm->bt_tech == GLP_BT_DFS || + parm->bt_tech == GLP_BT_BFS || + parm->bt_tech == GLP_BT_BLB || + parm->bt_tech == GLP_BT_BPH)) + xerror("glp_intopt: bt_tech = %d; invalid parameter\n", + parm->bt_tech); + if (!(0.0 < parm->tol_int && parm->tol_int < 1.0)) + xerror("glp_intopt: tol_int = %g; invalid parameter\n", + parm->tol_int); + if (!(0.0 < parm->tol_obj && parm->tol_obj < 1.0)) + xerror("glp_intopt: tol_obj = %g; invalid parameter\n", + parm->tol_obj); + if (parm->tm_lim < 0) + xerror("glp_intopt: tm_lim = %d; invalid parameter\n", + parm->tm_lim); + if (parm->out_frq < 0) + xerror("glp_intopt: out_frq = %d; invalid parameter\n", + parm->out_frq); + if (parm->out_dly < 0) + xerror("glp_intopt: out_dly = %d; invalid parameter\n", + parm->out_dly); + if (!(0 <= parm->cb_size && parm->cb_size <= 256)) + xerror("glp_intopt: cb_size = %d; invalid parameter\n", + parm->cb_size); + if (!(parm->pp_tech == GLP_PP_NONE || + parm->pp_tech == GLP_PP_ROOT || + parm->pp_tech == GLP_PP_ALL)) + xerror("glp_intopt: pp_tech = %d; invalid parameter\n", + parm->pp_tech); + if (parm->mip_gap < 0.0) + xerror("glp_intopt: mip_gap = %g; invalid parameter\n", + parm->mip_gap); + if (!(parm->mir_cuts == GLP_ON || parm->mir_cuts == GLP_OFF)) + xerror("glp_intopt: mir_cuts = %d; invalid parameter\n", + parm->mir_cuts); + if (!(parm->gmi_cuts == GLP_ON || parm->gmi_cuts == GLP_OFF)) + xerror("glp_intopt: gmi_cuts = %d; invalid parameter\n", + parm->gmi_cuts); + if (!(parm->cov_cuts == GLP_ON || parm->cov_cuts == GLP_OFF)) + xerror("glp_intopt: cov_cuts = %d; invalid parameter\n", + parm->cov_cuts); + if (!(parm->clq_cuts == GLP_ON || parm->clq_cuts == GLP_OFF)) + xerror("glp_intopt: clq_cuts = %d; invalid parameter\n", + parm->clq_cuts); + if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) + xerror("glp_intopt: presolve = %d; invalid parameter\n", + parm->presolve); + if (!(parm->binarize == GLP_ON || parm->binarize == GLP_OFF)) + xerror("glp_intopt: binarize = %d; invalid parameter\n", + parm->binarize); + if (!(parm->fp_heur == GLP_ON || parm->fp_heur == GLP_OFF)) + xerror("glp_intopt: fp_heur = %d; invalid parameter\n", + parm->fp_heur); +#if 1 /* 28/V-2010 */ + if (!(parm->alien == GLP_ON || parm->alien == GLP_OFF)) + xerror("glp_intopt: alien = %d; invalid parameter\n", + parm->alien); +#endif +#if 0 /* 11/VII-2013 */ + /* integer solution is currently undefined */ + P->mip_stat = GLP_UNDEF; + P->mip_obj = 0.0; +#else + if (!parm->use_sol) + P->mip_stat = GLP_UNDEF; + if (P->mip_stat == GLP_NOFEAS) + P->mip_stat = GLP_UNDEF; + if (P->mip_stat == GLP_UNDEF) + P->mip_obj = 0.0; + else if (P->mip_stat == GLP_OPT) + P->mip_stat = GLP_FEAS; +#endif + /* check bounds of double-bounded variables */ + for (i = 1; i <= P->m; i++) + { GLPROW *row = P->row[i]; + if (row->type == GLP_DB && row->lb >= row->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: row %d: lb = %g, ub = %g; incorrect" + " bounds\n", i, row->lb, row->ub); + ret = GLP_EBOUND; + goto done; + } + } + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->type == GLP_DB && col->lb >= col->ub) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: column %d: lb = %g, ub = %g; incorr" + "ect bounds\n", j, col->lb, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + /* bounds of all integer variables must be integral */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (col->kind != GLP_IV) continue; + if (col->type == GLP_LO || col->type == GLP_DB) + { if (col->lb != floor(col->lb)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r lower bound %g\n", j, col->lb); + ret = GLP_EBOUND; + goto done; + } + } + if (col->type == GLP_UP || col->type == GLP_DB) + { if (col->ub != floor(col->ub)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r upper bound %g\n", j, col->ub); + ret = GLP_EBOUND; + goto done; + } + } + if (col->type == GLP_FX) + { if (col->lb != floor(col->lb)) + { if (parm->msg_lev >= GLP_MSG_ERR) + xprintf("glp_intopt: integer column %d has non-intege" + "r fixed value %g\n", j, col->lb); + ret = GLP_EBOUND; + goto done; + } + } + } + /* solve MIP problem */ + if (parm->msg_lev >= GLP_MSG_ALL) + { int ni = glp_get_num_int(P); + int nb = glp_get_num_bin(P); + char s[50]; + xprintf("GLPK Integer Optimizer, v%s\n", glp_version()); + xprintf("%d row%s, %d column%s, %d non-zero%s\n", + P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", + P->nnz, P->nnz == 1 ? "" : "s"); + if (nb == 0) + strcpy(s, "none of"); + else if (ni == 1 && nb == 1) + strcpy(s, ""); + else if (nb == 1) + strcpy(s, "one of"); + else if (nb == ni) + strcpy(s, "all of"); + else + sprintf(s, "%d of", nb); + xprintf("%d integer variable%s, %s which %s binary\n", + ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); + } +#if 1 /* 28/V-2010 */ + if (parm->alien) + { /* use alien integer optimizer */ + ret = _glp_intopt1(P, parm); + goto done; + } +#endif + if (!parm->presolve) +#if 0 /* 11/VII-2013 */ + ret = solve_mip(P, parm); +#else + ret = solve_mip(P, parm, P, NULL); +#endif + else + ret = preprocess_and_solve_mip(P, parm); +#if 1 /* 12/III-2013 */ + if (ret == GLP_ENOPFS) + P->mip_stat = GLP_NOFEAS; +#endif +done: /* return to the application program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_init_iocp - initialize integer optimizer control parameters +* +* SYNOPSIS +* +* void glp_init_iocp(glp_iocp *parm); +* +* DESCRIPTION +* +* The routine glp_init_iocp initializes control parameters, which are +* used by the integer optimizer, with default values. +* +* Default values of the control parameters are stored in a glp_iocp +* structure, which the parameter parm points to. */ + +void glp_init_iocp(glp_iocp *parm) +{ parm->msg_lev = GLP_MSG_ALL; + parm->br_tech = GLP_BR_DTH; + parm->bt_tech = GLP_BT_BLB; + parm->tol_int = 1e-5; + parm->tol_obj = 1e-7; + parm->tm_lim = INT_MAX; + parm->out_frq = 5000; + parm->out_dly = 10000; + parm->cb_func = NULL; + parm->cb_info = NULL; + parm->cb_size = 0; + parm->pp_tech = GLP_PP_ALL; + parm->mip_gap = 0.0; + parm->mir_cuts = GLP_OFF; + parm->gmi_cuts = GLP_OFF; + parm->cov_cuts = GLP_OFF; + parm->clq_cuts = GLP_OFF; + parm->presolve = GLP_OFF; + parm->binarize = GLP_OFF; + parm->fp_heur = GLP_OFF; + parm->ps_heur = GLP_OFF; + parm->ps_tm_lim = 60000; /* 1 minute */ + parm->sr_heur = GLP_ON; +#if 1 /* 24/X-2015; not documented--should not be used */ + parm->use_sol = GLP_OFF; + parm->save_sol = NULL; + parm->alien = GLP_OFF; +#endif +#if 0 /* 20/I-2018 */ +#if 1 /* 16/III-2016; not documented--should not be used */ + parm->flip = GLP_OFF; +#endif +#else + parm->flip = GLP_ON; +#endif + return; +} + +/*********************************************************************** +* NAME +* +* glp_mip_status - retrieve status of MIP solution +* +* SYNOPSIS +* +* int glp_mip_status(glp_prob *mip); +* +* RETURNS +* +* The routine lpx_mip_status reports the status of MIP solution found +* by the branch-and-bound solver as follows: +* +* GLP_UNDEF - MIP solution is undefined; +* GLP_OPT - MIP solution is integer optimal; +* GLP_FEAS - MIP solution is integer feasible but its optimality +* (or non-optimality) has not been proven, perhaps due to +* premature termination of the search; +* GLP_NOFEAS - problem has no integer feasible solution (proven by the +* solver). */ + +int glp_mip_status(glp_prob *mip) +{ int mip_stat = mip->mip_stat; + return mip_stat; +} + +/*********************************************************************** +* NAME +* +* glp_mip_obj_val - retrieve objective value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_obj_val(glp_prob *mip); +* +* RETURNS +* +* The routine glp_mip_obj_val returns value of the objective function +* for MIP solution. */ + +double glp_mip_obj_val(glp_prob *mip) +{ /*struct LPXCPS *cps = mip->cps;*/ + double z; + z = mip->mip_obj; + /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ + return z; +} + +/*********************************************************************** +* NAME +* +* glp_mip_row_val - retrieve row value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_row_val(glp_prob *mip, int i); +* +* RETURNS +* +* The routine glp_mip_row_val returns value of the auxiliary variable +* associated with i-th row. */ + +double glp_mip_row_val(glp_prob *mip, int i) +{ /*struct LPXCPS *cps = mip->cps;*/ + double mipx; + if (!(1 <= i && i <= mip->m)) + xerror("glp_mip_row_val: i = %d; row number out of range\n", i) + ; + mipx = mip->row[i]->mipx; + /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ + return mipx; +} + +/*********************************************************************** +* NAME +* +* glp_mip_col_val - retrieve column value (MIP solution) +* +* SYNOPSIS +* +* double glp_mip_col_val(glp_prob *mip, int j); +* +* RETURNS +* +* The routine glp_mip_col_val returns value of the structural variable +* associated with j-th column. */ + +double glp_mip_col_val(glp_prob *mip, int j) +{ /*struct LPXCPS *cps = mip->cps;*/ + double mipx; + if (!(1 <= j && j <= mip->n)) + xerror("glp_mip_col_val: j = %d; column number out of range\n", + j); + mipx = mip->col[j]->mipx; + /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ + return mipx; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi10.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi10.c new file mode 100644 index 000000000..5550aa39f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi10.c @@ -0,0 +1,305 @@ +/* glpapi10.c (solution checking routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +void glp_check_kkt(glp_prob *P, int sol, int cond, double *_ae_max, + int *_ae_ind, double *_re_max, int *_re_ind) +{ /* check feasibility and optimality conditions */ + int m = P->m; + int n = P->n; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, ae_ind, re_ind; + double e, sp, sn, t, ae_max, re_max; + if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) + xerror("glp_check_kkt: sol = %d; invalid solution indicator\n", + sol); + if (!(cond == GLP_KKT_PE || cond == GLP_KKT_PB || + cond == GLP_KKT_DE || cond == GLP_KKT_DB || + cond == GLP_KKT_CS)) + xerror("glp_check_kkt: cond = %d; invalid condition indicator " + "\n", cond); + ae_max = re_max = 0.0; + ae_ind = re_ind = 0; + if (cond == GLP_KKT_PE) + { /* xR - A * xS = 0 */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + sp = sn = 0.0; + /* t := xR[i] */ + if (sol == GLP_SOL) + t = row->prim; + else if (sol == GLP_IPT) + t = row->pval; + else if (sol == GLP_MIP) + t = row->mipx; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + /* t := - a[i,j] * xS[j] */ + if (sol == GLP_SOL) + t = - aij->val * col->prim; + else if (sol == GLP_IPT) + t = - aij->val * col->pval; + else if (sol == GLP_MIP) + t = - aij->val * col->mipx; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + } + /* absolute error */ + e = fabs(sp - sn); + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + sp + sn); + if (re_max < e) + re_max = e, re_ind = i; + } + } + else if (cond == GLP_KKT_PB) + { /* lR <= xR <= uR */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* t := xR[i] */ + if (sol == GLP_SOL) + t = row->prim; + else if (sol == GLP_IPT) + t = row->pval; + else if (sol == GLP_MIP) + t = row->mipx; + else + xassert(sol != sol); + /* check lower bound */ + if (row->type == GLP_LO || row->type == GLP_DB || + row->type == GLP_FX) + { if (t < row->lb) + { /* absolute error */ + e = row->lb - t; + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + fabs(row->lb)); + if (re_max < e) + re_max = e, re_ind = i; + } + } + /* check upper bound */ + if (row->type == GLP_UP || row->type == GLP_DB || + row->type == GLP_FX) + { if (t > row->ub) + { /* absolute error */ + e = t - row->ub; + if (ae_max < e) + ae_max = e, ae_ind = i; + /* relative error */ + e /= (1.0 + fabs(row->ub)); + if (re_max < e) + re_max = e, re_ind = i; + } + } + } + /* lS <= xS <= uS */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* t := xS[j] */ + if (sol == GLP_SOL) + t = col->prim; + else if (sol == GLP_IPT) + t = col->pval; + else if (sol == GLP_MIP) + t = col->mipx; + else + xassert(sol != sol); + /* check lower bound */ + if (col->type == GLP_LO || col->type == GLP_DB || + col->type == GLP_FX) + { if (t < col->lb) + { /* absolute error */ + e = col->lb - t; + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + fabs(col->lb)); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + /* check upper bound */ + if (col->type == GLP_UP || col->type == GLP_DB || + col->type == GLP_FX) + { if (t > col->ub) + { /* absolute error */ + e = t - col->ub; + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + fabs(col->ub)); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + } + } + else if (cond == GLP_KKT_DE) + { /* A' * (lambdaR - cR) + (lambdaS - cS) = 0 */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + sp = sn = 0.0; + /* t := lambdaS[j] - cS[j] */ + if (sol == GLP_SOL) + t = col->dual - col->coef; + else if (sol == GLP_IPT) + t = col->dval - col->coef; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { row = aij->row; + /* t := a[i,j] * (lambdaR[i] - cR[i]) */ + if (sol == GLP_SOL) + t = aij->val * row->dual; + else if (sol == GLP_IPT) + t = aij->val * row->dval; + else + xassert(sol != sol); + if (t >= 0.0) sp += t; else sn -= t; + } + /* absolute error */ + e = fabs(sp - sn); + if (ae_max < e) + ae_max = e, ae_ind = m+j; + /* relative error */ + e /= (1.0 + sp + sn); + if (re_max < e) + re_max = e, re_ind = m+j; + } + } + else if (cond == GLP_KKT_DB) + { /* check lambdaR */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + /* t := lambdaR[i] */ + if (sol == GLP_SOL) + t = row->dual; + else if (sol == GLP_IPT) + t = row->dval; + else + xassert(sol != sol); + /* correct sign */ + if (P->dir == GLP_MIN) + t = + t; + else if (P->dir == GLP_MAX) + t = - t; + else + xassert(P != P); + /* check for positivity */ +#if 1 /* 08/III-2013 */ + /* the former check was correct */ + /* the bug reported by David Price is related to violation + of complementarity slackness, not to this condition */ + if (row->type == GLP_FR || row->type == GLP_LO) +#else + if (row->stat == GLP_NF || row->stat == GLP_NL) +#endif + { if (t < 0.0) + { e = - t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = i; + } + } + /* check for negativity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (row->type == GLP_FR || row->type == GLP_UP) +#else + if (row->stat == GLP_NF || row->stat == GLP_NU) +#endif + { if (t > 0.0) + { e = + t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = i; + } + } + } + /* check lambdaS */ + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* t := lambdaS[j] */ + if (sol == GLP_SOL) + t = col->dual; + else if (sol == GLP_IPT) + t = col->dval; + else + xassert(sol != sol); + /* correct sign */ + if (P->dir == GLP_MIN) + t = + t; + else if (P->dir == GLP_MAX) + t = - t; + else + xassert(P != P); + /* check for positivity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (col->type == GLP_FR || col->type == GLP_LO) +#else + if (col->stat == GLP_NF || col->stat == GLP_NL) +#endif + { if (t < 0.0) + { e = - t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = m+j; + } + } + /* check for negativity */ +#if 1 /* 08/III-2013 */ + /* see comment above */ + if (col->type == GLP_FR || col->type == GLP_UP) +#else + if (col->stat == GLP_NF || col->stat == GLP_NU) +#endif + { if (t > 0.0) + { e = + t; + if (ae_max < e) + ae_max = re_max = e, ae_ind = re_ind = m+j; + } + } + } + } + else + xassert(cond != cond); + if (_ae_max != NULL) *_ae_max = ae_max; + if (_ae_ind != NULL) *_ae_ind = ae_ind; + if (_re_max != NULL) *_re_max = re_max; + if (_re_ind != NULL) *_re_ind = re_ind; + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi12.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi12.c new file mode 100644 index 000000000..020c89811 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi12.c @@ -0,0 +1,2185 @@ +/* glpapi12.c (basis factorization and simplex tableau routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_bf_exists - check if the basis factorization exists +* +* SYNOPSIS +* +* int glp_bf_exists(glp_prob *lp); +* +* RETURNS +* +* If the basis factorization for the current basis associated with +* the specified problem object exists and therefore is available for +* computations, the routine glp_bf_exists returns non-zero. Otherwise +* the routine returns zero. */ + +int glp_bf_exists(glp_prob *lp) +{ int ret; + ret = (lp->m == 0 || lp->valid); + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_factorize - compute the basis factorization +* +* SYNOPSIS +* +* int glp_factorize(glp_prob *lp); +* +* DESCRIPTION +* +* The routine glp_factorize computes the basis factorization for the +* current basis associated with the specified problem object. +* +* RETURNS +* +* 0 The basis factorization has been successfully computed. +* +* GLP_EBADB +* The basis matrix is invalid, i.e. the number of basic (auxiliary +* and structural) variables differs from the number of rows in the +* problem object. +* +* GLP_ESING +* The basis matrix is singular within the working precision. +* +* GLP_ECOND +* The basis matrix is ill-conditioned. */ + +static int b_col(void *info, int j, int ind[], double val[]) +{ glp_prob *lp = info; + int m = lp->m; + GLPAIJ *aij; + int k, len; + xassert(1 <= j && j <= m); + /* determine the ordinal number of basic auxiliary or structural + variable x[k] corresponding to basic variable xB[j] */ + k = lp->head[j]; + /* build j-th column of the basic matrix, which is k-th column of + the scaled augmented matrix (I | -R*A*S) */ + if (k <= m) + { /* x[k] is auxiliary variable */ + len = 1; + ind[1] = k; + val[1] = 1.0; + } + else + { /* x[k] is structural variable */ + len = 0; + for (aij = lp->col[k-m]->ptr; aij != NULL; aij = aij->c_next) + { len++; + ind[len] = aij->row->i; + val[len] = - aij->row->rii * aij->val * aij->col->sjj; + } + } + return len; +} + +int glp_factorize(glp_prob *lp) +{ int m = lp->m; + int n = lp->n; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int *head = lp->head; + int j, k, stat, ret; + /* invalidate the basis factorization */ + lp->valid = 0; + /* build the basis header */ + j = 0; + for (k = 1; k <= m+n; k++) + { if (k <= m) + { stat = row[k]->stat; + row[k]->bind = 0; + } + else + { stat = col[k-m]->stat; + col[k-m]->bind = 0; + } + if (stat == GLP_BS) + { j++; + if (j > m) + { /* too many basic variables */ + ret = GLP_EBADB; + goto fini; + } + head[j] = k; + if (k <= m) + row[k]->bind = j; + else + col[k-m]->bind = j; + } + } + if (j < m) + { /* too few basic variables */ + ret = GLP_EBADB; + goto fini; + } + /* try to factorize the basis matrix */ + if (m > 0) + { if (lp->bfd == NULL) + { lp->bfd = bfd_create_it(); +#if 0 /* 08/III-2014 */ + copy_bfcp(lp); +#endif + } + switch (bfd_factorize(lp->bfd, m, /*lp->head,*/ b_col, lp)) + { case 0: + /* ok */ + break; + case BFD_ESING: + /* singular matrix */ + ret = GLP_ESING; + goto fini; + case BFD_ECOND: + /* ill-conditioned matrix */ + ret = GLP_ECOND; + goto fini; + default: + xassert(lp != lp); + } + lp->valid = 1; + } + /* factorization successful */ + ret = 0; +fini: /* bring the return code to the calling program */ + return ret; +} + +/*********************************************************************** +* NAME +* +* glp_bf_updated - check if the basis factorization has been updated +* +* SYNOPSIS +* +* int glp_bf_updated(glp_prob *lp); +* +* RETURNS +* +* If the basis factorization has been just computed from scratch, the +* routine glp_bf_updated returns zero. Otherwise, if the factorization +* has been updated one or more times, the routine returns non-zero. */ + +int glp_bf_updated(glp_prob *lp) +{ int cnt; + if (!(lp->m == 0 || lp->valid)) + xerror("glp_bf_update: basis factorization does not exist\n"); +#if 0 /* 15/XI-2009 */ + cnt = (lp->m == 0 ? 0 : lp->bfd->upd_cnt); +#else + cnt = (lp->m == 0 ? 0 : bfd_get_count(lp->bfd)); +#endif + return cnt; +} + +/*********************************************************************** +* NAME +* +* glp_get_bfcp - retrieve basis factorization control parameters +* +* SYNOPSIS +* +* void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm); +* +* DESCRIPTION +* +* The routine glp_get_bfcp retrieves control parameters, which are +* used on computing and updating the basis factorization associated +* with the specified problem object. +* +* Current values of control parameters are stored by the routine in +* a glp_bfcp structure, which the parameter parm points to. */ + +#if 1 /* 08/III-2014 */ +void glp_get_bfcp(glp_prob *P, glp_bfcp *parm) +{ if (P->bfd == NULL) + P->bfd = bfd_create_it(); + bfd_get_bfcp(P->bfd, parm); + return; +} +#endif + +/*********************************************************************** +* NAME +* +* glp_set_bfcp - change basis factorization control parameters +* +* SYNOPSIS +* +* void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm); +* +* DESCRIPTION +* +* The routine glp_set_bfcp changes control parameters, which are used +* by internal GLPK routines in computing and updating the basis +* factorization associated with the specified problem object. +* +* New values of the control parameters should be passed in a structure +* glp_bfcp, which the parameter parm points to. +* +* The parameter parm can be specified as NULL, in which case all +* control parameters are reset to their default values. */ + +#if 1 /* 08/III-2014 */ +void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm) +{ if (P->bfd == NULL) + P->bfd = bfd_create_it(); + if (parm != NULL) + { if (!(parm->type == GLP_BF_LUF + GLP_BF_FT || + parm->type == GLP_BF_LUF + GLP_BF_BG || + parm->type == GLP_BF_LUF + GLP_BF_GR || + parm->type == GLP_BF_BTF + GLP_BF_BG || + parm->type == GLP_BF_BTF + GLP_BF_GR)) + xerror("glp_set_bfcp: type = 0x%02X; invalid parameter\n", + parm->type); + if (!(0.0 < parm->piv_tol && parm->piv_tol < 1.0)) + xerror("glp_set_bfcp: piv_tol = %g; invalid parameter\n", + parm->piv_tol); + if (parm->piv_lim < 1) + xerror("glp_set_bfcp: piv_lim = %d; invalid parameter\n", + parm->piv_lim); + if (!(parm->suhl == GLP_ON || parm->suhl == GLP_OFF)) + xerror("glp_set_bfcp: suhl = %d; invalid parameter\n", + parm->suhl); + if (!(0.0 <= parm->eps_tol && parm->eps_tol <= 1e-6)) + xerror("glp_set_bfcp: eps_tol = %g; invalid parameter\n", + parm->eps_tol); + if (!(1 <= parm->nfs_max && parm->nfs_max <= 32767)) + xerror("glp_set_bfcp: nfs_max = %d; invalid parameter\n", + parm->nfs_max); + if (!(1 <= parm->nrs_max && parm->nrs_max <= 32767)) + xerror("glp_set_bfcp: nrs_max = %d; invalid parameter\n", + parm->nrs_max); + } + bfd_set_bfcp(P->bfd, parm); + return; +} +#endif + +/*********************************************************************** +* NAME +* +* glp_get_bhead - retrieve the basis header information +* +* SYNOPSIS +* +* int glp_get_bhead(glp_prob *lp, int k); +* +* DESCRIPTION +* +* The routine glp_get_bhead returns the basis header information for +* the current basis associated with the specified problem object. +* +* RETURNS +* +* If xB[k], 1 <= k <= m, is i-th auxiliary variable (1 <= i <= m), the +* routine returns i. Otherwise, if xB[k] is j-th structural variable +* (1 <= j <= n), the routine returns m+j. Here m is the number of rows +* and n is the number of columns in the problem object. */ + +int glp_get_bhead(glp_prob *lp, int k) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_bhead: basis factorization does not exist\n"); + if (!(1 <= k && k <= lp->m)) + xerror("glp_get_bhead: k = %d; index out of range\n", k); + return lp->head[k]; +} + +/*********************************************************************** +* NAME +* +* glp_get_row_bind - retrieve row index in the basis header +* +* SYNOPSIS +* +* int glp_get_row_bind(glp_prob *lp, int i); +* +* RETURNS +* +* The routine glp_get_row_bind returns the index k of basic variable +* xB[k], 1 <= k <= m, which is i-th auxiliary variable, 1 <= i <= m, +* in the current basis associated with the specified problem object, +* where m is the number of rows. However, if i-th auxiliary variable +* is non-basic, the routine returns zero. */ + +int glp_get_row_bind(glp_prob *lp, int i) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_row_bind: basis factorization does not exist\n" + ); + if (!(1 <= i && i <= lp->m)) + xerror("glp_get_row_bind: i = %d; row number out of range\n", + i); + return lp->row[i]->bind; +} + +/*********************************************************************** +* NAME +* +* glp_get_col_bind - retrieve column index in the basis header +* +* SYNOPSIS +* +* int glp_get_col_bind(glp_prob *lp, int j); +* +* RETURNS +* +* The routine glp_get_col_bind returns the index k of basic variable +* xB[k], 1 <= k <= m, which is j-th structural variable, 1 <= j <= n, +* in the current basis associated with the specified problem object, +* where m is the number of rows, n is the number of columns. However, +* if j-th structural variable is non-basic, the routine returns zero.*/ + +int glp_get_col_bind(glp_prob *lp, int j) +{ if (!(lp->m == 0 || lp->valid)) + xerror("glp_get_col_bind: basis factorization does not exist\n" + ); + if (!(1 <= j && j <= lp->n)) + xerror("glp_get_col_bind: j = %d; column number out of range\n" + , j); + return lp->col[j]->bind; +} + +/*********************************************************************** +* NAME +* +* glp_ftran - perform forward transformation (solve system B*x = b) +* +* SYNOPSIS +* +* void glp_ftran(glp_prob *lp, double x[]); +* +* DESCRIPTION +* +* The routine glp_ftran performs forward transformation, i.e. solves +* the system B*x = b, where B is the basis matrix corresponding to the +* current basis for the specified problem object, x is the vector of +* unknowns to be computed, b is the vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* SCALING/UNSCALING +* +* Let A~ = (I | -A) is the augmented constraint matrix of the original +* (unscaled) problem. In the scaled LP problem instead the matrix A the +* scaled matrix A" = R*A*S is actually used, so +* +* A~" = (I | A") = (I | R*A*S) = (R*I*inv(R) | R*A*S) = +* (1) +* = R*(I | A)*S~ = R*A~*S~, +* +* is the scaled augmented constraint matrix, where R and S are diagonal +* scaling matrices used to scale rows and columns of the matrix A, and +* +* S~ = diag(inv(R) | S) (2) +* +* is an augmented diagonal scaling matrix. +* +* By definition: +* +* A~ = (B | N), (3) +* +* where B is the basic matrix, which consists of basic columns of the +* augmented constraint matrix A~, and N is a matrix, which consists of +* non-basic columns of A~. From (1) it follows that: +* +* A~" = (B" | N") = (R*B*SB | R*N*SN), (4) +* +* where SB and SN are parts of the augmented scaling matrix S~, which +* correspond to basic and non-basic variables, respectively. Therefore +* +* B" = R*B*SB, (5) +* +* which is the scaled basis matrix. */ + +void glp_ftran(glp_prob *lp, double x[]) +{ int m = lp->m; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int i, k; + /* B*x = b ===> (R*B*SB)*(inv(SB)*x) = R*b ===> + B"*x" = b", where b" = R*b, x = SB*x" */ + if (!(m == 0 || lp->valid)) + xerror("glp_ftran: basis factorization does not exist\n"); + /* b" := R*b */ + for (i = 1; i <= m; i++) + x[i] *= row[i]->rii; + /* x" := inv(B")*b" */ + if (m > 0) bfd_ftran(lp->bfd, x); + /* x := SB*x" */ + for (i = 1; i <= m; i++) + { k = lp->head[i]; + if (k <= m) + x[i] /= row[k]->rii; + else + x[i] *= col[k-m]->sjj; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_btran - perform backward transformation (solve system B'*x = b) +* +* SYNOPSIS +* +* void glp_btran(glp_prob *lp, double x[]); +* +* DESCRIPTION +* +* The routine glp_btran performs backward transformation, i.e. solves +* the system B'*x = b, where B' is a matrix transposed to the basis +* matrix corresponding to the current basis for the specified problem +* problem object, x is the vector of unknowns to be computed, b is the +* vector of right-hand sides. +* +* On entry elements of the vector b should be stored in dense format +* in locations x[1], ..., x[m], where m is the number of rows. On exit +* the routine stores elements of the vector x in the same locations. +* +* SCALING/UNSCALING +* +* See comments to the routine glp_ftran. */ + +void glp_btran(glp_prob *lp, double x[]) +{ int m = lp->m; + GLPROW **row = lp->row; + GLPCOL **col = lp->col; + int i, k; + /* B'*x = b ===> (SB*B'*R)*(inv(R)*x) = SB*b ===> + (B")'*x" = b", where b" = SB*b, x = R*x" */ + if (!(m == 0 || lp->valid)) + xerror("glp_btran: basis factorization does not exist\n"); + /* b" := SB*b */ + for (i = 1; i <= m; i++) + { k = lp->head[i]; + if (k <= m) + x[i] /= row[k]->rii; + else + x[i] *= col[k-m]->sjj; + } + /* x" := inv[(B")']*b" */ + if (m > 0) bfd_btran(lp->bfd, x); + /* x := R*x" */ + for (i = 1; i <= m; i++) + x[i] *= row[i]->rii; + return; +} + +/*********************************************************************** +* NAME +* +* glp_warm_up - "warm up" LP basis +* +* SYNOPSIS +* +* int glp_warm_up(glp_prob *P); +* +* DESCRIPTION +* +* The routine glp_warm_up "warms up" the LP basis for the specified +* problem object using current statuses assigned to rows and columns +* (that is, to auxiliary and structural variables). +* +* This operation includes computing factorization of the basis matrix +* (if it does not exist), computing primal and dual components of basic +* solution, and determining the solution status. +* +* RETURNS +* +* 0 The operation has been successfully performed. +* +* GLP_EBADB +* The basis matrix is invalid, i.e. the number of basic (auxiliary +* and structural) variables differs from the number of rows in the +* problem object. +* +* GLP_ESING +* The basis matrix is singular within the working precision. +* +* GLP_ECOND +* The basis matrix is ill-conditioned. */ + +int glp_warm_up(glp_prob *P) +{ GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, type, stat, ret; + double eps, temp, *work; + /* invalidate basic solution */ + P->pbs_stat = P->dbs_stat = GLP_UNDEF; + P->obj_val = 0.0; + P->some = 0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + row->prim = row->dual = 0.0; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + col->prim = col->dual = 0.0; + } + /* compute the basis factorization, if necessary */ + if (!glp_bf_exists(P)) + { ret = glp_factorize(P); + if (ret != 0) goto done; + } + /* allocate working array */ + work = xcalloc(1+P->m, sizeof(double)); + /* determine and store values of non-basic variables, compute + vector (- N * xN) */ + for (i = 1; i <= P->m; i++) + work[i] = 0.0; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat == GLP_BS) + continue; + else if (row->stat == GLP_NL) + row->prim = row->lb; + else if (row->stat == GLP_NU) + row->prim = row->ub; + else if (row->stat == GLP_NF) + row->prim = 0.0; + else if (row->stat == GLP_NS) + row->prim = row->lb; + else + xassert(row != row); + /* N[j] is i-th column of matrix (I|-A) */ + work[i] -= row->prim; + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + continue; + else if (col->stat == GLP_NL) + col->prim = col->lb; + else if (col->stat == GLP_NU) + col->prim = col->ub; + else if (col->stat == GLP_NF) + col->prim = 0.0; + else if (col->stat == GLP_NS) + col->prim = col->lb; + else + xassert(col != col); + /* N[j] is (m+j)-th column of matrix (I|-A) */ + if (col->prim != 0.0) + { for (aij = col->ptr; aij != NULL; aij = aij->c_next) + work[aij->row->i] += aij->val * col->prim; + } + } + /* compute vector of basic variables xB = - inv(B) * N * xN */ + glp_ftran(P, work); + /* store values of basic variables, check primal feasibility */ + P->pbs_stat = GLP_FEAS; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat != GLP_BS) + continue; + row->prim = work[row->bind]; + type = row->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(row->lb); + if (row->prim < row->lb - eps) + P->pbs_stat = GLP_INFEAS; + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(row->ub); + if (row->prim > row->ub + eps) + P->pbs_stat = GLP_INFEAS; + } + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat != GLP_BS) + continue; + col->prim = work[col->bind]; + type = col->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(col->lb); + if (col->prim < col->lb - eps) + P->pbs_stat = GLP_INFEAS; + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { eps = 1e-6 + 1e-9 * fabs(col->ub); + if (col->prim > col->ub + eps) + P->pbs_stat = GLP_INFEAS; + } + } + /* compute value of the objective function */ + P->obj_val = P->c0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + P->obj_val += col->coef * col->prim; + } + /* build vector cB of objective coefficients at basic variables */ + for (i = 1; i <= P->m; i++) + work[i] = 0.0; + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + work[col->bind] = col->coef; + } + /* compute vector of simplex multipliers pi = inv(B') * cB */ + glp_btran(P, work); + /* compute and store reduced costs of non-basic variables d[j] = + c[j] - N'[j] * pi, check dual feasibility */ + P->dbs_stat = GLP_FEAS; + for (i = 1; i <= P->m; i++) + { row = P->row[i]; + if (row->stat == GLP_BS) + { row->dual = 0.0; + continue; + } + /* N[j] is i-th column of matrix (I|-A) */ + row->dual = - work[i]; +#if 0 /* 07/III-2013 */ + type = row->type; + temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); + if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || + (type == GLP_FR || type == GLP_UP) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#else + stat = row->stat; + temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); + if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || + (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#endif + } + for (j = 1; j <= P->n; j++) + { col = P->col[j]; + if (col->stat == GLP_BS) + { col->dual = 0.0; + continue; + } + /* N[j] is (m+j)-th column of matrix (I|-A) */ + col->dual = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + col->dual += aij->val * work[aij->row->i]; +#if 0 /* 07/III-2013 */ + type = col->type; + temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); + if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || + (type == GLP_FR || type == GLP_UP) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#else + stat = col->stat; + temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); + if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || + (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) + P->dbs_stat = GLP_INFEAS; +#endif + } + /* free working array */ + xfree(work); + ret = 0; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* glp_eval_tab_row - compute row of the simplex tableau +* +* SYNOPSIS +* +* int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_eval_tab_row computes a row of the current simplex +* tableau for the basic variable, which is specified by the number k: +* if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, +* x[k] is (k-m)-th structural variable, where m is number of rows, and +* n is number of columns. The current basis must be available. +* +* The routine stores column indices and numerical values of non-zero +* elements of the computed row using sparse format to the locations +* ind[1], ..., ind[len] and val[1], ..., val[len], respectively, where +* 0 <= len <= n is number of non-zeros returned on exit. +* +* Element indices stored in the array ind have the same sense as the +* index k, i.e. indices 1 to m denote auxiliary variables and indices +* m+1 to m+n denote structural ones (all these variables are obviously +* non-basic by definition). +* +* The computed row shows how the specified basic variable x[k] = xB[i] +* depends on non-basic variables: +* +* xB[i] = alfa[i,1]*xN[1] + alfa[i,2]*xN[2] + ... + alfa[i,n]*xN[n], +* +* where alfa[i,j] are elements of the simplex table row, xN[j] are +* non-basic (auxiliary and structural) variables. +* +* RETURNS +* +* The routine returns number of non-zero elements in the simplex table +* row stored in the arrays ind and val. +* +* BACKGROUND +* +* The system of equality constraints of the LP problem is: +* +* xR = A * xS, (1) +* +* where xR is the vector of auxliary variables, xS is the vector of +* structural variables, A is the matrix of constraint coefficients. +* +* The system (1) can be written in homogenous form as follows: +* +* A~ * x = 0, (2) +* +* where A~ = (I | -A) is the augmented constraint matrix (has m rows +* and m+n columns), x = (xR | xS) is the vector of all (auxiliary and +* structural) variables. +* +* By definition for the current basis we have: +* +* A~ = (B | N), (3) +* +* where B is the basis matrix. Thus, the system (2) can be written as: +* +* B * xB + N * xN = 0. (4) +* +* From (4) it follows that: +* +* xB = A^ * xN, (5) +* +* where the matrix +* +* A^ = - inv(B) * N (6) +* +* is called the simplex table. +* +* It is understood that i-th row of the simplex table is: +* +* e * A^ = - e * inv(B) * N, (7) +* +* where e is a unity vector with e[i] = 1. +* +* To compute i-th row of the simplex table the routine first computes +* i-th row of the inverse: +* +* rho = inv(B') * e, (8) +* +* where B' is a matrix transposed to B, and then computes elements of +* i-th row of the simplex table as scalar products: +* +* alfa[i,j] = - rho * N[j] for all j, (9) +* +* where N[j] is a column of the augmented constraint matrix A~, which +* corresponds to some non-basic auxiliary or structural variable. */ + +int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]) +{ int m = lp->m; + int n = lp->n; + int i, t, len, lll, *iii; + double alfa, *rho, *vvv; + if (!(m == 0 || lp->valid)) + xerror("glp_eval_tab_row: basis factorization does not exist\n" + ); + if (!(1 <= k && k <= m+n)) + xerror("glp_eval_tab_row: k = %d; variable number out of range" + , k); + /* determine xB[i] which corresponds to x[k] */ + if (k <= m) + i = glp_get_row_bind(lp, k); + else + i = glp_get_col_bind(lp, k-m); + if (i == 0) + xerror("glp_eval_tab_row: k = %d; variable must be basic", k); + xassert(1 <= i && i <= m); + /* allocate working arrays */ + rho = xcalloc(1+m, sizeof(double)); + iii = xcalloc(1+m, sizeof(int)); + vvv = xcalloc(1+m, sizeof(double)); + /* compute i-th row of the inverse; see (8) */ + for (t = 1; t <= m; t++) rho[t] = 0.0; + rho[i] = 1.0; + glp_btran(lp, rho); + /* compute i-th row of the simplex table */ + len = 0; + for (k = 1; k <= m+n; k++) + { if (k <= m) + { /* x[k] is auxiliary variable, so N[k] is a unity column */ + if (glp_get_row_stat(lp, k) == GLP_BS) continue; + /* compute alfa[i,j]; see (9) */ + alfa = - rho[k]; + } + else + { /* x[k] is structural variable, so N[k] is a column of the + original constraint matrix A with negative sign */ + if (glp_get_col_stat(lp, k-m) == GLP_BS) continue; + /* compute alfa[i,j]; see (9) */ + lll = glp_get_mat_col(lp, k-m, iii, vvv); + alfa = 0.0; + for (t = 1; t <= lll; t++) alfa += rho[iii[t]] * vvv[t]; + } + /* store alfa[i,j] */ + if (alfa != 0.0) len++, ind[len] = k, val[len] = alfa; + } + xassert(len <= n); + /* free working arrays */ + xfree(rho); + xfree(iii); + xfree(vvv); + /* return to the calling program */ + return len; +} + +/*********************************************************************** +* NAME +* +* glp_eval_tab_col - compute column of the simplex tableau +* +* SYNOPSIS +* +* int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_eval_tab_col computes a column of the current simplex +* table for the non-basic variable, which is specified by the number k: +* if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, +* x[k] is (k-m)-th structural variable, where m is number of rows, and +* n is number of columns. The current basis must be available. +* +* The routine stores row indices and numerical values of non-zero +* elements of the computed column using sparse format to the locations +* ind[1], ..., ind[len] and val[1], ..., val[len] respectively, where +* 0 <= len <= m is number of non-zeros returned on exit. +* +* Element indices stored in the array ind have the same sense as the +* index k, i.e. indices 1 to m denote auxiliary variables and indices +* m+1 to m+n denote structural ones (all these variables are obviously +* basic by the definition). +* +* The computed column shows how basic variables depend on the specified +* non-basic variable x[k] = xN[j]: +* +* xB[1] = ... + alfa[1,j]*xN[j] + ... +* xB[2] = ... + alfa[2,j]*xN[j] + ... +* . . . . . . +* xB[m] = ... + alfa[m,j]*xN[j] + ... +* +* where alfa[i,j] are elements of the simplex table column, xB[i] are +* basic (auxiliary and structural) variables. +* +* RETURNS +* +* The routine returns number of non-zero elements in the simplex table +* column stored in the arrays ind and val. +* +* BACKGROUND +* +* As it was explained in comments to the routine glp_eval_tab_row (see +* above) the simplex table is the following matrix: +* +* A^ = - inv(B) * N. (1) +* +* Therefore j-th column of the simplex table is: +* +* A^ * e = - inv(B) * N * e = - inv(B) * N[j], (2) +* +* where e is a unity vector with e[j] = 1, B is the basis matrix, N[j] +* is a column of the augmented constraint matrix A~, which corresponds +* to the given non-basic auxiliary or structural variable. */ + +int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]) +{ int m = lp->m; + int n = lp->n; + int t, len, stat; + double *col; + if (!(m == 0 || lp->valid)) + xerror("glp_eval_tab_col: basis factorization does not exist\n" + ); + if (!(1 <= k && k <= m+n)) + xerror("glp_eval_tab_col: k = %d; variable number out of range" + , k); + if (k <= m) + stat = glp_get_row_stat(lp, k); + else + stat = glp_get_col_stat(lp, k-m); + if (stat == GLP_BS) + xerror("glp_eval_tab_col: k = %d; variable must be non-basic", + k); + /* obtain column N[k] with negative sign */ + col = xcalloc(1+m, sizeof(double)); + for (t = 1; t <= m; t++) col[t] = 0.0; + if (k <= m) + { /* x[k] is auxiliary variable, so N[k] is a unity column */ + col[k] = -1.0; + } + else + { /* x[k] is structural variable, so N[k] is a column of the + original constraint matrix A with negative sign */ + len = glp_get_mat_col(lp, k-m, ind, val); + for (t = 1; t <= len; t++) col[ind[t]] = val[t]; + } + /* compute column of the simplex table, which corresponds to the + specified non-basic variable x[k] */ + glp_ftran(lp, col); + len = 0; + for (t = 1; t <= m; t++) + { if (col[t] != 0.0) + { len++; + ind[len] = glp_get_bhead(lp, t); + val[len] = col[t]; + } + } + xfree(col); + /* return to the calling program */ + return len; +} + +/*********************************************************************** +* NAME +* +* glp_transform_row - transform explicitly specified row +* +* SYNOPSIS +* +* int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_transform_row performs the same operation as the +* routine glp_eval_tab_row with exception that the row to be +* transformed is specified explicitly as a sparse vector. +* +* The explicitly specified row may be thought as a linear form: +* +* x = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], (1) +* +* where x is an auxiliary variable for this row, a[j] are coefficients +* of the linear form, x[m+j] are structural variables. +* +* On entry column indices and numerical values of non-zero elements of +* the row should be stored in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], where len is the number of non-zero elements. +* +* This routine uses the system of equality constraints and the current +* basis in order to express the auxiliary variable x in (1) through the +* current non-basic variables (as if the transformed row were added to +* the problem object and its auxiliary variable were basic), i.e. the +* resultant row has the form: +* +* x = alfa[1]*xN[1] + alfa[2]*xN[2] + ... + alfa[n]*xN[n], (2) +* +* where xN[j] are non-basic (auxiliary or structural) variables, n is +* the number of columns in the LP problem object. +* +* On exit the routine stores indices and numerical values of non-zero +* elements of the resultant row (2) in locations ind[1], ..., ind[len'] +* and val[1], ..., val[len'], where 0 <= len' <= n is the number of +* non-zero elements in the resultant row returned by the routine. Note +* that indices (numbers) of non-basic variables stored in the array ind +* correspond to original ordinal numbers of variables: indices 1 to m +* mean auxiliary variables and indices m+1 to m+n mean structural ones. +* +* RETURNS +* +* The routine returns len', which is the number of non-zero elements in +* the resultant row stored in the arrays ind and val. +* +* BACKGROUND +* +* The explicitly specified row (1) is transformed in the same way as it +* were the objective function row. +* +* From (1) it follows that: +* +* x = aB * xB + aN * xN, (3) +* +* where xB is the vector of basic variables, xN is the vector of +* non-basic variables. +* +* The simplex table, which corresponds to the current basis, is: +* +* xB = [-inv(B) * N] * xN. (4) +* +* Therefore substituting xB from (4) to (3) we have: +* +* x = aB * [-inv(B) * N] * xN + aN * xN = +* (5) +* = rho * (-N) * xN + aN * xN = alfa * xN, +* +* where: +* +* rho = inv(B') * aB, (6) +* +* and +* +* alfa = aN + rho * (-N) (7) +* +* is the resultant row computed by the routine. */ + +int glp_transform_row(glp_prob *P, int len, int ind[], double val[]) +{ int i, j, k, m, n, t, lll, *iii; + double alfa, *a, *aB, *rho, *vvv; + if (!glp_bf_exists(P)) + xerror("glp_transform_row: basis factorization does not exist " + "\n"); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* unpack the row to be transformed to the array a */ + a = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) a[j] = 0.0; + if (!(0 <= len && len <= n)) + xerror("glp_transform_row: len = %d; invalid row length\n", + len); + for (t = 1; t <= len; t++) + { j = ind[t]; + if (!(1 <= j && j <= n)) + xerror("glp_transform_row: ind[%d] = %d; column index out o" + "f range\n", t, j); + if (val[t] == 0.0) + xerror("glp_transform_row: val[%d] = 0; zero coefficient no" + "t allowed\n", t); + if (a[j] != 0.0) + xerror("glp_transform_row: ind[%d] = %d; duplicate column i" + "ndices not allowed\n", t, j); + a[j] = val[t]; + } + /* construct the vector aB */ + aB = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) + { k = glp_get_bhead(P, i); + /* xB[i] is k-th original variable */ + xassert(1 <= k && k <= m+n); + aB[i] = (k <= m ? 0.0 : a[k-m]); + } + /* solve the system B'*rho = aB to compute the vector rho */ + rho = aB, glp_btran(P, rho); + /* compute coefficients at non-basic auxiliary variables */ + len = 0; + for (i = 1; i <= m; i++) + { if (glp_get_row_stat(P, i) != GLP_BS) + { alfa = - rho[i]; + if (alfa != 0.0) + { len++; + ind[len] = i; + val[len] = alfa; + } + } + } + /* compute coefficients at non-basic structural variables */ + iii = xcalloc(1+m, sizeof(int)); + vvv = xcalloc(1+m, sizeof(double)); + for (j = 1; j <= n; j++) + { if (glp_get_col_stat(P, j) != GLP_BS) + { alfa = a[j]; + lll = glp_get_mat_col(P, j, iii, vvv); + for (t = 1; t <= lll; t++) alfa += vvv[t] * rho[iii[t]]; + if (alfa != 0.0) + { len++; + ind[len] = m+j; + val[len] = alfa; + } + } + } + xassert(len <= n); + xfree(iii); + xfree(vvv); + xfree(aB); + xfree(a); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_transform_col - transform explicitly specified column +* +* SYNOPSIS +* +* int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +* +* DESCRIPTION +* +* The routine glp_transform_col performs the same operation as the +* routine glp_eval_tab_col with exception that the column to be +* transformed is specified explicitly as a sparse vector. +* +* The explicitly specified column may be thought as if it were added +* to the original system of equality constraints: +* +* x[1] = a[1,1]*x[m+1] + ... + a[1,n]*x[m+n] + a[1]*x +* x[2] = a[2,1]*x[m+1] + ... + a[2,n]*x[m+n] + a[2]*x (1) +* . . . . . . . . . . . . . . . +* x[m] = a[m,1]*x[m+1] + ... + a[m,n]*x[m+n] + a[m]*x +* +* where x[i] are auxiliary variables, x[m+j] are structural variables, +* x is a structural variable for the explicitly specified column, a[i] +* are constraint coefficients for x. +* +* On entry row indices and numerical values of non-zero elements of +* the column should be stored in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], where len is the number of non-zero elements. +* +* This routine uses the system of equality constraints and the current +* basis in order to express the current basic variables through the +* structural variable x in (1) (as if the transformed column were added +* to the problem object and the variable x were non-basic), i.e. the +* resultant column has the form: +* +* xB[1] = ... + alfa[1]*x +* xB[2] = ... + alfa[2]*x (2) +* . . . . . . +* xB[m] = ... + alfa[m]*x +* +* where xB are basic (auxiliary and structural) variables, m is the +* number of rows in the problem object. +* +* On exit the routine stores indices and numerical values of non-zero +* elements of the resultant column (2) in locations ind[1], ..., +* ind[len'] and val[1], ..., val[len'], where 0 <= len' <= m is the +* number of non-zero element in the resultant column returned by the +* routine. Note that indices (numbers) of basic variables stored in +* the array ind correspond to original ordinal numbers of variables: +* indices 1 to m mean auxiliary variables and indices m+1 to m+n mean +* structural ones. +* +* RETURNS +* +* The routine returns len', which is the number of non-zero elements +* in the resultant column stored in the arrays ind and val. +* +* BACKGROUND +* +* The explicitly specified column (1) is transformed in the same way +* as any other column of the constraint matrix using the formula: +* +* alfa = inv(B) * a, (3) +* +* where alfa is the resultant column computed by the routine. */ + +int glp_transform_col(glp_prob *P, int len, int ind[], double val[]) +{ int i, m, t; + double *a, *alfa; + if (!glp_bf_exists(P)) + xerror("glp_transform_col: basis factorization does not exist " + "\n"); + m = glp_get_num_rows(P); + /* unpack the column to be transformed to the array a */ + a = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) a[i] = 0.0; + if (!(0 <= len && len <= m)) + xerror("glp_transform_col: len = %d; invalid column length\n", + len); + for (t = 1; t <= len; t++) + { i = ind[t]; + if (!(1 <= i && i <= m)) + xerror("glp_transform_col: ind[%d] = %d; row index out of r" + "ange\n", t, i); + if (val[t] == 0.0) + xerror("glp_transform_col: val[%d] = 0; zero coefficient no" + "t allowed\n", t); + if (a[i] != 0.0) + xerror("glp_transform_col: ind[%d] = %d; duplicate row indi" + "ces not allowed\n", t, i); + a[i] = val[t]; + } + /* solve the system B*a = alfa to compute the vector alfa */ + alfa = a, glp_ftran(P, alfa); + /* store resultant coefficients */ + len = 0; + for (i = 1; i <= m; i++) + { if (alfa[i] != 0.0) + { len++; + ind[len] = glp_get_bhead(P, i); + val[len] = alfa[i]; + } + } + xfree(a); + return len; +} + +/*********************************************************************** +* NAME +* +* glp_prim_rtest - perform primal ratio test +* +* SYNOPSIS +* +* int glp_prim_rtest(glp_prob *P, int len, const int ind[], +* const double val[], int dir, double eps); +* +* DESCRIPTION +* +* The routine glp_prim_rtest performs the primal ratio test using an +* explicitly specified column of the simplex table. +* +* The current basic solution associated with the LP problem object +* must be primal feasible. +* +* The explicitly specified column of the simplex table shows how the +* basic variables xB depend on some non-basic variable x (which is not +* necessarily presented in the problem object): +* +* xB[1] = ... + alfa[1] * x + ... +* xB[2] = ... + alfa[2] * x + ... (*) +* . . . . . . . . +* xB[m] = ... + alfa[m] * x + ... +* +* The column (*) is specifed on entry to the routine using the sparse +* format. Ordinal numbers of basic variables xB[i] should be placed in +* locations ind[1], ..., ind[len], where ordinal number 1 to m denote +* auxiliary variables, and ordinal numbers m+1 to m+n denote structural +* variables. The corresponding non-zero coefficients alfa[i] should be +* placed in locations val[1], ..., val[len]. The arrays ind and val are +* not changed on exit. +* +* The parameter dir specifies direction in which the variable x changes +* on entering the basis: +1 means increasing, -1 means decreasing. +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small alfa[j] of the row (*). +* +* The routine determines which basic variable (among specified in +* ind[1], ..., ind[len]) should leave the basis in order to keep primal +* feasibility. +* +* RETURNS +* +* The routine glp_prim_rtest returns the index piv in the arrays ind +* and val corresponding to the pivot element chosen, 1 <= piv <= len. +* If the adjacent basic solution is primal unbounded and therefore the +* choice cannot be made, the routine returns zero. +* +* COMMENTS +* +* If the non-basic variable x is presented in the LP problem object, +* the column (*) can be computed with the routine glp_eval_tab_col; +* otherwise it can be computed with the routine glp_transform_col. */ + +int glp_prim_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps) +{ int k, m, n, piv, t, type, stat; + double alfa, big, beta, lb, ub, temp, teta; + if (glp_get_prim_stat(P) != GLP_FEAS) + xerror("glp_prim_rtest: basic solution is not primal feasible " + "\n"); + if (!(dir == +1 || dir == -1)) + xerror("glp_prim_rtest: dir = %d; invalid parameter\n", dir); + if (!(0.0 < eps && eps < 1.0)) + xerror("glp_prim_rtest: eps = %g; invalid parameter\n", eps); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* initial settings */ + piv = 0, teta = DBL_MAX, big = 0.0; + /* walk through the entries of the specified column */ + for (t = 1; t <= len; t++) + { /* get the ordinal number of basic variable */ + k = ind[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_prim_rtest: ind[%d] = %d; variable number out o" + "f range\n", t, k); + /* determine type, bounds, status and primal value of basic + variable xB[i] = x[k] in the current basic solution */ + if (k <= m) + { type = glp_get_row_type(P, k); + lb = glp_get_row_lb(P, k); + ub = glp_get_row_ub(P, k); + stat = glp_get_row_stat(P, k); + beta = glp_get_row_prim(P, k); + } + else + { type = glp_get_col_type(P, k-m); + lb = glp_get_col_lb(P, k-m); + ub = glp_get_col_ub(P, k-m); + stat = glp_get_col_stat(P, k-m); + beta = glp_get_col_prim(P, k-m); + } + if (stat != GLP_BS) + xerror("glp_prim_rtest: ind[%d] = %d; non-basic variable no" + "t allowed\n", t, k); + /* determine influence coefficient at basic variable xB[i] + in the explicitly specified column and turn to the case of + increasing the variable x in order to simplify the program + logic */ + alfa = (dir > 0 ? + val[t] : - val[t]); + /* analyze main cases */ + if (type == GLP_FR) + { /* xB[i] is free variable */ + continue; + } + else if (type == GLP_LO) +lo: { /* xB[i] has an lower bound */ + if (alfa > - eps) continue; + temp = (lb - beta) / alfa; + } + else if (type == GLP_UP) +up: { /* xB[i] has an upper bound */ + if (alfa < + eps) continue; + temp = (ub - beta) / alfa; + } + else if (type == GLP_DB) + { /* xB[i] has both lower and upper bounds */ + if (alfa < 0.0) goto lo; else goto up; + } + else if (type == GLP_FX) + { /* xB[i] is fixed variable */ + if (- eps < alfa && alfa < + eps) continue; + temp = 0.0; + } + else + xassert(type != type); + /* if the value of the variable xB[i] violates its lower or + upper bound (slightly, because the current basis is assumed + to be primal feasible), temp is negative; we can think this + happens due to round-off errors and the value is exactly on + the bound; this allows replacing temp by zero */ + if (temp < 0.0) temp = 0.0; + /* apply the minimal ratio test */ + if (teta > temp || teta == temp && big < fabs(alfa)) + piv = t, teta = temp, big = fabs(alfa); + } + /* return index of the pivot element chosen */ + return piv; +} + +/*********************************************************************** +* NAME +* +* glp_dual_rtest - perform dual ratio test +* +* SYNOPSIS +* +* int glp_dual_rtest(glp_prob *P, int len, const int ind[], +* const double val[], int dir, double eps); +* +* DESCRIPTION +* +* The routine glp_dual_rtest performs the dual ratio test using an +* explicitly specified row of the simplex table. +* +* The current basic solution associated with the LP problem object +* must be dual feasible. +* +* The explicitly specified row of the simplex table is a linear form +* that shows how some basic variable x (which is not necessarily +* presented in the problem object) depends on non-basic variables xN: +* +* x = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n]. (*) +* +* The row (*) is specified on entry to the routine using the sparse +* format. Ordinal numbers of non-basic variables xN[j] should be placed +* in locations ind[1], ..., ind[len], where ordinal numbers 1 to m +* denote auxiliary variables, and ordinal numbers m+1 to m+n denote +* structural variables. The corresponding non-zero coefficients alfa[j] +* should be placed in locations val[1], ..., val[len]. The arrays ind +* and val are not changed on exit. +* +* The parameter dir specifies direction in which the variable x changes +* on leaving the basis: +1 means that x goes to its lower bound, and -1 +* means that x goes to its upper bound. +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small alfa[j] of the row (*). +* +* The routine determines which non-basic variable (among specified in +* ind[1], ..., ind[len]) should enter the basis in order to keep dual +* feasibility. +* +* RETURNS +* +* The routine glp_dual_rtest returns the index piv in the arrays ind +* and val corresponding to the pivot element chosen, 1 <= piv <= len. +* If the adjacent basic solution is dual unbounded and therefore the +* choice cannot be made, the routine returns zero. +* +* COMMENTS +* +* If the basic variable x is presented in the LP problem object, the +* row (*) can be computed with the routine glp_eval_tab_row; otherwise +* it can be computed with the routine glp_transform_row. */ + +int glp_dual_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps) +{ int k, m, n, piv, t, stat; + double alfa, big, cost, obj, temp, teta; + if (glp_get_dual_stat(P) != GLP_FEAS) + xerror("glp_dual_rtest: basic solution is not dual feasible\n") + ; + if (!(dir == +1 || dir == -1)) + xerror("glp_dual_rtest: dir = %d; invalid parameter\n", dir); + if (!(0.0 < eps && eps < 1.0)) + xerror("glp_dual_rtest: eps = %g; invalid parameter\n", eps); + m = glp_get_num_rows(P); + n = glp_get_num_cols(P); + /* take into account optimization direction */ + obj = (glp_get_obj_dir(P) == GLP_MIN ? +1.0 : -1.0); + /* initial settings */ + piv = 0, teta = DBL_MAX, big = 0.0; + /* walk through the entries of the specified row */ + for (t = 1; t <= len; t++) + { /* get ordinal number of non-basic variable */ + k = ind[t]; + if (!(1 <= k && k <= m+n)) + xerror("glp_dual_rtest: ind[%d] = %d; variable number out o" + "f range\n", t, k); + /* determine status and reduced cost of non-basic variable + x[k] = xN[j] in the current basic solution */ + if (k <= m) + { stat = glp_get_row_stat(P, k); + cost = glp_get_row_dual(P, k); + } + else + { stat = glp_get_col_stat(P, k-m); + cost = glp_get_col_dual(P, k-m); + } + if (stat == GLP_BS) + xerror("glp_dual_rtest: ind[%d] = %d; basic variable not al" + "lowed\n", t, k); + /* determine influence coefficient at non-basic variable xN[j] + in the explicitly specified row and turn to the case of + increasing the variable x in order to simplify the program + logic */ + alfa = (dir > 0 ? + val[t] : - val[t]); + /* analyze main cases */ + if (stat == GLP_NL) + { /* xN[j] is on its lower bound */ + if (alfa < + eps) continue; + temp = (obj * cost) / alfa; + } + else if (stat == GLP_NU) + { /* xN[j] is on its upper bound */ + if (alfa > - eps) continue; + temp = (obj * cost) / alfa; + } + else if (stat == GLP_NF) + { /* xN[j] is non-basic free variable */ + if (- eps < alfa && alfa < + eps) continue; + temp = 0.0; + } + else if (stat == GLP_NS) + { /* xN[j] is non-basic fixed variable */ + continue; + } + else + xassert(stat != stat); + /* if the reduced cost of the variable xN[j] violates its zero + bound (slightly, because the current basis is assumed to be + dual feasible), temp is negative; we can think this happens + due to round-off errors and the reduced cost is exact zero; + this allows replacing temp by zero */ + if (temp < 0.0) temp = 0.0; + /* apply the minimal ratio test */ + if (teta > temp || teta == temp && big < fabs(alfa)) + piv = t, teta = temp, big = fabs(alfa); + } + /* return index of the pivot element chosen */ + return piv; +} + +/*********************************************************************** +* NAME +* +* glp_analyze_row - simulate one iteration of dual simplex method +* +* SYNOPSIS +* +* int glp_analyze_row(glp_prob *P, int len, const int ind[], +* const double val[], int type, double rhs, double eps, int *piv, +* double *x, double *dx, double *y, double *dy, double *dz); +* +* DESCRIPTION +* +* Let the current basis be optimal or dual feasible, and there be +* specified a row (constraint), which is violated by the current basic +* solution. The routine glp_analyze_row simulates one iteration of the +* dual simplex method to determine some information on the adjacent +* basis (see below), where the specified row becomes active constraint +* (i.e. its auxiliary variable becomes non-basic). +* +* The current basic solution associated with the problem object passed +* to the routine must be dual feasible, and its primal components must +* be defined. +* +* The row to be analyzed must be previously transformed either with +* the routine glp_eval_tab_row (if the row is in the problem object) +* or with the routine glp_transform_row (if the row is external, i.e. +* not in the problem object). This is needed to express the row only +* through (auxiliary and structural) variables, which are non-basic in +* the current basis: +* +* y = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n], +* +* where y is an auxiliary variable of the row, alfa[j] is an influence +* coefficient, xN[j] is a non-basic variable. +* +* The row is passed to the routine in sparse format. Ordinal numbers +* of non-basic variables are stored in locations ind[1], ..., ind[len], +* where numbers 1 to m denote auxiliary variables while numbers m+1 to +* m+n denote structural variables. Corresponding non-zero coefficients +* alfa[j] are stored in locations val[1], ..., val[len]. The arrays +* ind and val are ot changed on exit. +* +* The parameters type and rhs specify the row type and its right-hand +* side as follows: +* +* type = GLP_LO: y = sum alfa[j] * xN[j] >= rhs +* +* type = GLP_UP: y = sum alfa[j] * xN[j] <= rhs +* +* The parameter eps is an absolute tolerance (small positive number) +* used by the routine to skip small coefficients alfa[j] on performing +* the dual ratio test. +* +* If the operation was successful, the routine stores the following +* information to corresponding location (if some parameter is NULL, +* its value is not stored): +* +* piv index in the array ind and val, 1 <= piv <= len, determining +* the non-basic variable, which would enter the adjacent basis; +* +* x value of the non-basic variable in the current basis; +* +* dx difference between values of the non-basic variable in the +* adjacent and current bases, dx = x.new - x.old; +* +* y value of the row (i.e. of its auxiliary variable) in the +* current basis; +* +* dy difference between values of the row in the adjacent and +* current bases, dy = y.new - y.old; +* +* dz difference between values of the objective function in the +* adjacent and current bases, dz = z.new - z.old. Note that in +* case of minimization dz >= 0, and in case of maximization +* dz <= 0, i.e. in the adjacent basis the objective function +* always gets worse (degrades). */ + +int _glp_analyze_row(glp_prob *P, int len, const int ind[], + const double val[], int type, double rhs, double eps, int *_piv, + double *_x, double *_dx, double *_y, double *_dy, double *_dz) +{ int t, k, dir, piv, ret = 0; + double x, dx, y, dy, dz; + if (P->pbs_stat == GLP_UNDEF) + xerror("glp_analyze_row: primal basic solution components are " + "undefined\n"); + if (P->dbs_stat != GLP_FEAS) + xerror("glp_analyze_row: basic solution is not dual feasible\n" + ); + /* compute the row value y = sum alfa[j] * xN[j] in the current + basis */ + if (!(0 <= len && len <= P->n)) + xerror("glp_analyze_row: len = %d; invalid row length\n", len); + y = 0.0; + for (t = 1; t <= len; t++) + { /* determine value of x[k] = xN[j] in the current basis */ + k = ind[t]; + if (!(1 <= k && k <= P->m+P->n)) + xerror("glp_analyze_row: ind[%d] = %d; row/column index out" + " of range\n", t, k); + if (k <= P->m) + { /* x[k] is auxiliary variable */ + if (P->row[k]->stat == GLP_BS) + xerror("glp_analyze_row: ind[%d] = %d; basic auxiliary v" + "ariable is not allowed\n", t, k); + x = P->row[k]->prim; + } + else + { /* x[k] is structural variable */ + if (P->col[k-P->m]->stat == GLP_BS) + xerror("glp_analyze_row: ind[%d] = %d; basic structural " + "variable is not allowed\n", t, k); + x = P->col[k-P->m]->prim; + } + y += val[t] * x; + } + /* check if the row is primal infeasible in the current basis, + i.e. the constraint is violated at the current point */ + if (type == GLP_LO) + { if (y >= rhs) + { /* the constraint is not violated */ + ret = 1; + goto done; + } + /* in the adjacent basis y goes to its lower bound */ + dir = +1; + } + else if (type == GLP_UP) + { if (y <= rhs) + { /* the constraint is not violated */ + ret = 1; + goto done; + } + /* in the adjacent basis y goes to its upper bound */ + dir = -1; + } + else + xerror("glp_analyze_row: type = %d; invalid parameter\n", + type); + /* compute dy = y.new - y.old */ + dy = rhs - y; + /* perform dual ratio test to determine which non-basic variable + should enter the adjacent basis to keep it dual feasible */ + piv = glp_dual_rtest(P, len, ind, val, dir, eps); + if (piv == 0) + { /* no dual feasible adjacent basis exists */ + ret = 2; + goto done; + } + /* non-basic variable x[k] = xN[j] should enter the basis */ + k = ind[piv]; + xassert(1 <= k && k <= P->m+P->n); + /* determine its value in the current basis */ + if (k <= P->m) + x = P->row[k]->prim; + else + x = P->col[k-P->m]->prim; + /* compute dx = x.new - x.old = dy / alfa[j] */ + xassert(val[piv] != 0.0); + dx = dy / val[piv]; + /* compute dz = z.new - z.old = d[j] * dx, where d[j] is reduced + cost of xN[j] in the current basis */ + if (k <= P->m) + dz = P->row[k]->dual * dx; + else + dz = P->col[k-P->m]->dual * dx; + /* store the analysis results */ + if (_piv != NULL) *_piv = piv; + if (_x != NULL) *_x = x; + if (_dx != NULL) *_dx = dx; + if (_y != NULL) *_y = y; + if (_dy != NULL) *_dy = dy; + if (_dz != NULL) *_dz = dz; +done: return ret; +} + +#if 0 +int main(void) +{ /* example program for the routine glp_analyze_row */ + glp_prob *P; + glp_smcp parm; + int i, k, len, piv, ret, ind[1+100]; + double rhs, x, dx, y, dy, dz, val[1+100]; + P = glp_create_prob(); + /* read plan.mps (see glpk/examples) */ + ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "plan.mps"); + glp_assert(ret == 0); + /* and solve it to optimality */ + ret = glp_simplex(P, NULL); + glp_assert(ret == 0); + glp_assert(glp_get_status(P) == GLP_OPT); + /* the optimal objective value is 296.217 */ + /* we would like to know what happens if we would add a new row + (constraint) to plan.mps: + .01 * bin1 + .01 * bin2 + .02 * bin4 + .02 * bin5 <= 12 */ + /* first, we specify this new row */ + glp_create_index(P); + len = 0; + ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; + ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; + rhs = 12; + /* then we can compute value of the row (i.e. of its auxiliary + variable) in the current basis to see if the constraint is + violated */ + y = 0.0; + for (k = 1; k <= len; k++) + y += val[k] * glp_get_col_prim(P, ind[k]); + glp_printf("y = %g\n", y); + /* this prints y = 15.1372, so the constraint is violated, since + we require that y <= rhs = 12 */ + /* now we transform the row to express it only through non-basic + (auxiliary and artificial) variables */ + len = glp_transform_row(P, len, ind, val); + /* finally, we simulate one step of the dual simplex method to + obtain necessary information for the adjacent basis */ + ret = _glp_analyze_row(P, len, ind, val, GLP_UP, rhs, 1e-9, &piv, + &x, &dx, &y, &dy, &dz); + glp_assert(ret == 0); + glp_printf("k = %d, x = %g; dx = %g; y = %g; dy = %g; dz = %g\n", + ind[piv], x, dx, y, dy, dz); + /* this prints dz = 5.64418 and means that in the adjacent basis + the objective function would be 296.217 + 5.64418 = 301.861 */ + /* now we actually include the row into the problem object; note + that the arrays ind and val are clobbered, so we need to build + them once again */ + len = 0; + ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; + ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; + ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; + rhs = 12; + i = glp_add_rows(P, 1); + glp_set_row_bnds(P, i, GLP_UP, 0, rhs); + glp_set_mat_row(P, i, len, ind, val); + /* and perform one dual simplex iteration */ + glp_init_smcp(&parm); + parm.meth = GLP_DUAL; + parm.it_lim = 1; + glp_simplex(P, &parm); + /* the current objective value is 301.861 */ + return 0; +} +#endif + +/*********************************************************************** +* NAME +* +* glp_analyze_bound - analyze active bound of non-basic variable +* +* SYNOPSIS +* +* void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, +* double *limit2, int *var2); +* +* DESCRIPTION +* +* The routine glp_analyze_bound analyzes the effect of varying the +* active bound of specified non-basic variable. +* +* The non-basic variable is specified by the parameter k, where +* 1 <= k <= m means auxiliary variable of corresponding row while +* m+1 <= k <= m+n means structural variable (column). +* +* Note that the current basic solution must be optimal, and the basis +* factorization must exist. +* +* Results of the analysis have the following meaning. +* +* value1 is the minimal value of the active bound, at which the basis +* still remains primal feasible and thus optimal. -DBL_MAX means that +* the active bound has no lower limit. +* +* var1 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) basic variable, which reaches its bound first and thereby +* limits further decreasing the active bound being analyzed. +* if value1 = -DBL_MAX, var1 is set to 0. +* +* value2 is the maximal value of the active bound, at which the basis +* still remains primal feasible and thus optimal. +DBL_MAX means that +* the active bound has no upper limit. +* +* var2 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) basic variable, which reaches its bound first and thereby +* limits further increasing the active bound being analyzed. +* if value2 = +DBL_MAX, var2 is set to 0. */ + +void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, + double *value2, int *var2) +{ GLPROW *row; + GLPCOL *col; + int m, n, stat, kase, p, len, piv, *ind; + double x, new_x, ll, uu, xx, delta, *val; +#if 0 /* 04/IV-2016 */ + /* sanity checks */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_analyze_bound: P = %p; invalid problem object\n", + P); +#endif + m = P->m, n = P->n; + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + xerror("glp_analyze_bound: optimal basic solution required\n"); + if (!(m == 0 || P->valid)) + xerror("glp_analyze_bound: basis factorization required\n"); + if (!(1 <= k && k <= m+n)) + xerror("glp_analyze_bound: k = %d; variable number out of rang" + "e\n", k); + /* retrieve information about the specified non-basic variable + x[k] whose active bound is to be analyzed */ + if (k <= m) + { row = P->row[k]; + stat = row->stat; + x = row->prim; + } + else + { col = P->col[k-m]; + stat = col->stat; + x = col->prim; + } + if (stat == GLP_BS) + xerror("glp_analyze_bound: k = %d; basic variable not allowed " + "\n", k); + /* allocate working arrays */ + ind = xcalloc(1+m, sizeof(int)); + val = xcalloc(1+m, sizeof(double)); + /* compute column of the simplex table corresponding to the + non-basic variable x[k] */ + len = glp_eval_tab_col(P, k, ind, val); + xassert(0 <= len && len <= m); + /* perform analysis */ + for (kase = -1; kase <= +1; kase += 2) + { /* kase < 0 means active bound of x[k] is decreasing; + kase > 0 means active bound of x[k] is increasing */ + /* use the primal ratio test to determine some basic variable + x[p] which reaches its bound first */ + piv = glp_prim_rtest(P, len, ind, val, kase, 1e-9); + if (piv == 0) + { /* nothing limits changing the active bound of x[k] */ + p = 0; + new_x = (kase < 0 ? -DBL_MAX : +DBL_MAX); + goto store; + } + /* basic variable x[p] limits changing the active bound of + x[k]; determine its value in the current basis */ + xassert(1 <= piv && piv <= len); + p = ind[piv]; + if (p <= m) + { row = P->row[p]; + ll = glp_get_row_lb(P, row->i); + uu = glp_get_row_ub(P, row->i); + stat = row->stat; + xx = row->prim; + } + else + { col = P->col[p-m]; + ll = glp_get_col_lb(P, col->j); + uu = glp_get_col_ub(P, col->j); + stat = col->stat; + xx = col->prim; + } + xassert(stat == GLP_BS); + /* determine delta x[p] = bound of x[p] - value of x[p] */ + if (kase < 0 && val[piv] > 0.0 || + kase > 0 && val[piv] < 0.0) + { /* delta x[p] < 0, so x[p] goes toward its lower bound */ + xassert(ll != -DBL_MAX); + delta = ll - xx; + } + else + { /* delta x[p] > 0, so x[p] goes toward its upper bound */ + xassert(uu != +DBL_MAX); + delta = uu - xx; + } + /* delta x[p] = alfa[p,k] * delta x[k], so new x[k] = x[k] + + delta x[k] = x[k] + delta x[p] / alfa[p,k] is the value of + x[k] in the adjacent basis */ + xassert(val[piv] != 0.0); + new_x = x + delta / val[piv]; +store: /* store analysis results */ + if (kase < 0) + { if (value1 != NULL) *value1 = new_x; + if (var1 != NULL) *var1 = p; + } + else + { if (value2 != NULL) *value2 = new_x; + if (var2 != NULL) *var2 = p; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* NAME +* +* glp_analyze_coef - analyze objective coefficient at basic variable +* +* SYNOPSIS +* +* void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, +* double *value1, double *coef2, int *var2, double *value2); +* +* DESCRIPTION +* +* The routine glp_analyze_coef analyzes the effect of varying the +* objective coefficient at specified basic variable. +* +* The basic variable is specified by the parameter k, where +* 1 <= k <= m means auxiliary variable of corresponding row while +* m+1 <= k <= m+n means structural variable (column). +* +* Note that the current basic solution must be optimal, and the basis +* factorization must exist. +* +* Results of the analysis have the following meaning. +* +* coef1 is the minimal value of the objective coefficient, at which +* the basis still remains dual feasible and thus optimal. -DBL_MAX +* means that the objective coefficient has no lower limit. +* +* var1 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) non-basic variable, whose reduced cost reaches its zero +* bound first and thereby limits further decreasing the objective +* coefficient being analyzed. If coef1 = -DBL_MAX, var1 is set to 0. +* +* value1 is value of the basic variable being analyzed in an adjacent +* basis, which is defined as follows. Let the objective coefficient +* reaches its minimal value (coef1) and continues decreasing. Then the +* reduced cost of the limiting non-basic variable (var1) becomes dual +* infeasible and the current basis becomes non-optimal that forces the +* limiting non-basic variable to enter the basis replacing there some +* basic variable that leaves the basis to keep primal feasibility. +* Should note that on determining the adjacent basis current bounds +* of the basic variable being analyzed are ignored as if it were free +* (unbounded) variable, so it cannot leave the basis. It may happen +* that no dual feasible adjacent basis exists, in which case value1 is +* set to -DBL_MAX or +DBL_MAX. +* +* coef2 is the maximal value of the objective coefficient, at which +* the basis still remains dual feasible and thus optimal. +DBL_MAX +* means that the objective coefficient has no upper limit. +* +* var2 is the ordinal number of an auxiliary (1 to m) or structural +* (m+1 to n) non-basic variable, whose reduced cost reaches its zero +* bound first and thereby limits further increasing the objective +* coefficient being analyzed. If coef2 = +DBL_MAX, var2 is set to 0. +* +* value2 is value of the basic variable being analyzed in an adjacent +* basis, which is defined exactly in the same way as value1 above with +* exception that now the objective coefficient is increasing. */ + +void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, + double *value1, double *coef2, int *var2, double *value2) +{ GLPROW *row; GLPCOL *col; + int m, n, type, stat, kase, p, q, dir, clen, cpiv, rlen, rpiv, + *cind, *rind; + double lb, ub, coef, x, lim_coef, new_x, d, delta, ll, uu, xx, + *rval, *cval; +#if 0 /* 04/IV-2016 */ + /* sanity checks */ + if (P == NULL || P->magic != GLP_PROB_MAGIC) + xerror("glp_analyze_coef: P = %p; invalid problem object\n", + P); +#endif + m = P->m, n = P->n; + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + xerror("glp_analyze_coef: optimal basic solution required\n"); + if (!(m == 0 || P->valid)) + xerror("glp_analyze_coef: basis factorization required\n"); + if (!(1 <= k && k <= m+n)) + xerror("glp_analyze_coef: k = %d; variable number out of range" + "\n", k); + /* retrieve information about the specified basic variable x[k] + whose objective coefficient c[k] is to be analyzed */ + if (k <= m) + { row = P->row[k]; + type = row->type; + lb = row->lb; + ub = row->ub; + coef = 0.0; + stat = row->stat; + x = row->prim; + } + else + { col = P->col[k-m]; + type = col->type; + lb = col->lb; + ub = col->ub; + coef = col->coef; + stat = col->stat; + x = col->prim; + } + if (stat != GLP_BS) + xerror("glp_analyze_coef: k = %d; non-basic variable not allow" + "ed\n", k); + /* allocate working arrays */ + cind = xcalloc(1+m, sizeof(int)); + cval = xcalloc(1+m, sizeof(double)); + rind = xcalloc(1+n, sizeof(int)); + rval = xcalloc(1+n, sizeof(double)); + /* compute row of the simplex table corresponding to the basic + variable x[k] */ + rlen = glp_eval_tab_row(P, k, rind, rval); + xassert(0 <= rlen && rlen <= n); + /* perform analysis */ + for (kase = -1; kase <= +1; kase += 2) + { /* kase < 0 means objective coefficient c[k] is decreasing; + kase > 0 means objective coefficient c[k] is increasing */ + /* note that decreasing c[k] is equivalent to increasing dual + variable lambda[k] and vice versa; we need to correctly set + the dir flag as required by the routine glp_dual_rtest */ + if (P->dir == GLP_MIN) + dir = - kase; + else if (P->dir == GLP_MAX) + dir = + kase; + else + xassert(P != P); + /* use the dual ratio test to determine non-basic variable + x[q] whose reduced cost d[q] reaches zero bound first */ + rpiv = glp_dual_rtest(P, rlen, rind, rval, dir, 1e-9); + if (rpiv == 0) + { /* nothing limits changing c[k] */ + lim_coef = (kase < 0 ? -DBL_MAX : +DBL_MAX); + q = 0; + /* x[k] keeps its current value */ + new_x = x; + goto store; + } + /* non-basic variable x[q] limits changing coefficient c[k]; + determine its status and reduced cost d[k] in the current + basis */ + xassert(1 <= rpiv && rpiv <= rlen); + q = rind[rpiv]; + xassert(1 <= q && q <= m+n); + if (q <= m) + { row = P->row[q]; + stat = row->stat; + d = row->dual; + } + else + { col = P->col[q-m]; + stat = col->stat; + d = col->dual; + } + /* note that delta d[q] = new d[q] - d[q] = - d[q], because + new d[q] = 0; delta d[q] = alfa[k,q] * delta c[k], so + delta c[k] = delta d[q] / alfa[k,q] = - d[q] / alfa[k,q] */ + xassert(rval[rpiv] != 0.0); + delta = - d / rval[rpiv]; + /* compute new c[k] = c[k] + delta c[k], which is the limiting + value of the objective coefficient c[k] */ + lim_coef = coef + delta; + /* let c[k] continue decreasing/increasing that makes d[q] + dual infeasible and forces x[q] to enter the basis; + to perform the primal ratio test we need to know in which + direction x[q] changes on entering the basis; we determine + that analyzing the sign of delta d[q] (see above), since + d[q] may be close to zero having wrong sign */ + /* let, for simplicity, the problem is minimization */ + if (kase < 0 && rval[rpiv] > 0.0 || + kase > 0 && rval[rpiv] < 0.0) + { /* delta d[q] < 0, so d[q] being non-negative will become + negative, so x[q] will increase */ + dir = +1; + } + else + { /* delta d[q] > 0, so d[q] being non-positive will become + positive, so x[q] will decrease */ + dir = -1; + } + /* if the problem is maximization, correct the direction */ + if (P->dir == GLP_MAX) dir = - dir; + /* check that we didn't make a silly mistake */ + if (dir > 0) + xassert(stat == GLP_NL || stat == GLP_NF); + else + xassert(stat == GLP_NU || stat == GLP_NF); + /* compute column of the simplex table corresponding to the + non-basic variable x[q] */ + clen = glp_eval_tab_col(P, q, cind, cval); + /* make x[k] temporarily free (unbounded) */ + if (k <= m) + { row = P->row[k]; + row->type = GLP_FR; + row->lb = row->ub = 0.0; + } + else + { col = P->col[k-m]; + col->type = GLP_FR; + col->lb = col->ub = 0.0; + } + /* use the primal ratio test to determine some basic variable + which leaves the basis */ + cpiv = glp_prim_rtest(P, clen, cind, cval, dir, 1e-9); + /* restore original bounds of the basic variable x[k] */ + if (k <= m) + { row = P->row[k]; + row->type = type; + row->lb = lb, row->ub = ub; + } + else + { col = P->col[k-m]; + col->type = type; + col->lb = lb, col->ub = ub; + } + if (cpiv == 0) + { /* non-basic variable x[q] can change unlimitedly */ + if (dir < 0 && rval[rpiv] > 0.0 || + dir > 0 && rval[rpiv] < 0.0) + { /* delta x[k] = alfa[k,q] * delta x[q] < 0 */ + new_x = -DBL_MAX; + } + else + { /* delta x[k] = alfa[k,q] * delta x[q] > 0 */ + new_x = +DBL_MAX; + } + goto store; + } + /* some basic variable x[p] limits changing non-basic variable + x[q] in the adjacent basis */ + xassert(1 <= cpiv && cpiv <= clen); + p = cind[cpiv]; + xassert(1 <= p && p <= m+n); + xassert(p != k); + if (p <= m) + { row = P->row[p]; + xassert(row->stat == GLP_BS); + ll = glp_get_row_lb(P, row->i); + uu = glp_get_row_ub(P, row->i); + xx = row->prim; + } + else + { col = P->col[p-m]; + xassert(col->stat == GLP_BS); + ll = glp_get_col_lb(P, col->j); + uu = glp_get_col_ub(P, col->j); + xx = col->prim; + } + /* determine delta x[p] = new x[p] - x[p] */ + if (dir < 0 && cval[cpiv] > 0.0 || + dir > 0 && cval[cpiv] < 0.0) + { /* delta x[p] < 0, so x[p] goes toward its lower bound */ + xassert(ll != -DBL_MAX); + delta = ll - xx; + } + else + { /* delta x[p] > 0, so x[p] goes toward its upper bound */ + xassert(uu != +DBL_MAX); + delta = uu - xx; + } + /* compute new x[k] = x[k] + alfa[k,q] * delta x[q], where + delta x[q] = delta x[p] / alfa[p,q] */ + xassert(cval[cpiv] != 0.0); + new_x = x + (rval[rpiv] / cval[cpiv]) * delta; +store: /* store analysis results */ + if (kase < 0) + { if (coef1 != NULL) *coef1 = lim_coef; + if (var1 != NULL) *var1 = q; + if (value1 != NULL) *value1 = new_x; + } + else + { if (coef2 != NULL) *coef2 = lim_coef; + if (var2 != NULL) *var2 = q; + if (value2 != NULL) *value2 = new_x; + } + } + /* free working arrays */ + xfree(cind); + xfree(cval); + xfree(rind); + xfree(rval); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi13.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi13.c new file mode 100644 index 000000000..1181b3975 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpapi13.c @@ -0,0 +1,710 @@ +/* glpapi13.c (branch-and-bound interface routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* NAME +* +* glp_ios_reason - determine reason for calling the callback routine +* +* SYNOPSIS +* +* glp_ios_reason(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_reason returns a code, which indicates why the +* user-defined callback routine is being called. */ + +int glp_ios_reason(glp_tree *tree) +{ return + tree->reason; +} + +/*********************************************************************** +* NAME +* +* glp_ios_get_prob - access the problem object +* +* SYNOPSIS +* +* glp_prob *glp_ios_get_prob(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_get_prob can be called from the user-defined +* callback routine to access the problem object, which is used by the +* MIP solver. It is the original problem object passed to the routine +* glp_intopt if the MIP presolver is not used; otherwise it is an +* internal problem object built by the presolver. If the current +* subproblem exists, LP segment of the problem object corresponds to +* its LP relaxation. +* +* RETURNS +* +* The routine glp_ios_get_prob returns a pointer to the problem object +* used by the MIP solver. */ + +glp_prob *glp_ios_get_prob(glp_tree *tree) +{ return + tree->mip; +} + +/*********************************************************************** +* NAME +* +* glp_ios_tree_size - determine size of the branch-and-bound tree +* +* SYNOPSIS +* +* void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, +* int *t_cnt); +* +* DESCRIPTION +* +* The routine glp_ios_tree_size stores the following three counts which +* characterize the current size of the branch-and-bound tree: +* +* a_cnt is the current number of active nodes, i.e. the current size of +* the active list; +* +* n_cnt is the current number of all (active and inactive) nodes; +* +* t_cnt is the total number of nodes including those which have been +* already removed from the tree. This count is increased whenever +* a new node appears in the tree and never decreased. +* +* If some of the parameters a_cnt, n_cnt, t_cnt is a null pointer, the +* corresponding count is not stored. */ + +void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, + int *t_cnt) +{ if (a_cnt != NULL) *a_cnt = tree->a_cnt; + if (n_cnt != NULL) *n_cnt = tree->n_cnt; + if (t_cnt != NULL) *t_cnt = tree->t_cnt; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_curr_node - determine current active subproblem +* +* SYNOPSIS +* +* int glp_ios_curr_node(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_curr_node returns the reference number of the +* current active subproblem. However, if the current subproblem does +* not exist, the routine returns zero. */ + +int glp_ios_curr_node(glp_tree *tree) +{ IOSNPD *node; + /* obtain pointer to the current subproblem */ + node = tree->curr; + /* return its reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_next_node - determine next active subproblem +* +* SYNOPSIS +* +* int glp_ios_next_node(glp_tree *tree, int p); +* +* RETURNS +* +* If the parameter p is zero, the routine glp_ios_next_node returns +* the reference number of the first active subproblem. However, if the +* tree is empty, zero is returned. +* +* If the parameter p is not zero, it must specify the reference number +* of some active subproblem, in which case the routine returns the +* reference number of the next active subproblem. However, if there is +* no next active subproblem in the list, zero is returned. +* +* All subproblems in the active list are ordered chronologically, i.e. +* subproblem A precedes subproblem B if A was created before B. */ + +int glp_ios_next_node(glp_tree *tree, int p) +{ IOSNPD *node; + if (p == 0) + { /* obtain pointer to the first active subproblem */ + node = tree->head; + } + else + { /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_next_node: p = %d; invalid subproblem refer" + "ence number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_next_node: p = %d; subproblem not in the ac" + "tive list\n", p); + /* obtain pointer to the next active subproblem */ + node = node->next; + } + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_prev_node - determine previous active subproblem +* +* SYNOPSIS +* +* int glp_ios_prev_node(glp_tree *tree, int p); +* +* RETURNS +* +* If the parameter p is zero, the routine glp_ios_prev_node returns +* the reference number of the last active subproblem. However, if the +* tree is empty, zero is returned. +* +* If the parameter p is not zero, it must specify the reference number +* of some active subproblem, in which case the routine returns the +* reference number of the previous active subproblem. However, if there +* is no previous active subproblem in the list, zero is returned. +* +* All subproblems in the active list are ordered chronologically, i.e. +* subproblem A precedes subproblem B if A was created before B. */ + +int glp_ios_prev_node(glp_tree *tree, int p) +{ IOSNPD *node; + if (p == 0) + { /* obtain pointer to the last active subproblem */ + node = tree->tail; + } + else + { /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_prev_node: p = %d; invalid subproblem refer" + "ence number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_prev_node: p = %d; subproblem not in the ac" + "tive list\n", p); + /* obtain pointer to the previous active subproblem */ + node = node->prev; + } + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_up_node - determine parent subproblem +* +* SYNOPSIS +* +* int glp_ios_up_node(glp_tree *tree, int p); +* +* RETURNS +* +* The parameter p must specify the reference number of some (active or +* inactive) subproblem, in which case the routine iet_get_up_node +* returns the reference number of its parent subproblem. However, if +* the specified subproblem is the root of the tree and, therefore, has +* no parent, the routine returns zero. */ + +int glp_ios_up_node(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_up_node: p = %d; invalid subproblem reference " + "number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* obtain pointer to the parent subproblem */ + node = node->up; + /* return the reference number */ + return node == NULL ? 0 : node->p; +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_level - determine subproblem level +* +* SYNOPSIS +* +* int glp_ios_node_level(glp_tree *tree, int p); +* +* RETURNS +* +* The routine glp_ios_node_level returns the level of the subproblem, +* whose reference number is p, in the branch-and-bound tree. (The root +* subproblem has level 0, and the level of any other subproblem is the +* level of its parent plus one.) */ + +int glp_ios_node_level(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return the node level */ + return node->level; +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_bound - determine subproblem local bound +* +* SYNOPSIS +* +* double glp_ios_node_bound(glp_tree *tree, int p); +* +* RETURNS +* +* The routine glp_ios_node_bound returns the local bound for (active or +* inactive) subproblem, whose reference number is p. +* +* COMMENTS +* +* The local bound for subproblem p is an lower (minimization) or upper +* (maximization) bound for integer optimal solution to this subproblem +* (not to the original problem). This bound is local in the sense that +* only subproblems in the subtree rooted at node p cannot have better +* integer feasible solutions. +* +* On creating a subproblem (due to the branching step) its local bound +* is inherited from its parent and then may get only stronger (never +* weaker). For the root subproblem its local bound is initially set to +* -DBL_MAX (minimization) or +DBL_MAX (maximization) and then improved +* as the root LP relaxation has been solved. +* +* Note that the local bound is not necessarily the optimal objective +* value to corresponding LP relaxation; it may be stronger. */ + +double glp_ios_node_bound(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_bound: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return the node local bound */ + return node->bound; +} + +/*********************************************************************** +* NAME +* +* glp_ios_best_node - find active subproblem with best local bound +* +* SYNOPSIS +* +* int glp_ios_best_node(glp_tree *tree); +* +* RETURNS +* +* The routine glp_ios_best_node returns the reference number of the +* active subproblem, whose local bound is best (i.e. smallest in case +* of minimization or largest in case of maximization). However, if the +* tree is empty, the routine returns zero. +* +* COMMENTS +* +* The best local bound is an lower (minimization) or upper +* (maximization) bound for integer optimal solution to the original +* MIP problem. */ + +int glp_ios_best_node(glp_tree *tree) +{ return + ios_best_node(tree); +} + +/*********************************************************************** +* NAME +* +* glp_ios_mip_gap - compute relative MIP gap +* +* SYNOPSIS +* +* double glp_ios_mip_gap(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_mip_gap computes the relative MIP gap with the +* following formula: +* +* gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), +* +* where best_mip is the best integer feasible solution found so far, +* best_bnd is the best (global) bound. If no integer feasible solution +* has been found yet, gap is set to DBL_MAX. +* +* RETURNS +* +* The routine glp_ios_mip_gap returns the relative MIP gap. */ + +double glp_ios_mip_gap(glp_tree *tree) +{ return + ios_relative_gap(tree); +} + +/*********************************************************************** +* NAME +* +* glp_ios_node_data - access subproblem application-specific data +* +* SYNOPSIS +* +* void *glp_ios_node_data(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine glp_ios_node_data allows the application accessing a +* memory block allocated for the subproblem (which may be active or +* inactive), whose reference number is p. +* +* The size of the block is defined by the control parameter cb_size +* passed to the routine glp_intopt. The block is initialized by binary +* zeros on creating corresponding subproblem, and its contents is kept +* until the subproblem will be removed from the tree. +* +* The application may use these memory blocks to store specific data +* for each subproblem. +* +* RETURNS +* +* The routine glp_ios_node_data returns a pointer to the memory block +* for the specified subproblem. Note that if cb_size = 0, the routine +* returns a null pointer. */ + +void *glp_ios_node_data(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" + "ce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* return pointer to the application-specific data */ + return node->data; +} + +/*********************************************************************** +* NAME +* +* glp_ios_row_attr - retrieve additional row attributes +* +* SYNOPSIS +* +* void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr); +* +* DESCRIPTION +* +* The routine glp_ios_row_attr retrieves additional attributes of row +* i and stores them in the structure glp_attr. */ + +void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr) +{ GLPROW *row; + if (!(1 <= i && i <= tree->mip->m)) + xerror("glp_ios_row_attr: i = %d; row number out of range\n", + i); + row = tree->mip->row[i]; + attr->level = row->level; + attr->origin = row->origin; + attr->klass = row->klass; + return; +} + +/**********************************************************************/ + +int glp_ios_pool_size(glp_tree *tree) +{ /* determine current size of the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_pool_size: operation not allowed\n"); + xassert(tree->local != NULL); +#ifdef NEW_LOCAL /* 02/II-2018 */ + return tree->local->m; +#else + return tree->local->size; +#endif +} + +/**********************************************************************/ + +int glp_ios_add_row(glp_tree *tree, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs) +{ /* add row (constraint) to the cut pool */ + int num; + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_add_row: operation not allowed\n"); + xassert(tree->local != NULL); + num = ios_add_row(tree, tree->local, name, klass, flags, len, + ind, val, type, rhs); + return num; +} + +/**********************************************************************/ + +void glp_ios_del_row(glp_tree *tree, int i) +{ /* remove row (constraint) from the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_del_row: operation not allowed\n"); + ios_del_row(tree, tree->local, i); + return; +} + +/**********************************************************************/ + +void glp_ios_clear_pool(glp_tree *tree) +{ /* remove all rows (constraints) from the cut pool */ + if (tree->reason != GLP_ICUTGEN) + xerror("glp_ios_clear_pool: operation not allowed\n"); + ios_clear_pool(tree, tree->local); + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_can_branch - check if can branch upon specified variable +* +* SYNOPSIS +* +* int glp_ios_can_branch(glp_tree *tree, int j); +* +* RETURNS +* +* If j-th variable (column) can be used to branch upon, the routine +* glp_ios_can_branch returns non-zero, otherwise zero. */ + +int glp_ios_can_branch(glp_tree *tree, int j) +{ if (!(1 <= j && j <= tree->mip->n)) + xerror("glp_ios_can_branch: j = %d; column number out of range" + "\n", j); + return tree->non_int[j]; +} + +/*********************************************************************** +* NAME +* +* glp_ios_branch_upon - choose variable to branch upon +* +* SYNOPSIS +* +* void glp_ios_branch_upon(glp_tree *tree, int j, int sel); +* +* DESCRIPTION +* +* The routine glp_ios_branch_upon can be called from the user-defined +* callback routine in response to the reason GLP_IBRANCH to choose a +* branching variable, whose ordinal number is j. Should note that only +* variables, for which the routine glp_ios_can_branch returns non-zero, +* can be used to branch upon. +* +* The parameter sel is a flag that indicates which branch (subproblem) +* should be selected next to continue the search: +* +* GLP_DN_BRNCH - select down-branch; +* GLP_UP_BRNCH - select up-branch; +* GLP_NO_BRNCH - use general selection technique. */ + +void glp_ios_branch_upon(glp_tree *tree, int j, int sel) +{ if (!(1 <= j && j <= tree->mip->n)) + xerror("glp_ios_branch_upon: j = %d; column number out of rang" + "e\n", j); + if (!(sel == GLP_DN_BRNCH || sel == GLP_UP_BRNCH || + sel == GLP_NO_BRNCH)) + xerror("glp_ios_branch_upon: sel = %d: invalid branch selectio" + "n flag\n", sel); + if (!(tree->non_int[j])) + xerror("glp_ios_branch_upon: j = %d; variable cannot be used t" + "o branch upon\n", j); + if (tree->br_var != 0) + xerror("glp_ios_branch_upon: branching variable already chosen" + "\n"); + tree->br_var = j; + tree->br_sel = sel; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_select_node - select subproblem to continue the search +* +* SYNOPSIS +* +* void glp_ios_select_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine glp_ios_select_node can be called from the user-defined +* callback routine in response to the reason GLP_ISELECT to select an +* active subproblem, whose reference number is p. The search will be +* continued from the subproblem selected. */ + +void glp_ios_select_node(glp_tree *tree, int p) +{ IOSNPD *node; + /* obtain pointer to the specified subproblem */ + if (!(1 <= p && p <= tree->nslots)) +err: xerror("glp_ios_select_node: p = %d; invalid subproblem refere" + "nce number\n", p); + node = tree->slot[p].node; + if (node == NULL) goto err; + /* the specified subproblem must be active */ + if (node->count != 0) + xerror("glp_ios_select_node: p = %d; subproblem not in the act" + "ive list\n", p); + /* no subproblem must be selected yet */ + if (tree->next_p != 0) + xerror("glp_ios_select_node: subproblem already selected\n"); + /* select the specified subproblem to continue the search */ + tree->next_p = p; + return; +} + +/*********************************************************************** +* NAME +* +* glp_ios_heur_sol - provide solution found by heuristic +* +* SYNOPSIS +* +* int glp_ios_heur_sol(glp_tree *tree, const double x[]); +* +* DESCRIPTION +* +* The routine glp_ios_heur_sol can be called from the user-defined +* callback routine in response to the reason GLP_IHEUR to provide an +* integer feasible solution found by a primal heuristic. +* +* Primal values of *all* variables (columns) found by the heuristic +* should be placed in locations x[1], ..., x[n], where n is the number +* of columns in the original problem object. Note that the routine +* glp_ios_heur_sol *does not* check primal feasibility of the solution +* provided. +* +* Using the solution passed in the array x the routine computes value +* of the objective function. If the objective value is better than the +* best known integer feasible solution, the routine computes values of +* auxiliary variables (rows) and stores all solution components in the +* problem object. +* +* RETURNS +* +* If the provided solution is accepted, the routine glp_ios_heur_sol +* returns zero. Otherwise, if the provided solution is rejected, the +* routine returns non-zero. */ + +int glp_ios_heur_sol(glp_tree *tree, const double x[]) +{ glp_prob *mip = tree->mip; + int m = tree->orig_m; + int n = tree->n; + int i, j; + double obj; + xassert(mip->m >= m); + xassert(mip->n == n); + /* check values of integer variables and compute value of the + objective function */ + obj = mip->c0; + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->kind == GLP_IV) + { /* provided value must be integral */ + if (x[j] != floor(x[j])) return 1; + } + obj += col->coef * x[j]; + } + /* check if the provided solution is better than the best known + integer feasible solution */ + if (mip->mip_stat == GLP_FEAS) + { switch (mip->dir) + { case GLP_MIN: + if (obj >= tree->mip->mip_obj) return 1; + break; + case GLP_MAX: + if (obj <= tree->mip->mip_obj) return 1; + break; + default: + xassert(mip != mip); + } + } + /* it is better; store it in the problem object */ + if (tree->parm->msg_lev >= GLP_MSG_ON) + xprintf("Solution found by heuristic: %.12g\n", obj); + mip->mip_stat = GLP_FEAS; + mip->mip_obj = obj; + for (j = 1; j <= n; j++) + mip->col[j]->mipx = x[j]; + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + GLPAIJ *aij; + row->mipx = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + row->mipx += aij->val * aij->col->mipx; + } +#if 1 /* 11/VII-2013 */ + ios_process_sol(tree); +#endif + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_ios_terminate - terminate the solution process. +* +* SYNOPSIS +* +* void glp_ios_terminate(glp_tree *tree); +* +* DESCRIPTION +* +* The routine glp_ios_terminate sets a flag indicating that the MIP +* solver should prematurely terminate the search. */ + +void glp_ios_terminate(glp_tree *tree) +{ if (tree->parm->msg_lev >= GLP_MSG_DBG) + xprintf("The search is prematurely terminated due to applicati" + "on request\n"); + tree->stop = 1; + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.c new file mode 100644 index 000000000..8b33c172f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.c @@ -0,0 +1,533 @@ +/* glphbm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glphbm.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* hbm_read_mat - read sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glphbm.h" +* HBM *hbm_read_mat(const char *fname); +* +* DESCRIPTION +* +* The routine hbm_read_mat reads a sparse matrix in the Harwell-Boeing +* format from a text file whose name is the character string fname. +* +* Detailed description of the Harwell-Boeing format recognised by this +* routine is given in the following report: +* +* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing +* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. +* +* RETURNS +* +* If no error occured, the routine hbm_read_mat returns a pointer to +* a data structure containing the matrix. In case of error the routine +* prints an appropriate error message and returns NULL. */ + +struct dsa +{ /* working area used by routine hbm_read_mat */ + const char *fname; + /* name of input text file */ + FILE *fp; + /* stream assigned to input text file */ + int seqn; + /* card sequential number */ + char card[80+1]; + /* card image buffer */ + int fmt_p; + /* scale factor */ + int fmt_k; + /* iterator */ + int fmt_f; + /* format code */ + int fmt_w; + /* field width */ + int fmt_d; + /* number of decimal places after point */ +}; + +/*********************************************************************** +* read_card - read next data card +* +* This routine reads the next 80-column card from the input text file +* and stores its image into the character string card. If the card was +* read successfully, the routine returns zero, otherwise non-zero. */ + +#if 1 /* 11/III-2012 */ +static int read_card(struct dsa *dsa) +{ int c, len = 0; + char buf[255+1]; + dsa->seqn++; + for (;;) + { c = fgetc(dsa->fp); + if (c == EOF) + { if (ferror(dsa->fp)) + xprintf("%s:%d: read error\n", + dsa->fname, dsa->seqn); + else + xprintf("%s:%d: unexpected end-of-file\n", + dsa->fname, dsa->seqn); + return 1; + } + else if (c == '\r') + /* nop */; + else if (c == '\n') + break; + else if (iscntrl(c)) + { xprintf("%s:%d: invalid control character\n", + dsa->fname, dsa->seqn, c); + return 1; + } + else + { if (len == sizeof(buf)-1) + goto err; + buf[len++] = (char)c; + } + } + /* remove trailing spaces */ + while (len > 80 && buf[len-1] == ' ') + len--; + buf[len] = '\0'; + /* line should not be longer than 80 chars */ + if (len > 80) +err: { xerror("%s:%d: card image too long\n", + dsa->fname, dsa->seqn); + return 1; + } + /* padd by spaces to 80-column card image */ + strcpy(dsa->card, buf); + memset(&dsa->card[len], ' ', 80 - len); + dsa->card[80] = '\0'; + return 0; +} +#endif + +/*********************************************************************** +* scan_int - scan integer value from the current card +* +* This routine scans an integer value from the current card, where fld +* is the name of the field, pos is the position of the field, width is +* the width of the field, val points to a location to which the scanned +* value should be stored. If the value was scanned successfully, the +* routine returns zero, otherwise non-zero. */ + +static int scan_int(struct dsa *dsa, char *fld, int pos, int width, + int *val) +{ char str[80+1]; + xassert(1 <= width && width <= 80); + memcpy(str, dsa->card + pos, width), str[width] = '\0'; + if (str2int(strspx(str), val)) + { xprintf("%s:%d: field '%s' contains invalid value '%s'\n", + dsa->fname, dsa->seqn, fld, str); + return 1; + } + return 0; +} + +/*********************************************************************** +* parse_fmt - parse Fortran format specification +* +* This routine parses the Fortran format specification represented as +* character string which fmt points to and stores format elements into +* appropriate static locations. Should note that not all valid Fortran +* format specifications may be recognised. If the format specification +* was recognised, the routine returns zero, otherwise non-zero. */ + +static int parse_fmt(struct dsa *dsa, char *fmt) +{ int k, s, val; + char str[80+1]; + /* first character should be left parenthesis */ + if (fmt[0] != '(') +fail: { xprintf("hbm_read_mat: format '%s' not recognised\n", fmt); + return 1; + } + k = 1; + /* optional scale factor */ + dsa->fmt_p = 0; + if (isdigit((unsigned char)fmt[k])) + { s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &val)) goto fail; + if (toupper((unsigned char)fmt[k]) != 'P') goto iter; + dsa->fmt_p = val, k++; + if (!(0 <= dsa->fmt_p && dsa->fmt_p <= 255)) goto fail; + /* optional comma may follow scale factor */ + if (fmt[k] == ',') k++; + } + /* optional iterator */ + dsa->fmt_k = 1; + if (isdigit((unsigned char)fmt[k])) + { s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &val)) goto fail; +iter: dsa->fmt_k = val; + if (!(1 <= dsa->fmt_k && dsa->fmt_k <= 255)) goto fail; + } + /* format code */ + dsa->fmt_f = toupper((unsigned char)fmt[k++]); + if (!(dsa->fmt_f == 'D' || dsa->fmt_f == 'E' || + dsa->fmt_f == 'F' || dsa->fmt_f == 'G' || + dsa->fmt_f == 'I')) goto fail; + /* field width */ + if (!isdigit((unsigned char)fmt[k])) goto fail; + s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &dsa->fmt_w)) goto fail; + if (!(1 <= dsa->fmt_w && dsa->fmt_w <= 255)) goto fail; + /* optional number of decimal places after point */ + dsa->fmt_d = 0; + if (fmt[k] == '.') + { k++; + if (!isdigit((unsigned char)fmt[k])) goto fail; + s = 0; + while (isdigit((unsigned char)fmt[k])) + { if (s == 80) goto fail; + str[s++] = fmt[k++]; + } + str[s] = '\0'; + if (str2int(str, &dsa->fmt_d)) goto fail; + if (!(0 <= dsa->fmt_d && dsa->fmt_d <= 255)) goto fail; + } + /* last character should be right parenthesis */ + if (!(fmt[k] == ')' && fmt[k+1] == '\0')) goto fail; + return 0; +} + +/*********************************************************************** +* read_int_array - read array of integer type +* +* This routine reads an integer array from the input text file, where +* name is array name, fmt is Fortran format specification that controls +* reading, n is number of array elements, val is array of integer type. +* If the array was read successful, the routine returns zero, otherwise +* non-zero. */ + +static int read_int_array(struct dsa *dsa, char *name, char *fmt, + int n, int val[]) +{ int k, pos; + char str[80+1]; + if (parse_fmt(dsa, fmt)) return 1; + if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 && + dsa->fmt_k * dsa->fmt_w <= 80)) + { xprintf( + "%s:%d: can't read array '%s' - invalid format '%s'\n", + dsa->fname, dsa->seqn, name, fmt); + return 1; + } + for (k = 1, pos = INT_MAX; k <= n; k++, pos++) + { if (pos >= dsa->fmt_k) + { if (read_card(dsa)) return 1; + pos = 0; + } + memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); + str[dsa->fmt_w] = '\0'; + strspx(str); + if (str2int(str, &val[k])) + { xprintf( + "%s:%d: can't read array '%s' - invalid value '%s'\n", + dsa->fname, dsa->seqn, name, str); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* read_real_array - read array of real type +* +* This routine reads a real array from the input text file, where name +* is array name, fmt is Fortran format specification that controls +* reading, n is number of array elements, val is array of real type. +* If the array was read successful, the routine returns zero, otherwise +* non-zero. */ + +static int read_real_array(struct dsa *dsa, char *name, char *fmt, + int n, double val[]) +{ int k, pos; + char str[80+1], *ptr; + if (parse_fmt(dsa, fmt)) return 1; + if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 && + dsa->fmt_k * dsa->fmt_w <= 80)) + { xprintf( + "%s:%d: can't read array '%s' - invalid format '%s'\n", + dsa->fname, dsa->seqn, name, fmt); + return 1; + } + for (k = 1, pos = INT_MAX; k <= n; k++, pos++) + { if (pos >= dsa->fmt_k) + { if (read_card(dsa)) return 1; + pos = 0; + } + memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); + str[dsa->fmt_w] = '\0'; + strspx(str); + if (strchr(str, '.') == NULL && strcmp(str, "0")) + { xprintf("%s(%d): can't read array '%s' - value '%s' has no " + "decimal point\n", dsa->fname, dsa->seqn, name, str); + return 1; + } + /* sometimes lower case letters appear */ + for (ptr = str; *ptr; ptr++) + *ptr = (char)toupper((unsigned char)*ptr); + ptr = strchr(str, 'D'); + if (ptr != NULL) *ptr = 'E'; + /* value may appear with decimal exponent but without letters + E or D (for example, -123.456-012), so missing letter should + be inserted */ + ptr = strchr(str+1, '+'); + if (ptr == NULL) ptr = strchr(str+1, '-'); + if (ptr != NULL && *(ptr-1) != 'E') + { xassert(strlen(str) < 80); + memmove(ptr+1, ptr, strlen(ptr)+1); + *ptr = 'E'; + } + if (str2num(str, &val[k])) + { xprintf( + "%s:%d: can't read array '%s' - invalid value '%s'\n", + dsa->fname, dsa->seqn, name, str); + return 1; + } + } + return 0; +} + +HBM *hbm_read_mat(const char *fname) +{ struct dsa _dsa, *dsa = &_dsa; + HBM *hbm = NULL; + dsa->fname = fname; + xprintf("hbm_read_mat: reading matrix from '%s'...\n", + dsa->fname); + dsa->fp = fopen(dsa->fname, "r"); + if (dsa->fp == NULL) + { xprintf("hbm_read_mat: unable to open '%s' - %s\n", +#if 0 /* 29/I-2017 */ + dsa->fname, strerror(errno)); +#else + dsa->fname, xstrerr(errno)); +#endif + goto fail; + } + dsa->seqn = 0; + hbm = xmalloc(sizeof(HBM)); + memset(hbm, 0, sizeof(HBM)); + /* read the first heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->title, dsa->card, 72), hbm->title[72] = '\0'; + strtrim(hbm->title); + xprintf("%s\n", hbm->title); + memcpy(hbm->key, dsa->card+72, 8), hbm->key[8] = '\0'; + strspx(hbm->key); + xprintf("key = %s\n", hbm->key); + /* read the second heading card */ + if (read_card(dsa)) goto fail; + if (scan_int(dsa, "totcrd", 0, 14, &hbm->totcrd)) goto fail; + if (scan_int(dsa, "ptrcrd", 14, 14, &hbm->ptrcrd)) goto fail; + if (scan_int(dsa, "indcrd", 28, 14, &hbm->indcrd)) goto fail; + if (scan_int(dsa, "valcrd", 42, 14, &hbm->valcrd)) goto fail; + if (scan_int(dsa, "rhscrd", 56, 14, &hbm->rhscrd)) goto fail; + xprintf("totcrd = %d; ptrcrd = %d; indcrd = %d; valcrd = %d; rhsc" + "rd = %d\n", hbm->totcrd, hbm->ptrcrd, hbm->indcrd, + hbm->valcrd, hbm->rhscrd); + /* read the third heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->mxtype, dsa->card, 3), hbm->mxtype[3] = '\0'; + if (strchr("RCP", hbm->mxtype[0]) == NULL || + strchr("SUHZR", hbm->mxtype[1]) == NULL || + strchr("AE", hbm->mxtype[2]) == NULL) + { xprintf("%s:%d: matrix type '%s' not recognised\n", + dsa->fname, dsa->seqn, hbm->mxtype); + goto fail; + } + if (scan_int(dsa, "nrow", 14, 14, &hbm->nrow)) goto fail; + if (scan_int(dsa, "ncol", 28, 14, &hbm->ncol)) goto fail; + if (scan_int(dsa, "nnzero", 42, 14, &hbm->nnzero)) goto fail; + if (scan_int(dsa, "neltvl", 56, 14, &hbm->neltvl)) goto fail; + xprintf("mxtype = %s; nrow = %d; ncol = %d; nnzero = %d; neltvl =" + " %d\n", hbm->mxtype, hbm->nrow, hbm->ncol, hbm->nnzero, + hbm->neltvl); + /* read the fourth heading card */ + if (read_card(dsa)) goto fail; + memcpy(hbm->ptrfmt, dsa->card, 16), hbm->ptrfmt[16] = '\0'; + strspx(hbm->ptrfmt); + memcpy(hbm->indfmt, dsa->card+16, 16), hbm->indfmt[16] = '\0'; + strspx(hbm->indfmt); + memcpy(hbm->valfmt, dsa->card+32, 20), hbm->valfmt[20] = '\0'; + strspx(hbm->valfmt); + memcpy(hbm->rhsfmt, dsa->card+52, 20), hbm->rhsfmt[20] = '\0'; + strspx(hbm->rhsfmt); + xprintf("ptrfmt = %s; indfmt = %s; valfmt = %s; rhsfmt = %s\n", + hbm->ptrfmt, hbm->indfmt, hbm->valfmt, hbm->rhsfmt); + /* read the fifth heading card (optional) */ + if (hbm->rhscrd <= 0) + { strcpy(hbm->rhstyp, "???"); + hbm->nrhs = 0; + hbm->nrhsix = 0; + } + else + { if (read_card(dsa)) goto fail; + memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0'; + if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail; + if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail; + xprintf("rhstyp = '%s'; nrhs = %d; nrhsix = %d\n", + hbm->rhstyp, hbm->nrhs, hbm->nrhsix); + } + /* read matrix structure */ + hbm->colptr = xcalloc(1+hbm->ncol+1, sizeof(int)); + if (read_int_array(dsa, "colptr", hbm->ptrfmt, hbm->ncol+1, + hbm->colptr)) goto fail; + hbm->rowind = xcalloc(1+hbm->nnzero, sizeof(int)); + if (read_int_array(dsa, "rowind", hbm->indfmt, hbm->nnzero, + hbm->rowind)) goto fail; + /* read matrix values */ + if (hbm->valcrd <= 0) goto done; + if (hbm->mxtype[2] == 'A') + { /* assembled matrix */ + hbm->values = xcalloc(1+hbm->nnzero, sizeof(double)); + if (read_real_array(dsa, "values", hbm->valfmt, hbm->nnzero, + hbm->values)) goto fail; + } + else + { /* elemental (unassembled) matrix */ + hbm->values = xcalloc(1+hbm->neltvl, sizeof(double)); + if (read_real_array(dsa, "values", hbm->valfmt, hbm->neltvl, + hbm->values)) goto fail; + } + /* read right-hand sides */ + if (hbm->nrhs <= 0) goto done; + if (hbm->rhstyp[0] == 'F') + { /* dense format */ + hbm->nrhsvl = hbm->nrow * hbm->nrhs; + hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, + hbm->rhsval)) goto fail; + } + else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'A') + { /* sparse format */ + /* read pointers */ + hbm->rhsptr = xcalloc(1+hbm->nrhs+1, sizeof(int)); + if (read_int_array(dsa, "rhsptr", hbm->ptrfmt, hbm->nrhs+1, + hbm->rhsptr)) goto fail; + /* read sparsity pattern */ + hbm->rhsind = xcalloc(1+hbm->nrhsix, sizeof(int)); + if (read_int_array(dsa, "rhsind", hbm->indfmt, hbm->nrhsix, + hbm->rhsind)) goto fail; + /* read values */ + hbm->rhsval = xcalloc(1+hbm->nrhsix, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsix, + hbm->rhsval)) goto fail; + } + else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'E') + { /* elemental format */ + hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); + if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, + hbm->rhsval)) goto fail; + } + else + { xprintf("%s:%d: right-hand side type '%c' not recognised\n", + dsa->fname, dsa->seqn, hbm->rhstyp[0]); + goto fail; + } + /* read starting guesses */ + if (hbm->rhstyp[1] == 'G') + { hbm->nguess = hbm->nrow * hbm->nrhs; + hbm->sguess = xcalloc(1+hbm->nguess, sizeof(double)); + if (read_real_array(dsa, "sguess", hbm->rhsfmt, hbm->nguess, + hbm->sguess)) goto fail; + } + /* read solution vectors */ + if (hbm->rhstyp[2] == 'X') + { hbm->nexact = hbm->nrow * hbm->nrhs; + hbm->xexact = xcalloc(1+hbm->nexact, sizeof(double)); + if (read_real_array(dsa, "xexact", hbm->rhsfmt, hbm->nexact, + hbm->xexact)) goto fail; + } +done: /* reading has been completed */ + xprintf("hbm_read_mat: %d cards were read\n", dsa->seqn); + fclose(dsa->fp); + return hbm; +fail: /* something wrong in Danish kingdom */ + if (hbm != NULL) + { if (hbm->colptr != NULL) xfree(hbm->colptr); + if (hbm->rowind != NULL) xfree(hbm->rowind); + if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); + if (hbm->rhsind != NULL) xfree(hbm->rhsind); + if (hbm->values != NULL) xfree(hbm->values); + if (hbm->rhsval != NULL) xfree(hbm->rhsval); + if (hbm->sguess != NULL) xfree(hbm->sguess); + if (hbm->xexact != NULL) xfree(hbm->xexact); + xfree(hbm); + } + if (dsa->fp != NULL) fclose(dsa->fp); + return NULL; +} + +/*********************************************************************** +* NAME +* +* hbm_free_mat - free sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glphbm.h" +* void hbm_free_mat(HBM *hbm); +* +* DESCRIPTION +* +* The hbm_free_mat routine frees all the memory allocated to the data +* structure containing a sparse matrix in the Harwell-Boeing format. */ + +void hbm_free_mat(HBM *hbm) +{ if (hbm->colptr != NULL) xfree(hbm->colptr); + if (hbm->rowind != NULL) xfree(hbm->rowind); + if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); + if (hbm->rhsind != NULL) xfree(hbm->rhsind); + if (hbm->values != NULL) xfree(hbm->values); + if (hbm->rhsval != NULL) xfree(hbm->rhsval); + if (hbm->sguess != NULL) xfree(hbm->sguess); + if (hbm->xexact != NULL) xfree(hbm->xexact); + xfree(hbm); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.h new file mode 100644 index 000000000..688a78ec1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glphbm.h @@ -0,0 +1,127 @@ +/* glphbm.h (Harwell-Boeing sparse matrix format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPHBM_H +#define GLPHBM_H + +typedef struct HBM HBM; + +struct HBM +{ /* sparse matrix in Harwell-Boeing format; for details see the + report: I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the + Harwell-Boeing Sparse Matrix Collection (Release I), 1992 */ + char title[72+1]; + /* matrix title (informative) */ + char key[8+1]; + /* matrix key (informative) */ + char mxtype[3+1]; + /* matrix type: + R.. real matrix + C.. complex matrix + P.. pattern only (no numerical values supplied) + .S. symmetric (lower triangle + main diagonal) + .U. unsymmetric + .H. hermitian (lower triangle + main diagonal) + .Z. skew symmetric (lower triangle only) + .R. rectangular + ..A assembled + ..E elemental (unassembled) */ + char rhstyp[3+1]; + /* optional types: + F.. right-hand sides in dense format + M.. right-hand sides in same format as matrix + .G. starting vector(s) (guess) is supplied + ..X exact solution vector(s) is supplied */ + char ptrfmt[16+1]; + /* format for pointers */ + char indfmt[16+1]; + /* format for row (or variable) indices */ + char valfmt[20+1]; + /* format for numerical values of coefficient matrix */ + char rhsfmt[20+1]; + /* format for numerical values of right-hand sides */ + int totcrd; + /* total number of cards excluding header */ + int ptrcrd; + /* number of cards for ponters */ + int indcrd; + /* number of cards for row (or variable) indices */ + int valcrd; + /* number of cards for numerical values */ + int rhscrd; + /* number of lines for right-hand sides; + including starting guesses and solution vectors if present; + zero indicates no right-hand side data is present */ + int nrow; + /* number of rows (or variables) */ + int ncol; + /* number of columns (or elements) */ + int nnzero; + /* number of row (or variable) indices; + equal to number of entries for assembled matrix */ + int neltvl; + /* number of elemental matrix entries; + zero in case of assembled matrix */ + int nrhs; + /* number of right-hand sides */ + int nrhsix; + /* number of row indices; + ignored in case of unassembled matrix */ + int nrhsvl; + /* total number of entries in all right-hand sides */ + int nguess; + /* total number of entries in all starting guesses */ + int nexact; + /* total number of entries in all solution vectors */ + int *colptr; /* alias: eltptr */ + /* column pointers (in case of assembled matrix); + elemental matrix pointers (in case of unassembled matrix) */ + int *rowind; /* alias: varind */ + /* row indices (in case of assembled matrix); + variable indices (in case of unassembled matrix) */ + int *rhsptr; + /* right-hand side pointers */ + int *rhsind; + /* right-hand side indices */ + double *values; + /* matrix values */ + double *rhsval; + /* right-hand side values */ + double *sguess; + /* starting guess values */ + double *xexact; + /* solution vector values */ +}; + +#define hbm_read_mat _glp_hbm_read_mat +HBM *hbm_read_mat(const char *fname); +/* read sparse matrix in Harwell-Boeing format */ + +#define hbm_free_mat _glp_hbm_free_mat +void hbm_free_mat(HBM *hbm); +/* free sparse matrix in Harwell-Boeing format */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios01.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios01.c new file mode 100644 index 000000000..cb1a0dabd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios01.c @@ -0,0 +1,1685 @@ +/* glpios01.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" +#include "misc.h" + +static int lpx_eval_tab_row(glp_prob *lp, int k, int ind[], + double val[]) +{ /* compute row of the simplex tableau */ + return glp_eval_tab_row(lp, k, ind, val); +} + +static int lpx_dual_ratio_test(glp_prob *lp, int len, const int ind[], + const double val[], int how, double tol) +{ /* perform dual ratio test */ + int piv; + piv = glp_dual_rtest(lp, len, ind, val, how, tol); + xassert(0 <= piv && piv <= len); + return piv == 0 ? 0 : ind[piv]; +} + +/*********************************************************************** +* NAME +* +* ios_create_tree - create branch-and-bound tree +* +* SYNOPSIS +* +* #include "glpios.h" +* glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); +* +* DESCRIPTION +* +* The routine ios_create_tree creates the branch-and-bound tree. +* +* Being created the tree consists of the only root subproblem whose +* reference number is 1. Note that initially the root subproblem is in +* frozen state and therefore needs to be revived. +* +* RETURNS +* +* The routine returns a pointer to the tree created. */ + +static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent); + +glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm) +{ int m = mip->m; + int n = mip->n; + glp_tree *tree; + int i, j; + xassert(mip->tree == NULL); + mip->tree = tree = xmalloc(sizeof(glp_tree)); + tree->pool = dmp_create_pool(); + tree->n = n; + /* save original problem components */ + tree->orig_m = m; + tree->orig_type = xcalloc(1+m+n, sizeof(char)); + tree->orig_lb = xcalloc(1+m+n, sizeof(double)); + tree->orig_ub = xcalloc(1+m+n, sizeof(double)); + tree->orig_stat = xcalloc(1+m+n, sizeof(char)); + tree->orig_prim = xcalloc(1+m+n, sizeof(double)); + tree->orig_dual = xcalloc(1+m+n, sizeof(double)); + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + tree->orig_type[i] = (char)row->type; + tree->orig_lb[i] = row->lb; + tree->orig_ub[i] = row->ub; + tree->orig_stat[i] = (char)row->stat; + tree->orig_prim[i] = row->prim; + tree->orig_dual[i] = row->dual; + } + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + tree->orig_type[m+j] = (char)col->type; + tree->orig_lb[m+j] = col->lb; + tree->orig_ub[m+j] = col->ub; + tree->orig_stat[m+j] = (char)col->stat; + tree->orig_prim[m+j] = col->prim; + tree->orig_dual[m+j] = col->dual; + } + tree->orig_obj = mip->obj_val; + /* initialize the branch-and-bound tree */ + tree->nslots = 0; + tree->avail = 0; + tree->slot = NULL; + tree->head = tree->tail = NULL; + tree->a_cnt = tree->n_cnt = tree->t_cnt = 0; + /* the root subproblem is not solved yet, so its final components + are unknown so far */ + tree->root_m = 0; + tree->root_type = NULL; + tree->root_lb = tree->root_ub = NULL; + tree->root_stat = NULL; + /* the current subproblem does not exist yet */ + tree->curr = NULL; + tree->mip = mip; + /*tree->solved = 0;*/ + tree->non_int = xcalloc(1+n, sizeof(char)); + memset(&tree->non_int[1], 0, n); + /* arrays to save parent subproblem components will be allocated + later */ + tree->pred_m = tree->pred_max = 0; + tree->pred_type = NULL; + tree->pred_lb = tree->pred_ub = NULL; + tree->pred_stat = NULL; + /* cut generators */ + tree->local = ios_create_pool(tree); + /*tree->first_attempt = 1;*/ + /*tree->max_added_cuts = 0;*/ + /*tree->min_eff = 0.0;*/ + /*tree->miss = 0;*/ + /*tree->just_selected = 0;*/ +#ifdef NEW_COVER /* 13/II-2018 */ + tree->cov_gen = NULL; +#endif + tree->mir_gen = NULL; + tree->clq_gen = NULL; + /*tree->round = 0;*/ +#if 0 + /* create the conflict graph */ + tree->n_ref = xcalloc(1+n, sizeof(int)); + memset(&tree->n_ref[1], 0, n * sizeof(int)); + tree->c_ref = xcalloc(1+n, sizeof(int)); + memset(&tree->c_ref[1], 0, n * sizeof(int)); + tree->g = scg_create_graph(0); + tree->j_ref = xcalloc(1+tree->g->n_max, sizeof(int)); +#endif + /* pseudocost branching */ + tree->pcost = NULL; + tree->iwrk = xcalloc(1+n, sizeof(int)); + tree->dwrk = xcalloc(1+n, sizeof(double)); + /* initialize control parameters */ + tree->parm = parm; + tree->tm_beg = xtime(); +#if 0 /* 10/VI-2013 */ + tree->tm_lag = xlset(0); +#else + tree->tm_lag = 0.0; +#endif + tree->sol_cnt = 0; +#if 1 /* 11/VII-2013 */ + tree->P = NULL; + tree->npp = NULL; + tree->save_sol = parm->save_sol; + tree->save_cnt = 0; +#endif + /* initialize advanced solver interface */ + tree->reason = 0; + tree->reopt = 0; + tree->reinv = 0; + tree->br_var = 0; + tree->br_sel = 0; + tree->child = 0; + tree->next_p = 0; + /*tree->btrack = NULL;*/ + tree->stop = 0; + /* create the root subproblem, which initially is identical to + the original MIP */ + new_node(tree, NULL); + return tree; +} + +/*********************************************************************** +* NAME +* +* ios_revive_node - revive specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_revive_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine ios_revive_node revives the specified subproblem, whose +* reference number is p, and thereby makes it the current subproblem. +* Note that the specified subproblem must be active. Besides, if the +* current subproblem already exists, it must be frozen before reviving +* another subproblem. */ + +void ios_revive_node(glp_tree *tree, int p) +{ glp_prob *mip = tree->mip; + IOSNPD *node, *root; + /* obtain pointer to the specified subproblem */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* the current subproblem must not exist */ + xassert(tree->curr == NULL); + /* the specified subproblem becomes current */ + tree->curr = node; + /*tree->solved = 0;*/ + /* obtain pointer to the root subproblem */ + root = tree->slot[1].node; + xassert(root != NULL); + /* at this point problem object components correspond to the root + subproblem, so if the root subproblem should be revived, there + is nothing more to do */ + if (node == root) goto done; + xassert(mip->m == tree->root_m); + /* build path from the root to the current node */ + node->temp = NULL; + for (node = node; node != NULL; node = node->up) + { if (node->up == NULL) + xassert(node == root); + else + node->up->temp = node; + } + /* go down from the root to the current node and make necessary + changes to restore components of the current subproblem */ + for (node = root; node != NULL; node = node->temp) + { int m = mip->m; + int n = mip->n; + /* if the current node is reached, the problem object at this + point corresponds to its parent, so save attributes of rows + and columns for the parent subproblem */ + if (node->temp == NULL) + { int i, j; + tree->pred_m = m; + /* allocate/reallocate arrays, if necessary */ + if (tree->pred_max < m + n) + { int new_size = m + n + 100; + if (tree->pred_type != NULL) xfree(tree->pred_type); + if (tree->pred_lb != NULL) xfree(tree->pred_lb); + if (tree->pred_ub != NULL) xfree(tree->pred_ub); + if (tree->pred_stat != NULL) xfree(tree->pred_stat); + tree->pred_max = new_size; + tree->pred_type = xcalloc(1+new_size, sizeof(char)); + tree->pred_lb = xcalloc(1+new_size, sizeof(double)); + tree->pred_ub = xcalloc(1+new_size, sizeof(double)); + tree->pred_stat = xcalloc(1+new_size, sizeof(char)); + } + /* save row attributes */ + for (i = 1; i <= m; i++) + { GLPROW *row = mip->row[i]; + tree->pred_type[i] = (char)row->type; + tree->pred_lb[i] = row->lb; + tree->pred_ub[i] = row->ub; + tree->pred_stat[i] = (char)row->stat; + } + /* save column attributes */ + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + tree->pred_type[mip->m+j] = (char)col->type; + tree->pred_lb[mip->m+j] = col->lb; + tree->pred_ub[mip->m+j] = col->ub; + tree->pred_stat[mip->m+j] = (char)col->stat; + } + } + /* change bounds of rows and columns */ + { IOSBND *b; + for (b = node->b_ptr; b != NULL; b = b->next) + { if (b->k <= m) + glp_set_row_bnds(mip, b->k, b->type, b->lb, b->ub); + else + glp_set_col_bnds(mip, b->k-m, b->type, b->lb, b->ub); + } + } + /* change statuses of rows and columns */ + { IOSTAT *s; + for (s = node->s_ptr; s != NULL; s = s->next) + { if (s->k <= m) + glp_set_row_stat(mip, s->k, s->stat); + else + glp_set_col_stat(mip, s->k-m, s->stat); + } + } + /* add new rows */ + if (node->r_ptr != NULL) + { IOSROW *r; + IOSAIJ *a; + int i, len, *ind; + double *val; + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (r = node->r_ptr; r != NULL; r = r->next) + { i = glp_add_rows(mip, 1); + glp_set_row_name(mip, i, r->name); +#if 1 /* 20/IX-2008 */ + xassert(mip->row[i]->level == 0); + mip->row[i]->level = node->level; + mip->row[i]->origin = r->origin; + mip->row[i]->klass = r->klass; +#endif + glp_set_row_bnds(mip, i, r->type, r->lb, r->ub); + len = 0; + for (a = r->ptr; a != NULL; a = a->next) + len++, ind[len] = a->j, val[len] = a->val; + glp_set_mat_row(mip, i, len, ind, val); + glp_set_rii(mip, i, r->rii); + glp_set_row_stat(mip, i, r->stat); + } + xfree(ind); + xfree(val); + } +#if 0 + /* add new edges to the conflict graph */ + /* add new cliques to the conflict graph */ + /* (not implemented yet) */ + xassert(node->own_nn == 0); + xassert(node->own_nc == 0); + xassert(node->e_ptr == NULL); +#endif + } + /* the specified subproblem has been revived */ + node = tree->curr; + /* delete its bound change list */ + while (node->b_ptr != NULL) + { IOSBND *b; + b = node->b_ptr; + node->b_ptr = b->next; + dmp_free_atom(tree->pool, b, sizeof(IOSBND)); + } + /* delete its status change list */ + while (node->s_ptr != NULL) + { IOSTAT *s; + s = node->s_ptr; + node->s_ptr = s->next; + dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); + } +#if 1 /* 20/XI-2009 */ + /* delete its row addition list (additional rows may appear, for + example, due to branching on GUB constraints */ + while (node->r_ptr != NULL) + { IOSROW *r; + r = node->r_ptr; + node->r_ptr = r->next; + xassert(r->name == NULL); + while (r->ptr != NULL) + { IOSAIJ *a; + a = r->ptr; + r->ptr = a->next; + dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, r, sizeof(IOSROW)); + } +#endif +done: return; +} + +/*********************************************************************** +* NAME +* +* ios_freeze_node - freeze current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_freeze_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_freeze_node freezes the current subproblem. */ + +void ios_freeze_node(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + IOSNPD *node; + /* obtain pointer to the current subproblem */ + node = tree->curr; + xassert(node != NULL); + if (node->up == NULL) + { /* freeze the root subproblem */ + int k; + xassert(node->p == 1); + xassert(tree->root_m == 0); + xassert(tree->root_type == NULL); + xassert(tree->root_lb == NULL); + xassert(tree->root_ub == NULL); + xassert(tree->root_stat == NULL); + tree->root_m = m; + tree->root_type = xcalloc(1+m+n, sizeof(char)); + tree->root_lb = xcalloc(1+m+n, sizeof(double)); + tree->root_ub = xcalloc(1+m+n, sizeof(double)); + tree->root_stat = xcalloc(1+m+n, sizeof(char)); + for (k = 1; k <= m+n; k++) + { if (k <= m) + { GLPROW *row = mip->row[k]; + tree->root_type[k] = (char)row->type; + tree->root_lb[k] = row->lb; + tree->root_ub[k] = row->ub; + tree->root_stat[k] = (char)row->stat; + } + else + { GLPCOL *col = mip->col[k-m]; + tree->root_type[k] = (char)col->type; + tree->root_lb[k] = col->lb; + tree->root_ub[k] = col->ub; + tree->root_stat[k] = (char)col->stat; + } + } + } + else + { /* freeze non-root subproblem */ + int root_m = tree->root_m; + int pred_m = tree->pred_m; + int i, j, k; + xassert(pred_m <= m); + /* build change lists for rows and columns which exist in the + parent subproblem */ + xassert(node->b_ptr == NULL); + xassert(node->s_ptr == NULL); + for (k = 1; k <= pred_m + n; k++) + { int pred_type, pred_stat, type, stat; + double pred_lb, pred_ub, lb, ub; + /* determine attributes in the parent subproblem */ + pred_type = tree->pred_type[k]; + pred_lb = tree->pred_lb[k]; + pred_ub = tree->pred_ub[k]; + pred_stat = tree->pred_stat[k]; + /* determine attributes in the current subproblem */ + if (k <= pred_m) + { GLPROW *row = mip->row[k]; + type = row->type; + lb = row->lb; + ub = row->ub; + stat = row->stat; + } + else + { GLPCOL *col = mip->col[k - pred_m]; + type = col->type; + lb = col->lb; + ub = col->ub; + stat = col->stat; + } + /* save type and bounds of a row/column, if changed */ + if (!(pred_type == type && pred_lb == lb && pred_ub == ub)) + { IOSBND *b; + b = dmp_get_atom(tree->pool, sizeof(IOSBND)); + b->k = k; + b->type = (unsigned char)type; + b->lb = lb; + b->ub = ub; + b->next = node->b_ptr; + node->b_ptr = b; + } + /* save status of a row/column, if changed */ + if (pred_stat != stat) + { IOSTAT *s; + s = dmp_get_atom(tree->pool, sizeof(IOSTAT)); + s->k = k; + s->stat = (unsigned char)stat; + s->next = node->s_ptr; + node->s_ptr = s; + } + } + /* save new rows added to the current subproblem */ + xassert(node->r_ptr == NULL); + if (pred_m < m) + { int i, len, *ind; + double *val; + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (i = m; i > pred_m; i--) + { GLPROW *row = mip->row[i]; + IOSROW *r; + const char *name; + r = dmp_get_atom(tree->pool, sizeof(IOSROW)); + name = glp_get_row_name(mip, i); + if (name == NULL) + r->name = NULL; + else + { r->name = dmp_get_atom(tree->pool, strlen(name)+1); + strcpy(r->name, name); + } +#if 1 /* 20/IX-2008 */ + r->origin = row->origin; + r->klass = row->klass; +#endif + r->type = (unsigned char)row->type; + r->lb = row->lb; + r->ub = row->ub; + r->ptr = NULL; + len = glp_get_mat_row(mip, i, ind, val); + for (k = 1; k <= len; k++) + { IOSAIJ *a; + a = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); + a->j = ind[k]; + a->val = val[k]; + a->next = r->ptr; + r->ptr = a; + } + r->rii = row->rii; + r->stat = (unsigned char)row->stat; + r->next = node->r_ptr; + node->r_ptr = r; + } + xfree(ind); + xfree(val); + } + /* remove all rows missing in the root subproblem */ + if (m != root_m) + { int nrs, *num; + nrs = m - root_m; + xassert(nrs > 0); + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = root_m + i; + glp_del_rows(mip, nrs, num); + xfree(num); + } + m = mip->m; + /* and restore attributes of all rows and columns for the root + subproblem */ + xassert(m == root_m); + for (i = 1; i <= m; i++) + { glp_set_row_bnds(mip, i, tree->root_type[i], + tree->root_lb[i], tree->root_ub[i]); + glp_set_row_stat(mip, i, tree->root_stat[i]); + } + for (j = 1; j <= n; j++) + { glp_set_col_bnds(mip, j, tree->root_type[m+j], + tree->root_lb[m+j], tree->root_ub[m+j]); + glp_set_col_stat(mip, j, tree->root_stat[m+j]); + } +#if 1 + /* remove all edges and cliques missing in the conflict graph + for the root subproblem */ + /* (not implemented yet) */ +#endif + } + /* the current subproblem has been frozen */ + tree->curr = NULL; + return; +} + +/*********************************************************************** +* NAME +* +* ios_clone_node - clone specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); +* +* DESCRIPTION +* +* The routine ios_clone_node clones the specified subproblem, whose +* reference number is p, creating its nnn exact copies. Note that the +* specified subproblem must be active and must be in the frozen state +* (i.e. it must not be the current subproblem). +* +* Each clone, an exact copy of the specified subproblem, becomes a new +* active subproblem added to the end of the active list. After cloning +* the specified subproblem becomes inactive. +* +* The reference numbers of clone subproblems are stored to locations +* ref[1], ..., ref[nnn]. */ + +static int get_slot(glp_tree *tree) +{ int p; + /* if no free slots are available, increase the room */ + if (tree->avail == 0) + { int nslots = tree->nslots; + IOSLOT *save = tree->slot; + if (nslots == 0) + tree->nslots = 20; + else + { tree->nslots = nslots + nslots; + xassert(tree->nslots > nslots); + } + tree->slot = xcalloc(1+tree->nslots, sizeof(IOSLOT)); + if (save != NULL) + { memcpy(&tree->slot[1], &save[1], nslots * sizeof(IOSLOT)); + xfree(save); + } + /* push more free slots into the stack */ + for (p = tree->nslots; p > nslots; p--) + { tree->slot[p].node = NULL; + tree->slot[p].next = tree->avail; + tree->avail = p; + } + } + /* pull a free slot from the stack */ + p = tree->avail; + tree->avail = tree->slot[p].next; + xassert(tree->slot[p].node == NULL); + tree->slot[p].next = 0; + return p; +} + +static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent) +{ IOSNPD *node; + int p; + /* pull a free slot for the new node */ + p = get_slot(tree); + /* create descriptor of the new subproblem */ + node = dmp_get_atom(tree->pool, sizeof(IOSNPD)); + tree->slot[p].node = node; + node->p = p; + node->up = parent; + node->level = (parent == NULL ? 0 : parent->level + 1); + node->count = 0; + node->b_ptr = NULL; + node->s_ptr = NULL; + node->r_ptr = NULL; + node->solved = 0; +#if 0 + node->own_nn = node->own_nc = 0; + node->e_ptr = NULL; +#endif +#if 1 /* 04/X-2008 */ + node->lp_obj = (parent == NULL ? (tree->mip->dir == GLP_MIN ? + -DBL_MAX : +DBL_MAX) : parent->lp_obj); +#endif + node->bound = (parent == NULL ? (tree->mip->dir == GLP_MIN ? + -DBL_MAX : +DBL_MAX) : parent->bound); + node->br_var = 0; + node->br_val = 0.0; + node->ii_cnt = 0; + node->ii_sum = 0.0; +#if 1 /* 30/XI-2009 */ + node->changed = 0; +#endif + if (tree->parm->cb_size == 0) + node->data = NULL; + else + { node->data = dmp_get_atom(tree->pool, tree->parm->cb_size); + memset(node->data, 0, tree->parm->cb_size); + } + node->temp = NULL; + node->prev = tree->tail; + node->next = NULL; + /* add the new subproblem to the end of the active list */ + if (tree->head == NULL) + tree->head = node; + else + tree->tail->next = node; + tree->tail = node; + tree->a_cnt++; + tree->n_cnt++; + tree->t_cnt++; + /* increase the number of child subproblems */ + if (parent == NULL) + xassert(p == 1); + else + parent->count++; + return node; +} + +void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]) +{ IOSNPD *node; + int k; + /* obtain pointer to the subproblem to be cloned */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* and must be in the frozen state */ + xassert(tree->curr != node); + /* remove the specified subproblem from the active list, because + it becomes inactive */ + if (node->prev == NULL) + tree->head = node->next; + else + node->prev->next = node->next; + if (node->next == NULL) + tree->tail = node->prev; + else + node->next->prev = node->prev; + node->prev = node->next = NULL; + tree->a_cnt--; + /* create clone subproblems */ + xassert(nnn > 0); + for (k = 1; k <= nnn; k++) + ref[k] = new_node(tree, node)->p; + return; +} + +/*********************************************************************** +* NAME +* +* ios_delete_node - delete specified subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_delete_node(glp_tree *tree, int p); +* +* DESCRIPTION +* +* The routine ios_delete_node deletes the specified subproblem, whose +* reference number is p. The subproblem must be active and must be in +* the frozen state (i.e. it must not be the current subproblem). +* +* Note that deletion is performed recursively, i.e. if a subproblem to +* be deleted is the only child of its parent, the parent subproblem is +* also deleted, etc. */ + +void ios_delete_node(glp_tree *tree, int p) +{ IOSNPD *node, *temp; + /* obtain pointer to the subproblem to be deleted */ + xassert(1 <= p && p <= tree->nslots); + node = tree->slot[p].node; + xassert(node != NULL); + /* the specified subproblem must be active */ + xassert(node->count == 0); + /* and must be in the frozen state */ + xassert(tree->curr != node); + /* remove the specified subproblem from the active list, because + it is gone from the tree */ + if (node->prev == NULL) + tree->head = node->next; + else + node->prev->next = node->next; + if (node->next == NULL) + tree->tail = node->prev; + else + node->next->prev = node->prev; + node->prev = node->next = NULL; + tree->a_cnt--; +loop: /* recursive deletion starts here */ + /* delete the bound change list */ + { IOSBND *b; + while (node->b_ptr != NULL) + { b = node->b_ptr; + node->b_ptr = b->next; + dmp_free_atom(tree->pool, b, sizeof(IOSBND)); + } + } + /* delete the status change list */ + { IOSTAT *s; + while (node->s_ptr != NULL) + { s = node->s_ptr; + node->s_ptr = s->next; + dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); + } + } + /* delete the row addition list */ + while (node->r_ptr != NULL) + { IOSROW *r; + r = node->r_ptr; + if (r->name != NULL) + dmp_free_atom(tree->pool, r->name, strlen(r->name)+1); + while (r->ptr != NULL) + { IOSAIJ *a; + a = r->ptr; + r->ptr = a->next; + dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); + } + node->r_ptr = r->next; + dmp_free_atom(tree->pool, r, sizeof(IOSROW)); + } +#if 0 + /* delete the edge addition list */ + /* delete the clique addition list */ + /* (not implemented yet) */ + xassert(node->own_nn == 0); + xassert(node->own_nc == 0); + xassert(node->e_ptr == NULL); +#endif + /* free application-specific data */ + if (tree->parm->cb_size == 0) + xassert(node->data == NULL); + else + dmp_free_atom(tree->pool, node->data, tree->parm->cb_size); + /* free the corresponding node slot */ + p = node->p; + xassert(tree->slot[p].node == node); + tree->slot[p].node = NULL; + tree->slot[p].next = tree->avail; + tree->avail = p; + /* save pointer to the parent subproblem */ + temp = node->up; + /* delete the subproblem descriptor */ + dmp_free_atom(tree->pool, node, sizeof(IOSNPD)); + tree->n_cnt--; + /* take pointer to the parent subproblem */ + node = temp; + if (node != NULL) + { /* the parent subproblem exists; decrease the number of its + child subproblems */ + xassert(node->count > 0); + node->count--; + /* if now the parent subproblem has no childs, it also must be + deleted */ + if (node->count == 0) goto loop; + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_delete_tree - delete branch-and-bound tree +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_delete_tree(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_delete_tree deletes the branch-and-bound tree, which +* the parameter tree points to, and frees all the memory allocated to +* this program object. +* +* On exit components of the problem object are restored to correspond +* to the original MIP passed to the routine ios_create_tree. */ + +void ios_delete_tree(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int i, j; + int m = mip->m; + int n = mip->n; + xassert(mip->tree == tree); + /* remove all additional rows */ + if (m != tree->orig_m) + { int nrs, *num; + nrs = m - tree->orig_m; + xassert(nrs > 0); + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = tree->orig_m + i; + glp_del_rows(mip, nrs, num); + xfree(num); + } + m = tree->orig_m; + /* restore original attributes of rows and columns */ + xassert(m == tree->orig_m); + xassert(n == tree->n); + for (i = 1; i <= m; i++) + { glp_set_row_bnds(mip, i, tree->orig_type[i], + tree->orig_lb[i], tree->orig_ub[i]); + glp_set_row_stat(mip, i, tree->orig_stat[i]); + mip->row[i]->prim = tree->orig_prim[i]; + mip->row[i]->dual = tree->orig_dual[i]; + } + for (j = 1; j <= n; j++) + { glp_set_col_bnds(mip, j, tree->orig_type[m+j], + tree->orig_lb[m+j], tree->orig_ub[m+j]); + glp_set_col_stat(mip, j, tree->orig_stat[m+j]); + mip->col[j]->prim = tree->orig_prim[m+j]; + mip->col[j]->dual = tree->orig_dual[m+j]; + } + mip->pbs_stat = mip->dbs_stat = GLP_FEAS; + mip->obj_val = tree->orig_obj; + /* delete the branch-and-bound tree */ + xassert(tree->local != NULL); + ios_delete_pool(tree, tree->local); + dmp_delete_pool(tree->pool); + xfree(tree->orig_type); + xfree(tree->orig_lb); + xfree(tree->orig_ub); + xfree(tree->orig_stat); + xfree(tree->orig_prim); + xfree(tree->orig_dual); + xfree(tree->slot); + if (tree->root_type != NULL) xfree(tree->root_type); + if (tree->root_lb != NULL) xfree(tree->root_lb); + if (tree->root_ub != NULL) xfree(tree->root_ub); + if (tree->root_stat != NULL) xfree(tree->root_stat); + xfree(tree->non_int); +#if 0 + xfree(tree->n_ref); + xfree(tree->c_ref); + xfree(tree->j_ref); +#endif + if (tree->pcost != NULL) ios_pcost_free(tree); + xfree(tree->iwrk); + xfree(tree->dwrk); +#if 0 + scg_delete_graph(tree->g); +#endif + if (tree->pred_type != NULL) xfree(tree->pred_type); + if (tree->pred_lb != NULL) xfree(tree->pred_lb); + if (tree->pred_ub != NULL) xfree(tree->pred_ub); + if (tree->pred_stat != NULL) xfree(tree->pred_stat); +#if 0 + xassert(tree->cut_gen == NULL); +#endif + xassert(tree->mir_gen == NULL); + xassert(tree->clq_gen == NULL); + xfree(tree); + mip->tree = NULL; + return; +} + +/*********************************************************************** +* NAME +* +* ios_eval_degrad - estimate obj. degrad. for down- and up-branches +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); +* +* DESCRIPTION +* +* Given optimal basis to LP relaxation of the current subproblem the +* routine ios_eval_degrad performs the dual ratio test to compute the +* objective values in the adjacent basis for down- and up-branches, +* which are stored in locations *dn and *up, assuming that x[j] is a +* variable chosen to branch upon. */ + +void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up) +{ glp_prob *mip = tree->mip; + int m = mip->m, n = mip->n; + int len, kase, k, t, stat; + double alfa, beta, gamma, delta, dz; + int *ind = tree->iwrk; + double *val = tree->dwrk; + /* current basis must be optimal */ + xassert(glp_get_status(mip) == GLP_OPT); + /* basis factorization must exist */ + xassert(glp_bf_exists(mip)); + /* obtain (fractional) value of x[j] in optimal basic solution + to LP relaxation of the current subproblem */ + xassert(1 <= j && j <= n); + beta = mip->col[j]->prim; + /* since the value of x[j] is fractional, it is basic; compute + corresponding row of the simplex table */ + len = lpx_eval_tab_row(mip, m+j, ind, val); + /* kase < 0 means down-branch; kase > 0 means up-branch */ + for (kase = -1; kase <= +1; kase += 2) + { /* for down-branch we introduce new upper bound floor(beta) + for x[j]; similarly, for up-branch we introduce new lower + bound ceil(beta) for x[j]; in the current basis this new + upper/lower bound is violated, so in the adjacent basis + x[j] will leave the basis and go to its new upper/lower + bound; we need to know which non-basic variable x[k] should + enter the basis to keep dual feasibility */ +#if 0 /* 23/XI-2009 */ + k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-7); +#else + k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-9); +#endif + /* if no variable has been chosen, current basis being primal + infeasible due to the new upper/lower bound of x[j] is dual + unbounded, therefore, LP relaxation to corresponding branch + has no primal feasible solution */ + if (k == 0) + { if (mip->dir == GLP_MIN) + { if (kase < 0) + *dn = +DBL_MAX; + else + *up = +DBL_MAX; + } + else if (mip->dir == GLP_MAX) + { if (kase < 0) + *dn = -DBL_MAX; + else + *up = -DBL_MAX; + } + else + xassert(mip != mip); + continue; + } + xassert(1 <= k && k <= m+n); + /* row of the simplex table corresponding to specified basic + variable x[j] is the following: + x[j] = ... + alfa * x[k] + ... ; + we need to know influence coefficient, alfa, at non-basic + variable x[k] chosen with the dual ratio test */ + for (t = 1; t <= len; t++) + if (ind[t] == k) break; + xassert(1 <= t && t <= len); + alfa = val[t]; + /* determine status and reduced cost of variable x[k] */ + if (k <= m) + { stat = mip->row[k]->stat; + gamma = mip->row[k]->dual; + } + else + { stat = mip->col[k-m]->stat; + gamma = mip->col[k-m]->dual; + } + /* x[k] cannot be basic or fixed non-basic */ + xassert(stat == GLP_NL || stat == GLP_NU || stat == GLP_NF); + /* if the current basis is dual degenerative, some reduced + costs, which are close to zero, may have wrong sign due to + round-off errors, so correct the sign of gamma */ + if (mip->dir == GLP_MIN) + { if (stat == GLP_NL && gamma < 0.0 || + stat == GLP_NU && gamma > 0.0 || + stat == GLP_NF) gamma = 0.0; + } + else if (mip->dir == GLP_MAX) + { if (stat == GLP_NL && gamma > 0.0 || + stat == GLP_NU && gamma < 0.0 || + stat == GLP_NF) gamma = 0.0; + } + else + xassert(mip != mip); + /* determine the change of x[j] in the adjacent basis: + delta x[j] = new x[j] - old x[j] */ + delta = (kase < 0 ? floor(beta) : ceil(beta)) - beta; + /* compute the change of x[k] in the adjacent basis: + delta x[k] = new x[k] - old x[k] = delta x[j] / alfa */ + delta /= alfa; + /* compute the change of the objective in the adjacent basis: + delta z = new z - old z = gamma * delta x[k] */ + dz = gamma * delta; + if (mip->dir == GLP_MIN) + xassert(dz >= 0.0); + else if (mip->dir == GLP_MAX) + xassert(dz <= 0.0); + else + xassert(mip != mip); + /* compute the new objective value in the adjacent basis: + new z = old z + delta z */ + if (kase < 0) + *dn = mip->obj_val + dz; + else + *up = mip->obj_val + dz; + } + /*xprintf("obj = %g; dn = %g; up = %g\n", + mip->obj_val, *dn, *up);*/ + return; +} + +/*********************************************************************** +* NAME +* +* ios_round_bound - improve local bound by rounding +* +* SYNOPSIS +* +* #include "glpios.h" +* double ios_round_bound(glp_tree *tree, double bound); +* +* RETURNS +* +* For the given local bound for any integer feasible solution to the +* current subproblem the routine ios_round_bound returns an improved +* local bound for the same integer feasible solution. +* +* BACKGROUND +* +* Let the current subproblem has the following objective function: +* +* z = sum c[j] * x[j] + s >= b, (1) +* j in J +* +* where J = {j: c[j] is non-zero and integer, x[j] is integer}, s is +* the sum of terms corresponding to fixed variables, b is an initial +* local bound (minimization). +* +* From (1) it follows that: +* +* d * sum (c[j] / d) * x[j] + s >= b, (2) +* j in J +* +* or, equivalently, +* +* sum (c[j] / d) * x[j] >= (b - s) / d = h, (3) +* j in J +* +* where d = gcd(c[j]). Since the left-hand side of (3) is integer, +* h = (b - s) / d can be rounded up to the nearest integer: +* +* h' = ceil(h) = (b' - s) / d, (4) +* +* that gives an rounded, improved local bound: +* +* b' = d * h' + s. (5) +* +* In case of maximization '>=' in (1) should be replaced by '<=' that +* leads to the following formula: +* +* h' = floor(h) = (b' - s) / d, (6) +* +* which should used in the same way as (4). +* +* NOTE: If b is a valid local bound for a child of the current +* subproblem, b' is also valid for that child subproblem. */ + +double ios_round_bound(glp_tree *tree, double bound) +{ glp_prob *mip = tree->mip; + int n = mip->n; + int d, j, nn, *c = tree->iwrk; + double s, h; + /* determine c[j] and compute s */ + nn = 0, s = mip->c0, d = 0; + for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->coef == 0.0) continue; + if (col->type == GLP_FX) + { /* fixed variable */ + s += col->coef * col->prim; + } + else + { /* non-fixed variable */ + if (col->kind != GLP_IV) goto skip; + if (col->coef != floor(col->coef)) goto skip; + if (fabs(col->coef) <= (double)INT_MAX) + c[++nn] = (int)fabs(col->coef); + else + d = 1; + } + } + /* compute d = gcd(c[1],...c[nn]) */ + if (d == 0) + { if (nn == 0) goto skip; + d = gcdn(nn, c); + } + xassert(d > 0); + /* compute new local bound */ + if (mip->dir == GLP_MIN) + { if (bound != +DBL_MAX) + { h = (bound - s) / (double)d; + if (h >= floor(h) + 0.001) + { /* round up */ + h = ceil(h); + /*xprintf("d = %d; old = %g; ", d, bound);*/ + bound = (double)d * h + s; + /*xprintf("new = %g\n", bound);*/ + } + } + } + else if (mip->dir == GLP_MAX) + { if (bound != -DBL_MAX) + { h = (bound - s) / (double)d; + if (h <= ceil(h) - 0.001) + { /* round down */ + h = floor(h); + bound = (double)d * h + s; + } + } + } + else + xassert(mip != mip); +skip: return bound; +} + +/*********************************************************************** +* NAME +* +* ios_is_hopeful - check if subproblem is hopeful +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_is_hopeful(glp_tree *tree, double bound); +* +* DESCRIPTION +* +* Given the local bound of a subproblem the routine ios_is_hopeful +* checks if the subproblem can have an integer optimal solution which +* is better than the best one currently known. +* +* RETURNS +* +* If the subproblem can have a better integer optimal solution, the +* routine returns non-zero; otherwise, if the corresponding branch can +* be pruned, the routine returns zero. */ + +int ios_is_hopeful(glp_tree *tree, double bound) +{ glp_prob *mip = tree->mip; + int ret = 1; + double eps; + if (mip->mip_stat == GLP_FEAS) + { eps = tree->parm->tol_obj * (1.0 + fabs(mip->mip_obj)); + switch (mip->dir) + { case GLP_MIN: + if (bound >= mip->mip_obj - eps) ret = 0; + break; + case GLP_MAX: + if (bound <= mip->mip_obj + eps) ret = 0; + break; + default: + xassert(mip != mip); + } + } + else + { switch (mip->dir) + { case GLP_MIN: + if (bound == +DBL_MAX) ret = 0; + break; + case GLP_MAX: + if (bound == -DBL_MAX) ret = 0; + break; + default: + xassert(mip != mip); + } + } + return ret; +} + +/*********************************************************************** +* NAME +* +* ios_best_node - find active node with best local bound +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_best_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_best_node finds an active node whose local bound is +* best among other active nodes. +* +* It is understood that the integer optimal solution of the original +* mip problem cannot be better than the best bound, so the best bound +* is an lower (minimization) or upper (maximization) global bound for +* the original problem. +* +* RETURNS +* +* The routine ios_best_node returns the subproblem reference number +* for the best node. However, if the tree is empty, it returns zero. */ + +int ios_best_node(glp_tree *tree) +{ IOSNPD *node, *best = NULL; + switch (tree->mip->dir) + { case GLP_MIN: + /* minimization */ + for (node = tree->head; node != NULL; node = node->next) + if (best == NULL || best->bound > node->bound) + best = node; + break; + case GLP_MAX: + /* maximization */ + for (node = tree->head; node != NULL; node = node->next) + if (best == NULL || best->bound < node->bound) + best = node; + break; + default: + xassert(tree != tree); + } + return best == NULL ? 0 : best->p; +} + +/*********************************************************************** +* NAME +* +* ios_relative_gap - compute relative mip gap +* +* SYNOPSIS +* +* #include "glpios.h" +* double ios_relative_gap(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_relative_gap computes the relative mip gap using the +* formula: +* +* gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), +* +* where best_mip is the best integer feasible solution found so far, +* best_bnd is the best (global) bound. If no integer feasible solution +* has been found yet, rel_gap is set to DBL_MAX. +* +* RETURNS +* +* The routine ios_relative_gap returns the relative mip gap. */ + +double ios_relative_gap(glp_tree *tree) +{ glp_prob *mip = tree->mip; + int p; + double best_mip, best_bnd, gap; + if (mip->mip_stat == GLP_FEAS) + { best_mip = mip->mip_obj; + p = ios_best_node(tree); + if (p == 0) + { /* the tree is empty */ + gap = 0.0; + } + else + { best_bnd = tree->slot[p].node->bound; + gap = fabs(best_mip - best_bnd) / (fabs(best_mip) + + DBL_EPSILON); + } + } + else + { /* no integer feasible solution has been found yet */ + gap = DBL_MAX; + } + return gap; +} + +/*********************************************************************** +* NAME +* +* ios_solve_node - solve LP relaxation of current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_solve_node(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_solve_node re-optimizes LP relaxation of the current +* subproblem using the dual simplex method. +* +* RETURNS +* +* The routine returns the code which is reported by glp_simplex. */ + +int ios_solve_node(glp_tree *tree) +{ glp_prob *mip = tree->mip; + glp_smcp parm; + int ret; + /* the current subproblem must exist */ + xassert(tree->curr != NULL); + /* set some control parameters */ + glp_init_smcp(&parm); + switch (tree->parm->msg_lev) + { case GLP_MSG_OFF: + parm.msg_lev = GLP_MSG_OFF; break; + case GLP_MSG_ERR: + parm.msg_lev = GLP_MSG_ERR; break; + case GLP_MSG_ON: + case GLP_MSG_ALL: + parm.msg_lev = GLP_MSG_ON; break; + case GLP_MSG_DBG: + parm.msg_lev = GLP_MSG_ALL; break; + default: + xassert(tree != tree); + } + parm.meth = GLP_DUALP; +#if 1 /* 16/III-2016 */ + if (tree->parm->flip) + parm.r_test = GLP_RT_FLIP; +#endif + /* respect time limit */ + if (tree->parm->tm_lim < INT_MAX) + parm.tm_lim = tree->parm->tm_lim - (glp_time() - tree->tm_beg); + if (parm.tm_lim < 0) + parm.tm_lim = 0; + if (tree->parm->msg_lev < GLP_MSG_DBG) + parm.out_dly = tree->parm->out_dly; + else + parm.out_dly = 0; + /* if the incumbent objective value is already known, use it to + prematurely terminate the dual simplex search */ + if (mip->mip_stat == GLP_FEAS) + { switch (tree->mip->dir) + { case GLP_MIN: + parm.obj_ul = mip->mip_obj; + break; + case GLP_MAX: + parm.obj_ll = mip->mip_obj; + break; + default: + xassert(mip != mip); + } + } + /* try to solve/re-optimize the LP relaxation */ + ret = glp_simplex(mip, &parm); +#if 1 /* 21/II-2016 by Chris */ + if (ret == GLP_EFAIL) + { /* retry with a new basis */ + glp_adv_basis(mip, 0); + ret = glp_simplex(mip, &parm); + } +#endif + tree->curr->solved++; +#if 0 + xprintf("ret = %d; status = %d; pbs = %d; dbs = %d; some = %d\n", + ret, glp_get_status(mip), mip->pbs_stat, mip->dbs_stat, + mip->some); + lpx_print_sol(mip, "sol"); +#endif + return ret; +} + +/**********************************************************************/ + +#ifdef NEW_LOCAL /* 02/II-2018 */ +IOSPOOL *ios_create_pool(glp_tree *tree) +{ /* create cut pool */ + IOSPOOL *pool; + pool = glp_create_prob(); + glp_add_cols(pool, tree->mip->n); + return pool; +} +#else +IOSPOOL *ios_create_pool(glp_tree *tree) +{ /* create cut pool */ + IOSPOOL *pool; +#if 0 + pool = dmp_get_atom(tree->pool, sizeof(IOSPOOL)); +#else + xassert(tree == tree); + pool = xmalloc(sizeof(IOSPOOL)); +#endif + pool->size = 0; + pool->head = pool->tail = NULL; + pool->ord = 0, pool->curr = NULL; + return pool; +} +#endif + +#ifdef NEW_LOCAL /* 02/II-2018 */ +int ios_add_row(glp_tree *tree, IOSPOOL *pool, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs) +{ /* add row (constraint) to the cut pool */ + int i; + i = glp_add_rows(pool, 1); + glp_set_row_name(pool, i, name); + pool->row[i]->klass = klass; + xassert(flags == 0); + glp_set_mat_row(pool, i, len, ind, val); + glp_set_row_bnds(pool, i, type, rhs, rhs); + return i; +} +#else +int ios_add_row(glp_tree *tree, IOSPOOL *pool, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs) +{ /* add row (constraint) to the cut pool */ + IOSCUT *cut; + IOSAIJ *aij; + int k; + xassert(pool != NULL); + cut = dmp_get_atom(tree->pool, sizeof(IOSCUT)); + if (name == NULL || name[0] == '\0') + cut->name = NULL; + else + { for (k = 0; name[k] != '\0'; k++) + { if (k == 256) + xerror("glp_ios_add_row: cut name too long\n"); + if (iscntrl((unsigned char)name[k])) + xerror("glp_ios_add_row: cut name contains invalid chara" + "cter(s)\n"); + } + cut->name = dmp_get_atom(tree->pool, strlen(name)+1); + strcpy(cut->name, name); + } + if (!(0 <= klass && klass <= 255)) + xerror("glp_ios_add_row: klass = %d; invalid cut class\n", + klass); + cut->klass = (unsigned char)klass; + if (flags != 0) + xerror("glp_ios_add_row: flags = %d; invalid cut flags\n", + flags); + cut->ptr = NULL; + if (!(0 <= len && len <= tree->n)) + xerror("glp_ios_add_row: len = %d; invalid cut length\n", + len); + for (k = 1; k <= len; k++) + { aij = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); + if (!(1 <= ind[k] && ind[k] <= tree->n)) + xerror("glp_ios_add_row: ind[%d] = %d; column index out of " + "range\n", k, ind[k]); + aij->j = ind[k]; + aij->val = val[k]; + aij->next = cut->ptr; + cut->ptr = aij; + } + if (!(type == GLP_LO || type == GLP_UP || type == GLP_FX)) + xerror("glp_ios_add_row: type = %d; invalid cut type\n", + type); + cut->type = (unsigned char)type; + cut->rhs = rhs; + cut->prev = pool->tail; + cut->next = NULL; + if (cut->prev == NULL) + pool->head = cut; + else + cut->prev->next = cut; + pool->tail = cut; + pool->size++; + return pool->size; +} +#endif + +#ifdef NEW_LOCAL /* 02/II-2018 */ +IOSCUT *ios_find_row(IOSPOOL *pool, int i) +{ /* find row (constraint) in the cut pool */ + xassert(0); +} +#else +IOSCUT *ios_find_row(IOSPOOL *pool, int i) +{ /* find row (constraint) in the cut pool */ + /* (smart linear search) */ + xassert(pool != NULL); + xassert(1 <= i && i <= pool->size); + if (pool->ord == 0) + { xassert(pool->curr == NULL); + pool->ord = 1; + pool->curr = pool->head; + } + xassert(pool->curr != NULL); + if (i < pool->ord) + { if (i < pool->ord - i) + { pool->ord = 1; + pool->curr = pool->head; + while (pool->ord != i) + { pool->ord++; + xassert(pool->curr != NULL); + pool->curr = pool->curr->next; + } + } + else + { while (pool->ord != i) + { pool->ord--; + xassert(pool->curr != NULL); + pool->curr = pool->curr->prev; + } + } + } + else if (i > pool->ord) + { if (i - pool->ord < pool->size - i) + { while (pool->ord != i) + { pool->ord++; + xassert(pool->curr != NULL); + pool->curr = pool->curr->next; + } + } + else + { pool->ord = pool->size; + pool->curr = pool->tail; + while (pool->ord != i) + { pool->ord--; + xassert(pool->curr != NULL); + pool->curr = pool->curr->prev; + } + } + } + xassert(pool->ord == i); + xassert(pool->curr != NULL); + return pool->curr; +} +#endif + +#ifdef NEW_LOCAL /* 02/II-2018 */ +void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i) +{ /* remove row (constraint) from the cut pool */ + xassert(0); +} +#else +void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i) +{ /* remove row (constraint) from the cut pool */ + IOSCUT *cut; + IOSAIJ *aij; + xassert(pool != NULL); + if (!(1 <= i && i <= pool->size)) + xerror("glp_ios_del_row: i = %d; cut number out of range\n", + i); + cut = ios_find_row(pool, i); + xassert(pool->curr == cut); + if (cut->next != NULL) + pool->curr = cut->next; + else if (cut->prev != NULL) + pool->ord--, pool->curr = cut->prev; + else + pool->ord = 0, pool->curr = NULL; + if (cut->name != NULL) + dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); + if (cut->prev == NULL) + { xassert(pool->head == cut); + pool->head = cut->next; + } + else + { xassert(cut->prev->next == cut); + cut->prev->next = cut->next; + } + if (cut->next == NULL) + { xassert(pool->tail == cut); + pool->tail = cut->prev; + } + else + { xassert(cut->next->prev == cut); + cut->next->prev = cut->prev; + } + while (cut->ptr != NULL) + { aij = cut->ptr; + cut->ptr = aij->next; + dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); + pool->size--; + return; +} +#endif + +#ifdef NEW_LOCAL /* 02/II-2018 */ +void ios_clear_pool(glp_tree *tree, IOSPOOL *pool) +{ /* remove all rows (constraints) from the cut pool */ + if (pool->m > 0) + { int i, *num; + num = talloc(1+pool->m, int); + for (i = 1; i <= pool->m; i++) + num[i] = i; + glp_del_rows(pool, pool->m, num); + tfree(num); + } + return; +} +#else +void ios_clear_pool(glp_tree *tree, IOSPOOL *pool) +{ /* remove all rows (constraints) from the cut pool */ + xassert(pool != NULL); + while (pool->head != NULL) + { IOSCUT *cut = pool->head; + pool->head = cut->next; + if (cut->name != NULL) + dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); + while (cut->ptr != NULL) + { IOSAIJ *aij = cut->ptr; + cut->ptr = aij->next; + dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); + } + dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); + } + pool->size = 0; + pool->head = pool->tail = NULL; + pool->ord = 0, pool->curr = NULL; + return; +} +#endif + +#ifdef NEW_LOCAL /* 02/II-2018 */ +void ios_delete_pool(glp_tree *tree, IOSPOOL *pool) +{ /* delete cut pool */ + xassert(pool != NULL); + glp_delete_prob(pool); + return; +} +#else +void ios_delete_pool(glp_tree *tree, IOSPOOL *pool) +{ /* delete cut pool */ + xassert(pool != NULL); + ios_clear_pool(tree, pool); + xfree(pool); + return; +} +#endif + +#if 1 /* 11/VII-2013 */ +#include "npp.h" + +void ios_process_sol(glp_tree *T) +{ /* process integer feasible solution just found */ + if (T->npp != NULL) + { /* postprocess solution from transformed mip */ + npp_postprocess(T->npp, T->mip); + /* store solution to problem passed to glp_intopt */ + npp_unload_sol(T->npp, T->P); + } + xassert(T->P != NULL); + /* save solution to text file, if requested */ + if (T->save_sol != NULL) + { char *fn, *mark; + fn = talloc(strlen(T->save_sol) + 50, char); + mark = strrchr(T->save_sol, '*'); + if (mark == NULL) + strcpy(fn, T->save_sol); + else + { memcpy(fn, T->save_sol, mark - T->save_sol); + fn[mark - T->save_sol] = '\0'; + sprintf(fn + strlen(fn), "%03d", ++(T->save_cnt)); + strcat(fn, &mark[1]); + } + glp_write_mip(T->P, fn); + tfree(fn); + } + return; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios02.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios02.c new file mode 100644 index 000000000..a73458aad --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios02.c @@ -0,0 +1,826 @@ +/* glpios02.c (preprocess current subproblem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* prepare_row_info - prepare row info to determine implied bounds +* +* Given a row (linear form) +* +* n +* sum a[j] * x[j] (1) +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] (2) +* +* this routine computes f_min, j_min, f_max, j_max needed to determine +* implied bounds. +* +* ALGORITHM +* +* Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. +* +* Parameters f_min and j_min are computed as follows: +* +* 1) if there is no x[k] such that k in J+ and l[k] = -inf or k in J- +* and u[k] = +inf, then +* +* f_min := sum a[j] * l[j] + sum a[j] * u[j] +* j in J+ j in J- +* (3) +* j_min := 0 +* +* 2) if there is exactly one x[k] such that k in J+ and l[k] = -inf +* or k in J- and u[k] = +inf, then +* +* f_min := sum a[j] * l[j] + sum a[j] * u[j] +* j in J+\{k} j in J-\{k} +* (4) +* j_min := k +* +* 3) if there are two or more x[k] such that k in J+ and l[k] = -inf +* or k in J- and u[k] = +inf, then +* +* f_min := -inf +* (5) +* j_min := 0 +* +* Parameters f_max and j_max are computed in a similar way as follows: +* +* 1) if there is no x[k] such that k in J+ and u[k] = +inf or k in J- +* and l[k] = -inf, then +* +* f_max := sum a[j] * u[j] + sum a[j] * l[j] +* j in J+ j in J- +* (6) +* j_max := 0 +* +* 2) if there is exactly one x[k] such that k in J+ and u[k] = +inf +* or k in J- and l[k] = -inf, then +* +* f_max := sum a[j] * u[j] + sum a[j] * l[j] +* j in J+\{k} j in J-\{k} +* (7) +* j_max := k +* +* 3) if there are two or more x[k] such that k in J+ and u[k] = +inf +* or k in J- and l[k] = -inf, then +* +* f_max := +inf +* (8) +* j_max := 0 */ + +struct f_info +{ int j_min, j_max; + double f_min, f_max; +}; + +static void prepare_row_info(int n, const double a[], const double l[], + const double u[], struct f_info *f) +{ int j, j_min, j_max; + double f_min, f_max; + xassert(n >= 0); + /* determine f_min and j_min */ + f_min = 0.0, j_min = 0; + for (j = 1; j <= n; j++) + { if (a[j] > 0.0) + { if (l[j] == -DBL_MAX) + { if (j_min == 0) + j_min = j; + else + { f_min = -DBL_MAX, j_min = 0; + break; + } + } + else + f_min += a[j] * l[j]; + } + else if (a[j] < 0.0) + { if (u[j] == +DBL_MAX) + { if (j_min == 0) + j_min = j; + else + { f_min = -DBL_MAX, j_min = 0; + break; + } + } + else + f_min += a[j] * u[j]; + } + else + xassert(a != a); + } + f->f_min = f_min, f->j_min = j_min; + /* determine f_max and j_max */ + f_max = 0.0, j_max = 0; + for (j = 1; j <= n; j++) + { if (a[j] > 0.0) + { if (u[j] == +DBL_MAX) + { if (j_max == 0) + j_max = j; + else + { f_max = +DBL_MAX, j_max = 0; + break; + } + } + else + f_max += a[j] * u[j]; + } + else if (a[j] < 0.0) + { if (l[j] == -DBL_MAX) + { if (j_max == 0) + j_max = j; + else + { f_max = +DBL_MAX, j_max = 0; + break; + } + } + else + f_max += a[j] * l[j]; + } + else + xassert(a != a); + } + f->f_max = f_max, f->j_max = j_max; + return; +} + +/*********************************************************************** +* row_implied_bounds - determine row implied bounds +* +* Given a row (linear form) +* +* n +* sum a[j] * x[j] +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine determines implied bounds of the row. +* +* ALGORITHM +* +* Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. +* +* The implied lower bound of the row is computed as follows: +* +* L' := sum a[j] * l[j] + sum a[j] * u[j] (9) +* j in J+ j in J- +* +* and as it follows from (3), (4), and (5): +* +* L' := if j_min = 0 then f_min else -inf (10) +* +* The implied upper bound of the row is computed as follows: +* +* U' := sum a[j] * u[j] + sum a[j] * l[j] (11) +* j in J+ j in J- +* +* and as it follows from (6), (7), and (8): +* +* U' := if j_max = 0 then f_max else +inf (12) +* +* The implied bounds are stored in locations LL and UU. */ + +static void row_implied_bounds(const struct f_info *f, double *LL, + double *UU) +{ *LL = (f->j_min == 0 ? f->f_min : -DBL_MAX); + *UU = (f->j_max == 0 ? f->f_max : +DBL_MAX); + return; +} + +/*********************************************************************** +* col_implied_bounds - determine column implied bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U (13) +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine determines implied bounds of variable x[k]. +* +* It is assumed that if L != -inf, the lower bound of the row can be +* active, and if U != +inf, the upper bound of the row can be active. +* +* ALGORITHM +* +* From (13) it follows that +* +* L <= sum a[j] * x[j] + a[k] * x[k] <= U +* j!=k +* or +* +* L - sum a[j] * x[j] <= a[k] * x[k] <= U - sum a[j] * x[j] +* j!=k j!=k +* +* Thus, if the row lower bound L can be active, implied lower bound of +* term a[k] * x[k] can be determined as follows: +* +* ilb(a[k] * x[k]) = min(L - sum a[j] * x[j]) = +* j!=k +* (14) +* = L - max sum a[j] * x[j] +* j!=k +* +* where, as it follows from (6), (7), and (8) +* +* / f_max - a[k] * u[k], j_max = 0, a[k] > 0 +* | +* | f_max - a[k] * l[k], j_max = 0, a[k] < 0 +* max sum a[j] * x[j] = { +* j!=k | f_max, j_max = k +* | +* \ +inf, j_max != 0 +* +* and if the upper bound U can be active, implied upper bound of term +* a[k] * x[k] can be determined as follows: +* +* iub(a[k] * x[k]) = max(U - sum a[j] * x[j]) = +* j!=k +* (15) +* = U - min sum a[j] * x[j] +* j!=k +* +* where, as it follows from (3), (4), and (5) +* +* / f_min - a[k] * l[k], j_min = 0, a[k] > 0 +* | +* | f_min - a[k] * u[k], j_min = 0, a[k] < 0 +* min sum a[j] * x[j] = { +* j!=k | f_min, j_min = k +* | +* \ -inf, j_min != 0 +* +* Since +* +* ilb(a[k] * x[k]) <= a[k] * x[k] <= iub(a[k] * x[k]) +* +* implied lower and upper bounds of x[k] are determined as follows: +* +* l'[k] := if a[k] > 0 then ilb / a[k] else ulb / a[k] (16) +* +* u'[k] := if a[k] > 0 then ulb / a[k] else ilb / a[k] (17) +* +* The implied bounds are stored in locations ll and uu. */ + +static void col_implied_bounds(const struct f_info *f, int n, + const double a[], double L, double U, const double l[], + const double u[], int k, double *ll, double *uu) +{ double ilb, iub; + xassert(n >= 0); + xassert(1 <= k && k <= n); + /* determine implied lower bound of term a[k] * x[k] (14) */ + if (L == -DBL_MAX || f->f_max == +DBL_MAX) + ilb = -DBL_MAX; + else if (f->j_max == 0) + { if (a[k] > 0.0) + { xassert(u[k] != +DBL_MAX); + ilb = L - (f->f_max - a[k] * u[k]); + } + else if (a[k] < 0.0) + { xassert(l[k] != -DBL_MAX); + ilb = L - (f->f_max - a[k] * l[k]); + } + else + xassert(a != a); + } + else if (f->j_max == k) + ilb = L - f->f_max; + else + ilb = -DBL_MAX; + /* determine implied upper bound of term a[k] * x[k] (15) */ + if (U == +DBL_MAX || f->f_min == -DBL_MAX) + iub = +DBL_MAX; + else if (f->j_min == 0) + { if (a[k] > 0.0) + { xassert(l[k] != -DBL_MAX); + iub = U - (f->f_min - a[k] * l[k]); + } + else if (a[k] < 0.0) + { xassert(u[k] != +DBL_MAX); + iub = U - (f->f_min - a[k] * u[k]); + } + else + xassert(a != a); + } + else if (f->j_min == k) + iub = U - f->f_min; + else + iub = +DBL_MAX; + /* determine implied bounds of x[k] (16) and (17) */ +#if 1 + /* do not use a[k] if it has small magnitude to prevent wrong + implied bounds; for example, 1e-15 * x1 >= x2 + x3, where + x1 >= -10, x2, x3 >= 0, would lead to wrong conclusion that + x1 >= 0 */ + if (fabs(a[k]) < 1e-6) + *ll = -DBL_MAX, *uu = +DBL_MAX; else +#endif + if (a[k] > 0.0) + { *ll = (ilb == -DBL_MAX ? -DBL_MAX : ilb / a[k]); + *uu = (iub == +DBL_MAX ? +DBL_MAX : iub / a[k]); + } + else if (a[k] < 0.0) + { *ll = (iub == +DBL_MAX ? -DBL_MAX : iub / a[k]); + *uu = (ilb == -DBL_MAX ? +DBL_MAX : ilb / a[k]); + } + else + xassert(a != a); + return; +} + +/*********************************************************************** +* check_row_bounds - check and relax original row bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* this routine checks the original row bounds L and U for feasibility +* and redundancy. If the original lower bound L or/and upper bound U +* cannot be active due to bounds of variables, the routine remove them +* replacing by -inf or/and +inf, respectively. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int check_row_bounds(const struct f_info *f, double *L_, + double *U_) +{ int ret = 0; + double L = *L_, U = *U_, LL, UU; + /* determine implied bounds of the row */ + row_implied_bounds(f, &LL, &UU); + /* check if the original lower bound is infeasible */ + if (L != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(L)); + if (UU < L - eps) + { ret = 1; + goto done; + } + } + /* check if the original upper bound is infeasible */ + if (U != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(U)); + if (LL > U + eps) + { ret = 1; + goto done; + } + } + /* check if the original lower bound is redundant */ + if (L != -DBL_MAX) + { double eps = 1e-12 * (1.0 + fabs(L)); + if (LL > L - eps) + { /* it cannot be active, so remove it */ + *L_ = -DBL_MAX; + } + } + /* check if the original upper bound is redundant */ + if (U != +DBL_MAX) + { double eps = 1e-12 * (1.0 + fabs(U)); + if (UU < U + eps) + { /* it cannot be active, so remove it */ + *U_ = +DBL_MAX; + } + } +done: return ret; +} + +/*********************************************************************** +* check_col_bounds - check and tighten original column bounds +* +* Given a row (constraint) +* +* n +* L <= sum a[j] * x[j] <= U +* j=1 +* +* and bounds of columns (variables) +* +* l[j] <= x[j] <= u[j] +* +* for column (variable) x[j] this routine checks the original column +* bounds l[j] and u[j] for feasibility and redundancy. If the original +* lower bound l[j] or/and upper bound u[j] cannot be active due to +* bounds of the constraint and other variables, the routine tighten +* them replacing by corresponding implied bounds, if possible. +* +* NOTE: It is assumed that if L != -inf, the row lower bound can be +* active, and if U != +inf, the row upper bound can be active. +* +* The flag means that variable x[j] is required to be integer. +* +* New actual bounds for x[j] are stored in locations lj and uj. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int check_col_bounds(const struct f_info *f, int n, + const double a[], double L, double U, const double l[], + const double u[], int flag, int j, double *_lj, double *_uj) +{ int ret = 0; + double lj, uj, ll, uu; + xassert(n >= 0); + xassert(1 <= j && j <= n); + lj = l[j], uj = u[j]; + /* determine implied bounds of the column */ + col_implied_bounds(f, n, a, L, U, l, u, j, &ll, &uu); + /* if x[j] is integral, round its implied bounds */ + if (flag) + { if (ll != -DBL_MAX) + ll = (ll - floor(ll) < 1e-3 ? floor(ll) : ceil(ll)); + if (uu != +DBL_MAX) + uu = (ceil(uu) - uu < 1e-3 ? ceil(uu) : floor(uu)); + } + /* check if the original lower bound is infeasible */ + if (lj != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(lj)); + if (uu < lj - eps) + { ret = 1; + goto done; + } + } + /* check if the original upper bound is infeasible */ + if (uj != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(uj)); + if (ll > uj + eps) + { ret = 1; + goto done; + } + } + /* check if the original lower bound is redundant */ + if (ll != -DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(ll)); + if (lj < ll - eps) + { /* it cannot be active, so tighten it */ + lj = ll; + } + } + /* check if the original upper bound is redundant */ + if (uu != +DBL_MAX) + { double eps = 1e-3 * (1.0 + fabs(uu)); + if (uj > uu + eps) + { /* it cannot be active, so tighten it */ + uj = uu; + } + } + /* due to round-off errors it may happen that lj > uj (although + lj < uj + eps, since no primal infeasibility is detected), so + adjuct the new actual bounds to provide lj <= uj */ + if (!(lj == -DBL_MAX || uj == +DBL_MAX)) + { double t1 = fabs(lj), t2 = fabs(uj); + double eps = 1e-10 * (1.0 + (t1 <= t2 ? t1 : t2)); + if (lj > uj - eps) + { if (lj == l[j]) + uj = lj; + else if (uj == u[j]) + lj = uj; + else if (t1 <= t2) + uj = lj; + else + lj = uj; + } + } + *_lj = lj, *_uj = uj; +done: return ret; +} + +/*********************************************************************** +* check_efficiency - check if change in column bounds is efficient +* +* Given the original bounds of a column l and u and its new actual +* bounds l' and u' (possibly tighten by the routine check_col_bounds) +* this routine checks if the change in the column bounds is efficient +* enough. If so, the routine returns non-zero, otherwise zero. +* +* The flag means that the variable is required to be integer. */ + +static int check_efficiency(int flag, double l, double u, double ll, + double uu) +{ int eff = 0; + /* check efficiency for lower bound */ + if (l < ll) + { if (flag || l == -DBL_MAX) + eff++; + else + { double r; + if (u == +DBL_MAX) + r = 1.0 + fabs(l); + else + r = 1.0 + (u - l); + if (ll - l >= 0.25 * r) + eff++; + } + } + /* check efficiency for upper bound */ + if (u > uu) + { if (flag || u == +DBL_MAX) + eff++; + else + { double r; + if (l == -DBL_MAX) + r = 1.0 + fabs(u); + else + r = 1.0 + (u - l); + if (u - uu >= 0.25 * r) + eff++; + } + } + return eff; +} + +/*********************************************************************** +* basic_preprocessing - perform basic preprocessing +* +* This routine performs basic preprocessing of the specified MIP that +* includes relaxing some row bounds and tightening some column bounds. +* +* On entry the arrays L and U contains original row bounds, and the +* arrays l and u contains original column bounds: +* +* L[0] is the lower bound of the objective row; +* L[i], i = 1,...,m, is the lower bound of i-th row; +* U[0] is the upper bound of the objective row; +* U[i], i = 1,...,m, is the upper bound of i-th row; +* l[0] is not used; +* l[j], j = 1,...,n, is the lower bound of j-th column; +* u[0] is not used; +* u[j], j = 1,...,n, is the upper bound of j-th column. +* +* On exit the arrays L, U, l, and u contain new actual bounds of rows +* and column in the same locations. +* +* The parameters nrs and num specify an initial list of rows to be +* processed: +* +* nrs is the number of rows in the initial list, 0 <= nrs <= m+1; +* num[0] is not used; +* num[1,...,nrs] are row numbers (0 means the objective row). +* +* The parameter max_pass specifies the maximal number of times that +* each row can be processed, max_pass > 0. +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +static int basic_preprocessing(glp_prob *mip, double L[], double U[], + double l[], double u[], int nrs, const int num[], int max_pass) +{ int m = mip->m; + int n = mip->n; + struct f_info f; + int i, j, k, len, size, ret = 0; + int *ind, *list, *mark, *pass; + double *val, *lb, *ub; + xassert(0 <= nrs && nrs <= m+1); + xassert(max_pass > 0); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + list = xcalloc(1+m+1, sizeof(int)); + mark = xcalloc(1+m+1, sizeof(int)); + memset(&mark[0], 0, (m+1) * sizeof(int)); + pass = xcalloc(1+m+1, sizeof(int)); + memset(&pass[0], 0, (m+1) * sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + lb = xcalloc(1+n, sizeof(double)); + ub = xcalloc(1+n, sizeof(double)); + /* initialize the list of rows to be processed */ + size = 0; + for (k = 1; k <= nrs; k++) + { i = num[k]; + xassert(0 <= i && i <= m); + /* duplicate row numbers are not allowed */ + xassert(!mark[i]); + list[++size] = i, mark[i] = 1; + } + xassert(size == nrs); + /* process rows in the list until it becomes empty */ + while (size > 0) + { /* get a next row from the list */ + i = list[size--], mark[i] = 0; + /* increase the row processing count */ + pass[i]++; + /* if the row is free, skip it */ + if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; + /* obtain coefficients of the row */ + len = 0; + if (i == 0) + { for (j = 1; j <= n; j++) + { GLPCOL *col = mip->col[j]; + if (col->coef != 0.0) + len++, ind[len] = j, val[len] = col->coef; + } + } + else + { GLPROW *row = mip->row[i]; + GLPAIJ *aij; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + len++, ind[len] = aij->col->j, val[len] = aij->val; + } + /* determine lower and upper bounds of columns corresponding + to non-zero row coefficients */ + for (k = 1; k <= len; k++) + j = ind[k], lb[k] = l[j], ub[k] = u[j]; + /* prepare the row info to determine implied bounds */ + prepare_row_info(len, val, lb, ub, &f); + /* check and relax bounds of the row */ + if (check_row_bounds(&f, &L[i], &U[i])) + { /* the feasible region is empty */ + ret = 1; + goto done; + } + /* if the row became free, drop it */ + if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; + /* process columns having non-zero coefficients in the row */ + for (k = 1; k <= len; k++) + { GLPCOL *col; + int flag, eff; + double ll, uu; + /* take a next column in the row */ + j = ind[k], col = mip->col[j]; + flag = col->kind != GLP_CV; + /* check and tighten bounds of the column */ + if (check_col_bounds(&f, len, val, L[i], U[i], lb, ub, + flag, k, &ll, &uu)) + { /* the feasible region is empty */ + ret = 1; + goto done; + } + /* check if change in the column bounds is efficient */ + eff = check_efficiency(flag, l[j], u[j], ll, uu); + /* set new actual bounds of the column */ + l[j] = ll, u[j] = uu; + /* if the change is efficient, add all rows affected by the + corresponding column, to the list */ + if (eff > 0) + { GLPAIJ *aij; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { int ii = aij->row->i; + /* if the row was processed maximal number of times, + skip it */ + if (pass[ii] >= max_pass) continue; + /* if the row is free, skip it */ + if (L[ii] == -DBL_MAX && U[ii] == +DBL_MAX) continue; + /* put the row into the list */ + if (mark[ii] == 0) + { xassert(size <= m); + list[++size] = ii, mark[ii] = 1; + } + } + } + } + } +done: /* free working arrays */ + xfree(ind); + xfree(list); + xfree(mark); + xfree(pass); + xfree(val); + xfree(lb); + xfree(ub); + return ret; +} + +/*********************************************************************** +* NAME +* +* ios_preprocess_node - preprocess current subproblem +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_preprocess_node(glp_tree *tree, int max_pass); +* +* DESCRIPTION +* +* The routine ios_preprocess_node performs basic preprocessing of the +* current subproblem. +* +* RETURNS +* +* If no primal infeasibility is detected, the routine returns zero, +* otherwise non-zero. */ + +int ios_preprocess_node(glp_tree *tree, int max_pass) +{ glp_prob *mip = tree->mip; + int m = mip->m; + int n = mip->n; + int i, j, nrs, *num, ret = 0; + double *L, *U, *l, *u; + /* the current subproblem must exist */ + xassert(tree->curr != NULL); + /* determine original row bounds */ + L = xcalloc(1+m, sizeof(double)); + U = xcalloc(1+m, sizeof(double)); + switch (mip->mip_stat) + { case GLP_UNDEF: + L[0] = -DBL_MAX, U[0] = +DBL_MAX; + break; + case GLP_FEAS: + switch (mip->dir) + { case GLP_MIN: + L[0] = -DBL_MAX, U[0] = mip->mip_obj - mip->c0; + break; + case GLP_MAX: + L[0] = mip->mip_obj - mip->c0, U[0] = +DBL_MAX; + break; + default: + xassert(mip != mip); + } + break; + default: + xassert(mip != mip); + } + for (i = 1; i <= m; i++) + { L[i] = glp_get_row_lb(mip, i); + U[i] = glp_get_row_ub(mip, i); + } + /* determine original column bounds */ + l = xcalloc(1+n, sizeof(double)); + u = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { l[j] = glp_get_col_lb(mip, j); + u[j] = glp_get_col_ub(mip, j); + } + /* build the initial list of rows to be analyzed */ + nrs = m + 1; + num = xcalloc(1+nrs, sizeof(int)); + for (i = 1; i <= nrs; i++) num[i] = i - 1; + /* perform basic preprocessing */ + if (basic_preprocessing(mip , L, U, l, u, nrs, num, max_pass)) + { ret = 1; + goto done; + } + /* set new actual (relaxed) row bounds */ + for (i = 1; i <= m; i++) + { /* consider only non-active rows to keep dual feasibility */ + if (glp_get_row_stat(mip, i) == GLP_BS) + { if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) + glp_set_row_bnds(mip, i, GLP_FR, 0.0, 0.0); + else if (U[i] == +DBL_MAX) + glp_set_row_bnds(mip, i, GLP_LO, L[i], 0.0); + else if (L[i] == -DBL_MAX) + glp_set_row_bnds(mip, i, GLP_UP, 0.0, U[i]); + } + } + /* set new actual (tightened) column bounds */ + for (j = 1; j <= n; j++) + { int type; + if (l[j] == -DBL_MAX && u[j] == +DBL_MAX) + type = GLP_FR; + else if (u[j] == +DBL_MAX) + type = GLP_LO; + else if (l[j] == -DBL_MAX) + type = GLP_UP; + else if (l[j] != u[j]) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(mip, j, type, l[j], u[j]); + } +done: /* free working arrays and return */ + xfree(L); + xfree(U); + xfree(l); + xfree(u); + xfree(num); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios03.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios03.c new file mode 100644 index 000000000..21d6a0007 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios03.c @@ -0,0 +1,1512 @@ +/* glpios03.c (branch-and-cut driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* show_progress - display current progress of the search +* +* This routine displays some information about current progress of the +* search. +* +* The information includes: +* +* the current number of iterations performed by the simplex solver; +* +* the objective value for the best known integer feasible solution, +* which is upper (minimization) or lower (maximization) global bound +* for optimal solution of the original mip problem; +* +* the best local bound for active nodes, which is lower (minimization) +* or upper (maximization) global bound for optimal solution of the +* original mip problem; +* +* the relative mip gap, in percents; +* +* the number of open (active) subproblems; +* +* the number of completely explored subproblems, i.e. whose nodes have +* been removed from the tree. */ + +static void show_progress(glp_tree *T, int bingo) +{ int p; + double temp; + char best_mip[50], best_bound[50], *rho, rel_gap[50]; + /* format the best known integer feasible solution */ + if (T->mip->mip_stat == GLP_FEAS) + sprintf(best_mip, "%17.9e", T->mip->mip_obj); + else + sprintf(best_mip, "%17s", "not found yet"); + /* determine reference number of an active subproblem whose local + bound is best */ + p = ios_best_node(T); + /* format the best bound */ + if (p == 0) + sprintf(best_bound, "%17s", "tree is empty"); + else + { temp = T->slot[p].node->bound; + if (temp == -DBL_MAX) + sprintf(best_bound, "%17s", "-inf"); + else if (temp == +DBL_MAX) + sprintf(best_bound, "%17s", "+inf"); + else + { if (fabs(temp) < 1e-9) + temp = 0; + sprintf(best_bound, "%17.9e", temp); + } + } + /* choose the relation sign between global bounds */ + if (T->mip->dir == GLP_MIN) + rho = ">="; + else if (T->mip->dir == GLP_MAX) + rho = "<="; + else + xassert(T != T); + /* format the relative mip gap */ + temp = ios_relative_gap(T); + if (temp == 0.0) + sprintf(rel_gap, " 0.0%%"); + else if (temp < 0.001) + sprintf(rel_gap, "< 0.1%%"); + else if (temp <= 9.999) + sprintf(rel_gap, "%5.1f%%", 100.0 * temp); + else + sprintf(rel_gap, "%6s", ""); + /* display progress of the search */ + xprintf("+%6d: %s %s %s %s %s (%d; %d)\n", + T->mip->it_cnt, bingo ? ">>>>>" : "mip =", best_mip, rho, + best_bound, rel_gap, T->a_cnt, T->t_cnt - T->n_cnt); + T->tm_lag = xtime(); + return; +} + +/*********************************************************************** +* is_branch_hopeful - check if specified branch is hopeful +* +* This routine checks if the specified subproblem can have an integer +* optimal solution which is better than the best known one. +* +* The check is based on comparison of the local objective bound stored +* in the subproblem descriptor and the incumbent objective value which +* is the global objective bound. +* +* If there is a chance that the specified subproblem can have a better +* integer optimal solution, the routine returns non-zero. Otherwise, if +* the corresponding branch can pruned, zero is returned. */ + +static int is_branch_hopeful(glp_tree *T, int p) +{ xassert(1 <= p && p <= T->nslots); + xassert(T->slot[p].node != NULL); + return ios_is_hopeful(T, T->slot[p].node->bound); +} + +/*********************************************************************** +* check_integrality - check integrality of basic solution +* +* This routine checks if the basic solution of LP relaxation of the +* current subproblem satisfies to integrality conditions, i.e. that all +* variables of integer kind have integral primal values. (The solution +* is assumed to be optimal.) +* +* For each variable of integer kind the routine computes the following +* quantity: +* +* ii(x[j]) = min(x[j] - floor(x[j]), ceil(x[j]) - x[j]), (1) +* +* which is a measure of the integer infeasibility (non-integrality) of +* x[j] (for example, ii(2.1) = 0.1, ii(3.7) = 0.3, ii(5.0) = 0). It is +* understood that 0 <= ii(x[j]) <= 0.5, and variable x[j] is integer +* feasible if ii(x[j]) = 0. However, due to floating-point arithmetic +* the routine checks less restrictive condition: +* +* ii(x[j]) <= tol_int, (2) +* +* where tol_int is a given tolerance (small positive number) and marks +* each variable which does not satisfy to (2) as integer infeasible by +* setting its fractionality flag. +* +* In order to characterize integer infeasibility of the basic solution +* in the whole the routine computes two parameters: ii_cnt, which is +* the number of variables with the fractionality flag set, and ii_sum, +* which is the sum of integer infeasibilities (1). */ + +static void check_integrality(glp_tree *T) +{ glp_prob *mip = T->mip; + int j, type, ii_cnt = 0; + double lb, ub, x, temp1, temp2, ii_sum = 0.0; + /* walk through the set of columns (structural variables) */ + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + T->non_int[j] = 0; + /* if the column is not integer, skip it */ + if (col->kind != GLP_IV) continue; + /* if the column is non-basic, it is integer feasible */ + if (col->stat != GLP_BS) continue; + /* obtain the type and bounds of the column */ + type = col->type, lb = col->lb, ub = col->ub; + /* obtain value of the column in optimal basic solution */ + x = col->prim; + /* if the column's primal value is close to the lower bound, + the column is integer feasible within given tolerance */ + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { temp1 = lb - T->parm->tol_int; + temp2 = lb + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; +#if 0 + /* the lower bound must not be violated */ + xassert(x >= lb); +#else + if (x < lb) continue; +#endif + } + /* if the column's primal value is close to the upper bound, + the column is integer feasible within given tolerance */ + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { temp1 = ub - T->parm->tol_int; + temp2 = ub + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; +#if 0 + /* the upper bound must not be violated */ + xassert(x <= ub); +#else + if (x > ub) continue; +#endif + } + /* if the column's primal value is close to nearest integer, + the column is integer feasible within given tolerance */ + temp1 = floor(x + 0.5) - T->parm->tol_int; + temp2 = floor(x + 0.5) + T->parm->tol_int; + if (temp1 <= x && x <= temp2) continue; + /* otherwise the column is integer infeasible */ + T->non_int[j] = 1; + /* increase the number of fractional-valued columns */ + ii_cnt++; + /* compute the sum of integer infeasibilities */ + temp1 = x - floor(x); + temp2 = ceil(x) - x; + xassert(temp1 > 0.0 && temp2 > 0.0); + ii_sum += (temp1 <= temp2 ? temp1 : temp2); + } + /* store ii_cnt and ii_sum to the current problem descriptor */ + xassert(T->curr != NULL); + T->curr->ii_cnt = ii_cnt; + T->curr->ii_sum = ii_sum; + /* and also display these parameters */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (ii_cnt == 0) + xprintf("There are no fractional columns\n"); + else if (ii_cnt == 1) + xprintf("There is one fractional column, integer infeasibil" + "ity is %.3e\n", ii_sum); + else + xprintf("There are %d fractional columns, integer infeasibi" + "lity is %.3e\n", ii_cnt, ii_sum); + } + return; +} + +/*********************************************************************** +* record_solution - record better integer feasible solution +* +* This routine records optimal basic solution of LP relaxation of the +* current subproblem, which being integer feasible is better than the +* best known integer feasible solution. */ + +static void record_solution(glp_tree *T) +{ glp_prob *mip = T->mip; + int i, j; + mip->mip_stat = GLP_FEAS; + mip->mip_obj = mip->obj_val; + for (i = 1; i <= mip->m; i++) + { GLPROW *row = mip->row[i]; + row->mipx = row->prim; + } + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + if (col->kind == GLP_CV) + col->mipx = col->prim; + else if (col->kind == GLP_IV) + { /* value of the integer column must be integral */ + col->mipx = floor(col->prim + 0.5); + } + else + xassert(col != col); + } + T->sol_cnt++; + return; +} + +/*********************************************************************** +* fix_by_red_cost - fix non-basic integer columns by reduced costs +* +* This routine fixes some non-basic integer columns if their reduced +* costs indicate that increasing (decreasing) the column at least by +* one involves the objective value becoming worse than the incumbent +* objective value. */ + +static void fix_by_red_cost(glp_tree *T) +{ glp_prob *mip = T->mip; + int j, stat, fixed = 0; + double obj, lb, ub, dj; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* basic solution of LP relaxation must be optimal */ + xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); + /* determine the objective function value */ + obj = mip->obj_val; + /* walk through the column list */ + for (j = 1; j <= mip->n; j++) + { GLPCOL *col = mip->col[j]; + /* if the column is not integer, skip it */ + if (col->kind != GLP_IV) continue; + /* obtain bounds of j-th column */ + lb = col->lb, ub = col->ub; + /* and determine its status and reduced cost */ + stat = col->stat, dj = col->dual; + /* analyze the reduced cost */ + switch (mip->dir) + { case GLP_MIN: + /* minimization */ + if (stat == GLP_NL) + { /* j-th column is non-basic on its lower bound */ + if (dj < 0.0) dj = 0.0; + if (obj + dj >= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; + } + else if (stat == GLP_NU) + { /* j-th column is non-basic on its upper bound */ + if (dj > 0.0) dj = 0.0; + if (obj - dj >= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; + } + break; + case GLP_MAX: + /* maximization */ + if (stat == GLP_NL) + { /* j-th column is non-basic on its lower bound */ + if (dj > 0.0) dj = 0.0; + if (obj + dj <= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; + } + else if (stat == GLP_NU) + { /* j-th column is non-basic on its upper bound */ + if (dj < 0.0) dj = 0.0; + if (obj - dj <= mip->mip_obj) + glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; + } + break; + default: + xassert(T != T); + } + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (fixed == 0) + /* nothing to say */; + else if (fixed == 1) + xprintf("One column has been fixed by reduced cost\n"); + else + xprintf("%d columns have been fixed by reduced costs\n", + fixed); + } + /* fixing non-basic columns on their current bounds does not + change the basic solution */ + xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); + return; +} + +/*********************************************************************** +* branch_on - perform branching on specified variable +* +* This routine performs branching on j-th column (structural variable) +* of the current subproblem. The specified column must be of integer +* kind and must have a fractional value in optimal basic solution of +* LP relaxation of the current subproblem (i.e. only columns for which +* the flag non_int[j] is set are valid candidates to branch on). +* +* Let x be j-th structural variable, and beta be its primal fractional +* value in the current basic solution. Branching on j-th variable is +* dividing the current subproblem into two new subproblems, which are +* identical to the current subproblem with the following exception: in +* the first subproblem that begins the down-branch x has a new upper +* bound x <= floor(beta), and in the second subproblem that begins the +* up-branch x has a new lower bound x >= ceil(beta). +* +* Depending on estimation of local bounds for down- and up-branches +* this routine returns the following: +* +* 0 - both branches have been created; +* 1 - one branch is hopeless and has been pruned, so now the current +* subproblem is other branch; +* 2 - both branches are hopeless and have been pruned; new subproblem +* selection is needed to continue the search. */ + +static int branch_on(glp_tree *T, int j, int next) +{ glp_prob *mip = T->mip; + IOSNPD *node; + int m = mip->m; + int n = mip->n; + int type, dn_type, up_type, dn_bad, up_bad, p, ret, clone[1+2]; + double lb, ub, beta, new_ub, new_lb, dn_lp, up_lp, dn_bnd, up_bnd; + /* determine bounds and value of x[j] in optimal solution to LP + relaxation of the current subproblem */ + xassert(1 <= j && j <= n); + type = mip->col[j]->type; + lb = mip->col[j]->lb; + ub = mip->col[j]->ub; + beta = mip->col[j]->prim; + /* determine new bounds of x[j] for down- and up-branches */ + new_ub = floor(beta); + new_lb = ceil(beta); + switch (type) + { case GLP_FR: + dn_type = GLP_UP; + up_type = GLP_LO; + break; + case GLP_LO: + xassert(lb <= new_ub); + dn_type = (lb == new_ub ? GLP_FX : GLP_DB); + xassert(lb + 1.0 <= new_lb); + up_type = GLP_LO; + break; + case GLP_UP: + xassert(new_ub <= ub - 1.0); + dn_type = GLP_UP; + xassert(new_lb <= ub); + up_type = (new_lb == ub ? GLP_FX : GLP_DB); + break; + case GLP_DB: + xassert(lb <= new_ub && new_ub <= ub - 1.0); + dn_type = (lb == new_ub ? GLP_FX : GLP_DB); + xassert(lb + 1.0 <= new_lb && new_lb <= ub); + up_type = (new_lb == ub ? GLP_FX : GLP_DB); + break; + default: + xassert(type != type); + } + /* compute local bounds to LP relaxation for both branches */ + ios_eval_degrad(T, j, &dn_lp, &up_lp); + /* and improve them by rounding */ + dn_bnd = ios_round_bound(T, dn_lp); + up_bnd = ios_round_bound(T, up_lp); + /* check local bounds for down- and up-branches */ + dn_bad = !ios_is_hopeful(T, dn_bnd); + up_bad = !ios_is_hopeful(T, up_bnd); + if (dn_bad && up_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Both down- and up-branches are hopeless\n"); + ret = 2; + goto done; + } + else if (up_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Up-branch is hopeless\n"); + glp_set_col_bnds(mip, j, dn_type, lb, new_ub); + T->curr->lp_obj = dn_lp; + if (mip->dir == GLP_MIN) + { if (T->curr->bound < dn_bnd) + T->curr->bound = dn_bnd; + } + else if (mip->dir == GLP_MAX) + { if (T->curr->bound > dn_bnd) + T->curr->bound = dn_bnd; + } + else + xassert(mip != mip); + ret = 1; + goto done; + } + else if (dn_bad) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Down-branch is hopeless\n"); + glp_set_col_bnds(mip, j, up_type, new_lb, ub); + T->curr->lp_obj = up_lp; + if (mip->dir == GLP_MIN) + { if (T->curr->bound < up_bnd) + T->curr->bound = up_bnd; + } + else if (mip->dir == GLP_MAX) + { if (T->curr->bound > up_bnd) + T->curr->bound = up_bnd; + } + else + xassert(mip != mip); + ret = 1; + goto done; + } + /* both down- and up-branches seem to be hopeful */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Branching on column %d, primal value is %.9e\n", + j, beta); + /* determine the reference number of the current subproblem */ + xassert(T->curr != NULL); + p = T->curr->p; + T->curr->br_var = j; + T->curr->br_val = beta; + /* freeze the current subproblem */ + ios_freeze_node(T); + /* create two clones of the current subproblem; the first clone + begins the down-branch, the second one begins the up-branch */ + ios_clone_node(T, p, 2, clone); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Node %d begins down branch, node %d begins up branch " + "\n", clone[1], clone[2]); + /* set new upper bound of j-th column in the down-branch */ + node = T->slot[clone[1]].node; + xassert(node != NULL); + xassert(node->up != NULL); + xassert(node->b_ptr == NULL); + node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); + node->b_ptr->k = m + j; + node->b_ptr->type = (unsigned char)dn_type; + node->b_ptr->lb = lb; + node->b_ptr->ub = new_ub; + node->b_ptr->next = NULL; + node->lp_obj = dn_lp; + if (mip->dir == GLP_MIN) + { if (node->bound < dn_bnd) + node->bound = dn_bnd; + } + else if (mip->dir == GLP_MAX) + { if (node->bound > dn_bnd) + node->bound = dn_bnd; + } + else + xassert(mip != mip); + /* set new lower bound of j-th column in the up-branch */ + node = T->slot[clone[2]].node; + xassert(node != NULL); + xassert(node->up != NULL); + xassert(node->b_ptr == NULL); + node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); + node->b_ptr->k = m + j; + node->b_ptr->type = (unsigned char)up_type; + node->b_ptr->lb = new_lb; + node->b_ptr->ub = ub; + node->b_ptr->next = NULL; + node->lp_obj = up_lp; + if (mip->dir == GLP_MIN) + { if (node->bound < up_bnd) + node->bound = up_bnd; + } + else if (mip->dir == GLP_MAX) + { if (node->bound > up_bnd) + node->bound = up_bnd; + } + else + xassert(mip != mip); + /* suggest the subproblem to be solved next */ + xassert(T->child == 0); + if (next == GLP_NO_BRNCH) + T->child = 0; + else if (next == GLP_DN_BRNCH) + T->child = clone[1]; + else if (next == GLP_UP_BRNCH) + T->child = clone[2]; + else + xassert(next != next); + ret = 0; +done: return ret; +} + +/*********************************************************************** +* cleanup_the_tree - prune hopeless branches from the tree +* +* This routine walks through the active list and checks the local +* bound for every active subproblem. If the local bound indicates that +* the subproblem cannot have integer optimal solution better than the +* incumbent objective value, the routine deletes such subproblem that, +* in turn, involves pruning the corresponding branch of the tree. */ + +static void cleanup_the_tree(glp_tree *T) +{ IOSNPD *node, *next_node; + int count = 0; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* walk through the list of active subproblems */ + for (node = T->head; node != NULL; node = next_node) + { /* deleting some active problem node may involve deleting its + parents recursively; however, all its parents being created + *before* it are always *precede* it in the node list, so + the next problem node is never affected by such deletion */ + next_node = node->next; + /* if the branch is hopeless, prune it */ + if (!is_branch_hopeful(T, node->p)) + ios_delete_node(T, node->p), count++; + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + { if (count == 1) + xprintf("One hopeless branch has been pruned\n"); + else if (count > 1) + xprintf("%d hopeless branches have been pruned\n", count); + } + return; +} + +/*********************************************************************** +* round_heur - simple rounding heuristic +* +* This routine attempts to guess an integer feasible solution by +* simple rounding values of all integer variables in basic solution to +* nearest integers. */ + +static int round_heur(glp_tree *T) +{ glp_prob *P = T->mip; + /*int m = P->m;*/ + int n = P->n; + int i, j, ret; + double *x; + /* compute rounded values of variables */ + x = talloc(1+n, double); + for (j = 1; j <= n; j++) + { GLPCOL *col = P->col[j]; + if (col->kind == GLP_IV) + { /* integer variable */ + x[j] = floor(col->prim + 0.5); + } + else if (col->type == GLP_FX) + { /* fixed variable */ + x[j] = col->prim; + } + else + { /* non-integer non-fixed variable */ + ret = 3; + goto done; + } + } + /* check that no constraints are violated */ + for (i = 1; i <= T->orig_m; i++) + { int type = T->orig_type[i]; + GLPAIJ *aij; + double sum; + if (type == GLP_FR) + continue; + /* compute value of linear form */ + sum = 0.0; + for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) + sum += aij->val * x[aij->col->j]; + /* check lower bound */ + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { if (sum < T->orig_lb[i] - 1e-9) + { /* lower bound is violated */ + ret = 2; + goto done; + } + } + /* check upper bound */ + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { if (sum > T->orig_ub[i] + 1e-9) + { /* upper bound is violated */ + ret = 2; + goto done; + } + } + } + /* rounded solution is integer feasible */ + if (glp_ios_heur_sol(T, x) == 0) + { /* solution is accepted */ + ret = 0; + } + else + { /* solution is rejected */ + ret = 1; + } +done: tfree(x); + return ret; +} + +/**********************************************************************/ + +#if 1 /* 08/III-2016 */ +static void gmi_gen(glp_tree *T) +{ /* generate Gomory's mixed integer cuts */ + glp_prob *P, *pool; + P = T->mip; + pool = glp_create_prob(); + glp_add_cols(pool, P->n); + glp_gmi_gen(P, pool, 50); + if (pool->m > 0) + { int i, len, *ind; + double *val; + ind = xcalloc(1+P->n, sizeof(int)); + val = xcalloc(1+P->n, sizeof(double)); + for (i = 1; i <= pool->m; i++) + { len = glp_get_mat_row(pool, i, ind, val); + glp_ios_add_row(T, NULL, GLP_RF_GMI, 0, len, ind, val, + GLP_LO, pool->row[i]->lb); + } + xfree(ind); + xfree(val); + } + glp_delete_prob(pool); + return; +} +#endif + +#ifdef NEW_COVER /* 13/II-2018 */ +static void cov_gen(glp_tree *T) +{ /* generate cover cuts */ + glp_prob *P, *pool; + if (T->cov_gen == NULL) + return; + P = T->mip; + pool = glp_create_prob(); + glp_add_cols(pool, P->n); + glp_cov_gen1(P, T->cov_gen, pool); + if (pool->m > 0) + { int i, len, *ind; + double *val; + ind = xcalloc(1+P->n, sizeof(int)); + val = xcalloc(1+P->n, sizeof(double)); + for (i = 1; i <= pool->m; i++) + { len = glp_get_mat_row(pool, i, ind, val); + glp_ios_add_row(T, NULL, GLP_RF_COV, 0, len, ind, val, + GLP_UP, pool->row[i]->ub); + } + xfree(ind); + xfree(val); + } + glp_delete_prob(pool); + return; +} +#endif + +#if 1 /* 08/III-2016 */ +static void mir_gen(glp_tree *T) +{ /* generate mixed integer rounding cuts */ + glp_prob *P, *pool; + P = T->mip; + pool = glp_create_prob(); + glp_add_cols(pool, P->n); + glp_mir_gen(P, T->mir_gen, pool); + if (pool->m > 0) + { int i, len, *ind; + double *val; + ind = xcalloc(1+P->n, sizeof(int)); + val = xcalloc(1+P->n, sizeof(double)); + for (i = 1; i <= pool->m; i++) + { len = glp_get_mat_row(pool, i, ind, val); + glp_ios_add_row(T, NULL, GLP_RF_MIR, 0, len, ind, val, + GLP_UP, pool->row[i]->ub); + } + xfree(ind); + xfree(val); + } + glp_delete_prob(pool); + return; +} +#endif + +#if 1 /* 08/III-2016 */ +static void clq_gen(glp_tree *T, glp_cfg *G) +{ /* generate clique cut from conflict graph */ + glp_prob *P = T->mip; + int n = P->n; + int len, *ind; + double *val; + ind = talloc(1+n, int); + val = talloc(1+n, double); + len = glp_clq_cut(T->mip, G, ind, val); + if (len > 0) + glp_ios_add_row(T, NULL, GLP_RF_CLQ, 0, len, ind, val, GLP_UP, + val[0]); + tfree(ind); + tfree(val); + return; +} +#endif + +static void generate_cuts(glp_tree *T) +{ /* generate generic cuts with built-in generators */ + if (!(T->parm->mir_cuts == GLP_ON || + T->parm->gmi_cuts == GLP_ON || + T->parm->cov_cuts == GLP_ON || + T->parm->clq_cuts == GLP_ON)) goto done; +#if 1 /* 20/IX-2008 */ + { int i, max_cuts, added_cuts; + max_cuts = T->n; + if (max_cuts < 1000) max_cuts = 1000; + added_cuts = 0; + for (i = T->orig_m+1; i <= T->mip->m; i++) + { if (T->mip->row[i]->origin == GLP_RF_CUT) + added_cuts++; + } + /* xprintf("added_cuts = %d\n", added_cuts); */ + if (added_cuts >= max_cuts) goto done; + } +#endif + /* generate and add to POOL all cuts violated by x* */ + if (T->parm->gmi_cuts == GLP_ON) + { if (T->curr->changed < 7) +#if 0 /* 08/III-2016 */ + ios_gmi_gen(T); +#else + gmi_gen(T); +#endif + } + if (T->parm->mir_cuts == GLP_ON) + { xassert(T->mir_gen != NULL); +#if 0 /* 08/III-2016 */ + ios_mir_gen(T, T->mir_gen); +#else + mir_gen(T); +#endif + } + if (T->parm->cov_cuts == GLP_ON) + { /* cover cuts works well along with mir cuts */ +#ifdef NEW_COVER /* 13/II-2018 */ + cov_gen(T); +#else + ios_cov_gen(T); +#endif + } + if (T->parm->clq_cuts == GLP_ON) + { if (T->clq_gen != NULL) +#if 0 /* 29/VI-2013 */ + { if (T->curr->level == 0 && T->curr->changed < 50 || + T->curr->level > 0 && T->curr->changed < 5) +#else /* FIXME */ + { if (T->curr->level == 0 && T->curr->changed < 500 || + T->curr->level > 0 && T->curr->changed < 50) +#endif +#if 0 /* 08/III-2016 */ + ios_clq_gen(T, T->clq_gen); +#else + clq_gen(T, T->clq_gen); +#endif + } + } +done: return; +} + +/**********************************************************************/ + +static void remove_cuts(glp_tree *T) +{ /* remove inactive cuts (some valueable globally valid cut might + be saved in the global cut pool) */ + int i, cnt = 0, *num = NULL; + xassert(T->curr != NULL); + for (i = T->orig_m+1; i <= T->mip->m; i++) + { if (T->mip->row[i]->origin == GLP_RF_CUT && + T->mip->row[i]->level == T->curr->level && + T->mip->row[i]->stat == GLP_BS) + { if (num == NULL) + num = xcalloc(1+T->mip->m, sizeof(int)); + num[++cnt] = i; + } + } + if (cnt > 0) + { glp_del_rows(T->mip, cnt, num); +#if 0 + xprintf("%d inactive cut(s) removed\n", cnt); +#endif + xfree(num); + xassert(glp_factorize(T->mip) == 0); + } + return; +} + +/**********************************************************************/ + +static void display_cut_info(glp_tree *T) +{ glp_prob *mip = T->mip; + int i, gmi = 0, mir = 0, cov = 0, clq = 0, app = 0; + for (i = mip->m; i > 0; i--) + { GLPROW *row; + row = mip->row[i]; + /* if (row->level < T->curr->level) break; */ + if (row->origin == GLP_RF_CUT) + { if (row->klass == GLP_RF_GMI) + gmi++; + else if (row->klass == GLP_RF_MIR) + mir++; + else if (row->klass == GLP_RF_COV) + cov++; + else if (row->klass == GLP_RF_CLQ) + clq++; + else + app++; + } + } + xassert(T->curr != NULL); + if (gmi + mir + cov + clq + app > 0) + { xprintf("Cuts on level %d:", T->curr->level); + if (gmi > 0) xprintf(" gmi = %d;", gmi); + if (mir > 0) xprintf(" mir = %d;", mir); + if (cov > 0) xprintf(" cov = %d;", cov); + if (clq > 0) xprintf(" clq = %d;", clq); + if (app > 0) xprintf(" app = %d;", app); + xprintf("\n"); + } + return; +} + +/*********************************************************************** +* NAME +* +* ios_driver - branch-and-cut driver +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_driver(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_driver is a branch-and-cut driver. It controls the +* MIP solution process. +* +* RETURNS +* +* 0 The MIP problem instance has been successfully solved. This code +* does not necessarily mean that the solver has found optimal +* solution. It only means that the solution process was successful. +* +* GLP_EFAIL +* The search was prematurely terminated due to the solver failure. +* +* GLP_EMIPGAP +* The search was prematurely terminated, because the relative mip +* gap tolerance has been reached. +* +* GLP_ETMLIM +* The search was prematurely terminated, because the time limit has +* been exceeded. +* +* GLP_ESTOP +* The search was prematurely terminated by application. */ + +int ios_driver(glp_tree *T) +{ int p, curr_p, p_stat, d_stat, ret; +#if 1 /* carry out to glp_tree */ + int pred_p = 0; + /* if the current subproblem has been just created due to + branching, pred_p is the reference number of its parent + subproblem, otherwise pred_p is zero */ +#endif +#if 1 /* 18/VII-2013 */ + int bad_cut; + double old_obj; +#endif +#if 0 /* 10/VI-2013 */ + glp_long ttt = T->tm_beg; +#else + double ttt = T->tm_beg; +#endif +#if 1 /* 27/II-2016 by Chris */ + int root_done = 0; +#endif +#if 0 + ((glp_iocp *)T->parm)->msg_lev = GLP_MSG_DBG; +#endif +#if 1 /* 16/III-2016 */ + if (((glp_iocp *)T->parm)->flip) +#if 0 /* 20/I-2018 */ + xprintf("WARNING: LONG-STEP DUAL SIMPLEX WILL BE USED\n"); +#else + xprintf("Long-step dual simplex will be used\n"); +#endif +#endif + /* on entry to the B&B driver it is assumed that the active list + contains the only active (i.e. root) subproblem, which is the + original MIP problem to be solved */ +loop: /* main loop starts here */ + /* at this point the current subproblem does not exist */ + xassert(T->curr == NULL); + /* if the active list is empty, the search is finished */ + if (T->head == NULL) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Active list is empty!\n"); +#if 0 /* 10/VI-2013 */ + xassert(dmp_in_use(T->pool).lo == 0); +#else + xassert(dmp_in_use(T->pool) == 0); +#endif + ret = 0; + goto done; + } + /* select some active subproblem to continue the search */ + xassert(T->next_p == 0); + /* let the application program select subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_ISELECT; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + if (T->next_p != 0) + { /* the application program has selected something */ + ; + } + else if (T->a_cnt == 1) + { /* the only active subproblem exists, so select it */ + xassert(T->head->next == NULL); + T->next_p = T->head->p; + } + else if (T->child != 0) + { /* select one of branching childs suggested by the branching + heuristic */ + T->next_p = T->child; + } + else + { /* select active subproblem as specified by the backtracking + technique option */ + T->next_p = ios_choose_node(T); + } + /* the active subproblem just selected becomes current */ + ios_revive_node(T, T->next_p); + T->next_p = T->child = 0; + /* invalidate pred_p, if it is not the reference number of the + parent of the current subproblem */ + if (T->curr->up != NULL && T->curr->up->p != pred_p) pred_p = 0; + /* determine the reference number of the current subproblem */ + p = T->curr->p; + if (T->parm->msg_lev >= GLP_MSG_DBG) + { xprintf("-----------------------------------------------------" + "-------------------\n"); + xprintf("Processing node %d at level %d\n", p, T->curr->level); + } +#if 0 + if (p == 1) + glp_write_lp(T->mip, NULL, "root.lp"); +#endif +#if 1 /* 24/X-2015 */ + if (p == 1) + { if (T->parm->sr_heur == GLP_OFF) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Simple rounding heuristic disabled\n"); + } + } +#endif + /* if it is the root subproblem, initialize cut generators */ + if (p == 1) + { if (T->parm->gmi_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Gomory's cuts enabled\n"); + } + if (T->parm->mir_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("MIR cuts enabled\n"); + xassert(T->mir_gen == NULL); +#if 0 /* 06/III-2016 */ + T->mir_gen = ios_mir_init(T); +#else + T->mir_gen = glp_mir_init(T->mip); +#endif + } + if (T->parm->cov_cuts == GLP_ON) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Cover cuts enabled\n"); +#ifdef NEW_COVER /* 13/II-2018 */ + xassert(T->cov_gen == NULL); + T->cov_gen = glp_cov_init(T->mip); +#endif + } + if (T->parm->clq_cuts == GLP_ON) + { xassert(T->clq_gen == NULL); + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Clique cuts enabled\n"); +#if 0 /* 08/III-2016 */ + T->clq_gen = ios_clq_init(T); +#else + T->clq_gen = glp_cfg_init(T->mip); +#endif + } + } +#if 1 /* 18/VII-2013 */ + bad_cut = 0; +#endif +more: /* minor loop starts here */ + /* at this point the current subproblem needs either to be solved + for the first time or re-optimized due to reformulation */ + /* display current progress of the search */ + if (T->parm->msg_lev >= GLP_MSG_DBG || + T->parm->msg_lev >= GLP_MSG_ON && + (double)(T->parm->out_frq - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_lag)) + show_progress(T, 0); + if (T->parm->msg_lev >= GLP_MSG_ALL && + xdifftime(xtime(), ttt) >= 60.0) +#if 0 /* 16/II-2012 */ + { glp_long total; + glp_mem_usage(NULL, NULL, &total, NULL); + xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", + xdifftime(xtime(), T->tm_beg), xltod(total) / 1048576.0); + ttt = xtime(); + } +#else + { size_t total; + glp_mem_usage(NULL, NULL, &total, NULL); + xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", + xdifftime(xtime(), T->tm_beg), (double)total / 1048576.0); + ttt = xtime(); + } +#endif + /* check the mip gap */ + if (T->parm->mip_gap > 0.0 && + ios_relative_gap(T) <= T->parm->mip_gap) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Relative gap tolerance reached; search terminated " + "\n"); + ret = GLP_EMIPGAP; + goto done; + } + /* check if the time limit has been exhausted */ + if (T->parm->tm_lim < INT_MAX && + (double)(T->parm->tm_lim - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_beg)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Time limit exhausted; search terminated\n"); + ret = GLP_ETMLIM; + goto done; + } + /* let the application program preprocess the subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IPREPRO; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* perform basic preprocessing */ + if (T->parm->pp_tech == GLP_PP_NONE) + ; + else if (T->parm->pp_tech == GLP_PP_ROOT) +#if 0 /* 27/II-2016 by Chris */ + { if (T->curr->level == 0) +#else + { if (!root_done) +#endif + { if (ios_preprocess_node(T, 100)) + goto fath; + } + } + else if (T->parm->pp_tech == GLP_PP_ALL) +#if 0 /* 27/II-2016 by Chris */ + { if (ios_preprocess_node(T, T->curr->level == 0 ? 100 : 10)) +#else + { if (ios_preprocess_node(T, !root_done ? 100 : 10)) +#endif + goto fath; + } + else + xassert(T != T); + /* preprocessing may improve the global bound */ + if (!is_branch_hopeful(T, p)) + { xprintf("*** not tested yet ***\n"); + goto fath; + } + /* solve LP relaxation of the current subproblem */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Solving LP relaxation...\n"); + ret = ios_solve_node(T); + if (ret == GLP_ETMLIM) + goto done; + else if (!(ret == 0 || ret == GLP_EOBJLL || ret == GLP_EOBJUL)) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("ios_driver: unable to solve current LP relaxation;" + " glp_simplex returned %d\n", ret); + ret = GLP_EFAIL; + goto done; + } + /* analyze status of the basic solution to LP relaxation found */ + p_stat = T->mip->pbs_stat; + d_stat = T->mip->dbs_stat; + if (p_stat == GLP_FEAS && d_stat == GLP_FEAS) + { /* LP relaxation has optimal solution */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Found optimal solution to LP relaxation\n"); + } + else if (d_stat == GLP_NOFEAS) + { /* LP relaxation has no dual feasible solution */ + /* since the current subproblem cannot have a larger feasible + region than its parent, there is something wrong */ + if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("ios_driver: current LP relaxation has no dual feas" + "ible solution\n"); + ret = GLP_EFAIL; + goto done; + } + else if (p_stat == GLP_INFEAS && d_stat == GLP_FEAS) + { /* LP relaxation has no primal solution which is better than + the incumbent objective value */ + xassert(T->mip->mip_stat == GLP_FEAS); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("LP relaxation has no solution better than incumben" + "t objective value\n"); + /* prune the branch */ + goto fath; + } + else if (p_stat == GLP_NOFEAS) + { /* LP relaxation has no primal feasible solution */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("LP relaxation has no feasible solution\n"); + /* prune the branch */ + goto fath; + } + else + { /* other cases cannot appear */ + xassert(T->mip != T->mip); + } + /* at this point basic solution to LP relaxation of the current + subproblem is optimal */ + xassert(p_stat == GLP_FEAS && d_stat == GLP_FEAS); + xassert(T->curr != NULL); + T->curr->lp_obj = T->mip->obj_val; + /* thus, it defines a local bound to integer optimal solution of + the current subproblem */ + { double bound = T->mip->obj_val; + /* some local bound to the current subproblem could be already + set before, so we should only improve it */ + bound = ios_round_bound(T, bound); + if (T->mip->dir == GLP_MIN) + { if (T->curr->bound < bound) + T->curr->bound = bound; + } + else if (T->mip->dir == GLP_MAX) + { if (T->curr->bound > bound) + T->curr->bound = bound; + } + else + xassert(T->mip != T->mip); + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Local bound is %.9e\n", bound); + } + /* if the local bound indicates that integer optimal solution of + the current subproblem cannot be better than the global bound, + prune the branch */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch is hopeless and can be pruned\n"); + goto fath; + } + /* let the application program generate additional rows ("lazy" + constraints) */ + xassert(T->reopt == 0); + xassert(T->reinv == 0); + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IROWGEN; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + if (T->reopt) + { /* some rows were added; re-optimization is needed */ + T->reopt = T->reinv = 0; + goto more; + } + if (T->reinv) + { /* no rows were added, however, some inactive rows were + removed */ + T->reinv = 0; + xassert(glp_factorize(T->mip) == 0); + } + } + /* check if the basic solution is integer feasible */ + check_integrality(T); + /* if the basic solution satisfies to all integrality conditions, + it is a new, better integer feasible solution */ + if (T->curr->ii_cnt == 0) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("New integer feasible solution found\n"); + if (T->parm->msg_lev >= GLP_MSG_ALL) + display_cut_info(T); + record_solution(T); + if (T->parm->msg_lev >= GLP_MSG_ON) + show_progress(T, 1); +#if 1 /* 11/VII-2013 */ + ios_process_sol(T); +#endif + /* make the application program happy */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IBINGO; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* since the current subproblem has been fathomed, prune its + branch */ + goto fath; + } + /* at this point basic solution to LP relaxation of the current + subproblem is optimal, but integer infeasible */ + /* try to fix some non-basic structural variables of integer kind + on their current bounds due to reduced costs */ + if (T->mip->mip_stat == GLP_FEAS) + fix_by_red_cost(T); + /* let the application program try to find some solution to the + original MIP with a primal heuristic */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } + /* try to find solution with the feasibility pump heuristic */ +#if 0 /* 27/II-2016 by Chris */ + if (T->parm->fp_heur) +#else + if (T->parm->fp_heur && !root_done) +#endif + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + ios_feas_pump(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#if 1 /* 25/V-2013 */ + /* try to find solution with the proximity search heuristic */ +#if 0 /* 27/II-2016 by Chris */ + if (T->parm->ps_heur) +#else + if (T->parm->ps_heur && !root_done) +#endif + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + ios_proxy_heur(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#endif +#if 1 /* 24/X-2015 */ + /* try to find solution with a simple rounding heuristic */ + if (T->parm->sr_heur) + { xassert(T->reason == 0); + T->reason = GLP_IHEUR; + round_heur(T); + T->reason = 0; + /* check if the current branch became hopeless */ + if (!is_branch_hopeful(T, p)) + { if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Current branch became hopeless and can be prune" + "d\n"); + goto fath; + } + } +#endif + /* it's time to generate cutting planes */ + xassert(T->local != NULL); +#ifdef NEW_LOCAL /* 02/II-2018 */ + xassert(T->local->m == 0); +#else + xassert(T->local->size == 0); +#endif + /* let the application program generate some cuts; note that it + can add cuts either to the local cut pool or directly to the + current subproblem */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } +#if 1 /* 18/VII-2013 */ + if (T->curr->changed > 0) + { double degrad = fabs(T->curr->lp_obj - old_obj); + if (degrad < 1e-4 * (1.0 + fabs(old_obj))) + bad_cut++; + else + bad_cut = 0; + } + old_obj = T->curr->lp_obj; +#if 0 /* 27/II-2016 by Chris */ + if (bad_cut == 0 || (T->curr->level == 0 && bad_cut <= 3)) +#else + if (bad_cut == 0 || (!root_done && bad_cut <= 3)) +#endif +#endif + /* try to generate generic cuts with built-in generators + (as suggested by Prof. Fischetti et al. the built-in cuts are + not generated at each branching node; an intense attempt of + generating new cuts is only made at the root node, and then + a moderate effort is spent after each backtracking step) */ +#if 0 /* 27/II-2016 by Chris */ + if (T->curr->level == 0 || pred_p == 0) +#else + if (!root_done || pred_p == 0) +#endif + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + generate_cuts(T); + T->reason = 0; + } + /* if the local cut pool is not empty, select useful cuts and add + them to the current subproblem */ +#ifdef NEW_LOCAL /* 02/II-2018 */ + if (T->local->m > 0) +#else + if (T->local->size > 0) +#endif + { xassert(T->reason == 0); + T->reason = GLP_ICUTGEN; + ios_process_cuts(T); + T->reason = 0; + } + /* clear the local cut pool */ + ios_clear_pool(T, T->local); + /* perform re-optimization, if necessary */ + if (T->reopt) + { T->reopt = 0; + T->curr->changed++; + goto more; + } + /* no cuts were generated; remove inactive cuts */ + remove_cuts(T); +#if 0 /* 27/II-2016 by Chris */ + if (T->parm->msg_lev >= GLP_MSG_ALL && T->curr->level == 0) +#else + if (T->parm->msg_lev >= GLP_MSG_ALL && !root_done) +#endif + display_cut_info(T); +#if 1 /* 27/II-2016 by Chris */ + /* the first node will not be treated as root any more */ + if (!root_done) root_done = 1; +#endif + /* update history information used on pseudocost branching */ + if (T->pcost != NULL) ios_pcost_update(T); + /* it's time to perform branching */ + xassert(T->br_var == 0); + xassert(T->br_sel == 0); + /* let the application program choose variable to branch on */ + if (T->parm->cb_func != NULL) + { xassert(T->reason == 0); + xassert(T->br_var == 0); + xassert(T->br_sel == 0); + T->reason = GLP_IBRANCH; + T->parm->cb_func(T, T->parm->cb_info); + T->reason = 0; + if (T->stop) + { ret = GLP_ESTOP; + goto done; + } + } + /* if nothing has been chosen, choose some variable as specified + by the branching technique option */ + if (T->br_var == 0) + T->br_var = ios_choose_var(T, &T->br_sel); + /* perform actual branching */ + curr_p = T->curr->p; + ret = branch_on(T, T->br_var, T->br_sel); + T->br_var = T->br_sel = 0; + if (ret == 0) + { /* both branches have been created */ + pred_p = curr_p; + goto loop; + } + else if (ret == 1) + { /* one branch is hopeless and has been pruned, so now the + current subproblem is other branch */ + /* the current subproblem should be considered as a new one, + since one bound of the branching variable was changed */ + T->curr->solved = T->curr->changed = 0; +#if 1 /* 18/VII-2013 */ + /* bad_cut = 0; */ +#endif + goto more; + } + else if (ret == 2) + { /* both branches are hopeless and have been pruned; new + subproblem selection is needed to continue the search */ + goto fath; + } + else + xassert(ret != ret); +fath: /* the current subproblem has been fathomed */ + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("Node %d fathomed\n", p); + /* freeze the current subproblem */ + ios_freeze_node(T); + /* and prune the corresponding branch of the tree */ + ios_delete_node(T, p); + /* if a new integer feasible solution has just been found, other + branches may become hopeless and therefore must be pruned */ + if (T->mip->mip_stat == GLP_FEAS) cleanup_the_tree(T); + /* new subproblem selection is needed due to backtracking */ + pred_p = 0; + goto loop; +done: /* display progress of the search on exit from the solver */ + if (T->parm->msg_lev >= GLP_MSG_ON) + show_progress(T, 0); + if (T->mir_gen != NULL) +#if 0 /* 06/III-2016 */ + ios_mir_term(T->mir_gen), T->mir_gen = NULL; +#else + glp_mir_free(T->mir_gen), T->mir_gen = NULL; +#endif +#ifdef NEW_COVER /* 13/II-2018 */ + if (T->cov_gen != NULL) + glp_cov_free(T->cov_gen), T->cov_gen = NULL; +#endif + if (T->clq_gen != NULL) +#if 0 /* 08/III-2016 */ + ios_clq_term(T->clq_gen), T->clq_gen = NULL; +#else + glp_cfg_free(T->clq_gen), T->clq_gen = NULL; +#endif + /* return to the calling program */ + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios07.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios07.c new file mode 100644 index 000000000..f750e571b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios07.c @@ -0,0 +1,551 @@ +/* glpios07.c (mixed cover cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*---------------------------------------------------------------------- +-- COVER INEQUALITIES +-- +-- Consider the set of feasible solutions to 0-1 knapsack problem: +-- +-- sum a[j]*x[j] <= b, (1) +-- j in J +-- +-- x[j] is binary, (2) +-- +-- where, wlog, we assume that a[j] > 0 (since 0-1 variables can be +-- complemented) and a[j] <= b (since a[j] > b implies x[j] = 0). +-- +-- A set C within J is called a cover if +-- +-- sum a[j] > b. (3) +-- j in C +-- +-- For any cover C the inequality +-- +-- sum x[j] <= |C| - 1 (4) +-- j in C +-- +-- is called a cover inequality and is valid for (1)-(2). +-- +-- MIXED COVER INEQUALITIES +-- +-- Consider the set of feasible solutions to mixed knapsack problem: +-- +-- sum a[j]*x[j] + y <= b, (5) +-- j in J +-- +-- x[j] is binary, (6) +-- +-- 0 <= y <= u is continuous, (7) +-- +-- where again we assume that a[j] > 0. +-- +-- Let C within J be some set. From (1)-(4) it follows that +-- +-- sum a[j] > b - y (8) +-- j in C +-- +-- implies +-- +-- sum x[j] <= |C| - 1. (9) +-- j in C +-- +-- Thus, we need to modify the inequality (9) in such a way that it be +-- a constraint only if the condition (8) is satisfied. +-- +-- Consider the following inequality: +-- +-- sum x[j] <= |C| - t. (10) +-- j in C +-- +-- If 0 < t <= 1, then (10) is equivalent to (9), because all x[j] are +-- binary variables. On the other hand, if t <= 0, (10) being satisfied +-- for any values of x[j] is not a constraint. +-- +-- Let +-- +-- t' = sum a[j] + y - b. (11) +-- j in C +-- +-- It is understood that the condition t' > 0 is equivalent to (8). +-- Besides, from (6)-(7) it follows that t' has an implied upper bound: +-- +-- t'max = sum a[j] + u - b. (12) +-- j in C +-- +-- This allows to express the parameter t having desired properties: +-- +-- t = t' / t'max. (13) +-- +-- In fact, t <= 1 by definition, and t > 0 being equivalent to t' > 0 +-- is equivalent to (8). +-- +-- Thus, the inequality (10), where t is given by formula (13) is valid +-- for (5)-(7). +-- +-- Note that if u = 0, then y = 0, so t = 1, and the conditions (8) and +-- (10) is transformed to the conditions (3) and (4). +-- +-- GENERATING MIXED COVER CUTS +-- +-- To generate a mixed cover cut in the form (10) we need to find such +-- set C which satisfies to the inequality (8) and for which, in turn, +-- the inequality (10) is violated in the current point. +-- +-- Substituting t from (13) to (10) gives: +-- +-- 1 +-- sum x[j] <= |C| - ----- (sum a[j] + y - b), (14) +-- j in C t'max j in C +-- +-- and finally we have the cut inequality in the standard form: +-- +-- sum x[j] + alfa * y <= beta, (15) +-- j in C +-- +-- where: +-- +-- alfa = 1 / t'max, (16) +-- +-- beta = |C| - alfa * (sum a[j] - b). (17) +-- j in C */ + +#if 1 +#define MAXTRY 1000 +#else +#define MAXTRY 10000 +#endif + +static int cover2(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using two-element cover */ + int i, j, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + { /* C = {i, j} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] - b; + alfa = 1.0 / (temp + u); + beta = 2.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover3(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using three-element cover */ + int i, j, k, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + for (k = j+1; k <= n; k++) + { /* C = {i, j, k} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + a[k] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] + a[k] - b; + alfa = 1.0 / (temp + u); + beta = 3.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + x[k] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + cov[3] = k; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover4(int n, double a[], double b, double u, double x[], + double y, int cov[], double *_alfa, double *_beta) +{ /* try to generate mixed cover cut using four-element cover */ + int i, j, k, l, try = 0, ret = 0; + double eps, alfa, beta, temp, rmax = 0.001; + eps = 0.001 * (1.0 + fabs(b)); + for (i = 0+1; i <= n; i++) + for (j = i+1; j <= n; j++) + for (k = j+1; k <= n; k++) + for (l = k+1; l <= n; l++) + { /* C = {i, j, k, l} */ + try++; + if (try > MAXTRY) goto done; + /* check if condition (8) is satisfied */ + if (a[i] + a[j] + a[k] + a[l] + y > b + eps) + { /* compute parameters for inequality (15) */ + temp = a[i] + a[j] + a[k] + a[l] - b; + alfa = 1.0 / (temp + u); + beta = 4.0 - alfa * temp; + /* compute violation of inequality (15) */ + temp = x[i] + x[j] + x[k] + x[l] + alfa * y - beta; + /* choose C providing maximum violation */ + if (rmax < temp) + { rmax = temp; + cov[1] = i; + cov[2] = j; + cov[3] = k; + cov[4] = l; + *_alfa = alfa; + *_beta = beta; + ret = 1; + } + } + } +done: return ret; +} + +static int cover(int n, double a[], double b, double u, double x[], + double y, int cov[], double *alfa, double *beta) +{ /* try to generate mixed cover cut; + input (see (5)): + n is the number of binary variables; + a[1:n] are coefficients at binary variables; + b is the right-hand side; + u is upper bound of continuous variable; + x[1:n] are values of binary variables at current point; + y is value of continuous variable at current point; + output (see (15), (16), (17)): + cov[1:r] are indices of binary variables included in cover C, + where r is the set cardinality returned on exit; + alfa coefficient at continuous variable; + beta is the right-hand side; */ + int j; + /* perform some sanity checks */ + xassert(n >= 2); + for (j = 1; j <= n; j++) xassert(a[j] > 0.0); +#if 1 /* ??? */ + xassert(b > -1e-5); +#else + xassert(b > 0.0); +#endif + xassert(u >= 0.0); + for (j = 1; j <= n; j++) xassert(0.0 <= x[j] && x[j] <= 1.0); + xassert(0.0 <= y && y <= u); + /* try to generate mixed cover cut */ + if (cover2(n, a, b, u, x, y, cov, alfa, beta)) return 2; + if (cover3(n, a, b, u, x, y, cov, alfa, beta)) return 3; + if (cover4(n, a, b, u, x, y, cov, alfa, beta)) return 4; + return 0; +} + +/*---------------------------------------------------------------------- +-- lpx_cover_cut - generate mixed cover cut. +-- +-- SYNOPSIS +-- +-- int lpx_cover_cut(LPX *lp, int len, int ind[], double val[], +-- double work[]); +-- +-- DESCRIPTION +-- +-- The routine lpx_cover_cut generates a mixed cover cut for a given +-- row of the MIP problem. +-- +-- The given row of the MIP problem should be explicitly specified in +-- the form: +-- +-- sum{j in J} a[j]*x[j] <= b. (1) +-- +-- On entry indices (ordinal numbers) of structural variables, which +-- have non-zero constraint coefficients, should be placed in locations +-- ind[1], ..., ind[len], and corresponding constraint coefficients +-- should be placed in locations val[1], ..., val[len]. The right-hand +-- side b should be stored in location val[0]. +-- +-- The working array work should have at least nb locations, where nb +-- is the number of binary variables in (1). +-- +-- The routine generates a mixed cover cut in the same form as (1) and +-- stores the cut coefficients and right-hand side in the same way as +-- just described above. +-- +-- RETURNS +-- +-- If the cutting plane has been successfully generated, the routine +-- returns 1 <= len' <= n, which is the number of non-zero coefficients +-- in the inequality constraint. Otherwise, the routine returns zero. */ + +static int lpx_cover_cut(glp_prob *lp, int len, int ind[], + double val[], double work[]) +{ int cov[1+4], j, k, nb, newlen, r; + double f_min, f_max, alfa, beta, u, *x = work, y; + /* substitute and remove fixed variables */ + newlen = 0; + for (k = 1; k <= len; k++) + { j = ind[k]; + if (glp_get_col_type(lp, j) == GLP_FX) + val[0] -= val[k] * glp_get_col_lb(lp, j); + else + { newlen++; + ind[newlen] = ind[k]; + val[newlen] = val[k]; + } + } + len = newlen; + /* move binary variables to the beginning of the list so that + elements 1, 2, ..., nb correspond to binary variables, and + elements nb+1, nb+2, ..., len correspond to rest variables */ + nb = 0; + for (k = 1; k <= len; k++) + { j = ind[k]; + if (glp_get_col_kind(lp, j) == GLP_BV) + { /* binary variable */ + int ind_k; + double val_k; + nb++; + ind_k = ind[nb], val_k = val[nb]; + ind[nb] = ind[k], val[nb] = val[k]; + ind[k] = ind_k, val[k] = val_k; + } + } + /* now the specified row has the form: + sum a[j]*x[j] + sum a[j]*y[j] <= b, + where x[j] are binary variables, y[j] are rest variables */ + /* at least two binary variables are needed */ + if (nb < 2) return 0; + /* compute implied lower and upper bounds for sum a[j]*y[j] */ + f_min = f_max = 0.0; + for (k = nb+1; k <= len; k++) + { j = ind[k]; + /* both bounds must be finite */ + if (glp_get_col_type(lp, j) != GLP_DB) return 0; + if (val[k] > 0.0) + { f_min += val[k] * glp_get_col_lb(lp, j); + f_max += val[k] * glp_get_col_ub(lp, j); + } + else + { f_min += val[k] * glp_get_col_ub(lp, j); + f_max += val[k] * glp_get_col_lb(lp, j); + } + } + /* sum a[j]*x[j] + sum a[j]*y[j] <= b ===> + sum a[j]*x[j] + (sum a[j]*y[j] - f_min) <= b - f_min ===> + sum a[j]*x[j] + y <= b - f_min, + where y = sum a[j]*y[j] - f_min; + note that 0 <= y <= u, u = f_max - f_min */ + /* determine upper bound of y */ + u = f_max - f_min; + /* determine value of y at the current point */ + y = 0.0; + for (k = nb+1; k <= len; k++) + { j = ind[k]; + y += val[k] * glp_get_col_prim(lp, j); + } + y -= f_min; + if (y < 0.0) y = 0.0; + if (y > u) y = u; + /* modify the right-hand side b */ + val[0] -= f_min; + /* now the transformed row has the form: + sum a[j]*x[j] + y <= b, where 0 <= y <= u */ + /* determine values of x[j] at the current point */ + for (k = 1; k <= nb; k++) + { j = ind[k]; + x[k] = glp_get_col_prim(lp, j); + if (x[k] < 0.0) x[k] = 0.0; + if (x[k] > 1.0) x[k] = 1.0; + } + /* if a[j] < 0, replace x[j] by its complement 1 - x'[j] */ + for (k = 1; k <= nb; k++) + { if (val[k] < 0.0) + { ind[k] = - ind[k]; + val[k] = - val[k]; + val[0] += val[k]; + x[k] = 1.0 - x[k]; + } + } + /* try to generate a mixed cover cut for the transformed row */ + r = cover(nb, val, val[0], u, x, y, cov, &alfa, &beta); + if (r == 0) return 0; + xassert(2 <= r && r <= 4); + /* now the cut is in the form: + sum{j in C} x[j] + alfa * y <= beta */ + /* store the right-hand side beta */ + ind[0] = 0, val[0] = beta; + /* restore the original ordinal numbers of x[j] */ + for (j = 1; j <= r; j++) cov[j] = ind[cov[j]]; + /* store cut coefficients at binary variables complementing back + the variables having negative row coefficients */ + xassert(r <= nb); + for (k = 1; k <= r; k++) + { if (cov[k] > 0) + { ind[k] = +cov[k]; + val[k] = +1.0; + } + else + { ind[k] = -cov[k]; + val[k] = -1.0; + val[0] -= 1.0; + } + } + /* substitute y = sum a[j]*y[j] - f_min */ + for (k = nb+1; k <= len; k++) + { r++; + ind[r] = ind[k]; + val[r] = alfa * val[k]; + } + val[0] += alfa * f_min; + xassert(r <= len); + len = r; + return len; +} + +/*---------------------------------------------------------------------- +-- lpx_eval_row - compute explictily specified row. +-- +-- SYNOPSIS +-- +-- double lpx_eval_row(LPX *lp, int len, int ind[], double val[]); +-- +-- DESCRIPTION +-- +-- The routine lpx_eval_row computes the primal value of an explicitly +-- specified row using current values of structural variables. +-- +-- The explicitly specified row may be thought as a linear form: +-- +-- y = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], +-- +-- where y is an auxiliary variable for this row, a[j] are coefficients +-- of the linear form, x[m+j] are structural variables. +-- +-- On entry column indices and numerical values of non-zero elements of +-- the row should be stored in locations ind[1], ..., ind[len] and +-- val[1], ..., val[len], where len is the number of non-zero elements. +-- The array ind and val are not changed on exit. +-- +-- RETURNS +-- +-- The routine returns a computed value of y, the auxiliary variable of +-- the specified row. */ + +static double lpx_eval_row(glp_prob *lp, int len, int ind[], + double val[]) +{ int n = glp_get_num_cols(lp); + int j, k; + double sum = 0.0; + if (len < 0) + xerror("lpx_eval_row: len = %d; invalid row length\n", len); + for (k = 1; k <= len; k++) + { j = ind[k]; + if (!(1 <= j && j <= n)) + xerror("lpx_eval_row: j = %d; column number out of range\n", + j); + sum += val[k] * glp_get_col_prim(lp, j); + } + return sum; +} + +/*********************************************************************** +* NAME +* +* ios_cov_gen - generate mixed cover cuts +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_cov_gen(glp_tree *tree); +* +* DESCRIPTION +* +* The routine ios_cov_gen generates mixed cover cuts for the current +* point and adds them to the cut pool. */ + +void ios_cov_gen(glp_tree *tree) +{ glp_prob *prob = tree->mip; + int m = glp_get_num_rows(prob); + int n = glp_get_num_cols(prob); + int i, k, type, kase, len, *ind; + double r, *val, *work; + xassert(glp_get_status(prob) == GLP_OPT); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + work = xcalloc(1+n, sizeof(double)); + /* look through all rows */ + for (i = 1; i <= m; i++) + for (kase = 1; kase <= 2; kase++) + { type = glp_get_row_type(prob, i); + if (kase == 1) + { /* consider rows of '<=' type */ + if (!(type == GLP_UP || type == GLP_DB)) continue; + len = glp_get_mat_row(prob, i, ind, val); + val[0] = glp_get_row_ub(prob, i); + } + else + { /* consider rows of '>=' type */ + if (!(type == GLP_LO || type == GLP_DB)) continue; + len = glp_get_mat_row(prob, i, ind, val); + for (k = 1; k <= len; k++) val[k] = - val[k]; + val[0] = - glp_get_row_lb(prob, i); + } + /* generate mixed cover cut: + sum{j in J} a[j] * x[j] <= b */ + len = lpx_cover_cut(prob, len, ind, val, work); + if (len == 0) continue; + /* at the current point the cut inequality is violated, i.e. + sum{j in J} a[j] * x[j] - b > 0 */ + r = lpx_eval_row(prob, len, ind, val) - val[0]; + if (r < 1e-3) continue; + /* add the cut to the cut pool */ + glp_ios_add_row(tree, NULL, GLP_RF_COV, 0, len, ind, val, + GLP_UP, val[0]); + } + /* free working arrays */ + xfree(ind); + xfree(val); + xfree(work); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios09.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios09.c new file mode 100644 index 000000000..d80ed9a3a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios09.c @@ -0,0 +1,664 @@ +/* glpios09.c (branching heuristics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* NAME +* +* ios_choose_var - select variable to branch on +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_choose_var(glp_tree *T, int *next); +* +* The routine ios_choose_var chooses a variable from the candidate +* list to branch on. Additionally the routine provides a flag stored +* in the location next to suggests which of the child subproblems +* should be solved next. +* +* RETURNS +* +* The routine ios_choose_var returns the ordinal number of the column +* choosen. */ + +static int branch_first(glp_tree *T, int *next); +static int branch_last(glp_tree *T, int *next); +static int branch_mostf(glp_tree *T, int *next); +static int branch_drtom(glp_tree *T, int *next); + +int ios_choose_var(glp_tree *T, int *next) +{ int j; + if (T->parm->br_tech == GLP_BR_FFV) + { /* branch on first fractional variable */ + j = branch_first(T, next); + } + else if (T->parm->br_tech == GLP_BR_LFV) + { /* branch on last fractional variable */ + j = branch_last(T, next); + } + else if (T->parm->br_tech == GLP_BR_MFV) + { /* branch on most fractional variable */ + j = branch_mostf(T, next); + } + else if (T->parm->br_tech == GLP_BR_DTH) + { /* branch using the heuristic by Dreebeck and Tomlin */ + j = branch_drtom(T, next); + } + else if (T->parm->br_tech == GLP_BR_PCH) + { /* hybrid pseudocost heuristic */ + j = ios_pcost_branch(T, next); + } + else + xassert(T != T); + return j; +} + +/*********************************************************************** +* branch_first - choose first branching variable +* +* This routine looks up the list of structural variables and chooses +* the first one, which is of integer kind and has fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. */ + +static int branch_first(glp_tree *T, int *_next) +{ int j, next; + double beta; + /* choose the column to branch on */ + for (j = 1; j <= T->n; j++) + if (T->non_int[j]) break; + xassert(1 <= j && j <= T->n); + /* select the branch to be solved next */ + beta = glp_get_col_prim(T->mip, j); + if (beta - floor(beta) < ceil(beta) - beta) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + *_next = next; + return j; +} + +/*********************************************************************** +* branch_last - choose last branching variable +* +* This routine looks up the list of structural variables and chooses +* the last one, which is of integer kind and has fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. */ + +static int branch_last(glp_tree *T, int *_next) +{ int j, next; + double beta; + /* choose the column to branch on */ + for (j = T->n; j >= 1; j--) + if (T->non_int[j]) break; + xassert(1 <= j && j <= T->n); + /* select the branch to be solved next */ + beta = glp_get_col_prim(T->mip, j); + if (beta - floor(beta) < ceil(beta) - beta) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + *_next = next; + return j; +} + +/*********************************************************************** +* branch_mostf - choose most fractional branching variable +* +* This routine looks up the list of structural variables and chooses +* that one, which is of integer kind and has most fractional value in +* optimal solution to the current LP relaxation. +* +* This routine also selects the branch to be solved next where integer +* infeasibility of the chosen variable is less than in other one. +* +* (Alexander Martin notices that "...most infeasible is as good as +* random...".) */ + +static int branch_mostf(glp_tree *T, int *_next) +{ int j, jj, next; + double beta, most, temp; + /* choose the column to branch on */ + jj = 0, most = DBL_MAX; + for (j = 1; j <= T->n; j++) + { if (T->non_int[j]) + { beta = glp_get_col_prim(T->mip, j); + temp = floor(beta) + 0.5; + if (most > fabs(beta - temp)) + { jj = j, most = fabs(beta - temp); + if (beta < temp) + next = GLP_DN_BRNCH; + else + next = GLP_UP_BRNCH; + } + } + } + *_next = next; + return jj; +} + +/*********************************************************************** +* branch_drtom - choose branching var using Driebeck-Tomlin heuristic +* +* This routine chooses a structural variable, which is required to be +* integral and has fractional value in optimal solution of the current +* LP relaxation, using a heuristic proposed by Driebeck and Tomlin. +* +* The routine also selects the branch to be solved next, again due to +* Driebeck and Tomlin. +* +* This routine is based on the heuristic proposed in: +* +* Driebeck N.J. An algorithm for the solution of mixed-integer +* programming problems, Management Science, 12: 576-87 (1966); +* +* and improved in: +* +* Tomlin J.A. Branch and bound methods for integer and non-convex +* programming, in J.Abadie (ed.), Integer and Nonlinear Programming, +* North-Holland, Amsterdam, pp. 437-50 (1970). +* +* Must note that this heuristic is time-expensive, because computing +* one-step degradation (see the routine below) requires one BTRAN for +* each fractional-valued structural variable. */ + +static int branch_drtom(glp_tree *T, int *_next) +{ glp_prob *mip = T->mip; + int m = mip->m; + int n = mip->n; + unsigned char *non_int = T->non_int; + int j, jj, k, t, next, kase, len, stat, *ind; + double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up, + dd_dn, dd_up, degrad, *val; + /* basic solution of LP relaxation must be optimal */ + xassert(glp_get_status(mip) == GLP_OPT); + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + /* nothing has been chosen so far */ + jj = 0, degrad = -1.0; + /* walk through the list of columns (structural variables) */ + for (j = 1; j <= n; j++) + { /* if j-th column is not marked as fractional, skip it */ + if (!non_int[j]) continue; + /* obtain (fractional) value of j-th column in basic solution + of LP relaxation */ + x = glp_get_col_prim(mip, j); + /* since the value of j-th column is fractional, the column is + basic; compute corresponding row of the simplex table */ + len = glp_eval_tab_row(mip, m+j, ind, val); + /* the following fragment computes a change in the objective + function: delta Z = new Z - old Z, where old Z is the + objective value in the current optimal basis, and new Z is + the objective value in the adjacent basis, for two cases: + 1) if new upper bound ub' = floor(x[j]) is introduced for + j-th column (down branch); + 2) if new lower bound lb' = ceil(x[j]) is introduced for + j-th column (up branch); + since in both cases the solution remaining dual feasible + becomes primal infeasible, one implicit simplex iteration + is performed to determine the change delta Z; + it is obvious that new Z, which is never better than old Z, + is a lower (minimization) or upper (maximization) bound of + the objective function for down- and up-branches. */ + for (kase = -1; kase <= +1; kase += 2) + { /* if kase < 0, the new upper bound of x[j] is introduced; + in this case x[j] should decrease in order to leave the + basis and go to its new upper bound */ + /* if kase > 0, the new lower bound of x[j] is introduced; + in this case x[j] should increase in order to leave the + basis and go to its new lower bound */ + /* apply the dual ratio test in order to determine which + auxiliary or structural variable should enter the basis + to keep dual feasibility */ + k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9); + if (k != 0) k = ind[k]; + /* if no non-basic variable has been chosen, LP relaxation + of corresponding branch being primal infeasible and dual + unbounded has no primal feasible solution; in this case + the change delta Z is formally set to infinity */ + if (k == 0) + { delta_z = + (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX); + goto skip; + } + /* row of the simplex table that corresponds to non-basic + variable x[k] choosen by the dual ratio test is: + x[j] = ... + alfa * x[k] + ... + where alfa is the influence coefficient (an element of + the simplex table row) */ + /* determine the coefficient alfa */ + for (t = 1; t <= len; t++) if (ind[t] == k) break; + xassert(1 <= t && t <= len); + alfa = val[t]; + /* since in the adjacent basis the variable x[j] becomes + non-basic, knowing its value in the current basis we can + determine its change delta x[j] = new x[j] - old x[j] */ + delta_j = (kase < 0 ? floor(x) : ceil(x)) - x; + /* and knowing the coefficient alfa we can determine the + corresponding change delta x[k] = new x[k] - old x[k], + where old x[k] is a value of x[k] in the current basis, + and new x[k] is a value of x[k] in the adjacent basis */ + delta_k = delta_j / alfa; + /* Tomlin noticed that if the variable x[k] is of integer + kind, its change cannot be less (eventually) than one in + the magnitude */ + if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV) + { /* x[k] is structural integer variable */ + if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3) + { if (delta_k > 0.0) + delta_k = ceil(delta_k); /* +3.14 -> +4 */ + else + delta_k = floor(delta_k); /* -3.14 -> -4 */ + } + } + /* now determine the status and reduced cost of x[k] in the + current basis */ + if (k <= m) + { stat = glp_get_row_stat(mip, k); + dk = glp_get_row_dual(mip, k); + } + else + { stat = glp_get_col_stat(mip, k-m); + dk = glp_get_col_dual(mip, k-m); + } + /* if the current basis is dual degenerate, some reduced + costs which are close to zero may have wrong sign due to + round-off errors, so correct the sign of d[k] */ + switch (T->mip->dir) + { case GLP_MIN: + if (stat == GLP_NL && dk < 0.0 || + stat == GLP_NU && dk > 0.0 || + stat == GLP_NF) dk = 0.0; + break; + case GLP_MAX: + if (stat == GLP_NL && dk > 0.0 || + stat == GLP_NU && dk < 0.0 || + stat == GLP_NF) dk = 0.0; + break; + default: + xassert(T != T); + } + /* now knowing the change of x[k] and its reduced cost d[k] + we can compute the corresponding change in the objective + function delta Z = new Z - old Z = d[k] * delta x[k]; + note that due to Tomlin's modification new Z can be even + worse than in the adjacent basis */ + delta_z = dk * delta_k; +skip: /* new Z is never better than old Z, therefore the change + delta Z is always non-negative (in case of minimization) + or non-positive (in case of maximization) */ + switch (T->mip->dir) + { case GLP_MIN: xassert(delta_z >= 0.0); break; + case GLP_MAX: xassert(delta_z <= 0.0); break; + default: xassert(T != T); + } + /* save the change in the objective fnction for down- and + up-branches, respectively */ + if (kase < 0) dz_dn = delta_z; else dz_up = delta_z; + } + /* thus, in down-branch no integer feasible solution can be + better than Z + dz_dn, and in up-branch no integer feasible + solution can be better than Z + dz_up, where Z is value of + the objective function in the current basis */ + /* following the heuristic by Driebeck and Tomlin we choose a + column (i.e. structural variable) which provides largest + degradation of the objective function in some of branches; + besides, we select the branch with smaller degradation to + be solved next and keep other branch with larger degradation + in the active list hoping to minimize the number of further + backtrackings */ + if (degrad < fabs(dz_dn) || degrad < fabs(dz_up)) + { jj = j; + if (fabs(dz_dn) < fabs(dz_up)) + { /* select down branch to be solved next */ + next = GLP_DN_BRNCH; + degrad = fabs(dz_up); + } + else + { /* select up branch to be solved next */ + next = GLP_UP_BRNCH; + degrad = fabs(dz_dn); + } + /* save the objective changes for printing */ + dd_dn = dz_dn, dd_up = dz_up; + /* if down- or up-branch has no feasible solution, we does + not need to consider other candidates (in principle, the + corresponding branch could be pruned right now) */ + if (degrad == DBL_MAX) break; + } + } + /* free working arrays */ + xfree(ind); + xfree(val); + /* something must be chosen */ + xassert(1 <= jj && jj <= n); +#if 1 /* 02/XI-2009 */ + if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val))) + { jj = branch_mostf(T, &next); + goto done; + } +#endif + if (T->parm->msg_lev >= GLP_MSG_DBG) + { xprintf("branch_drtom: column %d chosen to branch on\n", jj); + if (fabs(dd_dn) == DBL_MAX) + xprintf("branch_drtom: down-branch is infeasible\n"); + else + xprintf("branch_drtom: down-branch bound is %.9e\n", + glp_get_obj_val(mip) + dd_dn); + if (fabs(dd_up) == DBL_MAX) + xprintf("branch_drtom: up-branch is infeasible\n"); + else + xprintf("branch_drtom: up-branch bound is %.9e\n", + glp_get_obj_val(mip) + dd_up); + } +done: *_next = next; + return jj; +} + +/**********************************************************************/ + +struct csa +{ /* common storage area */ + int *dn_cnt; /* int dn_cnt[1+n]; */ + /* dn_cnt[j] is the number of subproblems, whose LP relaxations + have been solved and which are down-branches for variable x[j]; + dn_cnt[j] = 0 means the down pseudocost is uninitialized */ + double *dn_sum; /* double dn_sum[1+n]; */ + /* dn_sum[j] is the sum of per unit degradations of the objective + over all dn_cnt[j] subproblems */ + int *up_cnt; /* int up_cnt[1+n]; */ + /* up_cnt[j] is the number of subproblems, whose LP relaxations + have been solved and which are up-branches for variable x[j]; + up_cnt[j] = 0 means the up pseudocost is uninitialized */ + double *up_sum; /* double up_sum[1+n]; */ + /* up_sum[j] is the sum of per unit degradations of the objective + over all up_cnt[j] subproblems */ +}; + +void *ios_pcost_init(glp_tree *tree) +{ /* initialize working data used on pseudocost branching */ + struct csa *csa; + int n = tree->n, j; + csa = xmalloc(sizeof(struct csa)); + csa->dn_cnt = xcalloc(1+n, sizeof(int)); + csa->dn_sum = xcalloc(1+n, sizeof(double)); + csa->up_cnt = xcalloc(1+n, sizeof(int)); + csa->up_sum = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { csa->dn_cnt[j] = csa->up_cnt[j] = 0; + csa->dn_sum[j] = csa->up_sum[j] = 0.0; + } + return csa; +} + +static double eval_degrad(glp_prob *P, int j, double bnd) +{ /* compute degradation of the objective on fixing x[j] at given + value with a limited number of dual simplex iterations */ + /* this routine fixes column x[j] at specified value bnd, + solves resulting LP, and returns a lower bound to degradation + of the objective, degrad >= 0 */ + glp_prob *lp; + glp_smcp parm; + int ret; + double degrad; + /* the current basis must be optimal */ + xassert(glp_get_status(P) == GLP_OPT); + /* create a copy of P */ + lp = glp_create_prob(); + glp_copy_prob(lp, P, 0); + /* fix column x[j] at specified value */ + glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd); + /* try to solve resulting LP */ + glp_init_smcp(&parm); + parm.msg_lev = GLP_MSG_OFF; + parm.meth = GLP_DUAL; + parm.it_lim = 30; + parm.out_dly = 1000; + parm.meth = GLP_DUAL; + ret = glp_simplex(lp, &parm); + if (ret == 0 || ret == GLP_EITLIM) + { if (glp_get_prim_stat(lp) == GLP_NOFEAS) + { /* resulting LP has no primal feasible solution */ + degrad = DBL_MAX; + } + else if (glp_get_dual_stat(lp) == GLP_FEAS) + { /* resulting basis is optimal or at least dual feasible, + so we have the correct lower bound to degradation */ + if (P->dir == GLP_MIN) + degrad = lp->obj_val - P->obj_val; + else if (P->dir == GLP_MAX) + degrad = P->obj_val - lp->obj_val; + else + xassert(P != P); + /* degradation cannot be negative by definition */ + /* note that the lower bound to degradation may be close + to zero even if its exact value is zero due to round-off + errors on computing the objective value */ + if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val))) + degrad = 0.0; + } + else + { /* the final basis reported by the simplex solver is dual + infeasible, so we cannot determine a non-trivial lower + bound to degradation */ + degrad = 0.0; + } + } + else + { /* the simplex solver failed */ + degrad = 0.0; + } + /* delete the copy of P */ + glp_delete_prob(lp); + return degrad; +} + +void ios_pcost_update(glp_tree *tree) +{ /* update history information for pseudocost branching */ + /* this routine is called every time when LP relaxation of the + current subproblem has been solved to optimality with all lazy + and cutting plane constraints included */ + int j; + double dx, dz, psi; + struct csa *csa = tree->pcost; + xassert(csa != NULL); + xassert(tree->curr != NULL); + /* if the current subproblem is the root, skip updating */ + if (tree->curr->up == NULL) goto skip; + /* determine branching variable x[j], which was used in the + parent subproblem to create the current subproblem */ + j = tree->curr->up->br_var; + xassert(1 <= j && j <= tree->n); + /* determine the change dx[j] = new x[j] - old x[j], + where new x[j] is a value of x[j] in optimal solution to LP + relaxation of the current subproblem, old x[j] is a value of + x[j] in optimal solution to LP relaxation of the parent + subproblem */ + dx = tree->mip->col[j]->prim - tree->curr->up->br_val; + xassert(dx != 0.0); + /* determine corresponding change dz = new dz - old dz in the + objective function value */ + dz = tree->mip->obj_val - tree->curr->up->lp_obj; + /* determine per unit degradation of the objective function */ + psi = fabs(dz / dx); + /* update history information */ + if (dx < 0.0) + { /* the current subproblem is down-branch */ + csa->dn_cnt[j]++; + csa->dn_sum[j] += psi; + } + else /* dx > 0.0 */ + { /* the current subproblem is up-branch */ + csa->up_cnt[j]++; + csa->up_sum[j] += psi; + } +skip: return; +} + +void ios_pcost_free(glp_tree *tree) +{ /* free working area used on pseudocost branching */ + struct csa *csa = tree->pcost; + xassert(csa != NULL); + xfree(csa->dn_cnt); + xfree(csa->dn_sum); + xfree(csa->up_cnt); + xfree(csa->up_sum); + xfree(csa); + tree->pcost = NULL; + return; +} + +static double eval_psi(glp_tree *T, int j, int brnch) +{ /* compute estimation of pseudocost of variable x[j] for down- + or up-branch */ + struct csa *csa = T->pcost; + double beta, degrad, psi; + xassert(csa != NULL); + xassert(1 <= j && j <= T->n); + if (brnch == GLP_DN_BRNCH) + { /* down-branch */ + if (csa->dn_cnt[j] == 0) + { /* initialize down pseudocost */ + beta = T->mip->col[j]->prim; + degrad = eval_degrad(T->mip, j, floor(beta)); + if (degrad == DBL_MAX) + { psi = DBL_MAX; + goto done; + } + csa->dn_cnt[j] = 1; + csa->dn_sum[j] = degrad / (beta - floor(beta)); + } + psi = csa->dn_sum[j] / (double)csa->dn_cnt[j]; + } + else if (brnch == GLP_UP_BRNCH) + { /* up-branch */ + if (csa->up_cnt[j] == 0) + { /* initialize up pseudocost */ + beta = T->mip->col[j]->prim; + degrad = eval_degrad(T->mip, j, ceil(beta)); + if (degrad == DBL_MAX) + { psi = DBL_MAX; + goto done; + } + csa->up_cnt[j] = 1; + csa->up_sum[j] = degrad / (ceil(beta) - beta); + } + psi = csa->up_sum[j] / (double)csa->up_cnt[j]; + } + else + xassert(brnch != brnch); +done: return psi; +} + +static void progress(glp_tree *T) +{ /* display progress of pseudocost initialization */ + struct csa *csa = T->pcost; + int j, nv = 0, ni = 0; + for (j = 1; j <= T->n; j++) + { if (glp_ios_can_branch(T, j)) + { nv++; + if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++; + } + } + xprintf("Pseudocosts initialized for %d of %d variables\n", + ni, nv); + return; +} + +int ios_pcost_branch(glp_tree *T, int *_next) +{ /* choose branching variable with pseudocost branching */ +#if 0 /* 10/VI-2013 */ + glp_long t = xtime(); +#else + double t = xtime(); +#endif + int j, jjj, sel; + double beta, psi, d1, d2, d, dmax; + /* initialize the working arrays */ + if (T->pcost == NULL) + T->pcost = ios_pcost_init(T); + /* nothing has been chosen so far */ + jjj = 0, dmax = -1.0; + /* go through the list of branching candidates */ + for (j = 1; j <= T->n; j++) + { if (!glp_ios_can_branch(T, j)) continue; + /* determine primal value of x[j] in optimal solution to LP + relaxation of the current subproblem */ + beta = T->mip->col[j]->prim; + /* estimate pseudocost of x[j] for down-branch */ + psi = eval_psi(T, j, GLP_DN_BRNCH); + if (psi == DBL_MAX) + { /* down-branch has no primal feasible solution */ + jjj = j, sel = GLP_DN_BRNCH; + goto done; + } + /* estimate degradation of the objective for down-branch */ + d1 = psi * (beta - floor(beta)); + /* estimate pseudocost of x[j] for up-branch */ + psi = eval_psi(T, j, GLP_UP_BRNCH); + if (psi == DBL_MAX) + { /* up-branch has no primal feasible solution */ + jjj = j, sel = GLP_UP_BRNCH; + goto done; + } + /* estimate degradation of the objective for up-branch */ + d2 = psi * (ceil(beta) - beta); + /* determine d = max(d1, d2) */ + d = (d1 > d2 ? d1 : d2); + /* choose x[j] which provides maximal estimated degradation of + the objective either in down- or up-branch */ + if (dmax < d) + { dmax = d; + jjj = j; + /* continue the search from a subproblem, where degradation + is less than in other one */ + sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH); + } + /* display progress of pseudocost initialization */ + if (T->parm->msg_lev >= GLP_ON) + { if (xdifftime(xtime(), t) >= 10.0) + { progress(T); + t = xtime(); + } + } + } + if (dmax == 0.0) + { /* no degradation is indicated; choose a variable having most + fractional value */ + jjj = branch_mostf(T, &sel); + } +done: *_next = sel; + return jjj; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios11.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios11.c new file mode 100644 index 000000000..09fccef6b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios11.c @@ -0,0 +1,435 @@ +/* glpios11.c (process cuts stored in the local cut pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017, 2018 Andrew Makhorin, Department for +* Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +* rights reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "draft.h" +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* NAME +* +* ios_process_cuts - process cuts stored in the local cut pool +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_process_cuts(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_process_cuts analyzes each cut currently stored in +* the local cut pool, which must be non-empty, and either adds the cut +* to the current subproblem or just discards it. All cuts are assumed +* to be locally valid. On exit the local cut pool remains unchanged. +* +* REFERENCES +* +* 1. E.Balas, S.Ceria, G.Cornuejols, "Mixed 0-1 Programming by +* Lift-and-Project in a Branch-and-Cut Framework", Management Sc., +* 42 (1996) 1229-1246. +* +* 2. G.Andreello, A.Caprara, and M.Fischetti, "Embedding Cuts in +* a Branch&Cut Framework: a Computational Study with {0,1/2}-Cuts", +* Preliminary Draft, October 28, 2003, pp.6-8. */ + +struct info +{ /* estimated cut efficiency */ + IOSCUT *cut; + /* pointer to cut in the cut pool */ + char flag; + /* if this flag is set, the cut is included into the current + subproblem */ + double eff; + /* cut efficacy (normalized residual) */ + double deg; + /* lower bound to objective degradation */ +}; + +static int CDECL fcmp(const void *arg1, const void *arg2) +{ const struct info *info1 = arg1, *info2 = arg2; + if (info1->deg == 0.0 && info2->deg == 0.0) + { if (info1->eff > info2->eff) return -1; + if (info1->eff < info2->eff) return +1; + } + else + { if (info1->deg > info2->deg) return -1; + if (info1->deg < info2->deg) return +1; + } + return 0; +} + +static double parallel(IOSCUT *a, IOSCUT *b, double work[]); + +#ifdef NEW_LOCAL /* 02/II-2018 */ +void ios_process_cuts(glp_tree *T) +{ IOSPOOL *pool; + IOSCUT *cut; + GLPAIJ *aij; + struct info *info; + int k, kk, max_cuts, len, ret, *ind; + double *val, *work, rhs; + /* the current subproblem must exist */ + xassert(T->curr != NULL); + /* the pool must exist and be non-empty */ + pool = T->local; + xassert(pool != NULL); + xassert(pool->m > 0); + /* allocate working arrays */ + info = xcalloc(1+pool->m, sizeof(struct info)); + ind = xcalloc(1+T->n, sizeof(int)); + val = xcalloc(1+T->n, sizeof(double)); + work = xcalloc(1+T->n, sizeof(double)); + for (k = 1; k <= T->n; k++) work[k] = 0.0; + /* build the list of cuts stored in the cut pool */ + for (k = 1; k <= pool->m; k++) + info[k].cut = pool->row[k], info[k].flag = 0; + /* estimate efficiency of all cuts in the cut pool */ + for (k = 1; k <= pool->m; k++) + { double temp, dy, dz; + cut = info[k].cut; + /* build the vector of cut coefficients and compute its + Euclidean norm */ + len = 0; temp = 0.0; + for (aij = cut->ptr; aij != NULL; aij = aij->r_next) + { xassert(1 <= aij->col->j && aij->col->j <= T->n); + len++, ind[len] = aij->col->j, val[len] = aij->val; + temp += aij->val * aij->val; + } + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + /* transform the cut to express it only through non-basic + (auxiliary and structural) variables */ + len = glp_transform_row(T->mip, len, ind, val); + /* determine change in the cut value and in the objective + value for the adjacent basis by simulating one step of the + dual simplex */ + switch (cut->type) + { case GLP_LO: rhs = cut->lb; break; + case GLP_UP: rhs = cut->ub; break; + default: xassert(cut != cut); + } + ret = _glp_analyze_row(T->mip, len, ind, val, cut->type, + rhs, 1e-9, NULL, NULL, NULL, NULL, &dy, &dz); + /* determine normalized residual and lower bound to objective + degradation */ + if (ret == 0) + { info[k].eff = fabs(dy) / sqrt(temp); + /* if some reduced costs violates (slightly) their zero + bounds (i.e. have wrong signs) due to round-off errors, + dz also may have wrong sign being close to zero */ + if (T->mip->dir == GLP_MIN) + { if (dz < 0.0) dz = 0.0; + info[k].deg = + dz; + } + else /* GLP_MAX */ + { if (dz > 0.0) dz = 0.0; + info[k].deg = - dz; + } + } + else if (ret == 1) + { /* the constraint is not violated at the current point */ + info[k].eff = info[k].deg = 0.0; + } + else if (ret == 2) + { /* no dual feasible adjacent basis exists */ + info[k].eff = 1.0; + info[k].deg = DBL_MAX; + } + else + xassert(ret != ret); + /* if the degradation is too small, just ignore it */ + if (info[k].deg < 0.01) info[k].deg = 0.0; + } + /* sort the list of cuts by decreasing objective degradation and + then by decreasing efficacy */ + qsort(&info[1], pool->m, sizeof(struct info), fcmp); + /* only first (most efficient) max_cuts in the list are qualified + as candidates to be added to the current subproblem */ + max_cuts = (T->curr->level == 0 ? 90 : 10); + if (max_cuts > pool->m) max_cuts = pool->m; + /* add cuts to the current subproblem */ +#if 0 + xprintf("*** adding cuts ***\n"); +#endif + for (k = 1; k <= max_cuts; k++) + { int i, len; + /* if this cut seems to be inefficient, skip it */ + if (info[k].deg < 0.01 && info[k].eff < 0.01) continue; + /* if the angle between this cut and every other cut included + in the current subproblem is small, skip this cut */ + for (kk = 1; kk < k; kk++) + { if (info[kk].flag) + { if (parallel(info[k].cut, info[kk].cut, work) > 0.90) + break; + } + } + if (kk < k) continue; + /* add this cut to the current subproblem */ +#if 0 + xprintf("eff = %g; deg = %g\n", info[k].eff, info[k].deg); +#endif + cut = info[k].cut, info[k].flag = 1; + i = glp_add_rows(T->mip, 1); + if (cut->name != NULL) + glp_set_row_name(T->mip, i, cut->name); + xassert(T->mip->row[i]->origin == GLP_RF_CUT); + T->mip->row[i]->klass = cut->klass; + len = 0; + for (aij = cut->ptr; aij != NULL; aij = aij->r_next) + len++, ind[len] = aij->col->j, val[len] = aij->val; + glp_set_mat_row(T->mip, i, len, ind, val); + switch (cut->type) + { case GLP_LO: rhs = cut->lb; break; + case GLP_UP: rhs = cut->ub; break; + default: xassert(cut != cut); + } + glp_set_row_bnds(T->mip, i, cut->type, rhs, rhs); + } + /* free working arrays */ + xfree(info); + xfree(ind); + xfree(val); + xfree(work); + return; +} +#else +void ios_process_cuts(glp_tree *T) +{ IOSPOOL *pool; + IOSCUT *cut; + IOSAIJ *aij; + struct info *info; + int k, kk, max_cuts, len, ret, *ind; + double *val, *work; + /* the current subproblem must exist */ + xassert(T->curr != NULL); + /* the pool must exist and be non-empty */ + pool = T->local; + xassert(pool != NULL); + xassert(pool->size > 0); + /* allocate working arrays */ + info = xcalloc(1+pool->size, sizeof(struct info)); + ind = xcalloc(1+T->n, sizeof(int)); + val = xcalloc(1+T->n, sizeof(double)); + work = xcalloc(1+T->n, sizeof(double)); + for (k = 1; k <= T->n; k++) work[k] = 0.0; + /* build the list of cuts stored in the cut pool */ + for (k = 0, cut = pool->head; cut != NULL; cut = cut->next) + k++, info[k].cut = cut, info[k].flag = 0; + xassert(k == pool->size); + /* estimate efficiency of all cuts in the cut pool */ + for (k = 1; k <= pool->size; k++) + { double temp, dy, dz; + cut = info[k].cut; + /* build the vector of cut coefficients and compute its + Euclidean norm */ + len = 0; temp = 0.0; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + { xassert(1 <= aij->j && aij->j <= T->n); + len++, ind[len] = aij->j, val[len] = aij->val; + temp += aij->val * aij->val; + } + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + /* transform the cut to express it only through non-basic + (auxiliary and structural) variables */ + len = glp_transform_row(T->mip, len, ind, val); + /* determine change in the cut value and in the objective + value for the adjacent basis by simulating one step of the + dual simplex */ + ret = _glp_analyze_row(T->mip, len, ind, val, cut->type, + cut->rhs, 1e-9, NULL, NULL, NULL, NULL, &dy, &dz); + /* determine normalized residual and lower bound to objective + degradation */ + if (ret == 0) + { info[k].eff = fabs(dy) / sqrt(temp); + /* if some reduced costs violates (slightly) their zero + bounds (i.e. have wrong signs) due to round-off errors, + dz also may have wrong sign being close to zero */ + if (T->mip->dir == GLP_MIN) + { if (dz < 0.0) dz = 0.0; + info[k].deg = + dz; + } + else /* GLP_MAX */ + { if (dz > 0.0) dz = 0.0; + info[k].deg = - dz; + } + } + else if (ret == 1) + { /* the constraint is not violated at the current point */ + info[k].eff = info[k].deg = 0.0; + } + else if (ret == 2) + { /* no dual feasible adjacent basis exists */ + info[k].eff = 1.0; + info[k].deg = DBL_MAX; + } + else + xassert(ret != ret); + /* if the degradation is too small, just ignore it */ + if (info[k].deg < 0.01) info[k].deg = 0.0; + } + /* sort the list of cuts by decreasing objective degradation and + then by decreasing efficacy */ + qsort(&info[1], pool->size, sizeof(struct info), fcmp); + /* only first (most efficient) max_cuts in the list are qualified + as candidates to be added to the current subproblem */ + max_cuts = (T->curr->level == 0 ? 90 : 10); + if (max_cuts > pool->size) max_cuts = pool->size; + /* add cuts to the current subproblem */ +#if 0 + xprintf("*** adding cuts ***\n"); +#endif + for (k = 1; k <= max_cuts; k++) + { int i, len; + /* if this cut seems to be inefficient, skip it */ + if (info[k].deg < 0.01 && info[k].eff < 0.01) continue; + /* if the angle between this cut and every other cut included + in the current subproblem is small, skip this cut */ + for (kk = 1; kk < k; kk++) + { if (info[kk].flag) + { if (parallel(info[k].cut, info[kk].cut, work) > 0.90) + break; + } + } + if (kk < k) continue; + /* add this cut to the current subproblem */ +#if 0 + xprintf("eff = %g; deg = %g\n", info[k].eff, info[k].deg); +#endif + cut = info[k].cut, info[k].flag = 1; + i = glp_add_rows(T->mip, 1); + if (cut->name != NULL) + glp_set_row_name(T->mip, i, cut->name); + xassert(T->mip->row[i]->origin == GLP_RF_CUT); + T->mip->row[i]->klass = cut->klass; + len = 0; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + len++, ind[len] = aij->j, val[len] = aij->val; + glp_set_mat_row(T->mip, i, len, ind, val); + xassert(cut->type == GLP_LO || cut->type == GLP_UP); + glp_set_row_bnds(T->mip, i, cut->type, cut->rhs, cut->rhs); + } + /* free working arrays */ + xfree(info); + xfree(ind); + xfree(val); + xfree(work); + return; +} +#endif + +#if 0 +/*********************************************************************** +* Given a cut a * x >= b (<= b) the routine efficacy computes the cut +* efficacy as follows: +* +* eff = d * (a * x~ - b) / ||a||, +* +* where d is -1 (in case of '>= b') or +1 (in case of '<= b'), x~ is +* the vector of values of structural variables in optimal solution to +* LP relaxation of the current subproblem, ||a|| is the Euclidean norm +* of the vector of cut coefficients. +* +* If the cut is violated at point x~, the efficacy eff is positive, +* and its value is the Euclidean distance between x~ and the cut plane +* a * x = b in the space of structural variables. +* +* Following geometrical intuition, it is quite natural to consider +* this distance as a first-order measure of the expected efficacy of +* the cut: the larger the distance the better the cut [1]. */ + +static double efficacy(glp_tree *T, IOSCUT *cut) +{ glp_prob *mip = T->mip; + IOSAIJ *aij; + double s = 0.0, t = 0.0, temp; + for (aij = cut->ptr; aij != NULL; aij = aij->next) + { xassert(1 <= aij->j && aij->j <= mip->n); + s += aij->val * mip->col[aij->j]->prim; + t += aij->val * aij->val; + } + temp = sqrt(t); + if (temp < DBL_EPSILON) temp = DBL_EPSILON; + if (cut->type == GLP_LO) + temp = (s >= cut->rhs ? 0.0 : (cut->rhs - s) / temp); + else if (cut->type == GLP_UP) + temp = (s <= cut->rhs ? 0.0 : (s - cut->rhs) / temp); + else + xassert(cut != cut); + return temp; +} +#endif + +/*********************************************************************** +* Given two cuts a1 * x >= b1 (<= b1) and a2 * x >= b2 (<= b2) the +* routine parallel computes the cosine of angle between the cut planes +* a1 * x = b1 and a2 * x = b2 (which is the acute angle between two +* normals to these planes) in the space of structural variables as +* follows: +* +* cos phi = (a1' * a2) / (||a1|| * ||a2||), +* +* where (a1' * a2) is a dot product of vectors of cut coefficients, +* ||a1|| and ||a2|| are Euclidean norms of vectors a1 and a2. +* +* Note that requirement cos phi = 0 forces the cuts to be orthogonal, +* i.e. with disjoint support, while requirement cos phi <= 0.999 means +* only avoiding duplicate (parallel) cuts [1]. */ + +#ifdef NEW_LOCAL /* 02/II-2018 */ +static double parallel(IOSCUT *a, IOSCUT *b, double work[]) +{ GLPAIJ *aij; + double s = 0.0, sa = 0.0, sb = 0.0, temp; + for (aij = a->ptr; aij != NULL; aij = aij->r_next) + { work[aij->col->j] = aij->val; + sa += aij->val * aij->val; + } + for (aij = b->ptr; aij != NULL; aij = aij->r_next) + { s += work[aij->col->j] * aij->val; + sb += aij->val * aij->val; + } + for (aij = a->ptr; aij != NULL; aij = aij->r_next) + work[aij->col->j] = 0.0; + temp = sqrt(sa) * sqrt(sb); + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + return s / temp; +} +#else +static double parallel(IOSCUT *a, IOSCUT *b, double work[]) +{ IOSAIJ *aij; + double s = 0.0, sa = 0.0, sb = 0.0, temp; + for (aij = a->ptr; aij != NULL; aij = aij->next) + { work[aij->j] = aij->val; + sa += aij->val * aij->val; + } + for (aij = b->ptr; aij != NULL; aij = aij->next) + { s += work[aij->j] * aij->val; + sb += aij->val * aij->val; + } + for (aij = a->ptr; aij != NULL; aij = aij->next) + work[aij->j] = 0.0; + temp = sqrt(sa) * sqrt(sb); + if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; + return s / temp; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios12.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios12.c new file mode 100644 index 000000000..bec6fa2c4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpios12.c @@ -0,0 +1,177 @@ +/* glpios12.c (node selection heuristics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" + +/*********************************************************************** +* NAME +* +* ios_choose_node - select subproblem to continue the search +* +* SYNOPSIS +* +* #include "glpios.h" +* int ios_choose_node(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_choose_node selects a subproblem from the active +* list to continue the search. The choice depends on the backtracking +* technique option. +* +* RETURNS +* +* The routine ios_choose_node return the reference number of the +* subproblem selected. */ + +static int most_feas(glp_tree *T); +static int best_proj(glp_tree *T); +static int best_node(glp_tree *T); + +int ios_choose_node(glp_tree *T) +{ int p; + if (T->parm->bt_tech == GLP_BT_DFS) + { /* depth first search */ + xassert(T->tail != NULL); + p = T->tail->p; + } + else if (T->parm->bt_tech == GLP_BT_BFS) + { /* breadth first search */ + xassert(T->head != NULL); + p = T->head->p; + } + else if (T->parm->bt_tech == GLP_BT_BLB) + { /* select node with best local bound */ + p = best_node(T); + } + else if (T->parm->bt_tech == GLP_BT_BPH) + { if (T->mip->mip_stat == GLP_UNDEF) + { /* "most integer feasible" subproblem */ + p = most_feas(T); + } + else + { /* best projection heuristic */ + p = best_proj(T); + } + } + else + xassert(T != T); + return p; +} + +static int most_feas(glp_tree *T) +{ /* select subproblem whose parent has minimal sum of integer + infeasibilities */ + IOSNPD *node; + int p; + double best; + p = 0, best = DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + { xassert(node->up != NULL); + if (best > node->up->ii_sum) + p = node->p, best = node->up->ii_sum; + } + return p; +} + +static int best_proj(glp_tree *T) +{ /* select subproblem using the best projection heuristic */ + IOSNPD *root, *node; + int p; + double best, deg, obj; + /* the global bound must exist */ + xassert(T->mip->mip_stat == GLP_FEAS); + /* obtain pointer to the root node, which must exist */ + root = T->slot[1].node; + xassert(root != NULL); + /* deg estimates degradation of the objective function per unit + of the sum of integer infeasibilities */ + xassert(root->ii_sum > 0.0); + deg = (T->mip->mip_obj - root->bound) / root->ii_sum; + /* nothing has been selected so far */ + p = 0, best = DBL_MAX; + /* walk through the list of active subproblems */ + for (node = T->head; node != NULL; node = node->next) + { xassert(node->up != NULL); + /* obj estimates optimal objective value if the sum of integer + infeasibilities were zero */ + obj = node->up->bound + deg * node->up->ii_sum; + if (T->mip->dir == GLP_MAX) obj = - obj; + /* select the subproblem which has the best estimated optimal + objective value */ + if (best > obj) p = node->p, best = obj; + } + return p; +} + +static int best_node(glp_tree *T) +{ /* select subproblem with best local bound */ + IOSNPD *node, *best = NULL; + double bound, eps; + switch (T->mip->dir) + { case GLP_MIN: + bound = +DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + if (bound > node->bound) bound = node->bound; + xassert(bound != +DBL_MAX); + eps = 1e-10 * (1.0 + fabs(bound)); + for (node = T->head; node != NULL; node = node->next) + { if (node->bound <= bound + eps) + { xassert(node->up != NULL); + if (best == NULL || +#if 1 + best->up->ii_sum > node->up->ii_sum) best = node; +#else + best->lp_obj > node->lp_obj) best = node; +#endif + } + } + break; + case GLP_MAX: + bound = -DBL_MAX; + for (node = T->head; node != NULL; node = node->next) + if (bound < node->bound) bound = node->bound; + xassert(bound != -DBL_MAX); + eps = 1e-10 * (1.0 + fabs(bound)); + for (node = T->head; node != NULL; node = node->next) + { if (node->bound >= bound - eps) + { xassert(node->up != NULL); + if (best == NULL || +#if 1 + best->up->ii_sum > node->up->ii_sum) best = node; +#else + best->lp_obj < node->lp_obj) best = node; +#endif + } + } + break; + default: + xassert(T != T); + } + xassert(best != NULL); + return best->p; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.c new file mode 100644 index 000000000..2b3a81762 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.c @@ -0,0 +1,1144 @@ +/* glpipm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpipm.h" +#include "glpmat.h" + +#define ITER_MAX 100 +/* maximal number of iterations */ + +struct csa +{ /* common storage area */ + /*--------------------------------------------------------------*/ + /* LP data */ + int m; + /* number of rows (equality constraints) */ + int n; + /* number of columns (structural variables) */ + int *A_ptr; /* int A_ptr[1+m+1]; */ + int *A_ind; /* int A_ind[A_ptr[m+1]]; */ + double *A_val; /* double A_val[A_ptr[m+1]]; */ + /* mxn-matrix A in storage-by-rows format */ + double *b; /* double b[1+m]; */ + /* m-vector b of right-hand sides */ + double *c; /* double c[1+n]; */ + /* n-vector c of objective coefficients; c[0] is constant term of + the objective function */ + /*--------------------------------------------------------------*/ + /* LP solution */ + double *x; /* double x[1+n]; */ + double *y; /* double y[1+m]; */ + double *z; /* double z[1+n]; */ + /* current point in primal-dual space; the best point on exit */ + /*--------------------------------------------------------------*/ + /* control parameters */ + const glp_iptcp *parm; + /*--------------------------------------------------------------*/ + /* working arrays and variables */ + double *D; /* double D[1+n]; */ + /* diagonal nxn-matrix D = X*inv(Z), where X = diag(x[j]) and + Z = diag(z[j]) */ + int *P; /* int P[1+m+m]; */ + /* permutation mxm-matrix P used to minimize fill-in in Cholesky + factorization */ + int *S_ptr; /* int S_ptr[1+m+1]; */ + int *S_ind; /* int S_ind[S_ptr[m+1]]; */ + double *S_val; /* double S_val[S_ptr[m+1]]; */ + double *S_diag; /* double S_diag[1+m]; */ + /* symmetric mxm-matrix S = P*A*D*A'*P' whose upper triangular + part without diagonal elements is stored in S_ptr, S_ind, and + S_val in storage-by-rows format, diagonal elements are stored + in S_diag */ + int *U_ptr; /* int U_ptr[1+m+1]; */ + int *U_ind; /* int U_ind[U_ptr[m+1]]; */ + double *U_val; /* double U_val[U_ptr[m+1]]; */ + double *U_diag; /* double U_diag[1+m]; */ + /* upper triangular mxm-matrix U defining Cholesky factorization + S = U'*U; its non-diagonal elements are stored in U_ptr, U_ind, + U_val in storage-by-rows format, diagonal elements are stored + in U_diag */ + int iter; + /* iteration number (0, 1, 2, ...); iter = 0 corresponds to the + initial point */ + double obj; + /* current value of the objective function */ + double rpi; + /* relative primal infeasibility rpi = ||A*x-b||/(1+||b||) */ + double rdi; + /* relative dual infeasibility rdi = ||A'*y+z-c||/(1+||c||) */ + double gap; + /* primal-dual gap = |c'*x-b'*y|/(1+|c'*x|) which is a relative + difference between primal and dual objective functions */ + double phi; + /* merit function phi = ||A*x-b||/max(1,||b||) + + + ||A'*y+z-c||/max(1,||c||) + + + |c'*x-b'*y|/max(1,||b||,||c||) */ + double mu; + /* duality measure mu = x'*z/n (used as barrier parameter) */ + double rmu; + /* rmu = max(||A*x-b||,||A'*y+z-c||)/mu */ + double rmu0; + /* the initial value of rmu on iteration 0 */ + double *phi_min; /* double phi_min[1+ITER_MAX]; */ + /* phi_min[k] = min(phi[k]), where phi[k] is the value of phi on + k-th iteration, 0 <= k <= iter */ + int best_iter; + /* iteration number, on which the value of phi reached its best + (minimal) value */ + double *best_x; /* double best_x[1+n]; */ + double *best_y; /* double best_y[1+m]; */ + double *best_z; /* double best_z[1+n]; */ + /* best point (in the sense of the merit function phi) which has + been reached on iteration iter_best */ + double best_obj; + /* objective value at the best point */ + double *dx_aff; /* double dx_aff[1+n]; */ + double *dy_aff; /* double dy_aff[1+m]; */ + double *dz_aff; /* double dz_aff[1+n]; */ + /* affine scaling direction */ + double alfa_aff_p, alfa_aff_d; + /* maximal primal and dual stepsizes in affine scaling direction, + on which x and z are still non-negative */ + double mu_aff; + /* duality measure mu_aff = x_aff'*z_aff/n in the boundary point + x_aff' = x+alfa_aff_p*dx_aff, z_aff' = z+alfa_aff_d*dz_aff */ + double sigma; + /* Mehrotra's heuristic parameter (0 <= sigma <= 1) */ + double *dx_cc; /* double dx_cc[1+n]; */ + double *dy_cc; /* double dy_cc[1+m]; */ + double *dz_cc; /* double dz_cc[1+n]; */ + /* centering corrector direction */ + double *dx; /* double dx[1+n]; */ + double *dy; /* double dy[1+m]; */ + double *dz; /* double dz[1+n]; */ + /* final combined direction dx = dx_aff+dx_cc, dy = dy_aff+dy_cc, + dz = dz_aff+dz_cc */ + double alfa_max_p; + double alfa_max_d; + /* maximal primal and dual stepsizes in combined direction, on + which x and z are still non-negative */ +}; + +/*********************************************************************** +* initialize - allocate and initialize common storage area +* +* This routine allocates and initializes the common storage area (CSA) +* used by interior-point method routines. */ + +static void initialize(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int i; + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix A has %d non-zeros\n", csa->A_ptr[m+1]-1); + csa->D = xcalloc(1+n, sizeof(double)); + /* P := I */ + csa->P = xcalloc(1+m+m, sizeof(int)); + for (i = 1; i <= m; i++) csa->P[i] = csa->P[m+i] = i; + /* S := A*A', symbolically */ + csa->S_ptr = xcalloc(1+m+1, sizeof(int)); + csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, + csa->S_ptr); + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix S = A*A' has %d non-zeros (upper triangle)\n", + csa->S_ptr[m+1]-1 + m); + /* determine P using specified ordering algorithm */ + if (csa->parm->ord_alg == GLP_ORD_NONE) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Original ordering is being used\n"); + for (i = 1; i <= m; i++) + csa->P[i] = csa->P[m+i] = i; + } + else if (csa->parm->ord_alg == GLP_ORD_QMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Minimum degree ordering (QMD)...\n"); + min_degree(m, csa->S_ptr, csa->S_ind, csa->P); + } + else if (csa->parm->ord_alg == GLP_ORD_AMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Approximate minimum degree ordering (AMD)...\n"); + amd_order1(m, csa->S_ptr, csa->S_ind, csa->P); + } + else if (csa->parm->ord_alg == GLP_ORD_SYMAMD) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Approximate minimum degree ordering (SYMAMD)...\n") + ; + symamd_ord(m, csa->S_ptr, csa->S_ind, csa->P); + } + else + xassert(csa != csa); + /* S := P*A*A'*P', symbolically */ + xfree(csa->S_ind); + csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, + csa->S_ptr); + csa->S_val = xcalloc(csa->S_ptr[m+1], sizeof(double)); + csa->S_diag = xcalloc(1+m, sizeof(double)); + /* compute Cholesky factorization S = U'*U, symbolically */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Computing Cholesky factorization S = L*L'...\n"); + csa->U_ptr = xcalloc(1+m+1, sizeof(int)); + csa->U_ind = chol_symbolic(m, csa->S_ptr, csa->S_ind, csa->U_ptr); + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Matrix L has %d non-zeros\n", csa->U_ptr[m+1]-1 + m); + csa->U_val = xcalloc(csa->U_ptr[m+1], sizeof(double)); + csa->U_diag = xcalloc(1+m, sizeof(double)); + csa->iter = 0; + csa->obj = 0.0; + csa->rpi = 0.0; + csa->rdi = 0.0; + csa->gap = 0.0; + csa->phi = 0.0; + csa->mu = 0.0; + csa->rmu = 0.0; + csa->rmu0 = 0.0; + csa->phi_min = xcalloc(1+ITER_MAX, sizeof(double)); + csa->best_iter = 0; + csa->best_x = xcalloc(1+n, sizeof(double)); + csa->best_y = xcalloc(1+m, sizeof(double)); + csa->best_z = xcalloc(1+n, sizeof(double)); + csa->best_obj = 0.0; + csa->dx_aff = xcalloc(1+n, sizeof(double)); + csa->dy_aff = xcalloc(1+m, sizeof(double)); + csa->dz_aff = xcalloc(1+n, sizeof(double)); + csa->alfa_aff_p = 0.0; + csa->alfa_aff_d = 0.0; + csa->mu_aff = 0.0; + csa->sigma = 0.0; + csa->dx_cc = xcalloc(1+n, sizeof(double)); + csa->dy_cc = xcalloc(1+m, sizeof(double)); + csa->dz_cc = xcalloc(1+n, sizeof(double)); + csa->dx = csa->dx_aff; + csa->dy = csa->dy_aff; + csa->dz = csa->dz_aff; + csa->alfa_max_p = 0.0; + csa->alfa_max_d = 0.0; + return; +} + +/*********************************************************************** +* A_by_vec - compute y = A*x +* +* This routine computes matrix-vector product y = A*x, where A is the +* constraint matrix. */ + +static void A_by_vec(struct csa *csa, double x[], double y[]) +{ /* compute y = A*x */ + int m = csa->m; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int i, t, beg, end; + double temp; + for (i = 1; i <= m; i++) + { temp = 0.0; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) temp += A_val[t] * x[A_ind[t]]; + y[i] = temp; + } + return; +} + +/*********************************************************************** +* AT_by_vec - compute y = A'*x +* +* This routine computes matrix-vector product y = A'*x, where A' is a +* matrix transposed to the constraint matrix A. */ + +static void AT_by_vec(struct csa *csa, double x[], double y[]) +{ /* compute y = A'*x, where A' is transposed to A */ + int m = csa->m; + int n = csa->n; + int *A_ptr = csa->A_ptr; + int *A_ind = csa->A_ind; + double *A_val = csa->A_val; + int i, j, t, beg, end; + double temp; + for (j = 1; j <= n; j++) y[j] = 0.0; + for (i = 1; i <= m; i++) + { temp = x[i]; + if (temp == 0.0) continue; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) y[A_ind[t]] += A_val[t] * temp; + } + return; +} + +/*********************************************************************** +* decomp_NE - numeric factorization of matrix S = P*A*D*A'*P' +* +* This routine implements numeric phase of Cholesky factorization of +* the matrix S = P*A*D*A'*P', which is a permuted matrix of the normal +* equation system. Matrix D is assumed to be already computed. */ + +static void decomp_NE(struct csa *csa) +{ adat_numeric(csa->m, csa->n, csa->P, csa->A_ptr, csa->A_ind, + csa->A_val, csa->D, csa->S_ptr, csa->S_ind, csa->S_val, + csa->S_diag); + chol_numeric(csa->m, csa->S_ptr, csa->S_ind, csa->S_val, + csa->S_diag, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag); + return; +} + +/*********************************************************************** +* solve_NE - solve normal equation system +* +* This routine solves the normal equation system: +* +* A*D*A'*y = h. +* +* It is assumed that the matrix A*D*A' has been previously factorized +* by the routine decomp_NE. +* +* On entry the array y contains the vector of right-hand sides h. On +* exit this array contains the computed vector of unknowns y. +* +* Once the vector y has been computed the routine checks for numeric +* stability. If the residual vector: +* +* r = A*D*A'*y - h +* +* is relatively small, the routine returns zero, otherwise non-zero is +* returned. */ + +static int solve_NE(struct csa *csa, double y[]) +{ int m = csa->m; + int n = csa->n; + int *P = csa->P; + int i, j, ret = 0; + double *h, *r, *w; + /* save vector of right-hand sides h */ + h = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) h[i] = y[i]; + /* solve normal equation system (A*D*A')*y = h */ + /* since S = P*A*D*A'*P' = U'*U, then A*D*A' = P'*U'*U*P, so we + have inv(A*D*A') = P'*inv(U)*inv(U')*P */ + /* w := P*h */ + w = xcalloc(1+m, sizeof(double)); + for (i = 1; i <= m; i++) w[i] = y[P[i]]; + /* w := inv(U')*w */ + ut_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); + /* w := inv(U)*w */ + u_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); + /* y := P'*w */ + for (i = 1; i <= m; i++) y[i] = w[P[m+i]]; + xfree(w); + /* compute residual vector r = A*D*A'*y - h */ + r = xcalloc(1+m, sizeof(double)); + /* w := A'*y */ + w = xcalloc(1+n, sizeof(double)); + AT_by_vec(csa, y, w); + /* w := D*w */ + for (j = 1; j <= n; j++) w[j] *= csa->D[j]; + /* r := A*w */ + A_by_vec(csa, w, r); + xfree(w); + /* r := r - h */ + for (i = 1; i <= m; i++) r[i] -= h[i]; + /* check for numeric stability */ + for (i = 1; i <= m; i++) + { if (fabs(r[i]) / (1.0 + fabs(h[i])) > 1e-4) + { ret = 1; + break; + } + } + xfree(h); + xfree(r); + return ret; +} + +/*********************************************************************** +* solve_NS - solve Newtonian system +* +* This routine solves the Newtonian system: +* +* A*dx = p +* +* A'*dy + dz = q +* +* Z*dx + X*dz = r +* +* where X = diag(x[j]), Z = diag(z[j]), by reducing it to the normal +* equation system: +* +* (A*inv(Z)*X*A')*dy = A*inv(Z)*(X*q-r)+p +* +* (it is assumed that the matrix A*inv(Z)*X*A' has been factorized by +* the routine decomp_NE). +* +* Once vector dy has been computed the routine computes vectors dx and +* dz as follows: +* +* dx = inv(Z)*(X*(A'*dy-q)+r) +* +* dz = inv(X)*(r-Z*dx) +* +* The routine solve_NS returns the same code which was reported by the +* routine solve_NE (see above). */ + +static int solve_NS(struct csa *csa, double p[], double q[], double r[], + double dx[], double dy[], double dz[]) +{ int m = csa->m; + int n = csa->n; + double *x = csa->x; + double *z = csa->z; + int i, j, ret; + double *w = dx; + /* compute the vector of right-hand sides A*inv(Z)*(X*q-r)+p for + the normal equation system */ + for (j = 1; j <= n; j++) + w[j] = (x[j] * q[j] - r[j]) / z[j]; + A_by_vec(csa, w, dy); + for (i = 1; i <= m; i++) dy[i] += p[i]; + /* solve the normal equation system to compute vector dy */ + ret = solve_NE(csa, dy); + /* compute vectors dx and dz */ + AT_by_vec(csa, dy, dx); + for (j = 1; j <= n; j++) + { dx[j] = (x[j] * (dx[j] - q[j]) + r[j]) / z[j]; + dz[j] = (r[j] - z[j] * dx[j]) / x[j]; + } + return ret; +} + +/*********************************************************************** +* initial_point - choose initial point using Mehrotra's heuristic +* +* This routine chooses a starting point using a heuristic proposed in +* the paper: +* +* S. Mehrotra. On the implementation of a primal-dual interior point +* method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. +* +* The starting point x in the primal space is chosen as a solution of +* the following least squares problem: +* +* minimize ||x|| +* +* subject to A*x = b +* +* which can be computed explicitly as follows: +* +* x = A'*inv(A*A')*b +* +* Similarly, the starting point (y, z) in the dual space is chosen as +* a solution of the following least squares problem: +* +* minimize ||z|| +* +* subject to A'*y + z = c +* +* which can be computed explicitly as follows: +* +* y = inv(A*A')*A*c +* +* z = c - A'*y +* +* However, some components of the vectors x and z may be non-positive +* or close to zero, so the routine uses a Mehrotra's heuristic to find +* a more appropriate starting point. */ + +static void initial_point(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + double *D = csa->D; + int i, j; + double dp, dd, ex, ez, xz; + /* factorize A*A' */ + for (j = 1; j <= n; j++) D[j] = 1.0; + decomp_NE(csa); + /* x~ = A'*inv(A*A')*b */ + for (i = 1; i <= m; i++) y[i] = b[i]; + solve_NE(csa, y); + AT_by_vec(csa, y, x); + /* y~ = inv(A*A')*A*c */ + A_by_vec(csa, c, y); + solve_NE(csa, y); + /* z~ = c - A'*y~ */ + AT_by_vec(csa, y,z); + for (j = 1; j <= n; j++) z[j] = c[j] - z[j]; + /* use Mehrotra's heuristic in order to choose more appropriate + starting point with positive components of vectors x and z */ + dp = dd = 0.0; + for (j = 1; j <= n; j++) + { if (dp < -1.5 * x[j]) dp = -1.5 * x[j]; + if (dd < -1.5 * z[j]) dd = -1.5 * z[j]; + } + /* note that b = 0 involves x = 0, and c = 0 involves y = 0 and + z = 0, so we need to be careful */ + if (dp == 0.0) dp = 1.5; + if (dd == 0.0) dd = 1.5; + ex = ez = xz = 0.0; + for (j = 1; j <= n; j++) + { ex += (x[j] + dp); + ez += (z[j] + dd); + xz += (x[j] + dp) * (z[j] + dd); + } + dp += 0.5 * (xz / ez); + dd += 0.5 * (xz / ex); + for (j = 1; j <= n; j++) + { x[j] += dp; + z[j] += dd; + xassert(x[j] > 0.0 && z[j] > 0.0); + } + return; +} + +/*********************************************************************** +* basic_info - perform basic computations at the current point +* +* This routine computes the following quantities at the current point: +* +* 1) value of the objective function: +* +* F = c'*x + c[0] +* +* 2) relative primal infeasibility: +* +* rpi = ||A*x-b|| / (1+||b||) +* +* 3) relative dual infeasibility: +* +* rdi = ||A'*y+z-c|| / (1+||c||) +* +* 4) primal-dual gap (relative difference between the primal and the +* dual objective function values): +* +* gap = |c'*x-b'*y| / (1+|c'*x|) +* +* 5) merit function: +* +* phi = ||A*x-b|| / max(1,||b||) + ||A'*y+z-c|| / max(1,||c||) + +* +* + |c'*x-b'*y| / max(1,||b||,||c||) +* +* 6) duality measure: +* +* mu = x'*z / n +* +* 7) the ratio of infeasibility to mu: +* +* rmu = max(||A*x-b||,||A'*y+z-c||) / mu +* +* where ||*|| denotes euclidian norm, *' denotes transposition. */ + +static void basic_info(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + int i, j; + double norm1, bnorm, norm2, cnorm, cx, by, *work, temp; + /* compute value of the objective function */ + temp = c[0]; + for (j = 1; j <= n; j++) temp += c[j] * x[j]; + csa->obj = temp; + /* norm1 = ||A*x-b|| */ + work = xcalloc(1+m, sizeof(double)); + A_by_vec(csa, x, work); + norm1 = 0.0; + for (i = 1; i <= m; i++) + norm1 += (work[i] - b[i]) * (work[i] - b[i]); + norm1 = sqrt(norm1); + xfree(work); + /* bnorm = ||b|| */ + bnorm = 0.0; + for (i = 1; i <= m; i++) bnorm += b[i] * b[i]; + bnorm = sqrt(bnorm); + /* compute relative primal infeasibility */ + csa->rpi = norm1 / (1.0 + bnorm); + /* norm2 = ||A'*y+z-c|| */ + work = xcalloc(1+n, sizeof(double)); + AT_by_vec(csa, y, work); + norm2 = 0.0; + for (j = 1; j <= n; j++) + norm2 += (work[j] + z[j] - c[j]) * (work[j] + z[j] - c[j]); + norm2 = sqrt(norm2); + xfree(work); + /* cnorm = ||c|| */ + cnorm = 0.0; + for (j = 1; j <= n; j++) cnorm += c[j] * c[j]; + cnorm = sqrt(cnorm); + /* compute relative dual infeasibility */ + csa->rdi = norm2 / (1.0 + cnorm); + /* by = b'*y */ + by = 0.0; + for (i = 1; i <= m; i++) by += b[i] * y[i]; + /* cx = c'*x */ + cx = 0.0; + for (j = 1; j <= n; j++) cx += c[j] * x[j]; + /* compute primal-dual gap */ + csa->gap = fabs(cx - by) / (1.0 + fabs(cx)); + /* compute merit function */ + csa->phi = 0.0; + csa->phi += norm1 / (bnorm > 1.0 ? bnorm : 1.0); + csa->phi += norm2 / (cnorm > 1.0 ? cnorm : 1.0); + temp = 1.0; + if (temp < bnorm) temp = bnorm; + if (temp < cnorm) temp = cnorm; + csa->phi += fabs(cx - by) / temp; + /* compute duality measure */ + temp = 0.0; + for (j = 1; j <= n; j++) temp += x[j] * z[j]; + csa->mu = temp / (double)n; + /* compute the ratio of infeasibility to mu */ + csa->rmu = (norm1 > norm2 ? norm1 : norm2) / csa->mu; + return; +} + +/*********************************************************************** +* make_step - compute next point using Mehrotra's technique +* +* This routine computes the next point using the predictor-corrector +* technique proposed in the paper: +* +* S. Mehrotra. On the implementation of a primal-dual interior point +* method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. +* +* At first, the routine computes so called affine scaling (predictor) +* direction (dx_aff,dy_aff,dz_aff) which is a solution of the system: +* +* A*dx_aff = b - A*x +* +* A'*dy_aff + dz_aff = c - A'*y - z +* +* Z*dx_aff + X*dz_aff = - X*Z*e +* +* where (x,y,z) is the current point, X = diag(x[j]), Z = diag(z[j]), +* e = (1,...,1)'. +* +* Then, the routine computes the centering parameter sigma, using the +* following Mehrotra's heuristic: +* +* alfa_aff_p = inf{0 <= alfa <= 1 | x+alfa*dx_aff >= 0} +* +* alfa_aff_d = inf{0 <= alfa <= 1 | z+alfa*dz_aff >= 0} +* +* mu_aff = (x+alfa_aff_p*dx_aff)'*(z+alfa_aff_d*dz_aff)/n +* +* sigma = (mu_aff/mu)^3 +* +* where alfa_aff_p is the maximal stepsize along the affine scaling +* direction in the primal space, alfa_aff_d is the maximal stepsize +* along the same direction in the dual space. +* +* After determining sigma the routine computes so called centering +* (corrector) direction (dx_cc,dy_cc,dz_cc) which is the solution of +* the system: +* +* A*dx_cc = 0 +* +* A'*dy_cc + dz_cc = 0 +* +* Z*dx_cc + X*dz_cc = sigma*mu*e - X*Z*e +* +* Finally, the routine computes the combined direction +* +* (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) +* +* and determines maximal primal and dual stepsizes along the combined +* direction: +* +* alfa_max_p = inf{0 <= alfa <= 1 | x+alfa*dx >= 0} +* +* alfa_max_d = inf{0 <= alfa <= 1 | z+alfa*dz >= 0} +* +* In order to prevent the next point to be too close to the boundary +* of the positive ortant, the routine decreases maximal stepsizes: +* +* alfa_p = gamma_p * alfa_max_p +* +* alfa_d = gamma_d * alfa_max_d +* +* where gamma_p and gamma_d are scaling factors, and computes the next +* point: +* +* x_new = x + alfa_p * dx +* +* y_new = y + alfa_d * dy +* +* z_new = z + alfa_d * dz +* +* which becomes the current point on the next iteration. */ + +static int make_step(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + double *b = csa->b; + double *c = csa->c; + double *x = csa->x; + double *y = csa->y; + double *z = csa->z; + double *dx_aff = csa->dx_aff; + double *dy_aff = csa->dy_aff; + double *dz_aff = csa->dz_aff; + double *dx_cc = csa->dx_cc; + double *dy_cc = csa->dy_cc; + double *dz_cc = csa->dz_cc; + double *dx = csa->dx; + double *dy = csa->dy; + double *dz = csa->dz; + int i, j, ret = 0; + double temp, gamma_p, gamma_d, *p, *q, *r; + /* allocate working arrays */ + p = xcalloc(1+m, sizeof(double)); + q = xcalloc(1+n, sizeof(double)); + r = xcalloc(1+n, sizeof(double)); + /* p = b - A*x */ + A_by_vec(csa, x, p); + for (i = 1; i <= m; i++) p[i] = b[i] - p[i]; + /* q = c - A'*y - z */ + AT_by_vec(csa, y,q); + for (j = 1; j <= n; j++) q[j] = c[j] - q[j] - z[j]; + /* r = - X * Z * e */ + for (j = 1; j <= n; j++) r[j] = - x[j] * z[j]; + /* solve the first Newtonian system */ + if (solve_NS(csa, p, q, r, dx_aff, dy_aff, dz_aff)) + { ret = 1; + goto done; + } + /* alfa_aff_p = inf{0 <= alfa <= 1 | x + alfa*dx_aff >= 0} */ + /* alfa_aff_d = inf{0 <= alfa <= 1 | z + alfa*dz_aff >= 0} */ + csa->alfa_aff_p = csa->alfa_aff_d = 1.0; + for (j = 1; j <= n; j++) + { if (dx_aff[j] < 0.0) + { temp = - x[j] / dx_aff[j]; + if (csa->alfa_aff_p > temp) csa->alfa_aff_p = temp; + } + if (dz_aff[j] < 0.0) + { temp = - z[j] / dz_aff[j]; + if (csa->alfa_aff_d > temp) csa->alfa_aff_d = temp; + } + } + /* mu_aff = (x+alfa_aff_p*dx_aff)' * (z+alfa_aff_d*dz_aff) / n */ + temp = 0.0; + for (j = 1; j <= n; j++) + temp += (x[j] + csa->alfa_aff_p * dx_aff[j]) * + (z[j] + csa->alfa_aff_d * dz_aff[j]); + csa->mu_aff = temp / (double)n; + /* sigma = (mu_aff/mu)^3 */ + temp = csa->mu_aff / csa->mu; + csa->sigma = temp * temp * temp; + /* p = 0 */ + for (i = 1; i <= m; i++) p[i] = 0.0; + /* q = 0 */ + for (j = 1; j <= n; j++) q[j] = 0.0; + /* r = sigma * mu * e - X * Z * e */ + for (j = 1; j <= n; j++) + r[j] = csa->sigma * csa->mu - dx_aff[j] * dz_aff[j]; + /* solve the second Newtonian system with the same coefficients + but with altered right-hand sides */ + if (solve_NS(csa, p, q, r, dx_cc, dy_cc, dz_cc)) + { ret = 1; + goto done; + } + /* (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) */ + for (j = 1; j <= n; j++) dx[j] = dx_aff[j] + dx_cc[j]; + for (i = 1; i <= m; i++) dy[i] = dy_aff[i] + dy_cc[i]; + for (j = 1; j <= n; j++) dz[j] = dz_aff[j] + dz_cc[j]; + /* alfa_max_p = inf{0 <= alfa <= 1 | x + alfa*dx >= 0} */ + /* alfa_max_d = inf{0 <= alfa <= 1 | z + alfa*dz >= 0} */ + csa->alfa_max_p = csa->alfa_max_d = 1.0; + for (j = 1; j <= n; j++) + { if (dx[j] < 0.0) + { temp = - x[j] / dx[j]; + if (csa->alfa_max_p > temp) csa->alfa_max_p = temp; + } + if (dz[j] < 0.0) + { temp = - z[j] / dz[j]; + if (csa->alfa_max_d > temp) csa->alfa_max_d = temp; + } + } + /* determine scale factors (not implemented yet) */ + gamma_p = 0.90; + gamma_d = 0.90; + /* compute the next point */ + for (j = 1; j <= n; j++) + { x[j] += gamma_p * csa->alfa_max_p * dx[j]; + xassert(x[j] > 0.0); + } + for (i = 1; i <= m; i++) + y[i] += gamma_d * csa->alfa_max_d * dy[i]; + for (j = 1; j <= n; j++) + { z[j] += gamma_d * csa->alfa_max_d * dz[j]; + xassert(z[j] > 0.0); + } +done: /* free working arrays */ + xfree(p); + xfree(q); + xfree(r); + return ret; +} + +/*********************************************************************** +* terminate - deallocate common storage area +* +* This routine frees all memory allocated to the common storage area +* used by interior-point method routines. */ + +static void terminate(struct csa *csa) +{ xfree(csa->D); + xfree(csa->P); + xfree(csa->S_ptr); + xfree(csa->S_ind); + xfree(csa->S_val); + xfree(csa->S_diag); + xfree(csa->U_ptr); + xfree(csa->U_ind); + xfree(csa->U_val); + xfree(csa->U_diag); + xfree(csa->phi_min); + xfree(csa->best_x); + xfree(csa->best_y); + xfree(csa->best_z); + xfree(csa->dx_aff); + xfree(csa->dy_aff); + xfree(csa->dz_aff); + xfree(csa->dx_cc); + xfree(csa->dy_cc); + xfree(csa->dz_cc); + return; +} + +/*********************************************************************** +* ipm_main - main interior-point method routine +* +* This is a main routine of the primal-dual interior-point method. +* +* The routine ipm_main returns one of the following codes: +* +* 0 - optimal solution found; +* 1 - problem has no feasible (primal or dual) solution; +* 2 - no convergence; +* 3 - iteration limit exceeded; +* 4 - numeric instability on solving Newtonian system. +* +* In case of non-zero return code the routine returns the best point, +* which has been reached during optimization. */ + +static int ipm_main(struct csa *csa) +{ int m = csa->m; + int n = csa->n; + int i, j, status; + double temp; + /* choose initial point using Mehrotra's heuristic */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Guessing initial point...\n"); + initial_point(csa); + /* main loop starts here */ + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Optimization begins...\n"); + for (;;) + { /* perform basic computations at the current point */ + basic_info(csa); + /* save initial value of rmu */ + if (csa->iter == 0) csa->rmu0 = csa->rmu; + /* accumulate values of min(phi[k]) and save the best point */ + xassert(csa->iter <= ITER_MAX); + if (csa->iter == 0 || csa->phi_min[csa->iter-1] > csa->phi) + { csa->phi_min[csa->iter] = csa->phi; + csa->best_iter = csa->iter; + for (j = 1; j <= n; j++) csa->best_x[j] = csa->x[j]; + for (i = 1; i <= m; i++) csa->best_y[i] = csa->y[i]; + for (j = 1; j <= n; j++) csa->best_z[j] = csa->z[j]; + csa->best_obj = csa->obj; + } + else + csa->phi_min[csa->iter] = csa->phi_min[csa->iter-1]; + /* display information at the current point */ + if (csa->parm->msg_lev >= GLP_MSG_ON) + xprintf("%3d: obj = %17.9e; rpi = %8.1e; rdi = %8.1e; gap =" + " %8.1e\n", csa->iter, csa->obj, csa->rpi, csa->rdi, + csa->gap); + /* check if the current point is optimal */ + if (csa->rpi < 1e-8 && csa->rdi < 1e-8 && csa->gap < 1e-8) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL SOLUTION FOUND\n"); + status = 0; + break; + } + /* check if the problem has no feasible solution */ + temp = 1e5 * csa->phi_min[csa->iter]; + if (temp < 1e-8) temp = 1e-8; + if (csa->phi >= temp) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("PROBLEM HAS NO FEASIBLE PRIMAL/DUAL SOLUTION\n") + ; + status = 1; + break; + } + /* check for very slow convergence or divergence */ + if (((csa->rpi >= 1e-8 || csa->rdi >= 1e-8) && csa->rmu / + csa->rmu0 >= 1e6) || + (csa->iter >= 30 && csa->phi_min[csa->iter] >= 0.5 * + csa->phi_min[csa->iter - 30])) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("NO CONVERGENCE; SEARCH TERMINATED\n"); + status = 2; + break; + } + /* check for maximal number of iterations */ + if (csa->iter == ITER_MAX) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + status = 3; + break; + } + /* start the next iteration */ + csa->iter++; + /* factorize normal equation system */ + for (j = 1; j <= n; j++) csa->D[j] = csa->x[j] / csa->z[j]; + decomp_NE(csa); + /* compute the next point using Mehrotra's predictor-corrector + technique */ + if (make_step(csa)) + { if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("NUMERIC INSTABILITY; SEARCH TERMINATED\n"); + status = 4; + break; + } + } + /* restore the best point */ + if (status != 0) + { for (j = 1; j <= n; j++) csa->x[j] = csa->best_x[j]; + for (i = 1; i <= m; i++) csa->y[i] = csa->best_y[i]; + for (j = 1; j <= n; j++) csa->z[j] = csa->best_z[j]; + if (csa->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Best point %17.9e was reached on iteration %d\n", + csa->best_obj, csa->best_iter); + } + /* return to the calling program */ + return status; +} + +/*********************************************************************** +* NAME +* +* ipm_solve - core LP solver based on the interior-point method +* +* SYNOPSIS +* +* #include "glpipm.h" +* int ipm_solve(glp_prob *P, const glp_iptcp *parm); +* +* DESCRIPTION +* +* The routine ipm_solve is a core LP solver based on the primal-dual +* interior-point method. +* +* The routine assumes the following standard formulation of LP problem +* to be solved: +* +* minimize +* +* F = c[0] + c[1]*x[1] + c[2]*x[2] + ... + c[n]*x[n] +* +* subject to linear constraints +* +* a[1,1]*x[1] + a[1,2]*x[2] + ... + a[1,n]*x[n] = b[1] +* +* a[2,1]*x[1] + a[2,2]*x[2] + ... + a[2,n]*x[n] = b[2] +* +* . . . . . . +* +* a[m,1]*x[1] + a[m,2]*x[2] + ... + a[m,n]*x[n] = b[m] +* +* and non-negative variables +* +* x[1] >= 0, x[2] >= 0, ..., x[n] >= 0 +* +* where: +* F is the objective function; +* x[1], ..., x[n] are (structural) variables; +* c[0] is a constant term of the objective function; +* c[1], ..., c[n] are objective coefficients; +* a[1,1], ..., a[m,n] are constraint coefficients; +* b[1], ..., b[n] are right-hand sides. +* +* The solution is three vectors x, y, and z, which are stored by the +* routine in the arrays x, y, and z, respectively. These vectors +* correspond to the best primal-dual point found during optimization. +* They are approximate solution of the following system (which is the +* Karush-Kuhn-Tucker optimality conditions): +* +* A*x = b (primal feasibility condition) +* +* A'*y + z = c (dual feasibility condition) +* +* x'*z = 0 (primal-dual complementarity condition) +* +* x >= 0, z >= 0 (non-negativity condition) +* +* where: +* x[1], ..., x[n] are primal (structural) variables; +* y[1], ..., y[m] are dual variables (Lagrange multipliers) for +* equality constraints; +* z[1], ..., z[n] are dual variables (Lagrange multipliers) for +* non-negativity constraints. +* +* RETURNS +* +* 0 LP has been successfully solved. +* +* GLP_ENOCVG +* No convergence. +* +* GLP_EITLIM +* Iteration limit exceeded. +* +* GLP_EINSTAB +* Numeric instability on solving Newtonian system. +* +* In case of non-zero return code the routine returns the best point, +* which has been reached during optimization. */ + +int ipm_solve(glp_prob *P, const glp_iptcp *parm) +{ struct csa _dsa, *csa = &_dsa; + int m = P->m; + int n = P->n; + int nnz = P->nnz; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, j, loc, ret, *A_ind, *A_ptr; + double dir, *A_val, *b, *c, *x, *y, *z; + xassert(m > 0); + xassert(n > 0); + /* allocate working arrays */ + A_ptr = xcalloc(1+m+1, sizeof(int)); + A_ind = xcalloc(1+nnz, sizeof(int)); + A_val = xcalloc(1+nnz, sizeof(double)); + b = xcalloc(1+m, sizeof(double)); + c = xcalloc(1+n, sizeof(double)); + x = xcalloc(1+n, sizeof(double)); + y = xcalloc(1+m, sizeof(double)); + z = xcalloc(1+n, sizeof(double)); + /* prepare rows and constraint coefficients */ + loc = 1; + for (i = 1; i <= m; i++) + { row = P->row[i]; + xassert(row->type == GLP_FX); + b[i] = row->lb * row->rii; + A_ptr[i] = loc; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { A_ind[loc] = aij->col->j; + A_val[loc] = row->rii * aij->val * aij->col->sjj; + loc++; + } + } + A_ptr[m+1] = loc; + xassert(loc-1 == nnz); + /* prepare columns and objective coefficients */ + if (P->dir == GLP_MIN) + dir = +1.0; + else if (P->dir == GLP_MAX) + dir = -1.0; + else + xassert(P != P); + c[0] = dir * P->c0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + xassert(col->type == GLP_LO && col->lb == 0.0); + c[j] = dir * col->coef * col->sjj; + } + /* allocate and initialize the common storage area */ + csa->m = m; + csa->n = n; + csa->A_ptr = A_ptr; + csa->A_ind = A_ind; + csa->A_val = A_val; + csa->b = b; + csa->c = c; + csa->x = x; + csa->y = y; + csa->z = z; + csa->parm = parm; + initialize(csa); + /* solve LP with the interior-point method */ + ret = ipm_main(csa); + /* deallocate the common storage area */ + terminate(csa); + /* determine solution status */ + if (ret == 0) + { /* optimal solution found */ + P->ipt_stat = GLP_OPT; + ret = 0; + } + else if (ret == 1) + { /* problem has no feasible (primal or dual) solution */ + P->ipt_stat = GLP_NOFEAS; + ret = 0; + } + else if (ret == 2) + { /* no convergence */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_ENOCVG; + } + else if (ret == 3) + { /* iteration limit exceeded */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_EITLIM; + } + else if (ret == 4) + { /* numeric instability on solving Newtonian system */ + P->ipt_stat = GLP_INFEAS; + ret = GLP_EINSTAB; + } + else + xassert(ret != ret); + /* store row solution components */ + for (i = 1; i <= m; i++) + { row = P->row[i]; + row->pval = row->lb; + row->dval = dir * y[i] * row->rii; + } + /* store column solution components */ + P->ipt_obj = P->c0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + col->pval = x[j] * col->sjj; + col->dval = dir * z[j] / col->sjj; + P->ipt_obj += col->coef * col->pval; + } + /* free working arrays */ + xfree(A_ptr); + xfree(A_ind); + xfree(A_val); + xfree(b); + xfree(c); + xfree(x); + xfree(y); + xfree(z); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.h new file mode 100644 index 000000000..a5f94fec1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpipm.h @@ -0,0 +1,36 @@ +/* glpipm.h (primal-dual interior-point method) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPIPM_H +#define GLPIPM_H + +#include "prob.h" + +#define ipm_solve _glp_ipm_solve +int ipm_solve(glp_prob *P, const glp_iptcp *parm); +/* core LP solver based on the interior-point method */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.c new file mode 100644 index 000000000..97d1c6515 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.c @@ -0,0 +1,924 @@ +/* glpmat.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpmat.h" +#include "qmd.h" +#include "amd.h" +#include "colamd.h" + +/*---------------------------------------------------------------------- +-- check_fvs - check sparse vector in full-vector storage format. +-- +-- SYNOPSIS +-- +-- #include "glpmat.h" +-- int check_fvs(int n, int nnz, int ind[], double vec[]); +-- +-- DESCRIPTION +-- +-- The routine check_fvs checks if a given vector of dimension n in +-- full-vector storage format has correct representation. +-- +-- RETURNS +-- +-- The routine returns one of the following codes: +-- +-- 0 - the vector is correct; +-- 1 - the number of elements (n) is negative; +-- 2 - the number of non-zero elements (nnz) is negative; +-- 3 - some element index is out of range; +-- 4 - some element index is duplicate; +-- 5 - some non-zero element is out of pattern. */ + +int check_fvs(int n, int nnz, int ind[], double vec[]) +{ int i, t, ret, *flag = NULL; + /* check the number of elements */ + if (n < 0) + { ret = 1; + goto done; + } + /* check the number of non-zero elements */ + if (nnz < 0) + { ret = 2; + goto done; + } + /* check vector indices */ + flag = xcalloc(1+n, sizeof(int)); + for (i = 1; i <= n; i++) flag[i] = 0; + for (t = 1; t <= nnz; t++) + { i = ind[t]; + if (!(1 <= i && i <= n)) + { ret = 3; + goto done; + } + if (flag[i]) + { ret = 4; + goto done; + } + flag[i] = 1; + } + /* check vector elements */ + for (i = 1; i <= n; i++) + { if (!flag[i] && vec[i] != 0.0) + { ret = 5; + goto done; + } + } + /* the vector is ok */ + ret = 0; +done: if (flag != NULL) xfree(flag); + return ret; +} + +/*---------------------------------------------------------------------- +-- check_pattern - check pattern of sparse matrix. +-- +-- SYNOPSIS +-- +-- #include "glpmat.h" +-- int check_pattern(int m, int n, int A_ptr[], int A_ind[]); +-- +-- DESCRIPTION +-- +-- The routine check_pattern checks the pattern of a given mxn matrix +-- in storage-by-rows format. +-- +-- RETURNS +-- +-- The routine returns one of the following codes: +-- +-- 0 - the pattern is correct; +-- 1 - the number of rows (m) is negative; +-- 2 - the number of columns (n) is negative; +-- 3 - A_ptr[1] is not 1; +-- 4 - some column index is out of range; +-- 5 - some column indices are duplicate. */ + +int check_pattern(int m, int n, int A_ptr[], int A_ind[]) +{ int i, j, ptr, ret, *flag = NULL; + /* check the number of rows */ + if (m < 0) + { ret = 1; + goto done; + } + /* check the number of columns */ + if (n < 0) + { ret = 2; + goto done; + } + /* check location A_ptr[1] */ + if (A_ptr[1] != 1) + { ret = 3; + goto done; + } + /* check row patterns */ + flag = xcalloc(1+n, sizeof(int)); + for (j = 1; j <= n; j++) flag[j] = 0; + for (i = 1; i <= m; i++) + { /* check pattern of row i */ + for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) + { j = A_ind[ptr]; + /* check column index */ + if (!(1 <= j && j <= n)) + { ret = 4; + goto done; + } + /* check for duplication */ + if (flag[j]) + { ret = 5; + goto done; + } + flag[j] = 1; + } + /* clear flags */ + for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) + { j = A_ind[ptr]; + flag[j] = 0; + } + } + /* the pattern is ok */ + ret = 0; +done: if (flag != NULL) xfree(flag); + return ret; +} + +/*---------------------------------------------------------------------- +-- transpose - transpose sparse matrix. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void transpose(int m, int n, int A_ptr[], int A_ind[], +-- double A_val[], int AT_ptr[], int AT_ind[], double AT_val[]); +-- +-- *Description* +-- +-- For a given mxn sparse matrix A the routine transpose builds a nxm +-- sparse matrix A' which is a matrix transposed to A. +-- +-- The arrays A_ptr, A_ind, and A_val specify a given mxn matrix A to +-- be transposed in storage-by-rows format. The parameter A_val can be +-- NULL, in which case numeric values are not copied. The arrays A_ptr, +-- A_ind, and A_val are not changed on exit. +-- +-- On entry the arrays AT_ptr, AT_ind, and AT_val must be allocated, +-- but their content is ignored. On exit the routine stores a resultant +-- nxm matrix A' in these arrays in storage-by-rows format. Note that +-- if the parameter A_val is NULL, the array AT_val is not used. +-- +-- The routine transpose has a side effect that elements in rows of the +-- resultant matrix A' follow in ascending their column indices. */ + +void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], + int AT_ptr[], int AT_ind[], double AT_val[]) +{ int i, j, t, beg, end, pos, len; + /* determine row lengths of resultant matrix */ + for (j = 1; j <= n; j++) AT_ptr[j] = 0; + for (i = 1; i <= m; i++) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) AT_ptr[A_ind[t]]++; + } + /* set up row pointers of resultant matrix */ + pos = 1; + for (j = 1; j <= n; j++) + len = AT_ptr[j], pos += len, AT_ptr[j] = pos; + AT_ptr[n+1] = pos; + /* build resultant matrix */ + for (i = m; i >= 1; i--) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + { pos = --AT_ptr[A_ind[t]]; + AT_ind[pos] = i; + if (A_val != NULL) AT_val[pos] = A_val[t]; + } + } + return; +} + +/*---------------------------------------------------------------------- +-- adat_symbolic - compute S = P*A*D*A'*P' (symbolic phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], +-- int A_ind[], int S_ptr[]); +-- +-- *Description* +-- +-- The routine adat_symbolic implements the symbolic phase to compute +-- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, +-- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix +-- transposed to A, P' is an inverse of P. +-- +-- The parameter m is the number of rows in A and the order of P. +-- +-- The parameter n is the number of columns in A and the order of D. +-- +-- The array P_per specifies permutation matrix P. It is not changed on +-- exit. +-- +-- The arrays A_ptr and A_ind specify the pattern of matrix A. They are +-- not changed on exit. +-- +-- On exit the routine stores the pattern of upper triangular part of +-- matrix S without diagonal elements in the arrays S_ptr and S_ind in +-- storage-by-rows format. The array S_ptr should be allocated on entry, +-- however, its content is ignored. The array S_ind is allocated by the +-- routine itself which returns a pointer to it. +-- +-- *Returns* +-- +-- The routine returns a pointer to the array S_ind. */ + +int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], + int S_ptr[]) +{ int i, j, t, ii, jj, tt, k, size, len; + int *S_ind, *AT_ptr, *AT_ind, *ind, *map, *temp; + /* build the pattern of A', which is a matrix transposed to A, to + efficiently access A in column-wise manner */ + AT_ptr = xcalloc(1+n+1, sizeof(int)); + AT_ind = xcalloc(A_ptr[m+1], sizeof(int)); + transpose(m, n, A_ptr, A_ind, NULL, AT_ptr, AT_ind, NULL); + /* allocate the array S_ind */ + size = A_ptr[m+1] - 1; + if (size < m) size = m; + S_ind = xcalloc(1+size, sizeof(int)); + /* allocate and initialize working arrays */ + ind = xcalloc(1+m, sizeof(int)); + map = xcalloc(1+m, sizeof(int)); + for (jj = 1; jj <= m; jj++) map[jj] = 0; + /* compute pattern of S; note that symbolically S = B*B', where + B = P*A, B' is matrix transposed to B */ + S_ptr[1] = 1; + for (ii = 1; ii <= m; ii++) + { /* compute pattern of ii-th row of S */ + len = 0; + i = P_per[ii]; /* i-th row of A = ii-th row of B */ + for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { k = A_ind[t]; + /* walk through k-th column of A */ + for (tt = AT_ptr[k]; tt < AT_ptr[k+1]; tt++) + { j = AT_ind[tt]; + jj = P_per[m+j]; /* j-th row of A = jj-th row of B */ + /* a[i,k] != 0 and a[j,k] != 0 ergo s[ii,jj] != 0 */ + if (ii < jj && !map[jj]) ind[++len] = jj, map[jj] = 1; + } + } + /* now (ind) is pattern of ii-th row of S */ + S_ptr[ii+1] = S_ptr[ii] + len; + /* at least (S_ptr[ii+1] - 1) locations should be available in + the array S_ind */ + if (S_ptr[ii+1] - 1 > size) + { temp = S_ind; + size += size; + S_ind = xcalloc(1+size, sizeof(int)); + memcpy(&S_ind[1], &temp[1], (S_ptr[ii] - 1) * sizeof(int)); + xfree(temp); + } + xassert(S_ptr[ii+1] - 1 <= size); + /* (ii-th row of S) := (ind) */ + memcpy(&S_ind[S_ptr[ii]], &ind[1], len * sizeof(int)); + /* clear the row pattern map */ + for (t = 1; t <= len; t++) map[ind[t]] = 0; + } + /* free working arrays */ + xfree(AT_ptr); + xfree(AT_ind); + xfree(ind); + xfree(map); + /* reallocate the array S_ind to free unused locations */ + temp = S_ind; + size = S_ptr[m+1] - 1; + S_ind = xcalloc(1+size, sizeof(int)); + memcpy(&S_ind[1], &temp[1], size * sizeof(int)); + xfree(temp); + return S_ind; +} + +/*---------------------------------------------------------------------- +-- adat_numeric - compute S = P*A*D*A'*P' (numeric phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void adat_numeric(int m, int n, int P_per[], +-- int A_ptr[], int A_ind[], double A_val[], double D_diag[], +-- int S_ptr[], int S_ind[], double S_val[], double S_diag[]); +-- +-- *Description* +-- +-- The routine adat_numeric implements the numeric phase to compute +-- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, +-- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix +-- transposed to A, P' is an inverse of P. +-- +-- The parameter m is the number of rows in A and the order of P. +-- +-- The parameter n is the number of columns in A and the order of D. +-- +-- The matrix P is specified in the array P_per, which is not changed +-- on exit. +-- +-- The matrix A is specified in the arrays A_ptr, A_ind, and A_val in +-- storage-by-rows format. These arrays are not changed on exit. +-- +-- Diagonal elements of the matrix D are specified in the array D_diag, +-- where D_diag[0] is not used, D_diag[i] = d[i,i] for i = 1, ..., n. +-- The array D_diag is not changed on exit. +-- +-- The pattern of the upper triangular part of the matrix S without +-- diagonal elements (previously computed by the routine adat_symbolic) +-- is specified in the arrays S_ptr and S_ind, which are not changed on +-- exit. Numeric values of non-diagonal elements of S are stored in +-- corresponding locations of the array S_val, and values of diagonal +-- elements of S are stored in locations S_diag[1], ..., S_diag[n]. */ + +void adat_numeric(int m, int n, int P_per[], + int A_ptr[], int A_ind[], double A_val[], double D_diag[], + int S_ptr[], int S_ind[], double S_val[], double S_diag[]) +{ int i, j, t, ii, jj, tt, beg, end, beg1, end1, k; + double sum, *work; + work = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) work[j] = 0.0; + /* compute S = B*D*B', where B = P*A, B' is a matrix transposed + to B */ + for (ii = 1; ii <= m; ii++) + { i = P_per[ii]; /* i-th row of A = ii-th row of B */ + /* (work) := (i-th row of A) */ + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + work[A_ind[t]] = A_val[t]; + /* compute ii-th row of S */ + beg = S_ptr[ii], end = S_ptr[ii+1]; + for (t = beg; t < end; t++) + { jj = S_ind[t]; + j = P_per[jj]; /* j-th row of A = jj-th row of B */ + /* s[ii,jj] := sum a[i,k] * d[k,k] * a[j,k] */ + sum = 0.0; + beg1 = A_ptr[j], end1 = A_ptr[j+1]; + for (tt = beg1; tt < end1; tt++) + { k = A_ind[tt]; + sum += work[k] * D_diag[k] * A_val[tt]; + } + S_val[t] = sum; + } + /* s[ii,ii] := sum a[i,k] * d[k,k] * a[i,k] */ + sum = 0.0; + beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + { k = A_ind[t]; + sum += A_val[t] * D_diag[k] * A_val[t]; + work[k] = 0.0; + } + S_diag[ii] = sum; + } + xfree(work); + return; +} + +/*---------------------------------------------------------------------- +-- min_degree - minimum degree ordering. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); +-- +-- *Description* +-- +-- The routine min_degree uses the minimum degree ordering algorithm +-- to find a permutation matrix P for a given sparse symmetric positive +-- matrix A which minimizes the number of non-zeros in upper triangular +-- factor U for Cholesky factorization P*A*P' = U'*U. +-- +-- The parameter n is the order of matrices A and P. +-- +-- The pattern of the given matrix A is specified on entry in the arrays +-- A_ptr and A_ind in storage-by-rows format. Only the upper triangular +-- part without diagonal elements (which all are assumed to be non-zero) +-- should be specified as if A were upper triangular. The arrays A_ptr +-- and A_ind are not changed on exit. +-- +-- The permutation matrix P is stored by the routine in the array P_per +-- on exit. +-- +-- *Algorithm* +-- +-- The routine min_degree is based on some subroutines from the package +-- SPARSPAK (see comments in the module glpqmd). */ + +void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]) +{ int i, j, ne, t, pos, len; + int *xadj, *adjncy, *deg, *marker, *rchset, *nbrhd, *qsize, + *qlink, nofsub; + /* determine number of non-zeros in complete pattern */ + ne = A_ptr[n+1] - 1; + ne += ne; + /* allocate working arrays */ + xadj = xcalloc(1+n+1, sizeof(int)); + adjncy = xcalloc(1+ne, sizeof(int)); + deg = xcalloc(1+n, sizeof(int)); + marker = xcalloc(1+n, sizeof(int)); + rchset = xcalloc(1+n, sizeof(int)); + nbrhd = xcalloc(1+n, sizeof(int)); + qsize = xcalloc(1+n, sizeof(int)); + qlink = xcalloc(1+n, sizeof(int)); + /* determine row lengths in complete pattern */ + for (i = 1; i <= n; i++) xadj[i] = 0; + for (i = 1; i <= n; i++) + { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { j = A_ind[t]; + xassert(i < j && j <= n); + xadj[i]++, xadj[j]++; + } + } + /* set up row pointers for complete pattern */ + pos = 1; + for (i = 1; i <= n; i++) + len = xadj[i], pos += len, xadj[i] = pos; + xadj[n+1] = pos; + xassert(pos - 1 == ne); + /* construct complete pattern */ + for (i = 1; i <= n; i++) + { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) + { j = A_ind[t]; + adjncy[--xadj[i]] = j, adjncy[--xadj[j]] = i; + } + } + /* call the main minimimum degree ordering routine */ + genqmd(&n, xadj, adjncy, P_per, P_per + n, deg, marker, rchset, + nbrhd, qsize, qlink, &nofsub); + /* make sure that permutation matrix P is correct */ + for (i = 1; i <= n; i++) + { j = P_per[i]; + xassert(1 <= j && j <= n); + xassert(P_per[n+j] == i); + } + /* free working arrays */ + xfree(xadj); + xfree(adjncy); + xfree(deg); + xfree(marker); + xfree(rchset); + xfree(nbrhd); + xfree(qsize); + xfree(qlink); + return; +} + +/**********************************************************************/ + +void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]) +{ /* approximate minimum degree ordering (AMD) */ + int k, ret; + double Control[AMD_CONTROL], Info[AMD_INFO]; + /* get the default parameters */ + amd_defaults(Control); +#if 0 + /* and print them */ + amd_control(Control); +#endif + /* make all indices 0-based */ + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; + for (k = 1; k <= n+1; k++) A_ptr[k]--; + /* call the ordering routine */ + ret = amd_order(n, &A_ptr[1], &A_ind[1], &P_per[1], Control, Info) + ; +#if 0 + amd_info(Info); +#endif + xassert(ret == AMD_OK || ret == AMD_OK_BUT_JUMBLED); + /* retsore 1-based indices */ + for (k = 1; k <= n+1; k++) A_ptr[k]++; + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; + /* patch up permutation matrix */ + memset(&P_per[n+1], 0, n * sizeof(int)); + for (k = 1; k <= n; k++) + { P_per[k]++; + xassert(1 <= P_per[k] && P_per[k] <= n); + xassert(P_per[n+P_per[k]] == 0); + P_per[n+P_per[k]] = k; + } + return; +} + +/**********************************************************************/ + +static void *allocate(size_t n, size_t size) +{ void *ptr; + ptr = xcalloc(n, size); + memset(ptr, 0, n * size); + return ptr; +} + +static void release(void *ptr) +{ xfree(ptr); + return; +} + +void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]) +{ /* approximate minimum degree ordering (SYMAMD) */ + int k, ok; + int stats[COLAMD_STATS]; + /* make all indices 0-based */ + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; + for (k = 1; k <= n+1; k++) A_ptr[k]--; + /* call the ordering routine */ + ok = symamd(n, &A_ind[1], &A_ptr[1], &P_per[1], NULL, stats, + allocate, release); +#if 0 + symamd_report(stats); +#endif + xassert(ok); + /* restore 1-based indices */ + for (k = 1; k <= n+1; k++) A_ptr[k]++; + for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; + /* patch up permutation matrix */ + memset(&P_per[n+1], 0, n * sizeof(int)); + for (k = 1; k <= n; k++) + { P_per[k]++; + xassert(1 <= P_per[k] && P_per[k] <= n); + xassert(P_per[n+P_per[k]] == 0); + P_per[n+P_per[k]] = k; + } + return; +} + +/*---------------------------------------------------------------------- +-- chol_symbolic - compute Cholesky factorization (symbolic phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); +-- +-- *Description* +-- +-- The routine chol_symbolic implements the symbolic phase of Cholesky +-- factorization A = U'*U, where A is a given sparse symmetric positive +-- definite matrix, U is a resultant upper triangular factor, U' is a +-- matrix transposed to U. +-- +-- The parameter n is the order of matrices A and U. +-- +-- The pattern of the given matrix A is specified on entry in the arrays +-- A_ptr and A_ind in storage-by-rows format. Only the upper triangular +-- part without diagonal elements (which all are assumed to be non-zero) +-- should be specified as if A were upper triangular. The arrays A_ptr +-- and A_ind are not changed on exit. +-- +-- The pattern of the matrix U without diagonal elements (which all are +-- assumed to be non-zero) is stored on exit from the routine in the +-- arrays U_ptr and U_ind in storage-by-rows format. The array U_ptr +-- should be allocated on entry, however, its content is ignored. The +-- array U_ind is allocated by the routine which returns a pointer to it +-- on exit. +-- +-- *Returns* +-- +-- The routine returns a pointer to the array U_ind. +-- +-- *Method* +-- +-- The routine chol_symbolic computes the pattern of the matrix U in a +-- row-wise manner. No pivoting is used. +-- +-- It is known that to compute the pattern of row k of the matrix U we +-- need to merge the pattern of row k of the matrix A and the patterns +-- of each row i of U, where u[i,k] is non-zero (these rows are already +-- computed and placed above row k). +-- +-- However, to reduce the number of rows to be merged the routine uses +-- an advanced algorithm proposed in: +-- +-- D.J.Rose, R.E.Tarjan, and G.S.Lueker. Algorithmic aspects of vertex +-- elimination on graphs. SIAM J. Comput. 5, 1976, 266-83. +-- +-- The authors of the cited paper show that we have the same result if +-- we merge row k of the matrix A and such rows of the matrix U (among +-- rows 1, ..., k-1) whose leftmost non-diagonal non-zero element is +-- placed in k-th column. This feature signficantly reduces the number +-- of rows to be merged, especially on the final steps, where rows of +-- the matrix U become quite dense. +-- +-- To determine rows, which should be merged on k-th step, for a fixed +-- time the routine uses linked lists of row numbers of the matrix U. +-- Location head[k] contains the number of a first row, whose leftmost +-- non-diagonal non-zero element is placed in column k, and location +-- next[i] contains the number of a next row with the same property as +-- row i. */ + +int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]) +{ int i, j, k, t, len, size, beg, end, min_j, *U_ind, *head, *next, + *ind, *map, *temp; + /* initially we assume that on computing the pattern of U fill-in + will double the number of non-zeros in A */ + size = A_ptr[n+1] - 1; + if (size < n) size = n; + size += size; + U_ind = xcalloc(1+size, sizeof(int)); + /* allocate and initialize working arrays */ + head = xcalloc(1+n, sizeof(int)); + for (i = 1; i <= n; i++) head[i] = 0; + next = xcalloc(1+n, sizeof(int)); + ind = xcalloc(1+n, sizeof(int)); + map = xcalloc(1+n, sizeof(int)); + for (j = 1; j <= n; j++) map[j] = 0; + /* compute the pattern of matrix U */ + U_ptr[1] = 1; + for (k = 1; k <= n; k++) + { /* compute the pattern of k-th row of U, which is the union of + k-th row of A and those rows of U (among 1, ..., k-1) whose + leftmost non-diagonal non-zero is placed in k-th column */ + /* (ind) := (k-th row of A) */ + len = A_ptr[k+1] - A_ptr[k]; + memcpy(&ind[1], &A_ind[A_ptr[k]], len * sizeof(int)); + for (t = 1; t <= len; t++) + { j = ind[t]; + xassert(k < j && j <= n); + map[j] = 1; + } + /* walk through rows of U whose leftmost non-diagonal non-zero + is placed in k-th column */ + for (i = head[k]; i != 0; i = next[i]) + { /* (ind) := (ind) union (i-th row of U) */ + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + { j = U_ind[t]; + if (j > k && !map[j]) ind[++len] = j, map[j] = 1; + } + } + /* now (ind) is the pattern of k-th row of U */ + U_ptr[k+1] = U_ptr[k] + len; + /* at least (U_ptr[k+1] - 1) locations should be available in + the array U_ind */ + if (U_ptr[k+1] - 1 > size) + { temp = U_ind; + size += size; + U_ind = xcalloc(1+size, sizeof(int)); + memcpy(&U_ind[1], &temp[1], (U_ptr[k] - 1) * sizeof(int)); + xfree(temp); + } + xassert(U_ptr[k+1] - 1 <= size); + /* (k-th row of U) := (ind) */ + memcpy(&U_ind[U_ptr[k]], &ind[1], len * sizeof(int)); + /* determine column index of leftmost non-diagonal non-zero in + k-th row of U and clear the row pattern map */ + min_j = n + 1; + for (t = 1; t <= len; t++) + { j = ind[t], map[j] = 0; + if (min_j > j) min_j = j; + } + /* include k-th row into corresponding linked list */ + if (min_j <= n) next[k] = head[min_j], head[min_j] = k; + } + /* free working arrays */ + xfree(head); + xfree(next); + xfree(ind); + xfree(map); + /* reallocate the array U_ind to free unused locations */ + temp = U_ind; + size = U_ptr[n+1] - 1; + U_ind = xcalloc(1+size, sizeof(int)); + memcpy(&U_ind[1], &temp[1], size * sizeof(int)); + xfree(temp); + return U_ind; +} + +/*---------------------------------------------------------------------- +-- chol_numeric - compute Cholesky factorization (numeric phase). +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- int chol_numeric(int n, +-- int A_ptr[], int A_ind[], double A_val[], double A_diag[], +-- int U_ptr[], int U_ind[], double U_val[], double U_diag[]); +-- +-- *Description* +-- +-- The routine chol_symbolic implements the numeric phase of Cholesky +-- factorization A = U'*U, where A is a given sparse symmetric positive +-- definite matrix, U is a resultant upper triangular factor, U' is a +-- matrix transposed to U. +-- +-- The parameter n is the order of matrices A and U. +-- +-- Upper triangular part of the matrix A without diagonal elements is +-- specified in the arrays A_ptr, A_ind, and A_val in storage-by-rows +-- format. Diagonal elements of A are specified in the array A_diag, +-- where A_diag[0] is not used, A_diag[i] = a[i,i] for i = 1, ..., n. +-- The arrays A_ptr, A_ind, A_val, and A_diag are not changed on exit. +-- +-- The pattern of the matrix U without diagonal elements (previously +-- computed with the routine chol_symbolic) is specified in the arrays +-- U_ptr and U_ind, which are not changed on exit. Numeric values of +-- non-diagonal elements of U are stored in corresponding locations of +-- the array U_val, and values of diagonal elements of U are stored in +-- locations U_diag[1], ..., U_diag[n]. +-- +-- *Returns* +-- +-- The routine returns the number of non-positive diagonal elements of +-- the matrix U which have been replaced by a huge positive number (see +-- the method description below). Zero return code means the matrix A +-- has been successfully factorized. +-- +-- *Method* +-- +-- The routine chol_numeric computes the matrix U in a row-wise manner +-- using standard gaussian elimination technique. No pivoting is used. +-- +-- Initially the routine sets U = A, and before k-th elimination step +-- the matrix U is the following: +-- +-- 1 k n +-- 1 x x x x x x x x x x +-- . x x x x x x x x x +-- . . x x x x x x x x +-- . . . x x x x x x x +-- k . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- . . . . * * * * * * +-- n . . . . * * * * * * +-- +-- where 'x' are elements of already computed rows, '*' are elements of +-- the active submatrix. (Note that the lower triangular part of the +-- active submatrix being symmetric is not stored and diagonal elements +-- are stored separately in the array U_diag.) +-- +-- The matrix A is assumed to be positive definite. However, if it is +-- close to semi-definite, on some elimination step a pivot u[k,k] may +-- happen to be non-positive due to round-off errors. In this case the +-- routine uses a technique proposed in: +-- +-- S.J.Wright. The Cholesky factorization in interior-point and barrier +-- methods. Preprint MCS-P600-0596, Mathematics and Computer Science +-- Division, Argonne National Laboratory, Argonne, Ill., May 1996. +-- +-- The routine just replaces non-positive u[k,k] by a huge positive +-- number. This involves non-diagonal elements in k-th row of U to be +-- close to zero that, in turn, involves k-th component of a solution +-- vector to be close to zero. Note, however, that this technique works +-- only if the system A*x = b is consistent. */ + +int chol_numeric(int n, + int A_ptr[], int A_ind[], double A_val[], double A_diag[], + int U_ptr[], int U_ind[], double U_val[], double U_diag[]) +{ int i, j, k, t, t1, beg, end, beg1, end1, count = 0; + double ukk, uki, *work; + work = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) work[j] = 0.0; + /* U := (upper triangle of A) */ + /* note that the upper traingle of A is a subset of U */ + for (i = 1; i <= n; i++) + { beg = A_ptr[i], end = A_ptr[i+1]; + for (t = beg; t < end; t++) + j = A_ind[t], work[j] = A_val[t]; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + j = U_ind[t], U_val[t] = work[j], work[j] = 0.0; + U_diag[i] = A_diag[i]; + } + /* main elimination loop */ + for (k = 1; k <= n; k++) + { /* transform k-th row of U */ + ukk = U_diag[k]; + if (ukk > 0.0) + U_diag[k] = ukk = sqrt(ukk); + else + U_diag[k] = ukk = DBL_MAX, count++; + /* (work) := (transformed k-th row) */ + beg = U_ptr[k], end = U_ptr[k+1]; + for (t = beg; t < end; t++) + work[U_ind[t]] = (U_val[t] /= ukk); + /* transform other rows of U */ + for (t = beg; t < end; t++) + { i = U_ind[t]; + xassert(i > k); + /* (i-th row) := (i-th row) - u[k,i] * (k-th row) */ + uki = work[i]; + beg1 = U_ptr[i], end1 = U_ptr[i+1]; + for (t1 = beg1; t1 < end1; t1++) + U_val[t1] -= uki * work[U_ind[t1]]; + U_diag[i] -= uki * uki; + } + /* (work) := 0 */ + for (t = beg; t < end; t++) + work[U_ind[t]] = 0.0; + } + xfree(work); + return count; +} + +/*---------------------------------------------------------------------- +-- u_solve - solve upper triangular system U*x = b. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], +-- double U_diag[], double x[]); +-- +-- *Description* +-- +-- The routine u_solve solves an linear system U*x = b, where U is an +-- upper triangular matrix. +-- +-- The parameter n is the order of matrix U. +-- +-- The matrix U without diagonal elements is specified in the arrays +-- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements +-- of U are specified in the array U_diag, where U_diag[0] is not used, +-- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not +-- changed on exit. +-- +-- The right-hand side vector b is specified on entry in the array x, +-- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit +-- the routine stores computed components of the vector of unknowns x +-- in the array x in the same manner. */ + +void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]) +{ int i, t, beg, end; + double temp; + for (i = n; i >= 1; i--) + { temp = x[i]; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + temp -= U_val[t] * x[U_ind[t]]; + xassert(U_diag[i] != 0.0); + x[i] = temp / U_diag[i]; + } + return; +} + +/*---------------------------------------------------------------------- +-- ut_solve - solve lower triangular system U'*x = b. +-- +-- *Synopsis* +-- +-- #include "glpmat.h" +-- void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], +-- double U_diag[], double x[]); +-- +-- *Description* +-- +-- The routine ut_solve solves an linear system U'*x = b, where U is a +-- matrix transposed to an upper triangular matrix. +-- +-- The parameter n is the order of matrix U. +-- +-- The matrix U without diagonal elements is specified in the arrays +-- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements +-- of U are specified in the array U_diag, where U_diag[0] is not used, +-- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not +-- changed on exit. +-- +-- The right-hand side vector b is specified on entry in the array x, +-- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit +-- the routine stores computed components of the vector of unknowns x +-- in the array x in the same manner. */ + +void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]) +{ int i, t, beg, end; + double temp; + for (i = 1; i <= n; i++) + { xassert(U_diag[i] != 0.0); + temp = (x[i] /= U_diag[i]); + if (temp == 0.0) continue; + beg = U_ptr[i], end = U_ptr[i+1]; + for (t = beg; t < end; t++) + x[U_ind[t]] -= U_val[t] * temp; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.h new file mode 100644 index 000000000..5b0584371 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpmat.h @@ -0,0 +1,198 @@ +/* glpmat.h (linear algebra routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPMAT_H +#define GLPMAT_H + +/*********************************************************************** +* FULL-VECTOR STORAGE +* +* For a sparse vector x having n elements, ne of which are non-zero, +* the full-vector storage format uses two arrays x_ind and x_vec, which +* are set up as follows: +* +* x_ind is an integer array of length [1+ne]. Location x_ind[0] is +* not used, and locations x_ind[1], ..., x_ind[ne] contain indices of +* non-zero elements in vector x. +* +* x_vec is a floating-point array of length [1+n]. Location x_vec[0] +* is not used, and locations x_vec[1], ..., x_vec[n] contain numeric +* values of ALL elements in vector x, including its zero elements. +* +* Let, for example, the following sparse vector x be given: +* +* (0, 1, 0, 0, 2, 3, 0, 4) +* +* Then the arrays are: +* +* x_ind = { X; 2, 5, 6, 8 } +* +* x_vec = { X; 0, 1, 0, 0, 2, 3, 0, 4 } +* +* COMPRESSED-VECTOR STORAGE +* +* For a sparse vector x having n elements, ne of which are non-zero, +* the compressed-vector storage format uses two arrays x_ind and x_vec, +* which are set up as follows: +* +* x_ind is an integer array of length [1+ne]. Location x_ind[0] is +* not used, and locations x_ind[1], ..., x_ind[ne] contain indices of +* non-zero elements in vector x. +* +* x_vec is a floating-point array of length [1+ne]. Location x_vec[0] +* is not used, and locations x_vec[1], ..., x_vec[ne] contain numeric +* values of corresponding non-zero elements in vector x. +* +* Let, for example, the following sparse vector x be given: +* +* (0, 1, 0, 0, 2, 3, 0, 4) +* +* Then the arrays are: +* +* x_ind = { X; 2, 5, 6, 8 } +* +* x_vec = { X; 1, 2, 3, 4 } +* +* STORAGE-BY-ROWS +* +* For a sparse matrix A, which has m rows, n columns, and ne non-zero +* elements the storage-by-rows format uses three arrays A_ptr, A_ind, +* and A_val, which are set up as follows: +* +* A_ptr is an integer array of length [1+m+1] also called "row pointer +* array". It contains the relative starting positions of each row of A +* in the arrays A_ind and A_val, i.e. element A_ptr[i], 1 <= i <= m, +* indicates where row i begins in the arrays A_ind and A_val. If all +* elements in row i are zero, then A_ptr[i] = A_ptr[i+1]. Location +* A_ptr[0] is not used, location A_ptr[1] must contain 1, and location +* A_ptr[m+1] must contain ne+1 that indicates the position after the +* last element in the arrays A_ind and A_val. +* +* A_ind is an integer array of length [1+ne]. Location A_ind[0] is not +* used, and locations A_ind[1], ..., A_ind[ne] contain column indices +* of (non-zero) elements in matrix A. +* +* A_val is a floating-point array of length [1+ne]. Location A_val[0] +* is not used, and locations A_val[1], ..., A_val[ne] contain numeric +* values of non-zero elements in matrix A. +* +* Non-zero elements of matrix A are stored contiguously, and the rows +* of matrix A are stored consecutively from 1 to m in the arrays A_ind +* and A_val. The elements in each row of A may be stored in any order +* in A_ind and A_val. Note that elements with duplicate column indices +* are not allowed. +* +* Let, for example, the following sparse matrix A be given: +* +* | 11 . 13 . . . | +* | 21 22 . 24 . . | +* | . 32 33 . . . | +* | . . 43 44 . 46 | +* | . . . . . . | +* | 61 62 . . . 66 | +* +* Then the arrays are: +* +* A_ptr = { X; 1, 3, 6, 8, 11, 11; 14 } +* +* A_ind = { X; 1, 3; 4, 2, 1; 2, 3; 4, 3, 6; 1, 2, 6 } +* +* A_val = { X; 11, 13; 24, 22, 21; 32, 33; 44, 43, 46; 61, 62, 66 } +* +* PERMUTATION MATRICES +* +* Let P be a permutation matrix of the order n. It is represented as +* an integer array P_per of length [1+n+n] as follows: if p[i,j] = 1, +* then P_per[i] = j and P_per[n+j] = i. Location P_per[0] is not used. +* +* Let A' = P*A. If i-th row of A corresponds to i'-th row of A', then +* P_per[i'] = i and P_per[n+i] = i'. +* +* References: +* +* 1. Gustavson F.G. Some basic techniques for solving sparse systems of +* linear equations. In Rose and Willoughby (1972), pp. 41-52. +* +* 2. Basic Linear Algebra Subprograms Technical (BLAST) Forum Standard. +* University of Tennessee (2001). */ + +#define check_fvs _glp_mat_check_fvs +int check_fvs(int n, int nnz, int ind[], double vec[]); +/* check sparse vector in full-vector storage format */ + +#define check_pattern _glp_mat_check_pattern +int check_pattern(int m, int n, int A_ptr[], int A_ind[]); +/* check pattern of sparse matrix */ + +#define transpose _glp_mat_transpose +void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], + int AT_ptr[], int AT_ind[], double AT_val[]); +/* transpose sparse matrix */ + +#define adat_symbolic _glp_mat_adat_symbolic +int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], + int S_ptr[]); +/* compute S = P*A*D*A'*P' (symbolic phase) */ + +#define adat_numeric _glp_mat_adat_numeric +void adat_numeric(int m, int n, int P_per[], + int A_ptr[], int A_ind[], double A_val[], double D_diag[], + int S_ptr[], int S_ind[], double S_val[], double S_diag[]); +/* compute S = P*A*D*A'*P' (numeric phase) */ + +#define min_degree _glp_mat_min_degree +void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); +/* minimum degree ordering */ + +#define amd_order1 _glp_mat_amd_order1 +void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]); +/* approximate minimum degree ordering (AMD) */ + +#define symamd_ord _glp_mat_symamd_ord +void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]); +/* approximate minimum degree ordering (SYMAMD) */ + +#define chol_symbolic _glp_mat_chol_symbolic +int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); +/* compute Cholesky factorization (symbolic phase) */ + +#define chol_numeric _glp_mat_chol_numeric +int chol_numeric(int n, + int A_ptr[], int A_ind[], double A_val[], double A_diag[], + int U_ptr[], int U_ind[], double U_val[], double U_diag[]); +/* compute Cholesky factorization (numeric phase) */ + +#define u_solve _glp_mat_u_solve +void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]); +/* solve upper triangular system U*x = b */ + +#define ut_solve _glp_mat_ut_solve +void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], + double U_diag[], double x[]); +/* solve lower triangular system U'*x = b */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.c new file mode 100644 index 000000000..fbff6b8d4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.c @@ -0,0 +1,173 @@ +/* glprgr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#define _GLPSTD_ERRNO +#define _GLPSTD_STDIO +#include "env.h" +#include "glprgr.h" +#define xfault xerror + +/*********************************************************************** +* NAME +* +* rgr_write_bmp16 - write 16-color raster image in BMP file format +* +* SYNOPSIS +* +* #include "glprgr.h" +* int rgr_write_bmp16(const char *fname, int m, int n, const char +* map[]); +* +* DESCRIPTION +* +* The routine rgr_write_bmp16 writes 16-color raster image in +* uncompressed BMP file format (Windows bitmap) to a binary file whose +* name is specified by the character string fname. +* +* The parameters m and n specify, respectively, the number of rows and +* the numbers of columns (i.e. height and width) of the raster image. +* +* The character array map has m*n elements. Elements map[0, ..., n-1] +* correspond to the first (top) scanline, elements map[n, ..., 2*n-1] +* correspond to the second scanline, etc. +* +* Each element of the array map specifies a color of the corresponding +* pixel as 8-bit binary number XXXXIRGB, where four high-order bits (X) +* are ignored, I is high intensity bit, R is red color bit, G is green +* color bit, and B is blue color bit. Thus, all 16 possible colors are +* coded as following hexadecimal numbers: +* +* 0x00 = black 0x08 = dark gray +* 0x01 = blue 0x09 = bright blue +* 0x02 = green 0x0A = bright green +* 0x03 = cyan 0x0B = bright cyan +* 0x04 = red 0x0C = bright red +* 0x05 = magenta 0x0D = bright magenta +* 0x06 = brown 0x0E = yellow +* 0x07 = light gray 0x0F = white +* +* RETURNS +* +* If no error occured, the routine returns zero; otherwise, it prints +* an appropriate error message and returns non-zero. */ + +static void put_byte(FILE *fp, int c) +{ fputc(c, fp); + return; +} + +static void put_word(FILE *fp, int w) +{ /* big endian */ + put_byte(fp, w); + put_byte(fp, w >> 8); + return; +} + +static void put_dword(FILE *fp, int d) +{ /* big endian */ + put_word(fp, d); + put_word(fp, d >> 16); + return; +} + +int rgr_write_bmp16(const char *fname, int m, int n, const char map[]) +{ FILE *fp; + int offset, bmsize, i, j, b, ret = 0; + if (!(1 <= m && m <= 32767)) + xfault("rgr_write_bmp16: m = %d; invalid height\n", m); + if (!(1 <= n && n <= 32767)) + xfault("rgr_write_bmp16: n = %d; invalid width\n", n); + fp = fopen(fname, "wb"); + if (fp == NULL) + { xprintf("rgr_write_bmp16: unable to create '%s' - %s\n", +#if 0 /* 29/I-2017 */ + fname, strerror(errno)); +#else + fname, xstrerr(errno)); +#endif + ret = 1; + goto fini; + } + offset = 14 + 40 + 16 * 4; + bmsize = (4 * n + 31) / 32; + /* struct BMPFILEHEADER (14 bytes) */ + /* UINT bfType */ put_byte(fp, 'B'), put_byte(fp, 'M'); + /* DWORD bfSize */ put_dword(fp, offset + bmsize * 4); + /* UINT bfReserved1 */ put_word(fp, 0); + /* UNIT bfReserved2 */ put_word(fp, 0); + /* DWORD bfOffBits */ put_dword(fp, offset); + /* struct BMPINFOHEADER (40 bytes) */ + /* DWORD biSize */ put_dword(fp, 40); + /* LONG biWidth */ put_dword(fp, n); + /* LONG biHeight */ put_dword(fp, m); + /* WORD biPlanes */ put_word(fp, 1); + /* WORD biBitCount */ put_word(fp, 4); + /* DWORD biCompression */ put_dword(fp, 0 /* BI_RGB */); + /* DWORD biSizeImage */ put_dword(fp, 0); + /* LONG biXPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); + /* LONG biYPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); + /* DWORD biClrUsed */ put_dword(fp, 0); + /* DWORD biClrImportant */ put_dword(fp, 0); + /* struct RGBQUAD (16 * 4 = 64 bytes) */ + /* CGA-compatible colors: */ + /* 0x00 = black */ put_dword(fp, 0x000000); + /* 0x01 = blue */ put_dword(fp, 0x000080); + /* 0x02 = green */ put_dword(fp, 0x008000); + /* 0x03 = cyan */ put_dword(fp, 0x008080); + /* 0x04 = red */ put_dword(fp, 0x800000); + /* 0x05 = magenta */ put_dword(fp, 0x800080); + /* 0x06 = brown */ put_dword(fp, 0x808000); + /* 0x07 = light gray */ put_dword(fp, 0xC0C0C0); + /* 0x08 = dark gray */ put_dword(fp, 0x808080); + /* 0x09 = bright blue */ put_dword(fp, 0x0000FF); + /* 0x0A = bright green */ put_dword(fp, 0x00FF00); + /* 0x0B = bright cyan */ put_dword(fp, 0x00FFFF); + /* 0x0C = bright red */ put_dword(fp, 0xFF0000); + /* 0x0D = bright magenta */ put_dword(fp, 0xFF00FF); + /* 0x0E = yellow */ put_dword(fp, 0xFFFF00); + /* 0x0F = white */ put_dword(fp, 0xFFFFFF); + /* pixel data bits */ + b = 0; + for (i = m - 1; i >= 0; i--) + { for (j = 0; j < ((n + 7) / 8) * 8; j++) + { b <<= 4; + b |= (j < n ? map[i * n + j] & 15 : 0); + if (j & 1) put_byte(fp, b); + } + } + fflush(fp); + if (ferror(fp)) + { xprintf("rgr_write_bmp16: write error on '%s' - %s\n", +#if 0 /* 29/I-2017 */ + fname, strerror(errno)); +#else + fname, xstrerr(errno)); +#endif + ret = 1; + } +fini: if (fp != NULL) fclose(fp); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.h new file mode 100644 index 000000000..71e089e91 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glprgr.h @@ -0,0 +1,34 @@ +/* glprgr.h (raster graphics) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPRGR_H +#define GLPRGR_H + +#define rgr_write_bmp16 _glp_rgr_write_bmp16 +int rgr_write_bmp16(const char *fname, int m, int n, const char map[]); +/* write 16-color raster image in BMP file format */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpscl.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpscl.c new file mode 100644 index 000000000..de769a8b1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpscl.c @@ -0,0 +1,478 @@ +/* glpscl.c (problem scaling routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" +#include "prob.h" + +/*********************************************************************** +* min_row_aij - determine minimal |a[i,j]| in i-th row +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in i-th row of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If i-th row of the matrix is empty, the routine returns 1. */ + +static double min_row_aij(glp_prob *lp, int i, int scaled) +{ GLPAIJ *aij; + double min_aij, temp; + xassert(1 <= i && i <= lp->m); + min_aij = 1.0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->r_prev == NULL || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_row_aij - determine maximal |a[i,j]| in i-th row +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in i-th row of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If i-th row of the matrix is empty, the routine returns 1. */ + +static double max_row_aij(glp_prob *lp, int i, int scaled) +{ GLPAIJ *aij; + double max_aij, temp; + xassert(1 <= i && i <= lp->m); + max_aij = 1.0; + for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->r_prev == NULL || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* min_col_aij - determine minimal |a[i,j]| in j-th column +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in j-th column of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If j-th column of the matrix is empty, the routine returns 1. */ + +static double min_col_aij(glp_prob *lp, int j, int scaled) +{ GLPAIJ *aij; + double min_aij, temp; + xassert(1 <= j && j <= lp->n); + min_aij = 1.0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->c_prev == NULL || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_col_aij - determine maximal |a[i,j]| in j-th column +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in j-th column of the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If j-th column of the matrix is empty, the routine returns 1. */ + +static double max_col_aij(glp_prob *lp, int j, int scaled) +{ GLPAIJ *aij; + double max_aij, temp; + xassert(1 <= j && j <= lp->n); + max_aij = 1.0; + for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) + { temp = fabs(aij->val); + if (scaled) temp *= (aij->row->rii * aij->col->sjj); + if (aij->c_prev == NULL || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* min_mat_aij - determine minimal |a[i,j]| in constraint matrix +* +* This routine returns minimal magnitude of (non-zero) constraint +* coefficients in the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If the matrix is empty, the routine returns 1. */ + +static double min_mat_aij(glp_prob *lp, int scaled) +{ int i; + double min_aij, temp; + min_aij = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = min_row_aij(lp, i, scaled); + if (i == 1 || min_aij > temp) + min_aij = temp; + } + return min_aij; +} + +/*********************************************************************** +* max_mat_aij - determine maximal |a[i,j]| in constraint matrix +* +* This routine returns maximal magnitude of (non-zero) constraint +* coefficients in the constraint matrix. +* +* If the parameter scaled is zero, the original constraint matrix A is +* assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. +* +* If the matrix is empty, the routine returns 1. */ + +static double max_mat_aij(glp_prob *lp, int scaled) +{ int i; + double max_aij, temp; + max_aij = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, scaled); + if (i == 1 || max_aij < temp) + max_aij = temp; + } + return max_aij; +} + +/*********************************************************************** +* eq_scaling - perform equilibration scaling +* +* This routine performs equilibration scaling of rows and columns of +* the constraint matrix. +* +* If the parameter flag is zero, the routine scales rows at first and +* then columns. Otherwise, the routine scales columns and then rows. +* +* Rows are scaled as follows: +* +* n +* a'[i,j] = a[i,j] / max |a[i,j]|, i = 1,...,m. +* j=1 +* +* This makes the infinity (maximum) norm of each row of the matrix +* equal to 1. +* +* Columns are scaled as follows: +* +* m +* a'[i,j] = a[i,j] / max |a[i,j]|, j = 1,...,n. +* i=1 +* +* This makes the infinity (maximum) norm of each column of the matrix +* equal to 1. */ + +static void eq_scaling(glp_prob *lp, int flag) +{ int i, j, pass; + double temp; + xassert(flag == 0 || flag == 1); + for (pass = 0; pass <= 1; pass++) + { if (pass == flag) + { /* scale rows */ + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, 1); + glp_set_rii(lp, i, glp_get_rii(lp, i) / temp); + } + } + else + { /* scale columns */ + for (j = 1; j <= lp->n; j++) + { temp = max_col_aij(lp, j, 1); + glp_set_sjj(lp, j, glp_get_sjj(lp, j) / temp); + } + } + } + return; +} + +/*********************************************************************** +* gm_scaling - perform geometric mean scaling +* +* This routine performs geometric mean scaling of rows and columns of +* the constraint matrix. +* +* If the parameter flag is zero, the routine scales rows at first and +* then columns. Otherwise, the routine scales columns and then rows. +* +* Rows are scaled as follows: +* +* a'[i,j] = a[i,j] / sqrt(alfa[i] * beta[i]), i = 1,...,m, +* +* where: +* n n +* alfa[i] = min |a[i,j]|, beta[i] = max |a[i,j]|. +* j=1 j=1 +* +* This allows decreasing the ratio beta[i] / alfa[i] for each row of +* the matrix. +* +* Columns are scaled as follows: +* +* a'[i,j] = a[i,j] / sqrt(alfa[j] * beta[j]), j = 1,...,n, +* +* where: +* m m +* alfa[j] = min |a[i,j]|, beta[j] = max |a[i,j]|. +* i=1 i=1 +* +* This allows decreasing the ratio beta[j] / alfa[j] for each column +* of the matrix. */ + +static void gm_scaling(glp_prob *lp, int flag) +{ int i, j, pass; + double temp; + xassert(flag == 0 || flag == 1); + for (pass = 0; pass <= 1; pass++) + { if (pass == flag) + { /* scale rows */ + for (i = 1; i <= lp->m; i++) + { temp = min_row_aij(lp, i, 1) * max_row_aij(lp, i, 1); + glp_set_rii(lp, i, glp_get_rii(lp, i) / sqrt(temp)); + } + } + else + { /* scale columns */ + for (j = 1; j <= lp->n; j++) + { temp = min_col_aij(lp, j, 1) * max_col_aij(lp, j, 1); + glp_set_sjj(lp, j, glp_get_sjj(lp, j) / sqrt(temp)); + } + } + } + return; +} + +/*********************************************************************** +* max_row_ratio - determine worst scaling "quality" for rows +* +* This routine returns the worst scaling "quality" for rows of the +* currently scaled constraint matrix: +* +* m +* ratio = max ratio[i], +* i=1 +* where: +* n n +* ratio[i] = max |a[i,j]| / min |a[i,j]|, 1 <= i <= m, +* j=1 j=1 +* +* is the scaling "quality" of i-th row. */ + +static double max_row_ratio(glp_prob *lp) +{ int i; + double ratio, temp; + ratio = 1.0; + for (i = 1; i <= lp->m; i++) + { temp = max_row_aij(lp, i, 1) / min_row_aij(lp, i, 1); + if (i == 1 || ratio < temp) ratio = temp; + } + return ratio; +} + +/*********************************************************************** +* max_col_ratio - determine worst scaling "quality" for columns +* +* This routine returns the worst scaling "quality" for columns of the +* currently scaled constraint matrix: +* +* n +* ratio = max ratio[j], +* j=1 +* where: +* m m +* ratio[j] = max |a[i,j]| / min |a[i,j]|, 1 <= j <= n, +* i=1 i=1 +* +* is the scaling "quality" of j-th column. */ + +static double max_col_ratio(glp_prob *lp) +{ int j; + double ratio, temp; + ratio = 1.0; + for (j = 1; j <= lp->n; j++) + { temp = max_col_aij(lp, j, 1) / min_col_aij(lp, j, 1); + if (j == 1 || ratio < temp) ratio = temp; + } + return ratio; +} + +/*********************************************************************** +* gm_iterate - perform iterative geometric mean scaling +* +* This routine performs iterative geometric mean scaling of rows and +* columns of the constraint matrix. +* +* The parameter it_max specifies the maximal number of iterations. +* Recommended value of it_max is 15. +* +* The parameter tau specifies a minimal improvement of the scaling +* "quality" on each iteration, 0 < tau < 1. It means than the scaling +* process continues while the following condition is satisfied: +* +* ratio[k] <= tau * ratio[k-1], +* +* where ratio = max |a[i,j]| / min |a[i,j]| is the scaling "quality" +* to be minimized, k is the iteration number. Recommended value of tau +* is 0.90. */ + +static void gm_iterate(glp_prob *lp, int it_max, double tau) +{ int k, flag; + double ratio = 0.0, r_old; + /* if the scaling "quality" for rows is better than for columns, + the rows are scaled first; otherwise, the columns are scaled + first */ + flag = (max_row_ratio(lp) > max_col_ratio(lp)); + for (k = 1; k <= it_max; k++) + { /* save the scaling "quality" from previous iteration */ + r_old = ratio; + /* determine the current scaling "quality" */ + ratio = max_mat_aij(lp, 1) / min_mat_aij(lp, 1); +#if 0 + xprintf("k = %d; ratio = %g\n", k, ratio); +#endif + /* if improvement is not enough, terminate scaling */ + if (k > 1 && ratio > tau * r_old) break; + /* otherwise, perform another iteration */ + gm_scaling(lp, flag); + } + return; +} + +/*********************************************************************** +* NAME +* +* scale_prob - scale problem data +* +* SYNOPSIS +* +* #include "glpscl.h" +* void scale_prob(glp_prob *lp, int flags); +* +* DESCRIPTION +* +* The routine scale_prob performs automatic scaling of problem data +* for the specified problem object. */ + +static void scale_prob(glp_prob *lp, int flags) +{ static const char *fmt = + "%s: min|aij| = %10.3e max|aij| = %10.3e ratio = %10.3e\n"; + double min_aij, max_aij, ratio; + xprintf("Scaling...\n"); + /* cancel the current scaling effect */ + glp_unscale_prob(lp); + /* report original scaling "quality" */ + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, " A", min_aij, max_aij, ratio); + /* check if the problem is well scaled */ + if (min_aij >= 0.10 && max_aij <= 10.0) + { xprintf("Problem data seem to be well scaled\n"); + /* skip scaling, if required */ + if (flags & GLP_SF_SKIP) goto done; + } + /* perform iterative geometric mean scaling, if required */ + if (flags & GLP_SF_GM) + { gm_iterate(lp, 15, 0.90); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "GM", min_aij, max_aij, ratio); + } + /* perform equilibration scaling, if required */ + if (flags & GLP_SF_EQ) + { eq_scaling(lp, max_row_ratio(lp) > max_col_ratio(lp)); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "EQ", min_aij, max_aij, ratio); + } + /* round scale factors to nearest power of two, if required */ + if (flags & GLP_SF_2N) + { int i, j; + for (i = 1; i <= lp->m; i++) + glp_set_rii(lp, i, round2n(glp_get_rii(lp, i))); + for (j = 1; j <= lp->n; j++) + glp_set_sjj(lp, j, round2n(glp_get_sjj(lp, j))); + min_aij = min_mat_aij(lp, 1); + max_aij = max_mat_aij(lp, 1); + ratio = max_aij / min_aij; + xprintf(fmt, "2N", min_aij, max_aij, ratio); + } +done: return; +} + +/*********************************************************************** +* NAME +* +* glp_scale_prob - scale problem data +* +* SYNOPSIS +* +* void glp_scale_prob(glp_prob *lp, int flags); +* +* DESCRIPTION +* +* The routine glp_scale_prob performs automatic scaling of problem +* data for the specified problem object. +* +* The parameter flags specifies scaling options used by the routine. +* Options can be combined with the bitwise OR operator and may be the +* following: +* +* GLP_SF_GM perform geometric mean scaling; +* GLP_SF_EQ perform equilibration scaling; +* GLP_SF_2N round scale factors to nearest power of two; +* GLP_SF_SKIP skip scaling, if the problem is well scaled. +* +* The parameter flags may be specified as GLP_SF_AUTO, in which case +* the routine chooses scaling options automatically. */ + +void glp_scale_prob(glp_prob *lp, int flags) +{ if (flags & ~(GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP | + GLP_SF_AUTO)) + xerror("glp_scale_prob: flags = 0x%02X; invalid scaling option" + "s\n", flags); + if (flags & GLP_SF_AUTO) + flags = (GLP_SF_GM | GLP_SF_EQ | GLP_SF_SKIP); + scale_prob(lp, flags); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.c new file mode 100644 index 000000000..c6cfd25dd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.c @@ -0,0 +1,847 @@ +/* glpspm.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "glphbm.h" +#include "glprgr.h" +#include "glpspm.h" +#include "env.h" + +/*********************************************************************** +* NAME +* +* spm_create_mat - create general sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_create_mat(int m, int n); +* +* DESCRIPTION +* +* The routine spm_create_mat creates a general sparse matrix having +* m rows and n columns. Being created the matrix is zero (empty), i.e. +* has no elements. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_create_mat(int m, int n) +{ SPM *A; + xassert(0 <= m && m < INT_MAX); + xassert(0 <= n && n < INT_MAX); + A = xmalloc(sizeof(SPM)); + A->m = m; + A->n = n; + if (m == 0 || n == 0) + { A->pool = NULL; + A->row = NULL; + A->col = NULL; + } + else + { int i, j; + A->pool = dmp_create_pool(); + A->row = xcalloc(1+m, sizeof(SPME *)); + for (i = 1; i <= m; i++) A->row[i] = NULL; + A->col = xcalloc(1+n, sizeof(SPME *)); + for (j = 1; j <= n; j++) A->col[j] = NULL; + } + return A; +} + +/*********************************************************************** +* NAME +* +* spm_new_elem - add new element to sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPME *spm_new_elem(SPM *A, int i, int j, double val); +* +* DESCRIPTION +* +* The routine spm_new_elem adds a new element to the specified sparse +* matrix. Parameters i, j, and val specify the row number, the column +* number, and a numerical value of the element, respectively. +* +* RETURNS +* +* The routine returns a pointer to the new element added. */ + +SPME *spm_new_elem(SPM *A, int i, int j, double val) +{ SPME *e; + xassert(1 <= i && i <= A->m); + xassert(1 <= j && j <= A->n); + e = dmp_get_atom(A->pool, sizeof(SPME)); + e->i = i; + e->j = j; + e->val = val; + e->r_prev = NULL; + e->r_next = A->row[i]; + if (e->r_next != NULL) e->r_next->r_prev = e; + e->c_prev = NULL; + e->c_next = A->col[j]; + if (e->c_next != NULL) e->c_next->c_prev = e; + A->row[i] = A->col[j] = e; + return e; +} + +/*********************************************************************** +* NAME +* +* spm_delete_mat - delete general sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* void spm_delete_mat(SPM *A); +* +* DESCRIPTION +* +* The routine deletes the specified general sparse matrix freeing all +* the memory allocated to this object. */ + +void spm_delete_mat(SPM *A) +{ /* delete sparse matrix */ + if (A->pool != NULL) dmp_delete_pool(A->pool); + if (A->row != NULL) xfree(A->row); + if (A->col != NULL) xfree(A->col); + xfree(A); + return; +} + +/*********************************************************************** +* NAME +* +* spm_test_mat_e - create test sparse matrix of E(n,c) class +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_test_mat_e(int n, int c); +* +* DESCRIPTION +* +* The routine spm_test_mat_e creates a test sparse matrix of E(n,c) +* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct +* Methods for Sparse Matrices. Springer-Verlag, 1983. +* +* Matrix of E(n,c) class is a symmetric positive definite matrix of +* the order n. It has the number 4 on its main diagonal and the number +* -1 on its four co-diagonals, two of which are neighbour to the main +* diagonal and two others are shifted from the main diagonal on the +* distance c. +* +* It is necessary that n >= 3 and 2 <= c <= n-1. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_test_mat_e(int n, int c) +{ SPM *A; + int i; + xassert(n >= 3 && 2 <= c && c <= n-1); + A = spm_create_mat(n, n); + for (i = 1; i <= n; i++) + spm_new_elem(A, i, i, 4.0); + for (i = 1; i <= n-1; i++) + { spm_new_elem(A, i, i+1, -1.0); + spm_new_elem(A, i+1, i, -1.0); + } + for (i = 1; i <= n-c; i++) + { spm_new_elem(A, i, i+c, -1.0); + spm_new_elem(A, i+c, i, -1.0); + } + return A; +} + +/*********************************************************************** +* NAME +* +* spm_test_mat_d - create test sparse matrix of D(n,c) class +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_test_mat_d(int n, int c); +* +* DESCRIPTION +* +* The routine spm_test_mat_d creates a test sparse matrix of D(n,c) +* class as described in the book: Ole 0sterby, Zahari Zlatev. Direct +* Methods for Sparse Matrices. Springer-Verlag, 1983. +* +* Matrix of D(n,c) class is a non-singular matrix of the order n. It +* has unity main diagonal, three co-diagonals above the main diagonal +* on the distance c, which are cyclically continued below the main +* diagonal, and a triangle block of the size 10x10 in the upper right +* corner. +* +* It is necessary that n >= 14 and 1 <= c <= n-13. +* +* RETURNS +* +* The routine returns a pointer to the matrix created. */ + +SPM *spm_test_mat_d(int n, int c) +{ SPM *A; + int i, j; + xassert(n >= 14 && 1 <= c && c <= n-13); + A = spm_create_mat(n, n); + for (i = 1; i <= n; i++) + spm_new_elem(A, i, i, 1.0); + for (i = 1; i <= n-c; i++) + spm_new_elem(A, i, i+c, (double)(i+1)); + for (i = n-c+1; i <= n; i++) + spm_new_elem(A, i, i-n+c, (double)(i+1)); + for (i = 1; i <= n-c-1; i++) + spm_new_elem(A, i, i+c+1, (double)(-i)); + for (i = n-c; i <= n; i++) + spm_new_elem(A, i, i-n+c+1, (double)(-i)); + for (i = 1; i <= n-c-2; i++) + spm_new_elem(A, i, i+c+2, 16.0); + for (i = n-c-1; i <= n; i++) + spm_new_elem(A, i, i-n+c+2, 16.0); + for (j = 1; j <= 10; j++) + for (i = 1; i <= 11-j; i++) + spm_new_elem(A, i, n-11+i+j, 100.0 * (double)j); + return A; +} + +/*********************************************************************** +* NAME +* +* spm_show_mat - write sparse matrix pattern in BMP file format +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_show_mat(const SPM *A, const char *fname); +* +* DESCRIPTION +* +* The routine spm_show_mat writes pattern of the specified sparse +* matrix in uncompressed BMP file format (Windows bitmap) to a binary +* file whose name is specified by the character string fname. +* +* Each pixel corresponds to one matrix element. The pixel colors have +* the following meaning: +* +* Black structurally zero element +* White positive element +* Cyan negative element +* Green zero element +* Red duplicate element +* +* RETURNS +* +* If no error occured, the routine returns zero. Otherwise, it prints +* an appropriate error message and returns non-zero. */ + +int spm_show_mat(const SPM *A, const char *fname) +{ int m = A->m; + int n = A->n; + int i, j, k, ret; + char *map; + xprintf("spm_show_mat: writing matrix pattern to '%s'...\n", + fname); + xassert(1 <= m && m <= 32767); + xassert(1 <= n && n <= 32767); + map = xmalloc(m * n); + memset(map, 0x08, m * n); + for (i = 1; i <= m; i++) + { SPME *e; + for (e = A->row[i]; e != NULL; e = e->r_next) + { j = e->j; + xassert(1 <= j && j <= n); + k = n * (i - 1) + (j - 1); + if (map[k] != 0x08) + map[k] = 0x0C; + else if (e->val > 0.0) + map[k] = 0x0F; + else if (e->val < 0.0) + map[k] = 0x0B; + else + map[k] = 0x0A; + } + } + ret = rgr_write_bmp16(fname, m, n, map); + xfree(map); + return ret; +} + +/*********************************************************************** +* NAME +* +* spm_read_hbm - read sparse matrix in Harwell-Boeing format +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_read_hbm(const char *fname); +* +* DESCRIPTION +* +* The routine spm_read_hbm reads a sparse matrix in the Harwell-Boeing +* format from a text file whose name is the character string fname. +* +* Detailed description of the Harwell-Boeing format recognised by this +* routine can be found in the following report: +* +* I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing +* Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. +* +* NOTE +* +* The routine spm_read_hbm reads the matrix "as is", due to which zero +* and/or duplicate elements can appear in the matrix. +* +* RETURNS +* +* If no error occured, the routine returns a pointer to the matrix +* created. Otherwise, the routine prints an appropriate error message +* and returns NULL. */ + +SPM *spm_read_hbm(const char *fname) +{ SPM *A = NULL; + HBM *hbm; + int nrow, ncol, nnzero, i, j, beg, end, ptr, *colptr, *rowind; + double val, *values; + char *mxtype; + hbm = hbm_read_mat(fname); + if (hbm == NULL) + { xprintf("spm_read_hbm: unable to read matrix\n"); + goto fini; + } + mxtype = hbm->mxtype; + nrow = hbm->nrow; + ncol = hbm->ncol; + nnzero = hbm->nnzero; + colptr = hbm->colptr; + rowind = hbm->rowind; + values = hbm->values; + if (!(strcmp(mxtype, "RSA") == 0 || strcmp(mxtype, "PSA") == 0 || + strcmp(mxtype, "RUA") == 0 || strcmp(mxtype, "PUA") == 0 || + strcmp(mxtype, "RRA") == 0 || strcmp(mxtype, "PRA") == 0)) + { xprintf("spm_read_hbm: matrix type '%s' not supported\n", + mxtype); + goto fini; + } + A = spm_create_mat(nrow, ncol); + if (mxtype[1] == 'S' || mxtype[1] == 'U') + xassert(nrow == ncol); + for (j = 1; j <= ncol; j++) + { beg = colptr[j]; + end = colptr[j+1]; + xassert(1 <= beg && beg <= end && end <= nnzero + 1); + for (ptr = beg; ptr < end; ptr++) + { i = rowind[ptr]; + xassert(1 <= i && i <= nrow); + if (mxtype[0] == 'R') + val = values[ptr]; + else + val = 1.0; + spm_new_elem(A, i, j, val); + if (mxtype[1] == 'S' && i != j) + spm_new_elem(A, j, i, val); + } + } +fini: if (hbm != NULL) hbm_free_mat(hbm); + return A; +} + +/*********************************************************************** +* NAME +* +* spm_count_nnz - determine number of non-zeros in sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_count_nnz(const SPM *A); +* +* RETURNS +* +* The routine spm_count_nnz returns the number of structural non-zero +* elements in the specified sparse matrix. */ + +int spm_count_nnz(const SPM *A) +{ SPME *e; + int i, nnz = 0; + for (i = 1; i <= A->m; i++) + for (e = A->row[i]; e != NULL; e = e->r_next) nnz++; + return nnz; +} + +/*********************************************************************** +* NAME +* +* spm_drop_zeros - remove zero elements from sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_drop_zeros(SPM *A, double eps); +* +* DESCRIPTION +* +* The routine spm_drop_zeros removes all elements from the specified +* sparse matrix, whose absolute value is less than eps. +* +* If the parameter eps is 0, only zero elements are removed from the +* matrix. +* +* RETURNS +* +* The routine returns the number of elements removed. */ + +int spm_drop_zeros(SPM *A, double eps) +{ SPME *e, *next; + int i, count = 0; + for (i = 1; i <= A->m; i++) + { for (e = A->row[i]; e != NULL; e = next) + { next = e->r_next; + if (e->val == 0.0 || fabs(e->val) < eps) + { /* remove element from the row list */ + if (e->r_prev == NULL) + A->row[e->i] = e->r_next; + else + e->r_prev->r_next = e->r_next; + if (e->r_next == NULL) + ; + else + e->r_next->r_prev = e->r_prev; + /* remove element from the column list */ + if (e->c_prev == NULL) + A->col[e->j] = e->c_next; + else + e->c_prev->c_next = e->c_next; + if (e->c_next == NULL) + ; + else + e->c_next->c_prev = e->c_prev; + /* return element to the memory pool */ + dmp_free_atom(A->pool, e, sizeof(SPME)); + count++; + } + } + } + return count; +} + +/*********************************************************************** +* NAME +* +* spm_read_mat - read sparse matrix from text file +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_read_mat(const char *fname); +* +* DESCRIPTION +* +* The routine reads a sparse matrix from a text file whose name is +* specified by the parameter fname. +* +* For the file format see description of the routine spm_write_mat. +* +* RETURNS +* +* On success the routine returns a pointer to the matrix created, +* otherwise NULL. */ + +#if 1 +SPM *spm_read_mat(const char *fname) +{ xassert(fname != fname); + return NULL; +} +#else +SPM *spm_read_mat(const char *fname) +{ SPM *A = NULL; + PDS *pds; + jmp_buf jump; + int i, j, k, m, n, nnz, fail = 0; + double val; + xprintf("spm_read_mat: reading matrix from '%s'...\n", fname); + pds = pds_open_file(fname); + if (pds == NULL) + { xprintf("spm_read_mat: unable to open '%s' - %s\n", fname, + strerror(errno)); + fail = 1; + goto done; + } + if (setjmp(jump)) + { fail = 1; + goto done; + } + pds_set_jump(pds, jump); + /* number of rows, number of columns, number of non-zeros */ + m = pds_scan_int(pds); + if (m < 0) + pds_error(pds, "invalid number of rows\n"); + n = pds_scan_int(pds); + if (n < 0) + pds_error(pds, "invalid number of columns\n"); + nnz = pds_scan_int(pds); + if (nnz < 0) + pds_error(pds, "invalid number of non-zeros\n"); + /* create matrix */ + xprintf("spm_read_mat: %d rows, %d columns, %d non-zeros\n", + m, n, nnz); + A = spm_create_mat(m, n); + /* read matrix elements */ + for (k = 1; k <= nnz; k++) + { /* row index, column index, element value */ + i = pds_scan_int(pds); + if (!(1 <= i && i <= m)) + pds_error(pds, "row index out of range\n"); + j = pds_scan_int(pds); + if (!(1 <= j && j <= n)) + pds_error(pds, "column index out of range\n"); + val = pds_scan_num(pds); + /* add new element to the matrix */ + spm_new_elem(A, i, j, val); + } + xprintf("spm_read_mat: %d lines were read\n", pds->count); +done: if (pds != NULL) pds_close_file(pds); + if (fail && A != NULL) spm_delete_mat(A), A = NULL; + return A; +} +#endif + +/*********************************************************************** +* NAME +* +* spm_write_mat - write sparse matrix to text file +* +* SYNOPSIS +* +* #include "glpspm.h" +* int spm_write_mat(const SPM *A, const char *fname); +* +* DESCRIPTION +* +* The routine spm_write_mat writes the specified sparse matrix to a +* text file whose name is specified by the parameter fname. This file +* can be read back with the routine spm_read_mat. +* +* RETURNS +* +* On success the routine returns zero, otherwise non-zero. +* +* FILE FORMAT +* +* The file created by the routine spm_write_mat is a plain text file, +* which contains the following information: +* +* m n nnz +* row[1] col[1] val[1] +* row[2] col[2] val[2] +* . . . +* row[nnz] col[nnz] val[nnz] +* +* where: +* m is the number of rows; +* n is the number of columns; +* nnz is the number of non-zeros; +* row[k], k = 1,...,nnz, are row indices; +* col[k], k = 1,...,nnz, are column indices; +* val[k], k = 1,...,nnz, are element values. */ + +#if 1 +int spm_write_mat(const SPM *A, const char *fname) +{ xassert(A != A); + xassert(fname != fname); + return 0; +} +#else +int spm_write_mat(const SPM *A, const char *fname) +{ FILE *fp; + int i, nnz, ret = 0; + xprintf("spm_write_mat: writing matrix to '%s'...\n", fname); + fp = fopen(fname, "w"); + if (fp == NULL) + { xprintf("spm_write_mat: unable to create '%s' - %s\n", fname, + strerror(errno)); + ret = 1; + goto done; + } + /* number of rows, number of columns, number of non-zeros */ + nnz = spm_count_nnz(A); + fprintf(fp, "%d %d %d\n", A->m, A->n, nnz); + /* walk through rows of the matrix */ + for (i = 1; i <= A->m; i++) + { SPME *e; + /* walk through elements of i-th row */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { /* row index, column index, element value */ + fprintf(fp, "%d %d %.*g\n", e->i, e->j, DBL_DIG, e->val); + } + } + fflush(fp); + if (ferror(fp)) + { xprintf("spm_write_mat: writing error on '%s' - %s\n", fname, + strerror(errno)); + ret = 1; + goto done; + } + xprintf("spm_write_mat: %d lines were written\n", 1 + nnz); +done: if (fp != NULL) fclose(fp); + return ret; +} +#endif + +/*********************************************************************** +* NAME +* +* spm_transpose - transpose sparse matrix +* +* SYNOPSIS +* +* #include "glpspm.h" +* SPM *spm_transpose(const SPM *A); +* +* RETURNS +* +* The routine computes and returns sparse matrix B, which is a matrix +* transposed to sparse matrix A. */ + +SPM *spm_transpose(const SPM *A) +{ SPM *B; + int i; + B = spm_create_mat(A->n, A->m); + for (i = 1; i <= A->m; i++) + { SPME *e; + for (e = A->row[i]; e != NULL; e = e->r_next) + spm_new_elem(B, e->j, i, e->val); + } + return B; +} + +SPM *spm_add_sym(const SPM *A, const SPM *B) +{ /* add two sparse matrices (symbolic phase) */ + SPM *C; + int i, j, *flag; + xassert(A->m == B->m); + xassert(A->n == B->n); + /* create resultant matrix */ + C = spm_create_mat(A->m, A->n); + /* allocate and clear the flag array */ + flag = xcalloc(1+C->n, sizeof(int)); + for (j = 1; j <= C->n; j++) + flag[j] = 0; + /* compute pattern of C = A + B */ + for (i = 1; i <= C->m; i++) + { SPME *e; + /* at the beginning i-th row of C is empty */ + /* (i-th row of C) := (i-th row of C) union (i-th row of A) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { /* (note that i-th row of A may have duplicate elements) */ + j = e->j; + if (!flag[j]) + { spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + /* (i-th row of C) := (i-th row of C) union (i-th row of B) */ + for (e = B->row[i]; e != NULL; e = e->r_next) + { /* (note that i-th row of B may have duplicate elements) */ + j = e->j; + if (!flag[j]) + { spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + /* reset the flag array */ + for (e = C->row[i]; e != NULL; e = e->r_next) + flag[e->j] = 0; + } + /* check and deallocate the flag array */ + for (j = 1; j <= C->n; j++) + xassert(!flag[j]); + xfree(flag); + return C; +} + +void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, + const SPM *B) +{ /* add two sparse matrices (numeric phase) */ + int i, j; + double *work; + /* allocate and clear the working array */ + work = xcalloc(1+C->n, sizeof(double)); + for (j = 1; j <= C->n; j++) + work[j] = 0.0; + /* compute matrix C = alfa * A + beta * B */ + for (i = 1; i <= C->n; i++) + { SPME *e; + /* work := alfa * (i-th row of A) + beta * (i-th row of B) */ + /* (note that A and/or B may have duplicate elements) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] += alfa * e->val; + for (e = B->row[i]; e != NULL; e = e->r_next) + work[e->j] += beta * e->val; + /* (i-th row of C) := work, work := 0 */ + for (e = C->row[i]; e != NULL; e = e->r_next) + { j = e->j; + e->val = work[j]; + work[j] = 0.0; + } + } + /* check and deallocate the working array */ + for (j = 1; j <= C->n; j++) + xassert(work[j] == 0.0); + xfree(work); + return; +} + +SPM *spm_add_mat(double alfa, const SPM *A, double beta, const SPM *B) +{ /* add two sparse matrices (driver routine) */ + SPM *C; + C = spm_add_sym(A, B); + spm_add_num(C, alfa, A, beta, B); + return C; +} + +SPM *spm_mul_sym(const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (symbolic phase) */ + int i, j, k, *flag; + SPM *C; + xassert(A->n == B->m); + /* create resultant matrix */ + C = spm_create_mat(A->m, B->n); + /* allocate and clear the flag array */ + flag = xcalloc(1+C->n, sizeof(int)); + for (j = 1; j <= C->n; j++) + flag[j] = 0; + /* compute pattern of C = A * B */ + for (i = 1; i <= C->m; i++) + { SPME *e, *ee; + /* compute pattern of i-th row of C */ + for (e = A->row[i]; e != NULL; e = e->r_next) + { k = e->j; + for (ee = B->row[k]; ee != NULL; ee = ee->r_next) + { j = ee->j; + /* if a[i,k] != 0 and b[k,j] != 0 then c[i,j] != 0 */ + if (!flag[j]) + { /* c[i,j] does not exist, so create it */ + spm_new_elem(C, i, j, 0.0); + flag[j] = 1; + } + } + } + /* reset the flag array */ + for (e = C->row[i]; e != NULL; e = e->r_next) + flag[e->j] = 0; + } + /* check and deallocate the flag array */ + for (j = 1; j <= C->n; j++) + xassert(!flag[j]); + xfree(flag); + return C; +} + +void spm_mul_num(SPM *C, const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (numeric phase) */ + int i, j; + double *work; + /* allocate and clear the working array */ + work = xcalloc(1+A->n, sizeof(double)); + for (j = 1; j <= A->n; j++) + work[j] = 0.0; + /* compute matrix C = A * B */ + for (i = 1; i <= C->m; i++) + { SPME *e, *ee; + double temp; + /* work := (i-th row of A) */ + /* (note that A may have duplicate elements) */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] += e->val; + /* compute i-th row of C */ + for (e = C->row[i]; e != NULL; e = e->r_next) + { j = e->j; + /* c[i,j] := work * (j-th column of B) */ + temp = 0.0; + for (ee = B->col[j]; ee != NULL; ee = ee->c_next) + temp += work[ee->i] * ee->val; + e->val = temp; + } + /* reset the working array */ + for (e = A->row[i]; e != NULL; e = e->r_next) + work[e->j] = 0.0; + } + /* check and deallocate the working array */ + for (j = 1; j <= A->n; j++) + xassert(work[j] == 0.0); + xfree(work); + return; +} + +SPM *spm_mul_mat(const SPM *A, const SPM *B) +{ /* multiply two sparse matrices (driver routine) */ + SPM *C; + C = spm_mul_sym(A, B); + spm_mul_num(C, A, B); + return C; +} + +PER *spm_create_per(int n) +{ /* create permutation matrix */ + PER *P; + int k; + xassert(n >= 0); + P = xmalloc(sizeof(PER)); + P->n = n; + P->row = xcalloc(1+n, sizeof(int)); + P->col = xcalloc(1+n, sizeof(int)); + /* initially it is identity matrix */ + for (k = 1; k <= n; k++) + P->row[k] = P->col[k] = k; + return P; +} + +void spm_check_per(PER *P) +{ /* check permutation matrix for correctness */ + int i, j; + xassert(P->n >= 0); + for (i = 1; i <= P->n; i++) + { j = P->row[i]; + xassert(1 <= j && j <= P->n); + xassert(P->col[j] == i); + } + return; +} + +void spm_delete_per(PER *P) +{ /* delete permutation matrix */ + xfree(P->row); + xfree(P->col); + xfree(P); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.h new file mode 100644 index 000000000..eda9f98f2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpspm.h @@ -0,0 +1,165 @@ +/* glpspm.h (general sparse matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPSPM_H +#define GLPSPM_H + +#include "dmp.h" + +typedef struct SPM SPM; +typedef struct SPME SPME; + +struct SPM +{ /* general sparse matrix */ + int m; + /* number of rows, m >= 0 */ + int n; + /* number of columns, n >= 0 */ + DMP *pool; + /* memory pool to store matrix elements */ + SPME **row; /* SPME *row[1+m]; */ + /* row[i], 1 <= i <= m, is a pointer to i-th row list */ + SPME **col; /* SPME *col[1+n]; */ + /* col[j], 1 <= j <= n, is a pointer to j-th column list */ +}; + +struct SPME +{ /* sparse matrix element */ + int i; + /* row number */ + int j; + /* column number */ + double val; + /* element value */ + SPME *r_prev; + /* pointer to previous element in the same row */ + SPME *r_next; + /* pointer to next element in the same row */ + SPME *c_prev; + /* pointer to previous element in the same column */ + SPME *c_next; + /* pointer to next element in the same column */ +}; + +typedef struct PER PER; + +struct PER +{ /* permutation matrix */ + int n; + /* matrix order, n >= 0 */ + int *row; /* int row[1+n]; */ + /* row[i] = j means p[i,j] = 1 */ + int *col; /* int col[1+n]; */ + /* col[j] = i means p[i,j] = 1 */ +}; + +#define spm_create_mat _glp_spm_create_mat +SPM *spm_create_mat(int m, int n); +/* create general sparse matrix */ + +#define spm_new_elem _glp_spm_new_elem +SPME *spm_new_elem(SPM *A, int i, int j, double val); +/* add new element to sparse matrix */ + +#define spm_delete_mat _glp_spm_delete_mat +void spm_delete_mat(SPM *A); +/* delete general sparse matrix */ + +#define spm_test_mat_e _glp_spm_test_mat_e +SPM *spm_test_mat_e(int n, int c); +/* create test sparse matrix of E(n,c) class */ + +#define spm_test_mat_d _glp_spm_test_mat_d +SPM *spm_test_mat_d(int n, int c); +/* create test sparse matrix of D(n,c) class */ + +#define spm_show_mat _glp_spm_show_mat +int spm_show_mat(const SPM *A, const char *fname); +/* write sparse matrix pattern in BMP file format */ + +#define spm_read_hbm _glp_spm_read_hbm +SPM *spm_read_hbm(const char *fname); +/* read sparse matrix in Harwell-Boeing format */ + +#define spm_count_nnz _glp_spm_count_nnz +int spm_count_nnz(const SPM *A); +/* determine number of non-zeros in sparse matrix */ + +#define spm_drop_zeros _glp_spm_drop_zeros +int spm_drop_zeros(SPM *A, double eps); +/* remove zero elements from sparse matrix */ + +#define spm_read_mat _glp_spm_read_mat +SPM *spm_read_mat(const char *fname); +/* read sparse matrix from text file */ + +#define spm_write_mat _glp_spm_write_mat +int spm_write_mat(const SPM *A, const char *fname); +/* write sparse matrix to text file */ + +#define spm_transpose _glp_spm_transpose +SPM *spm_transpose(const SPM *A); +/* transpose sparse matrix */ + +#define spm_add_sym _glp_spm_add_sym +SPM *spm_add_sym(const SPM *A, const SPM *B); +/* add two sparse matrices (symbolic phase) */ + +#define spm_add_num _glp_spm_add_num +void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, + const SPM *B); +/* add two sparse matrices (numeric phase) */ + +#define spm_add_mat _glp_spm_add_mat +SPM *spm_add_mat(double alfa, const SPM *A, double beta, + const SPM *B); +/* add two sparse matrices (driver routine) */ + +#define spm_mul_sym _glp_spm_mul_sym +SPM *spm_mul_sym(const SPM *A, const SPM *B); +/* multiply two sparse matrices (symbolic phase) */ + +#define spm_mul_num _glp_spm_mul_num +void spm_mul_num(SPM *C, const SPM *A, const SPM *B); +/* multiply two sparse matrices (numeric phase) */ + +#define spm_mul_mat _glp_spm_mul_mat +SPM *spm_mul_mat(const SPM *A, const SPM *B); +/* multiply two sparse matrices (driver routine) */ + +#define spm_create_per _glp_spm_create_per +PER *spm_create_per(int n); +/* create permutation matrix */ + +#define spm_check_per _glp_spm_check_per +void spm_check_per(PER *P); +/* check permutation matrix for correctness */ + +#define spm_delete_per _glp_spm_delete_per +void spm_delete_per(PER *P); +/* delete permutation matrix */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx.h new file mode 100644 index 000000000..3b52b3cc5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx.h @@ -0,0 +1,437 @@ +/* glpssx.h (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPSSX_H +#define GLPSSX_H + +#include "bfx.h" +#include "env.h" +#if 1 /* 25/XI-2017 */ +#include "glpk.h" +#endif + +typedef struct SSX SSX; + +struct SSX +{ /* simplex solver workspace */ +/*---------------------------------------------------------------------- +// LP PROBLEM DATA +// +// It is assumed that LP problem has the following statement: +// +// minimize (or maximize) +// +// z = c[1]*x[1] + ... + c[m+n]*x[m+n] + c[0] (1) +// +// subject to equality constraints +// +// x[1] - a[1,1]*x[m+1] - ... - a[1,n]*x[m+n] = 0 +// +// . . . . . . . (2) +// +// x[m] - a[m,1]*x[m+1] + ... - a[m,n]*x[m+n] = 0 +// +// and bounds of variables +// +// l[1] <= x[1] <= u[1] +// +// . . . . . . . (3) +// +// l[m+n] <= x[m+n] <= u[m+n] +// +// where: +// x[1], ..., x[m] - auxiliary variables; +// x[m+1], ..., x[m+n] - structural variables; +// z - objective function; +// c[1], ..., c[m+n] - coefficients of the objective function; +// c[0] - constant term of the objective function; +// a[1,1], ..., a[m,n] - constraint coefficients; +// l[1], ..., l[m+n] - lower bounds of variables; +// u[1], ..., u[m+n] - upper bounds of variables. +// +// Bounds of variables can be finite as well as inifinite. Besides, +// lower and upper bounds can be equal to each other. So the following +// five types of variables are possible: +// +// Bounds of variable Type of variable +// ------------------------------------------------- +// -inf < x[k] < +inf Free (unbounded) variable +// l[k] <= x[k] < +inf Variable with lower bound +// -inf < x[k] <= u[k] Variable with upper bound +// l[k] <= x[k] <= u[k] Double-bounded variable +// l[k] = x[k] = u[k] Fixed variable +// +// Using vector-matrix notations the LP problem (1)-(3) can be written +// as follows: +// +// minimize (or maximize) +// +// z = c * x + c[0] (4) +// +// subject to equality constraints +// +// xR - A * xS = 0 (5) +// +// and bounds of variables +// +// l <= x <= u (6) +// +// where: +// xR - vector of auxiliary variables; +// xS - vector of structural variables; +// x = (xR, xS) - vector of all variables; +// z - objective function; +// c - vector of objective coefficients; +// c[0] - constant term of the objective function; +// A - matrix of constraint coefficients (has m rows +// and n columns); +// l - vector of lower bounds of variables; +// u - vector of upper bounds of variables. +// +// The simplex method makes no difference between auxiliary and +// structural variables, so it is convenient to think the system of +// equality constraints (5) written in a homogeneous form: +// +// (I | -A) * x = 0, (7) +// +// where (I | -A) is an augmented (m+n)xm constraint matrix, I is mxm +// unity matrix whose columns correspond to auxiliary variables, and A +// is the original mxn constraint matrix whose columns correspond to +// structural variables. Note that only the matrix A is stored. +----------------------------------------------------------------------*/ + int m; + /* number of rows (auxiliary variables), m > 0 */ + int n; + /* number of columns (structural variables), n > 0 */ + int *type; /* int type[1+m+n]; */ + /* type[0] is not used; + type[k], 1 <= k <= m+n, is the type of variable x[k]: */ +#define SSX_FR 0 /* free (unbounded) variable */ +#define SSX_LO 1 /* variable with lower bound */ +#define SSX_UP 2 /* variable with upper bound */ +#define SSX_DB 3 /* double-bounded variable */ +#define SSX_FX 4 /* fixed variable */ + mpq_t *lb; /* mpq_t lb[1+m+n]; alias: l */ + /* lb[0] is not used; + lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; + if x[k] has no lower bound, lb[k] is zero */ + mpq_t *ub; /* mpq_t ub[1+m+n]; alias: u */ + /* ub[0] is not used; + ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; + if x[k] has no upper bound, ub[k] is zero; + if x[k] is of fixed type, ub[k] is equal to lb[k] */ + int dir; + /* optimization direction (sense of the objective function): */ +#define SSX_MIN 0 /* minimization */ +#define SSX_MAX 1 /* maximization */ + mpq_t *coef; /* mpq_t coef[1+m+n]; alias: c */ + /* coef[0] is a constant term of the objective function; + coef[k], 1 <= k <= m+n, is a coefficient of the objective + function at variable x[k]; + note that auxiliary variables also may have non-zero objective + coefficients */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + int *A_ind; /* int A_ind[A_ptr[n+1]]; */ + mpq_t *A_val; /* mpq_t A_val[A_ptr[n+1]]; */ + /* constraint matrix A (see (5)) in storage-by-columns format */ +/*---------------------------------------------------------------------- +// LP BASIS AND CURRENT BASIC SOLUTION +// +// The LP basis is defined by the following partition of the augmented +// constraint matrix (7): +// +// (B | N) = (I | -A) * Q, (8) +// +// where B is a mxm non-singular basis matrix whose columns correspond +// to basic variables xB, N is a mxn matrix whose columns correspond to +// non-basic variables xN, and Q is a permutation (m+n)x(m+n) matrix. +// +// From (7) and (8) it follows that +// +// (I | -A) * x = (I | -A) * Q * Q' * x = (B | N) * (xB, xN), +// +// therefore +// +// (xB, xN) = Q' * x, (9) +// +// where x is the vector of all variables in the original order, xB is +// a vector of basic variables, xN is a vector of non-basic variables, +// Q' = inv(Q) is a matrix transposed to Q. +// +// Current values of non-basic variables xN[j], j = 1, ..., n, are not +// stored; they are defined implicitly by their statuses as follows: +// +// 0, if xN[j] is free variable +// lN[j], if xN[j] is on its lower bound (10) +// uN[j], if xN[j] is on its upper bound +// lN[j] = uN[j], if xN[j] is fixed variable +// +// where lN[j] and uN[j] are lower and upper bounds of xN[j]. +// +// Current values of basic variables xB[i], i = 1, ..., m, are computed +// as follows: +// +// beta = - inv(B) * N * xN, (11) +// +// where current values of xN are defined by (10). +// +// Current values of simplex multipliers pi[i], i = 1, ..., m (which +// are values of Lagrange multipliers for equality constraints (7) also +// called shadow prices) are computed as follows: +// +// pi = inv(B') * cB, (12) +// +// where B' is a matrix transposed to B, cB is a vector of objective +// coefficients at basic variables xB. +// +// Current values of reduced costs d[j], j = 1, ..., n, (which are +// values of Langrange multipliers for active inequality constraints +// corresponding to non-basic variables) are computed as follows: +// +// d = cN - N' * pi, (13) +// +// where N' is a matrix transposed to N, cN is a vector of objective +// coefficients at non-basic variables xN. +----------------------------------------------------------------------*/ + int *stat; /* int stat[1+m+n]; */ + /* stat[0] is not used; + stat[k], 1 <= k <= m+n, is the status of variable x[k]: */ +#define SSX_BS 0 /* basic variable */ +#define SSX_NL 1 /* non-basic variable on lower bound */ +#define SSX_NU 2 /* non-basic variable on upper bound */ +#define SSX_NF 3 /* non-basic free variable */ +#define SSX_NS 4 /* non-basic fixed variable */ + int *Q_row; /* int Q_row[1+m+n]; */ + /* matrix Q in row-like format; + Q_row[0] is not used; + Q_row[i] = j means that q[i,j] = 1 */ + int *Q_col; /* int Q_col[1+m+n]; */ + /* matrix Q in column-like format; + Q_col[0] is not used; + Q_col[j] = i means that q[i,j] = 1 */ + /* if k-th column of the matrix (I | A) is k'-th column of the + matrix (B | N), then Q_row[k] = k' and Q_col[k'] = k; + if x[k] is xB[i], then Q_row[k] = i and Q_col[i] = k; + if x[k] is xN[j], then Q_row[k] = m+j and Q_col[m+j] = k */ + BFX *binv; + /* invertable form of the basis matrix B */ + mpq_t *bbar; /* mpq_t bbar[1+m]; alias: beta */ + /* bbar[0] is a value of the objective function; + bbar[i], 1 <= i <= m, is a value of basic variable xB[i] */ + mpq_t *pi; /* mpq_t pi[1+m]; */ + /* pi[0] is not used; + pi[i], 1 <= i <= m, is a simplex multiplier corresponding to + i-th row (equality constraint) */ + mpq_t *cbar; /* mpq_t cbar[1+n]; alias: d */ + /* cbar[0] is not used; + cbar[j], 1 <= j <= n, is a reduced cost of non-basic variable + xN[j] */ +/*---------------------------------------------------------------------- +// SIMPLEX TABLE +// +// Due to (8) and (9) the system of equality constraints (7) for the +// current basis can be written as follows: +// +// xB = A~ * xN, (14) +// +// where +// +// A~ = - inv(B) * N (15) +// +// is a mxn matrix called the simplex table. +// +// The revised simplex method uses only two components of A~, namely, +// pivot column corresponding to non-basic variable xN[q] chosen to +// enter the basis, and pivot row corresponding to basic variable xB[p] +// chosen to leave the basis. +// +// Pivot column alfa_q is q-th column of A~, so +// +// alfa_q = A~ * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], (16) +// +// where N[q] is q-th column of the matrix N. +// +// Pivot row alfa_p is p-th row of A~ or, equivalently, p-th column of +// A~', a matrix transposed to A~, so +// +// alfa_p = A~' * e[p] = - N' * inv(B') * e[p] = - N' * rho_p, (17) +// +// where (*)' means transposition, and +// +// rho_p = inv(B') * e[p], (18) +// +// is p-th column of inv(B') or, that is the same, p-th row of inv(B). +----------------------------------------------------------------------*/ + int p; + /* number of basic variable xB[p], 1 <= p <= m, chosen to leave + the basis */ + mpq_t *rho; /* mpq_t rho[1+m]; */ + /* p-th row of the inverse inv(B); see (18) */ + mpq_t *ap; /* mpq_t ap[1+n]; */ + /* p-th row of the simplex table; see (17) */ + int q; + /* number of non-basic variable xN[q], 1 <= q <= n, chosen to + enter the basis */ + mpq_t *aq; /* mpq_t aq[1+m]; */ + /* q-th column of the simplex table; see (16) */ +/*--------------------------------------------------------------------*/ + int q_dir; + /* direction in which non-basic variable xN[q] should change on + moving to the adjacent vertex of the polyhedron: + +1 means that xN[q] increases + -1 means that xN[q] decreases */ + int p_stat; + /* non-basic status which should be assigned to basic variable + xB[p] when it has left the basis and become xN[q] */ + mpq_t delta; + /* actual change of xN[q] in the adjacent basis (it has the same + sign as q_dir) */ +/*--------------------------------------------------------------------*/ +#if 1 /* 25/XI-2017 */ + int msg_lev; + /* verbosity level: + GLP_MSG_OFF no output + GLP_MSG_ERR report errors and warnings + GLP_MSG_ON normal output + GLP_MSG_ALL highest verbosity */ +#endif + int it_lim; + /* simplex iterations limit; if this value is positive, it is + decreased by one each time when one simplex iteration has been + performed, and reaching zero value signals the solver to stop + the search; negative value means no iterations limit */ + int it_cnt; + /* simplex iterations count; this count is increased by one each + time when one simplex iteration has been performed */ + double tm_lim; + /* searching time limit, in seconds; if this value is positive, + it is decreased each time when one simplex iteration has been + performed by the amount of time spent for the iteration, and + reaching zero value signals the solver to stop the search; + negative value means no time limit */ + double out_frq; + /* output frequency, in seconds; this parameter specifies how + frequently the solver sends information about the progress of + the search to the standard output */ +#if 0 /* 10/VI-2013 */ + glp_long tm_beg; +#else + double tm_beg; +#endif + /* starting time of the search, in seconds; the total time of the + search is the difference between xtime() and tm_beg */ +#if 0 /* 10/VI-2013 */ + glp_long tm_lag; +#else + double tm_lag; +#endif + /* the most recent time, in seconds, at which the progress of the + the search was displayed */ +}; + +#define ssx_create _glp_ssx_create +#define ssx_factorize _glp_ssx_factorize +#define ssx_get_xNj _glp_ssx_get_xNj +#define ssx_eval_bbar _glp_ssx_eval_bbar +#define ssx_eval_pi _glp_ssx_eval_pi +#define ssx_eval_dj _glp_ssx_eval_dj +#define ssx_eval_cbar _glp_ssx_eval_cbar +#define ssx_eval_rho _glp_ssx_eval_rho +#define ssx_eval_row _glp_ssx_eval_row +#define ssx_eval_col _glp_ssx_eval_col +#define ssx_chuzc _glp_ssx_chuzc +#define ssx_chuzr _glp_ssx_chuzr +#define ssx_update_bbar _glp_ssx_update_bbar +#define ssx_update_pi _glp_ssx_update_pi +#define ssx_update_cbar _glp_ssx_update_cbar +#define ssx_change_basis _glp_ssx_change_basis +#define ssx_delete _glp_ssx_delete + +#define ssx_phase_I _glp_ssx_phase_I +#define ssx_phase_II _glp_ssx_phase_II +#define ssx_driver _glp_ssx_driver + +SSX *ssx_create(int m, int n, int nnz); +/* create simplex solver workspace */ + +int ssx_factorize(SSX *ssx); +/* factorize the current basis matrix */ + +void ssx_get_xNj(SSX *ssx, int j, mpq_t x); +/* determine value of non-basic variable */ + +void ssx_eval_bbar(SSX *ssx); +/* compute values of basic variables */ + +void ssx_eval_pi(SSX *ssx); +/* compute values of simplex multipliers */ + +void ssx_eval_dj(SSX *ssx, int j, mpq_t dj); +/* compute reduced cost of non-basic variable */ + +void ssx_eval_cbar(SSX *ssx); +/* compute reduced costs of all non-basic variables */ + +void ssx_eval_rho(SSX *ssx); +/* compute p-th row of the inverse */ + +void ssx_eval_row(SSX *ssx); +/* compute pivot row of the simplex table */ + +void ssx_eval_col(SSX *ssx); +/* compute pivot column of the simplex table */ + +void ssx_chuzc(SSX *ssx); +/* choose pivot column */ + +void ssx_chuzr(SSX *ssx); +/* choose pivot row */ + +void ssx_update_bbar(SSX *ssx); +/* update values of basic variables */ + +void ssx_update_pi(SSX *ssx); +/* update simplex multipliers */ + +void ssx_update_cbar(SSX *ssx); +/* update reduced costs of non-basic variables */ + +void ssx_change_basis(SSX *ssx); +/* change current basis to adjacent one */ + +void ssx_delete(SSX *ssx); +/* delete simplex solver workspace */ + +int ssx_phase_I(SSX *ssx); +/* find primal feasible solution */ + +int ssx_phase_II(SSX *ssx); +/* find optimal solution */ + +int ssx_driver(SSX *ssx); +/* base driver to exact simplex method */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx01.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx01.c new file mode 100644 index 000000000..9b70444ec --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx01.c @@ -0,0 +1,839 @@ +/* glpssx01.c (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpssx.h" +#define xfault xerror + +/*---------------------------------------------------------------------- +// ssx_create - create simplex solver workspace. +// +// This routine creates the workspace used by simplex solver routines, +// and returns a pointer to it. +// +// Parameters m, n, and nnz specify, respectively, the number of rows, +// columns, and non-zero constraint coefficients. +// +// This routine only allocates the memory for the workspace components, +// so the workspace needs to be saturated by data. */ + +SSX *ssx_create(int m, int n, int nnz) +{ SSX *ssx; + int i, j, k; + if (m < 1) + xfault("ssx_create: m = %d; invalid number of rows\n", m); + if (n < 1) + xfault("ssx_create: n = %d; invalid number of columns\n", n); + if (nnz < 0) + xfault("ssx_create: nnz = %d; invalid number of non-zero const" + "raint coefficients\n", nnz); + ssx = xmalloc(sizeof(SSX)); + ssx->m = m; + ssx->n = n; + ssx->type = xcalloc(1+m+n, sizeof(int)); + ssx->lb = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) mpq_init(ssx->lb[k]); + ssx->ub = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) mpq_init(ssx->ub[k]); + ssx->coef = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 0; k <= m+n; k++) mpq_init(ssx->coef[k]); + ssx->A_ptr = xcalloc(1+n+1, sizeof(int)); + ssx->A_ptr[n+1] = nnz+1; + ssx->A_ind = xcalloc(1+nnz, sizeof(int)); + ssx->A_val = xcalloc(1+nnz, sizeof(mpq_t)); + for (k = 1; k <= nnz; k++) mpq_init(ssx->A_val[k]); + ssx->stat = xcalloc(1+m+n, sizeof(int)); + ssx->Q_row = xcalloc(1+m+n, sizeof(int)); + ssx->Q_col = xcalloc(1+m+n, sizeof(int)); + ssx->binv = bfx_create_binv(); + ssx->bbar = xcalloc(1+m, sizeof(mpq_t)); + for (i = 0; i <= m; i++) mpq_init(ssx->bbar[i]); + ssx->pi = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->pi[i]); + ssx->cbar = xcalloc(1+n, sizeof(mpq_t)); + for (j = 1; j <= n; j++) mpq_init(ssx->cbar[j]); + ssx->rho = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->rho[i]); + ssx->ap = xcalloc(1+n, sizeof(mpq_t)); + for (j = 1; j <= n; j++) mpq_init(ssx->ap[j]); + ssx->aq = xcalloc(1+m, sizeof(mpq_t)); + for (i = 1; i <= m; i++) mpq_init(ssx->aq[i]); + mpq_init(ssx->delta); + return ssx; +} + +/*---------------------------------------------------------------------- +// ssx_factorize - factorize the current basis matrix. +// +// This routine computes factorization of the current basis matrix B +// and returns the singularity flag. If the matrix B is non-singular, +// the flag is zero, otherwise non-zero. */ + +static int basis_col(void *info, int j, int ind[], mpq_t val[]) +{ /* this auxiliary routine provides row indices and numeric values + of non-zero elements in j-th column of the matrix B */ + SSX *ssx = info; + int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + int k, len, ptr; + xassert(1 <= j && j <= m); + k = Q_col[j]; /* x[k] = xB[j] */ + xassert(1 <= k && k <= m+n); + /* j-th column of the matrix B is k-th column of the augmented + constraint matrix (I | -A) */ + if (k <= m) + { /* it is a column of the unity matrix I */ + len = 1, ind[1] = k, mpq_set_si(val[1], 1, 1); + } + else + { /* it is a column of the original constraint matrix -A */ + len = 0; + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { len++; + ind[len] = A_ind[ptr]; + mpq_neg(val[len], A_val[ptr]); + } + } + return len; +} + +int ssx_factorize(SSX *ssx) +{ int ret; + ret = bfx_factorize(ssx->binv, ssx->m, basis_col, ssx); + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_get_xNj - determine value of non-basic variable. +// +// This routine determines the value of non-basic variable xN[j] in the +// current basic solution defined as follows: +// +// 0, if xN[j] is free variable +// lN[j], if xN[j] is on its lower bound +// uN[j], if xN[j] is on its upper bound +// lN[j] = uN[j], if xN[j] is fixed variable +// +// where lN[j] and uN[j] are lower and upper bounds of xN[j]. */ + +void ssx_get_xNj(SSX *ssx, int j, mpq_t x) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *stat = ssx->stat; + int *Q_col = ssx->Q_col; + int k; + xassert(1 <= j && j <= n); + k = Q_col[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); + switch (stat[k]) + { case SSX_NL: + /* xN[j] is on its lower bound */ + mpq_set(x, lb[k]); break; + case SSX_NU: + /* xN[j] is on its upper bound */ + mpq_set(x, ub[k]); break; + case SSX_NF: + /* xN[j] is free variable */ + mpq_set_si(x, 0, 1); break; + case SSX_NS: + /* xN[j] is fixed variable */ + mpq_set(x, lb[k]); break; + default: + xassert(stat != stat); + } + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_bbar - compute values of basic variables. +// +// This routine computes values of basic variables xB in the current +// basic solution as follows: +// +// beta = - inv(B) * N * xN, +// +// where B is the basis matrix, N is the matrix of non-basic columns, +// xN is a vector of current values of non-basic variables. */ + +void ssx_eval_bbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int i, j, k, ptr; + mpq_t x, temp; + mpq_init(x); + mpq_init(temp); + /* bbar := 0 */ + for (i = 1; i <= m; i++) + mpq_set_si(bbar[i], 0, 1); + /* bbar := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n] */ + for (j = 1; j <= n; j++) + { ssx_get_xNj(ssx, j, x); + if (mpq_sgn(x) == 0) continue; + k = Q_col[m+j]; /* x[k] = xN[j] */ + if (k <= m) + { /* N[j] is a column of the unity matrix I */ + mpq_sub(bbar[k], bbar[k], x); + } + else + { /* N[j] is a column of the original constraint matrix -A */ + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, A_val[ptr], x); + mpq_add(bbar[A_ind[ptr]], bbar[A_ind[ptr]], temp); + } + } + } + /* bbar := inv(B) * bbar */ + bfx_ftran(ssx->binv, bbar, 0); +#if 1 + /* compute value of the objective function */ + /* bbar[0] := c[0] */ + mpq_set(bbar[0], coef[0]); + /* bbar[0] := bbar[0] + sum{i in B} cB[i] * xB[i] */ + for (i = 1; i <= m; i++) + { k = Q_col[i]; /* x[k] = xB[i] */ + if (mpq_sgn(coef[k]) == 0) continue; + mpq_mul(temp, coef[k], bbar[i]); + mpq_add(bbar[0], bbar[0], temp); + } + /* bbar[0] := bbar[0] + sum{j in N} cN[j] * xN[j] */ + for (j = 1; j <= n; j++) + { k = Q_col[m+j]; /* x[k] = xN[j] */ + if (mpq_sgn(coef[k]) == 0) continue; + ssx_get_xNj(ssx, j, x); + mpq_mul(temp, coef[k], x); + mpq_add(bbar[0], bbar[0], temp); + } +#endif + mpq_clear(x); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_pi - compute values of simplex multipliers. +// +// This routine computes values of simplex multipliers (shadow prices) +// pi in the current basic solution as follows: +// +// pi = inv(B') * cB, +// +// where B' is a matrix transposed to the basis matrix B, cB is a vector +// of objective coefficients at basic variables xB. */ + +void ssx_eval_pi(SSX *ssx) +{ int m = ssx->m; + mpq_t *coef = ssx->coef; + int *Q_col = ssx->Q_col; + mpq_t *pi = ssx->pi; + int i; + /* pi := cB */ + for (i = 1; i <= m; i++) mpq_set(pi[i], coef[Q_col[i]]); + /* pi := inv(B') * cB */ + bfx_btran(ssx->binv, pi); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_dj - compute reduced cost of non-basic variable. +// +// This routine computes reduced cost d[j] of non-basic variable xN[j] +// in the current basic solution as follows: +// +// d[j] = cN[j] - N[j] * pi, +// +// where cN[j] is an objective coefficient at xN[j], N[j] is a column +// of the augmented constraint matrix (I | -A) corresponding to xN[j], +// pi is the vector of simplex multipliers (shadow prices). */ + +void ssx_eval_dj(SSX *ssx, int j, mpq_t dj) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *pi = ssx->pi; + int k, ptr, end; + mpq_t temp; + mpq_init(temp); + xassert(1 <= j && j <= n); + k = Q_col[m+j]; /* x[k] = xN[j] */ + xassert(1 <= k && k <= m+n); + /* j-th column of the matrix N is k-th column of the augmented + constraint matrix (I | -A) */ + if (k <= m) + { /* it is a column of the unity matrix I */ + mpq_sub(dj, coef[k], pi[k]); + } + else + { /* it is a column of the original constraint matrix -A */ + mpq_set(dj, coef[k]); + for (ptr = A_ptr[k-m], end = A_ptr[k-m+1]; ptr < end; ptr++) + { mpq_mul(temp, A_val[ptr], pi[A_ind[ptr]]); + mpq_add(dj, dj, temp); + } + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_cbar - compute reduced costs of all non-basic variables. +// +// This routine computes the vector of reduced costs pi in the current +// basic solution for all non-basic variables, including fixed ones. */ + +void ssx_eval_cbar(SSX *ssx) +{ int n = ssx->n; + mpq_t *cbar = ssx->cbar; + int j; + for (j = 1; j <= n; j++) + ssx_eval_dj(ssx, j, cbar[j]); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_rho - compute p-th row of the inverse. +// +// This routine computes p-th row of the matrix inv(B), where B is the +// current basis matrix. +// +// p-th row of the inverse is computed using the following formula: +// +// rho = inv(B') * e[p], +// +// where B' is a matrix transposed to B, e[p] is a unity vector, which +// contains one in p-th position. */ + +void ssx_eval_rho(SSX *ssx) +{ int m = ssx->m; + int p = ssx->p; + mpq_t *rho = ssx->rho; + int i; + xassert(1 <= p && p <= m); + /* rho := 0 */ + for (i = 1; i <= m; i++) mpq_set_si(rho[i], 0, 1); + /* rho := e[p] */ + mpq_set_si(rho[p], 1, 1); + /* rho := inv(B') * rho */ + bfx_btran(ssx->binv, rho); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_row - compute pivot row of the simplex table. +// +// This routine computes p-th (pivot) row of the current simplex table +// A~ = - inv(B) * N using the following formula: +// +// A~[p] = - N' * inv(B') * e[p] = - N' * rho[p], +// +// where N' is a matrix transposed to the matrix N, rho[p] is p-th row +// of the inverse inv(B). */ + +void ssx_eval_row(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *rho = ssx->rho; + mpq_t *ap = ssx->ap; + int j, k, ptr; + mpq_t temp; + mpq_init(temp); + for (j = 1; j <= n; j++) + { /* ap[j] := - N'[j] * rho (inner product) */ + k = Q_col[m+j]; /* x[k] = xN[j] */ + if (k <= m) + mpq_neg(ap[j], rho[k]); + else + { mpq_set_si(ap[j], 0, 1); + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, A_val[ptr], rho[A_ind[ptr]]); + mpq_add(ap[j], ap[j], temp); + } + } + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_eval_col - compute pivot column of the simplex table. +// +// This routine computes q-th (pivot) column of the current simplex +// table A~ = - inv(B) * N using the following formula: +// +// A~[q] = - inv(B) * N[q], +// +// where N[q] is q-th column of the matrix N corresponding to chosen +// non-basic variable xN[q]. */ + +void ssx_eval_col(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int i, k, ptr; + xassert(1 <= q && q <= n); + /* aq := 0 */ + for (i = 1; i <= m; i++) mpq_set_si(aq[i], 0, 1); + /* aq := N[q] */ + k = Q_col[m+q]; /* x[k] = xN[q] */ + if (k <= m) + { /* N[q] is a column of the unity matrix I */ + mpq_set_si(aq[k], 1, 1); + } + else + { /* N[q] is a column of the original constraint matrix -A */ + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + mpq_neg(aq[A_ind[ptr]], A_val[ptr]); + } + /* aq := inv(B) * aq */ + bfx_ftran(ssx->binv, aq, 1); + /* aq := - aq */ + for (i = 1; i <= m; i++) mpq_neg(aq[i], aq[i]); + return; +} + +/*---------------------------------------------------------------------- +// ssx_chuzc - choose pivot column. +// +// This routine chooses non-basic variable xN[q] whose reduced cost +// indicates possible improving of the objective function to enter it +// in the basis. +// +// Currently the standard (textbook) pricing is used, i.e. that +// non-basic variable is preferred which has greatest reduced cost (in +// magnitude). +// +// If xN[q] has been chosen, the routine stores its number q and also +// sets the flag q_dir that indicates direction in which xN[q] has to +// change (+1 means increasing, -1 means decreasing). +// +// If the choice cannot be made, because the current basic solution is +// dual feasible, the routine sets the number q to 0. */ + +void ssx_chuzc(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int dir = (ssx->dir == SSX_MIN ? +1 : -1); + int *Q_col = ssx->Q_col; + int *stat = ssx->stat; + mpq_t *cbar = ssx->cbar; + int j, k, s, q, q_dir; + double best, temp; + /* nothing is chosen so far */ + q = 0, q_dir = 0, best = 0.0; + /* look through the list of non-basic variables */ + for (j = 1; j <= n; j++) + { k = Q_col[m+j]; /* x[k] = xN[j] */ + s = dir * mpq_sgn(cbar[j]); + if ((stat[k] == SSX_NF || stat[k] == SSX_NL) && s < 0 || + (stat[k] == SSX_NF || stat[k] == SSX_NU) && s > 0) + { /* reduced cost of xN[j] indicates possible improving of + the objective function */ + temp = fabs(mpq_get_d(cbar[j])); + xassert(temp != 0.0); + if (q == 0 || best < temp) + q = j, q_dir = - s, best = temp; + } + } + ssx->q = q, ssx->q_dir = q_dir; + return; +} + +/*---------------------------------------------------------------------- +// ssx_chuzr - choose pivot row. +// +// This routine looks through elements of q-th column of the simplex +// table and chooses basic variable xB[p] which should leave the basis. +// +// The choice is based on the standard (textbook) ratio test. +// +// If xB[p] has been chosen, the routine stores its number p and also +// sets its non-basic status p_stat which should be assigned to xB[p] +// when it has left the basis and become xN[q]. +// +// Special case p < 0 means that xN[q] is double-bounded variable and +// it reaches its opposite bound before any basic variable does that, +// so the current basis remains unchanged. +// +// If the choice cannot be made, because xN[q] can infinitely change in +// the feasible direction, the routine sets the number p to 0. */ + +void ssx_chuzr(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int q_dir = ssx->q_dir; + int i, k, s, t, p, p_stat; + mpq_t teta, temp; + mpq_init(teta); + mpq_init(temp); + xassert(1 <= q && q <= n); + xassert(q_dir == +1 || q_dir == -1); + /* nothing is chosen so far */ + p = 0, p_stat = 0; + /* look through the list of basic variables */ + for (i = 1; i <= m; i++) + { s = q_dir * mpq_sgn(aq[i]); + if (s < 0) + { /* xB[i] decreases */ + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* xB[i] has finite lower bound */ + mpq_sub(temp, bbar[i], lb[k]); + mpq_div(temp, temp, aq[i]); + mpq_abs(temp, temp); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = i; + p_stat = (t == SSX_FX ? SSX_NS : SSX_NL); + mpq_set(teta, temp); + } + } + } + else if (s > 0) + { /* xB[i] increases */ + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* xB[i] has finite upper bound */ + mpq_sub(temp, bbar[i], ub[k]); + mpq_div(temp, temp, aq[i]); + mpq_abs(temp, temp); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = i; + p_stat = (t == SSX_FX ? SSX_NS : SSX_NU); + mpq_set(teta, temp); + } + } + } + /* if something has been chosen and the ratio test indicates + exact degeneracy, the search can be finished */ + if (p != 0 && mpq_sgn(teta) == 0) break; + } + /* if xN[q] is double-bounded, check if it can reach its opposite + bound before any basic variable */ + k = Q_col[m+q]; /* x[k] = xN[q] */ + if (type[k] == SSX_DB) + { mpq_sub(temp, ub[k], lb[k]); + if (p == 0 || mpq_cmp(teta, temp) > 0) + { p = -1; + p_stat = -1; + mpq_set(teta, temp); + } + } + ssx->p = p; + ssx->p_stat = p_stat; + /* if xB[p] has been chosen, determine its actual change in the + adjacent basis (it has the same sign as q_dir) */ + if (p != 0) + { xassert(mpq_sgn(teta) >= 0); + if (q_dir > 0) + mpq_set(ssx->delta, teta); + else + mpq_neg(ssx->delta, teta); + } + mpq_clear(teta); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_update_bbar - update values of basic variables. +// +// This routine recomputes the current values of basic variables for +// the adjacent basis. +// +// The simplex table for the current basis is the following: +// +// xB[i] = sum{j in 1..n} alfa[i,j] * xN[q], i = 1,...,m +// +// therefore +// +// delta xB[i] = alfa[i,q] * delta xN[q], i = 1,...,m +// +// where delta xN[q] = xN.new[q] - xN[q] is the change of xN[q] in the +// adjacent basis, and delta xB[i] = xB.new[i] - xB[i] is the change of +// xB[i]. This gives formulae for recomputing values of xB[i]: +// +// xB.new[p] = xN[q] + delta xN[q] +// +// (because xN[q] becomes xB[p] in the adjacent basis), and +// +// xB.new[i] = xB[i] + alfa[i,q] * delta xN[q], i != p +// +// for other basic variables. */ + +void ssx_update_bbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *bbar = ssx->bbar; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *aq = ssx->aq; + int i; + mpq_t temp; + mpq_init(temp); + xassert(1 <= q && q <= n); + if (p < 0) + { /* xN[q] is double-bounded and goes to its opposite bound */ + /* nop */; + } + else + { /* xN[q] becomes xB[p] in the adjacent basis */ + /* xB.new[p] = xN[q] + delta xN[q] */ + xassert(1 <= p && p <= m); + ssx_get_xNj(ssx, q, temp); + mpq_add(bbar[p], temp, ssx->delta); + } + /* update values of other basic variables depending on xN[q] */ + for (i = 1; i <= m; i++) + { if (i == p) continue; + /* xB.new[i] = xB[i] + alfa[i,q] * delta xN[q] */ + if (mpq_sgn(aq[i]) == 0) continue; + mpq_mul(temp, aq[i], ssx->delta); + mpq_add(bbar[i], bbar[i], temp); + } +#if 1 + /* update value of the objective function */ + /* z.new = z + d[q] * delta xN[q] */ + mpq_mul(temp, cbar[q], ssx->delta); + mpq_add(bbar[0], bbar[0], temp); +#endif + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +-- ssx_update_pi - update simplex multipliers. +-- +-- This routine recomputes the vector of simplex multipliers for the +-- adjacent basis. */ + +void ssx_update_pi(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *pi = ssx->pi; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *aq = ssx->aq; + mpq_t *rho = ssx->rho; + int i; + mpq_t new_dq, temp; + mpq_init(new_dq); + mpq_init(temp); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in the adjacent basis */ + mpq_div(new_dq, cbar[q], aq[p]); + /* update the vector of simplex multipliers */ + for (i = 1; i <= m; i++) + { if (mpq_sgn(rho[i]) == 0) continue; + mpq_mul(temp, new_dq, rho[i]); + mpq_sub(pi[i], pi[i], temp); + } + mpq_clear(new_dq); + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_update_cbar - update reduced costs of non-basic variables. +// +// This routine recomputes the vector of reduced costs of non-basic +// variables for the adjacent basis. */ + +void ssx_update_cbar(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + mpq_t *cbar = ssx->cbar; + int p = ssx->p; + int q = ssx->q; + mpq_t *ap = ssx->ap; + int j; + mpq_t temp; + mpq_init(temp); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in the adjacent basis */ + /* d.new[q] = d[q] / alfa[p,q] */ + mpq_div(cbar[q], cbar[q], ap[q]); + /* update reduced costs of other non-basic variables */ + for (j = 1; j <= n; j++) + { if (j == q) continue; + /* d.new[j] = d[j] - (alfa[p,j] / alfa[p,q]) * d[q] */ + if (mpq_sgn(ap[j]) == 0) continue; + mpq_mul(temp, ap[j], cbar[q]); + mpq_sub(cbar[j], cbar[j], temp); + } + mpq_clear(temp); + return; +} + +/*---------------------------------------------------------------------- +// ssx_change_basis - change current basis to adjacent one. +// +// This routine changes the current basis to the adjacent one swapping +// basic variable xB[p] and non-basic variable xN[q]. */ + +void ssx_change_basis(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + int *stat = ssx->stat; + int *Q_row = ssx->Q_row; + int *Q_col = ssx->Q_col; + int p = ssx->p; + int q = ssx->q; + int p_stat = ssx->p_stat; + int k, kp, kq; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n); + k = Q_col[m+q]; /* x[k] = xN[q] */ + xassert(type[k] == SSX_DB); + switch (stat[k]) + { case SSX_NL: + stat[k] = SSX_NU; + break; + case SSX_NU: + stat[k] = SSX_NL; + break; + default: + xassert(stat != stat); + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + kp = Q_col[p]; /* x[kp] = xB[p] */ + kq = Q_col[m+q]; /* x[kq] = xN[q] */ + /* check non-basic status of xB[p] which becomes xN[q] */ + switch (type[kp]) + { case SSX_FR: + xassert(p_stat == SSX_NF); + break; + case SSX_LO: + xassert(p_stat == SSX_NL); + break; + case SSX_UP: + xassert(p_stat == SSX_NU); + break; + case SSX_DB: + xassert(p_stat == SSX_NL || p_stat == SSX_NU); + break; + case SSX_FX: + xassert(p_stat == SSX_NS); + break; + default: + xassert(type != type); + } + /* swap xB[p] and xN[q] */ + stat[kp] = (char)p_stat, stat[kq] = SSX_BS; + Q_row[kp] = m+q, Q_row[kq] = p; + Q_col[p] = kq, Q_col[m+q] = kp; + /* update factorization of the basis matrix */ + if (bfx_update(ssx->binv, p)) + { if (ssx_factorize(ssx)) + xassert(("Internal error: basis matrix is singular", 0)); + } + } + return; +} + +/*---------------------------------------------------------------------- +// ssx_delete - delete simplex solver workspace. +// +// This routine deletes the simplex solver workspace freeing all the +// memory allocated to this object. */ + +void ssx_delete(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int nnz = ssx->A_ptr[n+1]-1; + int i, j, k; + xfree(ssx->type); + for (k = 1; k <= m+n; k++) mpq_clear(ssx->lb[k]); + xfree(ssx->lb); + for (k = 1; k <= m+n; k++) mpq_clear(ssx->ub[k]); + xfree(ssx->ub); + for (k = 0; k <= m+n; k++) mpq_clear(ssx->coef[k]); + xfree(ssx->coef); + xfree(ssx->A_ptr); + xfree(ssx->A_ind); + for (k = 1; k <= nnz; k++) mpq_clear(ssx->A_val[k]); + xfree(ssx->A_val); + xfree(ssx->stat); + xfree(ssx->Q_row); + xfree(ssx->Q_col); + bfx_delete_binv(ssx->binv); + for (i = 0; i <= m; i++) mpq_clear(ssx->bbar[i]); + xfree(ssx->bbar); + for (i = 1; i <= m; i++) mpq_clear(ssx->pi[i]); + xfree(ssx->pi); + for (j = 1; j <= n; j++) mpq_clear(ssx->cbar[j]); + xfree(ssx->cbar); + for (i = 1; i <= m; i++) mpq_clear(ssx->rho[i]); + xfree(ssx->rho); + for (j = 1; j <= n; j++) mpq_clear(ssx->ap[j]); + xfree(ssx->ap); + for (i = 1; i <= m; i++) mpq_clear(ssx->aq[i]); + xfree(ssx->aq); + mpq_clear(ssx->delta); + xfree(ssx); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx02.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx02.c new file mode 100644 index 000000000..81db1350d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/glpssx02.c @@ -0,0 +1,523 @@ +/* glpssx02.c (simplex method, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "glpssx.h" + +static void show_progress(SSX *ssx, int phase) +{ /* this auxiliary routine displays information about progress of + the search */ + int i, def = 0; + for (i = 1; i <= ssx->m; i++) + if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++; + xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*", + ssx->it_cnt, phase == 1 ? "infsum" : "objval", + mpq_get_d(ssx->bbar[0]), def); +#if 0 + ssx->tm_lag = utime(); +#else + ssx->tm_lag = xtime(); +#endif + return; +} + +/*---------------------------------------------------------------------- +// ssx_phase_I - find primal feasible solution. +// +// This routine implements phase I of the primal simplex method. +// +// On exit the routine returns one of the following codes: +// +// 0 - feasible solution found; +// 1 - problem has no feasible solution; +// 2 - iterations limit exceeded; +// 3 - time limit exceeded. +----------------------------------------------------------------------*/ + +int ssx_phase_I(SSX *ssx) +{ int m = ssx->m; + int n = ssx->n; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + mpq_t *coef = ssx->coef; + int *A_ptr = ssx->A_ptr; + int *A_ind = ssx->A_ind; + mpq_t *A_val = ssx->A_val; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + mpq_t *pi = ssx->pi; + mpq_t *cbar = ssx->cbar; + int *orig_type, orig_dir; + mpq_t *orig_lb, *orig_ub, *orig_coef; + int i, k, ret; + /* save components of the original LP problem, which are changed + by the routine */ + orig_type = xcalloc(1+m+n, sizeof(int)); + orig_lb = xcalloc(1+m+n, sizeof(mpq_t)); + orig_ub = xcalloc(1+m+n, sizeof(mpq_t)); + orig_coef = xcalloc(1+m+n, sizeof(mpq_t)); + for (k = 1; k <= m+n; k++) + { orig_type[k] = type[k]; + mpq_init(orig_lb[k]); + mpq_set(orig_lb[k], lb[k]); + mpq_init(orig_ub[k]); + mpq_set(orig_ub[k], ub[k]); + } + orig_dir = ssx->dir; + for (k = 0; k <= m+n; k++) + { mpq_init(orig_coef[k]); + mpq_set(orig_coef[k], coef[k]); + } + /* build an artificial basic solution, which is primal feasible, + and also build an auxiliary objective function to minimize the + sum of infeasibilities for the original problem */ + ssx->dir = SSX_MIN; + for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1); + mpq_set_si(bbar[0], 0, 1); + for (i = 1; i <= m; i++) + { int t; + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* in the original problem x[k] has lower bound */ + if (mpq_cmp(bbar[i], lb[k]) < 0) + { /* which is violated */ + type[k] = SSX_UP; + mpq_set(ub[k], lb[k]); + mpq_set_si(lb[k], 0, 1); + mpq_set_si(coef[k], -1, 1); + mpq_add(bbar[0], bbar[0], ub[k]); + mpq_sub(bbar[0], bbar[0], bbar[i]); + } + } + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* in the original problem x[k] has upper bound */ + if (mpq_cmp(bbar[i], ub[k]) > 0) + { /* which is violated */ + type[k] = SSX_LO; + mpq_set(lb[k], ub[k]); + mpq_set_si(ub[k], 0, 1); + mpq_set_si(coef[k], +1, 1); + mpq_add(bbar[0], bbar[0], bbar[i]); + mpq_sub(bbar[0], bbar[0], lb[k]); + } + } + } + /* now the initial basic solution should be primal feasible due + to changes of bounds of some basic variables, which turned to + implicit artifical variables */ + /* compute simplex multipliers and reduced costs */ + ssx_eval_pi(ssx); + ssx_eval_cbar(ssx); + /* display initial progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif + show_progress(ssx, 1); + /* main loop starts here */ + for (;;) + { /* display current progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif +#if 0 + if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) +#else + if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) +#endif + show_progress(ssx, 1); + /* we do not need to wait until all artificial variables have + left the basis */ + if (mpq_sgn(bbar[0]) == 0) + { /* the sum of infeasibilities is zero, therefore the current + solution is primal feasible for the original problem */ + ret = 0; + break; + } + /* check if the iterations limit has been exhausted */ + if (ssx->it_lim == 0) + { ret = 2; + break; + } + /* check if the time limit has been exhausted */ +#if 0 + if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) +#else + if (ssx->tm_lim >= 0.0 && + ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) +#endif + { ret = 3; + break; + } + /* choose non-basic variable xN[q] */ + ssx_chuzc(ssx); + /* if xN[q] cannot be chosen, the sum of infeasibilities is + minimal but non-zero; therefore the original problem has no + primal feasible solution */ + if (ssx->q == 0) + { ret = 1; + break; + } + /* compute q-th column of the simplex table */ + ssx_eval_col(ssx); + /* choose basic variable xB[p] */ + ssx_chuzr(ssx); + /* the sum of infeasibilities cannot be negative, therefore + the auxiliary lp problem cannot have unbounded solution */ + xassert(ssx->p != 0); + /* update values of basic variables */ + ssx_update_bbar(ssx); + if (ssx->p > 0) + { /* compute p-th row of the inverse inv(B) */ + ssx_eval_rho(ssx); + /* compute p-th row of the simplex table */ + ssx_eval_row(ssx); + xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); + /* update simplex multipliers */ + ssx_update_pi(ssx); + /* update reduced costs of non-basic variables */ + ssx_update_cbar(ssx); + } + /* xB[p] is leaving the basis; if it is implicit artificial + variable, the corresponding residual vanishes; therefore + bounds of this variable should be restored to the original + values */ + if (ssx->p > 0) + { k = Q_col[ssx->p]; /* x[k] = xB[p] */ + if (type[k] != orig_type[k]) + { /* x[k] is implicit artificial variable */ + type[k] = orig_type[k]; + mpq_set(lb[k], orig_lb[k]); + mpq_set(ub[k], orig_ub[k]); + xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU); + ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL); + if (type[k] == SSX_FX) ssx->p_stat = SSX_NS; + /* nullify the objective coefficient at x[k] */ + mpq_set_si(coef[k], 0, 1); + /* since coef[k] has been changed, we need to compute + new reduced cost of x[k], which it will have in the + adjacent basis */ + /* the formula d[j] = cN[j] - pi' * N[j] is used (note + that the vector pi is not changed, because it depends + on objective coefficients at basic variables, but in + the adjacent basis, for which the vector pi has been + just recomputed, x[k] is non-basic) */ + if (k <= m) + { /* x[k] is auxiliary variable */ + mpq_neg(cbar[ssx->q], pi[k]); + } + else + { /* x[k] is structural variable */ + int ptr; + mpq_t temp; + mpq_init(temp); + mpq_set_si(cbar[ssx->q], 0, 1); + for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) + { mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]); + mpq_add(cbar[ssx->q], cbar[ssx->q], temp); + } + mpq_clear(temp); + } + } + } + /* jump to the adjacent vertex of the polyhedron */ + ssx_change_basis(ssx); + /* one simplex iteration has been performed */ + if (ssx->it_lim > 0) ssx->it_lim--; + ssx->it_cnt++; + } + /* display final progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif + show_progress(ssx, 1); + /* restore components of the original problem, which were changed + by the routine */ + for (k = 1; k <= m+n; k++) + { type[k] = orig_type[k]; + mpq_set(lb[k], orig_lb[k]); + mpq_clear(orig_lb[k]); + mpq_set(ub[k], orig_ub[k]); + mpq_clear(orig_ub[k]); + } + ssx->dir = orig_dir; + for (k = 0; k <= m+n; k++) + { mpq_set(coef[k], orig_coef[k]); + mpq_clear(orig_coef[k]); + } + xfree(orig_type); + xfree(orig_lb); + xfree(orig_ub); + xfree(orig_coef); + /* return to the calling program */ + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_phase_II - find optimal solution. +// +// This routine implements phase II of the primal simplex method. +// +// On exit the routine returns one of the following codes: +// +// 0 - optimal solution found; +// 1 - problem has unbounded solution; +// 2 - iterations limit exceeded; +// 3 - time limit exceeded. +----------------------------------------------------------------------*/ + +int ssx_phase_II(SSX *ssx) +{ int ret; + /* display initial progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif + show_progress(ssx, 2); + /* main loop starts here */ + for (;;) + { /* display current progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif +#if 0 + if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) +#else + if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) +#endif + show_progress(ssx, 2); + /* check if the iterations limit has been exhausted */ + if (ssx->it_lim == 0) + { ret = 2; + break; + } + /* check if the time limit has been exhausted */ +#if 0 + if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) +#else + if (ssx->tm_lim >= 0.0 && + ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) +#endif + { ret = 3; + break; + } + /* choose non-basic variable xN[q] */ + ssx_chuzc(ssx); + /* if xN[q] cannot be chosen, the current basic solution is + dual feasible and therefore optimal */ + if (ssx->q == 0) + { ret = 0; + break; + } + /* compute q-th column of the simplex table */ + ssx_eval_col(ssx); + /* choose basic variable xB[p] */ + ssx_chuzr(ssx); + /* if xB[p] cannot be chosen, the problem has no dual feasible + solution (i.e. unbounded) */ + if (ssx->p == 0) + { ret = 1; + break; + } + /* update values of basic variables */ + ssx_update_bbar(ssx); + if (ssx->p > 0) + { /* compute p-th row of the inverse inv(B) */ + ssx_eval_rho(ssx); + /* compute p-th row of the simplex table */ + ssx_eval_row(ssx); + xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); +#if 0 + /* update simplex multipliers */ + ssx_update_pi(ssx); +#endif + /* update reduced costs of non-basic variables */ + ssx_update_cbar(ssx); + } + /* jump to the adjacent vertex of the polyhedron */ + ssx_change_basis(ssx); + /* one simplex iteration has been performed */ + if (ssx->it_lim > 0) ssx->it_lim--; + ssx->it_cnt++; + } + /* display final progress of the search */ +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ON) +#endif + show_progress(ssx, 2); + /* return to the calling program */ + return ret; +} + +/*---------------------------------------------------------------------- +// ssx_driver - base driver to exact simplex method. +// +// This routine is a base driver to a version of the primal simplex +// method using exact (bignum) arithmetic. +// +// On exit the routine returns one of the following codes: +// +// 0 - optimal solution found; +// 1 - problem has no feasible solution; +// 2 - problem has unbounded solution; +// 3 - iterations limit exceeded (phase I); +// 4 - iterations limit exceeded (phase II); +// 5 - time limit exceeded (phase I); +// 6 - time limit exceeded (phase II); +// 7 - initial basis matrix is exactly singular. +----------------------------------------------------------------------*/ + +int ssx_driver(SSX *ssx) +{ int m = ssx->m; + int *type = ssx->type; + mpq_t *lb = ssx->lb; + mpq_t *ub = ssx->ub; + int *Q_col = ssx->Q_col; + mpq_t *bbar = ssx->bbar; + int i, k, ret; + ssx->tm_beg = xtime(); + /* factorize the initial basis matrix */ + if (ssx_factorize(ssx)) +#if 0 /* 25/XI-2017 */ + { xprintf("Initial basis matrix is singular\n"); +#else + { if (ssx->msg_lev >= GLP_MSG_ERR) + xprintf("Initial basis matrix is singular\n"); +#endif + ret = 7; + goto done; + } + /* compute values of basic variables */ + ssx_eval_bbar(ssx); + /* check if the initial basic solution is primal feasible */ + for (i = 1; i <= m; i++) + { int t; + k = Q_col[i]; /* x[k] = xB[i] */ + t = type[k]; + if (t == SSX_LO || t == SSX_DB || t == SSX_FX) + { /* x[k] has lower bound */ + if (mpq_cmp(bbar[i], lb[k]) < 0) + { /* which is violated */ + break; + } + } + if (t == SSX_UP || t == SSX_DB || t == SSX_FX) + { /* x[k] has upper bound */ + if (mpq_cmp(bbar[i], ub[k]) > 0) + { /* which is violated */ + break; + } + } + } + if (i > m) + { /* no basic variable violates its bounds */ + ret = 0; + goto skip; + } + /* phase I: find primal feasible solution */ + ret = ssx_phase_I(ssx); + switch (ret) + { case 0: + ret = 0; + break; + case 1: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); + ret = 1; + break; + case 2: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 3; + break; + case 3: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 5; + break; + default: + xassert(ret != ret); + } + /* compute values of basic variables (actually only the objective + value needs to be computed) */ + ssx_eval_bbar(ssx); +skip: /* compute simplex multipliers */ + ssx_eval_pi(ssx); + /* compute reduced costs of non-basic variables */ + ssx_eval_cbar(ssx); + /* if phase I failed, do not start phase II */ + if (ret != 0) goto done; + /* phase II: find optimal solution */ + ret = ssx_phase_II(ssx); + switch (ret) + { case 0: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("OPTIMAL SOLUTION FOUND\n"); + ret = 0; + break; + case 1: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); + ret = 2; + break; + case 2: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 4; + break; + case 3: +#if 1 /* 25/XI-2017 */ + if (ssx->msg_lev >= GLP_MSG_ALL) +#endif + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + ret = 6; + break; + default: + xassert(ret != ret); + } +done: /* decrease the time limit by the spent amount of time */ + if (ssx->tm_lim >= 0.0) +#if 0 + { ssx->tm_lim -= utime() - ssx->tm_beg; +#else + { ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg); +#endif + if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0; + } + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/ios.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/ios.h new file mode 100644 index 000000000..1cb07ee04 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/ios.h @@ -0,0 +1,547 @@ +/* ios.h (integer optimization suite) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef IOS_H +#define IOS_H + +#include "prob.h" + +#if 1 /* 02/II-2018 */ +#define NEW_LOCAL 1 +#endif + +#if 1 /* 15/II-2018 */ +#define NEW_COVER 1 +#endif + +typedef struct IOSLOT IOSLOT; +typedef struct IOSNPD IOSNPD; +typedef struct IOSBND IOSBND; +typedef struct IOSTAT IOSTAT; +typedef struct IOSROW IOSROW; +typedef struct IOSAIJ IOSAIJ; +#ifdef NEW_LOCAL /* 02/II-2018 */ +typedef glp_prob IOSPOOL; +typedef GLPROW IOSCUT; +#else +typedef struct IOSPOOL IOSPOOL; +typedef struct IOSCUT IOSCUT; +#endif + +struct glp_tree +{ /* branch-and-bound tree */ + int magic; + /* magic value used for debugging */ + DMP *pool; + /* memory pool to store all IOS components */ + int n; + /* number of columns (variables) */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the original MIP and its + LP relaxation (used to restore the original problem object on + exit from the solver) */ + int orig_m; + /* number of rows */ + unsigned char *orig_type; /* uchar orig_type[1+orig_m+n]; */ + /* types of all variables */ + double *orig_lb; /* double orig_lb[1+orig_m+n]; */ + /* lower bounds of all variables */ + double *orig_ub; /* double orig_ub[1+orig_m+n]; */ + /* upper bounds of all variables */ + unsigned char *orig_stat; /* uchar orig_stat[1+orig_m+n]; */ + /* statuses of all variables */ + double *orig_prim; /* double orig_prim[1+orig_m+n]; */ + /* primal values of all variables */ + double *orig_dual; /* double orig_dual[1+orig_m+n]; */ + /* dual values of all variables */ + double orig_obj; + /* optimal objective value for LP relaxation */ + /*--------------------------------------------------------------*/ + /* branch-and-bound tree */ + int nslots; + /* length of the array of slots (enlarged automatically) */ + int avail; + /* index of the first free slot; 0 means all slots are in use */ + IOSLOT *slot; /* IOSLOT slot[1+nslots]; */ + /* array of slots: + slot[0] is not used; + slot[p], 1 <= p <= nslots, either contains a pointer to some + node of the branch-and-bound tree, in which case p is used on + API level as the reference number of corresponding subproblem, + or is free; all free slots are linked into single linked list; + slot[1] always contains a pointer to the root node (it is free + only if the tree is empty) */ + IOSNPD *head; + /* pointer to the head of the active list */ + IOSNPD *tail; + /* pointer to the tail of the active list */ + /* the active list is a doubly linked list of active subproblems + which correspond to leaves of the tree; all subproblems in the + active list are ordered chronologically (each a new subproblem + is always added to the tail of the list) */ + int a_cnt; + /* current number of active nodes (including the current one) */ + int n_cnt; + /* current number of all (active and inactive) nodes */ + int t_cnt; + /* total number of nodes including those which have been already + removed from the tree; this count is increased by one whenever + a new node is created and never decreased */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the root subproblem */ + int root_m; + /* number of rows */ + unsigned char *root_type; /* uchar root_type[1+root_m+n]; */ + /* types of all variables */ + double *root_lb; /* double root_lb[1+root_m+n]; */ + /* lower bounds of all variables */ + double *root_ub; /* double root_ub[1+root_m+n]; */ + /* upper bounds of all variables */ + unsigned char *root_stat; /* uchar root_stat[1+root_m+n]; */ + /* statuses of all variables */ + /*--------------------------------------------------------------*/ + /* current subproblem and its LP relaxation */ + IOSNPD *curr; + /* pointer to the current subproblem (which can be only active); + NULL means the current subproblem does not exist */ + glp_prob *mip; + /* original problem object passed to the solver; if the current + subproblem exists, its LP segment corresponds to LP relaxation + of the current subproblem; if the current subproblem does not + exist, its LP segment corresponds to LP relaxation of the root + subproblem (note that the root subproblem may differ from the + original MIP, because it may be preprocessed and/or may have + additional rows) */ + unsigned char *non_int; /* uchar non_int[1+n]; */ + /* these column flags are set each time when LP relaxation of the + current subproblem has been solved; + non_int[0] is not used; + non_int[j], 1 <= j <= n, is j-th column flag; if this flag is + set, corresponding variable is required to be integer, but its + value in basic solution is fractional */ + /*--------------------------------------------------------------*/ + /* problem components corresponding to the parent (predecessor) + subproblem for the current subproblem; used to inspect changes + on freezing the current subproblem */ + int pred_m; + /* number of rows */ + int pred_max; + /* length of the following four arrays (enlarged automatically), + pred_max >= pred_m + n */ + unsigned char *pred_type; /* uchar pred_type[1+pred_m+n]; */ + /* types of all variables */ + double *pred_lb; /* double pred_lb[1+pred_m+n]; */ + /* lower bounds of all variables */ + double *pred_ub; /* double pred_ub[1+pred_m+n]; */ + /* upper bounds of all variables */ + unsigned char *pred_stat; /* uchar pred_stat[1+pred_m+n]; */ + /* statuses of all variables */ + /****************************************************************/ + /* built-in cut generators segment */ + IOSPOOL *local; + /* local cut pool */ +#if 1 /* 13/II-2018 */ + glp_cov *cov_gen; + /* pointer to working area used by the cover cut generator */ +#endif + glp_mir *mir_gen; + /* pointer to working area used by the MIR cut generator */ + glp_cfg *clq_gen; + /* pointer to conflict graph used by the clique cut generator */ + /*--------------------------------------------------------------*/ + void *pcost; + /* pointer to working area used on pseudocost branching */ + int *iwrk; /* int iwrk[1+n]; */ + /* working array */ + double *dwrk; /* double dwrk[1+n]; */ + /* working array */ + /*--------------------------------------------------------------*/ + /* control parameters and statistics */ + const glp_iocp *parm; + /* copy of control parameters passed to the solver */ + double tm_beg; + /* starting time of the search, in seconds; the total time of the + search is the difference between xtime() and tm_beg */ + double tm_lag; + /* the most recent time, in seconds, at which the progress of the + the search was displayed */ + int sol_cnt; + /* number of integer feasible solutions found */ +#if 1 /* 11/VII-2013 */ + void *P; /* glp_prob *P; */ + /* problem passed to glp_intopt */ + void *npp; /* NPP *npp; */ + /* preprocessor workspace or NULL */ + const char *save_sol; + /* filename (template) to save every new solution */ + int save_cnt; + /* count to generate filename */ +#endif + /*--------------------------------------------------------------*/ + /* advanced solver interface */ + int reason; + /* flag indicating the reason why the callback routine is being + called (see glpk.h) */ + int stop; + /* flag indicating that the callback routine requires premature + termination of the search */ + int next_p; + /* reference number of active subproblem selected to continue + the search; 0 means no subproblem has been selected */ + int reopt; + /* flag indicating that the current LP relaxation needs to be + re-optimized */ + int reinv; + /* flag indicating that some (non-active) rows were removed from + the current LP relaxation, so if there no new rows appear, the + basis must be re-factorized */ + int br_var; + /* the number of variable chosen to branch on */ + int br_sel; + /* flag indicating which branch (subproblem) is suggested to be + selected to continue the search: + GLP_DN_BRNCH - select down-branch + GLP_UP_BRNCH - select up-branch + GLP_NO_BRNCH - use general selection technique */ + int child; + /* subproblem reference number corresponding to br_sel */ +}; + +struct IOSLOT +{ /* node subproblem slot */ + IOSNPD *node; + /* pointer to subproblem descriptor; NULL means free slot */ + int next; + /* index of another free slot (only if this slot is free) */ +}; + +struct IOSNPD +{ /* node subproblem descriptor */ + int p; + /* subproblem reference number (it is the index to corresponding + slot, i.e. slot[p] points to this descriptor) */ + IOSNPD *up; + /* pointer to the parent subproblem; NULL means this node is the + root of the tree, in which case p = 1 */ + int level; + /* node level (the root node has level 0) */ + int count; + /* if count = 0, this subproblem is active; if count > 0, this + subproblem is inactive, in which case count is the number of + its child subproblems */ + /* the following three linked lists are destroyed on reviving and + built anew on freezing the subproblem: */ + IOSBND *b_ptr; + /* linked list of rows and columns of the parent subproblem whose + types and bounds were changed */ + IOSTAT *s_ptr; + /* linked list of rows and columns of the parent subproblem whose + statuses were changed */ + IOSROW *r_ptr; + /* linked list of rows (cuts) added to the parent subproblem */ + int solved; + /* how many times LP relaxation of this subproblem was solved; + for inactive subproblem this count is always non-zero; + for active subproblem, which is not current, this count may be + non-zero, if the subproblem was temporarily suspended */ + double lp_obj; + /* optimal objective value to LP relaxation of this subproblem; + on creating a subproblem this value is inherited from its + parent; for the root subproblem, which has no parent, this + value is initially set to -DBL_MAX (minimization) or +DBL_MAX + (maximization); each time the subproblem is re-optimized, this + value is appropriately changed */ + double bound; + /* local lower (minimization) or upper (maximization) bound for + integer optimal solution to *this* subproblem; this bound is + local in the sense that only subproblems in the subtree rooted + at this node cannot have better integer feasible solutions; + on creating a subproblem its local bound is inherited from its + parent and then can be made stronger (never weaker); for the + root subproblem its local bound is initially set to -DBL_MAX + (minimization) or +DBL_MAX (maximization) and then improved as + the root LP relaxation has been solved */ + /* the following two quantities are defined only if LP relaxation + of this subproblem was solved at least once (solved > 0): */ + int ii_cnt; + /* number of integer variables whose value in optimal solution to + LP relaxation of this subproblem is fractional */ + double ii_sum; + /* sum of integer infeasibilities */ +#if 1 /* 30/XI-2009 */ + int changed; + /* how many times this subproblem was re-formulated (by adding + cutting plane constraints) */ +#endif + int br_var; + /* ordinal number of branching variable, 1 <= br_var <= n, used + to split this subproblem; 0 means that either this subproblem + is active or branching was made on a constraint */ + double br_val; + /* (fractional) value of branching variable in optimal solution + to final LP relaxation of this subproblem */ + void *data; /* char data[tree->cb_size]; */ + /* pointer to the application-specific data */ + IOSNPD *temp; + /* working pointer used by some routines */ + IOSNPD *prev; + /* pointer to previous subproblem in the active list */ + IOSNPD *next; + /* pointer to next subproblem in the active list */ +}; + +struct IOSBND +{ /* bounds change entry */ + int k; + /* ordinal number of corresponding row (1 <= k <= m) or column + (m+1 <= k <= m+n), where m and n are the number of rows and + columns, resp., in the parent subproblem */ + unsigned char type; + /* new type */ + double lb; + /* new lower bound */ + double ub; + /* new upper bound */ + IOSBND *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSTAT +{ /* status change entry */ + int k; + /* ordinal number of corresponding row (1 <= k <= m) or column + (m+1 <= k <= m+n), where m and n are the number of rows and + columns, resp., in the parent subproblem */ + unsigned char stat; + /* new status */ + IOSTAT *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSROW +{ /* row (constraint) addition entry */ + char *name; + /* row name or NULL */ + unsigned char origin; + /* row origin flag (see glp_attr.origin) */ + unsigned char klass; + /* row class descriptor (see glp_attr.klass) */ + unsigned char type; + /* row type (GLP_LO, GLP_UP, etc.) */ + double lb; + /* row lower bound */ + double ub; + /* row upper bound */ + IOSAIJ *ptr; + /* pointer to the row coefficient list */ + double rii; + /* row scale factor */ + unsigned char stat; + /* row status (GLP_BS, GLP_NL, etc.) */ + IOSROW *next; + /* pointer to next entry for the same subproblem */ +}; + +struct IOSAIJ +{ /* constraint coefficient */ + int j; + /* variable (column) number, 1 <= j <= n */ + double val; + /* non-zero coefficient value */ + IOSAIJ *next; + /* pointer to next coefficient for the same row */ +}; + +#ifndef NEW_LOCAL /* 02/II-2018 */ +struct IOSPOOL +{ /* cut pool */ + int size; + /* pool size = number of cuts in the pool */ + IOSCUT *head; + /* pointer to the first cut */ + IOSCUT *tail; + /* pointer to the last cut */ + int ord; + /* ordinal number of the current cut, 1 <= ord <= size */ + IOSCUT *curr; + /* pointer to the current cut */ +}; +#endif + +#ifndef NEW_LOCAL /* 02/II-2018 */ +struct IOSCUT +{ /* cut (cutting plane constraint) */ + char *name; + /* cut name or NULL */ + unsigned char klass; + /* cut class descriptor (see glp_attr.klass) */ + IOSAIJ *ptr; + /* pointer to the cut coefficient list */ + unsigned char type; + /* cut type: + GLP_LO: sum a[j] * x[j] >= b + GLP_UP: sum a[j] * x[j] <= b + GLP_FX: sum a[j] * x[j] = b */ + double rhs; + /* cut right-hand side */ + IOSCUT *prev; + /* pointer to previous cut */ + IOSCUT *next; + /* pointer to next cut */ +}; +#endif + +#define ios_create_tree _glp_ios_create_tree +glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); +/* create branch-and-bound tree */ + +#define ios_revive_node _glp_ios_revive_node +void ios_revive_node(glp_tree *tree, int p); +/* revive specified subproblem */ + +#define ios_freeze_node _glp_ios_freeze_node +void ios_freeze_node(glp_tree *tree); +/* freeze current subproblem */ + +#define ios_clone_node _glp_ios_clone_node +void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); +/* clone specified subproblem */ + +#define ios_delete_node _glp_ios_delete_node +void ios_delete_node(glp_tree *tree, int p); +/* delete specified subproblem */ + +#define ios_delete_tree _glp_ios_delete_tree +void ios_delete_tree(glp_tree *tree); +/* delete branch-and-bound tree */ + +#define ios_eval_degrad _glp_ios_eval_degrad +void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); +/* estimate obj. degrad. for down- and up-branches */ + +#define ios_round_bound _glp_ios_round_bound +double ios_round_bound(glp_tree *tree, double bound); +/* improve local bound by rounding */ + +#define ios_is_hopeful _glp_ios_is_hopeful +int ios_is_hopeful(glp_tree *tree, double bound); +/* check if subproblem is hopeful */ + +#define ios_best_node _glp_ios_best_node +int ios_best_node(glp_tree *tree); +/* find active node with best local bound */ + +#define ios_relative_gap _glp_ios_relative_gap +double ios_relative_gap(glp_tree *tree); +/* compute relative mip gap */ + +#define ios_solve_node _glp_ios_solve_node +int ios_solve_node(glp_tree *tree); +/* solve LP relaxation of current subproblem */ + +#define ios_create_pool _glp_ios_create_pool +IOSPOOL *ios_create_pool(glp_tree *tree); +/* create cut pool */ + +#define ios_add_row _glp_ios_add_row +int ios_add_row(glp_tree *tree, IOSPOOL *pool, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs); +/* add row (constraint) to the cut pool */ + +#define ios_find_row _glp_ios_find_row +IOSCUT *ios_find_row(IOSPOOL *pool, int i); +/* find row (constraint) in the cut pool */ + +#define ios_del_row _glp_ios_del_row +void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i); +/* remove row (constraint) from the cut pool */ + +#define ios_clear_pool _glp_ios_clear_pool +void ios_clear_pool(glp_tree *tree, IOSPOOL *pool); +/* remove all rows (constraints) from the cut pool */ + +#define ios_delete_pool _glp_ios_delete_pool +void ios_delete_pool(glp_tree *tree, IOSPOOL *pool); +/* delete cut pool */ + +#if 1 /* 11/VII-2013 */ +#define ios_process_sol _glp_ios_process_sol +void ios_process_sol(glp_tree *T); +/* process integer feasible solution just found */ +#endif + +#define ios_preprocess_node _glp_ios_preprocess_node +int ios_preprocess_node(glp_tree *tree, int max_pass); +/* preprocess current subproblem */ + +#define ios_driver _glp_ios_driver +int ios_driver(glp_tree *tree); +/* branch-and-bound driver */ + +#define ios_cov_gen _glp_ios_cov_gen +void ios_cov_gen(glp_tree *tree); +/* generate mixed cover cuts */ + +#define ios_pcost_init _glp_ios_pcost_init +void *ios_pcost_init(glp_tree *tree); +/* initialize working data used on pseudocost branching */ + +#define ios_pcost_branch _glp_ios_pcost_branch +int ios_pcost_branch(glp_tree *T, int *next); +/* choose branching variable with pseudocost branching */ + +#define ios_pcost_update _glp_ios_pcost_update +void ios_pcost_update(glp_tree *tree); +/* update history information for pseudocost branching */ + +#define ios_pcost_free _glp_ios_pcost_free +void ios_pcost_free(glp_tree *tree); +/* free working area used on pseudocost branching */ + +#define ios_feas_pump _glp_ios_feas_pump +void ios_feas_pump(glp_tree *T); +/* feasibility pump heuristic */ + +#if 1 /* 25/V-2013 */ +#define ios_proxy_heur _glp_ios_proxy_heur +void ios_proxy_heur(glp_tree *T); +/* proximity search heuristic */ +#endif + +#define ios_process_cuts _glp_ios_process_cuts +void ios_process_cuts(glp_tree *T); +/* process cuts stored in the local cut pool */ + +#define ios_choose_node _glp_ios_choose_node +int ios_choose_node(glp_tree *T); +/* select subproblem to continue the search */ + +#define ios_choose_var _glp_ios_choose_var +int ios_choose_var(glp_tree *T, int *next); +/* select variable to branch on */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.c b/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.c new file mode 100644 index 000000000..38cb758cb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.c @@ -0,0 +1,1030 @@ +/* lux.c (LU-factorization, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "lux.h" + +#define xfault xerror +#define dmp_create_poolx(size) dmp_create_pool() + +/*********************************************************************** +* lux_create - create LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* LUX *lux_create(int n); +* +* DESCRIPTION +* +* The routine lux_create creates LU-factorization data structure for +* a matrix of the order n. Initially the factorization corresponds to +* the unity matrix (F = V = P = Q = I, so A = I). +* +* RETURNS +* +* The routine returns a pointer to the created LU-factorization data +* structure, which represents the unity matrix of the order n. */ + +LUX *lux_create(int n) +{ LUX *lux; + int k; + if (n < 1) + xfault("lux_create: n = %d; invalid parameter\n", n); + lux = xmalloc(sizeof(LUX)); + lux->n = n; + lux->pool = dmp_create_poolx(sizeof(LUXELM)); + lux->F_row = xcalloc(1+n, sizeof(LUXELM *)); + lux->F_col = xcalloc(1+n, sizeof(LUXELM *)); + lux->V_piv = xcalloc(1+n, sizeof(mpq_t)); + lux->V_row = xcalloc(1+n, sizeof(LUXELM *)); + lux->V_col = xcalloc(1+n, sizeof(LUXELM *)); + lux->P_row = xcalloc(1+n, sizeof(int)); + lux->P_col = xcalloc(1+n, sizeof(int)); + lux->Q_row = xcalloc(1+n, sizeof(int)); + lux->Q_col = xcalloc(1+n, sizeof(int)); + for (k = 1; k <= n; k++) + { lux->F_row[k] = lux->F_col[k] = NULL; + mpq_init(lux->V_piv[k]); + mpq_set_si(lux->V_piv[k], 1, 1); + lux->V_row[k] = lux->V_col[k] = NULL; + lux->P_row[k] = lux->P_col[k] = k; + lux->Q_row[k] = lux->Q_col[k] = k; + } + lux->rank = n; + return lux; +} + +/*********************************************************************** +* initialize - initialize LU-factorization data structures +* +* This routine initializes data structures for subsequent computing +* the LU-factorization of a given matrix A, which is specified by the +* formal routine col. On exit V = A and F = P = Q = I, where I is the +* unity matrix. */ + +static void initialize(LUX *lux, int (*col)(void *info, int j, + int ind[], mpq_t val[]), void *info, LUXWKA *wka) +{ int n = lux->n; + DMP *pool = lux->pool; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *P_col = lux->P_col; + int *Q_row = lux->Q_row; + int *Q_col = lux->Q_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_prev = wka->R_prev; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_prev = wka->C_prev; + int *C_next = wka->C_next; + LUXELM *fij, *vij; + int i, j, k, len, *ind; + mpq_t *val; + /* F := I */ + for (i = 1; i <= n; i++) + { while (F_row[i] != NULL) + { fij = F_row[i], F_row[i] = fij->r_next; + mpq_clear(fij->val); + dmp_free_atom(pool, fij, sizeof(LUXELM)); + } + } + for (j = 1; j <= n; j++) F_col[j] = NULL; + /* V := 0 */ + for (k = 1; k <= n; k++) mpq_set_si(V_piv[k], 0, 1); + for (i = 1; i <= n; i++) + { while (V_row[i] != NULL) + { vij = V_row[i], V_row[i] = vij->r_next; + mpq_clear(vij->val); + dmp_free_atom(pool, vij, sizeof(LUXELM)); + } + } + for (j = 1; j <= n; j++) V_col[j] = NULL; + /* V := A */ + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) mpq_init(val[k]); + for (j = 1; j <= n; j++) + { /* obtain j-th column of matrix A */ + len = col(info, j, ind, val); + if (!(0 <= len && len <= n)) + xfault("lux_decomp: j = %d: len = %d; invalid column length" + "\n", j, len); + /* copy elements of j-th column to matrix V */ + for (k = 1; k <= len; k++) + { /* get row index of a[i,j] */ + i = ind[k]; + if (!(1 <= i && i <= n)) + xfault("lux_decomp: j = %d: i = %d; row index out of ran" + "ge\n", j, i); + /* check for duplicate indices */ + if (V_row[i] != NULL && V_row[i]->j == j) + xfault("lux_decomp: j = %d: i = %d; duplicate row indice" + "s not allowed\n", j, i); + /* check for zero value */ + if (mpq_sgn(val[k]) == 0) + xfault("lux_decomp: j = %d: i = %d; zero elements not al" + "lowed\n", j, i); + /* add new element v[i,j] = a[i,j] to V */ + vij = dmp_get_atom(pool, sizeof(LUXELM)); + vij->i = i, vij->j = j; + mpq_init(vij->val); + mpq_set(vij->val, val[k]); + vij->r_prev = NULL; + vij->r_next = V_row[i]; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->r_next != NULL) vij->r_next->r_prev = vij; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_row[i] = V_col[j] = vij; + } + } + xfree(ind); + for (k = 1; k <= n; k++) mpq_clear(val[k]); + xfree(val); + /* P := Q := I */ + for (k = 1; k <= n; k++) + P_row[k] = P_col[k] = Q_row[k] = Q_col[k] = k; + /* the rank of A and V is not determined yet */ + lux->rank = -1; + /* initially the entire matrix V is active */ + /* determine its row lengths */ + for (i = 1; i <= n; i++) + { len = 0; + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) len++; + R_len[i] = len; + } + /* build linked lists of active rows */ + for (len = 0; len <= n; len++) R_head[len] = 0; + for (i = 1; i <= n; i++) + { len = R_len[i]; + R_prev[i] = 0; + R_next[i] = R_head[len]; + if (R_next[i] != 0) R_prev[R_next[i]] = i; + R_head[len] = i; + } + /* determine its column lengths */ + for (j = 1; j <= n; j++) + { len = 0; + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) len++; + C_len[j] = len; + } + /* build linked lists of active columns */ + for (len = 0; len <= n; len++) C_head[len] = 0; + for (j = 1; j <= n; j++) + { len = C_len[j]; + C_prev[j] = 0; + C_next[j] = C_head[len]; + if (C_next[j] != 0) C_prev[C_next[j]] = j; + C_head[len] = j; + } + return; +} + +/*********************************************************************** +* find_pivot - choose a pivot element +* +* This routine chooses a pivot element v[p,q] in the active submatrix +* of matrix U = P*V*Q. +* +* It is assumed that on entry the matrix U has the following partially +* triangularized form: +* +* 1 k n +* 1 x x x x x x x x x x +* . x x x x x x x x x +* . . x x x x x x x x +* . . . x x x x x x x +* k . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* . . . . * * * * * * +* n . . . . * * * * * * +* +* where rows and columns k, k+1, ..., n belong to the active submatrix +* (elements of the active submatrix are marked by '*'). +* +* Since the matrix U = P*V*Q is not stored, the routine works with the +* matrix V. It is assumed that the row-wise representation corresponds +* to the matrix V, but the column-wise representation corresponds to +* the active submatrix of the matrix V, i.e. elements of the matrix V, +* which does not belong to the active submatrix, are missing from the +* column linked lists. It is also assumed that each active row of the +* matrix V is in the set R[len], where len is number of non-zeros in +* the row, and each active column of the matrix V is in the set C[len], +* where len is number of non-zeros in the column (in the latter case +* only elements of the active submatrix are counted; such elements are +* marked by '*' on the figure above). +* +* Due to exact arithmetic any non-zero element of the active submatrix +* can be chosen as a pivot. However, to keep sparsity of the matrix V +* the routine uses Markowitz strategy, trying to choose such element +* v[p,q], which has smallest Markowitz cost (nr[p]-1) * (nc[q]-1), +* where nr[p] and nc[q] are the number of non-zero elements, resp., in +* p-th row and in q-th column of the active submatrix. +* +* In order to reduce the search, i.e. not to walk through all elements +* of the active submatrix, the routine exploits a technique proposed by +* I.Duff. This technique is based on using the sets R[len] and C[len] +* of active rows and columns. +* +* On exit the routine returns a pointer to a pivot v[p,q] chosen, or +* NULL, if the active submatrix is empty. */ + +static LUXELM *find_pivot(LUX *lux, LUXWKA *wka) +{ int n = lux->n; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_next = wka->C_next; + LUXELM *piv, *some, *vij; + int i, j, len, min_len, ncand, piv_lim = 5; + double best, cost; + /* nothing is chosen so far */ + piv = NULL, best = DBL_MAX, ncand = 0; + /* if in the active submatrix there is a column that has the only + non-zero (column singleton), choose it as a pivot */ + j = C_head[1]; + if (j != 0) + { xassert(C_len[j] == 1); + piv = V_col[j]; + xassert(piv != NULL && piv->c_next == NULL); + goto done; + } + /* if in the active submatrix there is a row that has the only + non-zero (row singleton), choose it as a pivot */ + i = R_head[1]; + if (i != 0) + { xassert(R_len[i] == 1); + piv = V_row[i]; + xassert(piv != NULL && piv->r_next == NULL); + goto done; + } + /* there are no singletons in the active submatrix; walk through + other non-empty rows and columns */ + for (len = 2; len <= n; len++) + { /* consider active columns having len non-zeros */ + for (j = C_head[len]; j != 0; j = C_next[j]) + { /* j-th column has len non-zeros */ + /* find an element in the row of minimal length */ + some = NULL, min_len = INT_MAX; + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) + { if (min_len > R_len[vij->i]) + some = vij, min_len = R_len[vij->i]; + /* if Markowitz cost of this element is not greater than + (len-1)**2, it can be chosen right now; this heuristic + reduces the search and works well in many cases */ + if (min_len <= len) + { piv = some; + goto done; + } + } + /* j-th column has been scanned */ + /* the minimal element found is a next pivot candidate */ + xassert(some != NULL); + ncand++; + /* compute its Markowitz cost */ + cost = (double)(min_len - 1) * (double)(len - 1); + /* choose between the current candidate and this element */ + if (cost < best) piv = some, best = cost; + /* if piv_lim candidates have been considered, there is a + doubt that a much better candidate exists; therefore it + is the time to terminate the search */ + if (ncand == piv_lim) goto done; + } + /* now consider active rows having len non-zeros */ + for (i = R_head[len]; i != 0; i = R_next[i]) + { /* i-th row has len non-zeros */ + /* find an element in the column of minimal length */ + some = NULL, min_len = INT_MAX; + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { if (min_len > C_len[vij->j]) + some = vij, min_len = C_len[vij->j]; + /* if Markowitz cost of this element is not greater than + (len-1)**2, it can be chosen right now; this heuristic + reduces the search and works well in many cases */ + if (min_len <= len) + { piv = some; + goto done; + } + } + /* i-th row has been scanned */ + /* the minimal element found is a next pivot candidate */ + xassert(some != NULL); + ncand++; + /* compute its Markowitz cost */ + cost = (double)(len - 1) * (double)(min_len - 1); + /* choose between the current candidate and this element */ + if (cost < best) piv = some, best = cost; + /* if piv_lim candidates have been considered, there is a + doubt that a much better candidate exists; therefore it + is the time to terminate the search */ + if (ncand == piv_lim) goto done; + } + } +done: /* bring the pivot v[p,q] to the factorizing routine */ + return piv; +} + +/*********************************************************************** +* eliminate - perform gaussian elimination +* +* This routine performs elementary gaussian transformations in order +* to eliminate subdiagonal elements in the k-th column of the matrix +* U = P*V*Q using the pivot element u[k,k], where k is the number of +* the current elimination step. +* +* The parameter piv specifies the pivot element v[p,q] = u[k,k]. +* +* Each time when the routine applies the elementary transformation to +* a non-pivot row of the matrix V, it stores the corresponding element +* to the matrix F in order to keep the main equality A = F*V. +* +* The routine assumes that on entry the matrices L = P*F*inv(P) and +* U = P*V*Q are the following: +* +* 1 k 1 k n +* 1 1 . . . . . . . . . 1 x x x x x x x x x x +* x 1 . . . . . . . . . x x x x x x x x x +* x x 1 . . . . . . . . . x x x x x x x x +* x x x 1 . . . . . . . . . x x x x x x x +* k x x x x 1 . . . . . k . . . . * * * * * * +* x x x x _ 1 . . . . . . . . # * * * * * +* x x x x _ . 1 . . . . . . . # * * * * * +* x x x x _ . . 1 . . . . . . # * * * * * +* x x x x _ . . . 1 . . . . . # * * * * * +* n x x x x _ . . . . 1 n . . . . # * * * * * +* +* matrix L matrix U +* +* where rows and columns of the matrix U with numbers k, k+1, ..., n +* form the active submatrix (eliminated elements are marked by '#' and +* other elements of the active submatrix are marked by '*'). Note that +* each eliminated non-zero element u[i,k] of the matrix U gives the +* corresponding element l[i,k] of the matrix L (marked by '_'). +* +* Actually all operations are performed on the matrix V. Should note +* that the row-wise representation corresponds to the matrix V, but the +* column-wise representation corresponds to the active submatrix of the +* matrix V, i.e. elements of the matrix V, which doesn't belong to the +* active submatrix, are missing from the column linked lists. +* +* Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal +* elements u[i',k] = v[i,q], i' = k+1, k+2, ..., n, the routine applies +* the following elementary gaussian transformations: +* +* (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), +* +* where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier. +* +* Additionally, in order to keep the main equality A = F*V, each time +* when the routine applies the transformation to i-th row of the matrix +* V, it also adds f[i,p] as a new element to the matrix F. +* +* IMPORTANT: On entry the working arrays flag and work should contain +* zeros. This status is provided by the routine on exit. */ + +static void eliminate(LUX *lux, LUXWKA *wka, LUXELM *piv, int flag[], + mpq_t work[]) +{ DMP *pool = lux->pool; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *R_len = wka->R_len; + int *R_head = wka->R_head; + int *R_prev = wka->R_prev; + int *R_next = wka->R_next; + int *C_len = wka->C_len; + int *C_head = wka->C_head; + int *C_prev = wka->C_prev; + int *C_next = wka->C_next; + LUXELM *fip, *vij, *vpj, *viq, *next; + mpq_t temp; + int i, j, p, q; + mpq_init(temp); + /* determine row and column indices of the pivot v[p,q] */ + xassert(piv != NULL); + p = piv->i, q = piv->j; + /* remove p-th (pivot) row from the active set; it will never + return there */ + if (R_prev[p] == 0) + R_head[R_len[p]] = R_next[p]; + else + R_next[R_prev[p]] = R_next[p]; + if (R_next[p] == 0) + ; + else + R_prev[R_next[p]] = R_prev[p]; + /* remove q-th (pivot) column from the active set; it will never + return there */ + if (C_prev[q] == 0) + C_head[C_len[q]] = C_next[q]; + else + C_next[C_prev[q]] = C_next[q]; + if (C_next[q] == 0) + ; + else + C_prev[C_next[q]] = C_prev[q]; + /* store the pivot value in a separate array */ + mpq_set(V_piv[p], piv->val); + /* remove the pivot from p-th row */ + if (piv->r_prev == NULL) + V_row[p] = piv->r_next; + else + piv->r_prev->r_next = piv->r_next; + if (piv->r_next == NULL) + ; + else + piv->r_next->r_prev = piv->r_prev; + R_len[p]--; + /* remove the pivot from q-th column */ + if (piv->c_prev == NULL) + V_col[q] = piv->c_next; + else + piv->c_prev->c_next = piv->c_next; + if (piv->c_next == NULL) + ; + else + piv->c_next->c_prev = piv->c_prev; + C_len[q]--; + /* free the space occupied by the pivot */ + mpq_clear(piv->val); + dmp_free_atom(pool, piv, sizeof(LUXELM)); + /* walk through p-th (pivot) row, which already does not contain + the pivot v[p,q], and do the following... */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { /* get column index of v[p,j] */ + j = vpj->j; + /* store v[p,j] in the working array */ + flag[j] = 1; + mpq_set(work[j], vpj->val); + /* remove j-th column from the active set; it will return there + later with a new length */ + if (C_prev[j] == 0) + C_head[C_len[j]] = C_next[j]; + else + C_next[C_prev[j]] = C_next[j]; + if (C_next[j] == 0) + ; + else + C_prev[C_next[j]] = C_prev[j]; + /* v[p,j] leaves the active submatrix, so remove it from j-th + column; however, v[p,j] is kept in p-th row */ + if (vpj->c_prev == NULL) + V_col[j] = vpj->c_next; + else + vpj->c_prev->c_next = vpj->c_next; + if (vpj->c_next == NULL) + ; + else + vpj->c_next->c_prev = vpj->c_prev; + C_len[j]--; + } + /* now walk through q-th (pivot) column, which already does not + contain the pivot v[p,q], and perform gaussian elimination */ + while (V_col[q] != NULL) + { /* element v[i,q] has to be eliminated */ + viq = V_col[q]; + /* get row index of v[i,q] */ + i = viq->i; + /* remove i-th row from the active set; later it will return + there with a new length */ + if (R_prev[i] == 0) + R_head[R_len[i]] = R_next[i]; + else + R_next[R_prev[i]] = R_next[i]; + if (R_next[i] == 0) + ; + else + R_prev[R_next[i]] = R_prev[i]; + /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] and + store it in the matrix F */ + fip = dmp_get_atom(pool, sizeof(LUXELM)); + fip->i = i, fip->j = p; + mpq_init(fip->val); + mpq_div(fip->val, viq->val, V_piv[p]); + fip->r_prev = NULL; + fip->r_next = F_row[i]; + fip->c_prev = NULL; + fip->c_next = F_col[p]; + if (fip->r_next != NULL) fip->r_next->r_prev = fip; + if (fip->c_next != NULL) fip->c_next->c_prev = fip; + F_row[i] = F_col[p] = fip; + /* v[i,q] has to be eliminated, so remove it from i-th row */ + if (viq->r_prev == NULL) + V_row[i] = viq->r_next; + else + viq->r_prev->r_next = viq->r_next; + if (viq->r_next == NULL) + ; + else + viq->r_next->r_prev = viq->r_prev; + R_len[i]--; + /* and also from q-th column */ + V_col[q] = viq->c_next; + C_len[q]--; + /* free the space occupied by v[i,q] */ + mpq_clear(viq->val); + dmp_free_atom(pool, viq, sizeof(LUXELM)); + /* perform gaussian transformation: + (i-th row) := (i-th row) - f[i,p] * (p-th row) + note that now p-th row, which is in the working array, + does not contain the pivot v[p,q], and i-th row does not + contain the element v[i,q] to be eliminated */ + /* walk through i-th row and transform existing non-zero + elements */ + for (vij = V_row[i]; vij != NULL; vij = next) + { next = vij->r_next; + /* get column index of v[i,j] */ + j = vij->j; + /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ + if (flag[j]) + { /* v[p,j] != 0 */ + flag[j] = 0; + mpq_mul(temp, fip->val, work[j]); + mpq_sub(vij->val, vij->val, temp); + if (mpq_sgn(vij->val) == 0) + { /* new v[i,j] is zero, so remove it from the active + submatrix */ + /* remove v[i,j] from i-th row */ + if (vij->r_prev == NULL) + V_row[i] = vij->r_next; + else + vij->r_prev->r_next = vij->r_next; + if (vij->r_next == NULL) + ; + else + vij->r_next->r_prev = vij->r_prev; + R_len[i]--; + /* remove v[i,j] from j-th column */ + if (vij->c_prev == NULL) + V_col[j] = vij->c_next; + else + vij->c_prev->c_next = vij->c_next; + if (vij->c_next == NULL) + ; + else + vij->c_next->c_prev = vij->c_prev; + C_len[j]--; + /* free the space occupied by v[i,j] */ + mpq_clear(vij->val); + dmp_free_atom(pool, vij, sizeof(LUXELM)); + } + } + } + /* now flag is the pattern of the set v[p,*] \ v[i,*] */ + /* walk through p-th (pivot) row and create new elements in + i-th row, which appear due to fill-in */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { j = vpj->j; + if (flag[j]) + { /* create new non-zero v[i,j] = 0 - f[i,p] * v[p,j] and + add it to i-th row and j-th column */ + vij = dmp_get_atom(pool, sizeof(LUXELM)); + vij->i = i, vij->j = j; + mpq_init(vij->val); + mpq_mul(vij->val, fip->val, work[j]); + mpq_neg(vij->val, vij->val); + vij->r_prev = NULL; + vij->r_next = V_row[i]; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->r_next != NULL) vij->r_next->r_prev = vij; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_row[i] = V_col[j] = vij; + R_len[i]++, C_len[j]++; + } + else + { /* there is no fill-in, because v[i,j] already exists in + i-th row; restore the flag, which was reset before */ + flag[j] = 1; + } + } + /* now i-th row has been completely transformed and can return + to the active set with a new length */ + R_prev[i] = 0; + R_next[i] = R_head[R_len[i]]; + if (R_next[i] != 0) R_prev[R_next[i]] = i; + R_head[R_len[i]] = i; + } + /* at this point q-th (pivot) column must be empty */ + xassert(C_len[q] == 0); + /* walk through p-th (pivot) row again and do the following... */ + for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) + { /* get column index of v[p,j] */ + j = vpj->j; + /* erase v[p,j] from the working array */ + flag[j] = 0; + mpq_set_si(work[j], 0, 1); + /* now j-th column has been completely transformed, so it can + return to the active list with a new length */ + C_prev[j] = 0; + C_next[j] = C_head[C_len[j]]; + if (C_next[j] != 0) C_prev[C_next[j]] = j; + C_head[C_len[j]] = j; + } + mpq_clear(temp); + /* return to the factorizing routine */ + return; +} + +/*********************************************************************** +* lux_decomp - compute LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], +* mpq_t val[]), void *info); +* +* DESCRIPTION +* +* The routine lux_decomp computes LU-factorization of a given square +* matrix A. +* +* The parameter lux specifies LU-factorization data structure built by +* means of the routine lux_create. +* +* The formal routine col specifies the original matrix A. In order to +* obtain j-th column of the matrix A the routine lux_decomp calls the +* routine col with the parameter j (1 <= j <= n, where n is the order +* of A). In response the routine col should store row indices and +* numerical values of non-zero elements of j-th column of A to the +* locations ind[1], ..., ind[len] and val[1], ..., val[len], resp., +* where len is the number of non-zeros in j-th column, which should be +* returned on exit. Neiter zero nor duplicate elements are allowed. +* +* The parameter info is a transit pointer passed to the formal routine +* col; it can be used for various purposes. +* +* RETURNS +* +* The routine lux_decomp returns the singularity flag. Zero flag means +* that the original matrix A is non-singular while non-zero flag means +* that A is (exactly!) singular. +* +* Note that LU-factorization is valid in both cases, however, in case +* of singularity some rows of the matrix V (including pivot elements) +* will be empty. +* +* REPAIRING SINGULAR MATRIX +* +* If the routine lux_decomp returns non-zero flag, it provides all +* necessary information that can be used for "repairing" the matrix A, +* where "repairing" means replacing linearly dependent columns of the +* matrix A by appropriate columns of the unity matrix. This feature is +* needed when the routine lux_decomp is used for reinverting the basis +* matrix within the simplex method procedure. +* +* On exit linearly dependent columns of the matrix U have the numbers +* rank+1, rank+2, ..., n, where rank is the exact rank of the matrix A +* stored by the routine to the member lux->rank. The correspondence +* between columns of A and U is the same as between columns of V and U. +* Thus, linearly dependent columns of the matrix A have the numbers +* Q_col[rank+1], Q_col[rank+2], ..., Q_col[n], where Q_col is an array +* representing the permutation matrix Q in column-like format. It is +* understood that each j-th linearly dependent column of the matrix U +* should be replaced by the unity vector, where all elements are zero +* except the unity diagonal element u[j,j]. On the other hand j-th row +* of the matrix U corresponds to the row of the matrix V (and therefore +* of the matrix A) with the number P_row[j], where P_row is an array +* representing the permutation matrix P in row-like format. Thus, each +* j-th linearly dependent column of the matrix U should be replaced by +* a column of the unity matrix with the number P_row[j]. +* +* The code that repairs the matrix A may look like follows: +* +* for (j = rank+1; j <= n; j++) +* { replace column Q_col[j] of the matrix A by column P_row[j] of +* the unity matrix; +* } +* +* where rank, P_row, and Q_col are members of the structure LUX. */ + +int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], + mpq_t val[]), void *info) +{ int n = lux->n; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *P_col = lux->P_col; + int *Q_row = lux->Q_row; + int *Q_col = lux->Q_col; + LUXELM *piv, *vij; + LUXWKA *wka; + int i, j, k, p, q, t, *flag; + mpq_t *work; + /* allocate working area */ + wka = xmalloc(sizeof(LUXWKA)); + wka->R_len = xcalloc(1+n, sizeof(int)); + wka->R_head = xcalloc(1+n, sizeof(int)); + wka->R_prev = xcalloc(1+n, sizeof(int)); + wka->R_next = xcalloc(1+n, sizeof(int)); + wka->C_len = xcalloc(1+n, sizeof(int)); + wka->C_head = xcalloc(1+n, sizeof(int)); + wka->C_prev = xcalloc(1+n, sizeof(int)); + wka->C_next = xcalloc(1+n, sizeof(int)); + /* initialize LU-factorization data structures */ + initialize(lux, col, info, wka); + /* allocate working arrays */ + flag = xcalloc(1+n, sizeof(int)); + work = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) + { flag[k] = 0; + mpq_init(work[k]); + } + /* main elimination loop */ + for (k = 1; k <= n; k++) + { /* choose a pivot element v[p,q] */ + piv = find_pivot(lux, wka); + if (piv == NULL) + { /* no pivot can be chosen, because the active submatrix is + empty */ + break; + } + /* determine row and column indices of the pivot element */ + p = piv->i, q = piv->j; + /* let v[p,q] correspond to u[i',j']; permute k-th and i'-th + rows and k-th and j'-th columns of the matrix U = P*V*Q to + move the element u[i',j'] to the position u[k,k] */ + i = P_col[p], j = Q_row[q]; + xassert(k <= i && i <= n && k <= j && j <= n); + /* permute k-th and i-th rows of the matrix U */ + t = P_row[k]; + P_row[i] = t, P_col[t] = i; + P_row[k] = p, P_col[p] = k; + /* permute k-th and j-th columns of the matrix U */ + t = Q_col[k]; + Q_col[j] = t, Q_row[t] = j; + Q_col[k] = q, Q_row[q] = k; + /* eliminate subdiagonal elements of k-th column of the matrix + U = P*V*Q using the pivot element u[k,k] = v[p,q] */ + eliminate(lux, wka, piv, flag, work); + } + /* determine the rank of A (and V) */ + lux->rank = k - 1; + /* free working arrays */ + xfree(flag); + for (k = 1; k <= n; k++) mpq_clear(work[k]); + xfree(work); + /* build column lists of the matrix V using its row lists */ + for (j = 1; j <= n; j++) + xassert(V_col[j] == NULL); + for (i = 1; i <= n; i++) + { for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { j = vij->j; + vij->c_prev = NULL; + vij->c_next = V_col[j]; + if (vij->c_next != NULL) vij->c_next->c_prev = vij; + V_col[j] = vij; + } + } + /* free working area */ + xfree(wka->R_len); + xfree(wka->R_head); + xfree(wka->R_prev); + xfree(wka->R_next); + xfree(wka->C_len); + xfree(wka->C_head); + xfree(wka->C_prev); + xfree(wka->C_next); + xfree(wka); + /* return to the calling program */ + return (lux->rank < n); +} + +/*********************************************************************** +* lux_f_solve - solve system F*x = b or F'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_f_solve(LUX *lux, int tr, mpq_t x[]); +* +* DESCRIPTION +* +* The routine lux_f_solve solves either the system F*x = b (if the +* flag tr is zero) or the system F'*x = b (if the flag tr is non-zero), +* where the matrix F is a component of LU-factorization specified by +* the parameter lux, F' is a matrix transposed to F. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix F. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_f_solve(LUX *lux, int tr, mpq_t x[]) +{ int n = lux->n; + LUXELM **F_row = lux->F_row; + LUXELM **F_col = lux->F_col; + int *P_row = lux->P_row; + LUXELM *fik, *fkj; + int i, j, k; + mpq_t temp; + mpq_init(temp); + if (!tr) + { /* solve the system F*x = b */ + for (j = 1; j <= n; j++) + { k = P_row[j]; + if (mpq_sgn(x[k]) != 0) + { for (fik = F_col[k]; fik != NULL; fik = fik->c_next) + { mpq_mul(temp, fik->val, x[k]); + mpq_sub(x[fik->i], x[fik->i], temp); + } + } + } + } + else + { /* solve the system F'*x = b */ + for (i = n; i >= 1; i--) + { k = P_row[i]; + if (mpq_sgn(x[k]) != 0) + { for (fkj = F_row[k]; fkj != NULL; fkj = fkj->r_next) + { mpq_mul(temp, fkj->val, x[k]); + mpq_sub(x[fkj->j], x[fkj->j], temp); + } + } + } + } + mpq_clear(temp); + return; +} + +/*********************************************************************** +* lux_v_solve - solve system V*x = b or V'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_v_solve(LUX *lux, int tr, double x[]); +* +* DESCRIPTION +* +* The routine lux_v_solve solves either the system V*x = b (if the +* flag tr is zero) or the system V'*x = b (if the flag tr is non-zero), +* where the matrix V is a component of LU-factorization specified by +* the parameter lux, V' is a matrix transposed to V. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix V. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_v_solve(LUX *lux, int tr, mpq_t x[]) +{ int n = lux->n; + mpq_t *V_piv = lux->V_piv; + LUXELM **V_row = lux->V_row; + LUXELM **V_col = lux->V_col; + int *P_row = lux->P_row; + int *Q_col = lux->Q_col; + LUXELM *vij; + int i, j, k; + mpq_t *b, temp; + b = xcalloc(1+n, sizeof(mpq_t)); + for (k = 1; k <= n; k++) + mpq_init(b[k]), mpq_set(b[k], x[k]), mpq_set_si(x[k], 0, 1); + mpq_init(temp); + if (!tr) + { /* solve the system V*x = b */ + for (k = n; k >= 1; k--) + { i = P_row[k], j = Q_col[k]; + if (mpq_sgn(b[i]) != 0) + { mpq_set(x[j], b[i]); + mpq_div(x[j], x[j], V_piv[i]); + for (vij = V_col[j]; vij != NULL; vij = vij->c_next) + { mpq_mul(temp, vij->val, x[j]); + mpq_sub(b[vij->i], b[vij->i], temp); + } + } + } + } + else + { /* solve the system V'*x = b */ + for (k = 1; k <= n; k++) + { i = P_row[k], j = Q_col[k]; + if (mpq_sgn(b[j]) != 0) + { mpq_set(x[i], b[j]); + mpq_div(x[i], x[i], V_piv[i]); + for (vij = V_row[i]; vij != NULL; vij = vij->r_next) + { mpq_mul(temp, vij->val, x[i]); + mpq_sub(b[vij->j], b[vij->j], temp); + } + } + } + } + for (k = 1; k <= n; k++) mpq_clear(b[k]); + mpq_clear(temp); + xfree(b); + return; +} + +/*********************************************************************** +* lux_solve - solve system A*x = b or A'*x = b +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_solve(LUX *lux, int tr, mpq_t x[]); +* +* DESCRIPTION +* +* The routine lux_solve solves either the system A*x = b (if the flag +* tr is zero) or the system A'*x = b (if the flag tr is non-zero), +* where the parameter lux specifies LU-factorization of the matrix A, +* A' is a matrix transposed to A. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit this array will contain elements of the solution +* vector x in the same locations. */ + +void lux_solve(LUX *lux, int tr, mpq_t x[]) +{ if (lux->rank < lux->n) + xfault("lux_solve: LU-factorization has incomplete rank\n"); + if (!tr) + { /* A = F*V, therefore inv(A) = inv(V)*inv(F) */ + lux_f_solve(lux, 0, x); + lux_v_solve(lux, 0, x); + } + else + { /* A' = V'*F', therefore inv(A') = inv(F')*inv(V') */ + lux_v_solve(lux, 1, x); + lux_f_solve(lux, 1, x); + } + return; +} + +/*********************************************************************** +* lux_delete - delete LU-factorization +* +* SYNOPSIS +* +* #include "lux.h" +* void lux_delete(LUX *lux); +* +* DESCRIPTION +* +* The routine lux_delete deletes LU-factorization data structure, +* which the parameter lux points to, freeing all the memory allocated +* to this object. */ + +void lux_delete(LUX *lux) +{ int n = lux->n; + LUXELM *fij, *vij; + int i; + for (i = 1; i <= n; i++) + { for (fij = lux->F_row[i]; fij != NULL; fij = fij->r_next) + mpq_clear(fij->val); + mpq_clear(lux->V_piv[i]); + for (vij = lux->V_row[i]; vij != NULL; vij = vij->r_next) + mpq_clear(vij->val); + } + dmp_delete_pool(lux->pool); + xfree(lux->F_row); + xfree(lux->F_col); + xfree(lux->V_piv); + xfree(lux->V_row); + xfree(lux->V_col); + xfree(lux->P_row); + xfree(lux->P_col); + xfree(lux->Q_row); + xfree(lux->Q_col); + xfree(lux); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.h b/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.h new file mode 100644 index 000000000..8767bb8ef --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/draft/lux.h @@ -0,0 +1,220 @@ +/* lux.h (LU-factorization, rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef LUX_H +#define LUX_H + +#include "dmp.h" +#include "mygmp.h" + +/*********************************************************************** +* The structure LUX defines LU-factorization of a square matrix A, +* which is the following quartet: +* +* [A] = (F, V, P, Q), (1) +* +* where F and V are such matrices that +* +* A = F * V, (2) +* +* and P and Q are such permutation matrices that the matrix +* +* L = P * F * inv(P) (3) +* +* is lower triangular with unity diagonal, and the matrix +* +* U = P * V * Q (4) +* +* is upper triangular. All the matrices have the order n. +* +* The matrices F and V are stored in row/column-wise sparse format as +* row and column linked lists of non-zero elements. Unity elements on +* the main diagonal of the matrix F are not stored. Pivot elements of +* the matrix V (that correspond to diagonal elements of the matrix U) +* are also missing from the row and column lists and stored separately +* in an ordinary array. +* +* The permutation matrices P and Q are stored as ordinary arrays using +* both row- and column-like formats. +* +* The matrices L and U being completely defined by the matrices F, V, +* P, and Q are not stored explicitly. +* +* It is easy to show that the factorization (1)-(3) is some version of +* LU-factorization. Indeed, from (3) and (4) it follows that: +* +* F = inv(P) * L * P, +* +* V = inv(P) * U * inv(Q), +* +* and substitution into (2) gives: +* +* A = F * V = inv(P) * L * U * inv(Q). +* +* For more details see the program documentation. */ + +typedef struct LUX LUX; +typedef struct LUXELM LUXELM; +typedef struct LUXWKA LUXWKA; + +struct LUX +{ /* LU-factorization of a square matrix */ + int n; + /* the order of matrices A, F, V, P, Q */ + DMP *pool; + /* memory pool for elements of matrices F and V */ + LUXELM **F_row; /* LUXELM *F_row[1+n]; */ + /* F_row[0] is not used; + F_row[i], 1 <= i <= n, is a pointer to the list of elements in + i-th row of matrix F (diagonal elements are not stored) */ + LUXELM **F_col; /* LUXELM *F_col[1+n]; */ + /* F_col[0] is not used; + F_col[j], 1 <= j <= n, is a pointer to the list of elements in + j-th column of matrix F (diagonal elements are not stored) */ + mpq_t *V_piv; /* mpq_t V_piv[1+n]; */ + /* V_piv[0] is not used; + V_piv[p], 1 <= p <= n, is a pivot element v[p,q] corresponding + to a diagonal element u[k,k] of matrix U = P*V*Q (used on k-th + elimination step, k = 1, 2, ..., n) */ + LUXELM **V_row; /* LUXELM *V_row[1+n]; */ + /* V_row[0] is not used; + V_row[i], 1 <= i <= n, is a pointer to the list of elements in + i-th row of matrix V (except pivot elements) */ + LUXELM **V_col; /* LUXELM *V_col[1+n]; */ + /* V_col[0] is not used; + V_col[j], 1 <= j <= n, is a pointer to the list of elements in + j-th column of matrix V (except pivot elements) */ + int *P_row; /* int P_row[1+n]; */ + /* P_row[0] is not used; + P_row[i] = j means that p[i,j] = 1, where p[i,j] is an element + of permutation matrix P */ + int *P_col; /* int P_col[1+n]; */ + /* P_col[0] is not used; + P_col[j] = i means that p[i,j] = 1, where p[i,j] is an element + of permutation matrix P */ + /* if i-th row or column of matrix F is i'-th row or column of + matrix L = P*F*inv(P), or if i-th row of matrix V is i'-th row + of matrix U = P*V*Q, then P_row[i'] = i and P_col[i] = i' */ + int *Q_row; /* int Q_row[1+n]; */ + /* Q_row[0] is not used; + Q_row[i] = j means that q[i,j] = 1, where q[i,j] is an element + of permutation matrix Q */ + int *Q_col; /* int Q_col[1+n]; */ + /* Q_col[0] is not used; + Q_col[j] = i means that q[i,j] = 1, where q[i,j] is an element + of permutation matrix Q */ + /* if j-th column of matrix V is j'-th column of matrix U = P*V*Q, + then Q_row[j] = j' and Q_col[j'] = j */ + int rank; + /* the (exact) rank of matrices A and V */ +}; + +struct LUXELM +{ /* element of matrix F or V */ + int i; + /* row index, 1 <= i <= m */ + int j; + /* column index, 1 <= j <= n */ + mpq_t val; + /* numeric (non-zero) element value */ + LUXELM *r_prev; + /* pointer to previous element in the same row */ + LUXELM *r_next; + /* pointer to next element in the same row */ + LUXELM *c_prev; + /* pointer to previous element in the same column */ + LUXELM *c_next; + /* pointer to next element in the same column */ +}; + +struct LUXWKA +{ /* working area (used only during factorization) */ + /* in order to efficiently implement Markowitz strategy and Duff + search technique there are two families {R[0], R[1], ..., R[n]} + and {C[0], C[1], ..., C[n]}; member R[k] is a set of active + rows of matrix V having k non-zeros, and member C[k] is a set + of active columns of matrix V having k non-zeros (in the active + submatrix); each set R[k] and C[k] is implemented as a separate + doubly linked list */ + int *R_len; /* int R_len[1+n]; */ + /* R_len[0] is not used; + R_len[i], 1 <= i <= n, is the number of non-zero elements in + i-th row of matrix V (that is the length of i-th row) */ + int *R_head; /* int R_head[1+n]; */ + /* R_head[k], 0 <= k <= n, is the number of a first row, which is + active and whose length is k */ + int *R_prev; /* int R_prev[1+n]; */ + /* R_prev[0] is not used; + R_prev[i], 1 <= i <= n, is the number of a previous row, which + is active and has the same length as i-th row */ + int *R_next; /* int R_next[1+n]; */ + /* R_prev[0] is not used; + R_prev[i], 1 <= i <= n, is the number of a next row, which is + active and has the same length as i-th row */ + int *C_len; /* int C_len[1+n]; */ + /* C_len[0] is not used; + C_len[j], 1 <= j <= n, is the number of non-zero elements in + j-th column of the active submatrix of matrix V (that is the + length of j-th column in the active submatrix) */ + int *C_head; /* int C_head[1+n]; */ + /* C_head[k], 0 <= k <= n, is the number of a first column, which + is active and whose length is k */ + int *C_prev; /* int C_prev[1+n]; */ + /* C_prev[0] is not used; + C_prev[j], 1 <= j <= n, is the number of a previous column, + which is active and has the same length as j-th column */ + int *C_next; /* int C_next[1+n]; */ + /* C_next[0] is not used; + C_next[j], 1 <= j <= n, is the number of a next column, which + is active and has the same length as j-th column */ +}; + +#define lux_create _glp_lux_create +LUX *lux_create(int n); +/* create LU-factorization */ + +#define lux_decomp _glp_lux_decomp +int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], + mpq_t val[]), void *info); +/* compute LU-factorization */ + +#define lux_f_solve _glp_lux_f_solve +void lux_f_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system F*x = b or F'*x = b */ + +#define lux_v_solve _glp_lux_v_solve +void lux_v_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system V*x = b or V'*x = b */ + +#define lux_solve _glp_lux_solve +void lux_solve(LUX *lux, int tr, mpq_t x[]); +/* solve system A*x = b or A'*x = b */ + +#define lux_delete _glp_lux_delete +void lux_delete(LUX *lux); +/* delete LU-factorization */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/alloc.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/alloc.c new file mode 100644 index 000000000..8e2d613de --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/alloc.c @@ -0,0 +1,252 @@ +/* alloc.c (dynamic memory allocation) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" + +#define ALIGN 16 +/* some processors need data to be properly aligned, so this macro + * defines the alignment boundary, in bytes, provided by glpk memory + * allocation routines; looks like 16-byte alignment boundary is + * sufficient for all 32- and 64-bit platforms (8-byte boundary is not + * sufficient for some 64-bit platforms because of jmp_buf) */ + +#define MBD_SIZE (((sizeof(MBD) + (ALIGN - 1)) / ALIGN) * ALIGN) +/* size of memory block descriptor, in bytes, rounded up to multiple + * of the alignment boundary */ + +/*********************************************************************** +* dma - dynamic memory allocation (basic routine) +* +* This routine performs dynamic memory allocation. It is similar to +* the standard realloc function, however, it provides every allocated +* memory block with a descriptor, which is used for sanity checks on +* reallocating/freeing previously allocated memory blocks as well as +* for book-keeping the memory usage statistics. */ + +static void *dma(const char *func, void *ptr, size_t size) +{ ENV *env = get_env_ptr(); + MBD *mbd; + if (ptr == NULL) + { /* new memory block will be allocated */ + mbd = NULL; + } + else + { /* allocated memory block will be reallocated or freed */ + /* get pointer to the block descriptor */ + mbd = (MBD *)((char *)ptr - MBD_SIZE); + /* make sure that the block descriptor is valid */ + if (mbd->self != mbd) + xerror("%s: ptr = %p; invalid pointer\n", func, ptr); + /* remove the block from the linked list */ + mbd->self = NULL; + if (mbd->prev == NULL) + env->mem_ptr = mbd->next; + else + mbd->prev->next = mbd->next; + if (mbd->next == NULL) + ; + else + mbd->next->prev = mbd->prev; + /* decrease usage counts */ + if (!(env->mem_count >= 1 && env->mem_total >= mbd->size)) + xerror("%s: memory allocation error\n", func); + env->mem_count--; + env->mem_total -= mbd->size; + if (size == 0) + { /* free the memory block */ + free(mbd); + return NULL; + } + } + /* allocate/reallocate memory block */ + if (size > SIZE_T_MAX - MBD_SIZE) + xerror("%s: block too large\n", func); + size += MBD_SIZE; + if (size > env->mem_limit - env->mem_total) + xerror("%s: memory allocation limit exceeded\n", func); + if (env->mem_count == INT_MAX) + xerror("%s: too many memory blocks allocated\n", func); + mbd = (mbd == NULL ? malloc(size) : realloc(mbd, size)); + if (mbd == NULL) + xerror("%s: no memory available\n", func); + /* setup the block descriptor */ + mbd->size = size; + mbd->self = mbd; + mbd->prev = NULL; + mbd->next = env->mem_ptr; + /* add the block to the beginning of the linked list */ + if (mbd->next != NULL) + mbd->next->prev = mbd; + env->mem_ptr = mbd; + /* increase usage counts */ + env->mem_count++; + if (env->mem_cpeak < env->mem_count) + env->mem_cpeak = env->mem_count; + env->mem_total += size; + if (env->mem_tpeak < env->mem_total) + env->mem_tpeak = env->mem_total; + return (char *)mbd + MBD_SIZE; +} + +/*********************************************************************** +* NAME +* +* glp_alloc - allocate memory block +* +* SYNOPSIS +* +* void *glp_alloc(int n, int size); +* +* DESCRIPTION +* +* The routine glp_alloc allocates a memory block of n * size bytes +* long. +* +* Note that being allocated the memory block contains arbitrary data +* (not binary zeros!). +* +* RETURNS +* +* The routine glp_alloc returns a pointer to the block allocated. +* To free this block the routine glp_free (not free!) must be used. */ + +void *glp_alloc(int n, int size) +{ if (n < 1) + xerror("glp_alloc: n = %d; invalid parameter\n", n); + if (size < 1) + xerror("glp_alloc: size = %d; invalid parameter\n", size); + if ((size_t)n > SIZE_T_MAX / (size_t)size) + xerror("glp_alloc: n = %d, size = %d; block too large\n", + n, size); + return dma("glp_alloc", NULL, (size_t)n * (size_t)size); +} + +/**********************************************************************/ + +void *glp_realloc(void *ptr, int n, int size) +{ /* reallocate memory block */ + if (ptr == NULL) + xerror("glp_realloc: ptr = %p; invalid pointer\n", ptr); + if (n < 1) + xerror("glp_realloc: n = %d; invalid parameter\n", n); + if (size < 1) + xerror("glp_realloc: size = %d; invalid parameter\n", size); + if ((size_t)n > SIZE_T_MAX / (size_t)size) + xerror("glp_realloc: n = %d, size = %d; block too large\n", + n, size); + return dma("glp_realloc", ptr, (size_t)n * (size_t)size); +} + +/*********************************************************************** +* NAME +* +* glp_free - free (deallocate) memory block +* +* SYNOPSIS +* +* void glp_free(void *ptr); +* +* DESCRIPTION +* +* The routine glp_free frees (deallocates) a memory block pointed to +* by ptr, which was previuosly allocated by the routine glp_alloc or +* reallocated by the routine glp_realloc. */ + +void glp_free(void *ptr) +{ if (ptr == NULL) + xerror("glp_free: ptr = %p; invalid pointer\n", ptr); + dma("glp_free", ptr, 0); + return; +} + +/*********************************************************************** +* NAME +* +* glp_mem_limit - set memory usage limit +* +* SYNOPSIS +* +* void glp_mem_limit(int limit); +* +* DESCRIPTION +* +* The routine glp_mem_limit limits the amount of memory available for +* dynamic allocation (in GLPK routines) to limit megabytes. */ + +void glp_mem_limit(int limit) +{ ENV *env = get_env_ptr(); + if (limit < 1) + xerror("glp_mem_limit: limit = %d; invalid parameter\n", + limit); + if ((size_t)limit <= (SIZE_T_MAX >> 20)) + env->mem_limit = (size_t)limit << 20; + else + env->mem_limit = SIZE_T_MAX; + return; +} + +/*********************************************************************** +* NAME +* +* glp_mem_usage - get memory usage information +* +* SYNOPSIS +* +* void glp_mem_usage(int *count, int *cpeak, size_t *total, +* size_t *tpeak); +* +* DESCRIPTION +* +* The routine glp_mem_usage reports some information about utilization +* of the memory by GLPK routines. Information is stored to locations +* specified by corresponding parameters (see below). Any parameter can +* be specified as NULL, in which case its value is not stored. +* +* *count is the number of the memory blocks currently allocated by the +* routines glp_malloc and glp_calloc (one call to glp_malloc or +* glp_calloc results in allocating one memory block). +* +* *cpeak is the peak value of *count reached since the initialization +* of the GLPK library environment. +* +* *total is the total amount, in bytes, of the memory blocks currently +* allocated by the routines glp_malloc and glp_calloc. +* +* *tpeak is the peak value of *total reached since the initialization +* of the GLPK library envirionment. */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak) +{ ENV *env = get_env_ptr(); + if (count != NULL) + *count = env->mem_count; + if (cpeak != NULL) + *cpeak = env->mem_cpeak; + if (total != NULL) + *total = env->mem_total; + if (tpeak != NULL) + *tpeak = env->mem_tpeak; + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/dlsup.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/dlsup.c new file mode 100644 index 000000000..54c56c6dd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/dlsup.c @@ -0,0 +1,167 @@ +/* dlsup.c (dynamic linking support) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "env.h" + +/* GNU version ********************************************************/ + +#if defined(HAVE_LTDL) + +#include + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h = NULL; + if (lt_dlinit() != 0) + { put_err_msg(lt_dlerror()); + goto done; + } + h = lt_dlopen(module); + if (h == NULL) + { put_err_msg(lt_dlerror()); + if (lt_dlexit() != 0) + xerror("xdlopen: %s\n", lt_dlerror()); + } +done: return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = lt_dlsym(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: %s\n", symbol, lt_dlerror()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (lt_dlclose(h) != 0) + xerror("xdlclose: %s\n", lt_dlerror()); + if (lt_dlexit() != 0) + xerror("xdlclose: %s\n", lt_dlerror()); + return; +} + +/* POSIX version ******************************************************/ + +#elif defined(HAVE_DLFCN) + +#include + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h; + h = dlopen(module, RTLD_NOW); + if (h == NULL) + put_err_msg(dlerror()); + return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = dlsym(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: %s\n", symbol, dlerror()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (dlclose(h) != 0) + xerror("xdlclose: %s\n", dlerror()); + return; +} + +/* MS Windows version *************************************************/ + +#elif defined(__WOE__) + +#include + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + void *h; + h = LoadLibrary(module); + if (h == NULL) + { char msg[20]; + sprintf(msg, "Error %d", GetLastError()); + put_err_msg(msg); + } + return h; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + void *ptr; + xassert(h != NULL); + ptr = GetProcAddress(h, symbol); + if (ptr == NULL) + xerror("xdlsym: %s: Error %d\n", symbol, GetLastError()); + return ptr; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != NULL); + if (!FreeLibrary(h)) + xerror("xdlclose: Error %d\n", GetLastError()); + return; +} + +/* NULL version *******************************************************/ + +#else + +void *xdlopen(const char *module) +{ /* open dynamically linked library */ + xassert(module == module); + put_err_msg("Shared libraries not supported"); + return NULL; +} + +void *xdlsym(void *h, const char *symbol) +{ /* obtain address of symbol from dynamically linked library */ + xassert(h != h); + xassert(symbol != symbol); + return NULL; +} + +void xdlclose(void *h) +{ /* close dynamically linked library */ + xassert(h != h); + return; +} + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/env.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/env.c new file mode 100644 index 000000000..5b901f35e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/env.c @@ -0,0 +1,316 @@ +/* env.c (GLPK environment initialization/termination) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "glpk.h" +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_init_env - initialize GLPK environment +* +* SYNOPSIS +* +* int glp_init_env(void); +* +* DESCRIPTION +* +* The routine glp_init_env initializes the GLPK environment. Normally +* the application program does not need to call this routine, because +* it is called automatically on the first call to any API routine. +* +* RETURNS +* +* The routine glp_init_env returns one of the following codes: +* +* 0 - initialization successful; +* 1 - environment has been already initialized; +* 2 - initialization failed (insufficient memory); +* 3 - initialization failed (unsupported programming model). */ + +int glp_init_env(void) +{ ENV *env; + int ok; + /* check if the programming model is supported */ + ok = (CHAR_BIT == 8 && sizeof(char) == 1 && + sizeof(short) == 2 && sizeof(int) == 4 && + (sizeof(void *) == 4 || sizeof(void *) == 8)); + if (!ok) + return 3; + /* check if the environment is already initialized */ + if (tls_get_ptr() != NULL) + return 1; + /* allocate and initialize the environment block */ + env = malloc(sizeof(ENV)); + if (env == NULL) + return 2; + memset(env, 0, sizeof(ENV)); +#if 0 /* 14/I-2017 */ + sprintf(env->version, "%d.%d", + GLP_MAJOR_VERSION, GLP_MINOR_VERSION); +#endif + env->self = env; + env->term_buf = malloc(TBUF_SIZE); + if (env->term_buf == NULL) + { free(env); + return 2; + } + env->term_out = GLP_ON; + env->term_hook = NULL; + env->term_info = NULL; + env->tee_file = NULL; +#if 1 /* 23/XI-2015 */ + env->err_st = 0; +#endif + env->err_file = NULL; + env->err_line = 0; + env->err_hook = NULL; + env->err_info = NULL; + env->err_buf = malloc(EBUF_SIZE); + if (env->err_buf == NULL) + { free(env->term_buf); + free(env); + return 2; + } + env->err_buf[0] = '\0'; + env->mem_limit = SIZE_T_MAX; + env->mem_ptr = NULL; + env->mem_count = env->mem_cpeak = 0; + env->mem_total = env->mem_tpeak = 0; +#if 1 /* 23/XI-2015 */ + env->gmp_pool = NULL; + env->gmp_size = 0; + env->gmp_work = NULL; +#endif + env->h_odbc = env->h_mysql = NULL; + /* save pointer to the environment block */ + tls_set_ptr(env); + /* initialization successful */ + return 0; +} + +/*********************************************************************** +* NAME +* +* get_env_ptr - retrieve pointer to environment block +* +* SYNOPSIS +* +* #include "env.h" +* ENV *get_env_ptr(void); +* +* DESCRIPTION +* +* The routine get_env_ptr retrieves and returns a pointer to the GLPK +* environment block. +* +* If the GLPK environment has not been initialized yet, the routine +* performs initialization. If initialization fails, the routine prints +* an error message to stderr and terminates the program. +* +* RETURNS +* +* The routine returns a pointer to the environment block. */ + +ENV *get_env_ptr(void) +{ ENV *env = tls_get_ptr(); + /* check if the environment has been initialized */ + if (env == NULL) + { /* not initialized yet; perform initialization */ + if (glp_init_env() != 0) + { /* initialization failed; display an error message */ + fprintf(stderr, "GLPK initialization failed\n"); + fflush(stderr); + /* and abnormally terminate the program */ + abort(); + } + /* initialization successful; retrieve the pointer */ + env = tls_get_ptr(); + } + /* check if the environment block is valid */ + if (env->self != env) + { fprintf(stderr, "Invalid GLPK environment\n"); + fflush(stderr); + abort(); + } + return env; +} + +/*********************************************************************** +* NAME +* +* glp_version - determine library version +* +* SYNOPSIS +* +* const char *glp_version(void); +* +* RETURNS +* +* The routine glp_version returns a pointer to a null-terminated +* character string, which specifies the version of the GLPK library in +* the form "X.Y", where X is the major version number, and Y is the +* minor version number, for example, "4.16". */ + +#define str(s) # s +#define xstr(s) str(s) + +const char *glp_version(void) +#if 0 /* 14/I-2017 */ +{ ENV *env = get_env_ptr(); + return env->version; +} +#else /* suggested by Heinrich */ +{ return + xstr(GLP_MAJOR_VERSION) "." xstr(GLP_MINOR_VERSION); +} +#endif + +/*********************************************************************** +* NAME +* +* glp_config - determine library configuration +* +* SYNOPSIS +* +* const char *glp_config(const char *option); +* +* DESCRIPTION +* +* The routine glp_config determines some options which were specified +* on configuring the GLPK library. +* +* RETURNS +* +* The routine glp_config returns a pointer to a null-terminating +* string depending on the option inquired. +* +* For option = "TLS" the routine returns the thread local storage +* class specifier used (e.g. "_Thread_local") if the GLPK library was +* configured to run in multi-threaded environment, or NULL otherwise. +* +* For option = "ODBC_DLNAME" the routine returns the name of ODBC +* shared library if this option was enabled, or NULL otherwise. +* +* For option = "MYSQL_DLNAME" the routine returns the name of MySQL +* shared library if this option was enabled, or NULL otherwise. */ + +const char *glp_config(const char *option) +{ const char *s; + if (strcmp(option, "TLS") == 0) +#ifndef TLS + s = NULL; +#else + s = xstr(TLS); +#endif + else if (strcmp(option, "ODBC_DLNAME") == 0) +#ifndef ODBC_DLNAME + s = NULL; +#else + s = ODBC_DLNAME; +#endif + else if (strcmp(option, "MYSQL_DLNAME") == 0) +#ifndef MYSQL_DLNAME + s = NULL; +#else + s = MYSQL_DLNAME; +#endif + else + { /* invalid option is always disabled */ + s = NULL; + } + return s; +} + +/*********************************************************************** +* NAME +* +* glp_free_env - free GLPK environment +* +* SYNOPSIS +* +* int glp_free_env(void); +* +* DESCRIPTION +* +* The routine glp_free_env frees all resources used by GLPK routines +* (memory blocks, etc.) which are currently still in use. +* +* Normally the application program does not need to call this routine, +* because GLPK routines always free all unused resources. However, if +* the application program even has deleted all problem objects, there +* will be several memory blocks still allocated for the library needs. +* For some reasons the application program may want GLPK to free this +* memory, in which case it should call glp_free_env. +* +* Note that a call to glp_free_env invalidates all problem objects as +* if no GLPK routine were called. +* +* RETURNS +* +* 0 - termination successful; +* 1 - environment is inactive (was not initialized). */ + +int glp_free_env(void) +{ ENV *env = tls_get_ptr(); + MBD *desc; + /* check if the environment is active */ + if (env == NULL) + return 1; + /* check if the environment block is valid */ + if (env->self != env) + { fprintf(stderr, "Invalid GLPK environment\n"); + fflush(stderr); + abort(); + } + /* close handles to shared libraries */ + if (env->h_odbc != NULL) + xdlclose(env->h_odbc); + if (env->h_mysql != NULL) + xdlclose(env->h_mysql); + /* free memory blocks which are still allocated */ + while (env->mem_ptr != NULL) + { desc = env->mem_ptr; + env->mem_ptr = desc->next; + free(desc); + } + /* close text file used for copying terminal output */ + if (env->tee_file != NULL) + fclose(env->tee_file); + /* invalidate the environment block */ + env->self = NULL; + /* free memory allocated to the environment block */ + free(env->term_buf); + free(env->err_buf); + free(env); + /* reset a pointer to the environment block */ + tls_set_ptr(NULL); + /* termination successful */ + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/env.h b/WebAPP/SOLVERs/GLPK/glpk/src/env/env.h new file mode 100644 index 000000000..67214ef6d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/env.h @@ -0,0 +1,274 @@ +/* env.h (GLPK environment) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef ENV_H +#define ENV_H + +#include "stdc.h" + +typedef struct ENV ENV; +typedef struct MBD MBD; + +#define SIZE_T_MAX (~(size_t)0) +/* largest value of size_t type */ + +#define TBUF_SIZE 4096 +/* terminal output buffer size, in bytes */ + +#define EBUF_SIZE 1024 +/* error message buffer size, in bytes */ + +/* enable/disable flag: */ +#define GLP_ON 1 +#define GLP_OFF 0 + +struct ENV +{ /* GLPK environment block */ +#if 0 /* 14/I-2007 */ + char version[7+1]; + /* version string returned by the routine glp_version */ +#endif + ENV *self; + /* pointer to this block to check its validity */ + /*--------------------------------------------------------------*/ + /* terminal output */ + char *term_buf; /* char term_buf[TBUF_SIZE]; */ + /* terminal output buffer */ + int term_out; + /* flag to enable/disable terminal output */ + int (*term_hook)(void *info, const char *s); + /* user-defined routine to intercept terminal output */ + void *term_info; + /* transit pointer (cookie) passed to the routine term_hook */ + FILE *tee_file; + /* output stream used to copy terminal output */ + /*--------------------------------------------------------------*/ + /* error handling */ +#if 1 /* 07/XI-2015 */ + int err_st; + /* error state flag; set on entry to glp_error */ +#endif + const char *err_file; + /* value of the __FILE__ macro passed to glp_error */ + int err_line; + /* value of the __LINE__ macro passed to glp_error */ + void (*err_hook)(void *info); + /* user-defined routine to intercept abnormal termination */ + void *err_info; + /* transit pointer (cookie) passed to the routine err_hook */ + char *err_buf; /* char err_buf[EBUF_SIZE]; */ + /* buffer to store error messages (used by I/O routines) */ + /*--------------------------------------------------------------*/ + /* dynamic memory allocation */ + size_t mem_limit; + /* maximal amount of memory, in bytes, available for dynamic + * allocation */ + MBD *mem_ptr; + /* pointer to the linked list of allocated memory blocks */ + int mem_count; + /* total number of currently allocated memory blocks */ + int mem_cpeak; + /* peak value of mem_count */ + size_t mem_total; + /* total amount of currently allocated memory, in bytes; it is + * the sum of the size field over all memory block descriptors */ + size_t mem_tpeak; + /* peak value of mem_total */ +#if 1 /* 23/XI-2015 */ + /*--------------------------------------------------------------*/ + /* bignum module working area */ + void *gmp_pool; /* DMP *gmp_pool; */ + /* working memory pool */ + int gmp_size; + /* size of working array */ + unsigned short *gmp_work; /* ushort gmp_work[gmp_size]; */ + /* working array */ +#endif + /*--------------------------------------------------------------*/ + /* dynamic linking support (optional) */ + void *h_odbc; + /* handle to ODBC shared library */ + void *h_mysql; + /* handle to MySQL shared library */ +}; + +struct MBD +{ /* memory block descriptor */ + size_t size; + /* size of block, in bytes, including descriptor */ + MBD *self; + /* pointer to this descriptor to check its validity */ + MBD *prev; + /* pointer to previous memory block descriptor */ + MBD *next; + /* pointer to next memory block descriptor */ +}; + +#define get_env_ptr _glp_get_env_ptr +ENV *get_env_ptr(void); +/* retrieve pointer to environment block */ + +#define tls_set_ptr _glp_tls_set_ptr +void tls_set_ptr(void *ptr); +/* store global pointer in TLS */ + +#define tls_get_ptr _glp_tls_get_ptr +void *tls_get_ptr(void); +/* retrieve global pointer from TLS */ + +#define xputs glp_puts +void glp_puts(const char *s); +/* write string on terminal */ + +#define xprintf glp_printf +void glp_printf(const char *fmt, ...); +/* write formatted output on terminal */ + +#define xvprintf glp_vprintf +void glp_vprintf(const char *fmt, va_list arg); +/* write formatted output on terminal */ + +int glp_term_out(int flag); +/* enable/disable terminal output */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info); +/* install hook to intercept terminal output */ + +int glp_open_tee(const char *fname); +/* start copying terminal output to text file */ + +int glp_close_tee(void); +/* stop copying terminal output to text file */ + +#ifndef GLP_ERRFUNC_DEFINED +#define GLP_ERRFUNC_DEFINED +typedef void (*glp_errfunc)(const char *fmt, ...); +#endif + +#define xerror glp_error_(__FILE__, __LINE__) +glp_errfunc glp_error_(const char *file, int line); +/* display fatal error message and terminate execution */ + +#define xassert(expr) \ + ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) +void glp_assert_(const char *expr, const char *file, int line); +/* check for logical condition */ + +void glp_error_hook(void (*func)(void *info), void *info); +/* install hook to intercept abnormal termination */ + +#define put_err_msg _glp_put_err_msg +void put_err_msg(const char *msg); +/* provide error message string */ + +#define get_err_msg _glp_get_err_msg +const char *get_err_msg(void); +/* obtain error message string */ + +#define xmalloc(size) glp_alloc(1, size) +/* allocate memory block (obsolete) */ + +#define xcalloc(n, size) glp_alloc(n, size) +/* allocate memory block (obsolete) */ + +#define xalloc(n, size) glp_alloc(n, size) +#define talloc(n, type) ((type *)glp_alloc(n, sizeof(type))) +void *glp_alloc(int n, int size); +/* allocate memory block */ + +#define xrealloc(ptr, n, size) glp_realloc(ptr, n, size) +#define trealloc(ptr, n, type) ((type *)glp_realloc(ptr, n, \ + sizeof(type))) +void *glp_realloc(void *ptr, int n, int size); +/* reallocate memory block */ + +#define xfree(ptr) glp_free(ptr) +#define tfree(ptr) glp_free(ptr) +void glp_free(void *ptr); +/* free memory block */ + +void glp_mem_limit(int limit); +/* set memory usage limit */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak); +/* get memory usage information */ + +typedef struct glp_file glp_file; +/* sequential stream descriptor */ + +#define glp_open _glp_open +glp_file *glp_open(const char *name, const char *mode); +/* open stream */ + +#define glp_eof _glp_eof +int glp_eof(glp_file *f); +/* test end-of-file indicator */ + +#define glp_ioerr _glp_ioerr +int glp_ioerr(glp_file *f); +/* test I/O error indicator */ + +#define glp_read _glp_read +int glp_read(glp_file *f, void *buf, int nnn); +/* read data from stream */ + +#define glp_getc _glp_getc +int glp_getc(glp_file *f); +/* read character from stream */ + +#define glp_write _glp_write +int glp_write(glp_file *f, const void *buf, int nnn); +/* write data to stream */ + +#define glp_format _glp_format +int glp_format(glp_file *f, const char *fmt, ...); +/* write formatted data to stream */ + +#define glp_close _glp_close +int glp_close(glp_file *f); +/* close stream */ + +#define xtime glp_time +double glp_time(void); +/* determine current universal time */ + +#define xdifftime glp_difftime +double glp_difftime(double t1, double t0); +/* compute difference between two time values */ + +#define xdlopen _glp_dlopen +void *xdlopen(const char *module); +/* open dynamically linked library */ + +#define xdlsym _glp_dlsym +void *xdlsym(void *h, const char *symbol); +/* obtain address of symbol from dynamically linked library */ + +#define xdlclose _glp_dlclose +void xdlclose(void *h); +/* close dynamically linked library */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/error.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/error.c new file mode 100644 index 000000000..a898b7687 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/error.c @@ -0,0 +1,200 @@ +/* error.c (error handling) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_error - display fatal error message and terminate execution +* +* SYNOPSIS +* +* void glp_error(const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_error (implemented as a macro) formats its +* parameters using the format control string fmt, writes the formatted +* message on the terminal, and abnormally terminates the program. */ + +static void errfunc(const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; +#if 1 /* 07/XI-2015 */ + env->err_st = 1; +#endif + env->term_out = GLP_ON; + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("Error detected in file %s at line %d\n", + env->err_file, env->err_line); + if (env->err_hook != NULL) + env->err_hook(env->err_info); + abort(); + exit(EXIT_FAILURE); + /* no return */ +} + +glp_errfunc glp_error_(const char *file, int line) +{ ENV *env = get_env_ptr(); + env->err_file = file; + env->err_line = line; + return errfunc; +} + +#if 1 /* 07/XI-2015 */ +/*********************************************************************** +* NAME +* +* glp_at_error - check for error state +* +* SYNOPSIS +* +* int glp_at_error(void); +* +* DESCRIPTION +* +* The routine glp_at_error checks if the GLPK environment is at error +* state, i.e. if the call to the routine is (indirectly) made from the +* glp_error routine via an user-defined hook routine. +* +* RETURNS +* +* If the GLPK environment is at error state, the routine glp_at_error +* returns non-zero, otherwise zero. */ + +int glp_at_error(void) +{ ENV *env = get_env_ptr(); + return env->err_st; +} +#endif + +/*********************************************************************** +* NAME +* +* glp_assert - check for logical condition +* +* SYNOPSIS +* +* void glp_assert(int expr); +* +* DESCRIPTION +* +* The routine glp_assert (implemented as a macro) checks for a logical +* condition specified by the parameter expr. If the condition is false +* (i.e. the value of expr is zero), the routine writes a message on +* the terminal and abnormally terminates the program. */ + +void glp_assert_(const char *expr, const char *file, int line) +{ glp_error_(file, line)("Assertion failed: %s\n", expr); + /* no return */ +} + +/*********************************************************************** +* NAME +* +* glp_error_hook - install hook to intercept abnormal termination +* +* SYNOPSIS +* +* void glp_error_hook(void (*func)(void *info), void *info); +* +* DESCRIPTION +* +* The routine glp_error_hook installs a user-defined hook routine to +* intercept abnormal termination. +* +* The parameter func specifies the user-defined hook routine. It is +* called from the routine glp_error before the latter calls the abort +* function to abnormally terminate the application program because of +* fatal error. The parameter info is a transit pointer, specified in +* the corresponding call to the routine glp_error_hook; it may be used +* to pass some information to the hook routine. +* +* To uninstall the hook routine the parameters func and info should be +* both specified as NULL. */ + +void glp_error_hook(void (*func)(void *info), void *info) +{ ENV *env = get_env_ptr(); + if (func == NULL) + { env->err_hook = NULL; + env->err_info = NULL; + } + else + { env->err_hook = func; + env->err_info = info; + } + return; +} + +/*********************************************************************** +* NAME +* +* put_err_msg - provide error message string +* +* SYNOPSIS +* +* #include "env.h" +* void put_err_msg(const char *msg); +* +* DESCRIPTION +* +* The routine put_err_msg stores an error message string pointed to by +* msg to the environment block. */ + +void put_err_msg(const char *msg) +{ ENV *env = get_env_ptr(); + int len; + len = strlen(msg); + if (len >= EBUF_SIZE) + len = EBUF_SIZE - 1; + memcpy(env->err_buf, msg, len); + if (len > 0 && env->err_buf[len-1] == '\n') + len--; + env->err_buf[len] = '\0'; + return; +} + +/*********************************************************************** +* NAME +* +* get_err_msg - obtain error message string +* +* SYNOPSIS +* +* #include "env.h" +* const char *get_err_msg(void); +* +* RETURNS +* +* The routine get_err_msg returns a pointer to an error message string +* previously stored by the routine put_err_msg. */ + +const char *get_err_msg(void) +{ ENV *env = get_env_ptr(); + return env->err_buf; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.c new file mode 100644 index 000000000..59331e22a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.c @@ -0,0 +1,98 @@ +/* stdc.c (replacements for standard non-thread-safe functions) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* portable ANSI C version ********************************************/ + +#if !defined(TLS) + +#define ENABLE_NON_SAFE +#include "stdc.h" + +struct tm *xgmtime(const time_t *timer) +{ return + gmtime(timer); +} + +char *xstrerr(int errnum) +{ return + strerror(errnum); +} + +char *xstrtok(char *s1, const char *s2) +{ return + strtok(s1, s2); +} + +/* MS Windows version *************************************************/ + +#elif defined(__WOE__) + +#include "stdc.h" + +struct tm *xgmtime(const time_t *timer) +{ static TLS struct tm result; + gmtime_s(&result, timer); + return &result; +} + +char *xstrerr(int errnum) +{ static TLS char s[1023+1]; + strerror_s(s, sizeof(s), errnum); + return s; +} + +char *xstrtok(char *s1, const char *s2) +{ static TLS char *ptr; + return strtok_s(s1, s2, &ptr); +} + +/* GNU/Linux version **************************************************/ + +#else + +#include "stdc.h" + +struct tm *xgmtime(const time_t *timer) +{ static TLS struct tm result; + gmtime_r(timer, &result); + return &result; +} + +char *xstrerr(int errnum) +{ static TLS char s[1023+1]; + strerror_r(errnum, s, sizeof(s)); + return s; +} + +char *xstrtok(char *s1, const char *s2) +{ static TLS char *ptr; + return strtok_r(s1, s2, &ptr); +} + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.h b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.h new file mode 100644 index 000000000..a376f2c9e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdc.h @@ -0,0 +1,73 @@ +/* stdc.h (standard ANSI C headers) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef STDC_H +#define STDC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ENABLE_NON_SAFE /* 29/I-2017 */ +/* disable using non-thread-safe functions directly */ +#undef gmtime +#define gmtime ??? +#undef strerror +#define strerror ??? +#undef strtok +#define strtok ??? +#endif + +#if 1 /* 29/I-2017 */ +/* provide replacements for these functions on a per-thread basis */ +#define xgmtime _glp_xgmtime +struct tm *xgmtime(const time_t *); +#define xstrerr _glp_xstrerr +char *xstrerr(int); +#define xstrtok _glp_xstrtok +char *xstrtok(char *, const char *); +#endif + +#if 1 /* 06/II-2018 */ +#ifdef HAVE_CONFIG_H +#include +#endif +#ifndef __WOE__ +#define CDECL +#else +#define CDECL __cdecl +#endif +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/stdout.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdout.c new file mode 100644 index 000000000..94eee02a4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/stdout.c @@ -0,0 +1,262 @@ +/* stdout.c (terminal output) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#undef NDEBUG +#include +#include "env.h" + +/*********************************************************************** +* NAME +* +* glp_puts - write string on terminal +* +* SYNOPSIS +* +* void glp_puts(const char *s); +* +* The routine glp_puts writes the string s on the terminal. */ + +void glp_puts(const char *s) +{ ENV *env = get_env_ptr(); + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* pass the string to the hook routine, if defined */ + if (env->term_hook != NULL) + { if (env->term_hook(env->term_info, s) != 0) + goto skip; + } + /* write the string on the terminal */ + fputs(s, stdout); + fflush(stdout); + /* write the string on the tee file, if required */ + if (env->tee_file != NULL) + { fputs(s, env->tee_file); + fflush(env->tee_file); + } +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_printf - write formatted output on terminal +* +* SYNOPSIS +* +* void glp_printf(const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_printf uses the format control string fmt to format +* its parameters and writes the formatted output on the terminal. */ + +void glp_printf(const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* format the output */ + va_start(arg, fmt); + vsprintf(env->term_buf, fmt, arg); + /* (do not use xassert) */ + assert(strlen(env->term_buf) < TBUF_SIZE); + va_end(arg); + /* write the formatted output on the terminal */ + glp_puts(env->term_buf); +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_vprintf - write formatted output on terminal +* +* SYNOPSIS +* +* void glp_vprintf(const char *fmt, va_list arg); +* +* DESCRIPTION +* +* The routine glp_vprintf uses the format control string fmt to format +* its parameters specified by the list arg and writes the formatted +* output on the terminal. */ + +void glp_vprintf(const char *fmt, va_list arg) +{ ENV *env = get_env_ptr(); + /* if terminal output is disabled, do nothing */ + if (!env->term_out) + goto skip; + /* format the output */ + vsprintf(env->term_buf, fmt, arg); + /* (do not use xassert) */ + assert(strlen(env->term_buf) < TBUF_SIZE); + /* write the formatted output on the terminal */ + glp_puts(env->term_buf); +skip: return; +} + +/*********************************************************************** +* NAME +* +* glp_term_out - enable/disable terminal output +* +* SYNOPSIS +* +* int glp_term_out(int flag); +* +* DESCRIPTION +* +* Depending on the parameter flag the routine glp_term_out enables or +* disables terminal output performed by glpk routines: +* +* GLP_ON - enable terminal output; +* GLP_OFF - disable terminal output. +* +* RETURNS +* +* The routine glp_term_out returns the previous value of the terminal +* output flag. */ + +int glp_term_out(int flag) +{ ENV *env = get_env_ptr(); + int old = env->term_out; + if (!(flag == GLP_ON || flag == GLP_OFF)) + xerror("glp_term_out: flag = %d; invalid parameter\n", flag); + env->term_out = flag; + return old; +} + +/*********************************************************************** +* NAME +* +* glp_term_hook - install hook to intercept terminal output +* +* SYNOPSIS +* +* void glp_term_hook(int (*func)(void *info, const char *s), +* void *info); +* +* DESCRIPTION +* +* The routine glp_term_hook installs a user-defined hook routine to +* intercept all terminal output performed by glpk routines. +* +* This feature can be used to redirect the terminal output to other +* destination, for example to a file or a text window. +* +* The parameter func specifies the user-defined hook routine. It is +* called from an internal printing routine, which passes to it two +* parameters: info and s. The parameter info is a transit pointer, +* specified in the corresponding call to the routine glp_term_hook; +* it may be used to pass some information to the hook routine. The +* parameter s is a pointer to the null terminated character string, +* which is intended to be written to the terminal. If the hook routine +* returns zero, the printing routine writes the string s to the +* terminal in a usual way; otherwise, if the hook routine returns +* non-zero, no terminal output is performed. +* +* To uninstall the hook routine the parameters func and info should be +* specified as NULL. */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info) +{ ENV *env = get_env_ptr(); + if (func == NULL) + { env->term_hook = NULL; + env->term_info = NULL; + } + else + { env->term_hook = func; + env->term_info = info; + } + return; +} + +/*********************************************************************** +* NAME +* +* glp_open_tee - start copying terminal output to text file +* +* SYNOPSIS +* +* int glp_open_tee(const char *name); +* +* DESCRIPTION +* +* The routine glp_open_tee starts copying all the terminal output to +* an output text file, whose name is specified by the character string +* name. +* +* RETURNS +* +* 0 - operation successful +* 1 - copying terminal output is already active +* 2 - unable to create output file */ + +int glp_open_tee(const char *name) +{ ENV *env = get_env_ptr(); + if (env->tee_file != NULL) + { /* copying terminal output is already active */ + return 1; + } + env->tee_file = fopen(name, "w"); + if (env->tee_file == NULL) + { /* unable to create output file */ + return 2; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_close_tee - stop copying terminal output to text file +* +* SYNOPSIS +* +* int glp_close_tee(void); +* +* DESCRIPTION +* +* The routine glp_close_tee stops copying the terminal output to the +* output text file previously open by the routine glp_open_tee closing +* that file. +* +* RETURNS +* +* 0 - operation successful +* 1 - copying terminal output was not started */ + +int glp_close_tee(void) +{ ENV *env = get_env_ptr(); + if (env->tee_file == NULL) + { /* copying terminal output was not started */ + return 1; + } + fclose(env->tee_file); + env->tee_file = NULL; + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/stream.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/stream.c new file mode 100644 index 000000000..906e5b04e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/stream.c @@ -0,0 +1,517 @@ +/* stream.c (stream input/output) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "zlib.h" + +struct glp_file +{ /* sequential stream descriptor */ + char *base; + /* pointer to buffer */ + int size; + /* size of buffer, in bytes */ + char *ptr; + /* pointer to next byte in buffer */ + int cnt; + /* count of bytes in buffer */ + int flag; + /* stream flags: */ +#define IONULL 0x01 /* null file */ +#define IOSTD 0x02 /* standard stream */ +#define IOGZIP 0x04 /* gzipped file */ +#define IOWRT 0x08 /* output stream */ +#define IOEOF 0x10 /* end of file */ +#define IOERR 0x20 /* input/output error */ + void *file; + /* pointer to underlying control object */ +}; + +/*********************************************************************** +* NAME +* +* glp_open - open stream +* +* SYNOPSIS +* +* glp_file *glp_open(const char *name, const char *mode); +* +* DESCRIPTION +* +* The routine glp_open opens a file whose name is a string pointed to +* by name and associates a stream with it. +* +* The following special filenames are recognized by the routine (this +* feature is platform independent): +* +* "/dev/null" empty (null) file; +* "/dev/stdin" standard input stream; +* "/dev/stdout" standard output stream; +* "/dev/stderr" standard error stream. +* +* If the specified filename is ended with ".gz", it is assumed that +* the file is in gzipped format. In this case the file is compressed +* or decompressed by the I/O routines "on the fly". +* +* The parameter mode points to a string, which indicates the open mode +* and should be one of the following: +* +* "r" open text file for reading; +* "w" truncate to zero length or create text file for writing; +* "a" append, open or create text file for writing at end-of-file; +* "rb" open binary file for reading; +* "wb" truncate to zero length or create binary file for writing; +* "ab" append, open or create binary file for writing at end-of-file. +* +* RETURNS +* +* The routine glp_open returns a pointer to the object controlling the +* stream. If the operation fails, the routine returns NULL. */ + +glp_file *glp_open(const char *name, const char *mode) +{ glp_file *f; + int flag; + void *file; + if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0) + flag = 0; + else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) + flag = IOWRT; +#if 1 /* 08/V-2014 */ + else if (strcmp(mode, "a") == 0 || strcmp(mode, "ab") == 0) + flag = IOWRT; +#endif + else + xerror("glp_open: invalid mode string\n"); + if (strcmp(name, "/dev/null") == 0) + { flag |= IONULL; + file = NULL; + } + else if (strcmp(name, "/dev/stdin") == 0) + { flag |= IOSTD; + file = stdin; + } + else if (strcmp(name, "/dev/stdout") == 0) + { flag |= IOSTD; + file = stdout; + } + else if (strcmp(name, "/dev/stderr") == 0) + { flag |= IOSTD; + file = stderr; + } + else + { char *ext = strrchr(name, '.'); + if (ext == NULL || strcmp(ext, ".gz") != 0) + { file = fopen(name, mode); + if (file == NULL) +#if 0 /* 29/I-2017 */ + { put_err_msg(strerror(errno)); +#else + { put_err_msg(xstrerr(errno)); +#endif + return NULL; + } + } + else + { flag |= IOGZIP; + if (strcmp(mode, "r") == 0) + mode = "rb"; + else if (strcmp(mode, "w") == 0) + mode = "wb"; +#if 1 /* 08/V-2014; this mode seems not to work */ + else if (strcmp(mode, "a") == 0) + mode = "ab"; +#endif + file = gzopen(name, mode); + if (file == NULL) +#if 0 /* 29/I-2017 */ + { put_err_msg(strerror(errno)); +#else + { put_err_msg(xstrerr(errno)); +#endif + return NULL; + } + } + } + f = talloc(1, glp_file); + f->base = talloc(BUFSIZ, char); + f->size = BUFSIZ; + f->ptr = f->base; + f->cnt = 0; + f->flag = flag; + f->file = file; + return f; +} + +/*********************************************************************** +* NAME +* +* glp_eof - test end-of-file indicator +* +* SYNOPSIS +* +* int glp_eof(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_eof tests the end-of-file indicator for the stream +* pointed to by f. +* +* RETURNS +* +* The routine glp_eof returns non-zero if and only if the end-of-file +* indicator is set for the specified stream. */ + +int glp_eof(glp_file *f) +{ return + f->flag & IOEOF; +} + +/*********************************************************************** +* NAME +* +* glp_ioerr - test I/O error indicator +* +* SYNOPSIS +* +* int glp_ioerr(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_ioerr tests the I/O error indicator for the stream +* pointed to by f. +* +* RETURNS +* +* The routine glp_ioerr returns non-zero if and only if the I/O error +* indicator is set for the specified stream. */ + +int glp_ioerr(glp_file *f) +{ return + f->flag & IOERR; +} + +/*********************************************************************** +* NAME +* +* glp_read - read data from stream +* +* SYNOPSIS +* +* int glp_read(glp_file *f, void *buf, int nnn); +* +* DESCRIPTION +* +* The routine glp_read reads, into the buffer pointed to by buf, up to +* nnn bytes, from the stream pointed to by f. +* +* RETURNS +* +* The routine glp_read returns the number of bytes successfully read +* (which may be less than nnn). If an end-of-file is encountered, the +* end-of-file indicator for the stream is set and glp_read returns +* zero. If a read error occurs, the error indicator for the stream is +* set and glp_read returns a negative value. */ + +int glp_read(glp_file *f, void *buf, int nnn) +{ int nrd, cnt; + if (f->flag & IOWRT) + xerror("glp_read: attempt to read from output stream\n"); + if (nnn < 1) + xerror("glp_read: nnn = %d; invalid parameter\n", nnn); + for (nrd = 0; nrd < nnn; nrd += cnt) + { if (f->cnt == 0) + { /* buffer is empty; fill it */ + if (f->flag & IONULL) + cnt = 0; + else if (!(f->flag & IOGZIP)) + { cnt = fread(f->base, 1, f->size, (FILE *)(f->file)); + if (ferror((FILE *)(f->file))) + { f->flag |= IOERR; +#if 0 /* 29/I-2017 */ + put_err_msg(strerror(errno)); +#else + put_err_msg(xstrerr(errno)); +#endif + return EOF; + } + } + else + { int errnum; + const char *msg; + cnt = gzread((gzFile)(f->file), f->base, f->size); + if (cnt < 0) + { f->flag |= IOERR; + msg = gzerror((gzFile)(f->file), &errnum); + if (errnum == Z_ERRNO) +#if 0 /* 29/I-2017 */ + put_err_msg(strerror(errno)); +#else + put_err_msg(xstrerr(errno)); +#endif + else + put_err_msg(msg); + return EOF; + } + } + if (cnt == 0) + { if (nrd == 0) + f->flag |= IOEOF; + break; + } + f->ptr = f->base; + f->cnt = cnt; + } + cnt = nnn - nrd; + if (cnt > f->cnt) + cnt = f->cnt; + memcpy((char *)buf + nrd, f->ptr, cnt); + f->ptr += cnt; + f->cnt -= cnt; + } + return nrd; +} + +/*********************************************************************** +* NAME +* +* glp_getc - read character from stream +* +* SYNOPSIS +* +* int glp_getc(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_getc obtains a next character as an unsigned char +* converted to an int from the input stream pointed to by f. +* +* RETURNS +* +* The routine glp_getc returns the next character obtained. However, +* if an end-of-file is encountered or a read error occurs, the routine +* returns EOF. (An end-of-file and a read error can be distinguished +* by use of the routines glp_eof and glp_ioerr.) */ + +int glp_getc(glp_file *f) +{ unsigned char buf[1]; + if (f->flag & IOWRT) + xerror("glp_getc: attempt to read from output stream\n"); + if (glp_read(f, buf, 1) != 1) + return EOF; + return buf[0]; +} + +/*********************************************************************** +* do_flush - flush output stream +* +* This routine causes buffered data for the specified output stream to +* be written to the associated file. +* +* If the operation was successful, the routine returns zero, otherwise +* non-zero. */ + +static int do_flush(glp_file *f) +{ xassert(f->flag & IOWRT); + if (f->cnt > 0) + { if (f->flag & IONULL) + ; + else if (!(f->flag & IOGZIP)) + { if ((int)fwrite(f->base, 1, f->cnt, (FILE *)(f->file)) + != f->cnt) + { f->flag |= IOERR; +#if 0 /* 29/I-2017 */ + put_err_msg(strerror(errno)); +#else + put_err_msg(xstrerr(errno)); +#endif + return EOF; + } + } + else + { int errnum; + const char *msg; + if (gzwrite((gzFile)(f->file), f->base, f->cnt) != f->cnt) + { f->flag |= IOERR; + msg = gzerror((gzFile)(f->file), &errnum); + if (errnum == Z_ERRNO) +#if 0 /* 29/I-2017 */ + put_err_msg(strerror(errno)); +#else + put_err_msg(xstrerr(errno)); +#endif + else + put_err_msg(msg); + return EOF; + } + } + } + f->ptr = f->base; + f->cnt = 0; + return 0; +} + +/*********************************************************************** +* NAME +* +* glp_write - write data to stream +* +* SYNOPSIS +* +* int glp_write(glp_file *f, const void *buf, int nnn); +* +* DESCRIPTION +* +* The routine glp_write writes, from the buffer pointed to by buf, up +* to nnn bytes, to the stream pointed to by f. +* +* RETURNS +* +* The routine glp_write returns the number of bytes successfully +* written (which is equal to nnn). If a write error occurs, the error +* indicator for the stream is set and glp_write returns a negative +* value. */ + +int glp_write(glp_file *f, const void *buf, int nnn) +{ int nwr, cnt; + if (!(f->flag & IOWRT)) + xerror("glp_write: attempt to write to input stream\n"); + if (nnn < 1) + xerror("glp_write: nnn = %d; invalid parameter\n", nnn); + for (nwr = 0; nwr < nnn; nwr += cnt) + { cnt = nnn - nwr; + if (cnt > f->size - f->cnt) + cnt = f->size - f->cnt; + memcpy(f->ptr, (const char *)buf + nwr, cnt); + f->ptr += cnt; + f->cnt += cnt; + if (f->cnt == f->size) + { /* buffer is full; flush it */ + if (do_flush(f) != 0) + return EOF; + } + } + return nwr; +} + +/*********************************************************************** +* NAME +* +* glp_format - write formatted data to stream +* +* SYNOPSIS +* +* int glp_format(glp_file *f, const char *fmt, ...); +* +* DESCRIPTION +* +* The routine glp_format writes formatted data to the stream pointed +* to by f. The format control string pointed to by fmt specifies how +* subsequent arguments are converted for output. +* +* RETURNS +* +* The routine glp_format returns the number of characters written, or +* a negative value if an output error occurs. */ + +int glp_format(glp_file *f, const char *fmt, ...) +{ ENV *env = get_env_ptr(); + va_list arg; + int nnn; + if (!(f->flag & IOWRT)) + xerror("glp_format: attempt to write to input stream\n"); + va_start(arg, fmt); + nnn = vsprintf(env->term_buf, fmt, arg); + xassert(0 <= nnn && nnn < TBUF_SIZE); + va_end(arg); + return nnn == 0 ? 0 : glp_write(f, env->term_buf, nnn); +} + +/*********************************************************************** +* NAME +* +* glp_close - close stream +* +* SYNOPSIS +* +* int glp_close(glp_file *f); +* +* DESCRIPTION +* +* The routine glp_close closes the stream pointed to by f. +* +* RETURNS +* +* If the operation was successful, the routine returns zero, otherwise +* non-zero. */ + +int glp_close(glp_file *f) +{ int ret = 0; + if (f->flag & IOWRT) + { if (do_flush(f) != 0) + ret = EOF; + } + if (f->flag & (IONULL | IOSTD)) + ; + else if (!(f->flag & IOGZIP)) + { if (fclose((FILE *)(f->file)) != 0) + { if (ret == 0) +#if 0 /* 29/I-2017 */ + { put_err_msg(strerror(errno)); +#else + { put_err_msg(xstrerr(errno)); +#endif + ret = EOF; + } + } + } + else + { int errnum; + errnum = gzclose((gzFile)(f->file)); + if (errnum == Z_OK) + ; + else if (errnum == Z_ERRNO) + { if (ret == 0) +#if 0 /* 29/I-2017 */ + { put_err_msg(strerror(errno)); +#else + { put_err_msg(xstrerr(errno)); +#endif + ret = EOF; + } + } +#if 1 /* FIXME */ + else + { if (ret == 0) + { ENV *env = get_env_ptr(); + sprintf(env->term_buf, "gzclose returned %d", errnum); + put_err_msg(env->term_buf); + ret = EOF; + } + } +#endif + } + tfree(f->base); + tfree(f); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/time.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/time.c new file mode 100644 index 000000000..1ffb28e98 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/time.c @@ -0,0 +1,150 @@ +/* time.c (standard time) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "env.h" +#include "jd.h" + +/*********************************************************************** +* NAME +* +* glp_time - determine current universal time +* +* SYNOPSIS +* +* double glp_time(void); +* +* RETURNS +* +* The routine glp_time returns the current universal time (UTC), in +* milliseconds, elapsed since 00:00:00 GMT January 1, 1970. */ + +#define EPOCH 2440588 /* = jday(1, 1, 1970) */ + +/* POSIX version ******************************************************/ + +#if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY) + +#if 0 /* 29/VI-2017 */ +#include +#include + +double glp_time(void) +{ struct timeval tv; + struct tm *tm; + int j; + double t; + gettimeofday(&tv, NULL); +#if 0 /* 29/I-2017 */ + tm = gmtime(&tv.tv_sec); +#else + tm = xgmtime(&tv.tv_sec); +#endif + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0 + + (double)(tv.tv_usec / 1000); + return t; +} +#else +#include + +double glp_time(void) +{ struct timeval tv; + double t; + gettimeofday(&tv, NULL); + t = (double)tv.tv_sec + (double)(tv.tv_usec) / 1e6; + xassert(0.0 <= t && t < 4294967296.0); + return 1000.0 * t; +} +#endif + +/* MS Windows version *************************************************/ + +#elif defined(__WOE__) + +#include + +double glp_time(void) +{ SYSTEMTIME st; + int j; + double t; + GetSystemTime(&st); + j = jday(st.wDay, st.wMonth, st.wYear); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)st.wHour) * 60.0 + + (double)st.wMinute) * 60.0 + (double)st.wSecond) * 1000.0 + + (double)st.wMilliseconds; + return t; +} + +/* portable ANSI C version ********************************************/ + +#else + +#include + +double glp_time(void) +{ time_t timer; + struct tm *tm; + int j; + double t; + timer = time(NULL); +#if 0 /* 29/I-2017 */ + tm = gmtime(&timer); +#else + tm = xgmtime(&timer); +#endif + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + xassert(j >= 0); + t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0; + return t; +} + +#endif + +/*********************************************************************** +* NAME +* +* glp_difftime - compute difference between two time values +* +* SYNOPSIS +* +* double glp_difftime(double t1, double t0); +* +* RETURNS +* +* The routine glp_difftime returns the difference between two time +* values t1 and t0, expressed in seconds. */ + +double glp_difftime(double t1, double t0) +{ return + (t1 - t0) / 1000.0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/env/tls.c b/WebAPP/SOLVERs/GLPK/glpk/src/env/tls.c new file mode 100644 index 000000000..4062ee4ce --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/env/tls.c @@ -0,0 +1,128 @@ +/* tls.c (thread local storage) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2001-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "env.h" + +#ifndef TLS +static void *tls = NULL; +#else +static TLS void *tls = NULL; +/* this option allows running multiple independent instances of GLPK in + * different threads of a multi-threaded application, in which case the + * variable tls should be placed in the Thread Local Storage (TLS); + * it is assumed that the macro TLS is previously defined to something + * like '__thread', '_Thread_local', etc. */ +#endif + +/*********************************************************************** +* NAME +* +* tls_set_ptr - store global pointer in TLS +* +* SYNOPSIS +* +* #include "env.h" +* void tls_set_ptr(void *ptr); +* +* DESCRIPTION +* +* The routine tls_set_ptr stores a pointer specified by the parameter +* ptr in the Thread Local Storage (TLS). */ + +void tls_set_ptr(void *ptr) +{ tls = ptr; + return; +} + +/*********************************************************************** +* NAME +* +* tls_get_ptr - retrieve global pointer from TLS +* +* SYNOPSIS +* +* #include "env.h" +* void *tls_get_ptr(void); +* +* RETURNS +* +* The routine tls_get_ptr returns a pointer previously stored by the +* routine tls_set_ptr. If the latter has not been called yet, NULL is +* returned. */ + +void *tls_get_ptr(void) +{ void *ptr; + ptr = tls; + return ptr; +} + +/**********************************************************************/ + +#ifdef __WOE__ + +/*** Author: Heinrich Schuchardt ***/ + +#pragma comment(lib, "user32.lib") + +#include + +#define VISTA 0x06 + +/* This is the main entry point of the DLL. */ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID + lpvReserved) +{ DWORD version; + DWORD major_version; +#ifdef TLS + switch (fdwReason) + { case DLL_PROCESS_ATTACH: + /* @TODO: + * GetVersion is deprecated but the version help functions are + * not available in Visual Studio 2010. So lets use it until + * we remove the outdated Build files. */ + version = GetVersion(); + major_version = version & 0xff; + if (major_version < VISTA) + { MessageBoxA(NULL, + "The GLPK library called by this application is configur" + "ed to use thread local storage which is not fully suppo" + "rted by your version of Microsoft Windows.\n\n" + "Microsoft Windows Vista or a later version of Windows i" + "s required to run this application.", + "GLPK", MB_OK | MB_ICONERROR); + return FALSE; + } + break; + } +#endif /* TLS */ + return TRUE; +} + +#endif /* __WOE__ */ + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/glpk.h b/WebAPP/SOLVERs/GLPK/glpk/src/glpk.h new file mode 100644 index 000000000..f4e250f90 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/glpk.h @@ -0,0 +1,1175 @@ +/* glpk.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef GLPK_H +#define GLPK_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* library version numbers: */ +#define GLP_MAJOR_VERSION 4 +#define GLP_MINOR_VERSION 65 + +typedef struct glp_prob glp_prob; +/* LP/MIP problem object */ + +/* optimization direction flag: */ +#define GLP_MIN 1 /* minimization */ +#define GLP_MAX 2 /* maximization */ + +/* kind of structural variable: */ +#define GLP_CV 1 /* continuous variable */ +#define GLP_IV 2 /* integer variable */ +#define GLP_BV 3 /* binary variable */ + +/* type of auxiliary/structural variable: */ +#define GLP_FR 1 /* free (unbounded) variable */ +#define GLP_LO 2 /* variable with lower bound */ +#define GLP_UP 3 /* variable with upper bound */ +#define GLP_DB 4 /* double-bounded variable */ +#define GLP_FX 5 /* fixed variable */ + +/* status of auxiliary/structural variable: */ +#define GLP_BS 1 /* basic variable */ +#define GLP_NL 2 /* non-basic variable on lower bound */ +#define GLP_NU 3 /* non-basic variable on upper bound */ +#define GLP_NF 4 /* non-basic free (unbounded) variable */ +#define GLP_NS 5 /* non-basic fixed variable */ + +/* scaling options: */ +#define GLP_SF_GM 0x01 /* perform geometric mean scaling */ +#define GLP_SF_EQ 0x10 /* perform equilibration scaling */ +#define GLP_SF_2N 0x20 /* round scale factors to power of two */ +#define GLP_SF_SKIP 0x40 /* skip if problem is well scaled */ +#define GLP_SF_AUTO 0x80 /* choose scaling options automatically */ + +/* solution indicator: */ +#define GLP_SOL 1 /* basic solution */ +#define GLP_IPT 2 /* interior-point solution */ +#define GLP_MIP 3 /* mixed integer solution */ + +/* solution status: */ +#define GLP_UNDEF 1 /* solution is undefined */ +#define GLP_FEAS 2 /* solution is feasible */ +#define GLP_INFEAS 3 /* solution is infeasible */ +#define GLP_NOFEAS 4 /* no feasible solution exists */ +#define GLP_OPT 5 /* solution is optimal */ +#define GLP_UNBND 6 /* solution is unbounded */ + +typedef struct +{ /* basis factorization control parameters */ + int msg_lev; /* (not used) */ + int type; /* factorization type: */ +#if 1 /* 05/III-2014 */ +#define GLP_BF_LUF 0x00 /* plain LU-factorization */ +#define GLP_BF_BTF 0x10 /* block triangular LU-factorization */ +#endif +#define GLP_BF_FT 0x01 /* Forrest-Tomlin (LUF only) */ +#define GLP_BF_BG 0x02 /* Schur compl. + Bartels-Golub */ +#define GLP_BF_GR 0x03 /* Schur compl. + Givens rotation */ + int lu_size; /* (not used) */ + double piv_tol; /* sgf_piv_tol */ + int piv_lim; /* sgf_piv_lim */ + int suhl; /* sgf_suhl */ + double eps_tol; /* sgf_eps_tol */ + double max_gro; /* (not used) */ + int nfs_max; /* fhvint.nfs_max */ + double upd_tol; /* (not used) */ + int nrs_max; /* scfint.nn_max */ + int rs_size; /* (not used) */ + double foo_bar[38]; /* (reserved) */ +} glp_bfcp; + +typedef struct +{ /* simplex solver control parameters */ + int msg_lev; /* message level: */ +#define GLP_MSG_OFF 0 /* no output */ +#define GLP_MSG_ERR 1 /* warning and error messages only */ +#define GLP_MSG_ON 2 /* normal output */ +#define GLP_MSG_ALL 3 /* full output */ +#define GLP_MSG_DBG 4 /* debug output */ + int meth; /* simplex method option: */ +#define GLP_PRIMAL 1 /* use primal simplex */ +#define GLP_DUALP 2 /* use dual; if it fails, use primal */ +#define GLP_DUAL 3 /* use dual simplex */ + int pricing; /* pricing technique: */ +#define GLP_PT_STD 0x11 /* standard (Dantzig's rule) */ +#define GLP_PT_PSE 0x22 /* projected steepest edge */ + int r_test; /* ratio test technique: */ +#define GLP_RT_STD 0x11 /* standard (textbook) */ +#define GLP_RT_HAR 0x22 /* Harris' two-pass ratio test */ +#if 1 /* 16/III-2016 */ +#define GLP_RT_FLIP 0x33 /* long-step (flip-flop) ratio test */ +#endif + double tol_bnd; /* primal feasibility tolerance */ + double tol_dj; /* dual feasibility tolerance */ + double tol_piv; /* pivot tolerance */ + double obj_ll; /* lower objective limit */ + double obj_ul; /* upper objective limit */ + int it_lim; /* simplex iteration limit */ + int tm_lim; /* time limit, ms */ + int out_frq; /* display output frequency, ms */ + int out_dly; /* display output delay, ms */ + int presolve; /* enable/disable using LP presolver */ +#if 1 /* 11/VII-2017 (not documented yet) */ + int excl; /* exclude fixed non-basic variables */ + int shift; /* shift bounds of variables to zero */ + int aorn; /* option to use A or N: */ +#define GLP_USE_AT 1 /* use A matrix in row-wise format */ +#define GLP_USE_NT 2 /* use N matrix in row-wise format */ + double foo_bar[33]; /* (reserved) */ +#endif +} glp_smcp; + +typedef struct +{ /* interior-point solver control parameters */ + int msg_lev; /* message level (see glp_smcp) */ + int ord_alg; /* ordering algorithm: */ +#define GLP_ORD_NONE 0 /* natural (original) ordering */ +#define GLP_ORD_QMD 1 /* quotient minimum degree (QMD) */ +#define GLP_ORD_AMD 2 /* approx. minimum degree (AMD) */ +#define GLP_ORD_SYMAMD 3 /* approx. minimum degree (SYMAMD) */ + double foo_bar[48]; /* (reserved) */ +} glp_iptcp; + +typedef struct glp_tree glp_tree; +/* branch-and-bound tree */ + +typedef struct +{ /* integer optimizer control parameters */ + int msg_lev; /* message level (see glp_smcp) */ + int br_tech; /* branching technique: */ +#define GLP_BR_FFV 1 /* first fractional variable */ +#define GLP_BR_LFV 2 /* last fractional variable */ +#define GLP_BR_MFV 3 /* most fractional variable */ +#define GLP_BR_DTH 4 /* heuristic by Driebeck and Tomlin */ +#define GLP_BR_PCH 5 /* hybrid pseudocost heuristic */ + int bt_tech; /* backtracking technique: */ +#define GLP_BT_DFS 1 /* depth first search */ +#define GLP_BT_BFS 2 /* breadth first search */ +#define GLP_BT_BLB 3 /* best local bound */ +#define GLP_BT_BPH 4 /* best projection heuristic */ + double tol_int; /* mip.tol_int */ + double tol_obj; /* mip.tol_obj */ + int tm_lim; /* mip.tm_lim (milliseconds) */ + int out_frq; /* mip.out_frq (milliseconds) */ + int out_dly; /* mip.out_dly (milliseconds) */ + void (*cb_func)(glp_tree *T, void *info); + /* mip.cb_func */ + void *cb_info; /* mip.cb_info */ + int cb_size; /* mip.cb_size */ + int pp_tech; /* preprocessing technique: */ +#define GLP_PP_NONE 0 /* disable preprocessing */ +#define GLP_PP_ROOT 1 /* preprocessing only on root level */ +#define GLP_PP_ALL 2 /* preprocessing on all levels */ + double mip_gap; /* relative MIP gap tolerance */ + int mir_cuts; /* MIR cuts (GLP_ON/GLP_OFF) */ + int gmi_cuts; /* Gomory's cuts (GLP_ON/GLP_OFF) */ + int cov_cuts; /* cover cuts (GLP_ON/GLP_OFF) */ + int clq_cuts; /* clique cuts (GLP_ON/GLP_OFF) */ + int presolve; /* enable/disable using MIP presolver */ + int binarize; /* try to binarize integer variables */ + int fp_heur; /* feasibility pump heuristic */ + int ps_heur; /* proximity search heuristic */ + int ps_tm_lim; /* proxy time limit, milliseconds */ + int sr_heur; /* simple rounding heuristic */ +#if 1 /* 24/X-2015; not documented--should not be used */ + int use_sol; /* use existing solution */ + const char *save_sol; /* filename to save every new solution */ + int alien; /* use alien solver */ +#endif +#if 1 /* 16/III-2016; not documented--should not be used */ + int flip; /* use long-step dual simplex */ +#endif + double foo_bar[23]; /* (reserved) */ +} glp_iocp; + +typedef struct +{ /* additional row attributes */ + int level; + /* subproblem level at which the row was added */ + int origin; + /* row origin flag: */ +#define GLP_RF_REG 0 /* regular constraint */ +#define GLP_RF_LAZY 1 /* "lazy" constraint */ +#define GLP_RF_CUT 2 /* cutting plane constraint */ + int klass; + /* row class descriptor: */ +#define GLP_RF_GMI 1 /* Gomory's mixed integer cut */ +#define GLP_RF_MIR 2 /* mixed integer rounding cut */ +#define GLP_RF_COV 3 /* mixed cover cut */ +#define GLP_RF_CLQ 4 /* clique cut */ + double foo_bar[7]; + /* (reserved) */ +} glp_attr; + +/* enable/disable flag: */ +#define GLP_ON 1 /* enable something */ +#define GLP_OFF 0 /* disable something */ + +/* reason codes: */ +#define GLP_IROWGEN 0x01 /* request for row generation */ +#define GLP_IBINGO 0x02 /* better integer solution found */ +#define GLP_IHEUR 0x03 /* request for heuristic solution */ +#define GLP_ICUTGEN 0x04 /* request for cut generation */ +#define GLP_IBRANCH 0x05 /* request for branching */ +#define GLP_ISELECT 0x06 /* request for subproblem selection */ +#define GLP_IPREPRO 0x07 /* request for preprocessing */ + +/* branch selection indicator: */ +#define GLP_NO_BRNCH 0 /* select no branch */ +#define GLP_DN_BRNCH 1 /* select down-branch */ +#define GLP_UP_BRNCH 2 /* select up-branch */ + +/* return codes: */ +#define GLP_EBADB 0x01 /* invalid basis */ +#define GLP_ESING 0x02 /* singular matrix */ +#define GLP_ECOND 0x03 /* ill-conditioned matrix */ +#define GLP_EBOUND 0x04 /* invalid bounds */ +#define GLP_EFAIL 0x05 /* solver failed */ +#define GLP_EOBJLL 0x06 /* objective lower limit reached */ +#define GLP_EOBJUL 0x07 /* objective upper limit reached */ +#define GLP_EITLIM 0x08 /* iteration limit exceeded */ +#define GLP_ETMLIM 0x09 /* time limit exceeded */ +#define GLP_ENOPFS 0x0A /* no primal feasible solution */ +#define GLP_ENODFS 0x0B /* no dual feasible solution */ +#define GLP_EROOT 0x0C /* root LP optimum not provided */ +#define GLP_ESTOP 0x0D /* search terminated by application */ +#define GLP_EMIPGAP 0x0E /* relative mip gap tolerance reached */ +#define GLP_ENOFEAS 0x0F /* no primal/dual feasible solution */ +#define GLP_ENOCVG 0x10 /* no convergence */ +#define GLP_EINSTAB 0x11 /* numerical instability */ +#define GLP_EDATA 0x12 /* invalid data */ +#define GLP_ERANGE 0x13 /* result out of range */ + +/* condition indicator: */ +#define GLP_KKT_PE 1 /* primal equalities */ +#define GLP_KKT_PB 2 /* primal bounds */ +#define GLP_KKT_DE 3 /* dual equalities */ +#define GLP_KKT_DB 4 /* dual bounds */ +#define GLP_KKT_CS 5 /* complementary slackness */ + +/* MPS file format: */ +#define GLP_MPS_DECK 1 /* fixed (ancient) */ +#define GLP_MPS_FILE 2 /* free (modern) */ + +typedef struct +{ /* MPS format control parameters */ + int blank; + /* character code to replace blanks in symbolic names */ + char *obj_name; + /* objective row name */ + double tol_mps; + /* zero tolerance for MPS data */ + double foo_bar[17]; + /* (reserved for use in the future) */ +} glp_mpscp; + +typedef struct +{ /* CPLEX LP format control parameters */ + double foo_bar[20]; + /* (reserved for use in the future) */ +} glp_cpxcp; + +#if 1 /* 10/XII-2017 */ +typedef struct glp_prep glp_prep; +/* LP/MIP preprocessor workspace */ +#endif + +typedef struct glp_tran glp_tran; +/* MathProg translator workspace */ + +glp_prob *glp_create_prob(void); +/* create problem object */ + +void glp_set_prob_name(glp_prob *P, const char *name); +/* assign (change) problem name */ + +void glp_set_obj_name(glp_prob *P, const char *name); +/* assign (change) objective function name */ + +void glp_set_obj_dir(glp_prob *P, int dir); +/* set (change) optimization direction flag */ + +int glp_add_rows(glp_prob *P, int nrs); +/* add new rows to problem object */ + +int glp_add_cols(glp_prob *P, int ncs); +/* add new columns to problem object */ + +void glp_set_row_name(glp_prob *P, int i, const char *name); +/* assign (change) row name */ + +void glp_set_col_name(glp_prob *P, int j, const char *name); +/* assign (change) column name */ + +void glp_set_row_bnds(glp_prob *P, int i, int type, double lb, + double ub); +/* set (change) row bounds */ + +void glp_set_col_bnds(glp_prob *P, int j, int type, double lb, + double ub); +/* set (change) column bounds */ + +void glp_set_obj_coef(glp_prob *P, int j, double coef); +/* set (change) obj. coefficient or constant term */ + +void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], + const double val[]); +/* set (replace) row of the constraint matrix */ + +void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], + const double val[]); +/* set (replace) column of the constraint matrix */ + +void glp_load_matrix(glp_prob *P, int ne, const int ia[], + const int ja[], const double ar[]); +/* load (replace) the whole constraint matrix */ + +int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]); +/* check for duplicate elements in sparse matrix */ + +void glp_sort_matrix(glp_prob *P); +/* sort elements of the constraint matrix */ + +void glp_del_rows(glp_prob *P, int nrs, const int num[]); +/* delete specified rows from problem object */ + +void glp_del_cols(glp_prob *P, int ncs, const int num[]); +/* delete specified columns from problem object */ + +void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); +/* copy problem object content */ + +void glp_erase_prob(glp_prob *P); +/* erase problem object content */ + +void glp_delete_prob(glp_prob *P); +/* delete problem object */ + +const char *glp_get_prob_name(glp_prob *P); +/* retrieve problem name */ + +const char *glp_get_obj_name(glp_prob *P); +/* retrieve objective function name */ + +int glp_get_obj_dir(glp_prob *P); +/* retrieve optimization direction flag */ + +int glp_get_num_rows(glp_prob *P); +/* retrieve number of rows */ + +int glp_get_num_cols(glp_prob *P); +/* retrieve number of columns */ + +const char *glp_get_row_name(glp_prob *P, int i); +/* retrieve row name */ + +const char *glp_get_col_name(glp_prob *P, int j); +/* retrieve column name */ + +int glp_get_row_type(glp_prob *P, int i); +/* retrieve row type */ + +double glp_get_row_lb(glp_prob *P, int i); +/* retrieve row lower bound */ + +double glp_get_row_ub(glp_prob *P, int i); +/* retrieve row upper bound */ + +int glp_get_col_type(glp_prob *P, int j); +/* retrieve column type */ + +double glp_get_col_lb(glp_prob *P, int j); +/* retrieve column lower bound */ + +double glp_get_col_ub(glp_prob *P, int j); +/* retrieve column upper bound */ + +double glp_get_obj_coef(glp_prob *P, int j); +/* retrieve obj. coefficient or constant term */ + +int glp_get_num_nz(glp_prob *P); +/* retrieve number of constraint coefficients */ + +int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); +/* retrieve row of the constraint matrix */ + +int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); +/* retrieve column of the constraint matrix */ + +void glp_create_index(glp_prob *P); +/* create the name index */ + +int glp_find_row(glp_prob *P, const char *name); +/* find row by its name */ + +int glp_find_col(glp_prob *P, const char *name); +/* find column by its name */ + +void glp_delete_index(glp_prob *P); +/* delete the name index */ + +void glp_set_rii(glp_prob *P, int i, double rii); +/* set (change) row scale factor */ + +void glp_set_sjj(glp_prob *P, int j, double sjj); +/* set (change) column scale factor */ + +double glp_get_rii(glp_prob *P, int i); +/* retrieve row scale factor */ + +double glp_get_sjj(glp_prob *P, int j); +/* retrieve column scale factor */ + +void glp_scale_prob(glp_prob *P, int flags); +/* scale problem data */ + +void glp_unscale_prob(glp_prob *P); +/* unscale problem data */ + +void glp_set_row_stat(glp_prob *P, int i, int stat); +/* set (change) row status */ + +void glp_set_col_stat(glp_prob *P, int j, int stat); +/* set (change) column status */ + +void glp_std_basis(glp_prob *P); +/* construct standard initial LP basis */ + +void glp_adv_basis(glp_prob *P, int flags); +/* construct advanced initial LP basis */ + +void glp_cpx_basis(glp_prob *P); +/* construct Bixby's initial LP basis */ + +int glp_simplex(glp_prob *P, const glp_smcp *parm); +/* solve LP problem with the simplex method */ + +int glp_exact(glp_prob *P, const glp_smcp *parm); +/* solve LP problem in exact arithmetic */ + +void glp_init_smcp(glp_smcp *parm); +/* initialize simplex method control parameters */ + +int glp_get_status(glp_prob *P); +/* retrieve generic status of basic solution */ + +int glp_get_prim_stat(glp_prob *P); +/* retrieve status of primal basic solution */ + +int glp_get_dual_stat(glp_prob *P); +/* retrieve status of dual basic solution */ + +double glp_get_obj_val(glp_prob *P); +/* retrieve objective value (basic solution) */ + +int glp_get_row_stat(glp_prob *P, int i); +/* retrieve row status */ + +double glp_get_row_prim(glp_prob *P, int i); +/* retrieve row primal value (basic solution) */ + +double glp_get_row_dual(glp_prob *P, int i); +/* retrieve row dual value (basic solution) */ + +int glp_get_col_stat(glp_prob *P, int j); +/* retrieve column status */ + +double glp_get_col_prim(glp_prob *P, int j); +/* retrieve column primal value (basic solution) */ + +double glp_get_col_dual(glp_prob *P, int j); +/* retrieve column dual value (basic solution) */ + +int glp_get_unbnd_ray(glp_prob *P); +/* determine variable causing unboundedness */ + +#if 1 /* 08/VIII-2013; not documented yet */ +int glp_get_it_cnt(glp_prob *P); +/* get simplex solver iteration count */ +#endif + +#if 1 /* 08/VIII-2013; not documented yet */ +void glp_set_it_cnt(glp_prob *P, int it_cnt); +/* set simplex solver iteration count */ +#endif + +int glp_interior(glp_prob *P, const glp_iptcp *parm); +/* solve LP problem with the interior-point method */ + +void glp_init_iptcp(glp_iptcp *parm); +/* initialize interior-point solver control parameters */ + +int glp_ipt_status(glp_prob *P); +/* retrieve status of interior-point solution */ + +double glp_ipt_obj_val(glp_prob *P); +/* retrieve objective value (interior point) */ + +double glp_ipt_row_prim(glp_prob *P, int i); +/* retrieve row primal value (interior point) */ + +double glp_ipt_row_dual(glp_prob *P, int i); +/* retrieve row dual value (interior point) */ + +double glp_ipt_col_prim(glp_prob *P, int j); +/* retrieve column primal value (interior point) */ + +double glp_ipt_col_dual(glp_prob *P, int j); +/* retrieve column dual value (interior point) */ + +void glp_set_col_kind(glp_prob *P, int j, int kind); +/* set (change) column kind */ + +int glp_get_col_kind(glp_prob *P, int j); +/* retrieve column kind */ + +int glp_get_num_int(glp_prob *P); +/* retrieve number of integer columns */ + +int glp_get_num_bin(glp_prob *P); +/* retrieve number of binary columns */ + +int glp_intopt(glp_prob *P, const glp_iocp *parm); +/* solve MIP problem with the branch-and-bound method */ + +void glp_init_iocp(glp_iocp *parm); +/* initialize integer optimizer control parameters */ + +int glp_mip_status(glp_prob *P); +/* retrieve status of MIP solution */ + +double glp_mip_obj_val(glp_prob *P); +/* retrieve objective value (MIP solution) */ + +double glp_mip_row_val(glp_prob *P, int i); +/* retrieve row value (MIP solution) */ + +double glp_mip_col_val(glp_prob *P, int j); +/* retrieve column value (MIP solution) */ + +void glp_check_kkt(glp_prob *P, int sol, int cond, double *ae_max, + int *ae_ind, double *re_max, int *re_ind); +/* check feasibility/optimality conditions */ + +int glp_print_sol(glp_prob *P, const char *fname); +/* write basic solution in printable format */ + +int glp_read_sol(glp_prob *P, const char *fname); +/* read basic solution from text file */ + +int glp_write_sol(glp_prob *P, const char *fname); +/* write basic solution to text file */ + +int glp_print_ranges(glp_prob *P, int len, const int list[], + int flags, const char *fname); +/* print sensitivity analysis report */ + +int glp_print_ipt(glp_prob *P, const char *fname); +/* write interior-point solution in printable format */ + +int glp_read_ipt(glp_prob *P, const char *fname); +/* read interior-point solution from text file */ + +int glp_write_ipt(glp_prob *P, const char *fname); +/* write interior-point solution to text file */ + +int glp_print_mip(glp_prob *P, const char *fname); +/* write MIP solution in printable format */ + +int glp_read_mip(glp_prob *P, const char *fname); +/* read MIP solution from text file */ + +int glp_write_mip(glp_prob *P, const char *fname); +/* write MIP solution to text file */ + +int glp_bf_exists(glp_prob *P); +/* check if LP basis factorization exists */ + +int glp_factorize(glp_prob *P); +/* compute LP basis factorization */ + +int glp_bf_updated(glp_prob *P); +/* check if LP basis factorization has been updated */ + +void glp_get_bfcp(glp_prob *P, glp_bfcp *parm); +/* retrieve LP basis factorization control parameters */ + +void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm); +/* change LP basis factorization control parameters */ + +int glp_get_bhead(glp_prob *P, int k); +/* retrieve LP basis header information */ + +int glp_get_row_bind(glp_prob *P, int i); +/* retrieve row index in the basis header */ + +int glp_get_col_bind(glp_prob *P, int j); +/* retrieve column index in the basis header */ + +void glp_ftran(glp_prob *P, double x[]); +/* perform forward transformation (solve system B*x = b) */ + +void glp_btran(glp_prob *P, double x[]); +/* perform backward transformation (solve system B'*x = b) */ + +int glp_warm_up(glp_prob *P); +/* "warm up" LP basis */ + +int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); +/* compute row of the simplex tableau */ + +int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); +/* compute column of the simplex tableau */ + +int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); +/* transform explicitly specified row */ + +int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); +/* transform explicitly specified column */ + +int glp_prim_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps); +/* perform primal ratio test */ + +int glp_dual_rtest(glp_prob *P, int len, const int ind[], + const double val[], int dir, double eps); +/* perform dual ratio test */ + +void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, + double *value2, int *var2); +/* analyze active bound of non-basic variable */ + +void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, + double *value1, double *coef2, int *var2, double *value2); +/* analyze objective coefficient at basic variable */ + +#if 1 /* 10/XII-2017 */ +glp_prep *glp_npp_alloc_wksp(void); +/* allocate the preprocessor workspace */ + +void glp_npp_load_prob(glp_prep *prep, glp_prob *P, int sol, + int names); +/* load original problem instance */ + +int glp_npp_preprocess1(glp_prep *prep, int hard); +/* perform basic LP/MIP preprocessing */ + +void glp_npp_build_prob(glp_prep *prep, glp_prob *Q); +/* build resultant problem instance */ + +void glp_npp_postprocess(glp_prep *prep, glp_prob *Q); +/* postprocess solution to resultant problem */ + +void glp_npp_obtain_sol(glp_prep *prep, glp_prob *P); +/* obtain solution to original problem */ + +void glp_npp_free_wksp(glp_prep *prep); +/* free the preprocessor workspace */ +#endif + +int glp_ios_reason(glp_tree *T); +/* determine reason for calling the callback routine */ + +glp_prob *glp_ios_get_prob(glp_tree *T); +/* access the problem object */ + +void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, + int *t_cnt); +/* determine size of the branch-and-bound tree */ + +int glp_ios_curr_node(glp_tree *T); +/* determine current active subproblem */ + +int glp_ios_next_node(glp_tree *T, int p); +/* determine next active subproblem */ + +int glp_ios_prev_node(glp_tree *T, int p); +/* determine previous active subproblem */ + +int glp_ios_up_node(glp_tree *T, int p); +/* determine parent subproblem */ + +int glp_ios_node_level(glp_tree *T, int p); +/* determine subproblem level */ + +double glp_ios_node_bound(glp_tree *T, int p); +/* determine subproblem local bound */ + +int glp_ios_best_node(glp_tree *T); +/* find active subproblem with best local bound */ + +double glp_ios_mip_gap(glp_tree *T); +/* compute relative MIP gap */ + +void *glp_ios_node_data(glp_tree *T, int p); +/* access subproblem application-specific data */ + +void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); +/* retrieve additional row attributes */ + +int glp_ios_pool_size(glp_tree *T); +/* determine current size of the cut pool */ + +int glp_ios_add_row(glp_tree *T, + const char *name, int klass, int flags, int len, const int ind[], + const double val[], int type, double rhs); +/* add row (constraint) to the cut pool */ + +void glp_ios_del_row(glp_tree *T, int i); +/* remove row (constraint) from the cut pool */ + +void glp_ios_clear_pool(glp_tree *T); +/* remove all rows (constraints) from the cut pool */ + +int glp_ios_can_branch(glp_tree *T, int j); +/* check if can branch upon specified variable */ + +void glp_ios_branch_upon(glp_tree *T, int j, int sel); +/* choose variable to branch upon */ + +void glp_ios_select_node(glp_tree *T, int p); +/* select subproblem to continue the search */ + +int glp_ios_heur_sol(glp_tree *T, const double x[]); +/* provide solution found by heuristic */ + +void glp_ios_terminate(glp_tree *T); +/* terminate the solution process */ + +#ifdef GLP_UNDOC +int glp_gmi_cut(glp_prob *P, int j, int ind[], double val[], double + phi[]); +/* generate Gomory's mixed integer cut (core routine) */ + +int glp_gmi_gen(glp_prob *P, glp_prob *pool, int max_cuts); +/* generate Gomory's mixed integer cuts */ + +typedef struct glp_cov glp_cov; +/* cover cur generator workspace */ + +glp_cov *glp_cov_init(glp_prob *P); +/* create and initialize cover cut generator */ + +void glp_cov_gen1(glp_prob *P, glp_cov *cov, glp_prob *pool); +/* generate locally valid simple cover cuts */ + +void glp_cov_free(glp_cov *cov); +/* delete cover cut generator workspace */ + +typedef struct glp_mir glp_mir; +/* MIR cut generator workspace */ + +glp_mir *glp_mir_init(glp_prob *P); +/* create and initialize MIR cut generator */ + +int glp_mir_gen(glp_prob *P, glp_mir *mir, glp_prob *pool); +/* generate mixed integer rounding (MIR) cuts */ + +void glp_mir_free(glp_mir *mir); +/* delete MIR cut generator workspace */ + +typedef struct glp_cfg glp_cfg; +/* conflict graph descriptor */ + +glp_cfg *glp_cfg_init(glp_prob *P); +/* create and initialize conflict graph */ + +void glp_cfg_free(glp_cfg *G); +/* delete conflict graph descriptor */ + +int glp_clq_cut(glp_prob *P, glp_cfg *G, int ind[], double val[]); +/* generate clique cut from conflict graph */ +#endif /* GLP_UNDOC */ + +void glp_init_mpscp(glp_mpscp *parm); +/* initialize MPS format control parameters */ + +int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +/* read problem data in MPS format */ + +int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, + const char *fname); +/* write problem data in MPS format */ + +void glp_init_cpxcp(glp_cpxcp *parm); +/* initialize CPLEX LP format control parameters */ + +int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); +/* read problem data in CPLEX LP format */ + +int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); +/* write problem data in CPLEX LP format */ + +int glp_read_prob(glp_prob *P, int flags, const char *fname); +/* read problem data in GLPK format */ + +int glp_write_prob(glp_prob *P, int flags, const char *fname); +/* write problem data in GLPK format */ + +glp_tran *glp_mpl_alloc_wksp(void); +/* allocate the MathProg translator workspace */ + +void glp_mpl_init_rand(glp_tran *tran, int seed); +/* initialize pseudo-random number generator */ + +int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); +/* read and translate model section */ + +int glp_mpl_read_data(glp_tran *tran, const char *fname); +/* read and translate data section */ + +int glp_mpl_generate(glp_tran *tran, const char *fname); +/* generate the model */ + +void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob); +/* build LP/MIP problem instance from the model */ + +int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol); +/* postsolve the model */ + +void glp_mpl_free_wksp(glp_tran *tran); +/* free the MathProg translator workspace */ + +int glp_read_cnfsat(glp_prob *P, const char *fname); +/* read CNF-SAT problem data in DIMACS format */ + +int glp_check_cnfsat(glp_prob *P); +/* check for CNF-SAT problem instance */ + +int glp_write_cnfsat(glp_prob *P, const char *fname); +/* write CNF-SAT problem data in DIMACS format */ + +int glp_minisat1(glp_prob *P); +/* solve CNF-SAT problem with MiniSat solver */ + +int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); +/* solve integer feasibility problem */ + +int glp_init_env(void); +/* initialize GLPK environment */ + +const char *glp_version(void); +/* determine library version */ + +const char *glp_config(const char *option); +/* determine library configuration */ + +int glp_free_env(void); +/* free GLPK environment */ + +void glp_puts(const char *s); +/* write string on terminal */ + +void glp_printf(const char *fmt, ...); +/* write formatted output on terminal */ + +void glp_vprintf(const char *fmt, va_list arg); +/* write formatted output on terminal */ + +int glp_term_out(int flag); +/* enable/disable terminal output */ + +void glp_term_hook(int (*func)(void *info, const char *s), void *info); +/* install hook to intercept terminal output */ + +int glp_open_tee(const char *name); +/* start copying terminal output to text file */ + +int glp_close_tee(void); +/* stop copying terminal output to text file */ + +#ifndef GLP_ERRFUNC_DEFINED +#define GLP_ERRFUNC_DEFINED +typedef void (*glp_errfunc)(const char *fmt, ...); +#endif + +#define glp_error glp_error_(__FILE__, __LINE__) +glp_errfunc glp_error_(const char *file, int line); +/* display fatal error message and terminate execution */ + +#if 1 /* 07/XI-2015 */ +int glp_at_error(void); +/* check for error state */ +#endif + +#define glp_assert(expr) \ + ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) +void glp_assert_(const char *expr, const char *file, int line); +/* check for logical condition */ + +void glp_error_hook(void (*func)(void *info), void *info); +/* install hook to intercept abnormal termination */ + +#define glp_malloc(size) glp_alloc(1, size) +/* allocate memory block (obsolete) */ + +#define glp_calloc(n, size) glp_alloc(n, size) +/* allocate memory block (obsolete) */ + +void *glp_alloc(int n, int size); +/* allocate memory block */ + +void *glp_realloc(void *ptr, int n, int size); +/* reallocate memory block */ + +void glp_free(void *ptr); +/* free (deallocate) memory block */ + +void glp_mem_limit(int limit); +/* set memory usage limit */ + +void glp_mem_usage(int *count, int *cpeak, size_t *total, + size_t *tpeak); +/* get memory usage information */ + +double glp_time(void); +/* determine current universal time */ + +double glp_difftime(double t1, double t0); +/* compute difference between two time values */ + +typedef struct glp_graph glp_graph; +typedef struct glp_vertex glp_vertex; +typedef struct glp_arc glp_arc; + +struct glp_graph +{ /* graph descriptor */ + void *pool; /* DMP *pool; */ + /* memory pool to store graph components */ + char *name; + /* graph name (1 to 255 chars); NULL means no name is assigned + to the graph */ + int nv_max; + /* length of the vertex list (enlarged automatically) */ + int nv; + /* number of vertices in the graph, 0 <= nv <= nv_max */ + int na; + /* number of arcs in the graph, na >= 0 */ + glp_vertex **v; /* glp_vertex *v[1+nv_max]; */ + /* v[i], 1 <= i <= nv, is a pointer to i-th vertex */ + void *index; /* AVL *index; */ + /* vertex index to find vertices by their names; NULL means the + index does not exist */ + int v_size; + /* size of data associated with each vertex (0 to 256 bytes) */ + int a_size; + /* size of data associated with each arc (0 to 256 bytes) */ +}; + +struct glp_vertex +{ /* vertex descriptor */ + int i; + /* vertex ordinal number, 1 <= i <= nv */ + char *name; + /* vertex name (1 to 255 chars); NULL means no name is assigned + to the vertex */ + void *entry; /* AVLNODE *entry; */ + /* pointer to corresponding entry in the vertex index; NULL means + that either the index does not exist or the vertex has no name + assigned */ + void *data; + /* pointer to data associated with the vertex */ + void *temp; + /* working pointer */ + glp_arc *in; + /* pointer to the (unordered) list of incoming arcs */ + glp_arc *out; + /* pointer to the (unordered) list of outgoing arcs */ +}; + +struct glp_arc +{ /* arc descriptor */ + glp_vertex *tail; + /* pointer to the tail endpoint */ + glp_vertex *head; + /* pointer to the head endpoint */ + void *data; + /* pointer to data associated with the arc */ + void *temp; + /* working pointer */ + glp_arc *t_prev; + /* pointer to previous arc having the same tail endpoint */ + glp_arc *t_next; + /* pointer to next arc having the same tail endpoint */ + glp_arc *h_prev; + /* pointer to previous arc having the same head endpoint */ + glp_arc *h_next; + /* pointer to next arc having the same head endpoint */ +}; + +glp_graph *glp_create_graph(int v_size, int a_size); +/* create graph */ + +void glp_set_graph_name(glp_graph *G, const char *name); +/* assign (change) graph name */ + +int glp_add_vertices(glp_graph *G, int nadd); +/* add new vertices to graph */ + +void glp_set_vertex_name(glp_graph *G, int i, const char *name); +/* assign (change) vertex name */ + +glp_arc *glp_add_arc(glp_graph *G, int i, int j); +/* add new arc to graph */ + +void glp_del_vertices(glp_graph *G, int ndel, const int num[]); +/* delete vertices from graph */ + +void glp_del_arc(glp_graph *G, glp_arc *a); +/* delete arc from graph */ + +void glp_erase_graph(glp_graph *G, int v_size, int a_size); +/* erase graph content */ + +void glp_delete_graph(glp_graph *G); +/* delete graph */ + +void glp_create_v_index(glp_graph *G); +/* create vertex name index */ + +int glp_find_vertex(glp_graph *G, const char *name); +/* find vertex by its name */ + +void glp_delete_v_index(glp_graph *G); +/* delete vertex name index */ + +int glp_read_graph(glp_graph *G, const char *fname); +/* read graph from plain text file */ + +int glp_write_graph(glp_graph *G, const char *fname); +/* write graph to plain text file */ + +void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, + int a_low, int a_cap, int a_cost); +/* convert minimum cost flow problem to LP */ + +int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, double *sol, int a_x, int v_pi); +/* find minimum-cost flow with out-of-kilter algorithm */ + +int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, int crash, double *sol, int a_x, int a_rc); +/* find minimum-cost flow with Bertsekas-Tseng relaxation method */ + +void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, + int t, int a_cap); +/* convert maximum flow problem to LP */ + +int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, + double *sol, int a_x, int v_cut); +/* find maximal flow with Ford-Fulkerson algorithm */ + +int glp_check_asnprob(glp_graph *G, int v_set); +/* check correctness of assignment problem data */ + +/* assignment problem formulation: */ +#define GLP_ASN_MIN 1 /* perfect matching (minimization) */ +#define GLP_ASN_MAX 2 /* perfect matching (maximization) */ +#define GLP_ASN_MMP 3 /* maximum matching */ + +int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, + int v_set, int a_cost); +/* convert assignment problem to LP */ + +int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, + double *sol, int a_x); +/* solve assignment problem with out-of-kilter algorithm */ + +int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); +/* find bipartite matching of maximum cardinality */ + +double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); +/* solve critical path problem */ + +int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +/* read min-cost flow problem data in DIMACS format */ + +int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, + int a_cost, const char *fname); +/* write min-cost flow problem data in DIMACS format */ + +int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, + const char *fname); +/* read maximum flow problem data in DIMACS format */ + +int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, + const char *fname); +/* write maximum flow problem data in DIMACS format */ + +int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname); +/* read assignment problem data in DIMACS format */ + +int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char + *fname); +/* write assignment problem data in DIMACS format */ + +int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); +/* read graph in DIMACS clique/coloring format */ + +int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); +/* write graph in DIMACS clique/coloring format */ + +int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+15]); +/* Klingman's network problem generator */ + +void glp_netgen_prob(int nprob, int parm[1+15]); +/* Klingman's standard network problem instance */ + +int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, + const int parm[1+14]); +/* grid-like network problem generator */ + +int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, + const int parm[1+5]); +/* Goldfarb's maximum flow problem generator */ + +int glp_weak_comp(glp_graph *G, int v_num); +/* find all weakly connected components of graph */ + +int glp_strong_comp(glp_graph *G, int v_num); +/* find all strongly connected components of graph */ + +int glp_top_sort(glp_graph *G, int v_num); +/* topological sorting of acyclic digraph */ + +int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); +/* find maximum weight clique with exact algorithm */ + +#ifdef __cplusplus +} +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.c new file mode 100644 index 000000000..ab73b2da1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.c @@ -0,0 +1,409 @@ +/* cfg.c (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "cfg.h" +#include "env.h" + +/*********************************************************************** +* cfg_create_graph - create conflict graph +* +* This routine creates the conflict graph, which initially is empty, +* and returns a pointer to the graph descriptor. +* +* The parameter n specifies the number of *all* variables in MIP, for +* which the conflict graph will be built. +* +* The parameter nv_max specifies maximal number of vertices in the +* conflict graph. It should be the double number of binary variables +* in corresponding MIP. */ + +CFG *cfg_create_graph(int n, int nv_max) +{ CFG *G; + xassert(n >= 0); + xassert(0 <= nv_max && nv_max <= n + n); + G = talloc(1, CFG); + G->n = n; + G->pos = talloc(1+n, int); + memset(&G->pos[1], 0, n * sizeof(int)); + G->neg = talloc(1+n, int); + memset(&G->neg[1], 0, n * sizeof(int)); + G->pool = dmp_create_pool(); + G->nv_max = nv_max; + G->nv = 0; + G->ref = talloc(1+nv_max, int); + G->vptr = talloc(1+nv_max, CFGVLE *); + G->cptr = talloc(1+nv_max, CFGCLE *); + return G; +} + +/*********************************************************************** +* cfg_add_clique - add clique to conflict graph +* +* This routine adds a clique to the conflict graph. +* +* The parameter size specifies the clique size, size >= 2. Note that +* any edge can be considered as a clique of size 2. +* +* The array ind specifies vertices constituting the clique in elements +* ind[k], 1 <= k <= size: +* +* ind[k] = +j means a vertex of the conflict graph that corresponds to +* original binary variable x[j], 1 <= j <= n. +* +* ind[k] = -j means a vertex of the conflict graph that corresponds to +* complement of original binary variable x[j], 1 <= j <= n. +* +* Note that if both vertices for x[j] and (1 - x[j]) have appeared in +* the conflict graph, the routine automatically adds an edge incident +* to these vertices. */ + +static void add_edge(CFG *G, int v, int w) +{ /* add clique of size 2 */ + DMP *pool = G->pool; + int nv = G->nv; + CFGVLE **vptr = G->vptr; + CFGVLE *vle; + xassert(1 <= v && v <= nv); + xassert(1 <= w && w <= nv); + xassert(v != w); + vle = dmp_talloc(pool, CFGVLE); + vle->v = w; + vle->next = vptr[v]; + vptr[v] = vle; + vle = dmp_talloc(pool, CFGVLE); + vle->v = v; + vle->next = vptr[w]; + vptr[w] = vle; + return; +} + +void cfg_add_clique(CFG *G, int size, const int ind[]) +{ int n = G->n; + int *pos = G->pos; + int *neg = G->neg; + DMP *pool = G->pool; + int nv_max = G->nv_max; + int *ref = G->ref; + CFGVLE **vptr = G->vptr; + CFGCLE **cptr = G->cptr; + int j, k, v; + xassert(2 <= size && size <= nv_max); + /* add new vertices to the conflict graph */ + for (k = 1; k <= size; k++) + { j = ind[k]; + if (j > 0) + { /* vertex corresponds to x[j] */ + xassert(1 <= j && j <= n); + if (pos[j] == 0) + { /* no such vertex exists; add it */ + v = pos[j] = ++(G->nv); + xassert(v <= nv_max); + ref[v] = j; + vptr[v] = NULL; + cptr[v] = NULL; + if (neg[j] != 0) + { /* now both vertices for x[j] and (1 - x[j]) exist */ + add_edge(G, v, neg[j]); + } + } + } + else + { /* vertex corresponds to (1 - x[j]) */ + j = -j; + xassert(1 <= j && j <= n); + if (neg[j] == 0) + { /* no such vertex exists; add it */ + v = neg[j] = ++(G->nv); + xassert(v <= nv_max); + ref[v] = j; + vptr[v] = NULL; + cptr[v] = NULL; + if (pos[j] != 0) + { /* now both vertices for x[j] and (1 - x[j]) exist */ + add_edge(G, v, pos[j]); + } + } + } + } + /* add specified clique to the conflict graph */ + if (size == 2) + add_edge(G, + ind[1] > 0 ? pos[+ind[1]] : neg[-ind[1]], + ind[2] > 0 ? pos[+ind[2]] : neg[-ind[2]]); + else + { CFGVLE *vp, *vle; + CFGCLE *cle; + /* build list of clique vertices */ + vp = NULL; + for (k = 1; k <= size; k++) + { vle = dmp_talloc(pool, CFGVLE); + vle->v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; + vle->next = vp; + vp = vle; + } + /* attach the clique to all its vertices */ + for (k = 1; k <= size; k++) + { cle = dmp_talloc(pool, CFGCLE); + cle->vptr = vp; + v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; + cle->next = cptr[v]; + cptr[v] = cle; + } + } + return; +} + +/*********************************************************************** +* cfg_get_adjacent - get vertices adjacent to specified vertex +* +* This routine stores numbers of all vertices adjacent to specified +* vertex v of the conflict graph in locations ind[1], ..., ind[len], +* and returns len, 1 <= len <= nv-1, where nv is the total number of +* vertices in the conflict graph. +* +* Note that the conflict graph defined by this routine has neither +* self-loops nor multiple edges. */ + +int cfg_get_adjacent(CFG *G, int v, int ind[]) +{ int nv = G->nv; + int *ref = G->ref; + CFGVLE **vptr = G->vptr; + CFGCLE **cptr = G->cptr; + CFGVLE *vle; + CFGCLE *cle; + int k, w, len; + xassert(1 <= v && v <= nv); + len = 0; + /* walk thru the list of adjacent vertices */ + for (vle = vptr[v]; vle != NULL; vle = vle->next) + { w = vle->v; + xassert(1 <= w && w <= nv); + xassert(w != v); + if (ref[w] > 0) + { ind[++len] = w; + ref[w] = -ref[w]; + } + } + /* walk thru the list of incident cliques */ + for (cle = cptr[v]; cle != NULL; cle = cle->next) + { /* walk thru the list of clique vertices */ + for (vle = cle->vptr; vle != NULL; vle = vle->next) + { w = vle->v; + xassert(1 <= w && w <= nv); + if (w != v && ref[w] > 0) + { ind[++len] = w; + ref[w] = -ref[w]; + } + } + } + xassert(1 <= len && len < nv); + /* unmark vertices included in the resultant adjacency list */ + for (k = 1; k <= len; k++) + { w = ind[k]; + ref[w] = -ref[w]; + } + return len; +} + +/*********************************************************************** +* cfg_expand_clique - expand specified clique to maximal clique +* +* Given some clique in the conflict graph this routine expands it to +* a maximal clique by including in it new vertices. +* +* On entry vertex indices constituting the initial clique should be +* stored in locations c_ind[1], ..., c_ind[c_len], where c_len is the +* initial clique size. On exit the routine stores new vertex indices +* to locations c_ind[c_len+1], ..., c_ind[c_len'], where c_len' is the +* size of the maximal clique found, and returns c_len'. +* +* ALGORITHM +* +* Let G = (V, E) be a graph, C within V be a current clique to be +* expanded, and D within V \ C be a subset of vertices adjacent to all +* vertices from C. On every iteration the routine chooses some vertex +* v in D, includes it into C, and removes from D the vertex v as well +* as all vertices not adjacent to v. Initially C is empty and D = V. +* Iterations repeat until D becomes an empty set. Obviously, the final +* set C is a maximal clique in G. +* +* Now let C0 be an initial clique, and we want C0 to be a subset of +* the final maximal clique C. To provide this condition the routine +* starts constructing C by choosing only such vertices v in D, which +* are in C0, until all vertices from C0 have been included in C. May +* note that if on some iteration C0 \ C is non-empty (i.e. if not all +* vertices from C0 have been included in C), C0 \ C is a subset of D, +* because C0 is a clique. */ + +static int intersection(int d_len, int d_ind[], int d_pos[], int len, + const int ind[]) +{ /* compute intersection D := D inter W, where W is some specified + * set of vertices */ + int k, t, v, new_len; + /* walk thru vertices in W and mark vertices in D */ + for (t = 1; t <= len; t++) + { /* v in W */ + v = ind[t]; + /* determine position of v in D */ + k = d_pos[v]; + if (k != 0) + { /* v in D */ + xassert(d_ind[k] == v); + /* mark v to keep it in D */ + d_ind[k] = -v; + } + } + /* remove all unmarked vertices from D */ + new_len = 0; + for (k = 1; k <= d_len; k++) + { /* v in D */ + v = d_ind[k]; + if (v < 0) + { /* v is marked; keep it */ + v = -v; + new_len++; + d_ind[new_len] = v; + d_pos[v] = new_len; + } + else + { /* v is not marked; remove it */ + d_pos[v] = 0; + } + } + return new_len; +} + +int cfg_expand_clique(CFG *G, int c_len, int c_ind[]) +{ int nv = G->nv; + int d_len, *d_ind, *d_pos, len, *ind; + int k, v; + xassert(0 <= c_len && c_len <= nv); + /* allocate working arrays */ + d_ind = talloc(1+nv, int); + d_pos = talloc(1+nv, int); + ind = talloc(1+nv, int); + /* initialize C := 0, D := V */ + d_len = nv; + for (k = 1; k <= nv; k++) + d_ind[k] = d_pos[k] = k; + /* expand C by vertices of specified initial clique C0 */ + for (k = 1; k <= c_len; k++) + { /* v in C0 */ + v = c_ind[k]; + xassert(1 <= v && v <= nv); + /* since C0 is clique, v should be in D */ + xassert(d_pos[v] != 0); + /* W := set of vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + /* D := D inter W */ + d_len = intersection(d_len, d_ind, d_pos, len, ind); + /* since v not in W, now v should be not in D */ + xassert(d_pos[v] == 0); + } + /* expand C by some other vertices until D is empty */ + while (d_len > 0) + { /* v in D */ + v = d_ind[1]; + xassert(1 <= v && v <= nv); + /* note that v is adjacent to all vertices in C (by design), + * so add v to C */ + c_ind[++c_len] = v; + /* W := set of vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + /* D := D inter W */ + d_len = intersection(d_len, d_ind, d_pos, len, ind); + /* since v not in W, now v should be not in D */ + xassert(d_pos[v] == 0); + } + /* free working arrays */ + tfree(d_ind); + tfree(d_pos); + tfree(ind); + /* bring maximal clique to calling routine */ + return c_len; +} + +/*********************************************************************** +* cfg_check_clique - check clique in conflict graph +* +* This routine checks that vertices of the conflict graph specified +* in locations c_ind[1], ..., c_ind[c_len] constitute a clique. +* +* NOTE: for testing/debugging only. */ + +void cfg_check_clique(CFG *G, int c_len, const int c_ind[]) +{ int nv = G->nv; + int k, kk, v, w, len, *ind; + char *flag; + ind = talloc(1+nv, int); + flag = talloc(1+nv, char); + memset(&flag[1], 0, nv); + /* walk thru clique vertices */ + xassert(c_len >= 0); + for (k = 1; k <= c_len; k++) + { /* get clique vertex v */ + v = c_ind[k]; + xassert(1 <= v && v <= nv); + /* get vertices adjacent to vertex v */ + len = cfg_get_adjacent(G, v, ind); + for (kk = 1; kk <= len; kk++) + { w = ind[kk]; + xassert(1 <= w && w <= nv); + xassert(w != v); + flag[w] = 1; + } + /* check that all clique vertices other than v are adjacent + to v */ + for (kk = 1; kk <= c_len; kk++) + { w = c_ind[kk]; + xassert(1 <= w && w <= nv); + if (w != v) + xassert(flag[w]); + } + /* reset vertex flags */ + for (kk = 1; kk <= len; kk++) + flag[ind[kk]] = 0; + } + tfree(ind); + tfree(flag); + return; +} + +/*********************************************************************** +* cfg_delete_graph - delete conflict graph +* +* This routine deletes the conflict graph by freeing all the memory +* allocated to this program object. */ + +void cfg_delete_graph(CFG *G) +{ tfree(G->pos); + tfree(G->neg); + dmp_delete_pool(G->pool); + tfree(G->ref); + tfree(G->vptr); + tfree(G->cptr); + tfree(G); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.h b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.h new file mode 100644 index 000000000..d478f6c08 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg.h @@ -0,0 +1,138 @@ +/* cfg.h (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef CFG_H +#define CFG_H + +#include "dmp.h" + +/*********************************************************************** +* The structure CFG describes the conflict graph. +* +* Conflict graph is an undirected graph G = (V, E), where V is a set +* of vertices, E <= V x V is a set of edges. Each vertex v in V of the +* conflict graph corresponds to a binary variable z[v], which is +* either an original binary variable x[j] or its complement 1 - x[j]. +* Edge (v,w) in E means that z[v] and z[w] cannot take the value 1 at +* the same time, i.e. it defines an inequality z[v] + z[w] <= 1, which +* is assumed to be valid for original MIP. +* +* Since the conflict graph may be dense, it is stored as an union of +* its cliques rather than explicitly. */ + +#if 0 /* 08/III-2016 */ +typedef struct CFG CFG; +#else +typedef struct glp_cfg CFG; +#endif +typedef struct CFGVLE CFGVLE; +typedef struct CFGCLE CFGCLE; + +#if 0 /* 08/III-2016 */ +struct CFG +#else +struct glp_cfg +#endif +{ /* conflict graph descriptor */ + int n; + /* number of *all* variables (columns) in corresponding MIP */ + int *pos; /* int pos[1+n]; */ + /* pos[0] is not used; + * pos[j] = v, 1 <= j <= n, means that vertex v corresponds to + * original binary variable x[j], and pos[j] = 0 means that the + * conflict graph has no such vertex */ + int *neg; /* int neg[1+n]; */ + /* neg[0] is not used; + * neg[j] = v, 1 <= j <= n, means that vertex v corresponds to + * complement of original binary variable x[j], and neg[j] = 0 + * means that the conflict graph has no such vertex */ + DMP *pool; + /* memory pool to allocate elements of the conflict graph */ + int nv_max; + /* maximal number of vertices in the conflict graph */ + int nv; + /* current number of vertices in the conflict graph */ + int *ref; /* int ref[1+nv_max]; */ + /* ref[v] = j, 1 <= v <= nv, means that vertex v corresponds + * either to original binary variable x[j] or to its complement, + * i.e. either pos[j] = v or neg[j] = v */ + CFGVLE **vptr; /* CFGVLE *vptr[1+nv_max]; */ + /* vptr[v], 1 <= v <= nv, is an initial pointer to the list of + * vertices adjacent to vertex v */ + CFGCLE **cptr; /* CFGCLE *cptr[1+nv_max]; */ + /* cptr[v], 1 <= v <= nv, is an initial pointer to the list of + * cliques that contain vertex v */ +}; + +struct CFGVLE +{ /* vertex list element */ + int v; + /* vertex number, 1 <= v <= nv */ + CFGVLE *next; + /* pointer to next vertex list element */ +}; + +struct CFGCLE +{ /* clique list element */ + CFGVLE *vptr; + /* initial pointer to the list of clique vertices */ + CFGCLE *next; + /* pointer to next clique list element */ +}; + +#define cfg_create_graph _glp_cfg_create_graph +CFG *cfg_create_graph(int n, int nv_max); +/* create conflict graph */ + +#define cfg_add_clique _glp_cfg_add_clique +void cfg_add_clique(CFG *G, int size, const int ind[]); +/* add clique to conflict graph */ + +#define cfg_get_adjacent _glp_cfg_get_adjacent +int cfg_get_adjacent(CFG *G, int v, int ind[]); +/* get vertices adjacent to specified vertex */ + +#define cfg_expand_clique _glp_cfg_expand_clique +int cfg_expand_clique(CFG *G, int c_len, int c_ind[]); +/* expand specified clique to maximal clique */ + +#define cfg_check_clique _glp_cfg_check_clique +void cfg_check_clique(CFG *G, int c_len, const int c_ind[]); +/* check clique in conflict graph */ + +#define cfg_delete_graph _glp_cfg_delete_graph +void cfg_delete_graph(CFG *G); +/* delete conflict graph */ + +#define cfg_build_graph _glp_cfg_build_graph +CFG *cfg_build_graph(void /* glp_prob */ *P); +/* build conflict graph */ + +#define cfg_find_clique _glp_cfg_find_clique +int cfg_find_clique(void /* glp_prob */ *P, CFG *G, int ind[], + double *sum); +/* find maximum weight clique in conflict graph */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg1.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg1.c new file mode 100644 index 000000000..80a2e8346 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg1.c @@ -0,0 +1,703 @@ +/* cfg1.c (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "cfg.h" +#include "env.h" +#include "prob.h" +#include "wclique.h" +#include "wclique1.h" + +/*********************************************************************** +* cfg_build_graph - build conflict graph +* +* This routine builds the conflict graph. It analyzes the specified +* problem object to discover original and implied packing inequalities +* and adds corresponding cliques to the conflict graph. +* +* Packing inequality has the form: +* +* sum z[j] <= 1, (1) +* j in J +* +* where z[j] = x[j] or z[j] = 1 - x[j], x[j] is an original binary +* variable. Every packing inequality (1) is equivalent to a set of +* edge inequalities: +* +* z[i] + z[j] <= 1 for all i, j in J, i != j, (2) +* +* and since every edge inequality (2) defines an edge in the conflict +* graph, corresponding packing inequality (1) defines a clique. +* +* To discover packing inequalities the routine analyzes constraints +* of the specified MIP. To simplify the analysis each constraint is +* analyzed separately. The analysis is performed as follows. +* +* Let some original constraint be the following: +* +* L <= sum a[j] x[j] <= U. (3) +* +* To analyze it the routine analyzes two constraints of "not greater +* than" type: +* +* sum (-a[j]) x[j] <= -L, (4) +* +* sum (+a[j]) x[j] <= +U, (5) +* +* which are relaxations of the original constraint (3). (If, however, +* L = -oo, or U = +oo, corresponding constraint being redundant is not +* analyzed.) +* +* Let a constraint of "not greater than" type be the following: +* +* sum a[j] x[j] + sum a[j] x[j] <= b, (6) +* j in J j in J' +* +* where J is a subset of binary variables, J' is a subset of other +* (continues and non-binary integer) variables. The constraint (6) is +* is relaxed as follows, to eliminate non-binary variables: +* +* sum a[j] x[j] <= b - sum a[j] x[j] <= b', (7) +* j in J j in J' +* +* b' = sup(b - sum a[j] x[j]) = +* j in J' +* +* = b - inf(sum a[j] x[j]) = +* +* = b - sum inf(a[j] x[j]) = (8) +* +* = b - sum a[j] inf(x[j]) - sum a[j] sup(x[j]) = +* a[j]>0 a[j]<0 +* +* = b - sum a[j] l[j] - sum a[j] u[j], +* a[j]>0 a[j]<0 +* +* where l[j] and u[j] are, resp., lower and upper bounds of x[j]. +* +* Then the routine transforms the relaxed constraint containing only +* binary variables: +* +* sum a[j] x[j] <= b (9) +* +* to an equivalent 0-1 knapsack constraint as follows: +* +* sum a[j] x[j] + sum a[j] x[j] <= b ==> +* a[j]>0 a[j]<0 +* +* sum a[j] x[j] + sum a[j] (1 - x[j]) <= b ==> +* a[j]>0 a[j]<0 (10) +* +* sum (+a[j]) x[j] + sum (-a[j]) x[j] <= b + sum (-a[j]) ==> +* a[j]>0 a[j]<0 a[j]<0 +* +* sum a'[j] z[j] <= b', +* +* where a'[j] = |a[j]| > 0, and +* +* ( x[j] if a[j] > 0 +* z[j] = < +* ( 1 - x[j] if a[j] < 0 +* +* is a binary variable, which is either original binary variable x[j] +* or its complement. +* +* Finally, the routine analyzes the resultant 0-1 knapsack inequality: +* +* sum a[j] z[j] <= b, (11) +* j in J +* +* where all a[j] are positive, to discover clique inequalities (1), +* which are valid for (11) and therefore valid for (3). (It is assumed +* that the original MIP has been preprocessed, so it is not checked, +* for example, that b > 0 or that a[j] <= b.) +* +* In principle, to discover any edge inequalities valid for (11) it +* is sufficient to check whether a[i] + a[j] > b for all i, j in J, +* i < j. However, this way requires O(|J|^2) checks, so the routine +* analyses (11) in the following way, which is much more efficient in +* many practical cases. +* +* 1. Let a[p] and a[q] be two minimal coefficients: +* +* a[p] = min a[j], (12) +* +* a[q] = min a[j], j != p, (13) +* +* such that +* +* a[p] + a[q] > b. (14) +* +* This means that a[i] + a[j] > b for any i, j in J, i != j, so +* +* z[i] + z[j] <= 1 (15) +* +* are valid for (11) for any i, j in J, i != j. This case means that +* J define a clique in the conflict graph. +* +* 2. Otherwise, let a[p] and [q] be two maximal coefficients: +* +* a[p] = max a[j], (16) +* +* a[q] = max a[j], j != p, (17) +* +* such that +* +* a[p] + a[q] <= b. (18) +* +* This means that a[i] + a[j] <= b for any i, j in J, i != j, so in +* this case no valid edge inequalities for (11) exist. +* +* 3. Otherwise, let all a[j] be ordered by descending their values: +* +* a[1] >= a[2] >= ... >= a[p-1] >= a[p] >= a[p+1] >= ... (19) +* +* where p is such that +* +* a[p-1] + a[p] > b, (20) +* +* a[p] + a[p+1] <= b. (21) +* +* (May note that due to the former two cases in this case we always +* have 2 <= p <= |J|-1.) +* +* Since a[p] and a[p-1] are two minimal coefficients in the set +* J' = {1, ..., p}, J' define a clique in the conflict graph for the +* same reason as in the first case. Similarly, since a[p] and a[p+1] +* are two maximal coefficients in the set J" = {p, ..., |J|}, no edge +* inequalities exist for all i, j in J" for the same reason as in the +* second case. Thus, to discover other edge inequalities (15) valid +* for (11), the routine checks if a[i] + a[j] > b for all i in J', +* j in J", i != j. */ + +#define is_binary(j) \ + (P->col[j]->kind == GLP_IV && P->col[j]->type == GLP_DB && \ + P->col[j]->lb == 0.0 && P->col[j]->ub == 1.0) +/* check if x[j] is binary variable */ + +struct term { int ind; double val; }; +/* term a[j] * z[j] used to sort a[j]'s */ + +static int CDECL fcmp(const void *e1, const void *e2) +{ /* auxiliary routine called from qsort */ + const struct term *t1 = e1, *t2 = e2; + if (t1->val > t2->val) + return -1; + else if (t1->val < t2->val) + return +1; + else + return 0; +} + +static void analyze_ineq(glp_prob *P, CFG *G, int len, int ind[], + double val[], double rhs, struct term t[]) +{ /* analyze inequality constraint (6) */ + /* P is the original MIP + * G is the conflict graph to be built + * len is the number of terms in the constraint + * ind[1], ..., ind[len] are indices of variables x[j] + * val[1], ..., val[len] are constraint coefficients a[j] + * rhs is the right-hand side b + * t[1+len] is a working array */ + int j, k, kk, p, q, type, new_len; + /* eliminate non-binary variables; see (7) and (8) */ + new_len = 0; + for (k = 1; k <= len; k++) + { /* get index of variable x[j] */ + j = ind[k]; + if (is_binary(j)) + { /* x[j] remains in relaxed constraint */ + new_len++; + ind[new_len] = j; + val[new_len] = val[k]; + } + else if (val[k] > 0.0) + { /* eliminate non-binary x[j] in case a[j] > 0 */ + /* b := b - a[j] * l[j]; see (8) */ + type = P->col[j]->type; + if (type == GLP_FR || type == GLP_UP) + { /* x[j] has no lower bound */ + goto done; + } + rhs -= val[k] * P->col[j]->lb; + } + else /* val[j] < 0.0 */ + { /* eliminate non-binary x[j] in case a[j] < 0 */ + /* b := b - a[j] * u[j]; see (8) */ + type = P->col[j]->type; + if (type == GLP_FR || type == GLP_LO) + { /* x[j] has no upper bound */ + goto done; + } + rhs -= val[k] * P->col[j]->ub; + } + } + len = new_len; + /* now we have the constraint (9) */ + if (len <= 1) + { /* at least two terms are needed */ + goto done; + } + /* make all constraint coefficients positive; see (10) */ + for (k = 1; k <= len; k++) + { if (val[k] < 0.0) + { /* a[j] < 0; substitute x[j] = 1 - x'[j], where x'[j] is + * a complement binary variable */ + ind[k] = -ind[k]; + val[k] = -val[k]; + rhs += val[k]; + } + } + /* now we have 0-1 knapsack inequality (11) */ + /* increase the right-hand side a bit to avoid false checks due + * to rounding errors */ + rhs += 0.001 * (1.0 + fabs(rhs)); + /*** first case ***/ + /* find two minimal coefficients a[p] and a[q] */ + p = 0; + for (k = 1; k <= len; k++) + { if (p == 0 || val[p] > val[k]) + p = k; + } + q = 0; + for (k = 1; k <= len; k++) + { if (k != p && (q == 0 || val[q] > val[k])) + q = k; + } + xassert(p != 0 && q != 0 && p != q); + /* check condition (14) */ + if (val[p] + val[q] > rhs) + { /* all z[j] define a clique in the conflict graph */ + cfg_add_clique(G, len, ind); + goto done; + } + /*** second case ***/ + /* find two maximal coefficients a[p] and a[q] */ + p = 0; + for (k = 1; k <= len; k++) + { if (p == 0 || val[p] < val[k]) + p = k; + } + q = 0; + for (k = 1; k <= len; k++) + { if (k != p && (q == 0 || val[q] < val[k])) + q = k; + } + xassert(p != 0 && q != 0 && p != q); + /* check condition (18) */ + if (val[p] + val[q] <= rhs) + { /* no valid edge inequalities exist */ + goto done; + } + /*** third case ***/ + xassert(len >= 3); + /* sort terms in descending order of coefficient values */ + for (k = 1; k <= len; k++) + { t[k].ind = ind[k]; + t[k].val = val[k]; + } + qsort(&t[1], len, sizeof(struct term), fcmp); + for (k = 1; k <= len; k++) + { ind[k] = t[k].ind; + val[k] = t[k].val; + } + /* now a[1] >= a[2] >= ... >= a[len-1] >= a[len] */ + /* note that a[1] + a[2] > b and a[len-1] + a[len] <= b due two + * the former two cases */ + xassert(val[1] + val[2] > rhs); + xassert(val[len-1] + val[len] <= rhs); + /* find p according to conditions (20) and (21) */ + for (p = 2; p < len; p++) + { if (val[p] + val[p+1] <= rhs) + break; + } + xassert(p < len); + /* z[1], ..., z[p] define a clique in the conflict graph */ + cfg_add_clique(G, p, ind); + /* discover other edge inequalities */ + for (k = 1; k <= p; k++) + { for (kk = p; kk <= len; kk++) + { if (k != kk && val[k] + val[kk] > rhs) + { int iii[1+2]; + iii[1] = ind[k]; + iii[2] = ind[kk]; + cfg_add_clique(G, 2, iii); + } + } + } +done: return; +} + +CFG *cfg_build_graph(void *P_) +{ glp_prob *P = P_; + int m = P->m; + int n = P->n; + CFG *G; + int i, k, type, len, *ind; + double *val; + struct term *t; + /* create the conflict graph (number of its vertices cannot be + * greater than double number of binary variables) */ + G = cfg_create_graph(n, 2 * glp_get_num_bin(P)); + /* allocate working arrays */ + ind = talloc(1+n, int); + val = talloc(1+n, double); + t = talloc(1+n, struct term); + /* analyze constraints to discover edge inequalities */ + for (i = 1; i <= m; i++) + { type = P->row[i]->type; + if (type == GLP_LO || type == GLP_DB || type == GLP_FX) + { /* i-th row has lower bound */ + /* analyze inequality sum (-a[j]) * x[j] <= -lb */ + len = glp_get_mat_row(P, i, ind, val); + for (k = 1; k <= len; k++) + val[k] = -val[k]; + analyze_ineq(P, G, len, ind, val, -P->row[i]->lb, t); + } + if (type == GLP_UP || type == GLP_DB || type == GLP_FX) + { /* i-th row has upper bound */ + /* analyze inequality sum (+a[j]) * x[j] <= +ub */ + len = glp_get_mat_row(P, i, ind, val); + analyze_ineq(P, G, len, ind, val, +P->row[i]->ub, t); + } + } + /* free working arrays */ + tfree(ind); + tfree(val); + tfree(t); + return G; +} + +/*********************************************************************** +* cfg_find_clique - find maximum weight clique in conflict graph +* +* This routine finds a maximum weight clique in the conflict graph +* G = (V, E), where the weight of vertex v in V is the value of +* corresponding binary variable z (which is either an original binary +* variable or its complement) in the optimal solution to LP relaxation +* provided in the problem object. The goal is to find a clique in G, +* whose weight is greater than 1, in which case corresponding packing +* inequality is violated at the optimal point. +* +* On exit the routine stores vertex indices of the conflict graph +* included in the clique found to locations ind[1], ..., ind[len], and +* returns len, which is the clique size. The clique weight is stored +* in location pointed to by the parameter sum. If no clique has been +* found, the routine returns 0. +* +* Since the conflict graph may have a big number of vertices and be +* quite dense, the routine uses an induced subgraph G' = (V', E'), +* which is constructed as follows: +* +* 1. If the weight of some vertex v in V is zero (close to zero), it +* is not included in V'. Obviously, including in a clique +* zero-weight vertices does not change its weight, so if in G there +* exist a clique of a non-zero weight, in G' exists a clique of the +* same weight. This point is extremely important, because dropping +* out zero-weight vertices can be done without retrieving lists of +* adjacent vertices whose size may be very large. +* +* 2. Cumulative weight of vertex v in V is the sum of the weight of v +* and weights of all vertices in V adjacent to v. Obviously, if +* a clique includes a vertex v, the clique weight cannot be greater +* than the cumulative weight of v. Since we are interested only in +* cliques whose weight is greater than 1, vertices of V, whose +* cumulative weight is not greater than 1, are not included in V'. +* +* May note that in many practical cases the size of the induced +* subgraph G' is much less than the size of the original conflict +* graph G due to many binary variables, whose optimal values are zero +* or close to zero. For example, it may happen that |V| = 100,000 and +* |E| = 1e9 while |V'| = 50 and |E'| = 1000. */ + +struct csa +{ /* common storage area */ + glp_prob *P; + /* original MIP */ + CFG *G; + /* original conflict graph G = (V, E), |V| = nv */ + int *ind; /* int ind[1+nv]; */ + /* working array */ + /*--------------------------------------------------------------*/ + /* induced subgraph G' = (V', E') of original conflict graph */ + int nn; + /* number of vertices in V' */ + int *vtoi; /* int vtoi[1+nv]; */ + /* vtoi[v] = i, 1 <= v <= nv, means that vertex v in V is vertex + * i in V'; vtoi[v] = 0 means that vertex v is not included in + * the subgraph */ + int *itov; /* int itov[1+nv]; */ + /* itov[i] = v, 1 <= i <= nn, means that vertex i in V' is vertex + * v in V */ + double *wgt; /* double wgt[1+nv]; */ + /* wgt[i], 1 <= i <= nn, is a weight of vertex i in V', which is + * the value of corresponding binary variable in optimal solution + * to LP relaxation */ +}; + +static void build_subgraph(struct csa *csa) +{ /* build induced subgraph */ + glp_prob *P = csa->P; + int n = P->n; + CFG *G = csa->G; + int *ind = csa->ind; + int *pos = G->pos; + int *neg = G->neg; + int nv = G->nv; + int *ref = G->ref; + int *vtoi = csa->vtoi; + int *itov = csa->itov; + double *wgt = csa->wgt; + int j, k, v, w, nn, len; + double z, sum; + /* initially induced subgraph is empty */ + nn = 0; + /* walk thru vertices of original conflict graph */ + for (v = 1; v <= nv; v++) + { /* determine value of binary variable z[j] that corresponds to + * vertex v */ + j = ref[v]; + xassert(1 <= j && j <= n); + if (pos[j] == v) + { /* z[j] = x[j], where x[j] is original variable */ + z = P->col[j]->prim; + } + else if (neg[j] == v) + { /* z[j] = 1 - x[j], where x[j] is original variable */ + z = 1.0 - P->col[j]->prim; + } + else + xassert(v != v); + /* if z[j] is close to zero, do not include v in the induced + * subgraph */ + if (z < 0.001) + { vtoi[v] = 0; + continue; + } + /* calculate cumulative weight of vertex v */ + sum = z; + /* walk thru all vertices adjacent to v */ + len = cfg_get_adjacent(G, v, ind); + for (k = 1; k <= len; k++) + { /* there is an edge (v,w) in the conflict graph */ + w = ind[k]; + xassert(w != v); + /* add value of z[j] that corresponds to vertex w */ + j = ref[w]; + xassert(1 <= j && j <= n); + if (pos[j] == w) + sum += P->col[j]->prim; + else if (neg[j] == w) + sum += 1.0 - P->col[j]->prim; + else + xassert(w != w); + } + /* cumulative weight of vertex v is an upper bound of weight + * of any clique containing v; so if it not greater than 1, do + * not include v in the induced subgraph */ + if (sum < 1.010) + { vtoi[v] = 0; + continue; + } + /* include vertex v in the induced subgraph */ + nn++; + vtoi[v] = nn; + itov[nn] = v; + wgt[nn] = z; + } + /* induced subgraph has been built */ + csa->nn = nn; + return; +} + +static int sub_adjacent(struct csa *csa, int i, int adj[]) +{ /* retrieve vertices of induced subgraph adjacent to specified + * vertex */ + CFG *G = csa->G; + int nv = G->nv; + int *ind = csa->ind; + int nn = csa->nn; + int *vtoi = csa->vtoi; + int *itov = csa->itov; + int j, k, v, w, len, len1; + /* determine original vertex v corresponding to vertex i */ + xassert(1 <= i && i <= nn); + v = itov[i]; + /* retrieve vertices adjacent to vertex v in original graph */ + len1 = cfg_get_adjacent(G, v, ind); + /* keep only adjacent vertices which are in induced subgraph and + * change their numbers appropriately */ + len = 0; + for (k = 1; k <= len1; k++) + { /* there exists edge (v, w) in original graph */ + w = ind[k]; + xassert(1 <= w && w <= nv && w != v); + j = vtoi[w]; + if (j != 0) + { /* vertex w is vertex j in induced subgraph */ + xassert(1 <= j && j <= nn && j != i); + adj[++len] = j; + } + } + return len; +} + +static int find_clique(struct csa *csa, int c_ind[]) +{ /* find maximum weight clique in induced subgraph with exact + * Ostergard's algorithm */ + int nn = csa->nn; + double *wgt = csa->wgt; + int i, j, k, p, q, t, ne, nb, len, *iwt, *ind; + unsigned char *a; + xassert(nn >= 2); + /* allocate working array */ + ind = talloc(1+nn, int); + /* calculate the number of elements in lower triangle (without + * diagonal) of adjacency matrix of induced subgraph */ + ne = (nn * (nn - 1)) / 2; + /* calculate the number of bytes needed to store lower triangle + * of adjacency matrix */ + nb = (ne + (CHAR_BIT - 1)) / CHAR_BIT; + /* allocate lower triangle of adjacency matrix */ + a = talloc(nb, unsigned char); + /* fill lower triangle of adjacency matrix */ + memset(a, 0, nb); + for (p = 1; p <= nn; p++) + { /* retrieve vertices adjacent to vertex p */ + len = sub_adjacent(csa, p, ind); + for (k = 1; k <= len; k++) + { /* there exists edge (p, q) in induced subgraph */ + q = ind[k]; + xassert(1 <= q && q <= nn && q != p); + /* determine row and column indices of this edge in lower + * triangle of adjacency matrix */ + if (p > q) + i = p, j = q; + else /* p < q */ + i = q, j = p; + /* set bit a[i,j] to 1, i > j */ + t = ((i - 1) * (i - 2)) / 2 + (j - 1); + a[t / CHAR_BIT] |= + (unsigned char)(1 << ((CHAR_BIT - 1) - t % CHAR_BIT)); + } + } + /* scale vertex weights by 1000 and convert them to integers as + * required by Ostergard's algorithm */ + iwt = ind; + for (i = 1; i <= nn; i++) + { /* it is assumed that 0 <= wgt[i] <= 1 */ + t = (int)(1000.0 * wgt[i] + 0.5); + if (t < 0) + t = 0; + else if (t > 1000) + t = 1000; + iwt[i] = t; + } + /* find maximum weight clique */ + len = wclique(nn, iwt, a, c_ind); + /* free working arrays */ + tfree(ind); + tfree(a); + /* return clique size to calling routine */ + return len; +} + +static int func(void *info, int i, int ind[]) +{ /* auxiliary routine used by routine find_clique1 */ + struct csa *csa = info; + xassert(1 <= i && i <= csa->nn); + return sub_adjacent(csa, i, ind); +} + +static int find_clique1(struct csa *csa, int c_ind[]) +{ /* find maximum weight clique in induced subgraph with greedy + * heuristic */ + int nn = csa->nn; + double *wgt = csa->wgt; + int len; + xassert(nn >= 2); + len = wclique1(nn, wgt, func, csa, c_ind); + /* return clique size to calling routine */ + return len; +} + +int cfg_find_clique(void *P, CFG *G, int ind[], double *sum_) +{ int nv = G->nv; + struct csa csa; + int i, k, len; + double sum; + /* initialize common storage area */ + csa.P = P; + csa.G = G; + csa.ind = talloc(1+nv, int); + csa.nn = -1; + csa.vtoi = talloc(1+nv, int); + csa.itov = talloc(1+nv, int); + csa.wgt = talloc(1+nv, double); + /* build induced subgraph */ + build_subgraph(&csa); +#ifdef GLP_DEBUG + xprintf("nn = %d\n", csa.nn); +#endif + /* if subgraph has less than two vertices, do nothing */ + if (csa.nn < 2) + { len = 0; + sum = 0.0; + goto skip; + } + /* find maximum weight clique in induced subgraph */ +#if 1 /* FIXME */ + if (csa.nn <= 50) +#endif + { /* induced subgraph is small; use exact algorithm */ + len = find_clique(&csa, ind); + } + else + { /* induced subgraph is large; use greedy heuristic */ + len = find_clique1(&csa, ind); + } + /* do not report clique, if it has less than two vertices */ + if (len < 2) + { len = 0; + sum = 0.0; + goto skip; + } + /* convert indices of clique vertices from induced subgraph to + * original conflict graph and compute clique weight */ + sum = 0.0; + for (k = 1; k <= len; k++) + { i = ind[k]; + xassert(1 <= i && i <= csa.nn); + sum += csa.wgt[i]; + ind[k] = csa.itov[i]; + } +skip: /* free working arrays */ + tfree(csa.ind); + tfree(csa.vtoi); + tfree(csa.itov); + tfree(csa.wgt); + /* return to calling routine */ + *sum_ = sum; + return len; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg2.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg2.c new file mode 100644 index 000000000..85c0705ee --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/cfg2.c @@ -0,0 +1,91 @@ +/* cfg2.c (conflict graph) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "cfg.h" +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_cfg_init - create and initialize conflict graph +* +* SYNOPSIS +* +* glp_cfg *glp_cfg_init(glp_prob *P); +* +* DESCRIPTION +* +* This routine creates and initializes the conflict graph for the +* specified problem object. +* +* RETURNS +* +* The routine returns a pointer to the conflict graph descriptor. +* However, if the conflict graph is empty (no conflicts have been +* found), the routine returns NULL. */ + +glp_cfg *glp_cfg_init(glp_prob *P) +{ glp_cfg *G; + int j, n1, n2; + xprintf("Constructing conflict graph...\n"); + G = cfg_build_graph(P); + n1 = n2 = 0; + for (j = 1; j <= P->n; j++) + { if (G->pos[j]) + n1 ++; + if (G->neg[j]) + n2++; + } + if (n1 == 0 && n2 == 0) + { xprintf("No conflicts found\n"); + cfg_delete_graph(G); + G = NULL; + } + else + xprintf("Conflict graph has %d + %d = %d vertices\n", + n1, n2, G->nv); + return G; +} + +/*********************************************************************** +* NAME +* +* glp_cfg_free - delete conflict graph descriptor +* +* SYNOPSIS +* +* void glp_cfg_free(glp_cfg *G); +* +* DESCRIPTION +* +* This routine deletes the conflict graph descriptor and frees all the +* memory allocated to it. */ + +void glp_cfg_free(glp_cfg *G) +{ xassert(G != NULL); + cfg_delete_graph(G); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/clqcut.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/clqcut.c new file mode 100644 index 000000000..d3db5b395 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/clqcut.c @@ -0,0 +1,134 @@ +/* clqcut.c (clique cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "cfg.h" +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_clq_cut - generate clique cut from conflict graph +* +* SYNOPSIS +* +* int glp_clq_cut(glp_prob *P, glp_cfg *G, int ind[], double val[]); +* +* DESCRIPTION +* +* This routine attempts to generate a clique cut. +* +* The cut generated by the routine is the following inequality: +* +* sum a[j] * x[j] <= b, +* +* which is expected to be violated at the current basic solution. +* +* If the cut has been successfully generated, the routine stores its +* non-zero coefficients a[j] and corresponding column indices j in the +* array locations val[1], ..., val[len] and ind[1], ..., ind[len], +* where 1 <= len <= n is the number of non-zero coefficients. The +* right-hand side value b is stored in val[0], and ind[0] is set to 0. +* +* RETURNS +* +* If the cut has been successfully generated, the routine returns +* len, the number of non-zero coefficients in the cut, 1 <= len <= n. +* Otherwise, the routine returns a non-positive value. */ + +int glp_clq_cut(glp_prob *P, glp_cfg *G, int ind[], double val[]) +{ int n = P->n; + int *pos = G->pos; + int *neg = G->neg; + int nv = G->nv; + int *ref = G->ref; + int j, k, v, len; + double rhs, sum; + xassert(G->n == n); + /* find maximum weight clique in conflict graph */ + len = cfg_find_clique(P, G, ind, &sum); +#ifdef GLP_DEBUG + xprintf("len = %d; sum = %g\n", len, sum); + cfg_check_clique(G, len, ind); +#endif + /* check if clique inequality is violated */ + if (sum < 1.07) + return 0; + /* expand clique to maximal one */ + len = cfg_expand_clique(G, len, ind); +#ifdef GLP_DEBUG + xprintf("maximal clique size = %d\n", len); + cfg_check_clique(G, len, ind); +#endif + /* construct clique cut (fixed binary variables are removed, so + this cut is only locally valid) */ + rhs = 1.0; + for (j = 1; j <= n; j++) + val[j] = 0.0; + for (k = 1; k <= len; k++) + { /* v is clique vertex */ + v = ind[k]; + xassert(1 <= v && v <= nv); + /* j is number of corresponding binary variable */ + j = ref[v]; + xassert(1 <= j && j <= n); + if (pos[j] == v) + { /* v corresponds to x[j] */ + if (P->col[j]->type == GLP_FX) + { /* x[j] is fixed */ + rhs -= P->col[j]->prim; + } + else + { /* x[j] is not fixed */ + val[j] += 1.0; + } + } + else if (neg[j] == v) + { /* v corresponds to (1 - x[j]) */ + if (P->col[j]->type == GLP_FX) + { /* x[j] is fixed */ + rhs -= (1.0 - P->col[j]->prim); + } + else + { /* x[j] is not fixed */ + val[j] -= 1.0; + rhs -= 1.0; + } + } + else + xassert(v != v); + } + /* convert cut inequality to sparse format */ + len = 0; + for (j = 1; j <= n; j++) + { if (val[j] != 0.0) + { len++; + ind[len] = j; + val[len] = val[j]; + } + } + ind[0] = 0, val[0] = rhs; + return len; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/covgen.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/covgen.c new file mode 100644 index 000000000..427c3aa81 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/covgen.c @@ -0,0 +1,885 @@ +/* covgen.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "fvs.h" +#include "ks.h" +#include "prob.h" + +struct glp_cov +{ /* cover cut generator working area */ + int n; + /* number of columns (variables) */ + glp_prob *set; + /* set of globally valid 0-1 knapsack inequalities chosen from + * the root problem; each inequality is either original row or + * its relaxation (surrogate 0-1 knapsack) which is constructed + * by substitution of lower/upper single/variable bounds for + * continuous and general integer (non-binary) variables */ +}; + +struct bnd +{ /* simple or variable bound */ + /* if z = 0, it is a simple bound x >= or <= b; if b = -DBL_MAX + * (b = +DBL_MAX), x has no lower (upper) bound; otherwise, if + * z != 0, it is a variable bound x >= or <= a * z + b */ + int z; + /* number of binary variable or 0 */ + double a, b; + /* bound parameters */ +}; + +struct csa +{ /* common storage area */ + glp_prob *P; + /* original (root) MIP */ + struct bnd *l; /* struct bnd l[1+P->n]; */ + /* lower simple/variable bounds of variables */ + struct bnd *u; /* struct bnd u[1+P->n]; */ + /* upper simple/variable bounds of variables */ + glp_prob *set; + /* see struct glp_cov above */ +}; + +/*********************************************************************** +* init_bounds - initialize bounds of variables with simple bounds +* +* This routine initializes lower and upper bounds of all variables +* with simple bounds specified in the original mip. */ + +static void init_bounds(struct csa *csa) +{ glp_prob *P = csa->P; + struct bnd *l = csa->l, *u = csa->u; + int j; + for (j = 1; j <= P->n; j++) + { l[j].z = u[j].z = 0; + l[j].a = u[j].a = 0; + l[j].b = glp_get_col_lb(P, j); + u[j].b = glp_get_col_ub(P, j); + } + return; +} + +/*********************************************************************** +* check_vb - check variable bound +* +* This routine checks if the specified i-th row has the form +* +* a1 * x + a2 * z >= or <= rhs, (1) +* +* where x is a non-fixed continuous or general integer variable, and +* z is a binary variable. If it is, the routine converts the row to +* the following variable lower/upper bound (VLB/VUB) of x: +* +* x >= or <= a * z + b, (2) +* +* where a = - a2 / a1, b = rhs / a1. Note that the inequality type is +* changed to opposite one when a1 < 0. +* +* If the row is identified as a variable bound, the routine returns +* GLP_LO for VLB or GLP_UP for VUB and provides the reference numbers +* of variables x and z and values of a and b. Otherwise, the routine +* returns zero. */ + +static int check_vb(struct csa *csa, int i, int *x, int *z, double *a, + double *b) +{ glp_prob *P = csa->P; + GLPROW *row; + GLPAIJ *a1, *a2; + int type; + double rhs; + xassert(1 <= i && i <= P->m); + row = P->row[i]; + /* check row type */ + switch (row->type) + { case GLP_LO: + case GLP_UP: + break; + default: + return 0; + } + /* take first term of the row */ + a1 = row->ptr; + if (a1 == NULL) + return 0; + /* take second term of the row */ + a2 = a1->r_next; + if (a2 == NULL) + return 0; + /* there should be exactly two terms in the row */ + if (a2->r_next != NULL) + return 0; + /* if first term is a binary variable, swap the terms */ + if (glp_get_col_kind(P, a1->col->j) == GLP_BV) + { GLPAIJ *a; + a = a1, a1 = a2, a2 = a; + } + /* now first term should be a non-fixed continuous or general + * integer variable */ + if (a1->col->type == GLP_FX) + return 0; + if (glp_get_col_kind(P, a1->col->j) == GLP_BV) + return 0; + /* and second term should be a binary variable */ + if (glp_get_col_kind(P, a2->col->j) != GLP_BV) + return 0; + /* VLB/VUB row has been identified */ + switch (row->type) + { case GLP_LO: + type = a1->val > 0 ? GLP_LO : GLP_UP; + rhs = row->lb; + break; + case GLP_UP: + type = a1->val > 0 ? GLP_UP : GLP_LO; + rhs = row->ub; + break; + default: + xassert(type != type); + } + *x = a1->col->j; + *z = a2->col->j; + *a = - a2->val / a1->val; + *b = rhs / a1->val; + return type; +} + +/*********************************************************************** +* set_vb - set variable bound +* +* This routine sets lower or upper variable bound specified as +* +* x >= a * z + b (type = GLP_LO) +* +* x <= a * z + b (type = GLP_UP) */ + +static void set_vb(struct csa *csa, int type, int x, int z, double a, + double b) +{ glp_prob *P = csa->P; + struct bnd *l = csa->l, *u = csa->u; + xassert(glp_get_col_type(P, x) != GLP_FX); + xassert(glp_get_col_kind(P, x) != GLP_BV); + xassert(glp_get_col_kind(P, z) == GLP_BV); + xassert(a != 0); + switch (type) + { case GLP_LO: + /* FIXME: check existing simple lower bound? */ + l[x].z = z, l[x].a = a, l[x].b = b; + break; + case GLP_UP: + /* FIXME: check existing simple upper bound? */ + u[x].z = z, u[x].a = a, u[x].b = b; + break; + default: + xassert(type != type); + } + return; +} + +/*********************************************************************** +* obtain_vbs - obtain and set variable bounds +* +* This routine walks thru all rows of the original mip, identifies +* rows specifying variable lower/upper bounds, and sets these bounds +* for corresponding (non-binary) variables. */ + +static void obtain_vbs(struct csa *csa) +{ glp_prob *P = csa->P; + int i, x, z, type, save; + double a, b; + for (i = 1; i <= P->m; i++) + { switch (P->row[i]->type) + { case GLP_FR: + break; + case GLP_LO: + case GLP_UP: + type = check_vb(csa, i, &x, &z, &a, &b); + if (type) + set_vb(csa, type, x, z, a, b); + break; + case GLP_DB: + case GLP_FX: + /* double-side inequality l <= ... <= u and equality + * ... = l = u are considered as two single inequalities + * ... >= l and ... <= u */ + save = P->row[i]->type; + P->row[i]->type = GLP_LO; + type = check_vb(csa, i, &x, &z, &a, &b); + if (type) + set_vb(csa, type, x, z, a, b); + P->row[i]->type = GLP_UP; + type = check_vb(csa, i, &x, &z, &a, &b); + if (type) + set_vb(csa, type, x, z, a, b); + P->row[i]->type = save; + break; + default: + xassert(P != P); + } + } + return; +} + +/*********************************************************************** +* add_term - add term to sparse vector +* +* This routine computes the following linear combination: +* +* v := v + a * e[j], +* +* where v is a sparse vector in full storage format, a is a non-zero +* scalar, e[j] is j-th column of unity matrix. */ + +static void add_term(FVS *v, int j, double a) +{ xassert(1 <= j && j <= v->n); + xassert(a != 0); + if (v->vec[j] == 0) + { /* create j-th component */ + v->nnz++; + xassert(v->nnz <= v->n); + v->ind[v->nnz] = j; + } + /* perform addition */ + v->vec[j] += a; + if (fabs(v->vec[j]) < 1e-9 * (1 + fabs(a))) + { /* remove j-th component */ + v->vec[j] = DBL_MIN; + } + return; +} + +/*********************************************************************** +* build_ks - build "0-1 knapsack" inequality +* +* Given an inequality of "not greater" type: +* +* sum{j in 1..n} a[j]*x[j] <= b, (1) +* +* this routine attempts to transform it to equivalent or relaxed "0-1 +* knapsack" inequality that contains only binary variables. +* +* If x[j] is a binary variable, the term a[j]*x[j] is not changed. +* Otherwise, if x[j] is a continuous or integer non-binary variable, +* it is replaced by its lower (if a[j] > 0) or upper (if a[j] < 0) +* single or variable bound. In the latter case, if x[j] is a non-fixed +* variable, this results in a relaxation of original inequality known +* as "surrogate knapsack". Thus, if the specified inequality is valid +* for the original mip, the resulting inequality is also valid. +* +* Note that in both source and resulting inequalities coefficients +* a[j] can have any sign. +* +* On entry to the routine the source inequality is specified by the +* parameters n, ind (contains original numbers of x[j]), a, and b. The +* parameter v is a working sparse vector whose components are assumed +* to be zero. +* +* On exit the routine stores the resulting "0-1 knapsack" inequality +* in the parameters ind, a, and b, and returns n which is the number +* of terms in the resulting inequality. Zero content of the vector v +* is restored before exit. +* +* If the resulting inequality cannot be constructed due to missing +* lower/upper bounds of some variable, the routine returns a negative +* value. */ + +static int build_ks(struct csa *csa, int n, int ind[], double a[], + double *b, FVS *v) +{ glp_prob *P = csa->P; + struct bnd *l = csa->l, *u = csa->u; + int j, k; + /* check that v = 0 */ +#ifdef GLP_DEBUG + fvs_check_vec(v); +#endif + xassert(v->nnz == 0); + /* walk thru terms of original inequality */ + for (j = 1; j <= n; j++) + { /* process term a[j]*x[j] */ + k = ind[j]; /* original number of x[j] in mip */ + if (glp_get_col_kind(P, k) == GLP_BV) + { /* x[j] is a binary variable */ + /* include its term into resulting inequality */ + add_term(v, k, a[j]); + } + else if (a[j] > 0) + { /* substitute x[j] by its lower bound */ + if (l[k].b == -DBL_MAX) + { /* x[j] has no lower bound */ + n = -1; + goto skip; + } + else if (l[k].z == 0) + { /* x[j] has simple lower bound */ + *b -= a[j] * l[k].b; + } + else + { /* x[j] has variable lower bound (a * z + b) */ + add_term(v, l[k].z, a[j] * l[k].a); + *b -= a[j] * l[k].b; + } + } + else /* a[j] < 0 */ + { /* substitute x[j] by its upper bound */ + if (u[k].b == +DBL_MAX) + { /* x[j] has no upper bound */ + n = -1; + goto skip; + } + else if (u[k].z == 0) + { /* x[j] has simple upper bound */ + *b -= a[j] * u[k].b; + } + else + { /* x[j] has variable upper bound (a * z + b) */ + add_term(v, u[k].z, a[j] * u[k].a); + *b -= a[j] * u[k].b; + } + } + } + /* replace tiny coefficients by exact zeros (see add_term) */ + fvs_adjust_vec(v, 2 * DBL_MIN); + /* copy terms of resulting inequality */ + xassert(v->nnz <= n); + n = v->nnz; + for (j = 1; j <= n; j++) + { ind[j] = v->ind[j]; + a[j] = v->vec[ind[j]]; + } +skip: /* restore zero content of v */ + fvs_clear_vec(v); + return n; +} + +/*********************************************************************** +* can_be_active - check if inequality can be active +* +* This routine checks if the specified "0-1 knapsack" inequality +* +* sum{j in 1..n} a[j]*x[j] <= b +* +* can be active. If so, the routine returns true, otherwise false. */ + +static int can_be_active(int n, const double a[], double b) +{ int j; + double s; + s = 0; + for (j = 1; j <= n; j++) + { if (a[j] > 0) + s += a[j]; + } + return s > b + .001 * (1 + fabs(b)); +} + +/*********************************************************************** +* is_sos_ineq - check if inequality is packing (SOS) constraint +* +* This routine checks if the specified "0-1 knapsack" inequality +* +* sum{j in 1..n} a[j]*x[j] <= b (1) +* +* is equivalent to packing inequality (Padberg calls such inequalities +* special ordered set or SOS constraints) +* +* sum{j in J'} x[j] - sum{j in J"} x[j] <= 1 - |J"|. (2) +* +* If so, the routine returns true, otherwise false. +* +* Note that if X is a set of feasible binary points satisfying to (2), +* its convex hull conv(X) equals to the set of feasible points of LP +* relaxation of (2), which is a n-dimensional simplex, so inequalities +* (2) are useless for generating cover cuts (due to unimodularity). +* +* ALGORITHM +* +* First, we make all a[j] positive by complementing x[j] = 1 - x'[j] +* in (1). This is performed implicitly (i.e. actually the array a is +* not changed), but b is replaced by b - sum{j : a[j] < 0}. +* +* Then we find two smallest coefficients a[p] = min{j in 1..n} a[j] +* and a[q] = min{j in 1..n : j != p} a[j]. It is obvious that if +* a[p] + a[q] > b, then a[i] + a[j] > b for all i != j, from which it +* follows that x[i] + x[j] <= 1 for all i != j. But the latter means +* that the original inequality (with all a[j] > 0) is equivalent to +* packing inequality +* +* sum{j in 1..n} x[j] <= 1. (3) +* +* Returning to original (uncomplemented) variables x'[j] = 1 - x[j] +* we have that the original inequality is equivalent to (2), where +* J' = {j : a[j] > 0} and J" = {j : a[j] < 0}. */ + +static int is_sos_ineq(int n, const double a[], double b) +{ int j, p, q; + xassert(n >= 2); + /* compute b := b - sum{j : a[j] < 0} */ + for (j = 1; j <= n; j++) + { if (a[j] < 0) + b -= a[j]; + } + /* find a[p] = min{j in 1..n} a[j] */ + p = 1; + for (j = 2; j <= n; j++) + { if (fabs(a[p]) > fabs(a[j])) + p = j; + } + /* find a[q] = min{j in 1..n : j != p} a[j] */ + q = 0; + for (j = 1; j <= n; j++) + { if (j != p) + { if (q == 0 || fabs(a[q]) > fabs(a[j])) + q = j; + } + } + xassert(q != 0); + /* check condition a[p] + a[q] > b */ + return fabs(a[p]) + fabs(a[q]) > b + .001 * (1 + fabs(b)); +} + +/*********************************************************************** +* process_ineq - basic inequality processing +* +* This routine performs basic processing of an inequality of "not +* greater" type +* +* sum{j in 1..n} a[j]*x[j] <= b +* +* specified by the parameters, n, ind, a, and b. +* +* If the inequality can be transformed to "0-1 knapsack" ineqiality +* suitable for generating cover cuts, the routine adds it to the set +* of "0-1 knapsack" inequalities. +* +* Note that the arrays ind and a are not saved on exit. */ + +static void process_ineq(struct csa *csa, int n, int ind[], double a[], + double b, FVS *v) +{ int i; + /* attempt to transform the specified inequality to equivalent or + * relaxed "0-1 knapsack" inequality */ + n = build_ks(csa, n, ind, a, &b, v); + if (n <= 1) + { /* uninteresting inequality (in principle, such inequalities + * should be removed by the preprocessor) */ + goto done; + } + if (!can_be_active(n, a, b)) + { /* inequality is redundant (i.e. cannot be active) */ + goto done; + } + if (is_sos_ineq(n, a, b)) + { /* packing (SOS) inequality is useless for generating cover + * cuts; currently such inequalities are just ignored */ + goto done; + } + /* add resulting "0-1 knapsack" inequality to the set */ + i = glp_add_rows(csa->set, 1); + glp_set_mat_row(csa->set, i, n, ind, a); + glp_set_row_bnds(csa->set, i, GLP_UP, b, b); +done: return; +} + +/**********************************************************************/ + +glp_cov *glp_cov_init(glp_prob *P) +{ /* create and initialize cover cut generator */ + glp_cov *cov; + struct csa csa; + int i, k, len, *ind; + double rhs, *val; + FVS fvs; + csa.P = P; + csa.l = talloc(1+P->n, struct bnd); + csa.u = talloc(1+P->n, struct bnd); + csa.set = glp_create_prob(); + glp_add_cols(csa.set, P->n); + /* initialize bounds of variables with simple bounds */ + init_bounds(&csa); + /* obtain and set variable bounds */ + obtain_vbs(&csa); + /* allocate working arrays */ + ind = talloc(1+P->n, int); + val = talloc(1+P->n, double); + fvs_alloc_vec(&fvs, P->n); + /* process all rows of the root mip */ + for (i = 1; i <= P->m; i++) + { switch (P->row[i]->type) + { case GLP_FR: + break; + case GLP_LO: + /* obtain row of ">=" type */ + len = glp_get_mat_row(P, i, ind, val); + rhs = P->row[i]->lb; + /* transforms it to row of "<=" type */ + for (k = 1; k <= len; k++) + val[k] = - val[k]; + rhs = - rhs; + /* process the row */ + process_ineq(&csa, len, ind, val, rhs, &fvs); + break; + case GLP_UP: + /* obtain row of "<=" type */ + len = glp_get_mat_row(P, i, ind, val); + rhs = P->row[i]->ub; + /* and process it */ + process_ineq(&csa, len, ind, val, rhs, &fvs); + break; + case GLP_DB: + case GLP_FX: + /* double-sided inequalitiy and equality constraints are + * processed as two separate inequalities */ + /* obtain row as if it were of ">=" type */ + len = glp_get_mat_row(P, i, ind, val); + rhs = P->row[i]->lb; + /* transforms it to row of "<=" type */ + for (k = 1; k <= len; k++) + val[k] = - val[k]; + rhs = - rhs; + /* and process it */ + process_ineq(&csa, len, ind, val, rhs, &fvs); + /* obtain the same row as if it were of "<=" type */ + len = glp_get_mat_row(P, i, ind, val); + rhs = P->row[i]->ub; + /* and process it */ + process_ineq(&csa, len, ind, val, rhs, &fvs); + break; + default: + xassert(P != P); + } + } + /* free working arrays */ + tfree(ind); + tfree(val); + fvs_check_vec(&fvs); + fvs_free_vec(&fvs); + /* the set of "0-1 knapsack" inequalities has been built */ + if (csa.set->m == 0) + { /* the set is empty */ + xprintf("No 0-1 knapsack inequalities detected\n"); + cov = NULL; + glp_delete_prob(csa.set); + } + else + { /* create the cover cut generator working area */ + xprintf("Number of 0-1 knapsack inequalities = %d\n", + csa.set->m); + cov = talloc(1, glp_cov); + cov->n = P->n; + cov->set = csa.set; +#if 0 + glp_write_lp(cov->set, 0, "set.lp"); +#endif + } + tfree(csa.l); + tfree(csa.u); + return cov; +} + +/*********************************************************************** +* solve_ks - solve 0-1 knapsack problem +* +* This routine finds (sub)optimal solution to 0-1 knapsack problem: +* +* maximize z = sum{j in 1..n} c[j]x[j] (1) +* +* s.t. sum{j in 1..n} a[j]x[j] <= b (2) +* +* x[j] in {0, 1} for all j in 1..n (3) +* +* It is assumed that the instance is non-normalized, i.e. parameters +* a, b, and c may have any sign. +* +* On exit the routine stores the (sub)optimal point found in locations +* x[1], ..., x[n] and returns the optimal objective value. However, if +* the instance is infeasible, the routine returns INT_MIN. */ + +static int solve_ks(int n, const int a[], int b, const int c[], + char x[]) +{ int z; + /* surprisingly, even for some small instances (n = 50-100) + * MT1 routine takes too much time, so it is used only for tiny + * instances */ + if (n <= 16) +#if 0 + z = ks_enum(n, a, b, c, x); +#else + z = ks_mt1(n, a, b, c, x); +#endif + else + z = ks_greedy(n, a, b, c, x); + return z; +} + +/*********************************************************************** +* simple_cover - find simple cover cut +* +* Given a 0-1 knapsack inequality (which may be globally as well as +* locally valid) +* +* sum{j in 1..n} a[j]x[j] <= b, (1) +* +* where all x[j] are binary variables and all a[j] are positive, and +* a fractional point x~{j in 1..n}, which is feasible to LP relaxation +* of (1), this routine attempts to find a simple cover inequality +* +* sum{j in C} (1 - x[j]) >= 1, (2) +* +* which is valid for (1) and violated at x~. +* +* Actually, the routine finds a cover C, i.e. a subset of {1, ..., n} +* such that +* +* sum{j in C} a[j] > b, (3) +* +* and which minimizes the left-hand side of (2) at x~ +* +* zeta = sum{j in C} (1 - x~[j]). (4) +* +* On exit the routine stores the characteritic vector z{j in 1..n} +* of the cover found (i.e. z[j] = 1 means j in C, and z[j] = 0 means +* j not in C), and returns corresponding minimal value of zeta (4). +* However, if no cover is found, the routine returns DBL_MAX. +* +* ALGORITHM +* +* The separation problem (3)-(4) is converted to 0-1 knapsack problem +* as follows. +* +* First, note that the constraint (3) is equivalent to +* +* sum{j in 1..n} a[j]z[j] >= b + eps, (5) +* +* where eps > 0 is a sufficiently small number (in case of integral +* a and b we may take eps = 1). Multiplying both sides of (5) by (-1) +* gives +* +* sum{j in 1..n} (-a[j])z[j] <= - b - eps. (6) +* +* To make all coefficients in (6) positive, z[j] is complemented by +* substitution z[j] = 1 - z'[j] that finally gives +* +* sum{j in 1..n} a[j]z'[j] <= sum{j in 1..n} a[j] - b - eps. (7) +* +* Minimization of zeta (4) is equivalent to maximization of +* +* -zeta = sum{j in 1..n} (x~[j] - 1)z[j]. (8) +* +* Substitution z[j] = 1 - z'[j] gives +* +* -zeta = sum{j in 1..n} (1 - x~[j])z'[j] - zeta0, (9) +* +* where zeta0 = sum{j in 1..n} (1 - x~[j]) is a constant term. +* +* Thus, the 0-1 knapsack problem to be solved is the following: +* +* maximize +* +* -zeta = sum{j in 1..n} (1 - x~[j])z'[j] - zeta0 (10) +* +* subject to +* +* sum{j in 1..n} a[j]z'[j] <= sum{j in 1..n} a[j] - b - eps (11) +* +* z'[j] in {0,1} for all j = 1,...,n (12) +* +* (The constant term zeta0 doesn't affect the solution, so it can be +* dropped.) */ + +static double simple_cover(int n, const double a[], double b, const + double x[], char z[]) +{ int j, *aa, bb, *cc; + double max_aj, min_aj, s, eps; + xassert(n >= 3); + /* allocate working arrays */ + aa = talloc(1+n, int); + cc = talloc(1+n, int); + /* compute max{j in 1..n} a[j] and min{j in 1..n} a[j] */ + max_aj = 0, min_aj = DBL_MAX; + for (j = 1; j <= n; j++) + { xassert(a[j] > 0); + if (max_aj < a[j]) + max_aj = a[j]; + if (min_aj > a[j]) + min_aj = a[j]; + } + /* scale and round constraint parameters to make them integral; + * note that we make the resulting inequality stronger than (11), + * so a[j]'s are rounded up while rhs is rounded down */ + s = 0; + for (j = 1; j <= n; j++) + { s += a[j]; + aa[j] = ceil(a[j] / max_aj * 1000); + } + bb = floor((s - b) / max_aj * 1000) - 1; + /* scale and round obj. coefficients to make them integral; + * again we make the objective function stronger than (10), so + * the coefficients are rounded down */ + for (j = 1; j <= n; j++) + { xassert(0 <= x[j] && x[j] <= 1); + cc[j] = floor((1 - x[j]) * 1000); + } + /* solve separation problem */ + if (solve_ks(n, aa, bb, cc, z) == INT_MIN) + { /* no cover exists */ + s = DBL_MAX; + goto skip; + } + /* determine z[j] = 1 - z'[j] */ + for (j = 1; j <= n; j++) + { xassert(z[j] == 0 || z[j] == 1); + z[j] ^= 1; + } + /* check condition (11) for original (non-scaled) parameters */ + s = 0; + for (j = 1; j <= n; j++) + { if (z[j]) + s += a[j]; + } + eps = 0.01 * (min_aj >= 1 ? min_aj : 1); + if (!(s >= b + eps)) + { /* no cover found within a precision req'd */ + s = DBL_MAX; + goto skip; + } + /* compute corresponding zeta (4) for cover found */ + s = 0; + for (j = 1; j <= n; j++) + { if (z[j]) + s += 1 - x[j]; + } +skip: /* free working arrays */ + tfree(aa); + tfree(cc); + return s; +} + +/**********************************************************************/ + +void glp_cov_gen1(glp_prob *P, glp_cov *cov, glp_prob *pool) +{ /* generate locally valid simple cover cuts */ + int i, k, len, new_len, *ind; + double *val, rhs, *x, zeta; + char *z; + xassert(P->n == cov->n && P->n == cov->set->n); + xassert(glp_get_status(P) == GLP_OPT); + /* allocate working arrays */ + ind = talloc(1+P->n, int); + val = talloc(1+P->n, double); + x = talloc(1+P->n, double); + z = talloc(1+P->n, char); + /* walk thru 0-1 knapsack inequalities */ + for (i = 1; i <= cov->set->m; i++) + { /* retrieve 0-1 knapsack inequality */ + len = glp_get_mat_row(cov->set, i, ind, val); + rhs = glp_get_row_ub(cov->set, i); + xassert(rhs != +DBL_MAX); + /* FIXME: skip, if slack is too large? */ + /* substitute and eliminate binary variables which have been + * fixed in the current subproblem (this makes the inequality + * only locally valid) */ + new_len = 0; + for (k = 1; k <= len; k++) + { if (glp_get_col_type(P, ind[k]) == GLP_FX) + rhs -= val[k] * glp_get_col_prim(P, ind[k]); + else + { new_len++; + ind[new_len] = ind[k]; + val[new_len] = val[k]; + } + } + len = new_len; + /* we need at least 3 binary variables in the inequality */ + if (len <= 2) + continue; + /* obtain values of binary variables from optimal solution to + * LP relaxation of current subproblem */ + for (k = 1; k <= len; k++) + { xassert(glp_get_col_kind(P, ind[k]) == GLP_BV); + x[k] = glp_get_col_prim(P, ind[k]); + if (x[k] < 0.00001) + x[k] = 0; + else if (x[k] > 0.99999) + x[k] = 1; + /* if val[k] < 0, perform substitution x[k] = 1 - x'[k] to + * make all coefficients positive */ + if (val[k] < 0) + { ind[k] = - ind[k]; /* x[k] is complemented */ + val[k] = - val[k]; + rhs += val[k]; + x[k] = 1 - x[k]; + } + } + /* find locally valid simple cover cut */ + zeta = simple_cover(len, val, rhs, x, z); + if (zeta > 0.95) + { /* no violation or insufficient violation; see (2) */ + continue; + } + /* construct cover inequality (2) for the cover found, which + * for original binary variables x[k] is equivalent to: + * sum{k in C'} x[k] + sum{k in C"} x'[k] <= |C| - 1 + * or + * sum{k in C'} x[k] + sum{k in C"} (1 - x[k]) <= |C| - 1 + * or + * sum{k in C'} x[k] - sum{k in C"} x[k] <= |C'| - 1 + * since |C| - |C"| = |C'| */ + new_len = 0; + rhs = -1; + for (k = 1; k <= len; k++) + { if (z[k]) + { new_len++; + if (ind[k] > 0) + { ind[new_len] = +ind[k]; + val[new_len] = +1; + rhs++; + } + else /* ind[k] < 0 */ + { ind[new_len] = -ind[k]; + val[new_len] = -1; + } + } + } + len = new_len; + /* add the cover inequality to the local cut pool */ + k = glp_add_rows(pool, 1); + glp_set_mat_row(pool, k, len, ind, val); + glp_set_row_bnds(pool, k, GLP_UP, rhs, rhs); + } + /* free working arrays */ + tfree(ind); + tfree(val); + tfree(x); + tfree(z); + return; +} + +/**********************************************************************/ + +void glp_cov_free(glp_cov *cov) +{ /* delete cover cut generator workspace */ + xassert(cov != NULL); + glp_delete_prob(cov->set); + tfree(cov); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/fpump.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/fpump.c new file mode 100644 index 000000000..0bdd6d4e5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/fpump.c @@ -0,0 +1,360 @@ +/* fpump.c (feasibility pump heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* ios_feas_pump - feasibility pump heuristic +* +* SYNOPSIS +* +* #include "glpios.h" +* void ios_feas_pump(glp_tree *T); +* +* DESCRIPTION +* +* The routine ios_feas_pump is a simple implementation of the Feasi- +* bility Pump heuristic. +* +* REFERENCES +* +* M.Fischetti, F.Glover, and A.Lodi. "The feasibility pump." Math. +* Program., Ser. A 104, pp. 91-104 (2005). */ + +struct VAR +{ /* binary variable */ + int j; + /* ordinal number */ + int x; + /* value in the rounded solution (0 or 1) */ + double d; + /* sorting key */ +}; + +static int CDECL fcmp(const void *x, const void *y) +{ /* comparison routine */ + const struct VAR *vx = x, *vy = y; + if (vx->d > vy->d) + return -1; + else if (vx->d < vy->d) + return +1; + else + return 0; +} + +void ios_feas_pump(glp_tree *T) +{ glp_prob *P = T->mip; + int n = P->n; + glp_prob *lp = NULL; + struct VAR *var = NULL; + RNG *rand = NULL; + GLPCOL *col; + glp_smcp parm; + int j, k, new_x, nfail, npass, nv, ret, stalling; + double dist, tol; + xassert(glp_get_status(P) == GLP_OPT); + /* this heuristic is applied only once on the root level */ + if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; + /* determine number of binary variables */ + nv = 0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + /* if x[j] is continuous, skip it */ + if (col->kind == GLP_CV) continue; + /* if x[j] is fixed, skip it */ + if (col->type == GLP_FX) continue; + /* x[j] is non-fixed integer */ + xassert(col->kind == GLP_IV); + if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) + { /* x[j] is binary */ + nv++; + } + else + { /* x[j] is general integer */ + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("FPUMP heuristic cannot be applied due to genera" + "l integer variables\n"); + goto done; + } + } + /* there must be at least one binary variable */ + if (nv == 0) goto done; + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Applying FPUMP heuristic...\n"); + /* build the list of binary variables */ + var = xcalloc(1+nv, sizeof(struct VAR)); + k = 0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + if (col->kind == GLP_IV && col->type == GLP_DB) + var[++k].j = j; + } + xassert(k == nv); + /* create working problem object */ + lp = glp_create_prob(); +more: /* copy the original problem object to keep it intact */ + glp_copy_prob(lp, P, GLP_OFF); + /* we are interested to find an integer feasible solution, which + is better than the best known one */ + if (P->mip_stat == GLP_FEAS) + { int *ind; + double *val, bnd; + /* add a row and make it identical to the objective row */ + glp_add_rows(lp, 1); + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { ind[j] = j; + val[j] = P->col[j]->coef; + } + glp_set_mat_row(lp, lp->m, n, ind, val); + xfree(ind); + xfree(val); + /* introduce upper (minimization) or lower (maximization) + bound to the original objective function; note that this + additional constraint is not violated at the optimal point + to LP relaxation */ +#if 0 /* modified by xypron */ + if (P->dir == GLP_MIN) + { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj)); + if (bnd < P->obj_val) bnd = P->obj_val; + glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); + } + else if (P->dir == GLP_MAX) + { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj)); + if (bnd > P->obj_val) bnd = P->obj_val; + glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); + } + else + xassert(P != P); +#else + bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj; + /* xprintf("bnd = %f\n", bnd); */ + if (P->dir == GLP_MIN) + glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); + else if (P->dir == GLP_MAX) + glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); + else + xassert(P != P); +#endif + } + /* reset pass count */ + npass = 0; + /* invalidate the rounded point */ + for (k = 1; k <= nv; k++) + var[k].x = -1; +pass: /* next pass starts here */ + npass++; + if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Pass %d\n", npass); + /* initialize minimal distance between the basic point and the + rounded one obtained during this pass */ + dist = DBL_MAX; + /* reset failure count (the number of succeeded iterations failed + to improve the distance) */ + nfail = 0; + /* if it is not the first pass, perturb the last rounded point + rather than construct it from the basic solution */ + if (npass > 1) + { double rho, temp; + if (rand == NULL) + rand = rng_create_rand(); + for (k = 1; k <= nv; k++) + { j = var[k].j; + col = lp->col[j]; + rho = rng_uniform(rand, -0.3, 0.7); + if (rho < 0.0) rho = 0.0; + temp = fabs((double)var[k].x - col->prim); + if (temp + rho > 0.5) var[k].x = 1 - var[k].x; + } + goto skip; + } +loop: /* innermost loop begins here */ + /* round basic solution (which is assumed primal feasible) */ + stalling = 1; + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + if (col->prim < 0.5) + { /* rounded value is 0 */ + new_x = 0; + } + else + { /* rounded value is 1 */ + new_x = 1; + } + if (var[k].x != new_x) + { stalling = 0; + var[k].x = new_x; + } + } + /* if the rounded point has not changed (stalling), choose and + flip some its entries heuristically */ + if (stalling) + { /* compute d[j] = |x[j] - round(x[j])| */ + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + var[k].d = fabs(col->prim - (double)var[k].x); + } + /* sort the list of binary variables by descending d[j] */ + qsort(&var[1], nv, sizeof(struct VAR), fcmp); + /* choose and flip some rounded components */ + for (k = 1; k <= nv; k++) + { if (k >= 5 && var[k].d < 0.35 || k >= 10) break; + var[k].x = 1 - var[k].x; + } + } +skip: /* check if the time limit has been exhausted */ + if (T->parm->tm_lim < INT_MAX && + (double)(T->parm->tm_lim - 1) <= + 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done; + /* build the objective, which is the distance between the current + (basic) point and the rounded one */ + lp->dir = GLP_MIN; + lp->c0 = 0.0; + for (j = 1; j <= n; j++) + lp->col[j]->coef = 0.0; + for (k = 1; k <= nv; k++) + { j = var[k].j; + if (var[k].x == 0) + lp->col[j]->coef = +1.0; + else + { lp->col[j]->coef = -1.0; + lp->c0 += 1.0; + } + } + /* minimize the distance with the simplex method */ + glp_init_smcp(&parm); + if (T->parm->msg_lev <= GLP_MSG_ERR) + parm.msg_lev = T->parm->msg_lev; + else if (T->parm->msg_lev <= GLP_MSG_ALL) + { parm.msg_lev = GLP_MSG_ON; + parm.out_dly = 10000; + } + ret = glp_simplex(lp, &parm); + if (ret != 0) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_simplex returned %d\n", ret); + goto done; + } + ret = glp_get_status(lp); + if (ret != GLP_OPT) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_get_status returned %d\n", ret); + goto done; + } + if (T->parm->msg_lev >= GLP_MSG_DBG) + xprintf("delta = %g\n", lp->obj_val); + /* check if the basic solution is integer feasible; note that it + may be so even if the minimial distance is positive */ + tol = 0.3 * T->parm->tol_int; + for (k = 1; k <= nv; k++) + { col = lp->col[var[k].j]; + if (tol < col->prim && col->prim < 1.0 - tol) break; + } + if (k > nv) + { /* okay; the basic solution seems to be integer feasible */ + double *x = xcalloc(1+n, sizeof(double)); + for (j = 1; j <= n; j++) + { x[j] = lp->col[j]->prim; + if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5); + } +#if 1 /* modified by xypron */ + /* reset direction and right-hand side of objective */ + lp->c0 = P->c0; + lp->dir = P->dir; + /* fix integer variables */ + for (k = 1; k <= nv; k++) +#if 0 /* 18/VI-2013; fixed by mao + * this bug causes numerical instability, because column statuses + * are not changed appropriately */ + { lp->col[var[k].j]->lb = x[var[k].j]; + lp->col[var[k].j]->ub = x[var[k].j]; + lp->col[var[k].j]->type = GLP_FX; + } +#else + glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.); +#endif + /* copy original objective function */ + for (j = 1; j <= n; j++) + lp->col[j]->coef = P->col[j]->coef; + /* solve original LP and copy result */ + ret = glp_simplex(lp, &parm); + if (ret != 0) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_simplex returned %d\n", ret); +#if 1 /* 17/III-2016: fix memory leak */ + xfree(x); +#endif + goto done; + } + ret = glp_get_status(lp); + if (ret != GLP_OPT) + { if (T->parm->msg_lev >= GLP_MSG_ERR) + xprintf("Warning: glp_get_status returned %d\n", ret); +#if 1 /* 17/III-2016: fix memory leak */ + xfree(x); +#endif + goto done; + } + for (j = 1; j <= n; j++) + if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim; +#endif + ret = glp_ios_heur_sol(T, x); + xfree(x); + if (ret == 0) + { /* the integer solution is accepted */ + if (ios_is_hopeful(T, T->curr->bound)) + { /* it is reasonable to apply the heuristic once again */ + goto more; + } + else + { /* the best known integer feasible solution just found + is close to optimal solution to LP relaxation */ + goto done; + } + } + } + /* the basic solution is fractional */ + if (dist == DBL_MAX || + lp->obj_val <= dist - 1e-6 * (1.0 + dist)) + { /* the distance is reducing */ + nfail = 0, dist = lp->obj_val; + } + else + { /* improving the distance failed */ + nfail++; + } + if (nfail < 3) goto loop; + if (npass < 5) goto pass; +done: /* delete working objects */ + if (lp != NULL) glp_delete_prob(lp); + if (var != NULL) xfree(var); + if (rand != NULL) rng_delete_rand(rand); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmicut.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmicut.c new file mode 100644 index 000000000..4ef0b746c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmicut.c @@ -0,0 +1,284 @@ +/* gmicut.c (Gomory's mixed integer cut generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2002-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_gmi_cut - generate Gomory's mixed integer cut (core routine) +* +* SYNOPSIS +* +* int glp_gmi_cut(glp_prob *P, int j, int ind[], double val[], double +* phi[]); +* +* DESCRIPTION +* +* This routine attempts to generate a Gomory's mixed integer cut for +* specified integer column (structural variable), whose primal value +* in current basic solution is integer infeasible (fractional). +* +* On entry to the routine the basic solution contained in the problem +* object P should be optimal, and the basis factorization should be +* valid. The parameter j should specify the ordinal number of column +* (structural variable x[j]), for which the cut should be generated, +* 1 <= j <= n, where n is the number of columns in the problem object. +* This column should be integer, non-fixed, and basic, and its primal +* value should be fractional. +* +* The cut generated by the routine is the following inequality: +* +* sum a[j] * x[j] >= b, +* +* which is expected to be violated at the current basic solution. +* +* If the cut has been successfully generated, the routine stores its +* non-zero coefficients a[j] and corresponding column indices j in the +* array locations val[1], ..., val[len] and ind[1], ..., ind[len], +* where 1 <= len <= n is the number of non-zero coefficients. The +* right-hand side value b is stored in val[0], and ind[0] is set to 0. +* +* The working array phi should have 1+m+n locations (location phi[0] +* is not used), where m and n is the number of rows and columns in the +* problem object, resp. +* +* RETURNS +* +* If the cut has been successfully generated, the routine returns +* len, the number of non-zero coefficients in the cut, 1 <= len <= n. +* +* Otherwise, the routine returns one of the following codes: +* +* -1 current basis factorization is not valid; +* +* -2 current basic solution is not optimal; +* +* -3 column ordinal number j is out of range; +* +* -4 variable x[j] is not of integral kind; +* +* -5 variable x[j] is either fixed or non-basic; +* +* -6 primal value of variable x[j] in basic solution is too close +* to nearest integer; +* +* -7 some coefficients in the simplex table row corresponding to +* variable x[j] are too large in magnitude; +* +* -8 some free (unbounded) variables have non-zero coefficients in +* the simplex table row corresponding to variable x[j]. +* +* ALGORITHM +* +* See glpk/doc/notes/gomory (in Russian). */ + +#define f(x) ((x) - floor(x)) +/* compute fractional part of x */ + +int glp_gmi_cut(glp_prob *P, int j, + int ind[/*1+n*/], double val[/*1+n*/], double phi[/*1+m+n*/]) +{ int m = P->m; + int n = P->n; + GLPROW *row; + GLPCOL *col; + GLPAIJ *aij; + int i, k, len, kind, stat; + double lb, ub, alfa, beta, ksi, phi1, rhs; + /* sanity checks */ + if (!(P->m == 0 || P->valid)) + { /* current basis factorization is not valid */ + return -1; + } + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + { /* current basic solution is not optimal */ + return -2; + } + if (!(1 <= j && j <= n)) + { /* column ordinal number is out of range */ + return -3; + } + col = P->col[j]; + if (col->kind != GLP_IV) + { /* x[j] is not of integral kind */ + return -4; + } + if (col->type == GLP_FX || col->stat != GLP_BS) + { /* x[j] is either fixed or non-basic */ + return -5; + } + if (fabs(col->prim - floor(col->prim + 0.5)) < 0.001) + { /* primal value of x[j] is too close to nearest integer */ + return -6; + } + /* compute row of the simplex tableau, which (row) corresponds + * to specified basic variable xB[i] = x[j]; see (23) */ + len = glp_eval_tab_row(P, m+j, ind, val); + /* determine beta[i], which a value of xB[i] in optimal solution + * to current LP relaxation; note that this value is the same as + * if it would be computed with formula (27); it is assumed that + * beta[i] is fractional enough */ + beta = P->col[j]->prim; + /* compute cut coefficients phi and right-hand side rho, which + * correspond to formula (30); dense format is used, because rows + * of the simplex tableau are usually dense */ + for (k = 1; k <= m+n; k++) + phi[k] = 0.0; + rhs = f(beta); /* initial value of rho; see (28), (32) */ + for (j = 1; j <= len; j++) + { /* determine original number of non-basic variable xN[j] */ + k = ind[j]; + xassert(1 <= k && k <= m+n); + /* determine the kind, bounds and current status of xN[j] in + * optimal solution to LP relaxation */ + if (k <= m) + { /* auxiliary variable */ + row = P->row[k]; + kind = GLP_CV; + lb = row->lb; + ub = row->ub; + stat = row->stat; + } + else + { /* structural variable */ + col = P->col[k-m]; + kind = col->kind; + lb = col->lb; + ub = col->ub; + stat = col->stat; + } + /* xN[j] cannot be basic */ + xassert(stat != GLP_BS); + /* determine row coefficient ksi[i,j] at xN[j]; see (23) */ + ksi = val[j]; + /* if ksi[i,j] is too large in magnitude, report failure */ + if (fabs(ksi) > 1e+05) + return -7; + /* if ksi[i,j] is too small in magnitude, skip it */ + if (fabs(ksi) < 1e-10) + goto skip; + /* compute row coefficient alfa[i,j] at y[j]; see (26) */ + switch (stat) + { case GLP_NF: + /* xN[j] is free (unbounded) having non-zero ksi[i,j]; + * report failure */ + return -8; + case GLP_NL: + /* xN[j] has active lower bound */ + alfa = - ksi; + break; + case GLP_NU: + /* xN[j] has active upper bound */ + alfa = + ksi; + break; + case GLP_NS: + /* xN[j] is fixed; skip it */ + goto skip; + default: + xassert(stat != stat); + } + /* compute cut coefficient phi'[j] at y[j]; see (21), (28) */ + switch (kind) + { case GLP_IV: + /* y[j] is integer */ + if (fabs(alfa - floor(alfa + 0.5)) < 1e-10) + { /* alfa[i,j] is close to nearest integer; skip it */ + goto skip; + } + else if (f(alfa) <= f(beta)) + phi1 = f(alfa); + else + phi1 = (f(beta) / (1.0 - f(beta))) * (1.0 - f(alfa)); + break; + case GLP_CV: + /* y[j] is continuous */ + if (alfa >= 0.0) + phi1 = + alfa; + else + phi1 = (f(beta) / (1.0 - f(beta))) * (- alfa); + break; + default: + xassert(kind != kind); + } + /* compute cut coefficient phi[j] at xN[j] and update right- + * hand side rho; see (31), (32) */ + switch (stat) + { case GLP_NL: + /* xN[j] has active lower bound */ + phi[k] = + phi1; + rhs += phi1 * lb; + break; + case GLP_NU: + /* xN[j] has active upper bound */ + phi[k] = - phi1; + rhs -= phi1 * ub; + break; + default: + xassert(stat != stat); + } +skip: ; + } + /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut + * coefficients are stored in the array phi in dense format; + * x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc- + * tural variables; see (30) */ + /* eliminate auxiliary variables in order to express the cut only + * through structural variables; see (33) */ + for (i = 1; i <= m; i++) + { if (fabs(phi[i]) < 1e-10) + continue; + /* auxiliary variable x[i] has non-zero cut coefficient */ + row = P->row[i]; + /* x[i] cannot be fixed variable */ + xassert(row->type != GLP_FX); + /* substitute x[i] = sum_j a[i,j] * x[m+j] */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + phi[m+aij->col->j] += phi[i] * aij->val; + } + /* convert the final cut to sparse format and substitute fixed + * (structural) variables */ + len = 0; + for (j = 1; j <= n; j++) + { if (fabs(phi[m+j]) < 1e-10) + continue; + /* structural variable x[m+j] has non-zero cut coefficient */ + col = P->col[j]; + if (col->type == GLP_FX) + { /* eliminate x[m+j] */ + rhs -= phi[m+j] * col->lb; + } + else + { len++; + ind[len] = j; + val[len] = phi[m+j]; + } + } + if (fabs(rhs) < 1e-12) + rhs = 0.0; + ind[0] = 0, val[0] = rhs; + /* the cut has been successfully generated */ + return len; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmigen.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmigen.c new file mode 100644 index 000000000..627682cbd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/gmigen.c @@ -0,0 +1,142 @@ +/* gmigen.c (Gomory's mixed integer cuts generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2002-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "prob.h" + +/*********************************************************************** +* NAME +* +* glp_gmi_gen - generate Gomory's mixed integer cuts +* +* SYNOPSIS +* +* int glp_gmi_gen(glp_prob *P, glp_prob *pool, int max_cuts); +* +* DESCRIPTION +* +* This routine attempts to generate Gomory's mixed integer cuts for +* integer variables, whose primal values in current basic solution are +* integer infeasible (fractional). +* +* On entry to the routine the basic solution contained in the problem +* object P should be optimal, and the basis factorization should be +* valid. +* +* The cutting plane inequalities generated by the routine are added to +* the specified cut pool. +* +* The parameter max_cuts specifies the maximal number of cuts to be +* generated. Note that the number of cuts cannot exceed the number of +* basic variables, which is the number of rows in the problem object. +* +* RETURNS +* +* The routine returns the number of cuts that have been generated and +* added to the cut pool. */ + +#define f(x) ((x) - floor(x)) +/* compute fractional part of x */ + +struct var { int j; double f; }; + +static int CDECL fcmp(const void *p1, const void *p2) +{ const struct var *v1 = p1, *v2 = p2; + if (v1->f > v2->f) return -1; + if (v1->f < v2->f) return +1; + return 0; +} + +int glp_gmi_gen(glp_prob *P, glp_prob *pool, int max_cuts) +{ int m = P->m; + int n = P->n; + GLPCOL *col; + struct var *var; + int i, j, k, t, len, nv, nnn, *ind; + double frac, *val, *phi; + /* sanity checks */ + if (!(P->m == 0 || P->valid)) + xerror("glp_gmi_gen: basis factorization does not exist\n"); + if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) + xerror("glp_gmi_gen: optimal basic solution required\n"); + if (pool->n != n) + xerror("glp_gmi_gen: cut pool has wrong number of columns\n"); + /* allocate working arrays */ + var = xcalloc(1+n, sizeof(struct var)); + ind = xcalloc(1+n, sizeof(int)); + val = xcalloc(1+n, sizeof(double)); + phi = xcalloc(1+m+n, sizeof(double)); + /* build the list of integer structural variables, which are + * basic and have integer infeasible (fractional) primal values + * in optimal solution to specified LP */ + nv = 0; + for (j = 1; j <= n; j++) + { col = P->col[j]; + if (col->kind != GLP_IV) + continue; + if (col->type == GLP_FX) + continue; + if (col->stat != GLP_BS) + continue; + frac = f(col->prim); + if (!(0.05 <= frac && frac <= 0.95)) + continue; + /* add variable to the list */ + nv++, var[nv].j = j, var[nv].f = frac; + } + /* sort the list by descending fractionality */ + qsort(&var[1], nv, sizeof(struct var), fcmp); + /* try to generate cuts by one for each variable in the list, but + * not more than max_cuts cuts */ + nnn = 0; + for (t = 1; t <= nv; t++) + { len = glp_gmi_cut(P, var[t].j, ind, val, phi); + if (len < 1) + goto skip; + /* if the cut inequality seems to be badly scaled, reject it + * to avoid numerical difficulties */ + for (k = 1; k <= len; k++) + { if (fabs(val[k]) < 1e-03) + goto skip; + if (fabs(val[k]) > 1e+03) + goto skip; + } + /* add the cut to the cut pool for further consideration */ + i = glp_add_rows(pool, 1); + glp_set_row_bnds(pool, i, GLP_LO, val[0], 0); + glp_set_mat_row(pool, i, len, ind, val); + /* one cut has been generated */ + nnn++; + if (nnn == max_cuts) + break; +skip: ; + } + /* free working arrays */ + xfree(var); + xfree(ind); + xfree(val); + xfree(phi); + return nnn; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/mirgen.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/mirgen.c new file mode 100644 index 000000000..45a0a55dc --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/mirgen.c @@ -0,0 +1,1529 @@ +/* mirgen.c (mixed integer rounding cuts generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2007-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#if 1 /* 29/II-2016 by Chris */ +/*---------------------------------------------------------------------- +Subject: Mir cut generation performance improvement +From: Chris Matrakidis +To: Andrew Makhorin , help-glpk + +Andrew, + +I noticed that mir cut generation takes considerable time on some large +problems (like rocII-4-11 from miplib). The attached patch makes two +improvements that considerably improve performance in such instances: +1. A lot of time was spent on generating a temporary vector in function +aggregate_row. It is a lot faster to reuse an existing vector. +2. A search for an element in the same function was done in row order, +where using the elements in the order they are in the column is more +efficient. This changes the generated cuts in some cases, but seems +neutral overall (0.3% less cuts in a test set of 64 miplib instances). + +Best Regards, + +Chris Matrakidis +----------------------------------------------------------------------*/ +#endif + +#include "env.h" +#include "prob.h" +#include "spv.h" + +#define MIR_DEBUG 0 + +#define MAXAGGR 5 +/* maximal number of rows that can be aggregated */ + +struct glp_mir +{ /* MIR cut generator working area */ + /*--------------------------------------------------------------*/ + /* global information valid for the root subproblem */ + int m; + /* number of rows (in the root subproblem) */ + int n; + /* number of columns */ + char *skip; /* char skip[1+m]; */ + /* skip[i], 1 <= i <= m, is a flag that means that row i should + not be used because (1) it is not suitable, or (2) because it + has been used in the aggregated constraint */ + char *isint; /* char isint[1+m+n]; */ + /* isint[k], 1 <= k <= m+n, is a flag that means that variable + x[k] is integer (otherwise, continuous) */ + double *lb; /* double lb[1+m+n]; */ + /* lb[k], 1 <= k <= m+n, is lower bound of x[k]; -DBL_MAX means + that x[k] has no lower bound */ + int *vlb; /* int vlb[1+m+n]; */ + /* vlb[k] = k', 1 <= k <= m+n, is the number of integer variable, + which defines variable lower bound x[k] >= lb[k] * x[k']; zero + means that x[k] has simple lower bound */ + double *ub; /* double ub[1+m+n]; */ + /* ub[k], 1 <= k <= m+n, is upper bound of x[k]; +DBL_MAX means + that x[k] has no upper bound */ + int *vub; /* int vub[1+m+n]; */ + /* vub[k] = k', 1 <= k <= m+n, is the number of integer variable, + which defines variable upper bound x[k] <= ub[k] * x[k']; zero + means that x[k] has simple upper bound */ + /*--------------------------------------------------------------*/ + /* current (fractional) point to be separated */ + double *x; /* double x[1+m+n]; */ + /* x[k] is current value of auxiliary (1 <= k <= m) or structural + (m+1 <= k <= m+n) variable */ + /*--------------------------------------------------------------*/ + /* aggregated constraint sum a[k] * x[k] = b, which is a linear + combination of original constraints transformed to equalities + by introducing auxiliary variables */ + int agg_cnt; + /* number of rows (original constraints) used to build aggregated + constraint, 1 <= agg_cnt <= MAXAGGR */ + int *agg_row; /* int agg_row[1+MAXAGGR]; */ + /* agg_row[k], 1 <= k <= agg_cnt, is the row number used to build + aggregated constraint */ + SPV *agg_vec; /* SPV agg_vec[1:m+n]; */ + /* sparse vector of aggregated constraint coefficients, a[k] */ + double agg_rhs; + /* right-hand side of the aggregated constraint, b */ + /*--------------------------------------------------------------*/ + /* bound substitution flags for modified constraint */ + char *subst; /* char subst[1+m+n]; */ + /* subst[k], 1 <= k <= m+n, is a bound substitution flag used for + variable x[k]: + '?' - x[k] is missing in modified constraint + 'L' - x[k] = (lower bound) + x'[k] + 'U' - x[k] = (upper bound) - x'[k] */ + /*--------------------------------------------------------------*/ + /* modified constraint sum a'[k] * x'[k] = b', where x'[k] >= 0, + derived from aggregated constraint by substituting bounds; + note that due to substitution of variable bounds there may be + additional terms in the modified constraint */ + SPV *mod_vec; /* SPV mod_vec[1:m+n]; */ + /* sparse vector of modified constraint coefficients, a'[k] */ + double mod_rhs; + /* right-hand side of the modified constraint, b' */ + /*--------------------------------------------------------------*/ + /* cutting plane sum alpha[k] * x[k] <= beta */ + SPV *cut_vec; /* SPV cut_vec[1:m+n]; */ + /* sparse vector of cutting plane coefficients, alpha[k] */ + double cut_rhs; + /* right-hand size of the cutting plane, beta */ +}; + +/*********************************************************************** +* NAME +* +* glp_mir_init - create and initialize MIR cut generator +* +* SYNOPSIS +* +* glp_mir *glp_mir_init(glp_prob *P); +* +* DESCRIPTION +* +* This routine creates and initializes the MIR cut generator for the +* specified problem object. +* +* RETURNS +* +* The routine returns a pointer to the MIR cut generator workspace. */ + +static void set_row_attrib(glp_prob *mip, glp_mir *mir) +{ /* set global row attributes */ + int m = mir->m; + int k; + for (k = 1; k <= m; k++) + { GLPROW *row = mip->row[k]; + mir->skip[k] = 0; + mir->isint[k] = 0; + switch (row->type) + { case GLP_FR: + mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; + case GLP_LO: + mir->lb[k] = row->lb, mir->ub[k] = +DBL_MAX; break; + case GLP_UP: + mir->lb[k] = -DBL_MAX, mir->ub[k] = row->ub; break; + case GLP_DB: + mir->lb[k] = row->lb, mir->ub[k] = row->ub; break; + case GLP_FX: + mir->lb[k] = mir->ub[k] = row->lb; break; + default: + xassert(row != row); + } + mir->vlb[k] = mir->vub[k] = 0; + } + return; +} + +static void set_col_attrib(glp_prob *mip, glp_mir *mir) +{ /* set global column attributes */ + int m = mir->m; + int n = mir->n; + int k; + for (k = m+1; k <= m+n; k++) + { GLPCOL *col = mip->col[k-m]; + switch (col->kind) + { case GLP_CV: + mir->isint[k] = 0; break; + case GLP_IV: + mir->isint[k] = 1; break; + default: + xassert(col != col); + } + switch (col->type) + { case GLP_FR: + mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; + case GLP_LO: + mir->lb[k] = col->lb, mir->ub[k] = +DBL_MAX; break; + case GLP_UP: + mir->lb[k] = -DBL_MAX, mir->ub[k] = col->ub; break; + case GLP_DB: + mir->lb[k] = col->lb, mir->ub[k] = col->ub; break; + case GLP_FX: + mir->lb[k] = mir->ub[k] = col->lb; break; + default: + xassert(col != col); + } + mir->vlb[k] = mir->vub[k] = 0; + } + return; +} + +static void set_var_bounds(glp_prob *mip, glp_mir *mir) +{ /* set variable bounds */ + int m = mir->m; + GLPAIJ *aij; + int i, k1, k2; + double a1, a2; + for (i = 1; i <= m; i++) + { /* we need the row to be '>= 0' or '<= 0' */ + if (!(mir->lb[i] == 0.0 && mir->ub[i] == +DBL_MAX || + mir->lb[i] == -DBL_MAX && mir->ub[i] == 0.0)) continue; + /* take first term */ + aij = mip->row[i]->ptr; + if (aij == NULL) continue; + k1 = m + aij->col->j, a1 = aij->val; + /* take second term */ + aij = aij->r_next; + if (aij == NULL) continue; + k2 = m + aij->col->j, a2 = aij->val; + /* there must be only two terms */ + if (aij->r_next != NULL) continue; + /* interchange terms, if needed */ + if (!mir->isint[k1] && mir->isint[k2]) + ; + else if (mir->isint[k1] && !mir->isint[k2]) + { k2 = k1, a2 = a1; + k1 = m + aij->col->j, a1 = aij->val; + } + else + { /* both terms are either continuous or integer */ + continue; + } + /* x[k2] should be double-bounded */ + if (mir->lb[k2] == -DBL_MAX || mir->ub[k2] == +DBL_MAX || + mir->lb[k2] == mir->ub[k2]) continue; + /* change signs, if necessary */ + if (mir->ub[i] == 0.0) a1 = - a1, a2 = - a2; + /* now the row has the form a1 * x1 + a2 * x2 >= 0, where x1 + is continuous, x2 is integer */ + if (a1 > 0.0) + { /* x1 >= - (a2 / a1) * x2 */ + if (mir->vlb[k1] == 0) + { /* set variable lower bound for x1 */ + mir->lb[k1] = - a2 / a1; + mir->vlb[k1] = k2; + /* the row should not be used */ + mir->skip[i] = 1; + } + } + else /* a1 < 0.0 */ + { /* x1 <= - (a2 / a1) * x2 */ + if (mir->vub[k1] == 0) + { /* set variable upper bound for x1 */ + mir->ub[k1] = - a2 / a1; + mir->vub[k1] = k2; + /* the row should not be used */ + mir->skip[i] = 1; + } + } + } + return; +} + +static void mark_useless_rows(glp_prob *mip, glp_mir *mir) +{ /* mark rows which should not be used */ + int m = mir->m; + GLPAIJ *aij; + int i, k, nv; + for (i = 1; i <= m; i++) + { /* free rows should not be used */ + if (mir->lb[i] == -DBL_MAX && mir->ub[i] == +DBL_MAX) + { mir->skip[i] = 1; + continue; + } + nv = 0; + for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) + { k = m + aij->col->j; + /* rows with free variables should not be used */ + if (mir->lb[k] == -DBL_MAX && mir->ub[k] == +DBL_MAX) + { mir->skip[i] = 1; + break; + } + /* rows with integer variables having infinite (lower or + upper) bound should not be used */ + if (mir->isint[k] && mir->lb[k] == -DBL_MAX || + mir->isint[k] && mir->ub[k] == +DBL_MAX) + { mir->skip[i] = 1; + break; + } + /* count non-fixed variables */ + if (!(mir->vlb[k] == 0 && mir->vub[k] == 0 && + mir->lb[k] == mir->ub[k])) nv++; + } + /* rows with all variables fixed should not be used */ + if (nv == 0) + { mir->skip[i] = 1; + continue; + } + } + return; +} + +glp_mir *glp_mir_init(glp_prob *mip) +{ /* create and initialize MIR cut generator */ + int m = mip->m; + int n = mip->n; + glp_mir *mir; +#if MIR_DEBUG + xprintf("ios_mir_init: warning: debug mode enabled\n"); +#endif + /* allocate working area */ + mir = xmalloc(sizeof(glp_mir)); + mir->m = m; + mir->n = n; + mir->skip = xcalloc(1+m, sizeof(char)); + mir->isint = xcalloc(1+m+n, sizeof(char)); + mir->lb = xcalloc(1+m+n, sizeof(double)); + mir->vlb = xcalloc(1+m+n, sizeof(int)); + mir->ub = xcalloc(1+m+n, sizeof(double)); + mir->vub = xcalloc(1+m+n, sizeof(int)); + mir->x = xcalloc(1+m+n, sizeof(double)); + mir->agg_row = xcalloc(1+MAXAGGR, sizeof(int)); + mir->agg_vec = spv_create_vec(m+n); + mir->subst = xcalloc(1+m+n, sizeof(char)); + mir->mod_vec = spv_create_vec(m+n); + mir->cut_vec = spv_create_vec(m+n); + /* set global row attributes */ + set_row_attrib(mip, mir); + /* set global column attributes */ + set_col_attrib(mip, mir); + /* set variable bounds */ + set_var_bounds(mip, mir); + /* mark rows which should not be used */ + mark_useless_rows(mip, mir); + return mir; +} + +/*********************************************************************** +* NAME +* +* glp_mir_gen - generate mixed integer rounding (MIR) cuts +* +* SYNOPSIS +* +* int glp_mir_gen(glp_prob *P, glp_mir *mir, glp_prob *pool); +* +* DESCRIPTION +* +* This routine attempts to generate mixed integer rounding (MIR) cuts +* for current basic solution to the specified problem object. +* +* The cutting plane inequalities generated by the routine are added to +* the specified cut pool. +* +* RETURNS +* +* The routine returns the number of cuts that have been generated and +* added to the cut pool. */ + +static void get_current_point(glp_prob *mip, glp_mir *mir) +{ /* obtain current point */ + int m = mir->m; + int n = mir->n; + int k; + for (k = 1; k <= m; k++) + mir->x[k] = mip->row[k]->prim; + for (k = m+1; k <= m+n; k++) + mir->x[k] = mip->col[k-m]->prim; + return; +} + +#if MIR_DEBUG +static void check_current_point(glp_mir *mir) +{ /* check current point */ + int m = mir->m; + int n = mir->n; + int k, kk; + double lb, ub, eps; + for (k = 1; k <= m+n; k++) + { /* determine lower bound */ + lb = mir->lb[k]; + kk = mir->vlb[k]; + if (kk != 0) + { xassert(lb != -DBL_MAX); + xassert(!mir->isint[k]); + xassert(mir->isint[kk]); + lb *= mir->x[kk]; + } + /* check lower bound */ + if (lb != -DBL_MAX) + { eps = 1e-6 * (1.0 + fabs(lb)); + xassert(mir->x[k] >= lb - eps); + } + /* determine upper bound */ + ub = mir->ub[k]; + kk = mir->vub[k]; + if (kk != 0) + { xassert(ub != +DBL_MAX); + xassert(!mir->isint[k]); + xassert(mir->isint[kk]); + ub *= mir->x[kk]; + } + /* check upper bound */ + if (ub != +DBL_MAX) + { eps = 1e-6 * (1.0 + fabs(ub)); + xassert(mir->x[k] <= ub + eps); + } + } + return; +} +#endif + +static void initial_agg_row(glp_prob *mip, glp_mir *mir, int i) +{ /* use original i-th row as initial aggregated constraint */ + int m = mir->m; + GLPAIJ *aij; + xassert(1 <= i && i <= m); + xassert(!mir->skip[i]); + /* mark i-th row in order not to use it in the same aggregated + constraint */ + mir->skip[i] = 2; + mir->agg_cnt = 1; + mir->agg_row[1] = i; + /* use x[i] - sum a[i,j] * x[m+j] = 0, where x[i] is auxiliary + variable of row i, x[m+j] are structural variables */ + spv_clear_vec(mir->agg_vec); + spv_set_vj(mir->agg_vec, i, 1.0); + for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) + spv_set_vj(mir->agg_vec, m + aij->col->j, - aij->val); + mir->agg_rhs = 0.0; +#if MIR_DEBUG + spv_check_vec(mir->agg_vec); +#endif + return; +} + +#if MIR_DEBUG +static void check_agg_row(glp_mir *mir) +{ /* check aggregated constraint */ + int m = mir->m; + int n = mir->n; + int j, k; + double r, big; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + r += mir->agg_vec->val[j] * mir->x[k]; + if (big < fabs(mir->agg_vec->val[j])) + big = fabs(mir->agg_vec->val[j]); + } + r -= mir->agg_rhs; + if (big < fabs(mir->agg_rhs)) + big = fabs(mir->agg_rhs); + /* the residual must be close to zero */ + xassert(fabs(r) <= 1e-6 * big); + return; +} +#endif + +static void subst_fixed_vars(glp_mir *mir) +{ /* substitute fixed variables into aggregated constraint */ + int m = mir->m; + int n = mir->n; + int j, k; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->vlb[k] == 0 && mir->vub[k] == 0 && + mir->lb[k] == mir->ub[k]) + { /* x[k] is fixed */ + mir->agg_rhs -= mir->agg_vec->val[j] * mir->lb[k]; + mir->agg_vec->val[j] = 0.0; + } + } + /* remove terms corresponding to fixed variables */ + spv_clean_vec(mir->agg_vec, DBL_EPSILON); +#if MIR_DEBUG + spv_check_vec(mir->agg_vec); +#endif + return; +} + +static void bound_subst_heur(glp_mir *mir) +{ /* bound substitution heuristic */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double d1, d2; + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer variable */ + /* compute distance from x[k] to its lower bound */ + kk = mir->vlb[k]; + if (kk == 0) + { if (mir->lb[k] == -DBL_MAX) + d1 = DBL_MAX; + else + d1 = mir->x[k] - mir->lb[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->lb[k] != -DBL_MAX); + d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + /* compute distance from x[k] to its upper bound */ + kk = mir->vub[k]; + if (kk == 0) + { if (mir->vub[k] == +DBL_MAX) + d2 = DBL_MAX; + else + d2 = mir->ub[k] - mir->x[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->ub[k] != +DBL_MAX); + d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + /* x[k] cannot be free */ + xassert(d1 != DBL_MAX || d2 != DBL_MAX); + /* choose the bound which is closer to x[k] */ + xassert(mir->subst[k] == '?'); + if (d1 <= d2) + mir->subst[k] = 'L'; + else + mir->subst[k] = 'U'; + } + return; +} + +static void build_mod_row(glp_mir *mir) +{ /* substitute bounds and build modified constraint */ + int m = mir->m; + int n = mir->n; + int j, jj, k, kk; + /* initially modified constraint is aggregated constraint */ + spv_copy_vec(mir->mod_vec, mir->agg_vec); + mir->mod_rhs = mir->agg_rhs; +#if MIR_DEBUG + spv_check_vec(mir->mod_vec); +#endif + /* substitute bounds for continuous variables; note that due to + substitution of variable bounds additional terms may appear in + modified constraint */ + for (j = mir->mod_vec->nnz; j >= 1; j--) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer variable */ + if (mir->subst[k] == 'L') + { /* x[k] = (lower bound) + x'[k] */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + { /* x[k] = lb[k] + x'[k] */ + mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; + } + else + { /* x[k] = lb[k] * x[kk] + x'[k] */ + xassert(mir->isint[kk]); + jj = mir->mod_vec->pos[kk]; + if (jj == 0) + { spv_set_vj(mir->mod_vec, kk, 1.0); + jj = mir->mod_vec->pos[kk]; + mir->mod_vec->val[jj] = 0.0; + } + mir->mod_vec->val[jj] += + mir->mod_vec->val[j] * mir->lb[k]; + } + } + else if (mir->subst[k] == 'U') + { /* x[k] = (upper bound) - x'[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + { /* x[k] = ub[k] - x'[k] */ + mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; + } + else + { /* x[k] = ub[k] * x[kk] - x'[k] */ + xassert(mir->isint[kk]); + jj = mir->mod_vec->pos[kk]; + if (jj == 0) + { spv_set_vj(mir->mod_vec, kk, 1.0); + jj = mir->mod_vec->pos[kk]; + mir->mod_vec->val[jj] = 0.0; + } + mir->mod_vec->val[jj] += + mir->mod_vec->val[j] * mir->ub[k]; + } + mir->mod_vec->val[j] = - mir->mod_vec->val[j]; + } + else + xassert(k != k); + } +#if MIR_DEBUG + spv_check_vec(mir->mod_vec); +#endif + /* substitute bounds for integer variables */ + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k]) continue; /* skip continuous variable */ + xassert(mir->subst[k] == '?'); + xassert(mir->vlb[k] == 0 && mir->vub[k] == 0); + xassert(mir->lb[k] != -DBL_MAX && mir->ub[k] != +DBL_MAX); + if (fabs(mir->lb[k]) <= fabs(mir->ub[k])) + { /* x[k] = lb[k] + x'[k] */ + mir->subst[k] = 'L'; + mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; + } + else + { /* x[k] = ub[k] - x'[k] */ + mir->subst[k] = 'U'; + mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; + mir->mod_vec->val[j] = - mir->mod_vec->val[j]; + } + } +#if MIR_DEBUG + spv_check_vec(mir->mod_vec); +#endif + return; +} + +#if MIR_DEBUG +static void check_mod_row(glp_mir *mir) +{ /* check modified constraint */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double r, big, x; + /* compute the residual r = sum a'[k] * x'[k] - b' and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - (lower bound) */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { /* x'[k] = (upper bound) - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); + r += mir->mod_vec->val[j] * x; + if (big < fabs(mir->mod_vec->val[j])) + big = fabs(mir->mod_vec->val[j]); + } + r -= mir->mod_rhs; + if (big < fabs(mir->mod_rhs)) + big = fabs(mir->mod_rhs); + /* the residual must be close to zero */ + xassert(fabs(r) <= 1e-6 * big); + return; +} +#endif + +/*********************************************************************** +* mir_ineq - construct MIR inequality +* +* Given the single constraint mixed integer set +* +* |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s}, +* + + j in N +* +* this routine constructs the mixed integer rounding (MIR) inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* +* which is valid for X. +* +* If the MIR inequality has been successfully constructed, the routine +* returns zero. Otherwise, if b is close to nearest integer, there may +* be numeric difficulties due to big coefficients; so in this case the +* routine returns non-zero. */ + +static int mir_ineq(const int n, const double a[], const double b, + double alpha[], double *beta, double *gamma) +{ int j; + double f, t; + if (fabs(b - floor(b + .5)) < 0.01) + return 1; + f = b - floor(b); + for (j = 1; j <= n; j++) + { t = (a[j] - floor(a[j])) - f; + if (t <= 0.0) + alpha[j] = floor(a[j]); + else + alpha[j] = floor(a[j]) + t / (1.0 - f); + } + *beta = floor(b); + *gamma = 1.0 / (1.0 - f); + return 0; +} + +/*********************************************************************** +* cmir_ineq - construct c-MIR inequality +* +* Given the mixed knapsack set +* +* MK |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, +* + + j in N +* +* x[j] <= u[j]}, +* +* a subset C of variables to be complemented, and a divisor delta > 0, +* this routine constructs the complemented MIR (c-MIR) inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* MK +* which is valid for X . +* +* If the c-MIR inequality has been successfully constructed, the +* routine returns zero. Otherwise, if there is a risk of numerical +* difficulties due to big coefficients (see comments to the routine +* mir_ineq), the routine cmir_ineq returns non-zero. */ + +static int cmir_ineq(const int n, const double a[], const double b, + const double u[], const char cset[], const double delta, + double alpha[], double *beta, double *gamma) +{ int j; + double *aa, bb; + aa = alpha, bb = b; + for (j = 1; j <= n; j++) + { aa[j] = a[j] / delta; + if (cset[j]) + aa[j] = - aa[j], bb -= a[j] * u[j]; + } + bb /= delta; + if (mir_ineq(n, aa, bb, alpha, beta, gamma)) return 1; + for (j = 1; j <= n; j++) + { if (cset[j]) + alpha[j] = - alpha[j], *beta += alpha[j] * u[j]; + } + *gamma /= delta; + return 0; +} + +/*********************************************************************** +* cmir_sep - c-MIR separation heuristic +* +* Given the mixed knapsack set +* +* MK |N| +* X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, +* + + j in N +* +* x[j] <= u[j]} +* +* * * +* and a fractional point (x , s ), this routine tries to construct +* c-MIR inequality +* +* sum alpha[j] * x[j] <= beta + gamma * s, +* j in N +* MK +* which is valid for X and has (desirably maximal) violation at the +* fractional point given. This is attained by choosing an appropriate +* set C of variables to be complemented and a divisor delta > 0, which +* together define corresponding c-MIR inequality. +* +* If a violated c-MIR inequality has been successfully constructed, +* the routine returns its violation: +* +* * * +* sum alpha[j] * x [j] - beta - gamma * s , +* j in N +* +* which is positive. In case of failure the routine returns zero. */ + +struct vset { int j; double v; }; + +static int CDECL cmir_cmp(const void *p1, const void *p2) +{ const struct vset *v1 = p1, *v2 = p2; + if (v1->v < v2->v) return -1; + if (v1->v > v2->v) return +1; + return 0; +} + +static double cmir_sep(const int n, const double a[], const double b, + const double u[], const double x[], const double s, + double alpha[], double *beta, double *gamma) +{ int fail, j, k, nv, v; + double delta, eps, d_try[1+3], r, r_best; + char *cset; + struct vset *vset; + /* allocate working arrays */ + cset = xcalloc(1+n, sizeof(char)); + vset = xcalloc(1+n, sizeof(struct vset)); + /* choose initial C */ + for (j = 1; j <= n; j++) + cset[j] = (char)(x[j] >= 0.5 * u[j]); + /* choose initial delta */ + r_best = delta = 0.0; + for (j = 1; j <= n; j++) + { xassert(a[j] != 0.0); + /* if x[j] is close to its bounds, skip it */ + eps = 1e-9 * (1.0 + fabs(u[j])); + if (x[j] < eps || x[j] > u[j] - eps) continue; + /* try delta = |a[j]| to construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, fabs(a[j]), alpha, beta, + gamma); + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, delta = fabs(a[j]); + } + if (r_best < 0.001) r_best = 0.0; + if (r_best == 0.0) goto done; + xassert(delta > 0.0); + /* try to increase violation by dividing delta by 2, 4, and 8, + respectively */ + d_try[1] = delta / 2.0; + d_try[2] = delta / 4.0; + d_try[3] = delta / 8.0; + for (j = 1; j <= 3; j++) + { /* construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, d_try[j], alpha, beta, + gamma); + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, delta = d_try[j]; + } + /* build subset of variables lying strictly between their bounds + and order it by nondecreasing values of |x[j] - u[j]/2| */ + nv = 0; + for (j = 1; j <= n; j++) + { /* if x[j] is close to its bounds, skip it */ + eps = 1e-9 * (1.0 + fabs(u[j])); + if (x[j] < eps || x[j] > u[j] - eps) continue; + /* add x[j] to the subset */ + nv++; + vset[nv].j = j; + vset[nv].v = fabs(x[j] - 0.5 * u[j]); + } + qsort(&vset[1], nv, sizeof(struct vset), cmir_cmp); + /* try to increase violation by successively complementing each + variable in the subset */ + for (v = 1; v <= nv; v++) + { j = vset[v].j; + /* replace x[j] by its complement or vice versa */ + cset[j] = (char)!cset[j]; + /* construct c-MIR inequality */ + fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); + /* restore the variable */ + cset[j] = (char)!cset[j]; + /* do not replace the variable in case of failure */ + if (fail) continue; + /* compute violation */ + r = - (*beta) - (*gamma) * s; + for (k = 1; k <= n; k++) r += alpha[k] * x[k]; + if (r_best < r) r_best = r, cset[j] = (char)!cset[j]; + } + /* construct the best c-MIR inequality chosen */ + fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); + xassert(!fail); +done: /* free working arrays */ + xfree(cset); + xfree(vset); + /* return to the calling routine */ + return r_best; +} + +static double generate(glp_mir *mir) +{ /* try to generate violated c-MIR cut for modified constraint */ + int m = mir->m; + int n = mir->n; + int j, k, kk, nint; + double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma; + spv_copy_vec(mir->cut_vec, mir->mod_vec); + mir->cut_rhs = mir->mod_rhs; + /* remove small terms, which can appear due to substitution of + variable bounds */ + spv_clean_vec(mir->cut_vec, DBL_EPSILON); +#if MIR_DEBUG + spv_check_vec(mir->cut_vec); +#endif + /* remove positive continuous terms to obtain MK relaxation */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k] && mir->cut_vec->val[j] > 0.0) + mir->cut_vec->val[j] = 0.0; + } + spv_clean_vec(mir->cut_vec, 0.0); +#if MIR_DEBUG + spv_check_vec(mir->cut_vec); +#endif + /* move integer terms to the beginning of the sparse vector and + determine the number of integer variables */ + nint = 0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) + { double temp; + nint++; + /* interchange elements [nint] and [j] */ + kk = mir->cut_vec->ind[nint]; + mir->cut_vec->pos[k] = nint; + mir->cut_vec->pos[kk] = j; + mir->cut_vec->ind[nint] = k; + mir->cut_vec->ind[j] = kk; + temp = mir->cut_vec->val[nint]; + mir->cut_vec->val[nint] = mir->cut_vec->val[j]; + mir->cut_vec->val[j] = temp; + } + } +#if MIR_DEBUG + spv_check_vec(mir->cut_vec); +#endif + /* if there is no integer variable, nothing to generate */ + if (nint == 0) goto done; + /* allocate working arrays */ + u = xcalloc(1+nint, sizeof(double)); + x = xcalloc(1+nint, sizeof(double)); + alpha = xcalloc(1+nint, sizeof(double)); + /* determine u and x */ + for (j = 1; j <= nint; j++) + { k = mir->cut_vec->ind[j]; + xassert(m+1 <= k && k <= m+n); + xassert(mir->isint[k]); + u[j] = mir->ub[k] - mir->lb[k]; + xassert(u[j] >= 1.0); + if (mir->subst[k] == 'L') + x[j] = mir->x[k] - mir->lb[k]; + else if (mir->subst[k] == 'U') + x[j] = mir->ub[k] - mir->x[k]; + else + xassert(k != k); +#if 0 /* 06/III-2016; notorious bug reported many times */ + xassert(x[j] >= -0.001); +#else + if (x[j] < -0.001) + { xprintf("glp_mir_gen: warning: x[%d] = %g\n", j, x[j]); + r_best = 0.0; + goto skip; + } +#endif + if (x[j] < 0.0) x[j] = 0.0; + } + /* compute s = - sum of continuous terms */ + s = 0.0; + for (j = nint+1; j <= mir->cut_vec->nnz; j++) + { double x; + k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + /* must be continuous */ + xassert(!mir->isint[k]); + if (mir->subst[k] == 'L') + { xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); +#if 0 /* 06/III-2016; notorious bug reported many times */ + xassert(x >= -0.001); +#else + if (x < -0.001) + { xprintf("glp_mir_gen: warning: x = %g\n", x); + r_best = 0.0; + goto skip; + } +#endif + if (x < 0.0) x = 0.0; + s -= mir->cut_vec->val[j] * x; + } + xassert(s >= 0.0); + /* apply heuristic to obtain most violated c-MIR inequality */ + b = mir->cut_rhs; + r_best = cmir_sep(nint, mir->cut_vec->val, b, u, x, s, alpha, + &beta, &gamma); + if (r_best == 0.0) goto skip; + xassert(r_best > 0.0); + /* convert to raw cut */ + /* sum alpha[j] * x[j] <= beta + gamma * s */ + for (j = 1; j <= nint; j++) + mir->cut_vec->val[j] = alpha[j]; + for (j = nint+1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + if (k <= m+n) mir->cut_vec->val[j] *= gamma; + } + mir->cut_rhs = beta; +#if MIR_DEBUG + spv_check_vec(mir->cut_vec); +#endif +skip: /* free working arrays */ + xfree(u); + xfree(x); + xfree(alpha); +done: return r_best; +} + +#if MIR_DEBUG +static void check_raw_cut(glp_mir *mir, double r_best) +{ /* check raw cut before back bound substitution */ + int m = mir->m; + int n = mir->n; + int j, k, kk; + double r, big, x; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->subst[k] == 'L') + { xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + x = mir->x[k] - mir->lb[k]; + else + x = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + else if (mir->subst[k] == 'U') + { xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + x = mir->ub[k] - mir->x[k]; + else + x = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + else + xassert(k != k); + r += mir->cut_vec->val[j] * x; + if (big < fabs(mir->cut_vec->val[j])) + big = fabs(mir->cut_vec->val[j]); + } + r -= mir->cut_rhs; + if (big < fabs(mir->cut_rhs)) + big = fabs(mir->cut_rhs); + /* the residual must be close to r_best */ + xassert(fabs(r - r_best) <= 1e-6 * big); + return; +} +#endif + +static void back_subst(glp_mir *mir) +{ /* back substitution of original bounds */ + int m = mir->m; + int n = mir->n; + int j, jj, k, kk; + /* at first, restore bounds of integer variables (because on + restoring variable bounds of continuous variables we need + original, not shifted, bounds of integer variables) */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (!mir->isint[k]) continue; /* skip continuous */ + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - lb[k] */ + xassert(mir->lb[k] != -DBL_MAX); + xassert(mir->vlb[k] == 0); + mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; + } + else if (mir->subst[k] == 'U') + { /* x'[k] = ub[k] - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + xassert(mir->vub[k] == 0); + mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; + mir->cut_vec->val[j] = - mir->cut_vec->val[j]; + } + else + xassert(k != k); + } + /* now restore bounds of continuous variables */ + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (mir->isint[k]) continue; /* skip integer */ + if (mir->subst[k] == 'L') + { /* x'[k] = x[k] - (lower bound) */ + xassert(mir->lb[k] != -DBL_MAX); + kk = mir->vlb[k]; + if (kk == 0) + { /* x'[k] = x[k] - lb[k] */ + mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; + } + else + { /* x'[k] = x[k] - lb[k] * x[kk] */ + jj = mir->cut_vec->pos[kk]; +#if 0 + xassert(jj != 0); +#else + if (jj == 0) + { spv_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + xassert(jj != 0); + mir->cut_vec->val[jj] = 0.0; + } +#endif + mir->cut_vec->val[jj] -= mir->cut_vec->val[j] * + mir->lb[k]; + } + } + else if (mir->subst[k] == 'U') + { /* x'[k] = (upper bound) - x[k] */ + xassert(mir->ub[k] != +DBL_MAX); + kk = mir->vub[k]; + if (kk == 0) + { /* x'[k] = ub[k] - x[k] */ + mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; + } + else + { /* x'[k] = ub[k] * x[kk] - x[k] */ + jj = mir->cut_vec->pos[kk]; + if (jj == 0) + { spv_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + xassert(jj != 0); + mir->cut_vec->val[jj] = 0.0; + } + mir->cut_vec->val[jj] += mir->cut_vec->val[j] * + mir->ub[k]; + } + mir->cut_vec->val[j] = - mir->cut_vec->val[j]; + } + else + xassert(k != k); + } +#if MIR_DEBUG + spv_check_vec(mir->cut_vec); +#endif + return; +} + +#if MIR_DEBUG +static void check_cut_row(glp_mir *mir, double r_best) +{ /* check the cut after back bound substitution or elimination of + auxiliary variables */ + int m = mir->m; + int n = mir->n; + int j, k; + double r, big; + /* compute the residual r = sum a[k] * x[k] - b and determine + big = max(1, |a[k]|, |b|) */ + r = 0.0, big = 1.0; + for (j = 1; j <= mir->cut_vec->nnz; j++) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + r += mir->cut_vec->val[j] * mir->x[k]; + if (big < fabs(mir->cut_vec->val[j])) + big = fabs(mir->cut_vec->val[j]); + } + r -= mir->cut_rhs; + if (big < fabs(mir->cut_rhs)) + big = fabs(mir->cut_rhs); + /* the residual must be close to r_best */ + xassert(fabs(r - r_best) <= 1e-6 * big); + return; +} +#endif + +static void subst_aux_vars(glp_prob *mip, glp_mir *mir) +{ /* final substitution to eliminate auxiliary variables */ + int m = mir->m; + int n = mir->n; + GLPAIJ *aij; + int j, k, kk, jj; + for (j = mir->cut_vec->nnz; j >= 1; j--) + { k = mir->cut_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (k > m) continue; /* skip structurals */ + for (aij = mip->row[k]->ptr; aij != NULL; aij = aij->r_next) + { kk = m + aij->col->j; /* structural */ + jj = mir->cut_vec->pos[kk]; + if (jj == 0) + { spv_set_vj(mir->cut_vec, kk, 1.0); + jj = mir->cut_vec->pos[kk]; + mir->cut_vec->val[jj] = 0.0; + } + mir->cut_vec->val[jj] += mir->cut_vec->val[j] * aij->val; + } + mir->cut_vec->val[j] = 0.0; + } + spv_clean_vec(mir->cut_vec, 0.0); + return; +} + +static void add_cut(glp_mir *mir, glp_prob *pool) +{ /* add constructed cut inequality to the cut pool */ + int m = mir->m; + int n = mir->n; + int j, k, len; + int *ind = xcalloc(1+n, sizeof(int)); + double *val = xcalloc(1+n, sizeof(double)); + len = 0; + for (j = mir->cut_vec->nnz; j >= 1; j--) + { k = mir->cut_vec->ind[j]; + xassert(m+1 <= k && k <= m+n); + len++, ind[len] = k - m, val[len] = mir->cut_vec->val[j]; + } +#if 0 +#if 0 + ios_add_cut_row(tree, pool, GLP_RF_MIR, len, ind, val, GLP_UP, + mir->cut_rhs); +#else + glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP, + mir->cut_rhs); +#endif +#else + { int i; + i = glp_add_rows(pool, 1); + glp_set_row_bnds(pool, i, GLP_UP, 0, mir->cut_rhs); + glp_set_mat_row(pool, i, len, ind, val); + } +#endif + xfree(ind); + xfree(val); + return; +} + +#if 0 /* 29/II-2016 by Chris */ +static int aggregate_row(glp_prob *mip, glp_mir *mir) +#else +static int aggregate_row(glp_prob *mip, glp_mir *mir, SPV *v) +#endif +{ /* try to aggregate another row */ + int m = mir->m; + int n = mir->n; + GLPAIJ *aij; +#if 0 /* 29/II-2016 by Chris */ + SPV *v; +#endif + int ii, j, jj, k, kk, kappa = 0, ret = 0; + double d1, d2, d, d_max = 0.0; + /* choose appropriate structural variable in the aggregated row + to be substituted */ + for (j = 1; j <= mir->agg_vec->nnz; j++) + { k = mir->agg_vec->ind[j]; + xassert(1 <= k && k <= m+n); + if (k <= m) continue; /* skip auxiliary var */ + if (mir->isint[k]) continue; /* skip integer var */ + if (fabs(mir->agg_vec->val[j]) < 0.001) continue; + /* compute distance from x[k] to its lower bound */ + kk = mir->vlb[k]; + if (kk == 0) + { if (mir->lb[k] == -DBL_MAX) + d1 = DBL_MAX; + else + d1 = mir->x[k] - mir->lb[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->lb[k] != -DBL_MAX); + d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; + } + /* compute distance from x[k] to its upper bound */ + kk = mir->vub[k]; + if (kk == 0) + { if (mir->vub[k] == +DBL_MAX) + d2 = DBL_MAX; + else + d2 = mir->ub[k] - mir->x[k]; + } + else + { xassert(1 <= kk && kk <= m+n); + xassert(mir->isint[kk]); + xassert(mir->ub[k] != +DBL_MAX); + d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; + } + /* x[k] cannot be free */ + xassert(d1 != DBL_MAX || d2 != DBL_MAX); + /* d = min(d1, d2) */ + d = (d1 <= d2 ? d1 : d2); + xassert(d != DBL_MAX); + /* should not be close to corresponding bound */ + if (d < 0.001) continue; + if (d_max < d) d_max = d, kappa = k; + } + if (kappa == 0) + { /* nothing chosen */ + ret = 1; + goto done; + } + /* x[kappa] has been chosen */ + xassert(m+1 <= kappa && kappa <= m+n); + xassert(!mir->isint[kappa]); + /* find another row, which have not been used yet, to eliminate + x[kappa] from the aggregated row */ +#if 0 /* 29/II-2016 by Chris */ + for (ii = 1; ii <= m; ii++) + { if (mir->skip[ii]) continue; + for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) + if (aij->col->j == kappa - m) break; + if (aij != NULL && fabs(aij->val) >= 0.001) break; +#else + ii = 0; + for (aij = mip->col[kappa - m]->ptr; aij != NULL; + aij = aij->c_next) + { if (aij->row->i > m) continue; + if (mir->skip[aij->row->i]) continue; + if (fabs(aij->val) >= 0.001) + { ii = aij->row->i; + break; + } +#endif + } +#if 0 /* 29/II-2016 by Chris */ + if (ii > m) +#else + if (ii == 0) +#endif + { /* nothing found */ + ret = 2; + goto done; + } + /* row ii has been found; include it in the aggregated list */ + mir->agg_cnt++; + xassert(mir->agg_cnt <= MAXAGGR); + mir->agg_row[mir->agg_cnt] = ii; + mir->skip[ii] = 2; + /* v := new row */ +#if 0 /* 29/II-2016 by Chris */ + v = ios_create_vec(m+n); +#else + spv_clear_vec(v); +#endif + spv_set_vj(v, ii, 1.0); + for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) + spv_set_vj(v, m + aij->col->j, - aij->val); +#if MIR_DEBUG + spv_check_vec(v); +#endif + /* perform gaussian elimination to remove x[kappa] */ + j = mir->agg_vec->pos[kappa]; + xassert(j != 0); + jj = v->pos[kappa]; + xassert(jj != 0); + spv_linear_comb(mir->agg_vec, + - mir->agg_vec->val[j] / v->val[jj], v); +#if 0 /* 29/II-2016 by Chris */ + ios_delete_vec(v); +#endif + spv_set_vj(mir->agg_vec, kappa, 0.0); +#if MIR_DEBUG + spv_check_vec(mir->agg_vec); +#endif +done: return ret; +} + +int glp_mir_gen(glp_prob *mip, glp_mir *mir, glp_prob *pool) +{ /* main routine to generate MIR cuts */ + int m = mir->m; + int n = mir->n; + int i, nnn = 0; + double r_best; +#if 1 /* 29/II-2016 by Chris */ + SPV *work; +#endif + xassert(mip->m >= m); + xassert(mip->n == n); + /* obtain current point */ + get_current_point(mip, mir); +#if MIR_DEBUG + /* check current point */ + check_current_point(mir); +#endif + /* reset bound substitution flags */ + memset(&mir->subst[1], '?', m+n); +#if 1 /* 29/II-2016 by Chris */ + work = spv_create_vec(m+n); +#endif + /* try to generate a set of violated MIR cuts */ + for (i = 1; i <= m; i++) + { if (mir->skip[i]) continue; + /* use original i-th row as initial aggregated constraint */ + initial_agg_row(mip, mir, i); +loop: ; +#if MIR_DEBUG + /* check aggregated row */ + check_agg_row(mir); +#endif + /* substitute fixed variables into aggregated constraint */ + subst_fixed_vars(mir); +#if MIR_DEBUG + /* check aggregated row */ + check_agg_row(mir); +#endif +#if MIR_DEBUG + /* check bound substitution flags */ + { int k; + for (k = 1; k <= m+n; k++) + xassert(mir->subst[k] == '?'); + } +#endif + /* apply bound substitution heuristic */ + bound_subst_heur(mir); + /* substitute bounds and build modified constraint */ + build_mod_row(mir); +#if MIR_DEBUG + /* check modified row */ + check_mod_row(mir); +#endif + /* try to generate violated c-MIR cut for modified row */ + r_best = generate(mir); + if (r_best > 0.0) + { /* success */ +#if MIR_DEBUG + /* check raw cut before back bound substitution */ + check_raw_cut(mir, r_best); +#endif + /* back substitution of original bounds */ + back_subst(mir); +#if MIR_DEBUG + /* check the cut after back bound substitution */ + check_cut_row(mir, r_best); +#endif + /* final substitution to eliminate auxiliary variables */ + subst_aux_vars(mip, mir); +#if MIR_DEBUG + /* check the cut after elimination of auxiliaries */ + check_cut_row(mir, r_best); +#endif + /* add constructed cut inequality to the cut pool */ + add_cut(mir, pool), nnn++; + } + /* reset bound substitution flags */ + { int j, k; + for (j = 1; j <= mir->mod_vec->nnz; j++) + { k = mir->mod_vec->ind[j]; + xassert(1 <= k && k <= m+n); + xassert(mir->subst[k] != '?'); + mir->subst[k] = '?'; + } + } + if (r_best == 0.0) + { /* failure */ + if (mir->agg_cnt < MAXAGGR) + { /* try to aggregate another row */ +#if 0 /* 29/II-2016 by Chris */ + if (aggregate_row(mip, mir) == 0) goto loop; +#else + if (aggregate_row(mip, mir, work) == 0) goto loop; +#endif + } + } + /* unmark rows used in the aggregated constraint */ + { int k, ii; + for (k = 1; k <= mir->agg_cnt; k++) + { ii = mir->agg_row[k]; + xassert(1 <= ii && ii <= m); + xassert(mir->skip[ii] == 2); + mir->skip[ii] = 0; + } + } + } +#if 1 /* 29/II-2016 by Chris */ + spv_delete_vec(work); +#endif + return nnn; +} + +/*********************************************************************** +* NAME +* +* glp_mir_free - delete MIR cut generator workspace +* +* SYNOPSIS +* +* void glp_mir_free(glp_mir *mir); +* +* DESCRIPTION +* +* This routine deletes the MIR cut generator workspace and frees all +* the memory allocated to it. */ + +void glp_mir_free(glp_mir *mir) +{ xfree(mir->skip); + xfree(mir->isint); + xfree(mir->lb); + xfree(mir->vlb); + xfree(mir->ub); + xfree(mir->vub); + xfree(mir->x); + xfree(mir->agg_row); + spv_delete_vec(mir->agg_vec); + xfree(mir->subst); + spv_delete_vec(mir->mod_vec); + spv_delete_vec(mir->cut_vec); + xfree(mir); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.c b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.c new file mode 100644 index 000000000..502f3cd04 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.c @@ -0,0 +1,303 @@ +/* spv.c (operations on sparse vectors) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2007-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spv.h" + +/*********************************************************************** +* NAME +* +* spv_create_vec - create sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* SPV *spv_create_vec(int n); +* +* DESCRIPTION +* +* The routine spv_create_vec creates a sparse vector of dimension n, +* which initially is a null vector. +* +* RETURNS +* +* The routine returns a pointer to the vector created. */ + +SPV *spv_create_vec(int n) +{ SPV *v; + xassert(n >= 0); + v = xmalloc(sizeof(SPV)); + v->n = n; + v->nnz = 0; + v->pos = xcalloc(1+n, sizeof(int)); + memset(&v->pos[1], 0, n * sizeof(int)); + v->ind = xcalloc(1+n, sizeof(int)); + v->val = xcalloc(1+n, sizeof(double)); + return v; +} + +/*********************************************************************** +* NAME +* +* spv_check_vec - check that sparse vector has correct representation +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_check_vec(SPV *v); +* +* DESCRIPTION +* +* The routine spv_check_vec checks that a sparse vector specified by +* the parameter v has correct representation. +* +* NOTE +* +* Complexity of this operation is O(n). */ + +void spv_check_vec(SPV *v) +{ int j, k, nnz; + xassert(v->n >= 0); + nnz = 0; + for (j = v->n; j >= 1; j--) + { k = v->pos[j]; + xassert(0 <= k && k <= v->nnz); + if (k != 0) + { xassert(v->ind[k] == j); + nnz++; + } + } + xassert(v->nnz == nnz); + return; +} + +/*********************************************************************** +* NAME +* +* spv_get_vj - retrieve component of sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* double spv_get_vj(SPV *v, int j); +* +* RETURNS +* +* The routine spv_get_vj returns j-th component of a sparse vector +* specified by the parameter v. */ + +double spv_get_vj(SPV *v, int j) +{ int k; + xassert(1 <= j && j <= v->n); + k = v->pos[j]; + xassert(0 <= k && k <= v->nnz); + return (k == 0 ? 0.0 : v->val[k]); +} + +/*********************************************************************** +* NAME +* +* spv_set_vj - set/change component of sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_set_vj(SPV *v, int j, double val); +* +* DESCRIPTION +* +* The routine spv_set_vj assigns val to j-th component of a sparse +* vector specified by the parameter v. */ + +void spv_set_vj(SPV *v, int j, double val) +{ int k; + xassert(1 <= j && j <= v->n); + k = v->pos[j]; + if (val == 0.0) + { if (k != 0) + { /* remove j-th component */ + v->pos[j] = 0; + if (k < v->nnz) + { v->pos[v->ind[v->nnz]] = k; + v->ind[k] = v->ind[v->nnz]; + v->val[k] = v->val[v->nnz]; + } + v->nnz--; + } + } + else + { if (k == 0) + { /* create j-th component */ + k = ++(v->nnz); + v->pos[j] = k; + v->ind[k] = j; + } + v->val[k] = val; + } + return; +} + +/*********************************************************************** +* NAME +* +* spv_clear_vec - set all components of sparse vector to zero +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_clear_vec(SPV *v); +* +* DESCRIPTION +* +* The routine spv_clear_vec sets all components of a sparse vector +* specified by the parameter v to zero. */ + +void spv_clear_vec(SPV *v) +{ int k; + for (k = 1; k <= v->nnz; k++) + v->pos[v->ind[k]] = 0; + v->nnz = 0; + return; +} + +/*********************************************************************** +* NAME +* +* spv_clean_vec - remove zero or small components from sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_clean_vec(SPV *v, double eps); +* +* DESCRIPTION +* +* The routine spv_clean_vec removes zero components and components +* whose magnitude is less than eps from a sparse vector specified by +* the parameter v. If eps is 0.0, only zero components are removed. */ + +void spv_clean_vec(SPV *v, double eps) +{ int k, nnz; + nnz = 0; + for (k = 1; k <= v->nnz; k++) + { if (fabs(v->val[k]) == 0.0 || fabs(v->val[k]) < eps) + { /* remove component */ + v->pos[v->ind[k]] = 0; + } + else + { /* keep component */ + nnz++; + v->pos[v->ind[k]] = nnz; + v->ind[nnz] = v->ind[k]; + v->val[nnz] = v->val[k]; + } + } + v->nnz = nnz; + return; +} + +/*********************************************************************** +* NAME +* +* spv_copy_vec - copy sparse vector (x := y) +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_copy_vec(SPV *x, SPV *y); +* +* DESCRIPTION +* +* The routine spv_copy_vec copies a sparse vector specified by the +* parameter y to a sparse vector specified by the parameter x. */ + +void spv_copy_vec(SPV *x, SPV *y) +{ int j; + xassert(x != y); + xassert(x->n == y->n); + spv_clear_vec(x); + x->nnz = y->nnz; + memcpy(&x->ind[1], &y->ind[1], x->nnz * sizeof(int)); + memcpy(&x->val[1], &y->val[1], x->nnz * sizeof(double)); + for (j = 1; j <= x->nnz; j++) + x->pos[x->ind[j]] = j; + return; +} + +/*********************************************************************** +* NAME +* +* spv_linear_comb - compute linear combination (x := x + a * y) +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_linear_comb(SPV *x, double a, SPV *y); +* +* DESCRIPTION +* +* The routine spv_linear_comb computes the linear combination +* +* x := x + a * y, +* +* where x and y are sparse vectors, a is a scalar. */ + +void spv_linear_comb(SPV *x, double a, SPV *y) +{ int j, k; + double xj, yj; + xassert(x != y); + xassert(x->n == y->n); + for (k = 1; k <= y->nnz; k++) + { j = y->ind[k]; + xj = spv_get_vj(x, j); + yj = y->val[k]; + spv_set_vj(x, j, xj + a * yj); + } + return; +} + +/*********************************************************************** +* NAME +* +* spv_delete_vec - delete sparse vector +* +* SYNOPSIS +* +* #include "glpios.h" +* void spv_delete_vec(SPV *v); +* +* DESCRIPTION +* +* The routine spv_delete_vec deletes a sparse vector specified by the +* parameter v freeing all the memory allocated to this object. */ + +void spv_delete_vec(SPV *v) +{ /* delete sparse vector */ + xfree(v->pos); + xfree(v->ind); + xfree(v->val); + xfree(v); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.h b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.h new file mode 100644 index 000000000..d7d4699f6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/intopt/spv.h @@ -0,0 +1,83 @@ +/* spv.h (operations on sparse vectors) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2007-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPV_H +#define SPV_H + +typedef struct SPV SPV; + +struct SPV +{ /* sparse vector v = (v[j]) */ + int n; + /* dimension, n >= 0 */ + int nnz; + /* number of non-zero components, 0 <= nnz <= n */ + int *pos; /* int pos[1+n]; */ + /* pos[j] = k, 1 <= j <= n, is position of (non-zero) v[j] in the + * arrays ind and val, where 1 <= k <= nnz; pos[j] = 0 means that + * v[j] is structural zero */ + int *ind; /* int ind[1+n]; */ + /* ind[k] = j, 1 <= k <= nnz, is index of v[j] */ + double *val; /* double val[1+n]; */ + /* val[k], 1 <= k <= nnz, is a numeric value of v[j] */ +}; + +#define spv_create_vec _glp_spv_create_vec +SPV *spv_create_vec(int n); +/* create sparse vector */ + +#define spv_check_vec _glp_spv_check_vec +void spv_check_vec(SPV *v); +/* check that sparse vector has correct representation */ + +#define spv_get_vj _glp_spv_get_vj +double spv_get_vj(SPV *v, int j); +/* retrieve component of sparse vector */ + +#define spv_set_vj _glp_spv_set_vj +void spv_set_vj(SPV *v, int j, double val); +/* set/change component of sparse vector */ + +#define spv_clear_vec _glp_spv_clear_vec +void spv_clear_vec(SPV *v); +/* set all components of sparse vector to zero */ + +#define spv_clean_vec _glp_spv_clean_vec +void spv_clean_vec(SPV *v, double eps); +/* remove zero or small components from sparse vector */ + +#define spv_copy_vec _glp_spv_copy_vec +void spv_copy_vec(SPV *x, SPV *y); +/* copy sparse vector (x := y) */ + +#define spv_linear_comb _glp_spv_linear_comb +void spv_linear_comb(SPV *x, double a, SPV *y); +/* compute linear combination (x := x + a * y) */ + +#define spv_delete_vec _glp_spv_delete_vec +void spv_delete_vec(SPV *v); +/* delete sparse vector */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/minisat/LICENSE b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/LICENSE new file mode 100644 index 000000000..8a6b9f362 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/LICENSE @@ -0,0 +1,20 @@ +MiniSat -- Copyright (c) 2005, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/minisat/README b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/README new file mode 100644 index 000000000..c183c7d61 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/README @@ -0,0 +1,22 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin . +************************************************************************ +MiniSat-C v1.14.1 +======================================== + +* Fixed some serious bugs. +* Tweaked to be Visual Studio friendly (by Alan Mishchenko). + This disabled reading of gzipped DIMACS files and signal handling, + but none of these features are essential (and easy to re-enable, if + wanted). + +MiniSat-C v1.14 +======================================== + +Ok, we get it. You hate C++. You hate templates. We agree; C++ is a +seriously messed up language. Although we are more pragmatic about the +quirks and maldesigns in C++, we sympathize with you. So here is a +pure C version of MiniSat, put together by Niklas Sorensson. diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.c b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.c new file mode 100644 index 000000000..2432d650e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.c @@ -0,0 +1,1315 @@ +/* minisat.c */ + +/* Modified by Andrew Makhorin , August 2011 */ +/* May 2017: Changes were made to provide 64-bit portability; thanks to + * Chris Matrakidis for patch */ + +/*********************************************************************** +* MiniSat -- Copyright (c) 2005, Niklas Sorensson +* http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation files +* (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, +* publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +***********************************************************************/ +/* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ + +#include "env.h" +#include "minisat.h" + +#if 1 /* by mao */ +static void *ymalloc(int size) +{ void *ptr; + xassert(size > 0); + ptr = malloc(size); + if (ptr == NULL) + xerror("MiniSat: no memory available\n"); + return ptr; +} + +static void *yrealloc(void *ptr, int size) +{ xassert(size > 0); + if (ptr == NULL) + ptr = malloc(size); + else + ptr = realloc(ptr, size); + if (ptr == NULL) + xerror("MiniSat: no memory available\n"); + return ptr; +} + +static void yfree(void *ptr) +{ xassert(ptr != NULL); + free(ptr); + return; +} + +#define assert xassert +#define printf xprintf +#define fflush(f) /* nop */ +#define malloc ymalloc +#define realloc yrealloc +#define free yfree +#define inline /* empty */ +#endif + +/*====================================================================*/ +/* Debug: */ + +#if 0 +#define VERBOSEDEBUG 1 +#endif + +/* For derivation output (verbosity level 2) */ +#define L_IND "%-*d" +#define L_ind solver_dlevel(s)*3+3,solver_dlevel(s) +#define L_LIT "%sx%d" +#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) + +#if 0 /* by mao */ +/* Just like 'assert()' but expression will be evaluated in the release + version as well. */ +static inline void check(int expr) { assert(expr); } +#endif + +#if 0 /* by mao */ +static void printlits(lit* begin, lit* end) +{ + int i; + for (i = 0; i < end - begin; i++) + printf(L_LIT" ",L_lit(begin[i])); +} +#endif + +/*====================================================================*/ +/* Random numbers: */ + +/* Returns a random float 0 <= x < 1. Seed must never be 0. */ +static inline double drand(double* seed) { + int q; + *seed *= 1389796; + q = (int)(*seed / 2147483647); + *seed -= (double)q * 2147483647; + return *seed / 2147483647; } + +/* Returns a random integer 0 <= x < size. Seed must never be 0. */ +static inline int irand(double* seed, int size) { + return (int)(drand(seed) * size); } + +/*====================================================================*/ +/* Predeclarations: */ + +static void sort(void** array, int size, + int(*comp)(const void *, const void *)); + +/*====================================================================*/ +/* Clause datatype + minor functions: */ + +#if 0 /* by mao; see minisat.h */ +struct clause_t +{ + int size_learnt; + lit lits[0]; +}; +#endif + +#define clause_size(c) ((c)->size_learnt >> 1) + +#define clause_begin(c) ((c)->lits) + +#define clause_learnt(c) ((c)->size_learnt & 1) + +#define clause_activity(c) \ + (*((float*)&(c)->lits[(c)->size_learnt>>1])) + +#define clause_setactivity(c, a) \ + (void)(*((float*)&(c)->lits[(c)->size_learnt>>1]) = (a)) + +/*====================================================================*/ +/* Encode literals in clause pointers: */ + +#if 0 /* 8/I-2017 by cmatraki (64-bit portability) */ +#define clause_from_lit(l) \ + (clause*)((unsigned long)(l) + (unsigned long)(l) + 1) + +#define clause_is_lit(c) \ + ((unsigned long)(c) & 1) + +#define clause_read_lit(c) \ + (lit)((unsigned long)(c) >> 1) +#else +#define clause_from_lit(l) \ + (clause*)((size_t)(l) + (size_t)(l) + 1) + +#define clause_is_lit(c) \ + ((size_t)(c) & 1) + +#define clause_read_lit(c) \ + (lit)((size_t)(c) >> 1) +#endif + +/*====================================================================*/ +/* Simple helpers: */ + +#define solver_dlevel(s) \ + (int)veci_size(&(s)->trail_lim) + +#define solver_read_wlist(s, l) \ + (vecp *)(&(s)->wlists[l]) + +static inline void vecp_remove(vecp* v, void* e) +{ + void** ws = vecp_begin(v); + int j = 0; + + for (; ws[j] != e ; j++); + assert(j < vecp_size(v)); + for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1]; + vecp_resize(v,vecp_size(v)-1); +} + +/*====================================================================*/ +/* Variable order functions: */ + +static inline void order_update(solver* s, int v) +{ /* updateorder */ + int* orderpos = s->orderpos; + double* activity = s->activity; + int* heap = veci_begin(&s->order); + int i = orderpos[v]; + int x = heap[i]; + int parent = (i - 1) / 2; + + assert(s->orderpos[v] != -1); + + while (i != 0 && activity[x] > activity[heap[parent]]){ + heap[i] = heap[parent]; + orderpos[heap[i]] = i; + i = parent; + parent = (i - 1) / 2; + } + heap[i] = x; + orderpos[x] = i; +} + +#define order_assigned(s, v) /* nop */ + +static inline void order_unassigned(solver* s, int v) +{ /* undoorder */ + int* orderpos = s->orderpos; + if (orderpos[v] == -1){ + orderpos[v] = veci_size(&s->order); + veci_push(&s->order,v); + order_update(s,v); + } +} + +static int order_select(solver* s, float random_var_freq) +{ /* selectvar */ + int* heap; + double* activity; + int* orderpos; + + lbool* values = s->assigns; + + /* Random decision: */ + if (drand(&s->random_seed) < random_var_freq){ + int next = irand(&s->random_seed,s->size); + assert(next >= 0 && next < s->size); + if (values[next] == l_Undef) + return next; + } + + /* Activity based decision: */ + + heap = veci_begin(&s->order); + activity = s->activity; + orderpos = s->orderpos; + + while (veci_size(&s->order) > 0){ + int next = heap[0]; + int size = veci_size(&s->order)-1; + int x = heap[size]; + + veci_resize(&s->order,size); + + orderpos[next] = -1; + + if (size > 0){ + double act = activity[x]; + + int i = 0; + int child = 1; + + while (child < size){ + if (child+1 < size + && activity[heap[child]] < activity[heap[child+1]]) + child++; + + assert(child < size); + + if (act >= activity[heap[child]]) + break; + + heap[i] = heap[child]; + orderpos[heap[i]] = i; + i = child; + child = 2 * child + 1; + } + heap[i] = x; + orderpos[heap[i]] = i; + } + + if (values[next] == l_Undef) + return next; + } + + return var_Undef; +} + +/*====================================================================*/ +/* Activity functions: */ + +static inline void act_var_rescale(solver* s) { + double* activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] *= 1e-100; + s->var_inc *= 1e-100; +} + +static inline void act_var_bump(solver* s, int v) { + double* activity = s->activity; + if ((activity[v] += s->var_inc) > 1e100) + act_var_rescale(s); + + /* printf("bump %d %f\n", v-1, activity[v]); */ + + if (s->orderpos[v] != -1) + order_update(s,v); + +} + +static inline void act_var_decay(solver* s) + { s->var_inc *= s->var_decay; } + +static inline void act_clause_rescale(solver* s) { + clause** cs = (clause**)vecp_begin(&s->learnts); + int i; + for (i = 0; i < vecp_size(&s->learnts); i++){ + float a = clause_activity(cs[i]); + clause_setactivity(cs[i], a * (float)1e-20); + } + s->cla_inc *= (float)1e-20; +} + +static inline void act_clause_bump(solver* s, clause *c) { + float a = clause_activity(c) + s->cla_inc; + clause_setactivity(c,a); + if (a > 1e20) act_clause_rescale(s); +} + +static inline void act_clause_decay(solver* s) + { s->cla_inc *= s->cla_decay; } + +/*====================================================================*/ +/* Clause functions: */ + +/* pre: size > 1 && no variable occurs twice + */ +static clause* clause_new(solver* s, lit* begin, lit* end, int learnt) +{ + int size; + clause* c; + int i; + + assert(end - begin > 1); + assert(learnt >= 0 && learnt < 2); + size = end - begin; + c = (clause*)malloc(sizeof(clause) + + sizeof(lit) * size + learnt * sizeof(float)); + c->size_learnt = (size << 1) | learnt; +#if 1 /* by mao & cmatraki; non-portable check that is a fundamental \ + * assumption of minisat code: bit 0 is used as a flag (zero \ + * for pointer, one for shifted int) so allocated memory should \ + * be at least 16-bit aligned */ + assert(((size_t)c & 1) == 0); +#endif + + for (i = 0; i < size; i++) + c->lits[i] = begin[i]; + + if (learnt) + *((float*)&c->lits[size]) = 0.0; + + assert(begin[0] >= 0); + assert(begin[0] < s->size*2); + assert(begin[1] >= 0); + assert(begin[1] < s->size*2); + + assert(lit_neg(begin[0]) < s->size*2); + assert(lit_neg(begin[1]) < s->size*2); + + /* vecp_push(solver_read_wlist(s,lit_neg(begin[0])),(void*)c); */ + /* vecp_push(solver_read_wlist(s,lit_neg(begin[1])),(void*)c); */ + + vecp_push(solver_read_wlist(s,lit_neg(begin[0])), + (void*)(size > 2 ? c : clause_from_lit(begin[1]))); + vecp_push(solver_read_wlist(s,lit_neg(begin[1])), + (void*)(size > 2 ? c : clause_from_lit(begin[0]))); + + return c; +} + +static void clause_remove(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + assert(lit_neg(lits[0]) < s->size*2); + assert(lit_neg(lits[1]) < s->size*2); + + /* vecp_remove(solver_read_wlist(s,lit_neg(lits[0])),(void*)c); */ + /* vecp_remove(solver_read_wlist(s,lit_neg(lits[1])),(void*)c); */ + + assert(lits[0] < s->size*2); + vecp_remove(solver_read_wlist(s,lit_neg(lits[0])), + (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); + vecp_remove(solver_read_wlist(s,lit_neg(lits[1])), + (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0]))); + + if (clause_learnt(c)){ + s->stats.learnts--; + s->stats.learnts_literals -= clause_size(c); + }else{ + s->stats.clauses--; + s->stats.clauses_literals -= clause_size(c); + } + + free(c); +} + +static lbool clause_simplify(solver* s, clause* c) +{ + lit* lits = clause_begin(c); + lbool* values = s->assigns; + int i; + + assert(solver_dlevel(s) == 0); + + for (i = 0; i < clause_size(c); i++){ + lbool sig = !lit_sign(lits[i]); sig += sig - 1; + if (values[lit_var(lits[i])] == sig) + return l_True; + } + return l_False; +} + +/*====================================================================*/ +/* Minor (solver) functions: */ + +void solver_setnvars(solver* s,int n) +{ + int var; + + if (s->cap < n){ + + while (s->cap < n) s->cap = s->cap*2+1; + + s->wlists = (vecp*) realloc(s->wlists, + sizeof(vecp)*s->cap*2); + s->activity = (double*) realloc(s->activity, + sizeof(double)*s->cap); + s->assigns = (lbool*) realloc(s->assigns, + sizeof(lbool)*s->cap); + s->orderpos = (int*) realloc(s->orderpos, + sizeof(int)*s->cap); + s->reasons = (clause**)realloc(s->reasons, + sizeof(clause*)*s->cap); + s->levels = (int*) realloc(s->levels, + sizeof(int)*s->cap); + s->tags = (lbool*) realloc(s->tags, + sizeof(lbool)*s->cap); + s->trail = (lit*) realloc(s->trail, + sizeof(lit)*s->cap); + } + + for (var = s->size; var < n; var++){ + vecp_new(&s->wlists[2*var]); + vecp_new(&s->wlists[2*var+1]); + s->activity [var] = 0; + s->assigns [var] = l_Undef; + s->orderpos [var] = veci_size(&s->order); + s->reasons [var] = (clause*)0; + s->levels [var] = 0; + s->tags [var] = l_Undef; + + /* does not hold because variables enqueued at top level will + not be reinserted in the heap + assert(veci_size(&s->order) == var); + */ + veci_push(&s->order,var); + order_update(s, var); + } + + s->size = n > s->size ? n : s->size; +} + +static inline bool enqueue(solver* s, lit l, clause* from) +{ + lbool* values = s->assigns; + int v = lit_var(l); + lbool val = values[v]; + lbool sig; +#ifdef VERBOSEDEBUG + printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); +#endif + + /* lbool */ sig = !lit_sign(l); sig += sig - 1; + if (val != l_Undef){ + return val == sig; + }else{ + /* New fact -- store it. */ + int* levels; + clause** reasons; +#ifdef VERBOSEDEBUG + printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); +#endif + /* int* */ levels = s->levels; + /* clause** */ reasons = s->reasons; + + values [v] = sig; + levels [v] = solver_dlevel(s); + reasons[v] = from; + s->trail[s->qtail++] = l; + + order_assigned(s, v); + return true; + } +} + +static inline void assume(solver* s, lit l){ + assert(s->qtail == s->qhead); + assert(s->assigns[lit_var(l)] == l_Undef); +#ifdef VERBOSEDEBUG + printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); +#endif + veci_push(&s->trail_lim,s->qtail); + enqueue(s,l,(clause*)0); +} + +static inline void solver_canceluntil(solver* s, int level) { + lit* trail; + lbool* values; + clause** reasons; + int bound; + int c; + + if (solver_dlevel(s) <= level) + return; + + trail = s->trail; + values = s->assigns; + reasons = s->reasons; + bound = (veci_begin(&s->trail_lim))[level]; + + for (c = s->qtail-1; c >= bound; c--) { + int x = lit_var(trail[c]); + values [x] = l_Undef; + reasons[x] = (clause*)0; + } + + for (c = s->qhead-1; c >= bound; c--) + order_unassigned(s,lit_var(trail[c])); + + s->qhead = s->qtail = bound; + veci_resize(&s->trail_lim,level); +} + +static void solver_record(solver* s, veci* cls) +{ + lit* begin = veci_begin(cls); + lit* end = begin + veci_size(cls); + clause* c = (veci_size(cls) > 1) ? clause_new(s,begin,end,1) + : (clause*)0; + enqueue(s,*begin,c); + + assert(veci_size(cls) > 0); + + if (c != 0) { + vecp_push(&s->learnts,c); + act_clause_bump(s,c); + s->stats.learnts++; + s->stats.learnts_literals += veci_size(cls); + } +} + +static double solver_progress(solver* s) +{ + lbool* values = s->assigns; + int* levels = s->levels; + int i; + + double progress = 0; + double F = 1.0 / s->size; + for (i = 0; i < s->size; i++) + if (values[i] != l_Undef) + progress += pow(F, levels[i]); + return progress / s->size; +} + +/*====================================================================*/ +/* Major methods: */ + +static bool solver_lit_removable(solver* s, lit l, int minl) +{ + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int top = veci_size(&s->tagged); + + assert(lit_var(l) >= 0 && lit_var(l) < s->size); + assert(reasons[lit_var(l)] != 0); + veci_resize(&s->stack,0); + veci_push(&s->stack,lit_var(l)); + + while (veci_size(&s->stack) > 0){ + clause* c; + int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; + assert(v >= 0 && v < s->size); + veci_resize(&s->stack,veci_size(&s->stack)-1); + assert(reasons[v] != 0); + c = reasons[v]; + + if (clause_is_lit(c)){ + int v = lit_var(clause_read_lit(c)); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 + && ((1 << (levels[v] & 31)) & minl)){ + veci_push(&s->stack,v); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + int j; + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + }else{ + lit* lits = clause_begin(c); + int i, j; + + for (i = 1; i < clause_size(c); i++){ + int v = lit_var(lits[i]); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 + && ((1 << (levels[v] & 31)) & minl)){ + + veci_push(&s->stack,lit_var(lits[i])); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + } + } + } + + return true; +} + +static void solver_analyze(solver* s, clause* c, veci* learnt) +{ + lit* trail = s->trail; + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int cnt = 0; + lit p = lit_Undef; + int ind = s->qtail-1; + lit* lits; + int i, j, minl; + int* tagged; + + veci_push(learnt,lit_Undef); + + do{ + assert(c != 0); + + if (clause_is_lit(c)){ + lit q = clause_read_lit(c); + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + }else{ + + if (clause_learnt(c)) + act_clause_bump(s,c); + + lits = clause_begin(c); + /* printlits(lits,lits+clause_size(c)); printf("\n"); */ + for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ + lit q = lits[j]; + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef + && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + } + } + + while (tags[lit_var(trail[ind--])] == l_Undef); + + p = trail[ind+1]; + c = reasons[lit_var(p)]; + cnt--; + + }while (cnt > 0); + + *veci_begin(learnt) = lit_neg(p); + + lits = veci_begin(learnt); + minl = 0; + for (i = 1; i < veci_size(learnt); i++){ + int lev = levels[lit_var(lits[i])]; + minl |= 1 << (lev & 31); + } + + /* simplify (full) */ + for (i = j = 1; i < veci_size(learnt); i++){ + if (reasons[lit_var(lits[i])] == 0 + || !solver_lit_removable(s,lits[i],minl)) + lits[j++] = lits[i]; + } + + /* update size of learnt + statistics */ + s->stats.max_literals += veci_size(learnt); + veci_resize(learnt,j); + s->stats.tot_literals += j; + + /* clear tags */ + tagged = veci_begin(&s->tagged); + for (i = 0; i < veci_size(&s->tagged); i++) + tags[tagged[i]] = l_Undef; + veci_resize(&s->tagged,0); + +#ifdef DEBUG + for (i = 0; i < s->size; i++) + assert(tags[i] == l_Undef); +#endif + +#ifdef VERBOSEDEBUG + printf(L_IND"Learnt {", L_ind); + for (i = 0; i < veci_size(learnt); i++) + printf(" "L_LIT, L_lit(lits[i])); +#endif + if (veci_size(learnt) > 1){ + int max_i = 1; + int max = levels[lit_var(lits[1])]; + lit tmp; + + for (i = 2; i < veci_size(learnt); i++) + if (levels[lit_var(lits[i])] > max){ + max = levels[lit_var(lits[i])]; + max_i = i; + } + + tmp = lits[1]; + lits[1] = lits[max_i]; + lits[max_i] = tmp; + } +#ifdef VERBOSEDEBUG + { + int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; + printf(" } at level %d\n", lev); + } +#endif +} + +clause* solver_propagate(solver* s) +{ + lbool* values = s->assigns; + clause* confl = (clause*)0; + lit* lits; + + /* printf("solver_propagate\n"); */ + while (confl == 0 && s->qtail - s->qhead > 0){ + lit p = s->trail[s->qhead++]; + vecp* ws = solver_read_wlist(s,p); + clause **begin = (clause**)vecp_begin(ws); + clause **end = begin + vecp_size(ws); + clause **i, **j; + + s->stats.propagations++; + s->simpdb_props--; + + /* printf("checking lit %d: "L_LIT"\n", veci_size(ws), + L_lit(p)); */ + for (i = j = begin; i < end; ){ + if (clause_is_lit(*i)){ + *j++ = *i; + if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ + confl = s->binary; + (clause_begin(confl))[1] = lit_neg(p); + (clause_begin(confl))[0] = clause_read_lit(*i++); + + /* Copy the remaining watches: */ + while (i < end) + *j++ = *i++; + } + }else{ + lit false_lit; + lbool sig; + + lits = clause_begin(*i); + + /* Make sure the false literal is data[1]: */ + false_lit = lit_neg(p); + if (lits[0] == false_lit){ + lits[0] = lits[1]; + lits[1] = false_lit; + } + assert(lits[1] == false_lit); + /* printf("checking clause: "); + printlits(lits, lits+clause_size(*i)); + printf("\n"); */ + + /* If 0th watch is true, then clause is already + satisfied. */ + sig = !lit_sign(lits[0]); sig += sig - 1; + if (values[lit_var(lits[0])] == sig){ + *j++ = *i; + }else{ + /* Look for new watch: */ + lit* stop = lits + clause_size(*i); + lit* k; + for (k = lits + 2; k < stop; k++){ + lbool sig = lit_sign(*k); sig += sig - 1; + if (values[lit_var(*k)] != sig){ + lits[1] = *k; + *k = false_lit; + vecp_push(solver_read_wlist(s, + lit_neg(lits[1])),*i); + goto next; } + } + + *j++ = *i; + /* Clause is unit under assignment: */ + if (!enqueue(s,lits[0], *i)){ + confl = *i++; + /* Copy the remaining watches: */ + while (i < end) + *j++ = *i++; + } + } + } + next: + i++; + } + + s->stats.inspects += j - (clause**)vecp_begin(ws); + vecp_resize(ws,j - (clause**)vecp_begin(ws)); + } + + return confl; +} + +static inline int clause_cmp (const void* x, const void* y) { + return clause_size((clause*)x) > 2 + && (clause_size((clause*)y) == 2 + || clause_activity((clause*)x) + < clause_activity((clause*)y)) ? -1 : 1; } + +void solver_reducedb(solver* s) +{ + int i, j; + double extra_lim = s->cla_inc / vecp_size(&s->learnts); + /* Remove any clause below this activity */ + clause** learnts = (clause**)vecp_begin(&s->learnts); + clause** reasons = s->reasons; + + sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), clause_cmp); + + for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ + if (clause_size(learnts[i]) > 2 + && reasons[lit_var(*clause_begin(learnts[i]))] + != learnts[i]) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + for (; i < vecp_size(&s->learnts); i++){ + if (clause_size(learnts[i]) > 2 + && reasons[lit_var(*clause_begin(learnts[i]))] + != learnts[i] + && clause_activity(learnts[i]) < extra_lim) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + + /* printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); */ + + vecp_resize(&s->learnts,j); +} + +static lbool solver_search(solver* s, int nof_conflicts, + int nof_learnts) +{ + int* levels = s->levels; + double var_decay = 0.95; + double clause_decay = 0.999; + double random_var_freq = 0.02; + + int conflictC = 0; + veci learnt_clause; + + assert(s->root_level == solver_dlevel(s)); + + s->stats.starts++; + s->var_decay = (float)(1 / var_decay ); + s->cla_decay = (float)(1 / clause_decay); + veci_resize(&s->model,0); + veci_new(&learnt_clause); + + for (;;){ + clause* confl = solver_propagate(s); + if (confl != 0){ + /* CONFLICT */ + int blevel; + +#ifdef VERBOSEDEBUG + printf(L_IND"**CONFLICT**\n", L_ind); +#endif + s->stats.conflicts++; conflictC++; + if (solver_dlevel(s) == s->root_level){ + veci_delete(&learnt_clause); + return l_False; + } + + veci_resize(&learnt_clause,0); + solver_analyze(s, confl, &learnt_clause); + blevel = veci_size(&learnt_clause) > 1 + ? levels[lit_var(veci_begin(&learnt_clause)[1])] + : s->root_level; + blevel = s->root_level > blevel ? s->root_level : blevel; + solver_canceluntil(s,blevel); + solver_record(s,&learnt_clause); + act_var_decay(s); + act_clause_decay(s); + + }else{ + /* NO CONFLICT */ + int next; + + if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ + /* Reached bound on number of conflicts: */ + s->progress_estimate = solver_progress(s); + solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; } + + if (solver_dlevel(s) == 0) + /* Simplify the set of problem clauses: */ + solver_simplify(s); + + if (nof_learnts >= 0 + && vecp_size(&s->learnts) - s->qtail >= nof_learnts) + /* Reduce the set of learnt clauses: */ + solver_reducedb(s); + + /* New variable decision: */ + s->stats.decisions++; + next = order_select(s,(float)random_var_freq); + + if (next == var_Undef){ + /* Model found: */ + lbool* values = s->assigns; + int i; + for (i = 0; i < s->size; i++) + veci_push(&s->model,(int)values[i]); + solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + + /* + veci apa; veci_new(&apa); + for (i = 0; i < s->size; i++) + veci_push(&apa,(int)(s->model.ptr[i] == l_True + ? toLit(i) : lit_neg(toLit(i)))); + printf("model: "); + printlits((lit*)apa.ptr, + (lit*)apa.ptr + veci_size(&apa)); printf("\n"); + veci_delete(&apa); + */ + + return l_True; + } + + assume(s,lit_neg(toLit(next))); + } + } + +#if 0 /* by mao; unreachable code */ + return l_Undef; /* cannot happen */ +#endif +} + +/*====================================================================*/ +/* External solver functions: */ + +solver* solver_new(void) +{ + solver* s = (solver*)malloc(sizeof(solver)); + + /* initialize vectors */ + vecp_new(&s->clauses); + vecp_new(&s->learnts); + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); + veci_new(&s->stack); + veci_new(&s->model); + + /* initialize arrays */ + s->wlists = 0; + s->activity = 0; + s->assigns = 0; + s->orderpos = 0; + s->reasons = 0; + s->levels = 0; + s->tags = 0; + s->trail = 0; + + /* initialize other vars */ + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + s->cla_inc = 1; + s->cla_decay = 1; + s->var_inc = 1; + s->var_decay = 1; + s->root_level = 0; + s->simpdb_assigns = 0; + s->simpdb_props = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; + s->binary = (clause*)malloc(sizeof(clause) + + sizeof(lit)*2); + s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.max_literals = 0; + s->stats.tot_literals = 0; + + return s; +} + +void solver_delete(solver* s) +{ + int i; + for (i = 0; i < vecp_size(&s->clauses); i++) + free(vecp_begin(&s->clauses)[i]); + + for (i = 0; i < vecp_size(&s->learnts); i++) + free(vecp_begin(&s->learnts)[i]); + + /* delete vectors */ + vecp_delete(&s->clauses); + vecp_delete(&s->learnts); + veci_delete(&s->order); + veci_delete(&s->trail_lim); + veci_delete(&s->tagged); + veci_delete(&s->stack); + veci_delete(&s->model); + free(s->binary); + + /* delete arrays */ + if (s->wlists != 0){ + int i; + for (i = 0; i < s->size*2; i++) + vecp_delete(&s->wlists[i]); + + /* if one is different from null, all are */ + free(s->wlists); + free(s->activity ); + free(s->assigns ); + free(s->orderpos ); + free(s->reasons ); + free(s->levels ); + free(s->trail ); + free(s->tags ); + } + + free(s); +} + +bool solver_addclause(solver* s, lit* begin, lit* end) +{ + lit *i,*j; + int maxvar; + lbool* values; + lit last; + + if (begin == end) return false; + + /* printlits(begin,end); printf("\n"); */ + /* insertion sort */ + maxvar = lit_var(*begin); + for (i = begin + 1; i < end; i++){ + lit l = *i; + maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; + for (j = i; j > begin && *(j-1) > l; j--) + *j = *(j-1); + *j = l; + } + solver_setnvars(s,maxvar+1); + + /* printlits(begin,end); printf("\n"); */ + values = s->assigns; + + /* delete duplicates */ + last = lit_Undef; + for (i = j = begin; i < end; i++){ + /* printf("lit: "L_LIT", value = %d\n", L_lit(*i), + (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); */ + lbool sig = !lit_sign(*i); sig += sig - 1; + if (*i == lit_neg(last) || sig == values[lit_var(*i)]) + return true; /* tautology */ + else if (*i != last && values[lit_var(*i)] == l_Undef) + last = *j++ = *i; + } + + /* printf("final: "); printlits(begin,j); printf("\n"); */ + + if (j == begin) /* empty clause */ + return false; + else if (j - begin == 1) /* unit clause */ + return enqueue(s,*begin,(clause*)0); + + /* create new clause */ + vecp_push(&s->clauses,clause_new(s,begin,j,0)); + + s->stats.clauses++; + s->stats.clauses_literals += j - begin; + + return true; +} + +bool solver_simplify(solver* s) +{ + clause** reasons; + int type; + + assert(solver_dlevel(s) == 0); + + if (solver_propagate(s) != 0) + return false; + + if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) + return true; + + reasons = s->reasons; + for (type = 0; type < 2; type++){ + vecp* cs = type ? &s->learnts : &s->clauses; + clause** cls = (clause**)vecp_begin(cs); + + int i, j; + for (j = i = 0; i < vecp_size(cs); i++){ + if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && + clause_simplify(s,cls[i]) == l_True) + clause_remove(s,cls[i]); + else + cls[j++] = cls[i]; + } + vecp_resize(cs,j); + } + + s->simpdb_assigns = s->qhead; + /* (shouldn't depend on 'stats' really, but it will do for now) */ + s->simpdb_props = (int)(s->stats.clauses_literals + + s->stats.learnts_literals); + + return true; +} + +bool solver_solve(solver* s, lit* begin, lit* end) +{ + double nof_conflicts = 100; + double nof_learnts = solver_nclauses(s) / 3; + lbool status = l_Undef; + lbool* values = s->assigns; + lit* i; + + /* printf("solve: "); printlits(begin, end); printf("\n"); */ + for (i = begin; i < end; i++){ + switch (lit_sign(*i) ? -values[lit_var(*i)] + : values[lit_var(*i)]){ + case 1: /* l_True: */ + break; + case 0: /* l_Undef */ + assume(s, *i); + if (solver_propagate(s) == NULL) + break; + /* falltrough */ + case -1: /* l_False */ + solver_canceluntil(s, 0); + return false; + } + } + + s->root_level = solver_dlevel(s); + + if (s->verbosity >= 1){ + printf("==================================[MINISAT]============" + "=======================\n"); + printf("| Conflicts | ORIGINAL | LEARNT " + " | Progress |\n"); + printf("| | Clauses Literals | Limit Clauses Litera" + "ls Lit/Cl | |\n"); + printf("=======================================================" + "=======================\n"); + } + + while (status == l_Undef){ + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; + + if (s->verbosity >= 1){ + printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %" + "6.3f %% |\n", + (double)s->stats.conflicts, + (double)s->stats.clauses, + (double)s->stats.clauses_literals, + (double)nof_learnts, + (double)s->stats.learnts, + (double)s->stats.learnts_literals, + Ratio, + s->progress_estimate*100); + fflush(stdout); + } + status = solver_search(s,(int)nof_conflicts, (int)nof_learnts); + nof_conflicts *= 1.5; + nof_learnts *= 1.1; + } + if (s->verbosity >= 1) + printf("=======================================================" + "=======================\n"); + + solver_canceluntil(s,0); + return status != l_False; +} + +int solver_nvars(solver* s) +{ + return s->size; +} + +int solver_nclauses(solver* s) +{ + return vecp_size(&s->clauses); +} + +int solver_nconflicts(solver* s) +{ + return (int)s->stats.conflicts; +} + +/*====================================================================*/ +/* Sorting functions (sigh): */ + +static inline void selectionsort(void** array, int size, + int(*comp)(const void *, const void *)) +{ + int i, j, best_i; + void* tmp; + + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (comp(array[j], array[best_i]) < 0) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} + +static void sortrnd(void** array, int size, + int(*comp)(const void *, const void *), + double* seed) +{ + if (size <= 15) + selectionsort(array, size, comp); + + else{ + void* pivot = array[irand(seed, size)]; + void* tmp; + int i = -1; + int j = size; + + for(;;){ + do i++; while(comp(array[i], pivot)<0); + do j--; while(comp(pivot, array[j])<0); + + if (i >= j) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + + sortrnd(array , i , comp, seed); + sortrnd(&array[i], size-i, comp, seed); + } +} + +static void sort(void** array, int size, + int(*comp)(const void *, const void *)) +{ + double seed = 91648253; + sortrnd(array,size,comp,&seed); +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.h b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.h new file mode 100644 index 000000000..2733e8d63 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/minisat/minisat.h @@ -0,0 +1,230 @@ +/* minisat.h */ + +/* Modified by Andrew Makhorin , August 2011 */ + +/*********************************************************************** +* MiniSat -- Copyright (c) 2005, Niklas Sorensson +* http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ +* +* Permission is hereby granted, free of charge, to any person +* obtaining a copy of this software and associated documentation files +* (the "Software"), to deal in the Software without restriction, +* including without limitation the rights to use, copy, modify, merge, +* publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, +* subject to the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +***********************************************************************/ +/* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ + +#ifndef MINISAT_H +#define MINISAT_H + +/*====================================================================*/ +/* Simple types: */ + +typedef int bool; + +#define true 1 +#define false 0 + +typedef int lit; +#if 0 /* by mao */ +typedef char lbool; +#else +typedef int lbool; +#endif + +#define var_Undef (int)(-1) +#define lit_Undef (lit)(-2) + +#define l_Undef (lbool)0 +#define l_True (lbool)1 +#define l_False (lbool)(-1) + +#define toLit(v) (lit)((v) + (v)) +#define lit_neg(l) (lit)((l) ^ 1) +#define lit_var(l) (int)((l) >> 1) +#define lit_sign(l) (int)((l) & 1) + +/*====================================================================*/ +/* Vectors: */ + +/* vector of 32-bit intergers (added for 64-bit portability) */ +typedef struct /* veci_t */ { + int size; + int cap; + int* ptr; +} veci; + +#define veci_new(v) \ +{ (v)->size = 0; \ + (v)->cap = 4; \ + (v)->ptr = (int*)malloc(sizeof(int)*(v)->cap); \ +} + +#define veci_delete(v) free((v)->ptr) + +#define veci_begin(v) ((v)->ptr) + +#define veci_size(v) ((v)->size) + +#define veci_resize(v, k) (void)((v)->size = (k)) +/* only safe to shrink !! */ + +#define veci_push(v, e) \ +{ if ((v)->size == (v)->cap) \ + { int newsize = (v)->cap * 2+1; \ + (v)->ptr = (int*)realloc((v)->ptr,sizeof(int)*newsize); \ + (v)->cap = newsize; \ + } \ + (v)->ptr[(v)->size++] = (e); \ +} + +/* vector of 32- or 64-bit pointers */ +typedef struct /* vecp_t */ { + int size; + int cap; + void** ptr; +} vecp; + +#define vecp_new(v) \ +{ (v)->size = 0; \ + (v)->cap = 4; \ + (v)->ptr = (void**)malloc(sizeof(void*)*(v)->cap); \ +} + +#define vecp_delete(v) free((v)->ptr) + +#define vecp_begin(v) ((v)->ptr) + +#define vecp_size(v) ((v)->size) + +#define vecp_resize(v, k) (void)((v)->size = (k)) +/* only safe to shrink !! */ + +#define vecp_push(v, e) \ +{ if ((v)->size == (v)->cap) \ + { int newsize = (v)->cap * 2+1; \ + (v)->ptr = (void**)realloc((v)->ptr,sizeof(void*)*newsize); \ + (v)->cap = newsize; \ + } \ + (v)->ptr[(v)->size++] = (e); \ +} + +/*====================================================================*/ +/* Solver representation: */ + +typedef struct /* clause_t */ +{ + int size_learnt; + lit lits[1]; +} clause; + +typedef struct /* stats_t */ +{ + double starts, decisions, propagations, inspects, conflicts; + double clauses, clauses_literals, learnts, learnts_literals, + max_literals, tot_literals; +} stats; + +typedef struct /* solver_t */ +{ + int size; /* nof variables */ + int cap; /* size of varmaps */ + int qhead; /* Head index of queue. */ + int qtail; /* Tail index of queue. */ + + /* clauses */ + vecp clauses; /* List of problem constraints. + (contains: clause*) */ + vecp learnts; /* List of learnt clauses. + (contains: clause*) */ + + /* activities */ + double var_inc; /* Amount to bump next variable with. */ + double var_decay; /* INVERSE decay factor for variable + activity: stores 1/decay. */ + float cla_inc; /* Amount to bump next clause with. */ + float cla_decay; /* INVERSE decay factor for clause + activity: stores 1/decay. */ + + vecp* wlists; + double* activity; /* A heuristic measurement of the activity + of a variable. */ + lbool* assigns; /* Current values of variables. */ + int* orderpos; /* Index in variable order. */ + clause** reasons; + int* levels; + lit* trail; + + clause* binary; /* A temporary binary clause */ + lbool* tags; + veci tagged; /* (contains: var) */ + veci stack; /* (contains: var) */ + + veci order; /* Variable order. (heap) (contains: var) */ + veci trail_lim; /* Separator indices for different decision + levels in 'trail'. (contains: int) */ + veci model; /* If problem is solved, this vector + contains the model (contains: lbool). */ + + int root_level; /* Level of first proper decision. */ + int simpdb_assigns;/* Number of top-level assignments at last + 'simplifyDB()'. */ + int simpdb_props; /* Number of propagations before next + 'simplifyDB()'. */ + double random_seed; + double progress_estimate; + int verbosity; /* Verbosity level. + 0=silent, + 1=some progress report, + 2=everything */ + + stats stats; +} solver; + +/*====================================================================*/ +/* Public interface: */ + +#if 1 /* by mao; to keep namespace clean */ +#define solver_new _glp_minisat_new +#define solver_delete _glp_minisat_delete +#define solver_addclause _glp_minisat_addclause +#define solver_simplify _glp_minisat_simplify +#define solver_solve _glp_minisat_solve +#define solver_nvars _glp_minisat_nvars +#define solver_nclauses _glp_minisat_nclauses +#define solver_nconflicts _glp_minisat_nconflicts +#define solver_setnvars _glp_minisat_setnvars +#define solver_propagate _glp_minisat_propagate +#define solver_reducedb _glp_minisat_reducedb +#endif + +solver* solver_new(void); +void solver_delete(solver* s); + +bool solver_addclause(solver* s, lit* begin, lit* end); +bool solver_simplify(solver* s); +bool solver_solve(solver* s, lit* begin, lit* end); + +int solver_nvars(solver* s); +int solver_nclauses(solver* s); +int solver_nconflicts(solver* s); + +void solver_setnvars(solver* s,int n); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.c new file mode 100644 index 000000000..c97cf13af --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.c @@ -0,0 +1,405 @@ +/* avl.c (binary search tree) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "avl.h" +#include "dmp.h" +#include "env.h" + +struct AVL +{ /* AVL tree (Adelson-Velsky & Landis binary search tree) */ + DMP *pool; + /* memory pool for allocating nodes */ + AVLNODE *root; + /* pointer to the root node */ + int (*fcmp)(void *info, const void *key1, const void *key2); + /* application-defined key comparison routine */ + void *info; + /* transit pointer passed to the routine fcmp */ + int size; + /* the tree size (the total number of nodes) */ + int height; + /* the tree height */ +}; + +struct AVLNODE +{ /* node of AVL tree */ + const void *key; + /* pointer to the node key (data structure for representing keys + is supplied by the application) */ + int rank; + /* node rank = relative position of the node in its own subtree = + the number of nodes in the left subtree plus one */ + int type; + /* reserved for the application specific information */ + void *link; + /* reserved for the application specific information */ + AVLNODE *up; + /* pointer to the parent node */ + short int flag; + /* node flag: + 0 - this node is the left child of its parent (or this node is + the root of the tree and has no parent) + 1 - this node is the right child of its parent */ + short int bal; + /* node balance = the difference between heights of the right and + left subtrees: + -1 - the left subtree is higher than the right one; + 0 - the left and right subtrees have the same height; + +1 - the left subtree is lower than the right one */ + AVLNODE *left; + /* pointer to the root of the left subtree */ + AVLNODE *right; + /* pointer to the root of the right subtree */ +}; + +AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, + const void *key2), void *info) +{ /* create AVL tree */ + AVL *tree; + tree = xmalloc(sizeof(AVL)); + tree->pool = dmp_create_pool(); + tree->root = NULL; + tree->fcmp = fcmp; + tree->info = info; + tree->size = 0; + tree->height = 0; + return tree; +} + +int avl_strcmp(void *info, const void *key1, const void *key2) +{ /* compare character string keys */ + xassert(info == info); + return strcmp(key1, key2); +} + +static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node); + +AVLNODE *avl_insert_node(AVL *tree, const void *key) +{ /* insert new node into AVL tree */ + AVLNODE *p, *q, *r; + short int flag; + /* find an appropriate point for insertion */ + p = NULL; q = tree->root; + while (q != NULL) + { p = q; + if (tree->fcmp(tree->info, key, p->key) <= 0) + { flag = 0; + q = p->left; + p->rank++; + } + else + { flag = 1; + q = p->right; + } + } + /* create new node and insert it into the tree */ + r = dmp_get_atom(tree->pool, sizeof(AVLNODE)); + r->key = key; r->type = 0; r->link = NULL; + r->rank = 1; r->up = p; + r->flag = (short int)(p == NULL ? 0 : flag); + r->bal = 0; r->left = NULL; r->right = NULL; + tree->size++; + if (p == NULL) + tree->root = r; + else + if (flag == 0) p->left = r; else p->right = r; + /* go upstairs to the root and correct all subtrees affected by + insertion */ + while (p != NULL) + { if (flag == 0) + { /* the height of the left subtree of [p] is increased */ + if (p->bal > 0) + { p->bal = 0; + break; + } + if (p->bal < 0) + { rotate_subtree(tree, p); + break; + } + p->bal = -1; flag = p->flag; p = p->up; + } + else + { /* the height of the right subtree of [p] is increased */ + if (p->bal < 0) + { p->bal = 0; + break; + } + if (p->bal > 0) + { rotate_subtree(tree, p); + break; + } + p->bal = +1; flag = p->flag; p = p->up; + } + } + /* if the root has been reached, the height of the entire tree is + increased */ + if (p == NULL) tree->height++; + return r; +} + +void avl_set_node_type(AVLNODE *node, int type) +{ /* assign the type field of specified node */ + node->type = type; + return; +} + +void avl_set_node_link(AVLNODE *node, void *link) +{ /* assign the link field of specified node */ + node->link = link; + return; +} + +AVLNODE *avl_find_node(AVL *tree, const void *key) +{ /* find node in AVL tree */ + AVLNODE *p; + int c; + p = tree->root; + while (p != NULL) + { c = tree->fcmp(tree->info, key, p->key); + if (c == 0) break; + p = (c < 0 ? p->left : p->right); + } + return p; +} + +int avl_get_node_type(AVLNODE *node) +{ /* retrieve the type field of specified node */ + return node->type; +} + +void *avl_get_node_link(AVLNODE *node) +{ /* retrieve the link field of specified node */ + return node->link; +} + +static AVLNODE *find_next_node(AVL *tree, AVLNODE *node) +{ /* find next node in AVL tree */ + AVLNODE *p, *q; + if (tree->root == NULL) return NULL; + p = node; + q = (p == NULL ? tree->root : p->right); + if (q == NULL) + { /* go upstairs from the left subtree */ + for (;;) + { q = p->up; + if (q == NULL) break; + if (p->flag == 0) break; + p = q; + } + } + else + { /* go downstairs into the right subtree */ + for (;;) + { p = q->left; + if (p == NULL) break; + q = p; + } + } + return q; +} + +void avl_delete_node(AVL *tree, AVLNODE *node) +{ /* delete specified node from AVL tree */ + AVLNODE *f, *p, *q, *r, *s, *x, *y; + short int flag; + p = node; + /* if both subtrees of the specified node are non-empty, the node + should be interchanged with the next one, at least one subtree + of which is always empty */ + if (p->left == NULL || p->right == NULL) goto skip; + f = p->up; q = p->left; + r = find_next_node(tree, p); s = r->right; + if (p->right == r) + { if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + r->rank = p->rank; r->up = f; + r->flag = p->flag; r->bal = p->bal; + r->left = q; r->right = p; + q->up = r; + p->rank = 1; p->up = r; p->flag = 1; + p->bal = (short int)(s == NULL ? 0 : +1); + p->left = NULL; p->right = s; + if (s != NULL) s->up = p; + } + else + { x = p->right; y = r->up; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + r->rank = p->rank; r->up = f; + r->flag = p->flag; r->bal = p->bal; + r->left = q; r->right = x; + q->up = r; x->up = r; y->left = p; + p->rank = 1; p->up = y; p->flag = 0; + p->bal = (short int)(s == NULL ? 0 : +1); + p->left = NULL; p->right = s; + if (s != NULL) s->up = p; + } +skip: /* now the specified node [p] has at least one empty subtree; + go upstairs to the root and adjust the rank field of all nodes + affected by deletion */ + q = p; f = q->up; + while (f != NULL) + { if (q->flag == 0) f->rank--; + q = f; f = q->up; + } + /* delete the specified node from the tree */ + f = p->up; flag = p->flag; + q = p->left != NULL ? p->left : p->right; + if (f == NULL) + tree->root = q; + else + if (flag == 0) f->left = q; else f->right = q; + if (q != NULL) q->up = f, q->flag = flag; + tree->size--; + /* go upstairs to the root and correct all subtrees affected by + deletion */ + while (f != NULL) + { if (flag == 0) + { /* the height of the left subtree of [f] is decreased */ + if (f->bal == 0) + { f->bal = +1; + break; + } + if (f->bal < 0) + f->bal = 0; + else + { f = rotate_subtree(tree, f); + if (f->bal < 0) break; + } + flag = f->flag; f = f->up; + } + else + { /* the height of the right subtree of [f] is decreased */ + if (f->bal == 0) + { f->bal = -1; + break; + } + if (f->bal > 0) + f->bal = 0; + else + { f = rotate_subtree(tree, f); + if (f->bal > 0) break; + } + flag = f->flag; f = f->up; + } + } + /* if the root has been reached, the height of the entire tree is + decreased */ + if (f == NULL) tree->height--; + /* returns the deleted node to the memory pool */ + dmp_free_atom(tree->pool, p, sizeof(AVLNODE)); + return; +} + +static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node) +{ /* restore balance of AVL subtree */ + AVLNODE *f, *p, *q, *r, *x, *y; + xassert(node != NULL); + p = node; + if (p->bal < 0) + { /* perform negative (left) rotation */ + f = p->up; q = p->left; r = q->right; + if (q->bal <= 0) + { /* perform single negative rotation */ + if (f == NULL) + tree->root = q; + else + if (p->flag == 0) f->left = q; else f->right = q; + p->rank -= q->rank; + q->up = f; q->flag = p->flag; q->bal++; q->right = p; + p->up = q; p->flag = 1; + p->bal = (short int)(-q->bal); p->left = r; + if (r != NULL) r->up = p, r->flag = 0; + node = q; + } + else + { /* perform double negative rotation */ + x = r->left; y = r->right; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + p->rank -= (q->rank + r->rank); + r->rank += q->rank; + p->bal = (short int)(r->bal >= 0 ? 0 : +1); + q->bal = (short int)(r->bal <= 0 ? 0 : -1); + r->up = f; r->flag = p->flag; r->bal = 0; + r->left = q; r->right = p; + p->up = r; p->flag = 1; p->left = y; + q->up = r; q->flag = 0; q->right = x; + if (x != NULL) x->up = q, x->flag = 1; + if (y != NULL) y->up = p, y->flag = 0; + node = r; + } + } + else + { /* perform positive (right) rotation */ + f = p->up; q = p->right; r = q->left; + if (q->bal >= 0) + { /* perform single positive rotation */ + if (f == NULL) + tree->root = q; + else + if (p->flag == 0) f->left = q; else f->right = q; + q->rank += p->rank; + q->up = f; q->flag = p->flag; q->bal--; q->left = p; + p->up = q; p->flag = 0; + p->bal = (short int)(-q->bal); p->right = r; + if (r != NULL) r->up = p, r->flag = 1; + node = q; + } + else + { /* perform double positive rotation */ + x = r->left; y = r->right; + if (f == NULL) + tree->root = r; + else + if (p->flag == 0) f->left = r; else f->right = r; + q->rank -= r->rank; + r->rank += p->rank; + p->bal = (short int)(r->bal <= 0 ? 0 : -1); + q->bal = (short int)(r->bal >= 0 ? 0 : +1); + r->up = f; r->flag = p->flag; r->bal = 0; + r->left = p; r->right = q; + p->up = r; p->flag = 0; p->right = x; + q->up = r; q->flag = 1; q->left = y; + if (x != NULL) x->up = p, x->flag = 1; + if (y != NULL) y->up = q, y->flag = 0; + node = r; + } + } + return node; +} + +void avl_delete_tree(AVL *tree) +{ /* delete AVL tree */ + dmp_delete_pool(tree->pool); + xfree(tree); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.h new file mode 100644 index 000000000..b0aaef61e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/avl.h @@ -0,0 +1,73 @@ +/* avl.h (binary search tree) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef AVL_H +#define AVL_H + +typedef struct AVL AVL; +typedef struct AVLNODE AVLNODE; + +#define avl_create_tree _glp_avl_create_tree +AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, + const void *key2), void *info); +/* create AVL tree */ + +#define avl_strcmp _glp_avl_strcmp +int avl_strcmp(void *info, const void *key1, const void *key2); +/* compare character string keys */ + +#define avl_insert_node _glp_avl_insert_node +AVLNODE *avl_insert_node(AVL *tree, const void *key); +/* insert new node into AVL tree */ + +#define avl_set_node_type _glp_avl_set_node_type +void avl_set_node_type(AVLNODE *node, int type); +/* assign the type field of specified node */ + +#define avl_set_node_link _glp_avl_set_node_link +void avl_set_node_link(AVLNODE *node, void *link); +/* assign the link field of specified node */ + +#define avl_find_node _glp_avl_find_node +AVLNODE *avl_find_node(AVL *tree, const void *key); +/* find node in AVL tree */ + +#define avl_get_node_type _glp_avl_get_node_type +int avl_get_node_type(AVLNODE *node); +/* retrieve the type field of specified node */ + +#define avl_get_node_link _glp_avl_get_node_link +void *avl_get_node_link(AVLNODE *node); +/* retrieve the link field of specified node */ + +#define avl_delete_node _glp_avl_delete_node +void avl_delete_node(AVL *tree, AVLNODE *node); +/* delete specified node from AVL tree */ + +#define avl_delete_tree _glp_avl_delete_tree +void avl_delete_tree(AVL *tree); +/* delete AVL tree */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.c new file mode 100644 index 000000000..540dd9fdd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.c @@ -0,0 +1,286 @@ +/* bignum.c (bignum arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "bignum.h" + +/*********************************************************************** +* Two routines below are intended to multiply and divide unsigned +* integer numbers of arbitrary precision. +* +* The routines assume that an unsigned integer number is represented in +* the positional numeral system with the base 2^16 = 65536, i.e. each +* "digit" of the number is in the range [0, 65535] and represented as +* a 16-bit value of the unsigned short type. In other words, a number x +* has the following representation: +* +* n-1 +* x = sum d[j] * 65536^j, +* j=0 +* +* where n is the number of places (positions), and d[j] is j-th "digit" +* of x, 0 <= d[j] <= 65535. +***********************************************************************/ + +/*********************************************************************** +* NAME +* +* bigmul - multiply unsigned integer numbers of arbitrary precision +* +* SYNOPSIS +* +* #include "bignum.h" +* void bigmul(int n, int m, unsigned short x[], unsigned short y[]); +* +* DESCRIPTION +* +* The routine bigmul multiplies unsigned integer numbers of arbitrary +* precision. +* +* n is the number of digits of multiplicand, n >= 1; +* +* m is the number of digits of multiplier, m >= 1; +* +* x is an array containing digits of the multiplicand in elements +* x[m], x[m+1], ..., x[n+m-1]. Contents of x[0], x[1], ..., x[m-1] are +* ignored on entry. +* +* y is an array containing digits of the multiplier in elements y[0], +* y[1], ..., y[m-1]. +* +* On exit digits of the product are stored in elements x[0], x[1], ..., +* x[n+m-1]. The array y is not changed. */ + +void bigmul(int n, int m, unsigned short x[], unsigned short y[]) +{ int i, j; + unsigned int t; + xassert(n >= 1); + xassert(m >= 1); + for (j = 0; j < m; j++) x[j] = 0; + for (i = 0; i < n; i++) + { if (x[i+m]) + { t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)x[i+m] * (unsigned int)y[j] + + (unsigned int)x[i+j]; + x[i+j] = (unsigned short)t; + t >>= 16; + } + x[i+m] = (unsigned short)t; + } + } + return; +} + +/*********************************************************************** +* NAME +* +* bigdiv - divide unsigned integer numbers of arbitrary precision +* +* SYNOPSIS +* +* #include "bignum.h" +* void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); +* +* DESCRIPTION +* +* The routine bigdiv divides one unsigned integer number of arbitrary +* precision by another with the algorithm described in [1]. +* +* n is the difference between the number of digits of dividend and the +* number of digits of divisor, n >= 0. +* +* m is the number of digits of divisor, m >= 1. +* +* x is an array containing digits of the dividend in elements x[0], +* x[1], ..., x[n+m-1]. +* +* y is an array containing digits of the divisor in elements y[0], +* y[1], ..., y[m-1]. The highest digit y[m-1] must be non-zero. +* +* On exit n+1 digits of the quotient are stored in elements x[m], +* x[m+1], ..., x[n+m], and m digits of the remainder are stored in +* elements x[0], x[1], ..., x[m-1]. The array y is changed but then +* restored. +* +* REFERENCES +* +* 1. D. Knuth. The Art of Computer Programming. Vol. 2: Seminumerical +* Algorithms. Stanford University, 1969. */ + +void bigdiv(int n, int m, unsigned short x[], unsigned short y[]) +{ int i, j; + unsigned int t; + unsigned short d, q, r; + xassert(n >= 0); + xassert(m >= 1); + xassert(y[m-1] != 0); + /* special case when divisor has the only digit */ + if (m == 1) + { d = 0; + for (i = n; i >= 0; i--) + { t = ((unsigned int)d << 16) + (unsigned int)x[i]; + x[i+1] = (unsigned short)(t / y[0]); + d = (unsigned short)(t % y[0]); + } + x[0] = d; + goto done; + } + /* multiply dividend and divisor by a normalizing coefficient in + * order to provide the condition y[m-1] >= base / 2 */ + d = (unsigned short)(0x10000 / ((unsigned int)y[m-1] + 1)); + if (d == 1) + x[n+m] = 0; + else + { t = 0; + for (i = 0; i < n+m; i++) + { t += (unsigned int)x[i] * (unsigned int)d; + x[i] = (unsigned short)t; + t >>= 16; + } + x[n+m] = (unsigned short)t; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)y[j] * (unsigned int)d; + y[j] = (unsigned short)t; + t >>= 16; + } + } + /* main loop */ + for (i = n; i >= 0; i--) + { /* estimate and correct the current digit of quotient */ + if (x[i+m] < y[m-1]) + { t = ((unsigned int)x[i+m] << 16) + (unsigned int)x[i+m-1]; + q = (unsigned short)(t / (unsigned int)y[m-1]); + r = (unsigned short)(t % (unsigned int)y[m-1]); + if (q == 0) goto putq; else goto test; + } + q = 0; + r = x[i+m-1]; +decr: q--; /* if q = 0 then q-- = 0xFFFF */ + t = (unsigned int)r + (unsigned int)y[m-1]; + r = (unsigned short)t; + if (t > 0xFFFF) goto msub; +test: t = (unsigned int)y[m-2] * (unsigned int)q; + if ((unsigned short)(t >> 16) > r) goto decr; + if ((unsigned short)(t >> 16) < r) goto msub; + if ((unsigned short)t > x[i+m-2]) goto decr; +msub: /* now subtract divisor multiplied by the current digit of + * quotient from the current dividend */ + if (q == 0) goto putq; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)y[j] * (unsigned int)q; + if (x[i+j] < (unsigned short)t) t += 0x10000; + x[i+j] -= (unsigned short)t; + t >>= 16; + } + if (x[i+m] >= (unsigned short)t) goto putq; + /* perform correcting addition, because the current digit of + * quotient is greater by one than its correct value */ + q--; + t = 0; + for (j = 0; j < m; j++) + { t += (unsigned int)x[i+j] + (unsigned int)y[j]; + x[i+j] = (unsigned short)t; + t >>= 16; + } +putq: /* store the current digit of quotient */ + x[i+m] = q; + } + /* divide divisor and remainder by the normalizing coefficient in + * order to restore their original values */ + if (d > 1) + { t = 0; + for (i = m-1; i >= 0; i--) + { t = (t << 16) + (unsigned int)x[i]; + x[i] = (unsigned short)(t / (unsigned int)d); + t %= (unsigned int)d; + } + t = 0; + for (j = m-1; j >= 0; j--) + { t = (t << 16) + (unsigned int)y[j]; + y[j] = (unsigned short)(t / (unsigned int)d); + t %= (unsigned int)d; + } + } +done: return; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include +#include +#include +#include "rng.h" + +#define N_MAX 7 +/* maximal number of digits in multiplicand */ + +#define M_MAX 5 +/* maximal number of digits in multiplier */ + +#define N_TEST 1000000 +/* number of tests */ + +int main(void) +{ RNG *rand; + int d, j, n, m, test; + unsigned short x[N_MAX], y[M_MAX], z[N_MAX+M_MAX]; + rand = rng_create_rand(); + for (test = 1; test <= N_TEST; test++) + { /* x[0,...,n-1] := multiplicand */ + n = 1 + rng_unif_rand(rand, N_MAX-1); + assert(1 <= n && n <= N_MAX); + for (j = 0; j < n; j++) + { d = rng_unif_rand(rand, 65536); + assert(0 <= d && d <= 65535); + x[j] = (unsigned short)d; + } + /* y[0,...,m-1] := multiplier */ + m = 1 + rng_unif_rand(rand, M_MAX-1); + assert(1 <= m && m <= M_MAX); + for (j = 0; j < m; j++) + { d = rng_unif_rand(rand, 65536); + assert(0 <= d && d <= 65535); + y[j] = (unsigned short)d; + } + if (y[m-1] == 0) y[m-1] = 1; + /* z[0,...,n+m-1] := x * y */ + for (j = 0; j < n; j++) z[m+j] = x[j]; + bigmul(n, m, z, y); + /* z[0,...,m-1] := z mod y, z[m,...,n+m-1] := z div y */ + bigdiv(n, m, z, y); + /* z mod y must be 0 */ + for (j = 0; j < m; j++) assert(z[j] == 0); + /* z div y must be x */ + for (j = 0; j < n; j++) assert(z[m+j] == x[j]); + } + fprintf(stderr, "%d tests successfully passed\n", N_TEST); + rng_delete_rand(rand); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.h new file mode 100644 index 000000000..8567519b7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/bignum.h @@ -0,0 +1,37 @@ +/* bignum.h (bignum arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BIGNUM_H +#define BIGNUM_H + +#define bigmul _glp_bigmul +void bigmul(int n, int m, unsigned short x[], unsigned short y[]); +/* multiply unsigned integer numbers of arbitrary precision */ + +#define bigdiv _glp_bigdiv +void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); +/* divide unsigned integer numbers of arbitrary precision */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.c new file mode 100644 index 000000000..6aa630a5e --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.c @@ -0,0 +1,147 @@ +/* dimacs.c (reading data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "dimacs.h" + +void dmx_error(DMX *csa, const char *fmt, ...) +{ /* print error message and terminate processing */ + va_list arg; + xprintf("%s:%d: error: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("\n"); + longjmp(csa->jump, 1); + /* no return */ +} + +void dmx_warning(DMX *csa, const char *fmt, ...) +{ /* print warning message and continue processing */ + va_list arg; + xprintf("%s:%d: warning: ", csa->fname, csa->count); + va_start(arg, fmt); + xvprintf(fmt, arg); + va_end(arg); + xprintf("\n"); + return; +} + +void dmx_read_char(DMX *csa) +{ /* read character from input text file */ + int c; + if (csa->c == '\n') csa->count++; + c = glp_getc(csa->fp); + if (c < 0) + { if (glp_ioerr(csa->fp)) + dmx_error(csa, "read error - %s", get_err_msg()); + else if (csa->c == '\n') + dmx_error(csa, "unexpected end of file"); + else + { dmx_warning(csa, "missing final end of line"); + c = '\n'; + } + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + dmx_error(csa, "invalid control character 0x%02X", c); + csa->c = c; + return; +} + +void dmx_read_designator(DMX *csa) +{ /* read one-character line designator */ + xassert(csa->c == '\n'); + dmx_read_char(csa); + for (;;) + { /* skip preceding white-space characters */ + while (csa->c == ' ') + dmx_read_char(csa); + if (csa->c == '\n') + { /* ignore empty line */ + if (!csa->empty) + { dmx_warning(csa, "empty line ignored"); + csa->empty = 1; + } + dmx_read_char(csa); + } + else if (csa->c == 'c') + { /* skip comment line */ + while (csa->c != '\n') + dmx_read_char(csa); + dmx_read_char(csa); + } + else + { /* hmm... looks like a line designator */ + csa->field[0] = (char)csa->c, csa->field[1] = '\0'; + /* check that it is followed by a white-space character */ + dmx_read_char(csa); + if (!(csa->c == ' ' || csa->c == '\n')) + dmx_error(csa, "line designator missing or invalid"); + break; + } + } + return; +} + +void dmx_read_field(DMX *csa) +{ /* read data field */ + int len = 0; + /* skip preceding white-space characters */ + while (csa->c == ' ') + dmx_read_char(csa); + /* scan data field */ + if (csa->c == '\n') + dmx_error(csa, "unexpected end of line"); + while (!(csa->c == ' ' || csa->c == '\n')) + { if (len == sizeof(csa->field)-1) + dmx_error(csa, "data field '%.15s...' too long", + csa->field); + csa->field[len++] = (char)csa->c; + dmx_read_char(csa); + } + csa->field[len] = '\0'; + return; +} + +void dmx_end_of_line(DMX *csa) +{ /* skip white-space characters until end of line */ + while (csa->c == ' ') + dmx_read_char(csa); + if (csa->c != '\n') + dmx_error(csa, "too many data fields specified"); + return; +} + +void dmx_check_int(DMX *csa, double num) +{ /* print a warning if non-integer data are detected */ + if (!csa->nonint && num != floor(num)) + { dmx_warning(csa, "non-integer data detected"); + csa->nonint = 1; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.h new file mode 100644 index 000000000..42fb99961 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dimacs.h @@ -0,0 +1,81 @@ +/* dimacs.h (reading data in DIMACS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef DIMACS_H +#define DIMACS_H + +#include "env.h" + +typedef struct DMX DMX; + +struct DMX +{ /* DIMACS data reader */ + jmp_buf jump; + /* label for go to in case of error */ + const char *fname; + /* name of input text file */ + glp_file *fp; + /* stream assigned to input text file */ + int count; + /* line count */ + int c; + /* current character */ + char field[255+1]; + /* data field */ + int empty; + /* warning 'empty line ignored' was printed */ + int nonint; + /* warning 'non-integer data detected' was printed */ +}; + +#define dmx_error _glp_dmx_error +void dmx_error(DMX *csa, const char *fmt, ...); +/* print error message and terminate processing */ + +#define dmx_warning _glp_dmx_warning +void dmx_warning(DMX *csa, const char *fmt, ...); +/* print warning message and continue processing */ + +#define dmx_read_char _glp_dmx_read_char +void dmx_read_char(DMX *csa); +/* read character from input text file */ + +#define dmx_read_designator _glp_dmx_read_designator +void dmx_read_designator(DMX *csa); +/* read one-character line designator */ + +#define dmx_read_field _glp_dmx_read_field +void dmx_read_field(DMX *csa); +/* read data field */ + +#define dmx_end_of_line _glp_dmx_end_of_line +void dmx_end_of_line(DMX *csa); +/* skip white-space characters until end of line */ + +#define dmx_check_int _glp_dmx_check_int +void dmx_check_int(DMX *csa, double num); +/* print a warning if non-integer data are detected */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.c new file mode 100644 index 000000000..a4882c861 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.c @@ -0,0 +1,243 @@ +/* dmp.c (dynamic memory pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "dmp.h" + +struct DMP +{ /* dynamic memory pool */ + void *avail[32]; + /* avail[k], 0 <= k <= 31, is a pointer to first available (free) + * atom of (k+1)*8 bytes long; at the beginning of each free atom + * there is a pointer to another free atom of the same size */ + void *block; + /* pointer to most recently allocated memory block; at the + * beginning of each allocated memory block there is a pointer to + * previously allocated memory block */ + int used; + /* number of bytes used in most recently allocated memory block */ + size_t count; + /* number of atoms which are currently in use */ +}; + +#define DMP_BLK_SIZE 8000 +/* size of memory blocks, in bytes, allocated for memory pools */ + +struct prefix +{ /* atom prefix (for debugging only) */ + DMP *pool; + /* dynamic memory pool */ + int size; + /* original atom size, in bytes */ +}; + +#define prefix_size ((sizeof(struct prefix) + 7) & ~7) +/* size of atom prefix rounded up to multiple of 8 bytes */ + +int dmp_debug; +/* debug mode flag */ + +/*********************************************************************** +* NAME +* +* dmp_create_pool - create dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* DMP *dmp_create_pool(void); +* +* DESCRIPTION +* +* The routine dmp_create_pool creates a dynamic memory pool. +* +* RETURNS +* +* The routine returns a pointer to the memory pool created. */ + +DMP *dmp_create_pool(void) +{ DMP *pool; + int k; + xassert(sizeof(void *) <= 8); + if (dmp_debug) + xprintf("dmp_create_pool: warning: debug mode is on\n"); + pool = talloc(1, DMP); + for (k = 0; k <= 31; k++) + pool->avail[k] = NULL; + pool->block = NULL; + pool->used = DMP_BLK_SIZE; + pool->count = 0; + return pool; +} + +/*********************************************************************** +* NAME +* +* dmp_get_atom - get free atom from dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void *dmp_get_atom(DMP *pool, int size); +* +* DESCRIPTION +* +* The routine dmp_get_atom obtains a free atom (memory space) from the +* specified memory pool. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the free atom contains arbitrary data, not binary zeros. +* +* RETURNS +* +* The routine returns a pointer to the free atom obtained. */ + +void *dmp_get_atom(DMP *pool, int size) +{ void *atom; + int k, need; + xassert(1 <= size && size <= 256); + /* round up atom size to multiple of 8 bytes */ + need = (size + 7) & ~7; + /* determine number of corresponding list of free atoms */ + k = (need >> 3) - 1; + /* obtain free atom */ + if (pool->avail[k] == NULL) + { /* corresponding list of free atoms is empty */ + /* if debug mode is on, add atom prefix size */ + if (dmp_debug) + need += prefix_size; + if (pool->used + need > DMP_BLK_SIZE) + { /* allocate new memory block */ + void *block = talloc(DMP_BLK_SIZE, char); + *(void **)block = pool->block; + pool->block = block; + pool->used = 8; /* sufficient to store pointer */ + } + /* allocate new atom in current memory block */ + atom = (char *)pool->block + pool->used; + pool->used += need; + } + else + { /* obtain atom from corresponding list of free atoms */ + atom = pool->avail[k]; + pool->avail[k] = *(void **)atom; + } + /* if debug mode is on, fill atom prefix */ + if (dmp_debug) + { ((struct prefix *)atom)->pool = pool; + ((struct prefix *)atom)->size = size; + atom = (char *)atom + prefix_size; + } + /* increase number of allocated atoms */ + pool->count++; + return atom; +} + +/*********************************************************************** +* NAME +* +* dmp_free_atom - return atom to dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void dmp_free_atom(DMP *pool, void *atom, int size); +* +* DESCRIPTION +* +* The routine dmp_free_atom returns the specified atom (memory space) +* to the specified memory pool, making the atom free. +* +* The parameter size is the atom size, in bytes, 1 <= size <= 256. +* +* Note that the atom can be returned only to the pool, from which it +* was obtained, and its size must be exactly the same as on obtaining +* it from the pool. */ + +void dmp_free_atom(DMP *pool, void *atom, int size) +{ int k; + xassert(1 <= size && size <= 256); + /* determine number of corresponding list of free atoms */ + k = ((size + 7) >> 3) - 1; + /* if debug mode is on, check atom prefix */ + if (dmp_debug) + { atom = (char *)atom - prefix_size; + xassert(((struct prefix *)atom)->pool == pool); + xassert(((struct prefix *)atom)->size == size); + } + /* return atom to corresponding list of free atoms */ + *(void **)atom = pool->avail[k]; + pool->avail[k] = atom; + /* decrease number of allocated atoms */ + xassert(pool->count > 0); + pool->count--; + return; +} + +/*********************************************************************** +* NAME +* +* dmp_in_use - determine how many atoms are still in use +* +* SYNOPSIS +* +* #include "dmp.h" +* size_t dmp_in_use(DMP *pool); +* +* RETURNS +* +* The routine returns the number of atoms of the specified memory pool +* which are still in use. */ + +size_t dmp_in_use(DMP *pool) +{ return + pool->count; +} + +/*********************************************************************** +* NAME +* +* dmp_delete_pool - delete dynamic memory pool +* +* SYNOPSIS +* +* #include "dmp.h" +* void dmp_delete_pool(DMP *pool); +* +* DESCRIPTION +* +* The routine dmp_delete_pool deletes the specified dynamic memory +* pool freeing all the memory allocated to this object. */ + +void dmp_delete_pool(DMP *pool) +{ while (pool->block != NULL) + { void *block = pool->block; + pool->block = *(void **)block; + tfree(block); + } + tfree(pool); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.h new file mode 100644 index 000000000..85fe7176a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/dmp.h @@ -0,0 +1,63 @@ +/* dmp.h (dynamic memory pool) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef DMP_H +#define DMP_H + +#include "stdc.h" + +typedef struct DMP DMP; + +#define dmp_debug _glp_dmp_debug +extern int dmp_debug; +/* debug mode flag */ + +#define dmp_create_pool _glp_dmp_create_pool +DMP *dmp_create_pool(void); +/* create dynamic memory pool */ + +#define dmp_talloc(pool, type) \ + ((type *)dmp_get_atom(pool, sizeof(type))) + +#define dmp_get_atom _glp_dmp_get_atom +void *dmp_get_atom(DMP *pool, int size); +/* get free atom from dynamic memory pool */ + +#define dmp_tfree(pool, atom) \ + dmp_free_atom(pool, atom, sizeof(*(atom))) + +#define dmp_free_atom _glp_dmp_free_atom +void dmp_free_atom(DMP *pool, void *atom, int size); +/* return atom to dynamic memory pool */ + +#define dmp_in_use _glp_dmp_in_use +size_t dmp_in_use(DMP *pool); +/* determine how many atoms are still in use */ + +#define dmp_delete_pool _glp_dmp_delete_pool +void dmp_delete_pool(DMP *pool); +/* delete dynamic memory pool */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.c new file mode 100644 index 000000000..4ea2913db --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.c @@ -0,0 +1,221 @@ +/* ffalg.c (Ford-Fulkerson algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ffalg.h" + +/*********************************************************************** +* NAME +* +* ffalg - Ford-Fulkerson algorithm +* +* SYNOPSIS +* +* #include "ffalg.h" +* void ffalg(int nv, int na, const int tail[], const int head[], +* int s, int t, const int cap[], int x[], char cut[]); +* +* DESCRIPTION +* +* The routine ffalg implements the Ford-Fulkerson algorithm to find a +* maximal flow in the specified flow network. +* +* INPUT PARAMETERS +* +* nv is the number of nodes, nv >= 2. +* +* na is the number of arcs, na >= 0. +* +* tail[a], a = 1,...,na, is the index of tail node of arc a. +* +* head[a], a = 1,...,na, is the index of head node of arc a. +* +* s is the source node index, 1 <= s <= nv. +* +* t is the sink node index, 1 <= t <= nv, t != s. +* +* cap[a], a = 1,...,na, is the capacity of arc a, cap[a] >= 0. +* +* NOTE: Multiple arcs are allowed, but self-loops are not allowed. +* +* OUTPUT PARAMETERS +* +* x[a], a = 1,...,na, is optimal value of the flow through arc a. +* +* cut[i], i = 1,...,nv, is 1 if node i is labelled, and 0 otherwise. +* The set of arcs, whose one endpoint is labelled and other is not, +* defines the minimal cut corresponding to the maximal flow found. +* If the parameter cut is NULL, the cut information are not stored. +* +* REFERENCES +* +* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND +* Corp., Report R-375-PR (August 1962), Chap. I "Static Maximal Flow," +* pp.30-33. */ + +void ffalg(int nv, int na, const int tail[], const int head[], + int s, int t, const int cap[], int x[], char cut[]) +{ int a, delta, i, j, k, pos1, pos2, temp, + *ptr, *arc, *link, *list; + /* sanity checks */ + xassert(nv >= 2); + xassert(na >= 0); + xassert(1 <= s && s <= nv); + xassert(1 <= t && t <= nv); + xassert(s != t); + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + xassert(1 <= i && i <= nv); + xassert(1 <= j && j <= nv); + xassert(i != j); + xassert(cap[a] >= 0); + } + /* allocate working arrays */ + ptr = xcalloc(1+nv+1, sizeof(int)); + arc = xcalloc(1+na+na, sizeof(int)); + link = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* ptr[i] := (degree of node i) */ + for (i = 1; i <= nv; i++) + ptr[i] = 0; + for (a = 1; a <= na; a++) + { ptr[tail[a]]++; + ptr[head[a]]++; + } + /* initialize arc pointers */ + ptr[1]++; + for (i = 1; i < nv; i++) + ptr[i+1] += ptr[i]; + ptr[nv+1] = ptr[nv]; + /* build arc lists */ + for (a = 1; a <= na; a++) + { arc[--ptr[tail[a]]] = a; + arc[--ptr[head[a]]] = a; + } + xassert(ptr[1] == 1); + xassert(ptr[nv+1] == na+na+1); + /* now the indices of arcs incident to node i are stored in + * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ + /* initialize arc flows */ + for (a = 1; a <= na; a++) + x[a] = 0; +loop: /* main loop starts here */ + /* build augmenting tree rooted at s */ + /* link[i] = 0 means that node i is not labelled yet; + * link[i] = a means that arc a immediately precedes node i */ + /* initially node s is labelled as the root */ + for (i = 1; i <= nv; i++) + link[i] = 0; + link[s] = -1, list[1] = s, pos1 = pos2 = 1; + /* breadth first search */ + while (pos1 <= pos2) + { /* dequeue node i */ + i = list[pos1++]; + /* consider all arcs incident to node i */ + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a = i->j is a forward arc from s to t */ + j = head[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow increasing the flow through + * it, skip the arc */ + if (x[a] == cap[a]) continue; + } + else if (head[a] == i) + { /* a = i<-j is a backward arc from s to t */ + j = tail[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow decreasing the flow through + * it, skip the arc */ + if (x[a] == 0) continue; + } + else + xassert(a != a); + /* label node j and enqueue it */ + link[j] = a, list[++pos2] = j; + /* check for breakthrough */ + if (j == t) goto brkt; + } + } + /* NONBREAKTHROUGH */ + /* no augmenting path exists; current flow is maximal */ + /* store minimal cut information, if necessary */ + if (cut != NULL) + { for (i = 1; i <= nv; i++) + cut[i] = (char)(link[i] != 0); + } + goto done; +brkt: /* BREAKTHROUGH */ + /* walk through arcs of the augmenting path (s, ..., t) found in + * the reverse order and determine maximal change of the flow */ + delta = 0; + for (j = t; j != s; j = i) + { /* arc a immediately precedes node j in the path */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + /* x[a] may be increased until its upper bound */ + temp = cap[a] - x[a]; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + /* x[a] may be decreased until its lower bound */ + temp = x[a]; + } + else + xassert(a != a); + if (delta == 0 || delta > temp) delta = temp; + } + xassert(delta > 0); + /* increase the flow along the path */ + for (j = t; j != s; j = i) + { /* arc a immediately precedes node j in the path */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + x[a] += delta; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + x[a] -= delta; + } + else + xassert(a != a); + } + goto loop; +done: /* free working arrays */ + xfree(ptr); + xfree(arc); + xfree(link); + xfree(list); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.h new file mode 100644 index 000000000..7016f8fa6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ffalg.h @@ -0,0 +1,34 @@ +/* ffalg.h (Ford-Fulkerson algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef FFALG_H +#define FFALG_H + +#define ffalg _glp_ffalg +void ffalg(int nv, int na, const int tail[], const int head[], + int s, int t, const int cap[], int x[], char cut[]); +/* Ford-Fulkerson algorithm */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/fp2rat.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fp2rat.c new file mode 100644 index 000000000..4699bbd16 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fp2rat.c @@ -0,0 +1,164 @@ +/* fp2rat.c (convert floating-point number to rational number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* fp2rat - convert floating-point number to rational number +* +* SYNOPSIS +* +* #include "misc.h" +* int fp2rat(double x, double eps, double *p, double *q); +* +* DESCRIPTION +* +* Given a floating-point number 0 <= x < 1 the routine fp2rat finds +* its "best" rational approximation p / q, where p >= 0 and q > 0 are +* integer numbers, such that |x - p / q| <= eps. +* +* RETURNS +* +* The routine fp2rat returns the number of iterations used to achieve +* the specified precision eps. +* +* EXAMPLES +* +* For x = sqrt(2) - 1 = 0.414213562373095 and eps = 1e-6 the routine +* gives p = 408 and q = 985, where 408 / 985 = 0.414213197969543. +* +* BACKGROUND +* +* It is well known that every positive real number x can be expressed +* as the following continued fraction: +* +* x = b[0] + a[1] +* ------------------------ +* b[1] + a[2] +* ----------------- +* b[2] + a[3] +* ---------- +* b[3] + ... +* +* where: +* +* a[k] = 1, k = 0, 1, 2, ... +* +* b[k] = floor(x[k]), k = 0, 1, 2, ... +* +* x[0] = x, +* +* x[k] = 1 / frac(x[k-1]), k = 1, 2, 3, ... +* +* To find the "best" rational approximation of x the routine computes +* partial fractions f[k] by dropping after k terms as follows: +* +* f[k] = A[k] / B[k], +* +* where: +* +* A[-1] = 1, A[0] = b[0], B[-1] = 0, B[0] = 1, +* +* A[k] = b[k] * A[k-1] + a[k] * A[k-2], +* +* B[k] = b[k] * B[k-1] + a[k] * B[k-2]. +* +* Once the condition +* +* |x - f[k]| <= eps +* +* has been satisfied, the routine reports p = A[k] and q = B[k] as the +* final answer. +* +* In the table below here is some statistics obtained for one million +* random numbers uniformly distributed in the range [0, 1). +* +* eps max p mean p max q mean q max k mean k +* ------------------------------------------------------------- +* 1e-1 8 1.6 9 3.2 3 1.4 +* 1e-2 98 6.2 99 12.4 5 2.4 +* 1e-3 997 20.7 998 41.5 8 3.4 +* 1e-4 9959 66.6 9960 133.5 10 4.4 +* 1e-5 97403 211.7 97404 424.2 13 5.3 +* 1e-6 479669 669.9 479670 1342.9 15 6.3 +* 1e-7 1579030 2127.3 3962146 4257.8 16 7.3 +* 1e-8 26188823 6749.4 26188824 13503.4 19 8.2 +* +* REFERENCES +* +* W. B. Jones and W. J. Thron, "Continued Fractions: Analytic Theory +* and Applications," Encyclopedia on Mathematics and Its Applications, +* Addison-Wesley, 1980. */ + +int fp2rat(double x, double eps, double *p, double *q) +{ int k; + double xk, Akm1, Ak, Bkm1, Bk, ak, bk, fk, temp; + xassert(0.0 <= x && x < 1.0); + for (k = 0; ; k++) + { xassert(k <= 100); + if (k == 0) + { /* x[0] = x */ + xk = x; + /* A[-1] = 1 */ + Akm1 = 1.0; + /* A[0] = b[0] = floor(x[0]) = 0 */ + Ak = 0.0; + /* B[-1] = 0 */ + Bkm1 = 0.0; + /* B[0] = 1 */ + Bk = 1.0; + } + else + { /* x[k] = 1 / frac(x[k-1]) */ + temp = xk - floor(xk); + xassert(temp != 0.0); + xk = 1.0 / temp; + /* a[k] = 1 */ + ak = 1.0; + /* b[k] = floor(x[k]) */ + bk = floor(xk); + /* A[k] = b[k] * A[k-1] + a[k] * A[k-2] */ + temp = bk * Ak + ak * Akm1; + Akm1 = Ak, Ak = temp; + /* B[k] = b[k] * B[k-1] + a[k] * B[k-2] */ + temp = bk * Bk + ak * Bkm1; + Bkm1 = Bk, Bk = temp; + } + /* f[k] = A[k] / B[k] */ + fk = Ak / Bk; +#if 0 + print("%.*g / %.*g = %.*g", + DBL_DIG, Ak, DBL_DIG, Bk, DBL_DIG, fk); +#endif + if (fabs(x - fk) <= eps) + break; + } + *p = Ak; + *q = Bk; + return k; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.c new file mode 100644 index 000000000..916a1bf94 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.c @@ -0,0 +1,137 @@ +/* fvs.c (sparse vector in FVS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "fvs.h" + +void fvs_alloc_vec(FVS *x, int n) +{ /* allocate sparse vector */ + int j; + xassert(n >= 0); + x->n = n; + x->nnz = 0; + x->ind = talloc(1+n, int); + x->vec = talloc(1+n, double); + for (j = 1; j <= n; j++) + x->vec[j] = 0.0; + return; +} + +void fvs_check_vec(const FVS *x) +{ /* check sparse vector */ + /* NOTE: for testing/debugging only */ + int n = x->n; + int nnz = x->nnz; + int *ind = x->ind; + double *vec = x->vec; + char *map; + int j, k; + xassert(n >= 0); + xassert(0 <= nnz && nnz <= n); + map = talloc(1+n, char); + for (j = 1; j <= n; j++) + map[j] = (vec[j] != 0.0); + for (k = 1; k <= nnz; k++) + { j = ind[k]; + xassert(1 <= j && j <= n); + xassert(map[j]); + map[j] = 0; + } + for (j = 1; j <= n; j++) + xassert(!map[j]); + tfree(map); + return; +} + +void fvs_gather_vec(FVS *x, double eps) +{ /* gather sparse vector */ + int n = x->n; + int *ind = x->ind; + double *vec = x->vec; + int j, nnz = 0; + for (j = n; j >= 1; j--) + { if (-eps < vec[j] && vec[j] < +eps) + vec[j] = 0.0; + else + ind[++nnz] = j; + } + x->nnz = nnz; + return; +} + +void fvs_clear_vec(FVS *x) +{ /* clear sparse vector */ + int *ind = x->ind; + double *vec = x->vec; + int k; + for (k = x->nnz; k >= 1; k--) + vec[ind[k]] = 0.0; + x->nnz = 0; + return; +} + +void fvs_copy_vec(FVS *x, const FVS *y) +{ /* copy sparse vector */ + int *x_ind = x->ind; + double *x_vec = x->vec; + int *y_ind = y->ind; + double *y_vec = y->vec; + int j, k; + xassert(x != y); + xassert(x->n == y->n); + fvs_clear_vec(x); + for (k = x->nnz = y->nnz; k >= 1; k--) + { j = x_ind[k] = y_ind[k]; + x_vec[j] = y_vec[j]; + } + return; +} + +void fvs_adjust_vec(FVS *x, double eps) +{ /* replace tiny vector elements by exact zeros */ + int nnz = x->nnz; + int *ind = x->ind; + double *vec = x->vec; + int j, k, cnt = 0; + for (k = 1; k <= nnz; k++) + { j = ind[k]; + if (-eps < vec[j] && vec[j] < +eps) + vec[j] = 0.0; + else + ind[++cnt] = j; + } + x->nnz = cnt; + return; +} + +void fvs_free_vec(FVS *x) +{ /* deallocate sparse vector */ + tfree(x->ind); + tfree(x->vec); + x->n = x->nnz = -1; + x->ind = NULL; + x->vec = NULL; + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.h new file mode 100644 index 000000000..abfed8cc9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/fvs.h @@ -0,0 +1,76 @@ +/* fvs.h (sparse vector in FVS format) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef FVS_H +#define FVS_H + +typedef struct FVS FVS; + +struct FVS +{ /* sparse vector in FVS (Full Vector Storage) format */ + int n; + /* vector dimension (total number of elements) */ + int nnz; + /* number of non-zero elements, 0 <= nnz <= n */ + int *ind; /* int ind[1+n]; */ + /* ind[0] is not used; + * ind[k] = j, 1 <= k <= nnz, means that vec[j] != 0 + * non-zero indices in the array ind are stored in arbitrary + * order; if vec[j] = 0, its index j SHOULD NOT be presented in + * the array ind */ + double *vec; /* double vec[1+n]; */ + /* vec[0] is not used; + * vec[j], 1 <= j <= n, is a numeric value of j-th element */ +}; + +#define fvs_alloc_vec _glp_fvs_alloc_vec +void fvs_alloc_vec(FVS *x, int n); +/* allocate sparse vector */ + +#define fvs_check_vec _glp_fvs_check_vec +void fvs_check_vec(const FVS *x); +/* check sparse vector */ + +#define fvs_gather_vec _glp_fvs_gather_vec +void fvs_gather_vec(FVS *x, double eps); +/* gather sparse vector */ + +#define fvs_clear_vec _glp_fvs_clear_vec +void fvs_clear_vec(FVS *x); +/* clear sparse vector */ + +#define fvs_copy_vec _glp_fvs_copy_vec +void fvs_copy_vec(FVS *x, const FVS *y); +/* copy sparse vector */ + +#define fvs_adjust_vec _glp_fvs_adjust_vec +void fvs_adjust_vec(FVS *x, double eps); +/* replace tiny vector elements by exact zeros */ + +#define fvs_free_vec _glp_fvs_free_vec +void fvs_free_vec(FVS *x); +/* deallocate sparse vector */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/gcd.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/gcd.c new file mode 100644 index 000000000..95c48cc04 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/gcd.c @@ -0,0 +1,102 @@ +/* gcd.c (greatest common divisor) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* gcd - find greatest common divisor of two integers +* +* SYNOPSIS +* +* #include "misc.h" +* int gcd(int x, int y); +* +* RETURNS +* +* The routine gcd returns gcd(x, y), the greatest common divisor of +* the two positive integers given. +* +* ALGORITHM +* +* The routine gcd is based on Euclid's algorithm. +* +* REFERENCES +* +* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical +* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The +* Greatest Common Divisor, pp. 333-56. */ + +int gcd(int x, int y) +{ int r; + xassert(x > 0 && y > 0); + while (y > 0) + r = x % y, x = y, y = r; + return x; +} + +/*********************************************************************** +* NAME +* +* gcdn - find greatest common divisor of n integers +* +* SYNOPSIS +* +* #include "misc.h" +* int gcdn(int n, int x[]); +* +* RETURNS +* +* The routine gcdn returns gcd(x[1], x[2], ..., x[n]), the greatest +* common divisor of n positive integers given, n > 0. +* +* BACKGROUND +* +* The routine gcdn is based on the following identity: +* +* gcd(x, y, z) = gcd(gcd(x, y), z). +* +* REFERENCES +* +* Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical +* Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The +* Greatest Common Divisor, pp. 333-56. */ + +int gcdn(int n, int x[]) +{ int d, j; + xassert(n > 0); + for (j = 1; j <= n; j++) + { xassert(x[j] > 0); + if (j == 1) + d = x[1]; + else + d = gcd(d, x[j]); + if (d == 1) + break; + } + return d; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.c new file mode 100644 index 000000000..c9d631719 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.c @@ -0,0 +1,152 @@ +/* jd.c (conversions between calendar date and Julian day number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include +#include "jd.h" + +/*********************************************************************** +* NAME +* +* jday - convert calendar date to Julian day number +* +* SYNOPSIS +* +* #include "jd.h" +* int jday(int d, int m, int y); +* +* DESCRIPTION +* +* The routine jday converts a calendar date, Gregorian calendar, to +* corresponding Julian day number j. +* +* From the given day d, month m, and year y, the Julian day number j +* is computed without using tables. +* +* The routine is valid for 1 <= y <= 4000. +* +* RETURNS +* +* The routine jday returns the Julian day number, or negative value if +* the specified date is incorrect. +* +* REFERENCES +* +* R. G. Tantzen, Algorithm 199: conversions between calendar date and +* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, +* Aug. 1963. */ + +int jday(int d, int m, int y) +{ int c, ya, j, dd; + if (!(1 <= d && d <= 31 && + 1 <= m && m <= 12 && + 1 <= y && y <= 4000)) + return -1; + if (m >= 3) + m -= 3; + else + m += 9, y--; + c = y / 100; + ya = y - 100 * c; + j = (146097 * c) / 4 + (1461 * ya) / 4 + (153 * m + 2) / 5 + d + + 1721119; + jdate(j, &dd, NULL, NULL); + if (d != dd) + return -1; + return j; +} + +/*********************************************************************** +* NAME +* +* jdate - convert Julian day number to calendar date +* +* SYNOPSIS +* +* #include "jd.h" +* int jdate(int j, int *d, int *m, int *y); +* +* DESCRIPTION +* +* The routine jdate converts a Julian day number j to corresponding +* calendar date, Gregorian calendar. +* +* The day d, month m, and year y are computed without using tables and +* stored in corresponding locations. +* +* The routine is valid for 1721426 <= j <= 3182395. +* +* RETURNS +* +* If the conversion is successful, the routine returns zero, otherwise +* non-zero. +* +* REFERENCES +* +* R. G. Tantzen, Algorithm 199: conversions between calendar date and +* Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, +* Aug. 1963. */ + +int jdate(int j, int *d_, int *m_, int *y_) +{ int d, m, y; + if (!(1721426 <= j && j <= 3182395)) + return 1; + j -= 1721119; + y = (4 * j - 1) / 146097; + j = (4 * j - 1) % 146097; + d = j / 4; + j = (4 * d + 3) / 1461; + d = (4 * d + 3) % 1461; + d = (d + 4) / 4; + m = (5 * d - 3) / 153; + d = (5 * d - 3) % 153; + d = (d + 5) / 5; + y = 100 * y + j; + if (m <= 9) + m += 3; + else m -= 9, + y++; + if (d_ != NULL) *d_ = d; + if (m_ != NULL) *m_ = m; + if (y_ != NULL) *y_ = y; + return 0; +} + +#ifdef GLP_TEST +#include +#include +#include + +int main(void) +{ int jbeg, jend, j, d, m, y; + jbeg = jday(1, 1, 1); + jend = jday(31, 12, 4000); + for (j = jbeg; j <= jend; j++) + { assert(jdate(j, &d, &m, &y) == 0); + assert(jday(d, m, y) == j); + } + printf("Routines jday and jdate work correctly.\n"); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.h new file mode 100644 index 000000000..009d2daad --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/jd.h @@ -0,0 +1,32 @@ +/* jd.h (conversions between calendar date and Julian day number) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#define jday _glp_jday +int jday(int d, int m, int y); +/* convert calendar date to Julian day number */ + +#define jdate _glp_jdate +int jdate(int j, int *d, int *m, int *y); +/* convert Julian day number to calendar date */ + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.c new file mode 100644 index 000000000..d64d3c1e2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.c @@ -0,0 +1,235 @@ +/* keller.c (cover edges by cliques, Kellerman's heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "keller.h" + +/*********************************************************************** +* NAME +* +* kellerman - cover edges by cliques with Kellerman's heuristic +* +* SYNOPSIS +* +* #include "keller.h" +* int kellerman(int n, int (*func)(void *info, int i, int ind[]), +* void *info, glp_graph *H); +* +* DESCRIPTION +* +* The routine kellerman implements Kellerman's heuristic algorithm +* to find a minimal set of cliques which cover all edges of specified +* graph G = (V, E). +* +* The parameter n specifies the number of vertices |V|, n >= 0. +* +* Formal routine func specifies the set of edges E in the following +* way. Running the routine kellerman calls the routine func and passes +* to it parameter i, which is the number of some vertex, 1 <= i <= n. +* In response the routine func should store numbers of all vertices +* adjacent to vertex i to locations ind[1], ind[2], ..., ind[len] and +* return the value of len, which is the number of adjacent vertices, +* 0 <= len <= n. Self-loops are allowed, but ignored. Multiple edges +* are not allowed. +* +* The parameter info is a transit pointer (magic cookie) passed to the +* formal routine func as its first parameter. +* +* The result provided by the routine kellerman is the bipartite graph +* H = (V union C, F), which defines the covering found. (The program +* object of type glp_graph specified by the parameter H should be +* previously created with the routine glp_create_graph. On entry the +* routine kellerman erases the content of this object with the routine +* glp_erase_graph.) Vertices of first part V correspond to vertices of +* the graph G and have the same ordinal numbers 1, 2, ..., n. Vertices +* of second part C correspond to cliques and have ordinal numbers +* n+1, n+2, ..., n+k, where k is the total number of cliques in the +* edge covering found. Every edge f in F in the program object H is +* represented as arc f = (i->j), where i in V and j in C, which means +* that vertex i of the graph G is in clique C[j], 1 <= j <= k. (Thus, +* if two vertices of the graph G are in the same clique, these vertices +* are adjacent in G, and corresponding edge is covered by that clique.) +* +* RETURNS +* +* The routine Kellerman returns k, the total number of cliques in the +* edge covering found. +* +* REFERENCE +* +* For more details see: glpk/doc/notes/keller.pdf (in Russian). */ + +struct set +{ /* set of vertices */ + int size; + /* size (cardinality) of the set, 0 <= card <= n */ + int *list; /* int list[1+n]; */ + /* the set contains vertices list[1,...,size] */ + int *pos; /* int pos[1+n]; */ + /* pos[i] > 0 means that vertex i is in the set and + * list[pos[i]] = i; pos[i] = 0 means that vertex i is not in + * the set */ +}; + +int kellerman(int n, int (*func)(void *info, int i, int ind[]), + void *info, void /* glp_graph */ *H_) +{ glp_graph *H = H_; + struct set W_, *W = &W_, V_, *V = &V_; + glp_arc *a; + int i, j, k, m, t, len, card, best; + xassert(n >= 0); + /* H := (V, 0; 0), where V is the set of vertices of graph G */ + glp_erase_graph(H, H->v_size, H->a_size); + glp_add_vertices(H, n); + /* W := 0 */ + W->size = 0; + W->list = xcalloc(1+n, sizeof(int)); + W->pos = xcalloc(1+n, sizeof(int)); + memset(&W->pos[1], 0, sizeof(int) * n); + /* V := 0 */ + V->size = 0; + V->list = xcalloc(1+n, sizeof(int)); + V->pos = xcalloc(1+n, sizeof(int)); + memset(&V->pos[1], 0, sizeof(int) * n); + /* main loop */ + for (i = 1; i <= n; i++) + { /* W must be empty */ + xassert(W->size == 0); + /* W := { j : i > j and (i,j) in E } */ + len = func(info, i, W->list); + xassert(0 <= len && len <= n); + for (t = 1; t <= len; t++) + { j = W->list[t]; + xassert(1 <= j && j <= n); + if (j >= i) continue; + xassert(W->pos[j] == 0); + W->list[++W->size] = j, W->pos[j] = W->size; + } + /* on i-th iteration we need to cover edges (i,j) for all + * j in W */ + /* if W is empty, it is a special case */ + if (W->size == 0) + { /* set k := k + 1 and create new clique C[k] = { i } */ + k = glp_add_vertices(H, 1) - n; + glp_add_arc(H, i, n + k); + continue; + } + /* try to include vertex i into existing cliques */ + /* V must be empty */ + xassert(V->size == 0); + /* k is the number of cliques found so far */ + k = H->nv - n; + for (m = 1; m <= k; m++) + { /* do while V != W; since here V is within W, we can use + * equivalent condition: do while |V| < |W| */ + if (V->size == W->size) break; + /* check if C[m] is within W */ + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] == 0) break; + } + if (a != NULL) continue; + /* C[m] is within W, expand clique C[m] with vertex i */ + /* C[m] := C[m] union {i} */ + glp_add_arc(H, i, n + m); + /* V is a set of vertices whose incident edges are already + * covered by existing cliques */ + /* V := V union C[m] */ + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (V->pos[j] == 0) + V->list[++V->size] = j, V->pos[j] = V->size; + } + } + /* remove from set W the vertices whose incident edges are + * already covered by existing cliques */ + /* W := W \ V, V := 0 */ + for (t = 1; t <= V->size; t++) + { j = V->list[t], V->pos[j] = 0; + if (W->pos[j] != 0) + { /* remove vertex j from W */ + if (W->pos[j] != W->size) + { int jj = W->list[W->size]; + W->list[W->pos[j]] = jj; + W->pos[jj] = W->pos[j]; + } + W->size--, W->pos[j] = 0; + } + } + V->size = 0; + /* now set W contains only vertices whose incident edges are + * still not covered by existing cliques; create new cliques + * to cover remaining edges until set W becomes empty */ + while (W->size > 0) + { /* find clique C[m], 1 <= m <= k, which shares maximal + * number of vertices with W; to break ties choose clique + * having smallest number m */ + m = 0, best = -1; + k = H->nv - n; + for (t = 1; t <= k; t++) + { /* compute cardinality of intersection of W and C[t] */ + card = 0; + for (a = H->v[n + t]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] != 0) card++; + } + if (best < card) + m = t, best = card; + } + xassert(m > 0); + /* set k := k + 1 and create new clique: + * C[k] := (W intersect C[m]) union { i }, which covers all + * edges incident to vertices from (W intersect C[m]) */ + k = glp_add_vertices(H, 1) - n; + for (a = H->v[n + m]->in; a != NULL; a = a->h_next) + { j = a->tail->i; + if (W->pos[j] != 0) + { /* vertex j is in both W and C[m]; include it in new + * clique C[k] */ + glp_add_arc(H, j, n + k); + /* remove vertex j from W, since edge (i,j) will be + * covered by new clique C[k] */ + if (W->pos[j] != W->size) + { int jj = W->list[W->size]; + W->list[W->pos[j]] = jj; + W->pos[jj] = W->pos[j]; + } + W->size--, W->pos[j] = 0; + } + } + /* include vertex i to new clique C[k] to cover edges (i,j) + * incident to all vertices j just removed from W */ + glp_add_arc(H, i, n + k); + } + } + /* free working arrays */ + xfree(W->list); + xfree(W->pos); + xfree(V->list); + xfree(V->pos); + /* return the number of cliques in the edge covering found */ + return H->nv - n; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.h new file mode 100644 index 000000000..d7a5b3431 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/keller.h @@ -0,0 +1,34 @@ +/* keller.h (cover edges by cliques, Kellerman's heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef KELLER_H +#define KELLER_H + +#define kellerman _glp_kellerman +int kellerman(int n, int (*func)(void *info, int i, int ind[]), + void *info, void /* glp_graph */ *H); +/* cover edges by cliques with Kellerman's heuristic */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.c new file mode 100644 index 000000000..0720cc90b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.c @@ -0,0 +1,466 @@ +/* ks.c (0-1 knapsack problem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ks.h" +#include "mt1.h" + +/*********************************************************************** +* 0-1 knapsack problem has the following formulation: +* +* maximize z = sum{j in 1..n} c[j]x[j] (1) +* +* s.t. sum{j in 1..n} a[j]x[j] <= b (2) +* +* x[j] in {0, 1} for all j in 1..n (3) +* +* In general case it is assumed that the instance is non-normalized, +* i.e. parameters a, b, and c may have any sign. +***********************************************************************/ + +/*********************************************************************** +* ks_enum - solve 0-1 knapsack problem by complete enumeration +* +* This routine finds optimal solution to 0-1 knapsack problem (1)-(3) +* by complete enumeration. It is intended mainly for testing purposes. +* +* The instance to be solved is specified by parameters n, a, b, and c. +* Note that these parameters can have any sign, i.e. normalization is +* not needed. +* +* On exit the routine stores the optimal point found in locations +* x[1], ..., x[n] and returns the optimal objective value. However, if +* the instance is infeasible, the routine returns INT_MIN. +* +* Since the complete enumeration is inefficient, this routine can be +* used only for small instances (n <= 20-30). */ + +#define N_MAX 40 + +int ks_enum(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]) +{ int j, s, z, z_best; + char x_best[1+N_MAX]; + xassert(0 <= n && n <= N_MAX); + /* initialization */ + memset(&x[1], 0, n * sizeof(char)); + z_best = INT_MIN; +loop: /* compute constraint and objective at current x */ + s = z = 0; + for (j = 1; j <= n; j++) + { if (x[j]) + s += a[j], z += c[j]; + } + /* check constraint violation */ + if (s > b) + goto next; + /* check objective function */ + if (z_best < z) + { /* better solution has been found */ + memcpy(&x_best[1], &x[1], n * sizeof(char)); + z_best = z; + } +next: /* generate next x */ + for (j = 1; j <= n; j++) + { if (!x[j]) + { x[j] = 1; + goto loop; + } + x[j] = 0; + } + /* report best (optimal) solution */ + memcpy(&x[1], &x_best[1], n * sizeof(char)); + return z_best; +} + +/*********************************************************************** +* reduce - prepare reduced instance of 0-1 knapsack +* +* Given original instance of 0-1 knapsack (1)-(3) specified by the +* parameters n, a, b, and c this routine transforms it to equivalent +* reduced instance in the same format. The reduced instance is +* normalized, i.e. the following additional conditions are met: +* +* n >= 2 (4) +* +* 1 <= a[j] <= b for all j in 1..n (5) +* +* sum{j in 1..n} a[j] >= b+1 (6) +* +* c[j] >= 1 for all j in 1..n (7) +* +* The routine creates the structure ks and stores there parameters n, +* a, b, and c of the reduced instance as well as template of solution +* to original instance. +* +* Normally the routine returns a pointer to the structure ks created. +* However, if the original instance is infeasible, the routine returns +* a null pointer. */ + +struct ks +{ int orig_n; + /* original problem dimension */ + int n; + /* reduced problem dimension */ + int *a; /* int a[1+orig_n]; */ + /* a{j in 1..n} are constraint coefficients (2) */ + int b; + /* b is constraint right-hand side (2) */ + int *c; /* int c[1+orig_n]; */ + /* c{j in 1..n} are objective coefficients (1) */ + int c0; + /* c0 is objective constant term */ + char *x; /* char x[1+orig_n]; */ + /* x{j in 1..orig_n} is solution template to original instance: + * x[j] = 0 x[j] is fixed at 0 + * x[j] = 1 x[j] is fixed at 1 + * x[j] = 0x10 x[j] = x[j'] + * x[j] = 0x11 x[j] = 1 - x[j'] + * where x[j'] is corresponding solution to reduced instance */ +}; + +static void free_ks(struct ks *ks); + +static struct ks *reduce(const int n, const int a[/*1+n*/], int b, + const int c[/*1+n*/]) +{ struct ks *ks; + int j, s; + xassert(n >= 0); + /* initially reduced instance is the same as original one */ + ks = talloc(1, struct ks); + ks->orig_n = n; + ks->n = 0; + ks->a = talloc(1+n, int); + memcpy(&ks->a[1], &a[1], n * sizeof(int)); + ks->b = b; + ks->c = talloc(1+n, int); + memcpy(&ks->c[1], &c[1], n * sizeof(int)); + ks->c0 = 0; + ks->x = talloc(1+n, char); + /* make all a[j] non-negative */ + for (j = 1; j <= n; j++) + { if (a[j] >= 0) + { /* keep original x[j] */ + ks->x[j] = 0x10; + } + else /* a[j] < 0 */ + { /* substitute x[j] = 1 - x'[j] */ + ks->x[j] = 0x11; + /* ... + a[j]x[j] + ... <= b + * ... + a[j](1 - x'[j]) + ... <= b + * ... - a[j]x'[j] + ... <= b - a[j] */ + ks->a[j] = - ks->a[j]; + ks->b += ks->a[j]; + /* z = ... + c[j]x[j] + ... + c0 = + * = ... + c[j](1 - x'[j]) + ... + c0 = + * = ... - c[j]x'[j] + ... + (c0 + c[j]) */ + ks->c0 += ks->c[j]; + ks->c[j] = - ks->c[j]; + } + } + /* now a[j] >= 0 for all j in 1..n */ + if (ks->b < 0) + { /* instance is infeasible */ + free_ks(ks); + return NULL; + } + /* build reduced instance */ + for (j = 1; j <= n; j++) + { if (ks->a[j] == 0) + { if (ks->c[j] <= 0) + { /* fix x[j] at 0 */ + ks->x[j] ^= 0x10; + } + else + { /* fix x[j] at 1 */ + ks->x[j] ^= 0x11; + ks->c0 += ks->c[j]; + } + } + else if (ks->a[j] > ks->b || ks->c[j] <= 0) + { /* fix x[j] at 0 */ + ks->x[j] ^= 0x10; + } + else + { /* include x[j] in reduced instance */ + ks->n++; + ks->a[ks->n] = ks->a[j]; + ks->c[ks->n] = ks->c[j]; + } + } + /* now conditions (5) and (7) are met */ + /* check condition (6) */ + s = 0; + for (j = 1; j <= ks->n; j++) + { xassert(1 <= ks->a[j] && ks->a[j] <= ks->b); + xassert(ks->c[j] >= 1); + s += ks->a[j]; + } + if (s <= ks->b) + { /* sum{j in 1..n} a[j] <= b */ + /* fix all remaining x[j] at 1 to obtain trivial solution */ + for (j = 1; j <= n; j++) + { if (ks->x[j] & 0x10) + ks->x[j] ^= 0x11; + } + for (j = 1; j <= ks->n; j++) + ks->c0 += ks->c[j]; + /* reduced instance is empty */ + ks->n = 0; + } + /* here n = 0 or n >= 2 due to condition (6) */ + xassert(ks->n == 0 || ks->n >= 2); + return ks; +} + +/*********************************************************************** +* restore - restore solution to original 0-1 knapsack instance +* +* Given optimal solution x{j in 1..ks->n} to the reduced 0-1 knapsack +* instance (previously prepared by the routine reduce) this routine +* constructs optimal solution to the original instance and stores it +* in the array ks->x{j in 1..ks->orig_n}. +* +* On exit the routine returns optimal objective value for the original +* instance. +* +* NOTE: This operation should be performed only once. */ + +static int restore(struct ks *ks, char x[]) +{ int j, k, z; + z = ks->c0; + for (j = 1, k = 0; j <= ks->orig_n; j++) + { if (ks->x[j] & 0x10) + { k++; + xassert(k <= ks->n); + xassert(x[k] == 0 || x[k] == 1); + if (ks->x[j] & 1) + ks->x[j] = 1 - x[k]; + else + ks->x[j] = x[k]; + if (x[k]) + z += ks->c[k]; + } + } + xassert(k == ks->n); + return z; +} + +/*********************************************************************** +* free_ks - deallocate structure ks +* +* This routine frees memory previously allocated to the structure ks +* and all its components. */ + +static void free_ks(struct ks *ks) +{ xassert(ks != NULL); + tfree(ks->a); + tfree(ks->c); + tfree(ks->x); + tfree(ks); +} + +/*********************************************************************** +* ks_mt1 - solve 0-1 knapsack problem with Martello & Toth algorithm +* +* This routine finds optimal solution to 0-1 knapsack problem (1)-(3) +* with Martello & Toth algorithm MT1. +* +* The instance to be solved is specified by parameters n, a, b, and c. +* Note that these parameters can have any sign, i.e. normalization is +* not needed. +* +* On exit the routine stores the optimal point found in locations +* x[1], ..., x[n] and returns the optimal objective value. However, if +* the instance is infeasible, the routine returns INT_MIN. +* +* REFERENCES +* +* S.Martello, P.Toth. Knapsack Problems: Algorithms and Computer Imp- +* lementations. John Wiley & Sons, 1990. */ + +struct mt +{ int j; + float r; /* r[j] = c[j] / a[j] */ +}; + +static int CDECL fcmp(const void *p1, const void *p2) +{ if (((struct mt *)p1)->r > ((struct mt *)p2)->r) + return -1; + else if (((struct mt *)p1)->r < ((struct mt *)p2)->r) + return +1; + else + return 0; +} + +static int mt1a(int n, const int a[], int b, const int c[], char x[]) +{ /* interface routine to MT1 */ + struct mt *mt; + int j, z, *p, *w, *x1, *xx, *min, *psign, *wsign, *zsign; + xassert(n >= 2); + /* allocate working arrays */ + mt = talloc(1+n, struct mt); + p = talloc(1+n+1, int); + w = talloc(1+n+1, int); + x1 = talloc(1+n+1, int); + xx = talloc(1+n+1, int); + min = talloc(1+n+1, int); + psign = talloc(1+n+1, int); + wsign = talloc(1+n+1, int); + zsign = talloc(1+n+1, int); + /* reorder items to provide c[j] / a[j] >= a[j+1] / a[j+1] */ + for (j = 1; j <= n; j++) + { mt[j].j = j; + mt[j].r = (float)c[j] / (float)a[j]; + } + qsort(&mt[1], n, sizeof(struct mt), fcmp); + /* load instance parameters */ + for (j = 1; j <= n; j++) + { p[j] = c[mt[j].j]; + w[j] = a[mt[j].j]; + } + /* find optimal solution */ + z = mt1(n, p, w, b, x1, 1, xx, min, psign, wsign, zsign); + xassert(z >= 0); + /* store optimal point found */ + for (j = 1; j <= n; j++) + { xassert(x1[j] == 0 || x1[j] == 1); + x[mt[j].j] = x1[j]; + } + /* free working arrays */ + tfree(mt); + tfree(p); + tfree(w); + tfree(x1); + tfree(xx); + tfree(min); + tfree(psign); + tfree(wsign); + tfree(zsign); + return z; +} + +int ks_mt1(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]) +{ struct ks *ks; + int j, s1, s2, z; + xassert(n >= 0); + /* prepare reduced instance */ + ks = reduce(n, a, b, c); + if (ks == NULL) + { /* original instance is infeasible */ + return INT_MIN; + } + /* find optimal solution to reduced instance */ + if (ks->n > 0) + mt1a(ks->n, ks->a, ks->b, ks->c, x); + /* restore solution to original instance */ + z = restore(ks, x); + memcpy(&x[1], &ks->x[1], n * sizeof(char)); + free_ks(ks); + /* check solution found */ + s1 = s2 = 0; + for (j = 1; j <= n; j++) + { xassert(x[j] == 0 || x[j] == 1); + if (x[j]) + s1 += a[j], s2 += c[j]; + } + xassert(s1 <= b); + xassert(s2 == z); + return z; +} + +/*********************************************************************** +* ks_greedy - solve 0-1 knapsack problem with greedy heuristic +* +* This routine finds (sub)optimal solution to 0-1 knapsack problem +* (1)-(3) with greedy heuristic. +* +* The instance to be solved is specified by parameters n, a, b, and c. +* Note that these parameters can have any sign, i.e. normalization is +* not needed. +* +* On exit the routine stores the optimal point found in locations +* x[1], ..., x[n] and returns the optimal objective value. However, if +* the instance is infeasible, the routine returns INT_MIN. */ + +static int greedy(int n, const int a[], int b, const int c[], char x[]) +{ /* core routine for normalized 0-1 knapsack instance */ + struct mt *mt; + int j, s, z; + xassert(n >= 2); + /* reorder items to provide c[j] / a[j] >= a[j+1] / a[j+1] */ + mt = talloc(1+n, struct mt); + for (j = 1; j <= n; j++) + { mt[j].j = j; + mt[j].r = (float)c[j] / (float)a[j]; + } + qsort(&mt[1], n, sizeof(struct mt), fcmp); + /* take items starting from most valuable ones until the knapsack + * is full */ + s = z = 0; + for (j = 1; j <= n; j++) + { if (s + a[mt[j].j] > b) + break; + x[mt[j].j] = 1; + s += a[mt[j].j]; + z += c[mt[j].j]; + } + /* don't take remaining items */ + for (j = j; j <= n; j++) + x[mt[j].j] = 0; + tfree(mt); + return z; +} + +int ks_greedy(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]) +{ struct ks *ks; + int j, s1, s2, z; + xassert(n >= 0); + /* prepare reduced instance */ + ks = reduce(n, a, b, c); + if (ks == NULL) + { /* original instance is infeasible */ + return INT_MIN; + } + /* find suboptimal solution to reduced instance */ + if (ks->n > 0) + greedy(ks->n, ks->a, ks->b, ks->c, x); + /* restore solution to original instance */ + z = restore(ks, x); + memcpy(&x[1], &ks->x[1], n * sizeof(char)); + free_ks(ks); + /* check solution found */ + s1 = s2 = 0; + for (j = 1; j <= n; j++) + { xassert(x[j] == 0 || x[j] == 1); + if (x[j]) + s1 += a[j], s2 += c[j]; + } + xassert(s1 <= b); + xassert(s2 == z); + return z; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.h new file mode 100644 index 000000000..d607dc44f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/ks.h @@ -0,0 +1,44 @@ +/* ks.h (0-1 knapsack problem) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef KS_H +#define KS_H + +#define ks_enum _glp_ks_enum +int ks_enum(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]); +/* solve 0-1 knapsack problem by complete enumeration */ + +#define ks_mt1 _glp_ks_mt1 +int ks_mt1(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]); +/* solve 0-1 knapsack problem with Martello & Toth algorithm */ + +#define ks_greedy _glp_ks_greedy +int ks_greedy(int n, const int a[/*1+n*/], int b, const int c[/*1+n*/], + char x[/*1+n*/]); +/* solve 0-1 knapsack problem with greedy heuristic */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.c new file mode 100644 index 000000000..d8bab398d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.c @@ -0,0 +1,314 @@ +/* mc13d.c (permutations to block triangular form) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran subroutines +* MC13D and MC13E associated with the following paper: +* +* I.S.Duff, J.K.Reid, Algorithm 529: Permutations to block triangular +* form, ACM Trans. on Math. Softw. 4 (1978), 189-192. +* +* Use of ACM Algorithms is subject to the ACM Software Copyright and +* License Agreement. See . +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mc13d.h" + +/*********************************************************************** +* NAME +* +* mc13d - permutations to block triangular form +* +* SYNOPSIS +* +* #include "mc13d.h" +* int mc13d(int n, const int icn[], const int ip[], const int lenr[], +* int ior[], int ib[], int lowl[], int numb[], int prev[]); +* +* DESCRIPTION +* +* Given the column numbers of the nonzeros in each row of the sparse +* matrix, the routine mc13d finds a symmetric permutation that makes +* the matrix block lower triangular. +* +* INPUT PARAMETERS +* +* n order of the matrix. +* +* icn array containing the column indices of the non-zeros. Those +* belonging to a single row must be contiguous but the ordering +* of column indices within each row is unimportant and wasted +* space between rows is permitted. +* +* ip ip[i], i = 1,2,...,n, is the position in array icn of the +* first column index of a non-zero in row i. +* +* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. +* +* OUTPUT PARAMETERS +* +* ior ior[i], i = 1,2,...,n, gives the position on the original +* ordering of the row or column which is in position i in the +* permuted form. +* +* ib ib[i], i = 1,2,...,num, is the row number in the permuted +* matrix of the beginning of block i, 1 <= num <= n. +* +* WORKING ARRAYS +* +* arp working array of length [1+n], where arp[0] is not used. +* arp[i] is one less than the number of unsearched edges leaving +* node i. At the end of the algorithm it is set to a permutation +* which puts the matrix in block lower triangular form. +* +* ib working array of length [1+n], where ib[0] is not used. +* ib[i] is the position in the ordering of the start of the ith +* block. ib[n+1-i] holds the node number of the ith node on the +* stack. +* +* lowl working array of length [1+n], where lowl[0] is not used. +* lowl[i] is the smallest stack position of any node to which a +* path from node i has been found. It is set to n+1 when node i +* is removed from the stack. +* +* numb working array of length [1+n], where numb[0] is not used. +* numb[i] is the position of node i in the stack if it is on it, +* is the permuted order of node i for those nodes whose final +* position has been found and is otherwise zero. +* +* prev working array of length [1+n], where prev[0] is not used. +* prev[i] is the node at the end of the path when node i was +* placed on the stack. +* +* RETURNS +* +* The routine mc13d returns num, the number of blocks found. */ + +int mc13d(int n, const int icn[], const int ip[], const int lenr[], + int ior[], int ib[], int lowl[], int numb[], int prev[]) +{ int *arp = ior; + int dummy, i, i1, i2, icnt, ii, isn, ist, ist1, iv, iw, j, lcnt, + nnm1, num, stp; + /* icnt is the number of nodes whose positions in final ordering + * have been found. */ + icnt = 0; + /* num is the number of blocks that have been found. */ + num = 0; + nnm1 = n + n - 1; + /* Initialization of arrays. */ + for (j = 1; j <= n; j++) + { numb[j] = 0; + arp[j] = lenr[j] - 1; + } + for (isn = 1; isn <= n; isn++) + { /* Look for a starting node. */ + if (numb[isn] != 0) continue; + iv = isn; + /* ist is the number of nodes on the stack ... it is the stack + * pointer. */ + ist = 1; + /* Put node iv at beginning of stack. */ + lowl[iv] = numb[iv] = 1; + ib[n] = iv; + /* The body of this loop puts a new node on the stack or + * backtracks. */ + for (dummy = 1; dummy <= nnm1; dummy++) + { i1 = arp[iv]; + /* Have all edges leaving node iv been searched? */ + if (i1 >= 0) + { i2 = ip[iv] + lenr[iv] - 1; + i1 = i2 - i1; + /* Look at edges leaving node iv until one enters a new + * node or all edges are exhausted. */ + for (ii = i1; ii <= i2; ii++) + { iw = icn[ii]; + /* Has node iw been on stack already? */ + if (numb[iw] == 0) goto L70; + /* Update value of lowl[iv] if necessary. */ + if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; + } + /* There are no more edges leaving node iv. */ + arp[iv] = -1; + } + /* Is node iv the root of a block? */ + if (lowl[iv] < numb[iv]) goto L60; + /* Order nodes in a block. */ + num++; + ist1 = n + 1 - ist; + lcnt = icnt + 1; + /* Peel block off the top of the stack starting at the top + * and working down to the root of the block. */ + for (stp = ist1; stp <= n; stp++) + { iw = ib[stp]; + lowl[iw] = n + 1; + numb[iw] = ++icnt; + if (iw == iv) break; + } + ist = n - stp; + ib[num] = lcnt; + /* Are there any nodes left on the stack? */ + if (ist != 0) goto L60; + /* Have all the nodes been ordered? */ + if (icnt < n) break; + goto L100; +L60: /* Backtrack to previous node on path. */ + iw = iv; + iv = prev[iv]; + /* Update value of lowl[iv] if necessary. */ + if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; + continue; +L70: /* Put new node on the stack. */ + arp[iv] = i2 - ii - 1; + prev[iw] = iv; + iv = iw; + lowl[iv] = numb[iv] = ++ist; + ib[n+1-ist] = iv; + } + } +L100: /* Put permutation in the required form. */ + for (i = 1; i <= n; i++) + arp[numb[i]] = i; + return num; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "env.h" + +void test(int n, int ipp); + +int main(void) +{ /* test program for routine mc13d */ + test( 1, 0); + test( 2, 1); + test( 2, 2); + test( 3, 3); + test( 4, 4); + test( 5, 10); + test(10, 10); + test(10, 20); + test(20, 20); + test(20, 50); + test(50, 50); + test(50, 200); + return 0; +} + +void fa01bs(int max, int *nrand); + +void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]); + +void test(int n, int ipp) +{ int ip[1+50], icn[1+1000], ior[1+50], ib[1+51], iw[1+150], + lenr[1+50]; + char a[1+50][1+50], hold[1+100]; + int i, ii, iblock, ij, index, j, jblock, jj, k9, num; + xprintf("\n\n\nMatrix is of order %d and has %d off-diagonal non-" + "zeros\n", n, ipp); + for (j = 1; j <= n; j++) + { for (i = 1; i <= n; i++) + a[i][j] = 0; + a[j][j] = 1; + } + for (k9 = 1; k9 <= ipp; k9++) + { /* these statements should be replaced by calls to your + * favorite random number generator to place two pseudo-random + * numbers between 1 and n in the variables i and j */ + for (;;) + { fa01bs(n, &i); + fa01bs(n, &j); + if (!a[i][j]) break; + } + a[i][j] = 1; + } + /* setup converts matrix a[i,j] to required sparsity-oriented + * storage format */ + setup(n, a, ip, icn, lenr); + num = mc13d(n, icn, ip, lenr, ior, ib, &iw[0], &iw[n], &iw[n+n]); + /* output reordered matrix with blocking to improve clarity */ + xprintf("\nThe reordered matrix which has %d block%s is of the fo" + "rm\n", num, num == 1 ? "" : "s"); + ib[num+1] = n + 1; + index = 100; + iblock = 1; + for (i = 1; i <= n; i++) + { for (ij = 1; ij <= index; ij++) + hold[ij] = ' '; + if (i == ib[iblock]) + { xprintf("\n"); + iblock++; + } + jblock = 1; + index = 0; + for (j = 1; j <= n; j++) + { if (j == ib[jblock]) + { hold[++index] = ' '; + jblock++; + } + ii = ior[i]; + jj = ior[j]; + hold[++index] = (char)(a[ii][jj] ? 'X' : '0'); + } + xprintf("%.*s\n", index, &hold[1]); + } + xprintf("\nThe starting point for each block is given by\n"); + for (i = 1; i <= num; i++) + { if ((i - 1) % 12 == 0) xprintf("\n"); + xprintf(" %4d", ib[i]); + } + xprintf("\n"); + return; +} + +void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]) +{ int i, j, ind; + for (i = 1; i <= n; i++) + lenr[i] = 0; + ind = 1; + for (i = 1; i <= n; i++) + { ip[i] = ind; + for (j = 1; j <= n; j++) + { if (a[i][j]) + { lenr[i]++; + icn[ind++] = j; + } + } + } + return; +} + +double g = 1431655765.0; + +double fa01as(int i) +{ /* random number generator */ + g = fmod(g * 9228907.0, 4294967296.0); + if (i >= 0) + return g / 4294967296.0; + else + return 2.0 * g / 4294967296.0 - 1.0; +} + +void fa01bs(int max, int *nrand) +{ *nrand = (int)(fa01as(1) * (double)max) + 1; + return; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.h new file mode 100644 index 000000000..bdd57a19a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc13d.h @@ -0,0 +1,34 @@ +/* mc13d.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MC13D_H +#define MC13D_H + +#define mc13d _glp_mc13d +int mc13d(int n, const int icn[], const int ip[], const int lenr[], + int ior[], int ib[], int lowl[], int numb[], int prev[]); +/* permutations to block triangular form */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.c new file mode 100644 index 000000000..700d0f4e2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.c @@ -0,0 +1,301 @@ +/* mc21a.c (permutations for zero-free diagonal) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is the result of translation of the Fortran subroutines +* MC21A and MC21B associated with the following paper: +* +* I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM +* Trans. on Math. Softw. 7 (1981), 387-390. +* +* Use of ACM Algorithms is subject to the ACM Software Copyright and +* License Agreement. See . +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mc21a.h" + +/*********************************************************************** +* NAME +* +* mc21a - permutations for zero-free diagonal +* +* SYNOPSIS +* +* #include "mc21a.h" +* int mc21a(int n, const int icn[], const int ip[], const int lenr[], +* int iperm[], int pr[], int arp[], int cv[], int out[]); +* +* DESCRIPTION +* +* Given the pattern of nonzeros of a sparse matrix, the routine mc21a +* attempts to find a permutation of its rows that makes the matrix have +* no zeros on its diagonal. +* +* INPUT PARAMETERS +* +* n order of matrix. +* +* icn array containing the column indices of the non-zeros. Those +* belonging to a single row must be contiguous but the ordering +* of column indices within each row is unimportant and wasted +* space between rows is permitted. +* +* ip ip[i], i = 1,2,...,n, is the position in array icn of the +* first column index of a non-zero in row i. +* +* lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. +* +* OUTPUT PARAMETER +* +* iperm contains permutation to make diagonal have the smallest +* number of zeros on it. Elements (iperm[i], i), i = 1,2,...,n, +* are non-zero at the end of the algorithm unless the matrix is +* structurally singular. In this case, (iperm[i], i) will be +* zero for n - numnz entries. +* +* WORKING ARRAYS +* +* pr working array of length [1+n], where pr[0] is not used. +* pr[i] is the previous row to i in the depth first search. +* +* arp working array of length [1+n], where arp[0] is not used. +* arp[i] is one less than the number of non-zeros in row i which +* have not been scanned when looking for a cheap assignment. +* +* cv working array of length [1+n], where cv[0] is not used. +* cv[i] is the most recent row extension at which column i was +* visited. +* +* out working array of length [1+n], where out[0] is not used. +* out[i] is one less than the number of non-zeros in row i +* which have not been scanned during one pass through the main +* loop. +* +* RETURNS +* +* The routine mc21a returns numnz, the number of non-zeros on diagonal +* of permuted matrix. */ + +int mc21a(int n, const int icn[], const int ip[], const int lenr[], + int iperm[], int pr[], int arp[], int cv[], int out[]) +{ int i, ii, in1, in2, j, j1, jord, k, kk, numnz; + /* Initialization of arrays. */ + for (i = 1; i <= n; i++) + { arp[i] = lenr[i] - 1; + cv[i] = iperm[i] = 0; + } + numnz = 0; + /* Main loop. */ + /* Each pass round this loop either results in a new assignment + * or gives a row with no assignment. */ + for (jord = 1; jord <= n; jord++) + { j = jord; + pr[j] = -1; + for (k = 1; k <= jord; k++) + { /* Look for a cheap assignment. */ + in1 = arp[j]; + if (in1 >= 0) + { in2 = ip[j] + lenr[j] - 1; + in1 = in2 - in1; + for (ii = in1; ii <= in2; ii++) + { i = icn[ii]; + if (iperm[i] == 0) goto L110; + } + /* No cheap assignment in row. */ + arp[j] = -1; + } + /* Begin looking for assignment chain starting with row j.*/ + out[j] = lenr[j] - 1; + /* Inner loop. Extends chain by one or backtracks. */ + for (kk = 1; kk <= jord; kk++) + { in1 = out[j]; + if (in1 >= 0) + { in2 = ip[j] + lenr[j] - 1; + in1 = in2 - in1; + /* Forward scan. */ + for (ii = in1; ii <= in2; ii++) + { i = icn[ii]; + if (cv[i] != jord) + { /* Column i has not yet been accessed during + * this pass. */ + j1 = j; + j = iperm[i]; + cv[i] = jord; + pr[j] = j1; + out[j1] = in2 - ii - 1; + goto L100; + } + } + } + /* Backtracking step. */ + j = pr[j]; + if (j == -1) goto L130; + } +L100: ; + } +L110: /* New assignment is made. */ + iperm[i] = j; + arp[j] = in2 - ii - 1; + numnz++; + for (k = 1; k <= jord; k++) + { j = pr[j]; + if (j == -1) break; + ii = ip[j] + lenr[j] - out[j] - 2; + i = icn[ii]; + iperm[i] = j; + } +L130: ; + } + /* If matrix is structurally singular, we now complete the + * permutation iperm. */ + if (numnz < n) + { for (i = 1; i <= n; i++) + arp[i] = 0; + k = 0; + for (i = 1; i <= n; i++) + { if (iperm[i] == 0) + out[++k] = i; + else + arp[iperm[i]] = i; + } + k = 0; + for (i = 1; i <= n; i++) + { if (arp[i] == 0) + iperm[out[++k]] = i; + } + } + return numnz; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "env.h" + +int sing; + +void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, + int iw[]); + +void fa01bs(int max, int *nrand); + +int main(void) +{ /* test program for the routine mc21a */ + /* these runs on random matrices cause all possible statements in + * mc21a to be executed */ + int i, iold, j, j1, j2, jj, knum, l, licn, n, nov4, num, numnz; + int ip[1+21], icn[1+1000], iperm[1+20], lenr[1+20], iw1[1+80]; + licn = 1000; + /* run on random matrices of orders 1 through 20 */ + for (n = 1; n <= 20; n++) + { nov4 = n / 4; + if (nov4 < 1) nov4 = 1; +L10: fa01bs(nov4, &l); + knum = l * n; + /* knum is requested number of non-zeros in random matrix */ + if (knum > licn) goto L10; + /* if sing is false, matrix is guaranteed structurally + * non-singular */ + sing = ((n / 2) * 2 == n); + /* call to subroutine to generate random matrix */ + ranmat(n, n, icn, ip, n+1, &knum, iw1); + /* knum is now actual number of non-zeros in random matrix */ + if (knum > licn) goto L10; + xprintf("n = %2d; nz = %4d; sing = %d\n", n, knum, sing); + /* set up array of row lengths */ + for (i = 1; i <= n; i++) + lenr[i] = ip[i+1] - ip[i]; + /* call to mc21a */ + numnz = mc21a(n, icn, ip, lenr, iperm, &iw1[0], &iw1[n], + &iw1[n+n], &iw1[n+n+n]); + /* testing to see if there are numnz non-zeros on the diagonal + * of the permuted matrix. */ + num = 0; + for (i = 1; i <= n; i++) + { iold = iperm[i]; + j1 = ip[iold]; + j2 = j1 + lenr[iold] - 1; + if (j2 < j1) continue; + for (jj = j1; jj <= j2; jj++) + { j = icn[jj]; + if (j == i) + { num++; + break; + } + } + } + if (num != numnz) + xprintf("Failure in mc21a, numnz = %d instead of %d\n", + numnz, num); + } + return 0; +} + +void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, + int iw[]) +{ /* subroutine to generate random matrix */ + int i, ii, inum, j, lrow, matnum; + inum = (*knum / n) * 2; + if (inum > n-1) inum = n-1; + matnum = 1; + /* each pass through this loop generates a row of the matrix */ + for (j = 1; j <= m; j++) + { iptr[j] = matnum; + if (!(sing || j > n)) + icn[matnum++] = j; + if (n == 1) continue; + for (i = 1; i <= n; i++) iw[i] = 0; + if (!sing) iw[j] = 1; + fa01bs(inum, &lrow); + lrow--; + if (lrow == 0) continue; + /* lrow off-diagonal non-zeros in row j of the matrix */ + for (ii = 1; ii <= lrow; ii++) + { for (;;) + { fa01bs(n, &i); + if (iw[i] != 1) break; + } + iw[i] = 1; + icn[matnum++] = i; + } + } + for (i = m+1; i <= nnnp1; i++) + iptr[i] = matnum; + *knum = matnum - 1; + return; +} + +double g = 1431655765.0; + +double fa01as(int i) +{ /* random number generator */ + g = fmod(g * 9228907.0, 4294967296.0); + if (i >= 0) + return g / 4294967296.0; + else + return 2.0 * g / 4294967296.0 - 1.0; +} + +void fa01bs(int max, int *nrand) +{ *nrand = (int)(fa01as(1) * (double)max) + 1; + return; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.h new file mode 100644 index 000000000..755f28b22 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mc21a.h @@ -0,0 +1,34 @@ +/* mc21a.h (permutations for zero-free diagonal) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MC21A_H +#define MC21A_H + +#define mc21a _glp_mc21a +int mc21a(int n, const int icn[], const int ip[], const int lenr[], + int iperm[], int pr[], int arp[], int cv[], int out[]); +/* permutations for zero-free diagonal */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/misc.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/misc.h new file mode 100644 index 000000000..1ba1dc505 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/misc.h @@ -0,0 +1,61 @@ +/* misc.h (miscellaneous routines) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MISC_H +#define MISC_H + +#define str2int _glp_str2int +int str2int(const char *str, int *val); +/* convert character string to value of int type */ + +#define str2num _glp_str2num +int str2num(const char *str, double *val); +/* convert character string to value of double type */ + +#define strspx _glp_strspx +char *strspx(char *str); +/* remove all spaces from character string */ + +#define strtrim _glp_strtrim +char *strtrim(char *str); +/* remove trailing spaces from character string */ + +#define gcd _glp_gcd +int gcd(int x, int y); +/* find greatest common divisor of two integers */ + +#define gcdn _glp_gcdn +int gcdn(int n, int x[]); +/* find greatest common divisor of n integers */ + +#define round2n _glp_round2n +double round2n(double x); +/* round floating-point number to nearest power of two */ + +#define fp2rat _glp_fp2rat +int fp2rat(double x, double eps, double *p, double *q); +/* convert floating-point number to rational number */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.c new file mode 100644 index 000000000..63a0f80ed --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.c @@ -0,0 +1,1110 @@ +/* mt1.c (0-1 knapsack problem; Martello & Toth algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES +* MT1 FROM THE BOOK: +* +* SILVANO MARTELLO, PAOLO TOTH. KNAPSACK PROBLEMS: ALGORITHMS AND +* COMPUTER IMPLEMENTATIONS. JOHN WILEY & SONS, 1990. +* +* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS OF +* THE ORIGINAL FORTRAN SUBROUTINES: SILVANO MARTELLO AND PAOLO TOTH. +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#line 1 "" +/* -- translated by f2c (version 20100827). + You must link the resulting object file with libf2c: + on Microsoft Windows system, link with libf2c.lib; + on Linux or Unix systems, link with .../path/to/libf2c.a -lm + or, if you install libf2c.a in a standard place, with -lf2c -lm + -- in that order, at the end of the command line, as in + cc *.o -lf2c -lm + Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., + + http://www.netlib.org/f2c/libf2c.zip +*/ + +#if 0 /* by mao */ +#include "f2c.h" +#else +#include "env.h" +#include "mt1.h" + +typedef int integer; +typedef float real; +#endif + +#line 1 "" +/*< SUBROUTINE MT1(N,P,W,C,Z,X,JDIM,JCK,XX,MIN,PSIGN,WSIGN,ZSIGN) >*/ +#if 1 /* by mao */ +static int chmt1_(int *, int *, int *, int *, int *, int *); + +static +#endif +/* Subroutine */ int mt1_(integer *n, integer *p, integer *w, integer *c__, + integer *z__, integer *x, integer *jdim, integer *jck, integer *xx, + integer *min__, integer *psign, integer *wsign, integer *zsign) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + static real a, b; + static integer j, r__, t, j1, n1, ch, ii, jj, kk, in, ll, ip, nn, iu, ii1, + chs, lim, lim1, diff, lold, mink; + extern /* Subroutine */ int chmt1_(integer *, integer *, integer *, + integer *, integer *, integer *); + static integer profit; + + +/* THIS SUBROUTINE SOLVES THE 0-1 SINGLE KNAPSACK PROBLEM */ + +/* MAXIMIZE Z = P(1)*X(1) + ... + P(N)*X(N) */ + +/* SUBJECT TO: W(1)*X(1) + ... + W(N)*X(N) .LE. C , */ +/* X(J) = 0 OR 1 FOR J=1,...,N. */ + +/* THE PROGRAM IS INCLUDED IN THE VOLUME */ +/* S. MARTELLO, P. TOTH, "KNAPSACK PROBLEMS: ALGORITHMS */ +/* AND COMPUTER IMPLEMENTATIONS", JOHN WILEY, 1990 */ +/* AND IMPLEMENTS THE BRANCH-AND-BOUND ALGORITHM DESCRIBED IN */ +/* SECTION 2.5.2 . */ +/* THE PROGRAM DERIVES FROM AN EARLIER CODE PRESENTED IN */ +/* S. MARTELLO, P. TOTH, "ALGORITHM FOR THE SOLUTION OF THE 0-1 SINGLE */ +/* KNAPSACK PROBLEM", COMPUTING, 1978. */ + +/* THE INPUT PROBLEM MUST SATISFY THE CONDITIONS */ + +/* 1) 2 .LE. N .LE. JDIM - 1 ; */ +/* 2) P(J), W(J), C POSITIVE INTEGERS; */ +/* 3) MAX (W(J)) .LE. C ; */ +/* 4) W(1) + ... + W(N) .GT. C ; */ +/* 5) P(J)/W(J) .GE. P(J+1)/W(J+1) FOR J=1,...,N-1. */ + +/* MT1 CALLS 1 PROCEDURE: CHMT1. */ + +/* THE PROGRAM IS COMPLETELY SELF-CONTAINED AND COMMUNICATION TO IT IS */ +/* ACHIEVED SOLELY THROUGH THE PARAMETER LIST OF MT1. */ +/* NO MACHINE-DEPENDENT CONSTANT IS USED. */ +/* THE PROGRAM IS WRITTEN IN 1967 AMERICAN NATIONAL STANDARD FORTRAN */ +/* AND IS ACCEPTED BY THE PFORT VERIFIER (PFORT IS THE PORTABLE */ +/* SUBSET OF ANSI DEFINED BY THE ASSOCIATION FOR COMPUTING MACHINERY). */ +/* THE PROGRAM HAS BEEN TESTED ON A DIGITAL VAX 11/780 AND AN H.P. */ +/* 9000/840. */ + +/* MT1 NEEDS 8 ARRAYS ( P , W , X , XX , MIN , PSIGN , WSIGN */ +/* AND ZSIGN ) OF LENGTH AT LEAST N + 1 . */ + +/* MEANING OF THE INPUT PARAMETERS: */ +/* N = NUMBER OF ITEMS; */ +/* P(J) = PROFIT OF ITEM J (J=1,...,N); */ +/* W(J) = WEIGHT OF ITEM J (J=1,...,N); */ +/* C = CAPACITY OF THE KNAPSACK; */ +/* JDIM = DIMENSION OF THE 8 ARRAYS; */ +/* JCK = 1 IF CHECK ON THE INPUT DATA IS DESIRED, */ +/* = 0 OTHERWISE. */ + +/* MEANING OF THE OUTPUT PARAMETERS: */ +/* Z = VALUE OF THE OPTIMAL SOLUTION IF Z .GT. 0 , */ +/* = ERROR IN THE INPUT DATA (WHEN JCK=1) IF Z .LT. 0 : CONDI- */ +/* TION - Z IS VIOLATED; */ +/* X(J) = 1 IF ITEM J IS IN THE OPTIMAL SOLUTION, */ +/* = 0 OTHERWISE. */ + +/* ARRAYS XX, MIN, PSIGN, WSIGN AND ZSIGN ARE DUMMY. */ + +/* ALL THE PARAMETERS ARE INTEGER. ON RETURN OF MT1 ALL THE INPUT */ +/* PARAMETERS ARE UNCHANGED. */ + +/*< INTEGER P(JDIM),W(JDIM),X(JDIM),C,Z >*/ +/*< INTEGER XX(JDIM),MIN(JDIM),PSIGN(JDIM),WSIGN(JDIM),ZSIGN(JDIM) >*/ +/*< INTEGER CH,CHS,DIFF,PROFIT,R,T >*/ +/*< Z = 0 >*/ +#line 65 "" + /* Parameter adjustments */ +#line 65 "" + --zsign; +#line 65 "" + --wsign; +#line 65 "" + --psign; +#line 65 "" + --min__; +#line 65 "" + --xx; +#line 65 "" + --x; +#line 65 "" + --w; +#line 65 "" + --p; +#line 65 "" + +#line 65 "" + /* Function Body */ +#line 65 "" + *z__ = 0; +/*< IF ( JCK .EQ. 1 ) CALL CHMT1(N,P,W,C,Z,JDIM) >*/ +#line 66 "" + if (*jck == 1) { +#line 66 "" + chmt1_(n, &p[1], &w[1], c__, z__, jdim); +#line 66 "" + } +/*< IF ( Z .LT. 0 ) RETURN >*/ +#line 67 "" + if (*z__ < 0) { +#line 67 "" + return 0; +#line 67 "" + } +/* INITIALIZE. */ +/*< CH = C >*/ +#line 69 "" + ch = *c__; +/*< IP = 0 >*/ +#line 70 "" + ip = 0; +/*< CHS = CH >*/ +#line 71 "" + chs = ch; +/*< DO 10 LL=1,N >*/ +#line 72 "" + i__1 = *n; +#line 72 "" + for (ll = 1; ll <= i__1; ++ll) { +/*< IF ( W(LL) .GT. CHS ) GO TO 20 >*/ +#line 73 "" + if (w[ll] > chs) { +#line 73 "" + goto L20; +#line 73 "" + } +/*< IP = IP + P(LL) >*/ +#line 74 "" + ip += p[ll]; +/*< CHS = CHS - W(LL) >*/ +#line 75 "" + chs -= w[ll]; +/*< 10 CONTINUE >*/ +#line 76 "" +/* L10: */ +#line 76 "" + } +/*< 20 LL = LL - 1 >*/ +#line 77 "" +L20: +#line 77 "" + --ll; +/*< IF ( CHS .EQ. 0 ) GO TO 50 >*/ +#line 78 "" + if (chs == 0) { +#line 78 "" + goto L50; +#line 78 "" + } +/*< P(N+1) = 0 >*/ +#line 79 "" + p[*n + 1] = 0; +/*< W(N+1) = CH + 1 >*/ +#line 80 "" + w[*n + 1] = ch + 1; +/*< LIM = IP + CHS*P(LL+2)/W(LL+2) >*/ +#line 81 "" + lim = ip + chs * p[ll + 2] / w[ll + 2]; +/*< A = W(LL+1) - CHS >*/ +#line 82 "" + a = (real) (w[ll + 1] - chs); +/*< B = IP + P(LL+1) >*/ +#line 83 "" + b = (real) (ip + p[ll + 1]); +/*< LIM1 = B - A*FLOAT(P(LL))/FLOAT(W(LL)) >*/ +#line 84 "" + lim1 = b - a * (real) p[ll] / (real) w[ll]; +/*< IF ( LIM1 .GT. LIM ) LIM = LIM1 >*/ +#line 85 "" + if (lim1 > lim) { +#line 85 "" + lim = lim1; +#line 85 "" + } +/*< MINK = CH + 1 >*/ +#line 86 "" + mink = ch + 1; +/*< MIN(N) = MINK >*/ +#line 87 "" + min__[*n] = mink; +/*< DO 30 J=2,N >*/ +#line 88 "" + i__1 = *n; +#line 88 "" + for (j = 2; j <= i__1; ++j) { +/*< KK = N + 2 - J >*/ +#line 89 "" + kk = *n + 2 - j; +/*< IF ( W(KK) .LT. MINK ) MINK = W(KK) >*/ +#line 90 "" + if (w[kk] < mink) { +#line 90 "" + mink = w[kk]; +#line 90 "" + } +/*< MIN(KK-1) = MINK >*/ +#line 91 "" + min__[kk - 1] = mink; +/*< 30 CONTINUE >*/ +#line 92 "" +/* L30: */ +#line 92 "" + } +/*< DO 40 J=1,N >*/ +#line 93 "" + i__1 = *n; +#line 93 "" + for (j = 1; j <= i__1; ++j) { +/*< XX(J) = 0 >*/ +#line 94 "" + xx[j] = 0; +/*< 40 CONTINUE >*/ +#line 95 "" +/* L40: */ +#line 95 "" + } +/*< Z = 0 >*/ +#line 96 "" + *z__ = 0; +/*< PROFIT = 0 >*/ +#line 97 "" + profit = 0; +/*< LOLD = N >*/ +#line 98 "" + lold = *n; +/*< II = 1 >*/ +#line 99 "" + ii = 1; +/*< GO TO 170 >*/ +#line 100 "" + goto L170; +/*< 50 Z = IP >*/ +#line 101 "" +L50: +#line 101 "" + *z__ = ip; +/*< DO 60 J=1,LL >*/ +#line 102 "" + i__1 = ll; +#line 102 "" + for (j = 1; j <= i__1; ++j) { +/*< X(J) = 1 >*/ +#line 103 "" + x[j] = 1; +/*< 60 CONTINUE >*/ +#line 104 "" +/* L60: */ +#line 104 "" + } +/*< NN = LL + 1 >*/ +#line 105 "" + nn = ll + 1; +/*< DO 70 J=NN,N >*/ +#line 106 "" + i__1 = *n; +#line 106 "" + for (j = nn; j <= i__1; ++j) { +/*< X(J) = 0 >*/ +#line 107 "" + x[j] = 0; +/*< 70 CONTINUE >*/ +#line 108 "" +/* L70: */ +#line 108 "" + } +/*< RETURN >*/ +#line 109 "" + return 0; +/* TRY TO INSERT THE II-TH ITEM INTO THE CURRENT SOLUTION. */ +/*< 80 IF ( W(II) .LE. CH ) GO TO 90 >*/ +#line 111 "" +L80: +#line 111 "" + if (w[ii] <= ch) { +#line 111 "" + goto L90; +#line 111 "" + } +/*< II1 = II + 1 >*/ +#line 112 "" + ii1 = ii + 1; +/*< IF ( Z .GE. CH*P(II1)/W(II1) + PROFIT ) GO TO 280 >*/ +#line 113 "" + if (*z__ >= ch * p[ii1] / w[ii1] + profit) { +#line 113 "" + goto L280; +#line 113 "" + } +/*< II = II1 >*/ +#line 114 "" + ii = ii1; +/*< GO TO 80 >*/ +#line 115 "" + goto L80; +/* BUILD A NEW CURRENT SOLUTION. */ +/*< 90 IP = PSIGN(II) >*/ +#line 117 "" +L90: +#line 117 "" + ip = psign[ii]; +/*< CHS = CH - WSIGN(II) >*/ +#line 118 "" + chs = ch - wsign[ii]; +/*< IN = ZSIGN(II) >*/ +#line 119 "" + in = zsign[ii]; +/*< DO 100 LL=IN,N >*/ +#line 120 "" + i__1 = *n; +#line 120 "" + for (ll = in; ll <= i__1; ++ll) { +/*< IF ( W(LL) .GT. CHS ) GO TO 160 >*/ +#line 121 "" + if (w[ll] > chs) { +#line 121 "" + goto L160; +#line 121 "" + } +/*< IP = IP + P(LL) >*/ +#line 122 "" + ip += p[ll]; +/*< CHS = CHS - W(LL) >*/ +#line 123 "" + chs -= w[ll]; +/*< 100 CONTINUE >*/ +#line 124 "" +/* L100: */ +#line 124 "" + } +/*< LL = N >*/ +#line 125 "" + ll = *n; +/*< 110 IF ( Z .GE. IP + PROFIT ) GO TO 280 >*/ +#line 126 "" +L110: +#line 126 "" + if (*z__ >= ip + profit) { +#line 126 "" + goto L280; +#line 126 "" + } +/*< Z = IP + PROFIT >*/ +#line 127 "" + *z__ = ip + profit; +/*< NN = II - 1 >*/ +#line 128 "" + nn = ii - 1; +/*< DO 120 J=1,NN >*/ +#line 129 "" + i__1 = nn; +#line 129 "" + for (j = 1; j <= i__1; ++j) { +/*< X(J) = XX(J) >*/ +#line 130 "" + x[j] = xx[j]; +/*< 120 CONTINUE >*/ +#line 131 "" +/* L120: */ +#line 131 "" + } +/*< DO 130 J=II,LL >*/ +#line 132 "" + i__1 = ll; +#line 132 "" + for (j = ii; j <= i__1; ++j) { +/*< X(J) = 1 >*/ +#line 133 "" + x[j] = 1; +/*< 130 CONTINUE >*/ +#line 134 "" +/* L130: */ +#line 134 "" + } +/*< IF ( LL .EQ. N ) GO TO 150 >*/ +#line 135 "" + if (ll == *n) { +#line 135 "" + goto L150; +#line 135 "" + } +/*< NN = LL + 1 >*/ +#line 136 "" + nn = ll + 1; +/*< DO 140 J=NN,N >*/ +#line 137 "" + i__1 = *n; +#line 137 "" + for (j = nn; j <= i__1; ++j) { +/*< X(J) = 0 >*/ +#line 138 "" + x[j] = 0; +/*< 140 CONTINUE >*/ +#line 139 "" +/* L140: */ +#line 139 "" + } +/*< 150 IF ( Z .NE. LIM ) GO TO 280 >*/ +#line 140 "" +L150: +#line 140 "" + if (*z__ != lim) { +#line 140 "" + goto L280; +#line 140 "" + } +/*< RETURN >*/ +#line 141 "" + return 0; +/*< 160 IU = CHS*P(LL)/W(LL) >*/ +#line 142 "" +L160: +#line 142 "" + iu = chs * p[ll] / w[ll]; +/*< LL = LL - 1 >*/ +#line 143 "" + --ll; +/*< IF ( IU .EQ. 0 ) GO TO 110 >*/ +#line 144 "" + if (iu == 0) { +#line 144 "" + goto L110; +#line 144 "" + } +/*< IF ( Z .GE. PROFIT + IP + IU ) GO TO 280 >*/ +#line 145 "" + if (*z__ >= profit + ip + iu) { +#line 145 "" + goto L280; +#line 145 "" + } +/* SAVE THE CURRENT SOLUTION. */ +/*< 170 WSIGN(II) = CH - CHS >*/ +#line 147 "" +L170: +#line 147 "" + wsign[ii] = ch - chs; +/*< PSIGN(II) = IP >*/ +#line 148 "" + psign[ii] = ip; +/*< ZSIGN(II) = LL + 1 >*/ +#line 149 "" + zsign[ii] = ll + 1; +/*< XX(II) = 1 >*/ +#line 150 "" + xx[ii] = 1; +/*< NN = LL - 1 >*/ +#line 151 "" + nn = ll - 1; +/*< IF ( NN .LT. II) GO TO 190 >*/ +#line 152 "" + if (nn < ii) { +#line 152 "" + goto L190; +#line 152 "" + } +/*< DO 180 J=II,NN >*/ +#line 153 "" + i__1 = nn; +#line 153 "" + for (j = ii; j <= i__1; ++j) { +/*< WSIGN(J+1) = WSIGN(J) - W(J) >*/ +#line 154 "" + wsign[j + 1] = wsign[j] - w[j]; +/*< PSIGN(J+1) = PSIGN(J) - P(J) >*/ +#line 155 "" + psign[j + 1] = psign[j] - p[j]; +/*< ZSIGN(J+1) = LL + 1 >*/ +#line 156 "" + zsign[j + 1] = ll + 1; +/*< XX(J+1) = 1 >*/ +#line 157 "" + xx[j + 1] = 1; +/*< 180 CONTINUE >*/ +#line 158 "" +/* L180: */ +#line 158 "" + } +/*< 190 J1 = LL + 1 >*/ +#line 159 "" +L190: +#line 159 "" + j1 = ll + 1; +/*< DO 200 J=J1,LOLD >*/ +#line 160 "" + i__1 = lold; +#line 160 "" + for (j = j1; j <= i__1; ++j) { +/*< WSIGN(J) = 0 >*/ +#line 161 "" + wsign[j] = 0; +/*< PSIGN(J) = 0 >*/ +#line 162 "" + psign[j] = 0; +/*< ZSIGN(J) = J >*/ +#line 163 "" + zsign[j] = j; +/*< 200 CONTINUE >*/ +#line 164 "" +/* L200: */ +#line 164 "" + } +/*< LOLD = LL >*/ +#line 165 "" + lold = ll; +/*< CH = CHS >*/ +#line 166 "" + ch = chs; +/*< PROFIT = PROFIT + IP >*/ +#line 167 "" + profit += ip; +/*< IF ( LL - (N - 2) ) 240, 220, 210 >*/ +#line 168 "" + if ((i__1 = ll - (*n - 2)) < 0) { +#line 168 "" + goto L240; +#line 168 "" + } else if (i__1 == 0) { +#line 168 "" + goto L220; +#line 168 "" + } else { +#line 168 "" + goto L210; +#line 168 "" + } +/*< 210 II = N >*/ +#line 169 "" +L210: +#line 169 "" + ii = *n; +/*< GO TO 250 >*/ +#line 170 "" + goto L250; +/*< 220 IF ( CH .LT. W(N) ) GO TO 230 >*/ +#line 171 "" +L220: +#line 171 "" + if (ch < w[*n]) { +#line 171 "" + goto L230; +#line 171 "" + } +/*< CH = CH - W(N) >*/ +#line 172 "" + ch -= w[*n]; +/*< PROFIT = PROFIT + P(N) >*/ +#line 173 "" + profit += p[*n]; +/*< XX(N) = 1 >*/ +#line 174 "" + xx[*n] = 1; +/*< 230 II = N - 1 >*/ +#line 175 "" +L230: +#line 175 "" + ii = *n - 1; +/*< GO TO 250 >*/ +#line 176 "" + goto L250; +/*< 240 II = LL + 2 >*/ +#line 177 "" +L240: +#line 177 "" + ii = ll + 2; +/*< IF ( CH .GE. MIN(II-1) ) GO TO 80 >*/ +#line 178 "" + if (ch >= min__[ii - 1]) { +#line 178 "" + goto L80; +#line 178 "" + } +/* SAVE THE CURRENT OPTIMAL SOLUTION. */ +/*< 250 IF ( Z .GE. PROFIT ) GO TO 270 >*/ +#line 180 "" +L250: +#line 180 "" + if (*z__ >= profit) { +#line 180 "" + goto L270; +#line 180 "" + } +/*< Z = PROFIT >*/ +#line 181 "" + *z__ = profit; +/*< DO 260 J=1,N >*/ +#line 182 "" + i__1 = *n; +#line 182 "" + for (j = 1; j <= i__1; ++j) { +/*< X(J) = XX(J) >*/ +#line 183 "" + x[j] = xx[j]; +/*< 260 CONTINUE >*/ +#line 184 "" +/* L260: */ +#line 184 "" + } +/*< IF ( Z .EQ. LIM ) RETURN >*/ +#line 185 "" + if (*z__ == lim) { +#line 185 "" + return 0; +#line 185 "" + } +/*< 270 IF ( XX(N) .EQ. 0 ) GO TO 280 >*/ +#line 186 "" +L270: +#line 186 "" + if (xx[*n] == 0) { +#line 186 "" + goto L280; +#line 186 "" + } +/*< XX(N) = 0 >*/ +#line 187 "" + xx[*n] = 0; +/*< CH = CH + W(N) >*/ +#line 188 "" + ch += w[*n]; +/*< PROFIT = PROFIT - P(N) >*/ +#line 189 "" + profit -= p[*n]; +/* BACKTRACK. */ +/*< 280 NN = II - 1 >*/ +#line 191 "" +L280: +#line 191 "" + nn = ii - 1; +/*< IF ( NN .EQ. 0 ) RETURN >*/ +#line 192 "" + if (nn == 0) { +#line 192 "" + return 0; +#line 192 "" + } +/*< DO 290 J=1,NN >*/ +#line 193 "" + i__1 = nn; +#line 193 "" + for (j = 1; j <= i__1; ++j) { +/*< KK = II - J >*/ +#line 194 "" + kk = ii - j; +/*< IF ( XX(KK) .EQ. 1 ) GO TO 300 >*/ +#line 195 "" + if (xx[kk] == 1) { +#line 195 "" + goto L300; +#line 195 "" + } +/*< 290 CONTINUE >*/ +#line 196 "" +/* L290: */ +#line 196 "" + } +/*< RETURN >*/ +#line 197 "" + return 0; +/*< 300 R = CH >*/ +#line 198 "" +L300: +#line 198 "" + r__ = ch; +/*< CH = CH + W(KK) >*/ +#line 199 "" + ch += w[kk]; +/*< PROFIT = PROFIT - P(KK) >*/ +#line 200 "" + profit -= p[kk]; +/*< XX(KK) = 0 >*/ +#line 201 "" + xx[kk] = 0; +/*< IF ( R .LT. MIN(KK) ) GO TO 310 >*/ +#line 202 "" + if (r__ < min__[kk]) { +#line 202 "" + goto L310; +#line 202 "" + } +/*< II = KK + 1 >*/ +#line 203 "" + ii = kk + 1; +/*< GO TO 80 >*/ +#line 204 "" + goto L80; +/*< 310 NN = KK + 1 >*/ +#line 205 "" +L310: +#line 205 "" + nn = kk + 1; +/*< II = KK >*/ +#line 206 "" + ii = kk; +/* TRY TO SUBSTITUTE THE NN-TH ITEM FOR THE KK-TH. */ +/*< 320 IF ( Z .GE. PROFIT + CH*P(NN)/W(NN) ) GO TO 280 >*/ +#line 208 "" +L320: +#line 208 "" + if (*z__ >= profit + ch * p[nn] / w[nn]) { +#line 208 "" + goto L280; +#line 208 "" + } +/*< DIFF = W(NN) - W(KK) >*/ +#line 209 "" + diff = w[nn] - w[kk]; +/*< IF ( DIFF ) 370, 330, 340 >*/ +#line 210 "" + if (diff < 0) { +#line 210 "" + goto L370; +#line 210 "" + } else if (diff == 0) { +#line 210 "" + goto L330; +#line 210 "" + } else { +#line 210 "" + goto L340; +#line 210 "" + } +/*< 330 NN = NN + 1 >*/ +#line 211 "" +L330: +#line 211 "" + ++nn; +/*< GO TO 320 >*/ +#line 212 "" + goto L320; +/*< 340 IF ( DIFF .GT. R ) GO TO 330 >*/ +#line 213 "" +L340: +#line 213 "" + if (diff > r__) { +#line 213 "" + goto L330; +#line 213 "" + } +/*< IF ( Z .GE. PROFIT + P(NN) ) GO TO 330 >*/ +#line 214 "" + if (*z__ >= profit + p[nn]) { +#line 214 "" + goto L330; +#line 214 "" + } +/*< Z = PROFIT + P(NN) >*/ +#line 215 "" + *z__ = profit + p[nn]; +/*< DO 350 J=1,KK >*/ +#line 216 "" + i__1 = kk; +#line 216 "" + for (j = 1; j <= i__1; ++j) { +/*< X(J) = XX(J) >*/ +#line 217 "" + x[j] = xx[j]; +/*< 350 CONTINUE >*/ +#line 218 "" +/* L350: */ +#line 218 "" + } +/*< JJ = KK + 1 >*/ +#line 219 "" + jj = kk + 1; +/*< DO 360 J=JJ,N >*/ +#line 220 "" + i__1 = *n; +#line 220 "" + for (j = jj; j <= i__1; ++j) { +/*< X(J) = 0 >*/ +#line 221 "" + x[j] = 0; +/*< 360 CONTINUE >*/ +#line 222 "" +/* L360: */ +#line 222 "" + } +/*< X(NN) = 1 >*/ +#line 223 "" + x[nn] = 1; +/*< IF ( Z .EQ. LIM ) RETURN >*/ +#line 224 "" + if (*z__ == lim) { +#line 224 "" + return 0; +#line 224 "" + } +/*< R = R - DIFF >*/ +#line 225 "" + r__ -= diff; +/*< KK = NN >*/ +#line 226 "" + kk = nn; +/*< NN = NN + 1 >*/ +#line 227 "" + ++nn; +/*< GO TO 320 >*/ +#line 228 "" + goto L320; +/*< 370 T = R - DIFF >*/ +#line 229 "" +L370: +#line 229 "" + t = r__ - diff; +/*< IF ( T .LT. MIN(NN) ) GO TO 330 >*/ +#line 230 "" + if (t < min__[nn]) { +#line 230 "" + goto L330; +#line 230 "" + } +/*< IF ( Z .GE. PROFIT + P(NN) + T*P(NN+1)/W(NN+1)) GO TO 280 >*/ +#line 231 "" + if (*z__ >= profit + p[nn] + t * p[nn + 1] / w[nn + 1]) { +#line 231 "" + goto L280; +#line 231 "" + } +/*< CH = CH - W(NN) >*/ +#line 232 "" + ch -= w[nn]; +/*< PROFIT = PROFIT + P(NN) >*/ +#line 233 "" + profit += p[nn]; +/*< XX(NN) = 1 >*/ +#line 234 "" + xx[nn] = 1; +/*< II = NN + 1 >*/ +#line 235 "" + ii = nn + 1; +/*< WSIGN(NN) = W(NN) >*/ +#line 236 "" + wsign[nn] = w[nn]; +/*< PSIGN(NN) = P(NN) >*/ +#line 237 "" + psign[nn] = p[nn]; +/*< ZSIGN(NN) = II >*/ +#line 238 "" + zsign[nn] = ii; +/*< N1 = NN + 1 >*/ +#line 239 "" + n1 = nn + 1; +/*< DO 380 J=N1,LOLD >*/ +#line 240 "" + i__1 = lold; +#line 240 "" + for (j = n1; j <= i__1; ++j) { +/*< WSIGN(J) = 0 >*/ +#line 241 "" + wsign[j] = 0; +/*< PSIGN(J) = 0 >*/ +#line 242 "" + psign[j] = 0; +/*< ZSIGN(J) = J >*/ +#line 243 "" + zsign[j] = j; +/*< 380 CONTINUE >*/ +#line 244 "" +/* L380: */ +#line 244 "" + } +/*< LOLD = NN >*/ +#line 245 "" + lold = nn; +/*< GO TO 80 >*/ +#line 246 "" + goto L80; +/*< END >*/ +} /* mt1_ */ + +/*< SUBROUTINE CHMT1(N,P,W,C,Z,JDIM) >*/ +#if 1 /* by mao */ +static +#endif +/* Subroutine */ int chmt1_(integer *n, integer *p, integer *w, integer *c__, + integer *z__, integer *jdim) +{ + /* System generated locals */ + integer i__1; + + /* Local variables */ + static integer j; + static real r__, rr; + static integer jsw; + + +/* CHECK THE INPUT DATA. */ + +/*< INTEGER P(JDIM),W(JDIM),C,Z >*/ +/*< IF ( N .GE. 2 .AND. N .LE. JDIM - 1 ) GO TO 10 >*/ +#line 253 "" + /* Parameter adjustments */ +#line 253 "" + --w; +#line 253 "" + --p; +#line 253 "" + +#line 253 "" + /* Function Body */ +#line 253 "" + if (*n >= 2 && *n <= *jdim - 1) { +#line 253 "" + goto L10; +#line 253 "" + } +/*< Z = - 1 >*/ +#line 254 "" + *z__ = -1; +/*< RETURN >*/ +#line 255 "" + return 0; +/*< 10 IF ( C .GT. 0 ) GO TO 30 >*/ +#line 256 "" +L10: +#line 256 "" + if (*c__ > 0) { +#line 256 "" + goto L30; +#line 256 "" + } +/*< 20 Z = - 2 >*/ +#line 257 "" +L20: +#line 257 "" + *z__ = -2; +/*< RETURN >*/ +#line 258 "" + return 0; +/*< 30 JSW = 0 >*/ +#line 259 "" +L30: +#line 259 "" + jsw = 0; +/*< RR = FLOAT(P(1))/FLOAT(W(1)) >*/ +#line 260 "" + rr = (real) p[1] / (real) w[1]; +/*< DO 50 J=1,N >*/ +#line 261 "" + i__1 = *n; +#line 261 "" + for (j = 1; j <= i__1; ++j) { +/*< R = RR >*/ +#line 262 "" + r__ = rr; +/*< IF ( P(J) .LE. 0 ) GO TO 20 >*/ +#line 263 "" + if (p[j] <= 0) { +#line 263 "" + goto L20; +#line 263 "" + } +/*< IF ( W(J) .LE. 0 ) GO TO 20 >*/ +#line 264 "" + if (w[j] <= 0) { +#line 264 "" + goto L20; +#line 264 "" + } +/*< JSW = JSW + W(J) >*/ +#line 265 "" + jsw += w[j]; +/*< IF ( W(J) .LE. C ) GO TO 40 >*/ +#line 266 "" + if (w[j] <= *c__) { +#line 266 "" + goto L40; +#line 266 "" + } +/*< Z = - 3 >*/ +#line 267 "" + *z__ = -3; +/*< RETURN >*/ +#line 268 "" + return 0; +/*< 40 RR = FLOAT(P(J))/FLOAT(W(J)) >*/ +#line 269 "" +L40: +#line 269 "" + rr = (real) p[j] / (real) w[j]; +/*< IF ( RR .LE. R ) GO TO 50 >*/ +#line 270 "" + if (rr <= r__) { +#line 270 "" + goto L50; +#line 270 "" + } +/*< Z = - 5 >*/ +#line 271 "" + *z__ = -5; +/*< RETURN >*/ +#line 272 "" + return 0; +/*< 50 CONTINUE >*/ +#line 273 "" +L50: +#line 273 "" + ; +#line 273 "" + } +/*< IF ( JSW .GT. C ) RETURN >*/ +#line 274 "" + if (jsw > *c__) { +#line 274 "" + return 0; +#line 274 "" + } +/*< Z = - 4 >*/ +#line 275 "" + *z__ = -4; +/*< RETURN >*/ +#line 276 "" + return 0; +/*< END >*/ +} /* chmt1_ */ + +#if 1 /* by mao */ +int mt1(int n, int p[], int w[], int c, int x[], int jck, int xx[], + int min[], int psign[], int wsign[], int zsign[]) +{ /* solve 0-1 knapsack problem */ + int z, jdim = n+1, j, s1, s2; + mt1_(&n, &p[1], &w[1], &c, &z, &x[1], &jdim, &jck, &xx[1], + &min[1], &psign[1], &wsign[1], &zsign[1]); + /* check solution found */ + s1 = s2 = 0; + for (j = 1; j <= n; j++) + { xassert(x[j] == 0 || x[j] == 1); + if (x[j]) + s1 += p[j], s2 += w[j]; + } + xassert(s1 == z); + xassert(s2 <= c); + return z; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.f b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.f new file mode 100644 index 000000000..82cc4a1be --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.f @@ -0,0 +1,277 @@ + SUBROUTINE MT1(N,P,W,C,Z,X,JDIM,JCK,XX,MIN,PSIGN,WSIGN,ZSIGN) +C +C THIS SUBROUTINE SOLVES THE 0-1 SINGLE KNAPSACK PROBLEM +C +C MAXIMIZE Z = P(1)*X(1) + ... + P(N)*X(N) +C +C SUBJECT TO: W(1)*X(1) + ... + W(N)*X(N) .LE. C , +C X(J) = 0 OR 1 FOR J=1,...,N. +C +C THE PROGRAM IS INCLUDED IN THE VOLUME +C S. MARTELLO, P. TOTH, "KNAPSACK PROBLEMS: ALGORITHMS +C AND COMPUTER IMPLEMENTATIONS", JOHN WILEY, 1990 +C AND IMPLEMENTS THE BRANCH-AND-BOUND ALGORITHM DESCRIBED IN +C SECTION 2.5.2 . +C THE PROGRAM DERIVES FROM AN EARLIER CODE PRESENTED IN +C S. MARTELLO, P. TOTH, "ALGORITHM FOR THE SOLUTION OF THE 0-1 SINGLE +C KNAPSACK PROBLEM", COMPUTING, 1978. +C +C THE INPUT PROBLEM MUST SATISFY THE CONDITIONS +C +C 1) 2 .LE. N .LE. JDIM - 1 ; +C 2) P(J), W(J), C POSITIVE INTEGERS; +C 3) MAX (W(J)) .LE. C ; +C 4) W(1) + ... + W(N) .GT. C ; +C 5) P(J)/W(J) .GE. P(J+1)/W(J+1) FOR J=1,...,N-1. +C +C MT1 CALLS 1 PROCEDURE: CHMT1. +C +C THE PROGRAM IS COMPLETELY SELF-CONTAINED AND COMMUNICATION TO IT IS +C ACHIEVED SOLELY THROUGH THE PARAMETER LIST OF MT1. +C NO MACHINE-DEPENDENT CONSTANT IS USED. +C THE PROGRAM IS WRITTEN IN 1967 AMERICAN NATIONAL STANDARD FORTRAN +C AND IS ACCEPTED BY THE PFORT VERIFIER (PFORT IS THE PORTABLE +C SUBSET OF ANSI DEFINED BY THE ASSOCIATION FOR COMPUTING MACHINERY). +C THE PROGRAM HAS BEEN TESTED ON A DIGITAL VAX 11/780 AND AN H.P. +C 9000/840. +C +C MT1 NEEDS 8 ARRAYS ( P , W , X , XX , MIN , PSIGN , WSIGN +C AND ZSIGN ) OF LENGTH AT LEAST N + 1 . +C +C MEANING OF THE INPUT PARAMETERS: +C N = NUMBER OF ITEMS; +C P(J) = PROFIT OF ITEM J (J=1,...,N); +C W(J) = WEIGHT OF ITEM J (J=1,...,N); +C C = CAPACITY OF THE KNAPSACK; +C JDIM = DIMENSION OF THE 8 ARRAYS; +C JCK = 1 IF CHECK ON THE INPUT DATA IS DESIRED, +C = 0 OTHERWISE. +C +C MEANING OF THE OUTPUT PARAMETERS: +C Z = VALUE OF THE OPTIMAL SOLUTION IF Z .GT. 0 , +C = ERROR IN THE INPUT DATA (WHEN JCK=1) IF Z .LT. 0 : CONDI- +C TION - Z IS VIOLATED; +C X(J) = 1 IF ITEM J IS IN THE OPTIMAL SOLUTION, +C = 0 OTHERWISE. +C +C ARRAYS XX, MIN, PSIGN, WSIGN AND ZSIGN ARE DUMMY. +C +C ALL THE PARAMETERS ARE INTEGER. ON RETURN OF MT1 ALL THE INPUT +C PARAMETERS ARE UNCHANGED. +C + INTEGER P(JDIM),W(JDIM),X(JDIM),C,Z + INTEGER XX(JDIM),MIN(JDIM),PSIGN(JDIM),WSIGN(JDIM),ZSIGN(JDIM) + INTEGER CH,CHS,DIFF,PROFIT,R,T + Z = 0 + IF ( JCK .EQ. 1 ) CALL CHMT1(N,P,W,C,Z,JDIM) + IF ( Z .LT. 0 ) RETURN +C INITIALIZE. + CH = C + IP = 0 + CHS = CH + DO 10 LL=1,N + IF ( W(LL) .GT. CHS ) GO TO 20 + IP = IP + P(LL) + CHS = CHS - W(LL) + 10 CONTINUE + 20 LL = LL - 1 + IF ( CHS .EQ. 0 ) GO TO 50 + P(N+1) = 0 + W(N+1) = CH + 1 + LIM = IP + CHS*P(LL+2)/W(LL+2) + A = W(LL+1) - CHS + B = IP + P(LL+1) + LIM1 = B - A*FLOAT(P(LL))/FLOAT(W(LL)) + IF ( LIM1 .GT. LIM ) LIM = LIM1 + MINK = CH + 1 + MIN(N) = MINK + DO 30 J=2,N + KK = N + 2 - J + IF ( W(KK) .LT. MINK ) MINK = W(KK) + MIN(KK-1) = MINK + 30 CONTINUE + DO 40 J=1,N + XX(J) = 0 + 40 CONTINUE + Z = 0 + PROFIT = 0 + LOLD = N + II = 1 + GO TO 170 + 50 Z = IP + DO 60 J=1,LL + X(J) = 1 + 60 CONTINUE + NN = LL + 1 + DO 70 J=NN,N + X(J) = 0 + 70 CONTINUE + RETURN +C TRY TO INSERT THE II-TH ITEM INTO THE CURRENT SOLUTION. + 80 IF ( W(II) .LE. CH ) GO TO 90 + II1 = II + 1 + IF ( Z .GE. CH*P(II1)/W(II1) + PROFIT ) GO TO 280 + II = II1 + GO TO 80 +C BUILD A NEW CURRENT SOLUTION. + 90 IP = PSIGN(II) + CHS = CH - WSIGN(II) + IN = ZSIGN(II) + DO 100 LL=IN,N + IF ( W(LL) .GT. CHS ) GO TO 160 + IP = IP + P(LL) + CHS = CHS - W(LL) + 100 CONTINUE + LL = N + 110 IF ( Z .GE. IP + PROFIT ) GO TO 280 + Z = IP + PROFIT + NN = II - 1 + DO 120 J=1,NN + X(J) = XX(J) + 120 CONTINUE + DO 130 J=II,LL + X(J) = 1 + 130 CONTINUE + IF ( LL .EQ. N ) GO TO 150 + NN = LL + 1 + DO 140 J=NN,N + X(J) = 0 + 140 CONTINUE + 150 IF ( Z .NE. LIM ) GO TO 280 + RETURN + 160 IU = CHS*P(LL)/W(LL) + LL = LL - 1 + IF ( IU .EQ. 0 ) GO TO 110 + IF ( Z .GE. PROFIT + IP + IU ) GO TO 280 +C SAVE THE CURRENT SOLUTION. + 170 WSIGN(II) = CH - CHS + PSIGN(II) = IP + ZSIGN(II) = LL + 1 + XX(II) = 1 + NN = LL - 1 + IF ( NN .LT. II) GO TO 190 + DO 180 J=II,NN + WSIGN(J+1) = WSIGN(J) - W(J) + PSIGN(J+1) = PSIGN(J) - P(J) + ZSIGN(J+1) = LL + 1 + XX(J+1) = 1 + 180 CONTINUE + 190 J1 = LL + 1 + DO 200 J=J1,LOLD + WSIGN(J) = 0 + PSIGN(J) = 0 + ZSIGN(J) = J + 200 CONTINUE + LOLD = LL + CH = CHS + PROFIT = PROFIT + IP + IF ( LL - (N - 2) ) 240, 220, 210 + 210 II = N + GO TO 250 + 220 IF ( CH .LT. W(N) ) GO TO 230 + CH = CH - W(N) + PROFIT = PROFIT + P(N) + XX(N) = 1 + 230 II = N - 1 + GO TO 250 + 240 II = LL + 2 + IF ( CH .GE. MIN(II-1) ) GO TO 80 +C SAVE THE CURRENT OPTIMAL SOLUTION. + 250 IF ( Z .GE. PROFIT ) GO TO 270 + Z = PROFIT + DO 260 J=1,N + X(J) = XX(J) + 260 CONTINUE + IF ( Z .EQ. LIM ) RETURN + 270 IF ( XX(N) .EQ. 0 ) GO TO 280 + XX(N) = 0 + CH = CH + W(N) + PROFIT = PROFIT - P(N) +C BACKTRACK. + 280 NN = II - 1 + IF ( NN .EQ. 0 ) RETURN + DO 290 J=1,NN + KK = II - J + IF ( XX(KK) .EQ. 1 ) GO TO 300 + 290 CONTINUE + RETURN + 300 R = CH + CH = CH + W(KK) + PROFIT = PROFIT - P(KK) + XX(KK) = 0 + IF ( R .LT. MIN(KK) ) GO TO 310 + II = KK + 1 + GO TO 80 + 310 NN = KK + 1 + II = KK +C TRY TO SUBSTITUTE THE NN-TH ITEM FOR THE KK-TH. + 320 IF ( Z .GE. PROFIT + CH*P(NN)/W(NN) ) GO TO 280 + DIFF = W(NN) - W(KK) + IF ( DIFF ) 370, 330, 340 + 330 NN = NN + 1 + GO TO 320 + 340 IF ( DIFF .GT. R ) GO TO 330 + IF ( Z .GE. PROFIT + P(NN) ) GO TO 330 + Z = PROFIT + P(NN) + DO 350 J=1,KK + X(J) = XX(J) + 350 CONTINUE + JJ = KK + 1 + DO 360 J=JJ,N + X(J) = 0 + 360 CONTINUE + X(NN) = 1 + IF ( Z .EQ. LIM ) RETURN + R = R - DIFF + KK = NN + NN = NN + 1 + GO TO 320 + 370 T = R - DIFF + IF ( T .LT. MIN(NN) ) GO TO 330 + IF ( Z .GE. PROFIT + P(NN) + T*P(NN+1)/W(NN+1)) GO TO 280 + CH = CH - W(NN) + PROFIT = PROFIT + P(NN) + XX(NN) = 1 + II = NN + 1 + WSIGN(NN) = W(NN) + PSIGN(NN) = P(NN) + ZSIGN(NN) = II + N1 = NN + 1 + DO 380 J=N1,LOLD + WSIGN(J) = 0 + PSIGN(J) = 0 + ZSIGN(J) = J + 380 CONTINUE + LOLD = NN + GO TO 80 + END + SUBROUTINE CHMT1(N,P,W,C,Z,JDIM) +C +C CHECK THE INPUT DATA. +C + INTEGER P(JDIM),W(JDIM),C,Z + IF ( N .GE. 2 .AND. N .LE. JDIM - 1 ) GO TO 10 + Z = - 1 + RETURN + 10 IF ( C .GT. 0 ) GO TO 30 + 20 Z = - 2 + RETURN + 30 JSW = 0 + RR = FLOAT(P(1))/FLOAT(W(1)) + DO 50 J=1,N + R = RR + IF ( P(J) .LE. 0 ) GO TO 20 + IF ( W(J) .LE. 0 ) GO TO 20 + JSW = JSW + W(J) + IF ( W(J) .LE. C ) GO TO 40 + Z = - 3 + RETURN + 40 RR = FLOAT(P(J))/FLOAT(W(J)) + IF ( RR .LE. R ) GO TO 50 + Z = - 5 + RETURN + 50 CONTINUE + IF ( JSW .GT. C ) RETURN + Z = - 4 + RETURN + END diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.h new file mode 100644 index 000000000..cceebba93 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mt1.h @@ -0,0 +1,34 @@ +/* mt1.h (0-1 knapsack problem; Martello & Toth algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2017-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MT1_H +#define MT1_H + +#define mt1 _glp_mt1 +int mt1(int n, int p[], int w[], int c, int x[], int jck, int xx[], + int min[], int psign[], int wsign[], int zsign[]); +/* solve 0-1 single knapsack problem */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.c new file mode 100644 index 000000000..89d053aec --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.c @@ -0,0 +1,1162 @@ +/* mygmp.c (integer and rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mygmp.h" + +#ifdef HAVE_GMP /* use GNU MP library */ + +/* nothing is needed */ + +#else /* use GLPK MP module */ + +#include "bignum.h" +#include "dmp.h" +#include "env.h" + +#define gmp_pool env->gmp_pool +#define gmp_size env->gmp_size +#define gmp_work env->gmp_work + +void *gmp_get_atom(int size) +{ ENV *env = get_env_ptr(); + if (gmp_pool == NULL) + gmp_pool = dmp_create_pool(); + return dmp_get_atom(gmp_pool, size); +} + +void gmp_free_atom(void *ptr, int size) +{ ENV *env = get_env_ptr(); + xassert(gmp_pool != NULL); + dmp_free_atom(gmp_pool, ptr, size); + return; +} + +int gmp_pool_count(void) +{ ENV *env = get_env_ptr(); + if (gmp_pool == NULL) + return 0; + else + return dmp_in_use(gmp_pool); +} + +unsigned short *gmp_get_work(int size) +{ ENV *env = get_env_ptr(); + xassert(size > 0); + if (gmp_size < size) + { if (gmp_size == 0) + { xassert(gmp_work == NULL); + gmp_size = 100; + } + else + { xassert(gmp_work != NULL); + xfree(gmp_work); + } + while (gmp_size < size) + gmp_size += gmp_size; + gmp_work = xcalloc(gmp_size, sizeof(unsigned short)); + } + return gmp_work; +} + +void gmp_free_mem(void) +{ ENV *env = get_env_ptr(); + if (gmp_pool != NULL) + dmp_delete_pool(gmp_pool); + if (gmp_work != NULL) + xfree(gmp_work); + gmp_pool = NULL; + gmp_size = 0; + gmp_work = NULL; + return; +} + +/*--------------------------------------------------------------------*/ + +mpz_t _mpz_init(void) +{ /* initialize x and set its value to 0 */ + mpz_t x; + x = gmp_get_atom(sizeof(struct mpz)); + x->val = 0; + x->ptr = NULL; + return x; +} + +void mpz_clear(mpz_t x) +{ /* free the space occupied by x */ + mpz_set_si(x, 0); + xassert(x->ptr == NULL); + /* free the number descriptor */ + gmp_free_atom(x, sizeof(struct mpz)); + return; +} + +void mpz_set(mpz_t z, mpz_t x) +{ /* set the value of z from x */ + struct mpz_seg *e, *ee, *es; + if (z != x) + { mpz_set_si(z, 0); + z->val = x->val; + xassert(z->ptr == NULL); + for (e = x->ptr, es = NULL; e != NULL; e = e->next) + { ee = gmp_get_atom(sizeof(struct mpz_seg)); + memcpy(ee->d, e->d, 12); + ee->next = NULL; + if (z->ptr == NULL) + z->ptr = ee; + else + es->next = ee; + es = ee; + } + } + return; +} + +void mpz_set_si(mpz_t x, int val) +{ /* set the value of x to val */ + struct mpz_seg *e; + /* free existing segments, if any */ + while (x->ptr != NULL) + { e = x->ptr; + x->ptr = e->next; + gmp_free_atom(e, sizeof(struct mpz_seg)); + } + /* assign new value */ + if (val == 0x80000000) + { /* long format is needed */ + x->val = -1; + x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg)); + memset(e->d, 0, 12); + e->d[1] = 0x8000; + e->next = NULL; + } + else + { /* short format is enough */ + x->val = val; + } + return; +} + +double mpz_get_d(mpz_t x) +{ /* convert x to a double, truncating if necessary */ + struct mpz_seg *e; + int j; + double val, deg; + if (x->ptr == NULL) + val = (double)x->val; + else + { xassert(x->val != 0); + val = 0.0; + deg = 1.0; + for (e = x->ptr; e != NULL; e = e->next) + { for (j = 0; j <= 5; j++) + { val += deg * (double)((int)e->d[j]); + deg *= 65536.0; + } + } + if (x->val < 0) + val = - val; + } + return val; +} + +double mpz_get_d_2exp(int *exp, mpz_t x) +{ /* convert x to a double, truncating if necessary (i.e. rounding + * towards zero), and returning the exponent separately; + * the return value is in the range 0.5 <= |d| < 1 and the + * exponent is stored to *exp; d*2^exp is the (truncated) x value; + * if x is zero, the return is 0.0 and 0 is stored to *exp; + * this is similar to the standard C frexp function */ + struct mpz_seg *e; + int j, n, n1; + double val; + if (x->ptr == NULL) + val = (double)x->val, n = 0; + else + { xassert(x->val != 0); + val = 0.0, n = 0; + for (e = x->ptr; e != NULL; e = e->next) + { for (j = 0; j <= 5; j++) + { val += (double)((int)e->d[j]); + val /= 65536.0, n += 16; + } + } + if (x->val < 0) + val = - val; + } + val = frexp(val, &n1); + *exp = n + n1; + return val; +} + +void mpz_swap(mpz_t x, mpz_t y) +{ /* swap the values x and y efficiently */ + int val; + void *ptr; + val = x->val, ptr = x->ptr; + x->val = y->val, x->ptr = y->ptr; + y->val = val, y->ptr = ptr; + return; +} + +static void normalize(mpz_t x) +{ /* normalize integer x that includes removing non-significant + * (leading) zeros and converting to short format, if possible */ + struct mpz_seg *es, *e; + /* if the integer is in short format, it remains unchanged */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + goto done; + } + xassert(x->val == +1 || x->val == -1); + /* find the last (most significant) non-zero segment */ + es = NULL; + for (e = x->ptr; e != NULL; e = e->next) + { if (e->d[0] || e->d[1] || e->d[2] || + e->d[3] || e->d[4] || e->d[5]) + es = e; + } + /* if all segments contain zeros, the integer is zero */ + if (es == NULL) + { mpz_set_si(x, 0); + goto done; + } + /* remove non-significant (leading) zero segments */ + while (es->next != NULL) + { e = es->next; + es->next = e->next; + gmp_free_atom(e, sizeof(struct mpz_seg)); + } + /* convert the integer to short format, if possible */ + e = x->ptr; + if (e->next == NULL && e->d[1] <= 0x7FFF && + !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5]) + { int val; + val = (int)e->d[0] + ((int)e->d[1] << 16); + if (x->val < 0) + val = - val; + mpz_set_si(x, val); + } +done: return; +} + +void mpz_add(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x + y */ + static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; + struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee; + int k, sx, sy, sz; + unsigned int t; + /* if [x] = 0 then [z] = [y] */ + if (x->val == 0) + { xassert(x->ptr == NULL); + mpz_set(z, y); + goto done; + } + /* if [y] = 0 then [z] = [x] */ + if (y->val == 0) + { xassert(y->ptr == NULL); + mpz_set(z, x); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val, zval = x->val + y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + if (!(xval > 0 && yval > 0 && zval <= 0 || + xval < 0 && yval < 0 && zval >= 0)) + { mpz_set_si(z, zval); + goto done; + } + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* main fragment */ + sz = sx; + ez = es = NULL; + if (sx > 0 && sy > 0 || sx < 0 && sy < 0) + { /* [x] and [y] have identical signs -- addition */ + t = 0; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) + ex = &zero; + if (ey == NULL) + ey = &zero; + ee = gmp_get_atom(sizeof(struct mpz_seg)); + for (k = 0; k <= 5; k++) + { t += (unsigned int)ex->d[k]; + t += (unsigned int)ey->d[k]; + ee->d[k] = (unsigned short)t; + t >>= 16; + } + ee->next = NULL; + if (ez == NULL) + ez = ee; + else + es->next = ee; + es = ee; + } + if (t) + { /* overflow -- one extra digit is needed */ + ee = gmp_get_atom(sizeof(struct mpz_seg)); + ee->d[0] = 1; + ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0; + ee->next = NULL; + xassert(es != NULL); + es->next = ee; + } + } + else + { /* [x] and [y] have different signs -- subtraction */ + t = 1; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) + ex = &zero; + if (ey == NULL) + ey = &zero; + ee = gmp_get_atom(sizeof(struct mpz_seg)); + for (k = 0; k <= 5; k++) + { t += (unsigned int)ex->d[k]; + t += (0xFFFF - (unsigned int)ey->d[k]); + ee->d[k] = (unsigned short)t; + t >>= 16; + } + ee->next = NULL; + if (ez == NULL) + ez = ee; + else + es->next = ee; + es = ee; + } + if (!t) + { /* |[x]| < |[y]| -- result in complement coding */ + sz = - sz; + t = 1; + for (ee = ez; ee != NULL; ee = ee->next) + { for (k = 0; k <= 5; k++) + { t += (0xFFFF - (unsigned int)ee->d[k]); + ee->d[k] = (unsigned short)t; + t >>= 16; + } + } + } + } + /* contruct and normalize result */ + mpz_set_si(z, 0); + z->val = sz; + z->ptr = ez; + normalize(z); +done: return; +} + +void mpz_sub(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x - y */ + if (x == y) + mpz_set_si(z, 0); + else + { y->val = - y->val; + mpz_add(z, x, y); + if (y != z) + y->val = - y->val; + } + return; +} + +void mpz_mul(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to x * y */ + struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; + int sx, sy, k, nx, ny, n; + unsigned int t; + unsigned short *work, *wx, *wy; + /* if [x] = 0 then [z] = 0 */ + if (x->val == 0) + { xassert(x->ptr == NULL); + mpz_set_si(z, 0); + goto done; + } + /* if [y] = 0 then [z] = 0 */ + if (y->val == 0) + { xassert(y->ptr == NULL); + mpz_set_si(z, 0); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val, sz = +1; + xassert(xval != 0x80000000 && yval != 0x80000000); + if (xval < 0) + xval = - xval, sz = - sz; + if (yval < 0) + yval = - yval, sz = - sz; + if (xval <= 0x7FFFFFFF / yval) + { mpz_set_si(z, sz * (xval * yval)); + goto done; + } + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* determine the number of digits of [x] */ + nx = n = 0; + for (e = ex; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) + nx = n; + } + } + xassert(nx > 0); + /* determine the number of digits of [y] */ + ny = n = 0; + for (e = ey; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) + ny = n; + } + } + xassert(ny > 0); + /* we need working array containing at least nx+ny+ny places */ + work = gmp_get_work(nx+ny+ny); + /* load digits of [x] */ + wx = &work[0]; + for (n = 0; n < nx; n++) + wx[ny+n] = 0; + for (n = 0, e = ex; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++, n++) + { if (e->d[k]) + wx[ny+n] = e->d[k]; + } + } + /* load digits of [y] */ + wy = &work[nx+ny]; + for (n = 0; n < ny; n++) wy[n] = 0; + for (n = 0, e = ey; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++, n++) + { if (e->d[k]) + wy[n] = e->d[k]; + } + } + /* compute [x] * [y] */ + bigmul(nx, ny, wx, wy); + /* construct and normalize result */ + mpz_set_si(z, 0); + z->val = sx * sy; + es = NULL; + k = 6; + for (n = 0; n < nx+ny; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (z->ptr == NULL) + z->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(z); +done: return; +} + +void mpz_neg(mpz_t z, mpz_t x) +{ /* set z to 0 - x */ + mpz_set(z, x); + z->val = - z->val; + return; +} + +void mpz_abs(mpz_t z, mpz_t x) +{ /* set z to the absolute value of x */ + mpz_set(z, x); + if (z->val < 0) + z->val = - z->val; + return; +} + +void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y) +{ /* divide x by y, forming quotient q and/or remainder r + * if q = NULL then quotient is not stored; if r = NULL then + * remainder is not stored + * the sign of quotient is determined as in algebra while the + * sign of remainder is the same as the sign of dividend: + * +26 : +7 = +3, remainder is +5 + * -26 : +7 = -3, remainder is -5 + * +26 : -7 = -3, remainder is +5 + * -26 : -7 = +3, remainder is -5 */ + struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; + int sx, sy, k, nx, ny, n; + unsigned int t; + unsigned short *work, *wx, *wy; + /* divide by zero is not allowed */ + if (y->val == 0) + { xassert(y->ptr == NULL); + xerror("mpz_div: divide by zero not allowed\n"); + } + /* if [x] = 0 then [q] = [r] = 0 */ + if (x->val == 0) + { xassert(x->ptr == NULL); + if (q != NULL) + mpz_set_si(q, 0); + if (r != NULL) + mpz_set_si(r, 0); + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + /* FIXME: use div function */ + if (q != NULL) + mpz_set_si(q, xval / yval); + if (r != NULL) + mpz_set_si(r, xval % yval); + goto done; + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* determine the number of digits of [x] */ + nx = n = 0; + for (e = ex; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) + nx = n; + } + } + xassert(nx > 0); + /* determine the number of digits of [y] */ + ny = n = 0; + for (e = ey; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++) + { n++; + if (e->d[k]) + ny = n; + } + } + xassert(ny > 0); + /* if nx < ny then [q] = 0 and [r] = [x] */ + if (nx < ny) + { if (r != NULL) + mpz_set(r, x); + if (q != NULL) + mpz_set_si(q, 0); + goto done; + } + /* we need working array containing at least nx+ny+1 places */ + work = gmp_get_work(nx+ny+1); + /* load digits of [x] */ + wx = &work[0]; + for (n = 0; n < nx; n++) + wx[n] = 0; + for (n = 0, e = ex; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wx[n] = e->d[k]; + } + /* load digits of [y] */ + wy = &work[nx+1]; + for (n = 0; n < ny; n++) + wy[n] = 0; + for (n = 0, e = ey; e != NULL; e = e->next) + { for (k = 0; k <= 5; k++, n++) + if (e->d[k]) wy[n] = e->d[k]; + } + /* compute quotient and remainder */ + xassert(wy[ny-1] != 0); + bigdiv(nx-ny, ny, wx, wy); + /* construct and normalize quotient */ + if (q != NULL) + { mpz_set_si(q, 0); + q->val = sx * sy; + es = NULL; + k = 6; + for (n = ny; n <= nx; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (q->ptr == NULL) + q->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(q); + } + /* construct and normalize remainder */ + if (r != NULL) + { mpz_set_si(r, 0); + r->val = sx; + es = NULL; + k = 6; + for (n = 0; n < ny; n++) + { if (k > 5) + { e = gmp_get_atom(sizeof(struct mpz_seg)); + e->d[0] = e->d[1] = e->d[2] = 0; + e->d[3] = e->d[4] = e->d[5] = 0; + e->next = NULL; + if (r->ptr == NULL) + r->ptr = e; + else + es->next = e; + es = e; + k = 0; + } + es->d[k++] = wx[n]; + } + normalize(r); + } +done: return; +} + +void mpz_gcd(mpz_t z, mpz_t x, mpz_t y) +{ /* set z to the greatest common divisor of x and y */ + /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and, + * in particular, GCD(0, 0) = 0 */ + mpz_t u, v, r; + mpz_init(u); + mpz_init(v); + mpz_init(r); + mpz_abs(u, x); + mpz_abs(v, y); + while (mpz_sgn(v)) + { mpz_div(NULL, r, u, v); + mpz_set(u, v); + mpz_set(v, r); + } + mpz_set(z, u); + mpz_clear(u); + mpz_clear(v); + mpz_clear(r); + return; +} + +int mpz_cmp(mpz_t x, mpz_t y) +{ /* compare x and y; return a positive value if x > y, zero if + * x = y, or a nefative value if x < y */ + static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; + struct mpz_seg dumx, dumy, *ex, *ey; + int cc, sx, sy, k; + unsigned int t; + if (x == y) + { cc = 0; + goto done; + } + /* special case when both [x] and [y] are in short format */ + if (x->ptr == NULL && y->ptr == NULL) + { int xval = x->val, yval = y->val; + xassert(xval != 0x80000000 && yval != 0x80000000); + cc = (xval > yval ? +1 : xval < yval ? -1 : 0); + goto done; + } + /* special case when [x] and [y] have different signs */ + if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0) + { cc = +1; + goto done; + } + if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0) + { cc = -1; + goto done; + } + /* convert [x] to long format, if necessary */ + if (x->ptr == NULL) + { xassert(x->val != 0x80000000); + if (x->val >= 0) + { sx = +1; + t = (unsigned int)(+ x->val); + } + else + { sx = -1; + t = (unsigned int)(- x->val); + } + ex = &dumx; + ex->d[0] = (unsigned short)t; + ex->d[1] = (unsigned short)(t >> 16); + ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; + ex->next = NULL; + } + else + { sx = x->val; + xassert(sx == +1 || sx == -1); + ex = x->ptr; + } + /* convert [y] to long format, if necessary */ + if (y->ptr == NULL) + { xassert(y->val != 0x80000000); + if (y->val >= 0) + { sy = +1; + t = (unsigned int)(+ y->val); + } + else + { sy = -1; + t = (unsigned int)(- y->val); + } + ey = &dumy; + ey->d[0] = (unsigned short)t; + ey->d[1] = (unsigned short)(t >> 16); + ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; + ey->next = NULL; + } + else + { sy = y->val; + xassert(sy == +1 || sy == -1); + ey = y->ptr; + } + /* main fragment */ + xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0); + cc = 0; + for (; ex || ey; ex = ex->next, ey = ey->next) + { if (ex == NULL) + ex = &zero; + if (ey == NULL) + ey = &zero; + for (k = 0; k <= 5; k++) + { if (ex->d[k] > ey->d[k]) + cc = +1; + if (ex->d[k] < ey->d[k]) + cc = -1; + } + } + if (sx < 0) cc = - cc; +done: return cc; +} + +int mpz_sgn(mpz_t x) +{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + int s; + s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0); + return s; +} + +int mpz_out_str(void *_fp, int base, mpz_t x) +{ /* output x on stream fp, as a string in given base; the base + * may vary from 2 to 36; + * return the number of bytes written, or if an error occurred, + * return 0 */ + FILE *fp = _fp; + mpz_t b, y, r; + int n, j, nwr = 0; + unsigned char *d; + static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (!(2 <= base && base <= 36)) + xerror("mpz_out_str: base = %d; invalid base\n", base); + mpz_init(b); + mpz_set_si(b, base); + mpz_init(y); + mpz_init(r); + /* determine the number of digits */ + mpz_abs(y, x); + for (n = 0; mpz_sgn(y) != 0; n++) + mpz_div(y, NULL, y, b); + if (n == 0) n = 1; + /* compute the digits */ + d = xmalloc(n); + mpz_abs(y, x); + for (j = 0; j < n; j++) + { mpz_div(y, r, y, b); + xassert(0 <= r->val && r->val < base && r->ptr == NULL); + d[j] = (unsigned char)r->val; + } + /* output the integer to the stream */ + if (fp == NULL) + fp = stdout; + if (mpz_sgn(x) < 0) + fputc('-', fp), nwr++; + for (j = n-1; j >= 0; j--) + fputc(set[d[j]], fp), nwr++; + if (ferror(fp)) + nwr = 0; + mpz_clear(b); + mpz_clear(y); + mpz_clear(r); + xfree(d); + return nwr; +} + +/*--------------------------------------------------------------------*/ + +mpq_t _mpq_init(void) +{ /* initialize x, and set its value to 0/1 */ + mpq_t x; + x = gmp_get_atom(sizeof(struct mpq)); + x->p.val = 0; + x->p.ptr = NULL; + x->q.val = 1; + x->q.ptr = NULL; + return x; +} + +void mpq_clear(mpq_t x) +{ /* free the space occupied by x */ + mpz_set_si(&x->p, 0); + xassert(x->p.ptr == NULL); + mpz_set_si(&x->q, 0); + xassert(x->q.ptr == NULL); + /* free the number descriptor */ + gmp_free_atom(x, sizeof(struct mpq)); + return; +} + +void mpq_canonicalize(mpq_t x) +{ /* remove any factors that are common to the numerator and + * denominator of x, and make the denominator positive */ + mpz_t f; + xassert(x->q.val != 0); + if (x->q.val < 0) + { mpz_neg(&x->p, &x->p); + mpz_neg(&x->q, &x->q); + } + mpz_init(f); + mpz_gcd(f, &x->p, &x->q); + if (!(f->val == 1 && f->ptr == NULL)) + { mpz_div(&x->p, NULL, &x->p, f); + mpz_div(&x->q, NULL, &x->q, f); + } + mpz_clear(f); + return; +} + +void mpq_set(mpq_t z, mpq_t x) +{ /* set the value of z from x */ + if (z != x) + { mpz_set(&z->p, &x->p); + mpz_set(&z->q, &x->q); + } + return; +} + +void mpq_set_si(mpq_t x, int p, unsigned int q) +{ /* set the value of x to p/q */ + if (q == 0) + xerror("mpq_set_si: zero denominator not allowed\n"); + mpz_set_si(&x->p, p); + xassert(q <= 0x7FFFFFFF); + mpz_set_si(&x->q, q); + return; +} + +double mpq_get_d(mpq_t x) +{ /* convert x to a double, truncating if necessary */ + int np, nq; + double p, q; + p = mpz_get_d_2exp(&np, &x->p); + q = mpz_get_d_2exp(&nq, &x->q); + return ldexp(p / q, np - nq); +} + +void mpq_set_d(mpq_t x, double val) +{ /* set x to val; there is no rounding, the conversion is exact */ + int s, n, d, j; + double f; + mpz_t temp; + xassert(-DBL_MAX <= val && val <= +DBL_MAX); + mpq_set_si(x, 0, 1); + if (val > 0.0) + s = +1; + else if (val < 0.0) + s = -1; + else + goto done; + f = frexp(fabs(val), &n); + /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ + mpz_init(temp); + while (f != 0.0) + { f *= 16.0, n -= 4; + d = (int)f; + xassert(0 <= d && d <= 15); + f -= (double)d; + /* x := 16 * x + d */ + mpz_set_si(temp, 16); + mpz_mul(&x->p, &x->p, temp); + mpz_set_si(temp, d); + mpz_add(&x->p, &x->p, temp); + } + mpz_clear(temp); + /* x := x * 2^n */ + if (n > 0) + { for (j = 1; j <= n; j++) + mpz_add(&x->p, &x->p, &x->p); + } + else if (n < 0) + { for (j = 1; j <= -n; j++) + mpz_add(&x->q, &x->q, &x->q); + mpq_canonicalize(x); + } + if (s < 0) + mpq_neg(x, x); +done: return; +} + +void mpq_add(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x + y */ + mpz_t p, q; + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_add(p, p, q); + mpz_mul(q, &x->q, &y->q); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_sub(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x - y */ + mpz_t p, q; + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_sub(p, p, q); + mpz_mul(q, &x->q, &y->q); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_mul(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x * y */ + mpz_mul(&z->p, &x->p, &y->p); + mpz_mul(&z->q, &x->q, &y->q); + mpq_canonicalize(z); + return; +} + +void mpq_div(mpq_t z, mpq_t x, mpq_t y) +{ /* set z to x / y */ + mpz_t p, q; + if (mpq_sgn(y) == 0) + xerror("mpq_div: zero divisor not allowed\n"); + mpz_init(p); + mpz_init(q); + mpz_mul(p, &x->p, &y->q); + mpz_mul(q, &x->q, &y->p); + mpz_set(&z->p, p); + mpz_set(&z->q, q); + mpz_clear(p); + mpz_clear(q); + mpq_canonicalize(z); + return; +} + +void mpq_neg(mpq_t z, mpq_t x) +{ /* set z to 0 - x */ + mpq_set(z, x); + mpz_neg(&z->p, &z->p); + return; +} + +void mpq_abs(mpq_t z, mpq_t x) +{ /* set z to the absolute value of x */ + mpq_set(z, x); + mpz_abs(&z->p, &z->p); + xassert(mpz_sgn(&x->q) > 0); + return; +} + +int mpq_cmp(mpq_t x, mpq_t y) +{ /* compare x and y; return a positive value if x > y, zero if + * x = y, or a negative value if x < y */ + mpq_t temp; + int s; + mpq_init(temp); + mpq_sub(temp, x, y); + s = mpq_sgn(temp); + mpq_clear(temp); + return s; +} + +int mpq_sgn(mpq_t x) +{ /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + int s; + s = mpz_sgn(&x->p); + xassert(mpz_sgn(&x->q) > 0); + return s; +} + +int mpq_out_str(void *_fp, int base, mpq_t x) +{ /* output x on stream fp, as a string in given base; the base + * may vary from 2 to 36; output is in the form 'num/den' or if + * the denominator is 1 then just 'num'; + * if the parameter fp is a null pointer, stdout is assumed; + * return the number of bytes written, or if an error occurred, + * return 0 */ + FILE *fp = _fp; + int nwr; + if (!(2 <= base && base <= 36)) + xerror("mpq_out_str: base = %d; invalid base\n", base); + if (fp == NULL) + fp = stdout; + nwr = mpz_out_str(fp, base, &x->p); + if (x->q.val == 1 && x->q.ptr == NULL) + ; + else + { fputc('/', fp), nwr++; + nwr += mpz_out_str(fp, base, &x->q); + } + if (ferror(fp)) + nwr = 0; + return nwr; +} + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.h new file mode 100644 index 000000000..31d2024df --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/mygmp.h @@ -0,0 +1,254 @@ +/* mygmp.h (integer and rational arithmetic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2008-2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MYGMP_H +#define MYGMP_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_GMP /* use GNU MP library */ + +#include + +#define gmp_pool_count() 0 + +#define gmp_free_mem() ((void)0) + +#else /* use GLPK MP module */ + +/*********************************************************************** +* INTEGER NUMBERS +* --------------- +* Depending on its magnitude an integer number of arbitrary precision +* is represented either in short format or in long format. +* +* Short format corresponds to the int type and allows representing +* integer numbers in the range [-(2^31-1), +(2^31-1)]. Note that for +* the most negative number of int type the short format is not used. +* +* In long format integer numbers are represented using the positional +* system with the base (radix) 2^16 = 65536: +* +* x = (-1)^s sum{j in 0..n-1} d[j] * 65536^j, +* +* where x is the integer to be represented, s is its sign (+1 or -1), +* d[j] are its digits (0 <= d[j] <= 65535). +* +* RATIONAL NUMBERS +* ---------------- +* A rational number is represented as an irreducible fraction: +* +* p / q, +* +* where p (numerator) and q (denominator) are integer numbers (q > 0) +* having no common divisors. */ + +struct mpz +{ /* integer number */ + int val; + /* if ptr is a null pointer, the number is in short format, and + val is its value; otherwise, the number is in long format, and + val is its sign (+1 or -1) */ + struct mpz_seg *ptr; + /* pointer to the linked list of the number segments ordered in + ascending of powers of the base */ +}; + +struct mpz_seg +{ /* integer number segment */ + unsigned short d[6]; + /* six digits of the number ordered in ascending of powers of the + base */ + struct mpz_seg *next; + /* pointer to the next number segment */ +}; + +struct mpq +{ /* rational number (p / q) */ + struct mpz p; + /* numerator */ + struct mpz q; + /* denominator */ +}; + +typedef struct mpz *mpz_t; +typedef struct mpq *mpq_t; + +#define gmp_get_atom _glp_gmp_get_atom +void *gmp_get_atom(int size); + +#define gmp_free_atom _glp_gmp_free_atom +void gmp_free_atom(void *ptr, int size); + +#define gmp_pool_count _glp_gmp_pool_count +int gmp_pool_count(void); + +#define gmp_get_work _glp_gmp_get_work +unsigned short *gmp_get_work(int size); + +#define gmp_free_mem _glp_gmp_free_mem +void gmp_free_mem(void); + +#define mpz_init(x) (void)((x) = _mpz_init()) + +#define _mpz_init _glp_mpz_init +mpz_t _mpz_init(void); +/* initialize x and set its value to 0 */ + +#define mpz_clear _glp_mpz_clear +void mpz_clear(mpz_t x); +/* free the space occupied by x */ + +#define mpz_set _glp_mpz_set +void mpz_set(mpz_t z, mpz_t x); +/* set the value of z from x */ + +#define mpz_set_si _glp_mpz_set_si +void mpz_set_si(mpz_t x, int val); +/* set the value of x to val */ + +#define mpz_get_d _glp_mpz_get_d +double mpz_get_d(mpz_t x); +/* convert x to a double, truncating if necessary */ + +#define mpz_get_d_2exp _glp_mpz_get_d_2exp +double mpz_get_d_2exp(int *exp, mpz_t x); +/* convert x to a double, returning the exponent separately */ + +#define mpz_swap _glp_mpz_swap +void mpz_swap(mpz_t x, mpz_t y); +/* swap the values x and y efficiently */ + +#define mpz_add _glp_mpz_add +void mpz_add(mpz_t, mpz_t, mpz_t); +/* set z to x + y */ + +#define mpz_sub _glp_mpz_sub +void mpz_sub(mpz_t, mpz_t, mpz_t); +/* set z to x - y */ + +#define mpz_mul _glp_mpz_mul +void mpz_mul(mpz_t, mpz_t, mpz_t); +/* set z to x * y */ + +#define mpz_neg _glp_mpz_neg +void mpz_neg(mpz_t z, mpz_t x); +/* set z to 0 - x */ + +#define mpz_abs _glp_mpz_abs +void mpz_abs(mpz_t z, mpz_t x); +/* set z to the absolute value of x */ + +#define mpz_div _glp_mpz_div +void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y); +/* divide x by y, forming quotient q and/or remainder r */ + +#define mpz_gcd _glp_mpz_gcd +void mpz_gcd(mpz_t z, mpz_t x, mpz_t y); +/* set z to the greatest common divisor of x and y */ + +#define mpz_cmp _glp_mpz_cmp +int mpz_cmp(mpz_t x, mpz_t y); +/* compare x and y */ + +#define mpz_sgn _glp_mpz_sgn +int mpz_sgn(mpz_t x); +/* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + +#define mpz_out_str _glp_mpz_out_str +int mpz_out_str(void *fp, int base, mpz_t x); +/* output x on stream fp, as a string in given base */ + +#define mpq_init(x) (void)((x) = _mpq_init()) + +#define _mpq_init _glp_mpq_init +mpq_t _mpq_init(void); +/* initialize x, and set its value to 0/1 */ + +#define mpq_clear _glp_mpq_clear +void mpq_clear(mpq_t x); +/* free the space occupied by x */ + +#define mpq_canonicalize _glp_mpq_canonicalize +void mpq_canonicalize(mpq_t x); +/* canonicalize x */ + +#define mpq_set _glp_mpq_set +void mpq_set(mpq_t z, mpq_t x); +/* set the value of z from x */ + +#define mpq_set_si _glp_mpq_set_si +void mpq_set_si(mpq_t x, int p, unsigned int q); +/* set the value of x to p/q */ + +#define mpq_get_d _glp_mpq_get_d +double mpq_get_d(mpq_t x); +/* convert x to a double, truncating if necessary */ + +#define mpq_set_d _glp_mpq_set_d +void mpq_set_d(mpq_t x, double val); +/* set x to val; there is no rounding, the conversion is exact */ + +#define mpq_add _glp_mpq_add +void mpq_add(mpq_t z, mpq_t x, mpq_t y); +/* set z to x + y */ + +#define mpq_sub _glp_mpq_sub +void mpq_sub(mpq_t z, mpq_t x, mpq_t y); +/* set z to x - y */ + +#define mpq_mul _glp_mpq_mul +void mpq_mul(mpq_t z, mpq_t x, mpq_t y); +/* set z to x * y */ + +#define mpq_div _glp_mpq_div +void mpq_div(mpq_t z, mpq_t x, mpq_t y); +/* set z to x / y */ + +#define mpq_neg _glp_mpq_neg +void mpq_neg(mpq_t z, mpq_t x); +/* set z to 0 - x */ + +#define mpq_abs _glp_mpq_abs +void mpq_abs(mpq_t z, mpq_t x); +/* set z to the absolute value of x */ + +#define mpq_cmp _glp_mpq_cmp +int mpq_cmp(mpq_t x, mpq_t y); +/* compare x and y */ + +#define mpq_sgn _glp_mpq_sgn +int mpq_sgn(mpq_t x); +/* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ + +#define mpq_out_str _glp_mpq_out_str +int mpq_out_str(void *fp, int base, mpq_t x); +/* output x on stream fp, as a string in given base */ + +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.c new file mode 100644 index 000000000..8eecd6df8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.c @@ -0,0 +1,382 @@ +/* okalg.c (out-of-kilter algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "okalg.h" + +/*********************************************************************** +* NAME +* +* okalg - out-of-kilter algorithm +* +* SYNOPSIS +* +* #include "okalg.h" +* int okalg(int nv, int na, const int tail[], const int head[], +* const int low[], const int cap[], const int cost[], int x[], +* int pi[]); +* +* DESCRIPTION +* +* The routine okalg implements the out-of-kilter algorithm to find a +* minimal-cost circulation in the specified flow network. +* +* INPUT PARAMETERS +* +* nv is the number of nodes, nv >= 0. +* +* na is the number of arcs, na >= 0. +* +* tail[a], a = 1,...,na, is the index of tail node of arc a. +* +* head[a], a = 1,...,na, is the index of head node of arc a. +* +* low[a], a = 1,...,na, is an lower bound to the flow through arc a. +* +* cap[a], a = 1,...,na, is an upper bound to the flow through arc a, +* which is the capacity of the arc. +* +* cost[a], a = 1,...,na, is a per-unit cost of the flow through arc a. +* +* NOTES +* +* 1. Multiple arcs are allowed, but self-loops are not allowed. +* +* 2. It is required that 0 <= low[a] <= cap[a] for all arcs. +* +* 3. Arc costs may have any sign. +* +* OUTPUT PARAMETERS +* +* x[a], a = 1,...,na, is optimal value of the flow through arc a. +* +* pi[i], i = 1,...,nv, is Lagrange multiplier for flow conservation +* equality constraint corresponding to node i (the node potential). +* +* RETURNS +* +* 0 optimal circulation found; +* +* 1 there is no feasible circulation; +* +* 2 integer overflow occured; +* +* 3 optimality test failed (logic error). +* +* REFERENCES +* +* L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND +* Corp., Report R-375-PR (August 1962), Chap. III "Minimal Cost Flow +* Problems," pp.113-26. */ + +static int overflow(int u, int v) +{ /* check for integer overflow on computing u + v */ + if (u > 0 && v > 0 && u + v < 0) return 1; + if (u < 0 && v < 0 && u + v > 0) return 1; + return 0; +} + +int okalg(int nv, int na, const int tail[], const int head[], + const int low[], const int cap[], const int cost[], int x[], + int pi[]) +{ int a, aok, delta, i, j, k, lambda, pos1, pos2, s, t, temp, ret, + *ptr, *arc, *link, *list; + /* sanity checks */ + xassert(nv >= 0); + xassert(na >= 0); + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + xassert(1 <= i && i <= nv); + xassert(1 <= j && j <= nv); + xassert(i != j); + xassert(0 <= low[a] && low[a] <= cap[a]); + } + /* allocate working arrays */ + ptr = xcalloc(1+nv+1, sizeof(int)); + arc = xcalloc(1+na+na, sizeof(int)); + link = xcalloc(1+nv, sizeof(int)); + list = xcalloc(1+nv, sizeof(int)); + /* ptr[i] := (degree of node i) */ + for (i = 1; i <= nv; i++) + ptr[i] = 0; + for (a = 1; a <= na; a++) + { ptr[tail[a]]++; + ptr[head[a]]++; + } + /* initialize arc pointers */ + ptr[1]++; + for (i = 1; i < nv; i++) + ptr[i+1] += ptr[i]; + ptr[nv+1] = ptr[nv]; + /* build arc lists */ + for (a = 1; a <= na; a++) + { arc[--ptr[tail[a]]] = a; + arc[--ptr[head[a]]] = a; + } + xassert(ptr[1] == 1); + xassert(ptr[nv+1] == na+na+1); + /* now the indices of arcs incident to node i are stored in + * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ + /* initialize arc flows and node potentials */ + for (a = 1; a <= na; a++) + x[a] = 0; + for (i = 1; i <= nv; i++) + pi[i] = 0; +loop: /* main loop starts here */ + /* find out-of-kilter arc */ + aok = 0; + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] < low[a] || (lambda < 0 && x[a] < cap[a])) + { /* arc a = i->j is out of kilter, and we need to increase + * the flow through this arc */ + aok = a, s = j, t = i; + break; + } + if (x[a] > cap[a] || (lambda > 0 && x[a] > low[a])) + { /* arc a = i->j is out of kilter, and we need to decrease + * the flow through this arc */ + aok = a, s = i, t = j; + break; + } + } + if (aok == 0) + { /* all arcs are in kilter */ + /* check for feasibility */ + for (a = 1; a <= na; a++) + { if (!(low[a] <= x[a] && x[a] <= cap[a])) + { ret = 3; + goto done; + } + } + for (i = 1; i <= nv; i++) + { temp = 0; + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a is outgoing arc */ + temp += x[a]; + } + else if (head[a] == i) + { /* a is incoming arc */ + temp -= x[a]; + } + else + xassert(a != a); + } + if (temp != 0) + { ret = 3; + goto done; + } + } + /* check for optimality */ + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + lambda = cost[a] + (pi[i] - pi[j]); + if ((lambda > 0 && x[a] != low[a]) || + (lambda < 0 && x[a] != cap[a])) + { ret = 3; + goto done; + } + } + /* current circulation is optimal */ + ret = 0; + goto done; + } + /* now we need to find a cycle (t, a, s, ..., t), which allows + * increasing the flow along it, where a is the out-of-kilter arc + * just found */ + /* link[i] = 0 means that node i is not labelled yet; + * link[i] = a means that arc a immediately precedes node i */ + /* initially only node s is labelled */ + for (i = 1; i <= nv; i++) + link[i] = 0; + link[s] = aok, list[1] = s, pos1 = pos2 = 1; + /* breadth first search */ + while (pos1 <= pos2) + { /* dequeue node i */ + i = list[pos1++]; + /* consider all arcs incident to node i */ + for (k = ptr[i]; k < ptr[i+1]; k++) + { a = arc[k]; + if (tail[a] == i) + { /* a = i->j is a forward arc from s to t */ + j = head[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow increasing the flow through + * it, skip the arc */ + if (x[a] >= cap[a]) continue; + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (lambda > 0 && x[a] >= low[a]) continue; + } + else if (head[a] == i) + { /* a = i<-j is a backward arc from s to t */ + j = tail[a]; + /* if node j has been labelled, skip the arc */ + if (link[j] != 0) continue; + /* if the arc does not allow decreasing the flow through + * it, skip the arc */ + if (x[a] <= low[a]) continue; + if (overflow(cost[a], pi[j] - pi[i])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[j] - pi[i]); + if (lambda < 0 && x[a] <= cap[a]) continue; + } + else + xassert(a != a); + /* label node j and enqueue it */ + link[j] = a, list[++pos2] = j; + /* check for breakthrough */ + if (j == t) goto brkt; + } + } + /* NONBREAKTHROUGH */ + /* consider all arcs, whose one endpoint is labelled and other is + * not, and determine maximal change of node potentials */ + delta = 0; + for (a = 1; a <= na; a++) + { i = tail[a], j = head[a]; + if (link[i] != 0 && link[j] == 0) + { /* a = i->j, where node i is labelled, node j is not */ + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] <= cap[a] && lambda > 0) + if (delta == 0 || delta > + lambda) delta = + lambda; + } + else if (link[i] == 0 && link[j] != 0) + { /* a = j<-i, where node j is labelled, node i is not */ + if (overflow(cost[a], pi[i] - pi[j])) + { ret = 2; + goto done; + } + lambda = cost[a] + (pi[i] - pi[j]); + if (x[a] >= low[a] && lambda < 0) + if (delta == 0 || delta > - lambda) delta = - lambda; + } + } + if (delta == 0) + { /* there is no feasible circulation */ + ret = 1; + goto done; + } + /* increase potentials of all unlabelled nodes */ + for (i = 1; i <= nv; i++) + { if (link[i] == 0) + { if (overflow(pi[i], delta)) + { ret = 2; + goto done; + } + pi[i] += delta; + } + } + goto loop; +brkt: /* BREAKTHROUGH */ + /* walk through arcs of the cycle (t, a, s, ..., t) found in the + * reverse order and determine maximal change of the flow */ + delta = 0; + for (j = t;; j = i) + { /* arc a immediately precedes node j in the cycle */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + lambda = cost[a] + (pi[i] - pi[j]); + if (lambda > 0 && x[a] < low[a]) + { /* x[a] may be increased until its lower bound */ + temp = low[a] - x[a]; + } + else if (lambda <= 0 && x[a] < cap[a]) + { /* x[a] may be increased until its upper bound */ + temp = cap[a] - x[a]; + } + else + xassert(a != a); + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + lambda = cost[a] + (pi[j] - pi[i]); + if (lambda < 0 && x[a] > cap[a]) + { /* x[a] may be decreased until its upper bound */ + temp = x[a] - cap[a]; + } + else if (lambda >= 0 && x[a] > low[a]) + { /* x[a] may be decreased until its lower bound */ + temp = x[a] - low[a]; + } + else + xassert(a != a); + } + else + xassert(a != a); + if (delta == 0 || delta > temp) delta = temp; + /* check for end of the cycle */ + if (i == t) break; + } + xassert(delta > 0); + /* increase the flow along the cycle */ + for (j = t;; j = i) + { /* arc a immediately precedes node j in the cycle */ + a = link[j]; + if (head[a] == j) + { /* a = i->j is a forward arc of the cycle */ + i = tail[a]; + /* overflow cannot occur */ + x[a] += delta; + } + else if (tail[a] == j) + { /* a = i<-j is a backward arc of the cycle */ + i = head[a]; + /* overflow cannot occur */ + x[a] -= delta; + } + else + xassert(a != a); + /* check for end of the cycle */ + if (i == t) break; + } + goto loop; +done: /* free working arrays */ + xfree(ptr); + xfree(arc); + xfree(link); + xfree(list); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.h new file mode 100644 index 000000000..2f2d97403 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/okalg.h @@ -0,0 +1,35 @@ +/* okalg.h (out-of-kilter algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef OKALG_H +#define OKALG_H + +#define okalg _glp_okalg +int okalg(int nv, int na, const int tail[], const int head[], + const int low[], const int cap[], const int cost[], int x[], + int pi[]); +/* out-of-kilter algorithm */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.c new file mode 100644 index 000000000..a3397dcf9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.c @@ -0,0 +1,584 @@ +/* qmd.c (quotient minimum degree algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES +* GENQMD, QMDRCH, QMDQT, QMDUPD, AND QMDMRG FROM THE BOOK: +* +* ALAN GEORGE, JOSEPH W-H LIU. COMPUTER SOLUTION OF LARGE SPARSE +* POSITIVE DEFINITE SYSTEMS. PRENTICE-HALL, 1981. +* +* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS +* OF THE ORIGINAL FORTRAN SUBROUTINES: ALAN GEORGE AND JOSEPH LIU, +* UNIVERSITY OF WATERLOO, WATERLOO, ONTARIO, CANADA. +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "qmd.h" + +/*********************************************************************** +* NAME +* +* genqmd - GENeral Quotient Minimum Degree algorithm +* +* SYNOPSIS +* +* #include "qmd.h" +* void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], +* int invp[], int deg[], int marker[], int rchset[], int nbrhd[], +* int qsize[], int qlink[], int *nofsub); +* +* PURPOSE +* +* This routine implements the minimum degree algorithm. It makes use +* of the implicit representation of the elimination graph by quotient +* graphs, and the notion of indistinguishable nodes. +* +* CAUTION +* +* The adjancy vector adjncy will be destroyed. +* +* INPUT PARAMETERS +* +* neqns - number of equations; +* (xadj, adjncy) - +* the adjancy structure. +* +* OUTPUT PARAMETERS +* +* perm - the minimum degree ordering; +* invp - the inverse of perm. +* +* WORKING PARAMETERS +* +* deg - the degree vector. deg[i] is negative means node i has been +* numbered; +* marker - a marker vector, where marker[i] is negative means node i +* has been merged with another nodeand thus can be ignored; +* rchset - vector used for the reachable set; +* nbrhd - vector used for neighborhood set; +* qsize - vector used to store the size of indistinguishable +* supernodes; +* qlink - vector used to store indistinguishable nodes, i, qlink[i], +* qlink[qlink[i]], ... are the members of the supernode +* represented by i. +* +* PROGRAM SUBROUTINES +* +* qmdrch, qmdqt, qmdupd. +***********************************************************************/ + +void genqmd(int *_neqns, int xadj[], int adjncy[], int perm[], + int invp[], int deg[], int marker[], int rchset[], int nbrhd[], + int qsize[], int qlink[], int *_nofsub) +{ int inode, ip, irch, j, mindeg, ndeg, nhdsze, node, np, num, + nump1, nxnode, rchsze, search, thresh; +# define neqns (*_neqns) +# define nofsub (*_nofsub) + /* Initialize degree vector and other working variables. */ + mindeg = neqns; + nofsub = 0; + for (node = 1; node <= neqns; node++) + { perm[node] = node; + invp[node] = node; + marker[node] = 0; + qsize[node] = 1; + qlink[node] = 0; + ndeg = xadj[node+1] - xadj[node]; + deg[node] = ndeg; + if (ndeg < mindeg) mindeg = ndeg; + } + num = 0; + /* Perform threshold search to get a node of min degree. + * Variable search point to where search should start. */ +s200: search = 1; + thresh = mindeg; + mindeg = neqns; +s300: nump1 = num + 1; + if (nump1 > search) search = nump1; + for (j = search; j <= neqns; j++) + { node = perm[j]; + if (marker[node] >= 0) + { ndeg = deg[node]; + if (ndeg <= thresh) goto s500; + if (ndeg < mindeg) mindeg = ndeg; + } + } + goto s200; + /* Node has minimum degree. Find its reachable sets by calling + * qmdrch. */ +s500: search = j; + nofsub += deg[node]; + marker[node] = 1; + qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, &nhdsze, + nbrhd); + /* Eliminate all nodes indistinguishable from node. They are given + * by node, qlink[node], ... . */ + nxnode = node; +s600: num++; + np = invp[nxnode]; + ip = perm[num]; + perm[np] = ip; + invp[ip] = np; + perm[num] = nxnode; + invp[nxnode] = num; + deg[nxnode] = -1; + nxnode = qlink[nxnode]; + if (nxnode > 0) goto s600; + if (rchsze > 0) + { /* Update the degrees of the nodes in the reachable set and + * identify indistinguishable nodes. */ + qmdupd(xadj, adjncy, &rchsze, rchset, deg, qsize, qlink, + marker, &rchset[rchsze+1], &nbrhd[nhdsze+1]); + /* Reset marker value of nodes in reach set. Update threshold + * value for cyclic search. Also call qmdqt to form new + * quotient graph. */ + marker[node] = 0; + for (irch = 1; irch <= rchsze; irch++) + { inode = rchset[irch]; + if (marker[inode] >= 0) + { marker[inode] = 0; + ndeg = deg[inode]; + if (ndeg < mindeg) mindeg = ndeg; + if (ndeg <= thresh) + { mindeg = thresh; + thresh = ndeg; + search = invp[inode]; + } + } + } + if (nhdsze > 0) + qmdqt(&node, xadj, adjncy, marker, &rchsze, rchset, nbrhd); + } + if (num < neqns) goto s300; + return; +# undef neqns +# undef nofsub +} + +/*********************************************************************** +* NAME +* +* qmdrch - Quotient MD ReaCHable set +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdrch(int *root, int xadj[], int adjncy[], int deg[], +* int marker[], int *rchsze, int rchset[], int *nhdsze, +* int nbrhd[]); +* +* PURPOSE +* +* This subroutine determines the reachable set of a node through a +* given subset. The adjancy structure is assumed to be stored in a +* quotient graph format. +* +* INPUT PARAMETERS +* +* root - the given node not in the subset; +* (xadj, adjncy) - +* the adjancy structure pair; +* deg - the degree vector. deg[i] < 0 means the node belongs to the +* given subset. +* +* OUTPUT PARAMETERS +* +* (rchsze, rchset) - +* the reachable set; +* (nhdsze, nbrhd) - +* the neighborhood set. +* +* UPDATED PARAMETERS +* +* marker - the marker vector for reach and nbrhd sets. > 0 means the +* node is in reach set. < 0 means the node has been merged +* with others in the quotient or it is in nbrhd set. +***********************************************************************/ + +void qmdrch(int *_root, int xadj[], int adjncy[], int deg[], + int marker[], int *_rchsze, int rchset[], int *_nhdsze, + int nbrhd[]) +{ int i, istop, istrt, j, jstop, jstrt, nabor, node; +# define root (*_root) +# define rchsze (*_rchsze) +# define nhdsze (*_nhdsze) + /* Loop through the neighbors of root in the quotient graph. */ + nhdsze = 0; + rchsze = 0; + istrt = xadj[root]; + istop = xadj[root+1] - 1; + if (istop < istrt) return; + for (i = istrt; i <= istop; i++) + { nabor = adjncy[i]; + if (nabor == 0) return; + if (marker[nabor] == 0) + { if (deg[nabor] >= 0) + { /* Include nabor into the reachable set. */ + rchsze++; + rchset[rchsze] = nabor; + marker[nabor] = 1; + goto s600; + } + /* nabor has been eliminated. Find nodes reachable from + * it. */ + marker[nabor] = -1; + nhdsze++; + nbrhd[nhdsze] = nabor; +s300: jstrt = xadj[nabor]; + jstop = xadj[nabor+1] - 1; + for (j = jstrt; j <= jstop; j++) + { node = adjncy[j]; + nabor = - node; + if (node < 0) goto s300; + if (node == 0) goto s600; + if (marker[node] == 0) + { rchsze++; + rchset[rchsze] = node; + marker[node] = 1; + } + } + } +s600: ; + } + return; +# undef root +# undef rchsze +# undef nhdsze +} + +/*********************************************************************** +* NAME +* +* qmdqt - Quotient MD Quotient graph Transformation +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdqt(int *root, int xadj[], int adjncy[], int marker[], +* int *rchsze, int rchset[], int nbrhd[]); +* +* PURPOSE +* +* This subroutine performs the quotient graph transformation after a +* node has been eliminated. +* +* INPUT PARAMETERS +* +* root - the node just eliminated. It becomes the representative of +* the new supernode; +* (xadj, adjncy) - +* the adjancy structure; +* (rchsze, rchset) - +* the reachable set of root in the old quotient graph; +* nbrhd - the neighborhood set which will be merged with root to form +* the new supernode; +* marker - the marker vector. +* +* UPDATED PARAMETERS +* +* adjncy - becomes the adjncy of the quotient graph. +***********************************************************************/ + +void qmdqt(int *_root, int xadj[], int adjncy[], int marker[], + int *_rchsze, int rchset[], int nbrhd[]) +{ int inhd, irch, j, jstop, jstrt, link, nabor, node; +# define root (*_root) +# define rchsze (*_rchsze) + irch = 0; + inhd = 0; + node = root; +s100: jstrt = xadj[node]; + jstop = xadj[node+1] - 2; + if (jstop >= jstrt) + { /* Place reach nodes into the adjacent list of node. */ + for (j = jstrt; j <= jstop; j++) + { irch++; + adjncy[j] = rchset[irch]; + if (irch >= rchsze) goto s400; + } + } + /* Link to other space provided by the nbrhd set. */ + link = adjncy[jstop+1]; + node = - link; + if (link >= 0) + { inhd++; + node = nbrhd[inhd]; + adjncy[jstop+1] = - node; + } + goto s100; + /* All reachable nodes have been saved. End the adjacent list. + * Add root to the neighborhood list of each node in the reach + * set. */ +s400: adjncy[j+1] = 0; + for (irch = 1; irch <= rchsze; irch++) + { node = rchset[irch]; + if (marker[node] >= 0) + { jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] < 0) + { adjncy[j] = root; + goto s600; + } + } + } +s600: ; + } + return; +# undef root +# undef rchsze +} + +/*********************************************************************** +* NAME +* +* qmdupd - Quotient MD UPDate +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], +* int deg[], int qsize[], int qlink[], int marker[], int rchset[], +* int nbrhd[]); +* +* PURPOSE +* +* This routine performs degree update for a set of nodes in the minimum +* degree algorithm. +* +* INPUT PARAMETERS +* +* (xadj, adjncy) - +* the adjancy structure; +* (nlist, list) - +* the list of nodes whose degree has to be updated. +* +* UPDATED PARAMETERS +* +* deg - the degree vector; +* qsize - size of indistinguishable supernodes; +* qlink - linked list for indistinguishable nodes; +* marker - used to mark those nodes in reach/nbrhd sets. +* +* WORKING PARAMETERS +* +* rchset - the reachable set; +* nbrhd - the neighborhood set. +* +* PROGRAM SUBROUTINES +* +* qmdmrg. +***********************************************************************/ + +void qmdupd(int xadj[], int adjncy[], int *_nlist, int list[], + int deg[], int qsize[], int qlink[], int marker[], int rchset[], + int nbrhd[]) +{ int deg0, deg1, il, inhd, inode, irch, j, jstop, jstrt, mark, + nabor, nhdsze, node, rchsze; +# define nlist (*_nlist) + /* Find all eliminated supernodes that are adjacent to some nodes + * in the given list. Put them into (nhdsze, nbrhd). deg0 contains + * the number of nodes in the list. */ + if (nlist <= 0) return; + deg0 = 0; + nhdsze = 0; + for (il = 1; il <= nlist; il++) + { node = list[il]; + deg0 += qsize[node]; + jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] == 0 && deg[nabor] < 0) + { marker[nabor] = -1; + nhdsze++; + nbrhd[nhdsze] = nabor; + } + } + } + /* Merge indistinguishable nodes in the list by calling the + * subroutine qmdmrg. */ + if (nhdsze > 0) + qmdmrg(xadj, adjncy, deg, qsize, qlink, marker, °0, &nhdsze, + nbrhd, rchset, &nbrhd[nhdsze+1]); + /* Find the new degrees of the nodes that have not been merged. */ + for (il = 1; il <= nlist; il++) + { node = list[il]; + mark = marker[node]; + if (mark == 0 || mark == 1) + { marker[node] = 2; + qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, + &nhdsze, nbrhd); + deg1 = deg0; + if (rchsze > 0) + { for (irch = 1; irch <= rchsze; irch++) + { inode = rchset[irch]; + deg1 += qsize[inode]; + marker[inode] = 0; + } + } + deg[node] = deg1 - 1; + if (nhdsze > 0) + { for (inhd = 1; inhd <= nhdsze; inhd++) + { inode = nbrhd[inhd]; + marker[inode] = 0; + } + } + } + } + return; +# undef nlist +} + +/*********************************************************************** +* NAME +* +* qmdmrg - Quotient MD MeRGe +* +* SYNOPSIS +* +* #include "qmd.h" +* void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], +* int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], +* int rchset[], int ovrlp[]); +* +* PURPOSE +* +* This routine merges indistinguishable nodes in the minimum degree +* ordering algorithm. It also computes the new degrees of these new +* supernodes. +* +* INPUT PARAMETERS +* +* (xadj, adjncy) - +* the adjancy structure; +* deg0 - the number of nodes in the given set; +* (nhdsze, nbrhd) - +* the set of eliminated supernodes adjacent to some nodes in +* the set. +* +* UPDATED PARAMETERS +* +* deg - the degree vector; +* qsize - size of indistinguishable nodes; +* qlink - linked list for indistinguishable nodes; +* marker - the given set is given by those nodes with marker value set +* to 1. Those nodes with degree updated will have marker value +* set to 2. +* +* WORKING PARAMETERS +* +* rchset - the reachable set; +* ovrlp - temp vector to store the intersection of two reachable sets. +***********************************************************************/ + +void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], + int qlink[], int marker[], int *_deg0, int *_nhdsze, int nbrhd[], + int rchset[], int ovrlp[]) +{ int deg1, head, inhd, iov, irch, j, jstop, jstrt, link, lnode, + mark, mrgsze, nabor, node, novrlp, rchsze, root; +# define deg0 (*_deg0) +# define nhdsze (*_nhdsze) + /* Initialization. */ + if (nhdsze <= 0) return; + for (inhd = 1; inhd <= nhdsze; inhd++) + { root = nbrhd[inhd]; + marker[root] = 0; + } + /* Loop through each eliminated supernode in the set + * (nhdsze, nbrhd). */ + for (inhd = 1; inhd <= nhdsze; inhd++) + { root = nbrhd[inhd]; + marker[root] = -1; + rchsze = 0; + novrlp = 0; + deg1 = 0; +s200: jstrt = xadj[root]; + jstop = xadj[root+1] - 1; + /* Determine the reachable set and its intersection with the + * input reachable set. */ + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + root = - nabor; + if (nabor < 0) goto s200; + if (nabor == 0) break; + mark = marker[nabor]; + if (mark == 0) + { rchsze++; + rchset[rchsze] = nabor; + deg1 += qsize[nabor]; + marker[nabor] = 1; + } + else if (mark == 1) + { novrlp++; + ovrlp[novrlp] = nabor; + marker[nabor] = 2; + } + } + /* From the overlapped set, determine the nodes that can be + * merged together. */ + head = 0; + mrgsze = 0; + for (iov = 1; iov <= novrlp; iov++) + { node = ovrlp[iov]; + jstrt = xadj[node]; + jstop = xadj[node+1] - 1; + for (j = jstrt; j <= jstop; j++) + { nabor = adjncy[j]; + if (marker[nabor] == 0) + { marker[node] = 1; + goto s1100; + } + } + /* Node belongs to the new merged supernode. Update the + * vectors qlink and qsize. */ + mrgsze += qsize[node]; + marker[node] = -1; + lnode = node; +s900: link = qlink[lnode]; + if (link > 0) + { lnode = link; + goto s900; + } + qlink[lnode] = head; + head = node; +s1100: ; + } + if (head > 0) + { qsize[head] = mrgsze; + deg[head] = deg0 + deg1 - 1; + marker[head] = 2; + } + /* Reset marker values. */ + root = nbrhd[inhd]; + marker[root] = 0; + if (rchsze > 0) + { for (irch = 1; irch <= rchsze; irch++) + { node = rchset[irch]; + marker[node] = 0; + } + } + } + return; +# undef deg0 +# undef nhdsze +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.h new file mode 100644 index 000000000..e55d50f52 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/qmd.h @@ -0,0 +1,58 @@ +/* qmd.h (quotient minimum degree algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2001-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef QMD_H +#define QMD_H + +#define genqmd _glp_genqmd +void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], + int invp[], int deg[], int marker[], int rchset[], int nbrhd[], + int qsize[], int qlink[], int *nofsub); +/* GENeral Quotient Minimum Degree algorithm */ + +#define qmdrch _glp_qmdrch +void qmdrch(int *root, int xadj[], int adjncy[], int deg[], + int marker[], int *rchsze, int rchset[], int *nhdsze, + int nbrhd[]); +/* Quotient MD ReaCHable set */ + +#define qmdqt _glp_qmdqt +void qmdqt(int *root, int xadj[], int adjncy[], int marker[], + int *rchsze, int rchset[], int nbrhd[]); +/* Quotient MD Quotient graph Transformation */ + +#define qmdupd _glp_qmdupd +void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], + int deg[], int qsize[], int qlink[], int marker[], int rchset[], + int nbrhd[]); +/* Quotient MD UPDate */ + +#define qmdmrg _glp_qmdmrg +void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], + int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], + int rchset[], int ovrlp[]); +/* Quotient MD MeRGe */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.c new file mode 100644 index 000000000..f0a47d6d5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.c @@ -0,0 +1,2850 @@ +/* relax4.c (relaxation method of Bertsekas and Tseng) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN CODE RELAX4. +* +* THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHOR OF +* THE ORIGINAL FORTRAN CODE PROF. DIMITRI P. BERTSEKAS, MASSACHUSETTS +* INSTITUTE OF TECHNOLOGY, CAMBRIDGE, MASSACHUSETTS, USA. +* +* The translation was made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "relax4.h" + +/*********************************************************************** +* WARNING +* +* A serious bug was *tentatively* fixed in this code (see #if/#endif +* marked by 'mao'). +* +* This bug is inherited from the original Fortran version of the +* RELAX-IV code. Unfortunately, the code is very intricate, so this +* bug is still under investigation. Thanks to Sylvain Fournier for bug +* report. +* +* RELAX-IV bug details +* -------------------- +* In the original RELAX-IV code there are four similar fragments in +* subroutines ascnt1 and ascnt2 like this: +* +* C +* C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. +* C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH +* C THE PRICES. +* C +* NB = 0 +* DO 6 I=1,NSAVE +* . . . +* IF (RC(ARC).EQ.0) THEN +* DELX=DELX+U(ARC) +* NB = NB + 1 +* PRDCSR(NB) = ARC +* END IF +* . . . +* +* On some instances the variable NB becomes greater than N (the number +* of nodes) that leads to indexing error, because the array PRDCSR is +* declared as array of N elements (more precisely, as array of MAXNN +* elements, however, NB becomes even much greater than MAXNN). +***********************************************************************/ + +#define false 0 +#define true 1 + +/*********************************************************************** +* NAME +* +* RELAX-IV (version of October 1994) +* +* PURPOSE +* +* This routine implements the relaxation method of Bertsekas and Tseng +* (see [1], [2]) for linear cost ordinary network flow problems. +* +* [1] Bertsekas, D. P., "A Unified Framework for Primal-Dual Methods" +* Mathematical Programming, Vol. 32, 1985, pp. 125-145. +* [2] Bertsekas, D. P., and Tseng, P., "Relaxation Methods for +* Minimum Cost" Operations Research, Vol. 26, 1988, pp. 93-114. +* +* The relaxation method is also described in the books: +* +* [3] Bertsekas, D. P., "Linear Network Optimization: Algorithms and +* Codes" MIT Press, 1991. +* [4] Bertsekas, D. P. and Tsitsiklis, J. N., "Parallel and Distributed +* Computation: Numerical Methods", Prentice-Hall, 1989. +* [5] Bertsekas, D. P., "Network Optimization: Continuous and Discrete +* Models", Athena Scientific, 1998. +* +* RELEASE NOTE +* +* This version of relaxation code has option for a special crash +* procedure for the initial price-flow pair. This is recommended for +* difficult problems where the default initialization results in long +* running times. crash = 1 corresponds to an auction/shortest path +* method +* +* These initializations are recommended in the absence of any prior +* information on a favorable initial flow-price vector pair that +* satisfies complementary slackness. +* +* The relaxation portion of the code differs from the code RELAXT-III +* and other earlier relaxation codes in that it maintains the set of +* nodes with nonzero deficit in a fifo queue. Like its predecessor +* RELAXT-III, this code maintains a linked list of balanced (i.e., of +* zero reduced cost) arcs so to reduce the work in labeling and +* scanning. Unlike RELAXT-III, it does not use selectively shortest +* path iterations for initialization. +* +* SOURCE +* +* The original Fortran code was written by Dimitri P. Bertsekas and +* Paul Tseng, with a contribution by Jonathan Eckstein in the phase II +* initialization. The original Fortran routine AUCTION was written by +* Dimitri P. Bertsekas and is based on the method described in the +* paper: +* +* [6] Bertsekas, D. P., "An Auction/Sequential Shortest Path Algorithm +* for the Minimum Cost Flow Problem", LIDS Report P-2146, MIT, +* Nov. 1992. +* +* For inquiries about the original Fortran code, please contact: +* +* Dimitri P. Bertsekas +* Laboratory for information and decision systems +* Massachusetts Institute of Technology +* Cambridge, MA 02139 +* (617) 253-7267, dimitrib@mit.edu +* +* This code is the result of translation of the original Fortran code. +* The translation was made by Andrew Makhorin . +* +* USER GUIDELINES +* +* This routine is in the public domain to be used only for research +* purposes. It cannot be used as part of a commercial product, or to +* satisfy in any part commercial delivery requirements to government +* or industry, without prior agreement with the authors. Users are +* requested to acknowledge the authorship of the code, and the +* relaxation method. +* +* No modification should be made to this code other than the minimal +* necessary to make it compatible with specific platforms. +* +* INPUT PARAMETERS (see notes 1, 2, 4) +* +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity +* (see note 3) +* repeat = true if initialization is to be skipped +* (false otherwise) +* crash = 0 if default initialization is used +* 1 if auction initialization is used +* startn[j] = starting node for arc j, j = 1,...,na +* endn[j] = ending node for arc j, j = 1,...,na +* fou[i] = first arc out of node i, i = 1,...,n +* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na +* fin[i] = first arc into node i, i = 1,...,n +* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na +* +* UPDATED PARAMETERS (see notes 1, 3, 4) +* +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = capacity of arc j on input +* and (capacity of arc j) - x[j] on output, j = 1,...,na +* dfct[i] = demand at node i on input +* and zero on output, i = 1,...,n +* +* OUTPUT PARAMETERS (see notes 1, 3, 4) +* +* x[j] = flow on arc j, j = 1,...,na +* nmultinode = number of multinode relaxation iterations in RELAX4 +* iter = number of relaxation iterations in RELAX4 +* num_augm = number of flow augmentation steps in RELAX4 +* num_ascnt = number of multinode ascent steps in RELAX4 +* nsp = number of auction/shortest path iterations +* +* WORKING PARAMETERS (see notes 1, 4, 5) +* +* label[1+n], prdcsr[1+n], save[1+na], tfstou[1+n], tnxtou[1+na], +* tfstin[1+n], tnxtin[1+na], nxtqueue[1+n], scan[1+n], mark[1+n], +* extend_arc[1+n], sb_level[1+n], sb_arc[1+n] +* +* RETURNS +* +* 0 = normal return +* 1,...,8 = problem is found to be infeasible +* +* NOTE 1 +* +* To run in limited memory systems, declare the arrays startn, endn, +* nxtin, nxtou, fin, fou, label, prdcsr, save, tfstou, tnxtou, tfstin, +* tnxtin, ddpos, ddneg, nxtqueue as short instead. +* +* NOTE 2 +* +* This routine makes no effort to initialize with a favorable x from +* amongst those flow vectors that satisfy complementary slackness with +* the initial reduced cost vector rc. If a favorable x is known, then +* it can be passed, together with the corresponding arrays u and dfct, +* to this routine directly. This, however, requires that the capacity +* tightening portion and the flow initialization portion of this +* routine (up to line labeled 90) be skipped. +* +* NOTE 3 +* +* All problem data should be less than large in magnitude, and large +* should be less than, say, 1/4 the largest int of the machine used. +* This will guard primarily against overflow in uncapacitated problems +* where the arc capacities are taken finite but very large. Note, +* however, that as in all codes operating with integers, overflow may +* occur if some of the problem data takes very large values. +* +* NOTE 4 +* +* [This note being specific to Fortran was removed.-A.M.] +* +* NOTE 5 +* +* ddpos and ddneg are arrays that give the directional derivatives for +* all positive and negative single-node price changes. These are used +* only in phase II of the initialization procedure, before the linked +* list of balanced arcs comes to play. Therefore, to reduce storage, +* they are equivalence to tfstou and tfstin, which are of the same size +* (number of nodes) and are used only after the tree comes into use. */ + +static void ascnt1(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode); + +static void ascnt2(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode); + +static int auction(struct relax4_csa *csa); + +int relax4(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int large = csa->large; + int repeat = csa->repeat; + int crash = csa->crash; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ + int *rc = csa->rc; + int *u = csa->u; + int *dfct = csa->dfct; + /* output parameters */ + int *x = csa->x; +# define nmultinode (csa->nmultinode) +# define iter (csa->iter) +# define num_augm (csa->num_augm) +# define num_ascnt (csa->num_ascnt) +# define nsp (csa->nsp) + /* working parameters */ + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *save = csa->save; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *ddpos = tfstou; + int *ddneg = tfstin; + /* local variables */ + int arc, augnod, capin, capout, defcit, delprc, delx, dm, dp, + dx, feasbl, i, ib, indef, j, lastqueue, maxcap, narc, nb, + nlabel, node, node2, node_def, naugnod, nscan, num_passes, + numnz, numnz_new, numpasses, nxtarc, nxtbrk, nxtnode, passes, + pchange, posit, prevnode, prvarc, quit, rdcost, scapin, + scapou, svitch, t, t1, t2, tmparc, tp, trc, ts; + /*--------------------------------------------------------------*/ + /* Initialization phase I */ + /* In this phase, we reduce the arc capacities by as much as + * possible without changing the problem; then we set the initial + * flow array x, together with the corresponding arrays u and + * dfct. */ + /* This phase and phase II (from here up to line labeled 90) can + * be skipped (by setting repeat to true) if the calling program + * places in common user-chosen values for the arc flows, the + * residual arc capacities, and the nodal deficits. When this is + * done, it is critical that the flow and the reduced cost for + * each arc satisfy complementary slackness and the dfct array + * properly correspond to the initial arc/flows. */ + if (repeat) + goto L90; + for (node = 1; node <= n; node++) + { node_def = dfct[node]; + ddpos[node] = node_def; + ddneg[node] = -node_def; + maxcap = 0; + scapou = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (scapou <= large - u[arc]) + scapou += u[arc]; + else + goto L10; + } + if (scapou <= large - node_def) + capout = scapou + node_def; + else + goto L10; + if (capout < 0) + { /* problem is infeasible */ + /* exogenous flow into node exceeds out capacity */ + return 1; + } + scapin = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { if (u[arc] > capout) + u[arc] = capout; + if (maxcap < u[arc]) + maxcap = u[arc]; + if (scapin <= large - u[arc]) + scapin += u[arc]; + else + goto L10; + } + if (scapin <= large + node_def) + capin = scapin - node_def; + else + goto L10; + if (capin < 0) + { /* problem is infeasible */ + /* exogenous flow out of node exceeds in capacity */ + return 2; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > capin) + u[arc] = capin; + } +L10: ; + } + /*--------------------------------------------------------------*/ + /* Initialization phase II */ + /* In this phase, we initialize the prices and flows by either + * calling the routine auction or by performing only single node + * (coordinate) relaxation iterations. */ + if (crash == 1) + { nsp = 0; + if (auction(csa) != 0) + { /* problem is found to be infeasible */ + return 3; + } + goto L70; + } + /* Initialize the arc flows to satisfy complementary slackness + * with the prices. u[arc] is the residual capacity of arc, and + * x[arc] is the flow. These two always add up to the total + * capacity for arc. Also compute the directional derivatives for + * each coordinate and compute the actual deficits. */ + for (arc = 1; arc <= na; arc++) + { x[arc] = 0; + if (rc[arc] <= 0) + { t = u[arc]; + t1 = startn[arc]; + t2 = endn[arc]; + ddpos[t1] += t; + ddneg[t2] += t; + if (rc[arc] < 0) + { x[arc] = t; + u[arc] = 0; + dfct[t1] += t; + dfct[t2] -= t; + ddneg[t1] -= t; + ddpos[t2] -= t; + } + } + } + /* Make 2 or 3 passes through all nodes, performing only single + * node relaxation iterations. The number of passes depends on the + * density of the network. */ + if (na > n * 10) + numpasses = 2; + else + numpasses = 3; + for (passes = 1; passes <= numpasses; passes++) + for (node = 1; node <= n; node++) + { if (dfct[node] == 0) + continue; + if (ddpos[node] <= 0) + { /* Compute delprc, the stepsize to the next breakpoint in + * the dual cost as the price of node is increased. + * [Since the reduced cost of all outgoing (resp., incoming) + * arcs will decrease (resp., increase) as the price of node + * is increased, the next breakpoint is the minimum of the + * positive reduced cost on outgoing arcs and of the + * negative reduced cost on incoming arcs.] */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if ((trc > 0) && (trc < delprc)) + delprc = trc; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if ((trc < 0) && (trc > -delprc)) + delprc = -trc; + } + /* If no breakpoint is left and dual ascent is still + * possible, the problem is infeasible. */ + if (delprc >= large) + { if (ddpos[node] == 0) + continue; + return 4; + } + /* delprc is the stepsize to next breakpoint. Increase + * price of node by delprc and compute the stepsize to the + * next breakpoint in the dual cost. */ +L53: nxtbrk = large; + /* Look at all arcs out of node. */ + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = endn[arc]; + t = u[arc]; + if (t > 0) + { dfct[node] += t; + dfct[t1] -= t; + x[arc] = t; + u[arc] = 0; + } + else + t = x[arc]; + ddneg[node] -= t; + ddpos[t1] -= t; + } + /* Decrease the reduced costs on all outgoing arcs. */ + trc -= delprc; + if ((trc > 0) && (trc < nxtbrk)) + nxtbrk = trc; + else if (trc == 0) + { /* Arc goes from inactive to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddpos[node] += u[arc]; + ddneg[endn[arc]] += u[arc]; + } + rc[arc] = trc; + } + /* Look at all arcs into node. */ + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = startn[arc]; + t = x[arc]; + if (t > 0) + { dfct[node] += t; + dfct[t1] -= t; + u[arc] = t; + x[arc] = 0; + } + else + t = u[arc]; + ddpos[t1] -= t; + ddneg[node] -= t; + } + /* Increase the reduced cost on all incoming arcs. */ + trc += delprc; + if ((trc < 0) && (trc > -nxtbrk)) + nxtbrk = -trc; + else if (trc == 0) + { /* Arc goes from active to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddneg[startn[arc]] += x[arc]; + ddpos[node] += x[arc]; + } + rc[arc] = trc; + } + /* If price of node can be increased further without + * decreasing the dual cost (even the dual cost doesn't + * increase), return to increase the price further. */ + if ((ddpos[node] <= 0) && (nxtbrk < large)) + { delprc = nxtbrk; + goto L53; + } + } + else if (ddneg[node] <= 0) + { /* Compute delprc, the stepsize to the next breakpoint in + * the dual cost as the price of node is decreased. + * [Since the reduced cost of all outgoing (resp., incoming) + * arcs will increase (resp., decrease) as the price of node + * is decreased, the next breakpoint is the minimum of the + * negative reduced cost on outgoing arcs and of the + * positive reduced cost on incoming arcs.] */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if ((trc < 0) && (trc > -delprc)) + delprc = -trc; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if ((trc > 0) && (trc < delprc)) + delprc = trc; + } + /* If no breakpoint is left and dual ascent is still + * possible, the problem is infeasible. */ + if (delprc == large) + { if (ddneg[node] == 0) + continue; + return 5; + } + /* delprc is the stepsize to next breakpoint. Decrease + * price of node by delprc and compute the stepsize to the + * next breakpoint in the dual cost. */ +L63: nxtbrk = large; + /* Look at all arcs out of node. */ + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = endn[arc]; + t = x[arc]; + if (t > 0) + { dfct[node] -= t; + dfct[t1] += t; + u[arc] = t; + x[arc] = 0; + } + else + t = u[arc]; + ddpos[node] -= t; + ddneg[t1] -= t; + } + /* Increase the reduced cost on all outgoing arcs. */ + trc += delprc; + if ((trc < 0) && (trc > -nxtbrk)) + nxtbrk = -trc; + else if (trc == 0) + { /* Arc goes from active to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddneg[node] += x[arc]; + ddpos[endn[arc]] += x[arc]; + } + rc[arc] = trc; + } + /* Look at all arcs into node. */ + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { trc = rc[arc]; + if (trc == 0) + { t1 = startn[arc]; + t = u[arc]; + if (t > 0) + { dfct[node] -= t; + dfct[t1] += t; + x[arc] = t; + u[arc] = 0; + } + else + t = x[arc]; + ddneg[t1] -= t; + ddpos[node] -= t; + } + /* Decrease the reduced cost on all incoming arcs. */ + trc -= delprc; + if ((trc > 0) && (trc < nxtbrk)) + nxtbrk = trc; + else if (trc == 0) + { /* Arc goes from inactive to balanced. Update the rate + * of dual ascent at node and at its neighbor. */ + ddpos[startn[arc]] += u[arc]; + ddneg[node] += u[arc]; + } + rc[arc] = trc; + } + /* If price of node can be decreased further without + * decreasing the dual cost (even the dual cost doesn't + * increase), return to decrease the price further. */ + if ((ddneg[node] <= 0) && (nxtbrk < large)) + { delprc = nxtbrk; + goto L63; + } + } + } + /*--------------------------------------------------------------*/ +L70: /* Initialize tree data structure. */ + for (i = 1; i <= n; i++) + tfstou[i] = tfstin[i] = 0; + for (i = 1; i <= na; i++) + { tnxtin[i] = tnxtou[i] = -1; + if (rc[i] == 0) + { tnxtou[i] = tfstou[startn[i]]; + tfstou[startn[i]] = i; + tnxtin[i] = tfstin[endn[i]]; + tfstin[endn[i]] = i; + } + } +L90: /* Initialize other variables. */ + feasbl = true; + iter = 0; + nmultinode = 0; + num_augm = 0; + num_ascnt = 0; + num_passes = 0; + numnz = n; + numnz_new = 0; + svitch = false; + for (i = 1; i <= n; i++) + mark[i] = scan[i] = false; + nlabel = 0; + /* RELAX4 uses an adaptive strategy to decide whether to continue + * the scanning process after a multinode price change. + * The threshold parameter tp and ts that control this strategy + * are set in the next two lines. */ + tp = 10; + ts = n / 15; + /* Initialize the queue of nodes with nonzero deficit. */ + for (node = 1; node <= n - 1; node++) + nxtqueue[node] = node + 1; + nxtqueue[n] = 1; + node = lastqueue = n; + /*--------------------------------------------------------------*/ + /* Start the relaxation algorithm. */ +L100: /* Code for advancing the queue of nonzero deficit nodes. */ + prevnode = node; + node = nxtqueue[node]; + defcit = dfct[node]; + if (node == lastqueue) + { numnz = numnz_new; + numnz_new = 0; + lastqueue = prevnode; + num_passes++; + } + /* Code for deleting a node from the queue. */ + if (defcit == 0) + { nxtnode = nxtqueue[node]; + if (node == nxtnode) + return 0; + else + { nxtqueue[prevnode] = nxtnode; + nxtqueue[node] = 0; + node = nxtnode; + goto L100; + } + } + else + posit = (defcit > 0); + iter++; + numnz_new++; + if (posit) + { /* Attempt a single node iteration from node with positive + * deficit. */ + pchange = false; + indef = defcit; + delx = 0; + nb = 0; + /* Check outgoing (probably) balanced arcs from node. */ + for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) + { if ((rc[arc] == 0) && (x[arc] > 0)) + { delx += x[arc]; + nb++; + save[nb] = arc; + } + } + /* Check incoming arcs. */ + for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) + { if ((rc[arc] == 0) && (u[arc] > 0)) + { delx += u[arc]; + nb++; + save[nb] = -arc; + } + } + /* End of initial node scan. */ +L4018: /* If no price change is possible, exit. */ + if (delx > defcit) + { quit = (defcit < indef); + goto L4016; + } + /* RELAX4 searches along the ascent direction for the best + * price by checking the slope of the dual cost at successive + * break points. First, we compute the distance to the next + * break point. */ + delprc = large; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Check if problem is infeasible. */ + if ((delx < defcit) && (delprc == large)) + { /* The dual cost can be decreased without bound. */ + return 6; + } + /* Skip flow adjustment if there is no flow to modify. */ + if (delx == 0) + goto L4014; + /* Adjust the flow on the balanced arcs incident to node to + * maintain complementary slackness after the price change. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { node2 = endn[arc]; + t1 = x[arc]; + dfct[node2] += t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + u[arc] += t1; + x[arc] = 0; + } + else + { narc = -arc; + node2 = startn[narc]; + t1 = u[narc]; + dfct[node2] += t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += t1; + u[narc] = 0; + } + } + defcit -= delx; +L4014: if (delprc == large) + { quit = true; + goto L4019; + } + /* Node corresponds to a dual ascent direction. Decrease the + * price of node by delprc and compute the stepsize to the next + * breakpoint in the dual cost. */ + nb = 0; + pchange = true; + dp = delprc; + delprc = large; + delx = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc] + dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = arc; + delx += x[arc]; + } + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc] - dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = -arc; + delx += u[arc]; + } + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Return to check if another price change is possible. */ + goto L4018; +L4016: /* Perform flow augmentation at node. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { /* arc is an outgoing arc from node. */ + node2 = endn[arc]; + t1 = dfct[node2]; + if (t1 < 0) + { /* Decrease the total deficit by decreasing flow of + * arc. */ + quit = true; + t2 = x[arc]; + dx = defcit; + if (dx > -t1) dx = -t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 + dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[arc] = t2 - dx; + u[arc] += dx; + if (defcit == 0) + break; + } + } + else + { /* -arc is an incoming arc to node. */ + narc = -arc; + node2 = startn[narc]; + t1 = dfct[node2]; + if (t1 < 0) + { /* Decrease the total deficit by increasing flow of + * -arc. */ + quit = true; + t2 = u[narc]; + dx = defcit; + if (dx > -t1) dx = -t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 + dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += dx; + u[narc] = t2 - dx; + if (defcit == 0) + break; + } + } + } +L4019: dfct[node] = defcit; + /* Reconstruct the linked list of balance arcs incident to this + * node. For each adjacent node, we add any newly balanced arcs + * to the list, but do not bother removing formerly balanced + * ones (they will be removed the next time each adjacent node + * is scanned). */ + if (pchange) + { arc = tfstou[node]; + tfstou[node] = 0; + while (arc > 0) + { nxtarc = tnxtou[arc]; + tnxtou[arc] = -1; + arc = nxtarc; + } + arc = tfstin[node]; + tfstin[node] = 0; + while (arc > 0) + { nxtarc = tnxtin[arc]; + tnxtin[arc] = -1; + arc = nxtarc; + } + /* Now add the currently balanced arcs to the list for this + * node (which is now empty), and the appropriate adjacent + * ones. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc < 0) + arc = -arc; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + } + } + /* End of single node iteration for positive deficit node. */ + } + else + { /* Attempt a single node iteration from node with negative + * deficit. */ + pchange = false; + defcit = -defcit; + indef = defcit; + delx = 0; + nb = 0; + for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) + { if ((rc[arc] == 0) && (x[arc] > 0)) + { delx += x[arc]; + nb++; + save[nb] = arc; + } + } + for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) + { if ((rc[arc] == 0) && (u[arc] > 0)) + { delx += u[arc]; + nb++; + save[nb] = -arc; + } + } +L4028: if (delx >= defcit) + { quit = (defcit < indef); + goto L4026; + } + /* Compute distance to next breakpoint. */ + delprc = large; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + /* Check if problem is infeasible. */ + if ((delx < defcit) && (delprc == large)) + return 7; + if (delx == 0) + goto L4024; + /* Flow augmentation is possible. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { node2 = startn[arc]; + t1 = x[arc]; + dfct[node2] -= t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + u[arc] += t1; + x[arc] = 0; + } + else + { narc = -arc; + node2 = endn[narc]; + t1 = u[narc]; + dfct[node2] -= t1; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += t1; + u[narc] = 0; + } + } + defcit -= delx; +L4024: if (delprc == large) + { quit = true; + goto L4029; + } + /* Price increase at node is possible. */ + nb = 0; + pchange = true; + dp = delprc; + delprc = large; + delx = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { rdcost = rc[arc] + dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = arc; + delx += x[arc]; + } + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { rdcost = rc[arc] - dp; + rc[arc] = rdcost; + if (rdcost == 0) + { nb++; + save[nb] = -arc; + delx += u[arc]; + } + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + goto L4028; +L4026: /* Perform flow augmentation at node. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { /* arc is an incoming arc to node. */ + node2 = startn[arc]; + t1 = dfct[node2]; + if (t1 > 0) + { quit = true; + t2 = x[arc]; + dx = defcit; + if (dx > t1) dx = t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 - dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[arc] = t2 - dx; + u[arc] += dx; + if (defcit == 0) + break; + } + } + else + { /* -arc is an outgoing arc from node. */ + narc = -arc; + node2 = endn[narc]; + t1 = dfct[node2]; + if (t1 > 0) + { quit = true; + t2 = u[narc]; + dx = defcit; + if (dx > t1) dx = t1; + if (dx > t2) dx = t2; + defcit -= dx; + dfct[node2] = t1 - dx; + if (nxtqueue[node2] == 0) + { nxtqueue[prevnode] = node2; + nxtqueue[node2] = node; + prevnode = node2; + } + x[narc] += dx; + u[narc] = t2 - dx; + if (defcit == 0) + break; + } + } + } +L4029: dfct[node] = -defcit; + /* Reconstruct the list of balanced arcs incident to node. */ + if (pchange) + { arc = tfstou[node]; + tfstou[node] = 0; + while (arc > 0) + { nxtarc = tnxtou[arc]; + tnxtou[arc] = -1; + arc = nxtarc; + } + arc = tfstin[node]; + tfstin[node] = 0; + while (arc > 0) + { nxtarc = tnxtin[arc]; + tnxtin[arc] = -1; + arc = nxtarc; + } + /* Now add the currently balanced arcs to the list for this + * node (which is now empty), and the appropriate adjacent + * ones. */ + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc <= 0) + arc = -arc; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + } + } + /* End of single node iteration for a negative deficit node. */ + } + if (quit || (num_passes <= 3)) + goto L100; + /* Do a multinode iteration from node. */ + nmultinode++; + /* If number of nonzero deficit nodes is small, continue labeling + * until a flow augmentation is done. */ + svitch = (numnz < tp); + /* Unmark nodes labeled earlier. */ + for (j = 1; j <= nlabel; j++) + { node2 = label[j]; + mark[node2] = scan[node2] = false; + } + /* Initialize labeling. */ + nlabel = 1; + label[1] = node; + mark[node] = true; + prdcsr[node] = 0; + /* Scan starting node. */ + scan[node] = true; + nscan = 1; + dm = dfct[node]; + delx = 0; + for (j = 1; j <= nb; j++) + { arc = save[j]; + if (arc > 0) + { if (posit) + node2 = endn[arc]; + else + node2 = startn[arc]; + if (!mark[node2]) + { nlabel++; + label[nlabel] = node2; + prdcsr[node2] = arc; + mark[node2] = true; + delx += x[arc]; + } + } + else + { narc = -arc; + if (posit) + node2 = startn[narc]; + else + node2 = endn[narc]; + if (!mark[node2]) + { nlabel++; + label[nlabel] = node2; + prdcsr[node2] = arc; + mark[node2] = true; + delx += u[narc]; + } + } + } +L4120:/* Start scanning a labeled but unscanned node. */ + nscan++; + /* Check to see if switch needs to be set to true so to continue + * scanning even after a price change. */ + svitch = svitch || ((nscan > ts) && (numnz < ts)); + /* Scanning will continue until either an overestimate of the + * residual capacity across the cut corresponding to the scanned + * set of nodes (called delx) exceeds the absolute value of the + * total deficit of the scanned nodes (called dm), or else an + * augmenting path is found. Arcs that are in the tree but are not + * balanced are removed as part of the scanning process. */ + i = label[nscan]; + scan[i] = true; + naugnod = 0; + if (posit) + { /* Scanning node i in case of positive deficit. */ + prvarc = 0; + arc = tfstou[i]; + while (arc > 0) + { /* arc is an outgoing arc from node. */ + if (rc[arc] == 0) + { if (x[arc] > 0) + { node2 = endn[arc]; + if (!mark[node2]) + { /* node2 is not labeled, so add node2 to the + labeled set. */ + prdcsr[node2] = arc; + if (dfct[node2] < 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += x[arc]; + } + } + prvarc = arc; + arc = tnxtou[arc]; + } + else + { tmparc = arc; + arc = tnxtou[arc]; + tnxtou[tmparc] = -1; + if (prvarc == 0) + tfstou[i] = arc; + else + tnxtou[prvarc] = arc; + } + } + prvarc = 0; + arc = tfstin[i]; + while (arc > 0) + { /* arc is an incoming arc into node. */ + if (rc[arc] == 0) + { if (u[arc] > 0) + { node2 = startn[arc]; + if (!mark[node2]) + { /* node2 is not labeled, so add node2 to the + * labeled set. */ + prdcsr[node2] = -arc; + if (dfct[node2] < 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += u[arc]; + } + } + prvarc = arc; + arc = tnxtin[arc]; + } + else + { tmparc = arc; + arc = tnxtin[arc]; + tnxtin[tmparc] = -1; + if (prvarc == 0) + tfstin[i] = arc; + else + tnxtin[prvarc] = arc; + } + } + /* Correct the residual capacity of the scanned node cut. */ + arc = prdcsr[i]; + if (arc > 0) + delx -= x[arc]; + else + delx -= u[-arc]; + /* End of scanning of node i for positive deficit case. */ + } + else + { /* Scanning node i for negative deficit case. */ + prvarc = 0; + arc = tfstin[i]; + while (arc > 0) + { if (rc[arc] == 0) + { if (x[arc] > 0) + { node2 = startn[arc]; + if (!mark[node2]) + { prdcsr[node2] = arc; + if (dfct[node2] > 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += x[arc]; + } + } + prvarc = arc; + arc = tnxtin[arc]; + } + else + { tmparc = arc; + arc = tnxtin[arc]; + tnxtin[tmparc] = -1; + if (prvarc == 0) + tfstin[i] = arc; + else + tnxtin[prvarc] = arc; + } + } + prvarc = 0; + arc = tfstou[i]; + while (arc > 0) + { if (rc[arc] == 0) + { if (u[arc] > 0) + { node2 = endn[arc]; + if (!mark[node2]) + { prdcsr[node2] = -arc; + if (dfct[node2] > 0) + { naugnod++; + save[naugnod] = node2; + } + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + delx += u[arc]; + } + } + prvarc = arc; + arc = tnxtou[arc]; + } + else + { tmparc = arc; + arc = tnxtou[arc]; + tnxtou[tmparc] = -1; + if (prvarc == 0) + tfstou[i] = arc; + else + tnxtou[prvarc] = arc; + } + } + arc = prdcsr[i]; + if (arc > 0) + delx -= x[arc]; + else + delx -= u[-arc]; + } + /* Add deficit of node scanned to dm. */ + dm += dfct[i]; + /* Check if the set of scanned nodes correspond to a dual ascent + * direction; if yes, perform a price adjustment step, otherwise + * continue labeling. */ + if (nscan < nlabel) + { if (svitch) + goto L4210; + if ((delx >= dm) && (delx >= -dm)) + goto L4210; + } + /* Try a price change. + * [Note that since delx - abs(dm) is an overestimate of ascent + * slope, we may occasionally try a direction that is not an + * ascent direction. In this case the ascnt routines return with + * quit = false, so we continue labeling nodes.] */ + if (posit) + { ascnt1(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, + &prevnode); + num_ascnt++; + } + else + { ascnt2(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, + &prevnode); + num_ascnt++; + } + if (!feasbl) + return 8; + if (!svitch) + goto L100; + /* Store those newly labeled nodes to which flow augmentation is + * possible. */ + naugnod = 0; + for (j = nscan + 1; j <= nlabel; j++) + { node2 = label[j]; + if (posit && (dfct[node2] < 0)) + { naugnod++; + save[naugnod] = node2; + } + else if ((!posit) && (dfct[node2] > 0)) + { naugnod++; + save[naugnod] = node2; + } + } +L4210:/* Check if flow augmentation is possible. If not, return to scan + * another node. */ + if (naugnod == 0) + goto L4120; + for (j = 1; j <= naugnod; j++) + { num_augm++; + augnod = save[j]; + if (posit) + { /* Do the augmentation from node with positive deficit. */ + dx = -dfct[augnod]; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { if (dx > x[arc]) dx = x[arc]; + ib = startn[arc]; + } + else + { if (dx > u[-arc]) dx = u[-arc]; + ib = endn[-arc]; + } + } + if (dx > dfct[node]) dx = dfct[node]; + if (dx > 0) + { /* Increase (decrease) the flow of all forward (backward) + * arcs in the flow augmenting path. Adjust node deficit + * accordingly. */ + if (nxtqueue[augnod] == 0) + { nxtqueue[prevnode] = augnod; + nxtqueue[augnod] = node; + prevnode = augnod; + } + dfct[augnod] += dx; + dfct[node] -= dx; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { x[arc] -= dx; + u[arc] += dx; + ib = startn[arc]; + } + else + { narc = -arc; + x[narc] += dx; + u[narc] -= dx; + ib = endn[narc]; + } + } + } + } + else + { /* Do the augmentation from node with negative deficit. */ + dx = dfct[augnod]; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { if (dx > x[arc]) dx = x[arc]; + ib = endn[arc]; + } + else + { if (dx > u[-arc]) dx = u[-arc]; + ib = startn[-arc]; + } + } + if (dx > -dfct[node]) dx = -dfct[node]; + if (dx > 0) + { /* Update the flow and deficits. */ + if (nxtqueue[augnod] == 0) + { nxtqueue[prevnode] = augnod; + nxtqueue[augnod] = node; + prevnode = augnod; + } + dfct[augnod] -= dx; + dfct[node] += dx; + ib = augnod; + while (ib != node) + { arc = prdcsr[ib]; + if (arc > 0) + { x[arc] -= dx; + u[arc] += dx; + ib = endn[arc]; + } + else + { narc = -arc; + x[narc] += dx; + u[narc] -= dx; + ib = startn[narc]; + } + } + } + } + if (dfct[node] == 0) + goto L100; + if (dfct[augnod] != 0) + svitch = false; + } + /* If node still has nonzero deficit and all newly labeled nodes + * have same sign for their deficit as node, we can continue + * labeling. In this case, continue labeling only when flow + * augmentation is done relatively infrequently. */ + if (svitch && (iter > 8 * num_augm)) + goto L4120; + /* Return to do another relaxation iteration. */ + goto L100; +# undef nmultinode +# undef iter +# undef num_augm +# undef num_ascnt +# undef nsp +} + +/*********************************************************************** +* NAME +* +* relax4_inidat - construct linked lists for network topology +* +* PURPOSE +* +* This routine constructs two linked lists for the network topology: +* one list (given by fou, nxtou) for the outgoing arcs of nodes and +* one list (given by fin, nxtin) for the incoming arcs of nodes. These +* two lists are required by RELAX4. +* +* INPUT PARAMETERS +* +* n = number of nodes +* na = number of arcs +* startn[j] = starting node for arc j, j = 1,...,na +* endn[j] = ending node for arc j, j = 1,...,na +* +* OUTPUT PARAMETERS +* +* fou[i] = first arc out of node i, i = 1,...,n +* nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na +* fin[i] = first arc into node i, i = 1,...,n +* nxtin[j] = next arc into the ending node of arc j, j = 1,...,na +* +* WORKING PARAMETERS +* +* tempin[1+n], tempou[1+n] */ + +void relax4_inidat(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int *startn = csa->startn; + int *endn = csa->endn; + /* output parameters */ + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* working parameters */ + int *tempin = csa->label; + int *tempou = csa->prdcsr; + /* local variables */ + int i, i1, i2; + for (i = 1; i <= n; i++) + { fin[i] = fou[i] = 0; + tempin[i] = tempou[i] = 0; + } + for (i = 1; i <= na; i++) + { nxtin[i] = nxtou[i] = 0; + i1 = startn[i]; + i2 = endn[i]; + if (fou[i1] != 0) + nxtou[tempou[i1]] = i; + else + fou[i1] = i; + tempou[i1] = i; + if (fin[i2] != 0) + nxtin[tempin[i2]] = i; + else + fin[i2] = i; + tempin[i2] = i; + } + return; +} + +/*********************************************************************** +* NAME +* +* ascnt1 - multi-node price adjustment for positive deficit case +* +* PURPOSE +* +* This subroutine performs the multi-node price adjustment step for +* the case where the scanned nodes have positive deficit. It first +* checks if decreasing the price of the scanned nodes increases the +* dual cost. If yes, then it decreases the price of all scanned nodes. +* There are two possibilities for price decrease: if switch = true, +* then the set of scanned nodes corresponds to an elementary direction +* of maximal rate of ascent, in which case the price of all scanned +* nodes are decreased until the next breakpoint in the dual cost is +* encountered. At this point, some arc becomes balanced and more +* node(s) are added to the labeled set and the subroutine is exited. +* If switch = false, then the price of all scanned nodes are decreased +* until the rate of ascent becomes negative (this corresponds to the +* price adjustment step in which both the line search and the +* degenerate ascent iteration are implemented). +* +* INPUT PARAMETERS +* +* dm = total deficit of scanned nodes +* switch = true if labeling is to continue after price change +* nscan = number of scanned nodes +* curnode = most recently scanned node +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity (see note 3) +* startn[i] = starting node for the i-th arc, i = 1,...,na +* endn[i] = ending node for the i-th arc, i = 1,...,na +* fou[i] = first arc leaving i-th node, i = 1,...,n +* nxtou[i] = next arc leaving the starting node of j-th arc, +* i = 1,...,na +* fin[i] = first arc entering i-th node, i = 1,...,n +* nxtin[i] = next arc entering the ending node of j-th arc, +* i = 1,...,na +* +* UPDATED PARAMETERS +* +* delx = a lower estimate of the total flow on balanced arcs in +* the scanned-nodes cut +* nlabel = number of labeled nodes +* feasbl = false if problem is found to be infeasible +* prevnode = the node before curnode in queue +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = residual capacity of arc j, j = 1,...,na +* x[j] = flow on arc j, j = 1,...,na +* dfct[i] = deficit at node i, i = 1,...,n +* label[k] = k-th node labeled, k = 1,...,nlabel +* prdcsr[i] = predecessor of node i in tree of labeled nodes (0 if i +* is unlabeled), i = 1,...,n +* tfstou[i] = first balanced arc out of node i, i = 1,...,n +* tnxtou[j] = next balanced arc out of the starting node of arc j, +* j = 1,...,na +* tfstin[i] = first balanced arc into node i, i = 1,...,n +* tnxtin[j] = next balanced arc into the ending node of arc j, +* j = 1,...,na +* nxtqueue[i] = node following node i in the fifo queue (0 if node is +* not in the queue), i = 1,...,n +* scan[i] = true if node i is scanned, i = 1,...,n +* mark[i] = true if node i is labeled, i = 1,...,n +* +* WORKING PARAMETERS +* +* save[1+na] */ + +static void ascnt1(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode) +{ /* input parameters */ + int n = csa->n; + /* int na = csa->na; */ + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define delx (*delx) +# define nlabel (*nlabel) +# define feasbl (*feasbl) +# define svitch (*svitch) +# define prevnode (*prevnode) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *save = csa->save; + /* local variables */ + int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, + t2, t3; + /* Store the arcs between the set of scanned nodes and its + * complement in save and compute delprc, the stepsize to the next + * breakpoint in the dual cost in the direction of decreasing + * prices of the scanned nodes. + * [The arcs are stored into save by looking at the arcs incident + * to either the set of scanned nodes or its complement, depending + * on whether nscan > n/2 or not. This improves the efficiency of + * storing.] */ + delprc = large; + dlx = 0; + nsave = 0; + if (nscan <= n / 2) + { for (i = 1; i <= nscan; i++) + { node = label[i]; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { /* arc points from scanned node to an unscanned node. */ + node2 = endn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { /* arc points from unscanned node to scanned node. */ + node2 = startn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + else + { for (node = 1; node <= n; node++) + { if (scan[node]) + continue; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + /* Check if the set of scanned nodes truly corresponds to a dual + * ascent direction. [Here delx + dlx is the exact sum of the flow + * on arcs from the scanned set to the unscanned set plus the + * (capacity - flow) on arcs from the unscanned set to the scanned + * set.] If this were not the case, set switch to true and exit + * subroutine. */ + if ((!svitch) && (delx + dlx >= dm)) + { svitch = true; + return; + } + delx += dlx; +L4: /* Check that the problem is feasible. */ + if (delprc == large) + { /* We can increase the dual cost without bound, so the primal + * problem is infeasible. */ + feasbl = false; + return; + } + /* Decrease the prices of the scanned nodes, add more nodes to + * the labeled set and check if a newly labeled node has negative + * deficit. */ + if (svitch) + { for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rc[arc] += delprc; + if (rc[arc] == 0) + { node2 = endn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[node2]; + tfstin[node2] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + else + { arc = -arc; + rc[arc] -= delprc; + if (rc[arc] == 0) + { node2 = startn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[node2]; + tfstou[node2] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = -arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + } + return; + } + else + { /* Decrease the prices of the scanned nodes by delprc. Adjust + * flow to maintain complementary slackness with the prices. */ + nb = 0; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { t1 = rc[arc]; + if (t1 == 0) + { t2 = x[arc]; + t3 = startn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + u[arc] += t2; + x[arc] = 0; + } + rc[arc] = t1 + delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += x[arc]; + nb++; + prdcsr[nb] = arc; + } + } + else + { arc = -arc; + t1 = rc[arc]; + if (t1 == 0) + { t2 = u[arc]; + t3 = startn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + x[arc] += t2; + u[arc] = 0; + } + rc[arc] = t1 - delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += u[arc]; + nb++; + prdcsr[nb] = arc; + } + } + } + } + if (delx <= dm) + { /* The set of scanned nodes still corresponds to a dual + * (possibly degenerate) ascent direction. Compute the stepsize + * delprc to the next breakpoint in the dual cost. */ + delprc = large; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + else + { arc = -arc; + rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + if ((delprc != large) || (delx < dm)) + goto L4; + } + /* Add new balanced arcs to the superset of balanced arcs. */ + for (i = 1; i <= nb; i++) + { arc = prdcsr[i]; + if (tnxtin[arc] == -1) + { j = endn[arc]; + tnxtin[arc] = tfstin[j]; + tfstin[j] = arc; + } + if (tnxtou[arc] == -1) + { j = startn[arc]; + tnxtou[arc] = tfstou[j]; + tfstou[j] = arc; + } + } + return; +# undef delx +# undef nlabel +# undef feasbl +# undef svitch +# undef prevnode +} + +/*********************************************************************** +* NAME +* +* ascnt2 - multi-node price adjustment for negative deficit case +* +* PURPOSE +* +* This routine is analogous to ascnt1 but for the case where the +* scanned nodes have negative deficit. */ + +static void ascnt2(struct relax4_csa *csa, int dm, int *delx, + int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, + int *prevnode) +{ /* input parameters */ + int n = csa->n; + /* int na = csa->na; */ + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define delx (*delx) +# define nlabel (*nlabel) +# define feasbl (*feasbl) +# define svitch (*svitch) +# define prevnode (*prevnode) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + int *label = csa->label; + int *prdcsr = csa->prdcsr; + int *tfstou = csa->tfstou; + int *tnxtou = csa->tnxtou; + int *tfstin = csa->tfstin; + int *tnxtin = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + char *scan = csa->scan; + char *mark = csa->mark; + int *save = csa->save; + /* local variables */ + int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, + t2, t3; + /* Store the arcs between the set of scanned nodes and its + * complement in save and compute delprc, the stepsize to the next + * breakpoint in the dual cost in the direction of increasing + * prices of the scanned nodes. */ + delprc = large; + dlx = 0; + nsave = 0; + if (nscan <= n / 2) + { for (i = 1; i <= nscan; i++) + { node = label[i]; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (!scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node2] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + else + { for (node = 1; node <= n; node++) + { if (scan[node]) + continue; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { node2 = endn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != arc)) + dlx += x[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + } + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { node2 = startn[arc]; + if (scan[node2]) + { nsave++; + save[nsave] = -arc; + rdcost = rc[arc]; + if ((rdcost == 0) && (prdcsr[node] != -arc)) + dlx += u[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + } + } + if ((!svitch) && (delx + dlx >= -dm)) + { svitch = true; + return; + } + delx += dlx; + /* Check that the problem is feasible. */ +L4: if (delprc == large) + { feasbl = false; + return; + } + /* Increase the prices of the scanned nodes, add more nodes to + * the labeled set and check if a newly labeled node has positive + * deficit. */ + if (svitch) + { for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rc[arc] += delprc; + if (rc[arc] == 0) + { node2 = startn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[node2]; + tfstou[node2] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[endn[arc]]; + tfstin[endn[arc]] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + else + { arc = -arc; + rc[arc] -= delprc; + if (rc[arc] == 0) + { node2 = endn[arc]; + if (tnxtou[arc] < 0) + { tnxtou[arc] = tfstou[startn[arc]]; + tfstou[startn[arc]] = arc; + } + if (tnxtin[arc] < 0) + { tnxtin[arc] = tfstin[node2]; + tfstin[node2] = arc; + } + if (!mark[node2]) + { prdcsr[node2] = -arc; + nlabel++; + label[nlabel] = node2; + mark[node2] = true; + } + } + } + } + return; + } + else + { nb = 0; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { t1 = rc[arc]; + if (t1 == 0) + { t2 = x[arc]; + t3 = startn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + u[arc] += t2; + x[arc] = 0; + } + rc[arc] = t1 + delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += x[arc]; + nb++; + prdcsr[nb] = arc; + } + } + else + { arc = -arc; + t1 = rc[arc]; + if (t1 == 0) + { t2 = u[arc]; + t3 = startn[arc]; + dfct[t3] += t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + t3 = endn[arc]; + dfct[t3] -= t2; + if (nxtqueue[t3] == 0) + { nxtqueue[prevnode] = t3; + nxtqueue[t3] = curnode; + prevnode = t3; + } + x[arc] += t2; + u[arc] = 0; + } + rc[arc] = t1 - delprc; +#if 0 /* by mao; 26/IV-2013 */ + if (rc[arc] == 0) +#else + if (rc[arc] == 0 && nb < n) +#endif + { delx += u[arc]; + nb++; + prdcsr[nb] = arc; + } + } + } + } + if (delx <= -dm) + { delprc = large; + for (i = 1; i <= nsave; i++) + { arc = save[i]; + if (arc > 0) + { rdcost = rc[arc]; + if ((rdcost < 0) && (rdcost > -delprc)) + delprc = -rdcost; + } + else + { arc = -arc; + rdcost = rc[arc]; + if ((rdcost > 0) && (rdcost < delprc)) + delprc = rdcost; + } + } + if ((delprc != large) || (delx < -dm)) + goto L4; + } + /* Add new balanced arcs to the superset of balanced arcs. */ + for (i = 1; i <= nb; i++) + { arc = prdcsr[i]; + if (tnxtin[arc] == -1) + { j = endn[arc]; + tnxtin[arc] = tfstin[j]; + tfstin[j] = arc; + } + if (tnxtou[arc] == -1) + { j = startn[arc]; + tnxtou[arc] = tfstou[j]; + tfstou[j] = arc; + } + } + return; +# undef delx +# undef nlabel +# undef feasbl +# undef svitch +# undef prevnode +} + +/*********************************************************************** +* NAME +* +* auction - compute good initial flow and prices +* +* PURPOSE +* +* This subroutine uses a version of the auction algorithm for min +* cost network flow to compute a good initial flow and prices for the +* problem. +* +* INPUT PARAMETERS +* +* n = number of nodes +* na = number of arcs +* large = a very large integer to represent infinity (see note 3) +* startn[i] = starting node for the i-th arc, i = 1,...,na +* endn[i] = ending node for the i-th arc, i = 1,...,na +* fou[i] = first arc leaving i-th node, i = 1,...,n +* nxtou[i] = next arc leaving the starting node of j-th arc, +* i = 1,...,na +* fin[i] = first arc entering i-th node, i = 1,...,n +* nxtin[i] = next arc entering the ending node of j-th arc, +* i = 1,...,na +* +* UPDATED PARAMETERS +* +* rc[j] = reduced cost of arc j, j = 1,...,na +* u[j] = residual capacity of arc j, j = 1,...,na +* x[j] = flow on arc j, j = 1,...,na +* dfct[i] = deficit at node i, i = 1,...,n +* +* OUTPUT PARAMETERS +* +* nsp = number of auction/shortest path iterations +* +* WORKING PARAMETERS +* +* p[1+n], prdcsr[1+n], save[1+na], fpushf[1+n], nxtpushf[1+na], +* fpushb[1+n], nxtpushb[1+na], nxtqueue[1+n], extend_arc[1+n], +* sb_level[1+n], sb_arc[1+n], path_id[1+n] +* +* RETURNS +* +* 0 = normal return +* 1 = problem is found to be infeasible */ + +static int auction(struct relax4_csa *csa) +{ /* input parameters */ + int n = csa->n; + int na = csa->na; + int large = csa->large; + int *startn = csa->startn; + int *endn = csa->endn; + int *fou = csa->fou; + int *nxtou = csa->nxtou; + int *fin = csa->fin; + int *nxtin = csa->nxtin; + /* updated parameters */ +# define crash (csa->crash) + int *rc = csa->rc; + int *u = csa->u; + int *x = csa->x; + int *dfct = csa->dfct; + /* output parameters */ +# define nsp (csa->nsp) + /* working parameters */ + int *p = csa->label; + int *prdcsr = csa->prdcsr; + int *save = csa->save; + int *fpushf = csa->tfstou; + int *nxtpushf = csa->tnxtou; + int *fpushb = csa->tfstin; + int *nxtpushb = csa->tnxtin; + int *nxtqueue = csa->nxtqueue; + int *extend_arc = csa->extend_arc; + int *sb_level = csa->sb_level; + int *sb_arc = csa->sb_arc; + char *path_id = csa->mark; + /* local variables */ + int arc, bstlevel, end, eps, extarc, factor, flow, i, incr, + last, lastqueue, maxcost, mincost, nas, naug, new_level, node, + nolist, num_passes, nxtnode, pass, pend, pr_term, prd, + prevarc, prevlevel, prevnode, pstart, pterm, rdcost, red_cost, + resid, root, secarc, seclevel, start, term, thresh_dfct; + /* start initialization using auction */ + naug = 0; + pass = 0; + thresh_dfct = 0; + /* factor determines by how much epsilon is reduced at each + * minimization */ + factor = 3; + /* num_passes determines how many auction scaling phases are + * performed */ + num_passes = 1; + /* set arc flows to satisfy cs and calculate maxcost and + * mincost */ + maxcost = -large; + mincost = large; + for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + rdcost = rc[arc]; + if (maxcost < rdcost) + maxcost = rdcost; + if (mincost > rdcost) + mincost = rdcost; + if (rdcost < 0) + { dfct[start] += u[arc]; + dfct[end] -= u[arc]; + x[arc] = u[arc]; + u[arc] = 0; + } + else + x[arc] = 0; + } + /* set initial epsilon */ + if ((maxcost - mincost) >= 8) + eps = (maxcost - mincost) / 8; + else + eps = 1; + /* set initial prices to zero */ + for (node = 1; node <= n; node++) + p[node] = 0; + /* Initialization using auction/shortest paths. */ +L100: /* Start of the first scaling phase. */ + pass++; + if ((pass == num_passes) || (eps == 1)) + crash = 0; + nolist = 0; + /* construct list of positive surplus nodes and queue of negative + * surplus nodes */ + for (node = 1; node <= n; node++) + { prdcsr[node] = 0; + path_id[node] = false; + extend_arc[node] = 0; + sb_level[node] = -large; + nxtqueue[node] = node + 1; + if (dfct[node] > 0) + { nolist++; + save[nolist] = node; + } + } + nxtqueue[n] = 1; + root = 1; + prevnode = lastqueue = n; + /* initialization with down iterations for negative surplus + * nodes */ + for (i = 1; i <= nolist; i++) + { node = save[i]; + nsp++; + /* build the list of arcs w/ room for pushing flow and find + * proper price for down iteration */ + bstlevel = -large; + fpushf[node] = 0; + for (arc = fou[node]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > 0) + { if (fpushf[node] == 0) + { fpushf[node] = arc; + nxtpushf[arc] = 0; + last = arc; + } + else + { nxtpushf[last] = arc; + nxtpushf[arc] = 0; + last = arc; + } + } + if (x[arc] > 0) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level > bstlevel) + { bstlevel = new_level; + extarc = arc; + } + } + } + fpushb[node] = 0; + for (arc = fin[node]; arc > 0; arc = nxtin[arc]) + { if (x[arc] > 0) + { if (fpushb[node] == 0) + { fpushb[node] = arc; + nxtpushb[arc] = 0; + last = arc; + } + else + { nxtpushb[last] = arc; + nxtpushb[arc] = 0; + last = arc; + } + } + if (u[arc] > 0) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level > bstlevel) + { bstlevel = new_level; + extarc = -arc; + } + } + } + extend_arc[node] = extarc; + p[node] = bstlevel - eps; + } +L200: /* Start the augmentation cycles of the new scaling phase. */ + if (dfct[root] >= thresh_dfct) + goto L3000; + term = root; + path_id[root] = true; +L500: /* Main forward algorithm with root as origin. */ + /* start of a new forward iteration */ + pterm = p[term]; + extarc = extend_arc[term]; + if (extarc == 0) + { /* build the list of arcs w/ room for pushing flow */ + fpushf[term] = 0; + for (arc = fou[term]; arc > 0; arc = nxtou[arc]) + { if (u[arc] > 0) + { if (fpushf[term] == 0) + { fpushf[term] = arc; + nxtpushf[arc] = 0; + last = arc; + } + else + { nxtpushf[last] = arc; + nxtpushf[arc] = 0; + last = arc; + } + } + } + fpushb[term] = 0; + for (arc = fin[term]; arc > 0; arc = nxtin[arc]) + { if (x[arc] > 0) + { if (fpushb[term] == 0) + { fpushb[term] = arc; + nxtpushb[arc] = 0; + last = arc; + } + else + { nxtpushb[last] = arc; + nxtpushb[arc] = 0; + last = arc; + } + } + } + goto L600; + } + /* speculative path extension attempt */ + /* note: arc > 0 means that arc is oriented from the root to the + * destinations + * arc < 0 means that arc is oriented from the destinations to the + * root + * extarc = 0 or prdarc = 0, means the extension arc or the + * predecessor arc, respectively, has not been established */ + if (extarc > 0) + { if (u[extarc] == 0) + { seclevel = sb_level[term]; + goto L580; + } + end = endn[extarc]; + bstlevel = p[end] + rc[extarc]; + if (pterm >= bstlevel) + { if (path_id[end]) + goto L1200; + term = end; + prdcsr[term] = extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + } + else + { extarc = -extarc; + if (x[extarc] == 0) + { seclevel = sb_level[term]; + goto L580; + } + start = startn[extarc]; + bstlevel = p[start] - rc[extarc]; + if (pterm >= bstlevel) + { if (path_id[start]) + goto L1200; + term = start; + prdcsr[term] = -extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + } +L550: /* second best logic test applied to save a full node scan + * if old best level continues to be best go for another + * contraction */ + seclevel = sb_level[term]; + if (bstlevel <= seclevel) + goto L800; +L580: /* if second best can be used do either a contraction or start + * over with a speculative extension */ + if (seclevel > -large) + { extarc = sb_arc[term]; + if (extarc > 0) + { if (u[extarc] == 0) + goto L600; + bstlevel = p[endn[extarc]] + rc[extarc]; + } + else + { if (x[-extarc] == 0) + goto L600; + bstlevel = p[startn[-extarc]] - rc[-extarc]; + } + if (bstlevel == seclevel) + { sb_level[term] = -large; + extend_arc[term] = extarc; + goto L800; + } + } +L600: /* extension/contraction attempt was unsuccessful, so scan + * terminal node */ + nsp++; + bstlevel = seclevel = large; + for (arc = fpushf[term]; arc > 0; arc = nxtpushf[arc]) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = arc; + } + else + { seclevel = new_level; + secarc = arc; + } + } + } + for (arc = fpushb[term]; arc > 0; arc = nxtpushb[arc]) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = -arc; + } + else + { seclevel = new_level; + secarc = -arc; + } + } + } + sb_level[term] = seclevel; + sb_arc[term] = secarc; + extend_arc[term] = extarc; +L800: /* End of node scan. */ + /* if the terminal node is the root, adjust its price and change + * root */ + if (term == root) + { p[term] = bstlevel + eps; + if (p[term] >= large) + { /* no path to the destination */ + /* problem is found to be infeasible */ + return 1; + } + path_id[root] = false; + prevnode = root; + root = nxtqueue[root]; + goto L200; + } + /* check whether extension or contraction */ + prd = prdcsr[term]; + if (prd > 0) + { pr_term = startn[prd]; + prevlevel = p[pr_term] - rc[prd]; + } + else + { pr_term = endn[-prd]; + prevlevel = p[pr_term] + rc[-prd]; + } + if (prevlevel > bstlevel) + { /* path extension */ + if (prevlevel >= bstlevel + eps) + p[term] = bstlevel + eps; + else + p[term] = prevlevel; + if (extarc > 0) + { end = endn[extarc]; + if (path_id[end]) + goto L1200; + term = end; + } + else + { start = startn[-extarc]; + if (path_id[start]) + goto L1200; + term = start; + } + prdcsr[term] = extarc; + path_id[term] = true; + /* if negative surplus node is found, do an augmentation */ + if (dfct[term] > 0) + goto L2000; + /* return for another iteration */ + goto L500; + } + else + { /* path contraction */ + p[term] = bstlevel + eps; + path_id[term] = false; + term = pr_term; + if (pr_term != root) + { if (bstlevel <= pterm + eps) + goto L2000; + } + pterm = p[term]; + extarc = prd; + if (prd > 0) + bstlevel += eps + rc[prd]; + else + bstlevel += eps - rc[-prd]; + /* do a second best test and if that fails, do a full node + * scan */ + goto L550; + } +L1200:/* A cycle is about to form; do a retreat sequence. */ + node = term; +L1600:if (node != root) + { path_id[node] = false; + prd = prdcsr[node]; + if (prd > 0) + { pr_term = startn[prd]; + if (p[pr_term] == p[node] + rc[prd] + eps) + { node = pr_term; + goto L1600; + } + } + else + { pr_term = endn[-prd]; + if (p[pr_term] == p[node] - rc[-prd] + eps) + { node = pr_term; + goto L1600; + } + } + /* do a full scan and price rise at pr_term */ + nsp++; + bstlevel = seclevel = large; + for (arc = fpushf[pr_term]; arc > 0; arc = nxtpushf[arc]) + { new_level = p[endn[arc]] + rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = arc; + } + else + { seclevel = new_level; + secarc = arc; + } + } + } + for (arc = fpushb[pr_term]; arc > 0; arc = nxtpushb[arc]) + { new_level = p[startn[arc]] - rc[arc]; + if (new_level < seclevel) + { if (new_level < bstlevel) + { seclevel = bstlevel; + bstlevel = new_level; + secarc = extarc; + extarc = -arc; + } + else + { seclevel = new_level; + secarc = -arc; + } + } + } + sb_level[pr_term] = seclevel; + sb_arc[pr_term] = secarc; + extend_arc[pr_term] = extarc; + p[pr_term] = bstlevel + eps; + if (pr_term == root) + { prevnode = root; + path_id[root] = false; + root = nxtqueue[root]; + goto L200; + } + path_id[pr_term] = false; + prd = prdcsr[pr_term]; + if (prd > 0) + term = startn[prd]; + else + term = endn[-prd]; + if (term == root) + { prevnode = root; + path_id[root] = false; + root = nxtqueue[root]; + goto L200; + } + else + goto L2000; + } +L2000:/* End of auction/shortest path routine. */ + /* do augmentation from root and correct the push lists */ + incr = -dfct[root]; + for (node = root;;) + { extarc = extend_arc[node]; + path_id[node] = false; + if (extarc > 0) + { node = endn[extarc]; + if (incr > u[extarc]) + incr = u[extarc]; + } + else + { node = startn[-extarc]; + if (incr > x[-extarc]) + incr = x[-extarc]; + } + if (node == term) + break; + } + path_id[term] = false; + if (dfct[term] > 0) + { if (incr > dfct[term]) + incr = dfct[term]; + } + for (node = root;;) + { extarc = extend_arc[node]; + if (extarc > 0) + { end = endn[extarc]; + /* add arc to the reduced graph */ + if (x[extarc] == 0) + { nxtpushb[extarc] = fpushb[end]; + fpushb[end] = extarc; + new_level = p[node] - rc[extarc]; + if (sb_level[end] > new_level) + { sb_level[end] = new_level; + sb_arc[end] = -extarc; + } + } + x[extarc] += incr; + u[extarc] -= incr; + /* remove arc from the reduced graph */ + if (u[extarc] == 0) + { nas++; + arc = fpushf[node]; + if (arc == extarc) + fpushf[node] = nxtpushf[arc]; + else + { prevarc = arc; + arc = nxtpushf[arc]; + while (arc > 0) + { if (arc == extarc) + { nxtpushf[prevarc] = nxtpushf[arc]; + break; + } + prevarc = arc; + arc = nxtpushf[arc]; + } + } + } + node = end; + } + else + { extarc = -extarc; + start = startn[extarc]; + /* add arc to the reduced graph */ + if (u[extarc] == 0) + { nxtpushf[extarc] = fpushf[start]; + fpushf[start] = extarc; + new_level = p[node] + rc[extarc]; + if (sb_level[start] > new_level) + { sb_level[start] = new_level; + sb_arc[start] = extarc; + } + } + u[extarc] += incr; + x[extarc] -= incr; + /* remove arc from the reduced graph */ + if (x[extarc] == 0) + { nas++; + arc = fpushb[node]; + if (arc == extarc) + fpushb[node] = nxtpushb[arc]; + else + { prevarc = arc; + arc = nxtpushb[arc]; + while (arc > 0) + { if (arc == extarc) + { nxtpushb[prevarc] = nxtpushb[arc]; + break; + } + prevarc = arc; + arc = nxtpushb[arc]; + } + } + } + node = start; + } + if (node == term) + break; + } + dfct[term] -= incr; + dfct[root] += incr; + /* insert term in the queue if it has a large enough surplus */ + if (dfct[term] < thresh_dfct) + { if (nxtqueue[term] == 0) + { nxtnode = nxtqueue[root]; + if ((p[term] >= p[nxtnode]) && (root != nxtnode)) + { nxtqueue[root] = term; + nxtqueue[term] = nxtnode; + } + else + { nxtqueue[prevnode] = term; + nxtqueue[term] = root; + prevnode = term; + } + } + } + /* if root has a large enough surplus, keep it in the queue and + * return for another iteration */ + if (dfct[root] < thresh_dfct) + { prevnode = root; + root = nxtqueue[root]; + goto L200; + } +L3000:/* end of augmentation cycle */ + /* Check for termination of scaling phase. If scaling phase is not + * finished, advance the queue and return to take another node. */ + nxtnode = nxtqueue[root]; + if (root != nxtnode) + { nxtqueue[root] = 0; + nxtqueue[prevnode] = nxtnode; + root = nxtnode; + goto L200; + } + /* End of subproblem (scaling phase). */ + /* Reduce epsilon. */ + eps /= factor; + if (eps < 1) eps = 1; + thresh_dfct /= factor; + if (eps == 1) thresh_dfct = 0; + /* if another auction scaling phase remains, reset the flows & + * the push lists; else reset arc flows to satisfy cs and compute + * reduced costs */ + if (crash == 1) + { for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + pstart = p[start]; + pend = p[end]; + if (pstart > pend + eps + rc[arc]) + { resid = u[arc]; + if (resid > 0) + { dfct[start] += resid; + dfct[end] -= resid; + x[arc] += resid; + u[arc] = 0; + } + } + else if (pstart < pend - eps + rc[arc]) + { flow = x[arc]; + if (flow > 0) + { dfct[start] -= flow; + dfct[end] += flow; + x[arc] = 0; + u[arc] += flow; + } + } + } + /* return for another phase */ + goto L100; + } + else + { crash = 1; + for (arc = 1; arc <= na; arc++) + { start = startn[arc]; + end = endn[arc]; + red_cost = rc[arc] + p[end] - p[start]; + if (red_cost < 0) + { resid = u[arc]; + if (resid > 0) + { dfct[start] += resid; + dfct[end] -= resid; + x[arc] += resid; + u[arc] = 0; + } + } + else if (red_cost > 0) + { flow = x[arc]; + if (flow > 0) + { dfct[start] -= flow; + dfct[end] += flow; + x[arc] = 0; + u[arc] += flow; + } + } + rc[arc] = red_cost; + } + } + return 0; +# undef crash +# undef nsp +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.h new file mode 100644 index 000000000..f48b8508c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/relax4.h @@ -0,0 +1,102 @@ +/* relax4.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef RELAX4_H +#define RELAX4_H + +struct relax4_csa +{ /* common storage area */ + /* input parameters --------------------------------------------*/ + int n; + /* number of nodes */ + int na; + /* number of arcs */ + int large; + /* very large int to represent infinity */ + int repeat; + /* true if initialization is to be skipped (false otherwise) */ + int crash; + /* 0 if default initialization is used + * 1 if auction initialization is used */ + int *startn; /* int startn[1+na]; */ + /* startn[j] = starting node for arc j, j = 1,...,na */ + int *endn; /* int endn[1+na] */ + /* endn[j] = ending node for arc j, j = 1,...,na */ + int *fou; /* int fou[1+n]; */ + /* fou[i] = first arc out of node i, i = 1,...,n */ + int *nxtou; /* int nxtou[1+na]; */ + /* nxtou[j] = next arc out of the starting node of arc j, + * j = 1,...,na */ + int *fin; /* int fin[1+n]; */ + /* fin[i] = first arc into node i, i = 1,...,n */ + int *nxtin; /* int nxtin[1+na]; */ + /* nxtin[j] = next arc into the ending node of arc j, + * j = 1,...,na */ + /* updated parameters ------------------------------------------*/ + int *rc; /* int rc[1+na]; */ + /* rc[j] = reduced cost of arc j, j = 1,...,na */ + int *u; /* int u[1+na]; */ + /* u[j] = capacity of arc j on input + * and (capacity of arc j) - x(j) on output, j = 1,...,na */ + int *dfct; /* int dfct[1+n]; */ + /* dfct[i] = demand at node i on input + * and zero on output, i = 1,...,n */ + /* output parameters -------------------------------------------*/ + int *x; /* int x[1+na]; */ + /* x[j] = flow on arc j, j = 1,...,na */ + int nmultinode; + /* number of multinode relaxation iterations in RELAX4 */ + int iter; + /* number of relaxation iterations in RELAX4 */ + int num_augm; + /* number of flow augmentation steps in RELAX4 */ + int num_ascnt; + /* number of multinode ascent steps in RELAX4 */ + int nsp; + /* number of auction/shortest path iterations */ + /* working parameters ------------------------------------------*/ + int *label; /* int label, tempin, p[1+n]; */ + int *prdcsr; /* int prdcsr, tempou, price[1+n]; */ + int *save; /* int save[1+na]; */ + int *tfstou; /* int tfstou, fpushf[1+n]; */ + int *tnxtou; /* int tnxtou, nxtpushf[1+na]; */ + int *tfstin; /* int tfstin, fpushb[1+n]; */ + int *tnxtin; /* int tnxtin, nxtpushb[1+na]; */ + int *nxtqueue; /* int nxtqueue[1+n]; */ + char *scan; /* bool scan[1+n]; */ + char *mark; /* bool mark, path_id[1+n]; */ + /* working parameters used by routine auction only -------------*/ + int *extend_arc; /* int extend_arc[1+n]; */ + int *sb_level; /* int sb_level[1+n]; */ + int *sb_arc; /* int sb_arc[1+n]; */ +}; + +#define relax4 _glp_relax4 +int relax4(struct relax4_csa *csa); + +#define relax4_inidat _glp_relax4_inidat +void relax4_inidat(struct relax4_csa *csa); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.c new file mode 100644 index 000000000..e0acb53a2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.c @@ -0,0 +1,227 @@ +/* rng.c (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* This code is a modified version of the module GB_FLIP, a portable +* pseudo-random number generator. The original version of GB_FLIP is +* a part of The Stanford GraphBase developed by Donald E. Knuth (see +* http://www-cs-staff.stanford.edu/~knuth/sgb.html). +* +* Note that all changes concern only external names, so this modified +* version produces exactly the same results as the original version. +* +* Changes were made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "rng.h" + +#if 0 +int A[56] = { -1 }; +#else +#define A (rand->A) +#endif +/* pseudo-random values */ + +#if 0 +int *fptr = A; +#else +#define fptr (rand->fptr) +#endif +/* the next A value to be exported */ + +#define mod_diff(x, y) (((x) - (y)) & 0x7FFFFFFF) +/* difference modulo 2^31 */ + +static int flip_cycle(RNG *rand) +{ /* this is an auxiliary routine to do 55 more steps of the basic + * recurrence, at high speed, and to reset fptr */ + int *ii, *jj; + for (ii = &A[1], jj = &A[32]; jj <= &A[55]; ii++, jj++) + *ii = mod_diff(*ii, *jj); + for (jj = &A[1]; ii <= &A[55]; ii++, jj++) + *ii = mod_diff(*ii, *jj); + fptr = &A[54]; + return A[55]; +} + +/*********************************************************************** +* NAME +* +* rng_create_rand - create pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* RNG *rng_create_rand(void); +* +* DESCRIPTION +* +* The routine rng_create_rand creates and initializes a pseudo-random +* number generator. +* +* RETURNS +* +* The routine returns a pointer to the generator created. */ + +RNG *rng_create_rand(void) +{ RNG *rand; + int i; + rand = talloc(1, RNG); + A[0] = -1; + for (i = 1; i <= 55; i++) A[i] = 0; + fptr = A; + rng_init_rand(rand, 1); + return rand; +} + +/*********************************************************************** +* NAME +* +* rng_init_rand - initialize pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* void rng_init_rand(RNG *rand, int seed); +* +* DESCRIPTION +* +* The routine rng_init_rand initializes the pseudo-random number +* generator. The parameter seed may be any integer number. Note that +* on creating the generator this routine is called with the parameter +* seed equal to 1. */ + +void rng_init_rand(RNG *rand, int seed) +{ int i; + int prev = seed, next = 1; + seed = prev = mod_diff(prev, 0); + A[55] = prev; + for (i = 21; i; i = (i + 21) % 55) + { A[i] = next; + next = mod_diff(prev, next); + if (seed & 1) + seed = 0x40000000 + (seed >> 1); + else + seed >>= 1; + next = mod_diff(next, seed); + prev = A[i]; + } + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + flip_cycle(rand); + return; +} + +/*********************************************************************** +* NAME +* +* rng_next_rand - obtain pseudo-random integer in the range [0, 2^31-1] +* +* SYNOPSIS +* +* #include "rng.h" +* int rng_next_rand(RNG *rand); +* +* RETURNS +* +* The routine rng_next_rand returns a next pseudo-random integer which +* is uniformly distributed between 0 and 2^31-1, inclusive. The period +* length of the generated numbers is 2^85 - 2^30. The low order bits of +* the generated numbers are just as random as the high-order bits. */ + +int rng_next_rand(RNG *rand) +{ return + *fptr >= 0 ? *fptr-- : flip_cycle(rand); +} + +/*********************************************************************** +* NAME +* +* rng_unif_rand - obtain pseudo-random integer in the range [0, m-1] +* +* SYNOPSIS +* +* #include "rng.h" +* int rng_unif_rand(RNG *rand, int m); +* +* RETURNS +* +* The routine rng_unif_rand returns a next pseudo-random integer which +* is uniformly distributed between 0 and m-1, inclusive, where m is any +* positive integer less than 2^31. */ + +#define two_to_the_31 ((unsigned int)0x80000000) + +int rng_unif_rand(RNG *rand, int m) +{ unsigned int t = two_to_the_31 - (two_to_the_31 % m); + int r; + xassert(m > 0); + do { r = rng_next_rand(rand); } while (t <= (unsigned int)r); + return r % m; +} + +/*********************************************************************** +* NAME +* +* rng_delete_rand - delete pseudo-random number generator +* +* SYNOPSIS +* +* #include "rng.h" +* void rng_delete_rand(RNG *rand); +* +* DESCRIPTION +* +* The routine rng_delete_rand frees all the memory allocated to the +* specified pseudo-random number generator. */ + +void rng_delete_rand(RNG *rand) +{ tfree(rand); + return; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +/* To be sure that this modified version produces the same results as + * the original version, run this validation program. */ + +int main(void) +{ RNG *rand; + int j; + rand = rng_create_rand(); + rng_init_rand(rand, -314159); + if (rng_next_rand(rand) != 119318998) + { fprintf(stderr, "Failure on the first try!\n"); + return -1; + } + for (j = 1; j <= 133; j++) rng_next_rand(rand); + if (rng_unif_rand(rand, 0x55555555) != 748103812) + { fprintf(stderr, "Failure on the second try!\n"); + return -2; + } + fprintf(stderr, "OK, the random-number generator routines seem to" + " work!\n"); + rng_delete_rand(rand); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.h new file mode 100644 index 000000000..49725e057 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng.h @@ -0,0 +1,67 @@ +/* rng.h (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef RNG_H +#define RNG_H + +typedef struct RNG RNG; + +struct RNG +{ /* Knuth's portable pseudo-random number generator */ + int A[56]; + /* pseudo-random values */ + int *fptr; + /* the next A value to be exported */ +}; + +#define rng_create_rand _glp_rng_create_rand +RNG *rng_create_rand(void); +/* create pseudo-random number generator */ + +#define rng_init_rand _glp_rng_init_rand +void rng_init_rand(RNG *rand, int seed); +/* initialize pseudo-random number generator */ + +#define rng_next_rand _glp_rng_next_rand +int rng_next_rand(RNG *rand); +/* obtain pseudo-random integer in the range [0, 2^31-1] */ + +#define rng_unif_rand _glp_rng_unif_rand +int rng_unif_rand(RNG *rand, int m); +/* obtain pseudo-random integer in the range [0, m-1] */ + +#define rng_delete_rand _glp_rng_delete_rand +void rng_delete_rand(RNG *rand); +/* delete pseudo-random number generator */ + +#define rng_unif_01 _glp_rng_unif_01 +double rng_unif_01(RNG *rand); +/* obtain pseudo-random number in the range [0, 1] */ + +#define rng_uniform _glp_rng_uniform +double rng_uniform(RNG *rand, double a, double b); +/* obtain pseudo-random number in the range [a, b] */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng1.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng1.c new file mode 100644 index 000000000..b89f676f2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/rng1.c @@ -0,0 +1,73 @@ +/* rng1.c (pseudo-random number generator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "rng.h" + +/*********************************************************************** +* NAME +* +* rng_unif_01 - obtain pseudo-random number in the range [0, 1] +* +* SYNOPSIS +* +* #include "rng.h" +* double rng_unif_01(RNG *rand); +* +* RETURNS +* +* The routine rng_unif_01 returns a next pseudo-random number which is +* uniformly distributed in the range [0, 1]. */ + +double rng_unif_01(RNG *rand) +{ double x; + x = (double)rng_next_rand(rand) / 2147483647.0; + xassert(0.0 <= x && x <= 1.0); + return x; +} + +/*********************************************************************** +* NAME +* +* rng_uniform - obtain pseudo-random number in the range [a, b] +* +* SYNOPSIS +* +* #include "rng.h" +* double rng_uniform(RNG *rand, double a, double b); +* +* RETURNS +* +* The routine rng_uniform returns a next pseudo-random number which is +* uniformly distributed in the range [a, b]. */ + +double rng_uniform(RNG *rand, double a, double b) +{ double x; + xassert(a < b); + x = rng_unif_01(rand); + x = a * (1.0 - x) + b * x; + xassert(a <= x && x <= b); + return x; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/round2n.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/round2n.c new file mode 100644 index 000000000..8a94c6162 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/round2n.c @@ -0,0 +1,64 @@ +/* round2n.c (round floating-point number to nearest power of two) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* round2n - round floating-point number to nearest power of two +* +* SYNOPSIS +* +* #include "misc.h" +* double round2n(double x); +* +* RETURNS +* +* Given a positive floating-point value x the routine round2n returns +* 2^n such that |x - 2^n| is minimal. +* +* EXAMPLES +* +* round2n(10.1) = 2^3 = 8 +* round2n(15.3) = 2^4 = 16 +* round2n(0.01) = 2^(-7) = 0.0078125 +* +* BACKGROUND +* +* Let x = f * 2^e, where 0.5 <= f < 1 is a normalized fractional part, +* e is an integer exponent. Then, obviously, 0.5 * 2^e <= x < 2^e, so +* if x - 0.5 * 2^e <= 2^e - x, we choose 0.5 * 2^e = 2^(e-1), and 2^e +* otherwise. The latter condition can be written as 2 * x <= 1.5 * 2^e +* or 2 * f * 2^e <= 1.5 * 2^e or, finally, f <= 0.75. */ + +double round2n(double x) +{ int e; + double f; + xassert(x > 0.0); + f = frexp(x, &e); + return ldexp(1.0, f <= 0.75 ? e-1 : e); +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2int.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2int.c new file mode 100644 index 000000000..cbd6e953f --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2int.c @@ -0,0 +1,92 @@ +/* str2int.c (convert string to int) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* str2int - convert character string to value of int type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2int(const char *str, int *val); +* +* DESCRIPTION +* +* The routine str2int converts the character string str to a value of +* integer type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2int(const char *str, int *val_) +{ int d, k, s, val = 0; + /* scan optional sign */ + if (str[0] == '+') + s = +1, k = 1; + else if (str[0] == '-') + s = -1, k = 1; + else + s = +1, k = 0; + /* check for the first digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan digits */ + while (isdigit((unsigned char)str[k])) + { d = str[k++] - '0'; + if (s > 0) + { if (val > INT_MAX / 10) + return 1; + val *= 10; + if (val > INT_MAX - d) + return 1; + val += d; + } + else /* s < 0 */ + { if (val < INT_MIN / 10) + return 1; + val *= 10; + if (val < INT_MIN + d) + return 1; + val -= d; + } + } + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2num.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2num.c new file mode 100644 index 000000000..26c2f68f1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/str2num.c @@ -0,0 +1,110 @@ +/* str2num.c (convert string to double) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* str2num - convert character string to value of double type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2num(const char *str, double *val); +* +* DESCRIPTION +* +* The routine str2num converts the character string str to a value of +* double type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2num(const char *str, double *val_) +{ int k; + double val; + /* scan optional sign */ + k = (str[0] == '+' || str[0] == '-' ? 1 : 0); + /* check for decimal point */ + if (str[k] == '.') + { k++; + /* a digit should follow it */ + if (!isdigit((unsigned char)str[k])) + return 2; + k++; + goto frac; + } + /* integer part should start with a digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan integer part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal point */ + if (str[k] == '.') k++; +frac: /* scan optional fraction part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal exponent */ + if (str[k] == 'E' || str[k] == 'e') + { k++; + /* scan optional sign */ + if (str[k] == '+' || str[k] == '-') + k++; + /* a digit should follow E, E+ or E- */ + if (!isdigit((unsigned char)str[k])) + return 2; + } + /* scan optional exponent part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* perform conversion */ + { char *endptr; + val = strtod(str, &endptr); + if (*endptr != '\0') + return 2; + } + /* check for overflow */ + if (!(-DBL_MAX <= val && val <= +DBL_MAX)) + return 1; + /* check for underflow */ + if (-DBL_MIN < val && val < +DBL_MIN) + val = 0.0; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/strspx.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/strspx.c new file mode 100644 index 000000000..fe8a2a101 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/strspx.c @@ -0,0 +1,60 @@ +/* strspx.c (remove all spaces from string) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "misc.h" + +/*********************************************************************** +* NAME +* +* strspx - remove all spaces from character string +* +* SYNOPSIS +* +* #include "misc.h" +* char *strspx(char *str); +* +* DESCRIPTION +* +* The routine strspx removes all spaces from the character string str. +* +* RETURNS +* +* The routine returns a pointer to the character string. +* +* EXAMPLES +* +* strspx(" Errare humanum est ") => "Errarehumanumest" +* +* strspx(" ") => "" */ + +char *strspx(char *str) +{ char *s, *t; + for (s = t = str; *s; s++) + { if (*s != ' ') + *t++ = *s; + } + *t = '\0'; + return str; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/strtrim.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/strtrim.c new file mode 100644 index 000000000..9992c4b0c --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/strtrim.c @@ -0,0 +1,62 @@ +/* strtrim.c (remove trailing spaces from string) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "misc.h" +#include "stdc.h" + +/*********************************************************************** +* NAME +* +* strtrim - remove trailing spaces from character string +* +* SYNOPSIS +* +* #include "misc.h" +* char *strtrim(char *str); +* +* DESCRIPTION +* +* The routine strtrim removes trailing spaces from the character +* string str. +* +* RETURNS +* +* The routine returns a pointer to the character string. +* +* EXAMPLES +* +* strtrim("Errare humanum est ") => "Errare humanum est" +* +* strtrim(" ") => "" */ + +char *strtrim(char *str) +{ char *t; + for (t = strrchr(str, '\0') - 1; t >= str; t--) + { if (*t != ' ') + break; + *t = '\0'; + } + return str; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.c new file mode 100644 index 000000000..99ba4d604 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.c @@ -0,0 +1,311 @@ +/* triang.c (find maximal triangular part of rectangular matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "triang.h" + +/*********************************************************************** +* triang - find maximal triangular part of rectangular matrix +* +* Given a mxn sparse matrix A this routine finds permutation matrices +* P and Q such that matrix A' = P * A * Q has the following structure: +* +* 1 s n +* 1 * . . . . . x x x x x +* * * . . . . x x x x x +* * * * . . . x x x x x +* * * * * . . x x x x x +* * * * * * . x x x x x +* s * * * * * * x x x x x +* x x x x x x x x x x x +* x x x x x x x x x x x +* m x x x x x x x x x x x +* +* where '*' are elements of the triangular part, '.' are structural +* zeros, 'x' are other elements. +* +* The formal routine mat specifies the original matrix A in both row- +* and column-wise format. If the routine mat is called with k = +i, +* 1 <= i <= m, it should store column indices and values of non-zero +* elements of i-th row of A in locations ind[1], ..., ind[len] and +* val[1], ..., val[len], resp., where len is the returned number of +* non-zeros in the row, 0 <= len <= n. Similarly, if the routine mat +* is called with k = -j, 1 <= j <= n, it should store row indices and +* values of non-zero elements of j-th column of A and return len, the +* number of non-zeros in the column, 0 <= len <= m. Should note that +* duplicate indices are not allowed. +* +* The parameter info is a transit pointer passed to the routine mat. +* +* The parameter tol is a tolerance. The routine triang guarantees that +* each diagonal element in the triangular part of matrix A' is not +* less in magnitude than tol * max, where max is the maximal magnitude +* of elements in corresponding column. +* +* On exit the routine triang stores information on the triangular part +* found in the arrays rn and cn. Elements rn[1], ..., rn[s] specify +* row numbers and elements cn[1], ..., cn[s] specify column numbers +* of the original matrix A, which correspond to rows/columns 1, ..., s +* of matrix A', where s is the size of the triangular part returned by +* the routine, 0 <= s <= min(m, n). The order of rows and columns that +* are not included in the triangular part remains unspecified. +* +* ALGORITHM +* +* The routine triang uses a simple greedy heuristic. +* +* At some step the matrix A' = P * A * Q has the following structure: +* +* 1 n +* 1 * . . . . . . . x x x +* * * . . . . . . x x x +* * * * . . . . . x x x +* * * * * . . . . x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* x x x x # # # # x x x +* m x x x x # # # # x x x +* +* where '#' are elements of active submatrix. Initially P = Q = I, so +* the active submatrix is the original matrix A = A'. +* +* If some row has exactly one non-zero in the active submatrix (row +* singleton), the routine includes this row and corresponding column +* in the triangular part, and removes the column from the active +* submatrix. Otherwise, the routine simply removes a column having +* maximal number of non-zeros from the active submatrix in the hope +* that new row singleton(s) will appear. +* +* COMPLEXITY +* +* The time complexity of the routine triang is O(nnz), where nnz is +* number of non-zeros in the original matrix A. */ + +int triang(int m, int n, int (*mat)(void *info, int k, int ind[], + double val[]), void *info, double tol, int rn[], int cn[]) +{ int head, i, j, jj, k, kk, ks, len, len2, next_j, ns, size; + int *cind, *rind, *cnt, *ptr, *list, *prev, *next; + double *cval, *rval, *big; + char *flag; + /* allocate working arrays */ + cind = talloc(1+m, int); + cval = talloc(1+m, double); + rind = talloc(1+n, int); + rval = talloc(1+n, double); + cnt = ptr = talloc(1+m, int); + list = talloc(1+n, int); + prev = talloc(1+n, int); + next = talloc(1+n, int); + big = talloc(1+n, double); + flag = talloc(1+n, char); + /*--------------------------------------------------------------*/ + /* build linked lists of columns having equal lengths */ + /*--------------------------------------------------------------*/ + /* ptr[len], 0 <= len <= m, is number of first column of length + * len; + * next[j], 1 <= j <= n, is number of next column having the same + * length as column j; + * big[j], 1 <= j <= n, is maximal magnitude of elements in j-th + * column */ + for (len = 0; len <= m; len++) + ptr[len] = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + /* add this column to beginning of list ptr[len] */ + next[j] = ptr[len]; + ptr[len] = j; + /* determine maximal magnitude of elements in this column */ + big[j] = 0.0; + for (k = 1; k <= len; k++) + { if (big[j] < fabs(cval[k])) + big[j] = fabs(cval[k]); + } + } + /*--------------------------------------------------------------*/ + /* build doubly linked list of columns ordered by decreasing */ + /* column lengths */ + /*--------------------------------------------------------------*/ + /* head is number of first column in the list; + * prev[j], 1 <= j <= n, is number of column that precedes j-th + * column in the list; + * next[j], 1 <= j <= n, is number of column that follows j-th + * column in the list */ + head = 0; + for (len = 0; len <= m; len++) + { /* walk thru list of columns of length len */ + for (j = ptr[len]; j != 0; j = next_j) + { next_j = next[j]; + /* add j-th column to beginning of the column list */ + prev[j] = 0; + next[j] = head; + if (head != 0) + prev[head] = j; + head = j; + } + } + /*--------------------------------------------------------------*/ + /* build initial singleton list */ + /*--------------------------------------------------------------*/ + /* there are used two list of columns: + * 1) doubly linked list of active columns, in which all columns + * are ordered by decreasing column lengths; + * 2) singleton list; an active column is included in this list + * if it has at least one row singleton in active submatrix */ + /* flag[j], 1 <= j <= n, is a flag of j-th column: + * 0 j-th column is inactive; + * 1 j-th column is active; + * 2 j-th column is active and has row singleton(s) */ + /* initially all columns are active */ + for (j = 1; j <= n; j++) + flag[j] = 1; + /* initialize row counts and build initial singleton list */ + /* cnt[i], 1 <= i <= m, is number of non-zeros, which i-th row + * has in active submatrix; + * ns is size of singleton list; + * list[1], ..., list[ns] are numbers of active columns included + * in the singleton list */ + ns = 0; + for (i = 1; i <= m; i++) + { /* get i-th row */ + len = cnt[i] = mat(info, +i, rind, rval); + xassert(0 <= len && len <= n); + if (len == 1) + { /* a[i,j] is row singleton */ + j = rind[1]; + xassert(1 <= j && j <= n); + if (flag[j] != 2) + { /* include j-th column in singleton list */ + flag[j] = 2; + list[++ns] = j; + } + } + } + /*--------------------------------------------------------------*/ + /* main loop */ + /*--------------------------------------------------------------*/ + size = 0; /* size of triangular part */ + /* loop until active column list is non-empty, i.e. until the + * active submatrix has at least one column */ + while (head != 0) + { if (ns == 0) + { /* singleton list is empty */ + /* remove from the active submatrix a column of maximal + * length in the hope that some row singletons appear */ + j = head; + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + goto drop; + } + /* take column j from the singleton list */ + j = list[ns--]; + xassert(flag[j] == 2); + /* j-th column has at least one row singleton in the active + * submatrix; choose one having maximal magnitude */ + len = mat(info, -j, cind, cval); + xassert(0 <= len && len <= m); + kk = 0; + for (k = 1; k <= len; k++) + { i = cind[k]; + xassert(1 <= i && i <= m); + if (cnt[i] == 1) + { /* a[i,j] is row singleton */ + if (kk == 0 || fabs(cval[kk]) < fabs(cval[k])) + kk = k; + } + } + xassert(kk > 0); + /* check magnitude of the row singleton chosen */ + if (fabs(cval[kk]) < tol * big[j]) + { /* all row singletons are too small in magnitude; drop j-th + * column */ + goto drop; + } + /* row singleton a[i,j] is ok; add i-th row and j-th column to + * the triangular part */ + size++; + rn[size] = cind[kk]; + cn[size] = j; +drop: /* remove j-th column from the active submatrix */ + xassert(flag[j]); + flag[j] = 0; + if (prev[j] == 0) + head = next[j]; + else + next[prev[j]] = next[j]; + if (next[j] == 0) + ; + else + prev[next[j]] = prev[j]; + /* decrease row counts */ + for (k = 1; k <= len; k++) + { i = cind[k]; + xassert(1 <= i && i <= m); + xassert(cnt[i] > 0); + cnt[i]--; + if (cnt[i] == 1) + { /* new singleton appeared in i-th row; determine number + * of corresponding column (it is the only active column + * in this row) */ + len2 = mat(info, +i, rind, rval); + xassert(0 <= len2 && len2 <= n); + ks = 0; + for (kk = 1; kk <= len2; kk++) + { jj = rind[kk]; + xassert(1 <= jj && jj <= n); + if (flag[jj]) + { xassert(ks == 0); + ks = kk; + } + } + xassert(ks > 0); + /* a[i,jj] is new row singleton */ + jj = rind[ks]; + if (flag[jj] != 2) + { /* include jj-th column in the singleton list */ + flag[jj] = 2; + list[++ns] = jj; + } + } + } + } + /* now all row counts should be zero */ + for (i = 1; i <= m; i++) + xassert(cnt[i] == 0); + /* deallocate working arrays */ + tfree(cind); + tfree(cval); + tfree(rind); + tfree(rval); + tfree(ptr); + tfree(list); + tfree(prev); + tfree(next); + tfree(big); + tfree(flag); + return size; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.h new file mode 100644 index 000000000..1e50d44dc --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/triang.h @@ -0,0 +1,34 @@ +/* triang.h (find maximal triangular part of rectangular matrix) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef TRIANG_H +#define TRIANG_H + +#define triang _glp_triang +int triang(int m, int n, int (*mat)(void *info, int k, int ind[], + double val[]), void *info, double tol, int rn[], int cn[]); +/* find maximal triangular part of rectangular matrix */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.c new file mode 100644 index 000000000..5daa69cff --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.c @@ -0,0 +1,242 @@ +/* wclique.c (maximum weight clique, Ostergard's algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Two subroutines sub() and wclique() below are intended to find a +* maximum weight clique in a given undirected graph. These subroutines +* are slightly modified version of the program WCLIQUE developed by +* Patric Ostergard and based +* on ideas from the article "P. R. J. Ostergard, A new algorithm for +* the maximum-weight clique problem, submitted for publication", which +* in turn is a generalization of the algorithm for unweighted graphs +* presented in "P. R. J. Ostergard, A fast algorithm for the maximum +* clique problem, submitted for publication". +* +* USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. +* +* Changes were made by Andrew Makhorin . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "wclique.h" + +/*********************************************************************** +* NAME +* +* wclique - find maximum weight clique with Ostergard's algorithm +* +* SYNOPSIS +* +* #include "wclique.h" +* int wclique(int n, const int w[], const unsigned char a[], +* int ind[]); +* +* DESCRIPTION +* +* The routine wclique finds a maximum weight clique in an undirected +* graph with Ostergard's algorithm. +* +* INPUT PARAMETERS +* +* n is the number of vertices, n > 0. +* +* w[i], i = 1,...,n, is a weight of vertex i. +* +* a[*] is the strict (without main diagonal) lower triangle of the +* graph adjacency matrix in packed format. +* +* OUTPUT PARAMETER +* +* ind[k], k = 1,...,size, is the number of a vertex included in the +* clique found, 1 <= ind[k] <= n, where size is the number of vertices +* in the clique returned on exit. +* +* RETURNS +* +* The routine returns the clique size, i.e. the number of vertices in +* the clique. */ + +struct csa +{ /* common storage area */ + int n; + /* number of vertices */ + const int *wt; /* int wt[0:n-1]; */ + /* weights */ + const unsigned char *a; + /* adjacency matrix (packed lower triangle without main diag.) */ + int record; + /* weight of best clique */ + int rec_level; + /* number of vertices in best clique */ + int *rec; /* int rec[0:n-1]; */ + /* best clique so far */ + int *clique; /* int clique[0:n-1]; */ + /* table for pruning */ + int *set; /* int set[0:n-1]; */ + /* current clique */ +}; + +#define n (csa->n) +#define wt (csa->wt) +#define a (csa->a) +#define record (csa->record) +#define rec_level (csa->rec_level) +#define rec (csa->rec) +#define clique (csa->clique) +#define set (csa->set) + +#if 0 +static int is_edge(struct csa *csa, int i, int j) +{ /* if there is arc (i,j), the routine returns true; otherwise + * false; 0 <= i, j < n */ + int k; + xassert(0 <= i && i < n); + xassert(0 <= j && j < n); + if (i == j) return 0; + if (i < j) k = i, i = j, j = k; + k = (i * (i - 1)) / 2 + j; + return a[k / CHAR_BIT] & + (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); +} +#else +#define is_edge(csa, i, j) ((i) == (j) ? 0 : \ + (i) > (j) ? is_edge1(i, j) : is_edge1(j, i)) +#define is_edge1(i, j) is_edge2(((i) * ((i) - 1)) / 2 + (j)) +#define is_edge2(k) (a[(k) / CHAR_BIT] & \ + (unsigned char)(1 << ((CHAR_BIT - 1) - (k) % CHAR_BIT))) +#endif + +static void sub(struct csa *csa, int ct, int table[], int level, + int weight, int l_weight) +{ int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable; + newtable = xcalloc(n, sizeof(int)); + if (ct <= 0) + { /* 0 or 1 elements left; include these */ + if (ct == 0) + { set[level++] = table[0]; + weight += l_weight; + } + if (weight > record) + { record = weight; + rec_level = level; + for (i = 0; i < level; i++) rec[i] = set[i]; + } + goto done; + } + for (i = ct; i >= 0; i--) + { if ((level == 0) && (i < ct)) goto done; + k = table[i]; + if ((level > 0) && (clique[k] <= (record - weight))) + goto done; /* prune */ + set[level] = k; + curr_weight = weight + wt[k]; + l_weight -= wt[k]; + if (l_weight <= (record - curr_weight)) + goto done; /* prune */ + p1 = newtable; + p2 = table; + left_weight = 0; + while (p2 < table + i) + { j = *p2++; + if (is_edge(csa, j, k)) + { *p1++ = j; + left_weight += wt[j]; + } + } + if (left_weight <= (record - curr_weight)) continue; + sub(csa, p1 - newtable - 1, newtable, level + 1, curr_weight, + left_weight); + } +done: xfree(newtable); + return; +} + +int wclique(int n_, const int w[], const unsigned char a_[], int ind[]) +{ struct csa csa_, *csa = &csa_; + int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos; + double timer; + n = n_; + xassert(n > 0); + wt = &w[1]; + a = a_; + record = 0; + rec_level = 0; + rec = &ind[1]; + clique = xcalloc(n, sizeof(int)); + set = xcalloc(n, sizeof(int)); + used = xcalloc(n, sizeof(int)); + nwt = xcalloc(n, sizeof(int)); + pos = xcalloc(n, sizeof(int)); + /* start timer */ + timer = xtime(); + /* order vertices */ + for (i = 0; i < n; i++) + { nwt[i] = 0; + for (j = 0; j < n; j++) + if (is_edge(csa, i, j)) nwt[i] += wt[j]; + } + for (i = 0; i < n; i++) + used[i] = 0; + for (i = n-1; i >= 0; i--) + { max_wt = -1; + max_nwt = -1; + for (j = 0; j < n; j++) + { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt + && nwt[j] > max_nwt))) + { max_wt = wt[j]; + max_nwt = nwt[j]; + p = j; + } + } + pos[i] = p; + used[p] = 1; + for (j = 0; j < n; j++) + if ((!used[j]) && (j != p) && (is_edge(csa, p, j))) + nwt[j] -= wt[p]; + } + /* main routine */ + wth = 0; + for (i = 0; i < n; i++) + { wth += wt[pos[i]]; + sub(csa, i, pos, 0, 0, wth); + clique[pos[i]] = record; + if (xdifftime(xtime(), timer) >= 5.0 - 0.001) + { /* print current record and reset timer */ + xprintf("level = %d (%d); best = %d\n", i+1, n, record); + timer = xtime(); + } + } + xfree(clique); + xfree(set); + xfree(used); + xfree(nwt); + xfree(pos); + /* return the solution found */ + for (i = 1; i <= rec_level; i++) ind[i]++; + return rec_level; +} + +#undef n +#undef wt +#undef a +#undef record +#undef rec_level +#undef rec +#undef clique +#undef set + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.h new file mode 100644 index 000000000..d52dc8052 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique.h @@ -0,0 +1,33 @@ +/* wclique.h (maximum weight clique, Ostergard's algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef WCLIQUE_H +#define WCLIQUE_H + +#define wclique _glp_wclique +int wclique(int n, const int w[], const unsigned char a[], int ind[]); +/* find maximum weight clique with Ostergard's algorithm */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.c b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.c new file mode 100644 index 000000000..a3d895429 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.c @@ -0,0 +1,317 @@ +/* wclique1.c (maximum weight clique, greedy heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "wclique1.h" + +/*********************************************************************** +* NAME +* +* wclique1 - find maximum weight clique with greedy heuristic +* +* SYNOPSIS +* +* #include "wclique1.h" +* int wclique1(int n, const double w[], +* int (*func)(void *info, int i, int ind[]), void *info, int c[]); +* +* DESCRIPTION +* +* The routine wclique1 implements a sequential greedy heuristic to +* find maximum weight clique in a given (undirected) graph G = (V, E). +* +* The parameter n specifies the number of vertices |V| in the graph, +* n >= 0. +* +* The array w specifies vertex weights in locations w[i], i = 1,...,n. +* All weights must be non-negative. +* +* The formal routine func specifies the graph. For a given vertex i, +* 1 <= i <= n, it stores indices of all vertices adjacent to vertex i +* in locations ind[1], ..., ind[deg], where deg is the degree of +* vertex i, 0 <= deg < n, returned on exit. Note that self-loops and +* multiple edges are not allowed. +* +* The parameter info is a cookie passed to the routine func. +* +* On exit the routine wclique1 stores vertex indices included in +* the clique found to locations c[1], ..., c[size], where size is the +* clique size returned by the routine, 0 <= size <= n. +* +* RETURNS +* +* The routine wclique1 returns the size of the clique found. */ + +struct vertex { int i; double cw; }; + +static int CDECL fcmp(const void *xx, const void *yy) +{ const struct vertex *x = xx, *y = yy; + if (x->cw > y->cw) return -1; + if (x->cw < y->cw) return +1; + return 0; +} + +int wclique1(int n, const double w[], + int (*func)(void *info, int i, int ind[]), void *info, int c[]) +{ struct vertex *v_list; + int deg, c_size, d_size, i, j, k, kk, l, *ind, *c_list, *d_list, + size = 0; + double c_wght, d_wght, *sw, best = 0.0; + char *d_flag, *skip; + /* perform sanity checks */ + xassert(n >= 0); + for (i = 1; i <= n; i++) + xassert(w[i] >= 0.0); + /* if the graph is empty, nothing to do */ + if (n == 0) goto done; + /* allocate working arrays */ + ind = xcalloc(1+n, sizeof(int)); + v_list = xcalloc(1+n, sizeof(struct vertex)); + c_list = xcalloc(1+n, sizeof(int)); + d_list = xcalloc(1+n, sizeof(int)); + d_flag = xcalloc(1+n, sizeof(char)); + skip = xcalloc(1+n, sizeof(char)); + sw = xcalloc(1+n, sizeof(double)); + /* build the vertex list */ + for (i = 1; i <= n; i++) + { v_list[i].i = i; + /* compute the cumulative weight of each vertex i, which is + * cw[i] = w[i] + sum{j : (i,j) in E} w[j] */ + v_list[i].cw = w[i]; + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (k = 1; k <= deg; k++) + { j = ind[k]; + xassert(1 <= j && j <= n && j != i); + v_list[i].cw += w[j]; + } + } + /* sort the vertex list to access vertices in descending order of + * cumulative weights */ + qsort(&v_list[1], n, sizeof(struct vertex), fcmp); + /* initially all vertices are unmarked */ + memset(&skip[1], 0, sizeof(char) * n); + /* clear flags of all vertices */ + memset(&d_flag[1], 0, sizeof(char) * n); + /* look through all vertices of the graph */ + for (l = 1; l <= n; l++) + { /* take vertex i */ + i = v_list[l].i; + /* if this vertex was already included in one of previosuly + * constructed cliques, skip it */ + if (skip[i]) continue; + /* use vertex i as the initial clique vertex */ + c_size = 1; /* size of current clique */ + c_list[1] = i; /* list of vertices in current clique */ + c_wght = w[i]; /* weight of current clique */ + /* determine the candidate set D = { j : (i,j) in E } */ + d_size = func(info, i, d_list); + xassert(0 <= d_size && d_size < n); + d_wght = 0.0; /* weight of set D */ + for (k = 1; k <= d_size; k++) + { j = d_list[k]; + xassert(1 <= j && j <= n && j != i); + xassert(!d_flag[j]); + d_flag[j] = 1; + d_wght += w[j]; + } + /* check an upper bound to the final clique weight */ + if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) + { /* skip constructing the current clique */ + goto next; + } + /* compute the summary weight of each vertex i in D, which is + * sw[i] = w[i] + sum{j in D and (i,j) in E} w[j] */ + for (k = 1; k <= d_size; k++) + { i = d_list[k]; + sw[i] = w[i]; + /* consider vertices adjacent to vertex i */ + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (kk = 1; kk <= deg; kk++) + { j = ind[kk]; + xassert(1 <= j && j <= n && j != i); + if (d_flag[j]) sw[i] += w[j]; + } + } + /* grow the current clique by adding vertices from D */ + while (d_size > 0) + { /* check an upper bound to the final clique weight */ + if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) + { /* skip constructing the current clique */ + goto next; + } + /* choose vertex i in D having maximal summary weight */ + i = d_list[1]; + for (k = 2; k <= d_size; k++) + { j = d_list[k]; + if (sw[i] < sw[j]) i = j; + } + /* include vertex i in the current clique */ + c_size++; + c_list[c_size] = i; + c_wght += w[i]; + /* remove all vertices not adjacent to vertex i, including + * vertex i itself, from the candidate set D */ + deg = func(info, i, ind); + xassert(0 <= deg && deg < n); + for (k = 1; k <= deg; k++) + { j = ind[k]; + xassert(1 <= j && j <= n && j != i); + /* vertex j is adjacent to vertex i */ + if (d_flag[j]) + { xassert(d_flag[j] == 1); + /* mark vertex j to keep it in D */ + d_flag[j] = 2; + } + } + kk = d_size, d_size = 0; + for (k = 1; k <= kk; k++) + { j = d_list[k]; + if (d_flag[j] == 1) + { /* remove vertex j from D */ + d_flag[j] = 0; + d_wght -= w[j]; + } + else if (d_flag[j] == 2) + { /* keep vertex j in D */ + d_list[++d_size] = j; + d_flag[j] = 1; + } + else + xassert(d_flag != d_flag); + } + } + /* the current clique has been completely constructed */ + if (best < c_wght) + { best = c_wght; + size = c_size; + xassert(1 <= size && size <= n); + memcpy(&c[1], &c_list[1], size * sizeof(int)); + } +next: /* mark the current clique vertices in order not to use them + * as initial vertices anymore */ + for (k = 1; k <= c_size; k++) + skip[c_list[k]] = 1; + /* set D can be non-empty, so clean up vertex flags */ + for (k = 1; k <= d_size; k++) + d_flag[d_list[k]] = 0; + } + /* free working arrays */ + xfree(ind); + xfree(v_list); + xfree(c_list); + xfree(d_list); + xfree(d_flag); + xfree(skip); + xfree(sw); +done: /* return to the calling program */ + return size; +} + +/**********************************************************************/ + +#ifdef GLP_TEST +#include "glpk.h" +#include "rng.h" + +typedef struct { double w; } v_data; + +#define weight(v) (((v_data *)((v)->data))->w) + +glp_graph *G; + +char *flag; + +int func(void *info, int i, int ind[]) +{ glp_arc *e; + int j, k, deg = 0; + xassert(info == NULL); + xassert(1 <= i && i <= G->nv); + /* look through incoming arcs */ + for (e = G->v[i]->in; e != NULL; e = e->h_next) + { j = e->tail->i; /* j->i */ + if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; + } + /* look through outgoing arcs */ + for (e = G->v[i]->out; e != NULL; e = e->t_next) + { j = e->head->i; /* i->j */ + if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; + } + /* clear the flag array */ + xassert(deg < G->nv); + for (k = 1; k <= deg; k++) flag[ind[k]] = 0; + return deg; +} + +int main(int argc, char *argv[]) +{ RNG *rand; + int i, k, kk, size, *c, *ind, deg; + double *w, sum, t; + /* read graph in DIMACS format */ + G = glp_create_graph(sizeof(v_data), 0); + xassert(argc == 2); + xassert(glp_read_ccdata(G, offsetof(v_data, w), argv[1]) == 0); + /* print the number of connected components */ + xprintf("nc = %d\n", glp_weak_comp(G, -1)); + /* assign random weights unformly distributed in [1,100] */ + w = xcalloc(1+G->nv, sizeof(double)); + rand = rng_create_rand(); + for (i = 1; i <= G->nv; i++) +#if 0 + w[i] = weight(G->v[i]) = 1.0; +#else + w[i] = weight(G->v[i]) = rng_unif_rand(rand, 100) + 1; +#endif + /* write graph in DIMACS format */ + xassert(glp_write_ccdata(G, offsetof(v_data, w), "graph") == 0); + /* find maximum weight clique */ + c = xcalloc(1+G->nv, sizeof(int)); + flag = xcalloc(1+G->nv, sizeof(char)); + memset(&flag[1], 0, G->nv); + t = xtime(); + size = wclique1(G->nv, w, func, NULL, c); + xprintf("Time used: %.1f s\n", xdifftime(xtime(), t)); + /* check the clique found */ + ind = xcalloc(1+G->nv, sizeof(int)); + for (k = 1; k <= size; k++) + { i = c[k]; + deg = func(NULL, i, ind); + for (kk = 1; kk <= size; kk++) + flag[c[kk]] = 1; + flag[i] = 0; + for (kk = 1; kk <= deg; kk++) + flag[ind[kk]] = 0; + for (kk = 1; kk <= size; kk++) + xassert(flag[c[kk]] == 0); + } + /* compute the clique weight */ + sum = 0.0; + for (i = 1; i <= size; i++) + sum += w[c[i]]; + xprintf("size = %d; sum = %g\n", size, sum); + return 0; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.h b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.h new file mode 100644 index 000000000..588f32571 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/misc/wclique1.h @@ -0,0 +1,34 @@ +/* wclique1.h (maximum weight clique, greedy heuristic) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef WCLIQUE1_H +#define WCLIQUE1_H + +#define wclique1 _glp_wclique1 +int wclique1(int n, const double w[], + int (*func)(void *info, int i, int ind[]), void *info, int c[]); +/* find maximum weight clique with greedy heuristic */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl.h b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl.h new file mode 100644 index 000000000..ddd315438 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl.h @@ -0,0 +1,2598 @@ +/* mpl.h (GNU MathProg translator) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MPL_H +#define MPL_H + +#include "avl.h" +#include "dmp.h" +#include "env.h" +#include "misc.h" +#include "rng.h" + +#if 0 /* 22/I-2013 */ +typedef struct MPL MPL; +#else +typedef struct glp_tran MPL; +#endif +typedef char STRING; +typedef struct SYMBOL SYMBOL; +typedef struct TUPLE TUPLE; +typedef struct ARRAY ELEMSET; +typedef struct ELEMVAR ELEMVAR; +typedef struct FORMULA FORMULA; +typedef struct ELEMCON ELEMCON; +typedef union VALUE VALUE; +typedef struct ARRAY ARRAY; +typedef struct MEMBER MEMBER; +#if 1 +/* many C compilers have DOMAIN declared in :( */ +#undef DOMAIN +#define DOMAIN DOMAIN1 +#endif +typedef struct DOMAIN DOMAIN; +typedef struct DOMAIN_BLOCK DOMAIN_BLOCK; +typedef struct DOMAIN_SLOT DOMAIN_SLOT; +typedef struct SET SET; +typedef struct WITHIN WITHIN; +typedef struct GADGET GADGET; +typedef struct PARAMETER PARAMETER; +typedef struct CONDITION CONDITION; +typedef struct VARIABLE VARIABLE; +typedef struct CONSTRAINT CONSTRAINT; +typedef struct TABLE TABLE; +typedef struct TABARG TABARG; +typedef struct TABFLD TABFLD; +typedef struct TABIN TABIN; +typedef struct TABOUT TABOUT; +typedef struct TABDCA TABDCA; +typedef union OPERANDS OPERANDS; +typedef struct ARG_LIST ARG_LIST; +typedef struct CODE CODE; +typedef struct CHECK CHECK; +typedef struct DISPLAY DISPLAY; +typedef struct DISPLAY1 DISPLAY1; +typedef struct PRINTF PRINTF; +typedef struct PRINTF1 PRINTF1; +typedef struct FOR FOR; +typedef struct STATEMENT STATEMENT; +typedef struct TUPLE SLICE; + +/**********************************************************************/ +/* * * TRANSLATOR DATABASE * * */ +/**********************************************************************/ + +#define A_BINARY 101 /* something binary */ +#define A_CHECK 102 /* check statement */ +#define A_CONSTRAINT 103 /* model constraint */ +#define A_DISPLAY 104 /* display statement */ +#define A_ELEMCON 105 /* elemental constraint/objective */ +#define A_ELEMSET 106 /* elemental set */ +#define A_ELEMVAR 107 /* elemental variable */ +#define A_EXPRESSION 108 /* expression */ +#define A_FOR 109 /* for statement */ +#define A_FORMULA 110 /* formula */ +#define A_INDEX 111 /* dummy index */ +#define A_INPUT 112 /* input table */ +#define A_INTEGER 113 /* something integer */ +#define A_LOGICAL 114 /* something logical */ +#define A_MAXIMIZE 115 /* objective has to be maximized */ +#define A_MINIMIZE 116 /* objective has to be minimized */ +#define A_NONE 117 /* nothing */ +#define A_NUMERIC 118 /* something numeric */ +#define A_OUTPUT 119 /* output table */ +#define A_PARAMETER 120 /* model parameter */ +#define A_PRINTF 121 /* printf statement */ +#define A_SET 122 /* model set */ +#define A_SOLVE 123 /* solve statement */ +#define A_SYMBOLIC 124 /* something symbolic */ +#define A_TABLE 125 /* data table */ +#define A_TUPLE 126 /* n-tuple */ +#define A_VARIABLE 127 /* model variable */ + +#define MAX_LENGTH 100 +/* maximal length of any symbolic value (this includes symbolic names, + numeric and string literals, and all symbolic values that may appear + during the evaluation phase) */ + +#define CONTEXT_SIZE 60 +/* size of the context queue, in characters */ + +#define OUTBUF_SIZE 1024 +/* size of the output buffer, in characters */ + +#if 0 /* 22/I-2013 */ +struct MPL +#else +struct glp_tran +#endif +{ /* translator database */ + /*--------------------------------------------------------------*/ + /* scanning segment */ + int line; + /* number of the current text line */ + int c; + /* the current character or EOF */ + int token; + /* the current token: */ +#define T_EOF 201 /* end of file */ +#define T_NAME 202 /* symbolic name (model section only) */ +#define T_SYMBOL 203 /* symbol (data section only) */ +#define T_NUMBER 204 /* numeric literal */ +#define T_STRING 205 /* string literal */ +#define T_AND 206 /* and && */ +#define T_BY 207 /* by */ +#define T_CROSS 208 /* cross */ +#define T_DIFF 209 /* diff */ +#define T_DIV 210 /* div */ +#define T_ELSE 211 /* else */ +#define T_IF 212 /* if */ +#define T_IN 213 /* in */ +#define T_INFINITY 214 /* Infinity */ +#define T_INTER 215 /* inter */ +#define T_LESS 216 /* less */ +#define T_MOD 217 /* mod */ +#define T_NOT 218 /* not ! */ +#define T_OR 219 /* or || */ +#define T_SPTP 220 /* s.t. */ +#define T_SYMDIFF 221 /* symdiff */ +#define T_THEN 222 /* then */ +#define T_UNION 223 /* union */ +#define T_WITHIN 224 /* within */ +#define T_PLUS 225 /* + */ +#define T_MINUS 226 /* - */ +#define T_ASTERISK 227 /* * */ +#define T_SLASH 228 /* / */ +#define T_POWER 229 /* ^ ** */ +#define T_LT 230 /* < */ +#define T_LE 231 /* <= */ +#define T_EQ 232 /* = == */ +#define T_GE 233 /* >= */ +#define T_GT 234 /* > */ +#define T_NE 235 /* <> != */ +#define T_CONCAT 236 /* & */ +#define T_BAR 237 /* | */ +#define T_POINT 238 /* . */ +#define T_COMMA 239 /* , */ +#define T_COLON 240 /* : */ +#define T_SEMICOLON 241 /* ; */ +#define T_ASSIGN 242 /* := */ +#define T_DOTS 243 /* .. */ +#define T_LEFT 244 /* ( */ +#define T_RIGHT 245 /* ) */ +#define T_LBRACKET 246 /* [ */ +#define T_RBRACKET 247 /* ] */ +#define T_LBRACE 248 /* { */ +#define T_RBRACE 249 /* } */ +#define T_APPEND 250 /* >> */ +#define T_TILDE 251 /* ~ */ +#define T_INPUT 252 /* <- */ + int imlen; + /* length of the current token */ + char *image; /* char image[MAX_LENGTH+1]; */ + /* image of the current token */ + double value; + /* value of the current token (for T_NUMBER only) */ + int b_token; + /* the previous token */ + int b_imlen; + /* length of the previous token */ + char *b_image; /* char b_image[MAX_LENGTH+1]; */ + /* image of the previous token */ + double b_value; + /* value of the previous token (if token is T_NUMBER) */ + int f_dots; + /* if this flag is set, the next token should be recognized as + T_DOTS, not as T_POINT */ + int f_scan; + /* if this flag is set, the next token is already scanned */ + int f_token; + /* the next token */ + int f_imlen; + /* length of the next token */ + char *f_image; /* char f_image[MAX_LENGTH+1]; */ + /* image of the next token */ + double f_value; + /* value of the next token (if token is T_NUMBER) */ + char *context; /* char context[CONTEXT_SIZE]; */ + /* context circular queue (not null-terminated!) */ + int c_ptr; + /* pointer to the current position in the context queue */ + int flag_d; + /* if this flag is set, the data section is being processed */ + /*--------------------------------------------------------------*/ + /* translating segment */ + DMP *pool; + /* memory pool used to allocate all data instances created during + the translation phase */ + AVL *tree; + /* symbolic name table: + node.type = A_INDEX => node.link -> DOMAIN_SLOT + node.type = A_SET => node.link -> SET + node.type = A_PARAMETER => node.link -> PARAMETER + node.type = A_VARIABLE => node.link -> VARIABLE + node.type = A_CONSTRANT => node.link -> CONSTRAINT */ + STATEMENT *model; + /* linked list of model statements in the original order */ + int flag_x; + /* if this flag is set, the current token being left parenthesis + begins a slice that allows recognizing any undeclared symbolic + names as dummy indices; this flag is automatically reset once + the next token has been scanned */ + int as_within; + /* the warning "in understood as within" has been issued */ + int as_in; + /* the warning "within understood as in" has been issued */ + int as_binary; + /* the warning "logical understood as binary" has been issued */ + int flag_s; + /* if this flag is set, the solve statement has been parsed */ + /*--------------------------------------------------------------*/ + /* common segment */ + DMP *strings; + /* memory pool to allocate STRING data structures */ + DMP *symbols; + /* memory pool to allocate SYMBOL data structures */ + DMP *tuples; + /* memory pool to allocate TUPLE data structures */ + DMP *arrays; + /* memory pool to allocate ARRAY data structures */ + DMP *members; + /* memory pool to allocate MEMBER data structures */ + DMP *elemvars; + /* memory pool to allocate ELEMVAR data structures */ + DMP *formulae; + /* memory pool to allocate FORMULA data structures */ + DMP *elemcons; + /* memory pool to allocate ELEMCON data structures */ + ARRAY *a_list; + /* linked list of all arrays in the database */ + char *sym_buf; /* char sym_buf[255+1]; */ + /* working buffer used by the routine format_symbol */ + char *tup_buf; /* char tup_buf[255+1]; */ + /* working buffer used by the routine format_tuple */ + /*--------------------------------------------------------------*/ + /* generating/postsolving segment */ + RNG *rand; + /* pseudo-random number generator */ + int flag_p; + /* if this flag is set, the postsolving phase is in effect */ + STATEMENT *stmt; + /* model statement being currently executed */ + TABDCA *dca; + /* pointer to table driver communication area for table statement + currently executed */ + int m; + /* number of rows in the problem, m >= 0 */ + int n; + /* number of columns in the problem, n >= 0 */ + ELEMCON **row; /* ELEMCON *row[1+m]; */ + /* row[0] is not used; + row[i] is elemental constraint or objective, which corresponds + to i-th row of the problem, 1 <= i <= m */ + ELEMVAR **col; /* ELEMVAR *col[1+n]; */ + /* col[0] is not used; + col[j] is elemental variable, which corresponds to j-th column + of the problem, 1 <= j <= n */ + /*--------------------------------------------------------------*/ + /* input/output segment */ + glp_file *in_fp; + /* stream assigned to the input text file */ + char *in_file; + /* name of the input text file */ + glp_file *out_fp; + /* stream assigned to the output text file used to write all data + produced by display and printf statements; NULL means the data + should be sent to stdout via the routine xprintf */ + char *out_file; + /* name of the output text file */ +#if 0 /* 08/XI-2009 */ + char *out_buf; /* char out_buf[OUTBUF_SIZE] */ + /* buffer to accumulate output data */ + int out_cnt; + /* count of data bytes stored in the output buffer */ +#endif + glp_file *prt_fp; + /* stream assigned to the print text file; may be NULL */ + char *prt_file; + /* name of the output print file */ + /*--------------------------------------------------------------*/ + /* solver interface segment */ + jmp_buf jump; + /* jump address for non-local go to in case of error */ + int phase; + /* phase of processing: + 0 - database is being or has been initialized + 1 - model section is being or has been read + 2 - data section is being or has been read + 3 - model is being or has been generated/postsolved + 4 - model processing error has occurred */ + char *mod_file; + /* name of the input text file, which contains model section */ + char *mpl_buf; /* char mpl_buf[255+1]; */ + /* working buffer used by some interface routines */ +}; + +/**********************************************************************/ +/* * * PROCESSING MODEL SECTION * * */ +/**********************************************************************/ + +#define alloc(type) ((type *)dmp_get_atomv(mpl->pool, sizeof(type))) +/* allocate atom of given type */ + +#define enter_context _glp_mpl_enter_context +void enter_context(MPL *mpl); +/* enter current token into context queue */ + +#define print_context _glp_mpl_print_context +void print_context(MPL *mpl); +/* print current content of context queue */ + +#define get_char _glp_mpl_get_char +void get_char(MPL *mpl); +/* scan next character from input text file */ + +#define append_char _glp_mpl_append_char +void append_char(MPL *mpl); +/* append character to current token */ + +#define get_token _glp_mpl_get_token +void get_token(MPL *mpl); +/* scan next token from input text file */ + +#define unget_token _glp_mpl_unget_token +void unget_token(MPL *mpl); +/* return current token back to input stream */ + +#define is_keyword _glp_mpl_is_keyword +int is_keyword(MPL *mpl, char *keyword); +/* check if current token is given non-reserved keyword */ + +#define is_reserved _glp_mpl_is_reserved +int is_reserved(MPL *mpl); +/* check if current token is reserved keyword */ + +#define make_code _glp_mpl_make_code +CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim); +/* generate pseudo-code (basic routine) */ + +#define make_unary _glp_mpl_make_unary +CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim); +/* generate pseudo-code for unary operation */ + +#define make_binary _glp_mpl_make_binary +CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, + int dim); +/* generate pseudo-code for binary operation */ + +#define make_ternary _glp_mpl_make_ternary +CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, + int type, int dim); +/* generate pseudo-code for ternary operation */ + +#define numeric_literal _glp_mpl_numeric_literal +CODE *numeric_literal(MPL *mpl); +/* parse reference to numeric literal */ + +#define string_literal _glp_mpl_string_literal +CODE *string_literal(MPL *mpl); +/* parse reference to string literal */ + +#define create_arg_list _glp_mpl_create_arg_list +ARG_LIST *create_arg_list(MPL *mpl); +/* create empty operands list */ + +#define expand_arg_list _glp_mpl_expand_arg_list +ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x); +/* append operand to operands list */ + +#define arg_list_len _glp_mpl_arg_list_len +int arg_list_len(MPL *mpl, ARG_LIST *list); +/* determine length of operands list */ + +#define subscript_list _glp_mpl_subscript_list +ARG_LIST *subscript_list(MPL *mpl); +/* parse subscript list */ + +#define object_reference _glp_mpl_object_reference +CODE *object_reference(MPL *mpl); +/* parse reference to named object */ + +#define numeric_argument _glp_mpl_numeric_argument +CODE *numeric_argument(MPL *mpl, char *func); +/* parse argument passed to built-in function */ + +#define symbolic_argument _glp_mpl_symbolic_argument +CODE *symbolic_argument(MPL *mpl, char *func); + +#define elemset_argument _glp_mpl_elemset_argument +CODE *elemset_argument(MPL *mpl, char *func); + +#define function_reference _glp_mpl_function_reference +CODE *function_reference(MPL *mpl); +/* parse reference to built-in function */ + +#define create_domain _glp_mpl_create_domain +DOMAIN *create_domain(MPL *mpl); +/* create empty domain */ + +#define create_block _glp_mpl_create_block +DOMAIN_BLOCK *create_block(MPL *mpl); +/* create empty domain block */ + +#define append_block _glp_mpl_append_block +void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block); +/* append domain block to specified domain */ + +#define append_slot _glp_mpl_append_slot +DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, + CODE *code); +/* create and append new slot to domain block */ + +#define expression_list _glp_mpl_expression_list +CODE *expression_list(MPL *mpl); +/* parse expression list */ + +#define literal_set _glp_mpl_literal_set +CODE *literal_set(MPL *mpl, CODE *code); +/* parse literal set */ + +#define indexing_expression _glp_mpl_indexing_expression +DOMAIN *indexing_expression(MPL *mpl); +/* parse indexing expression */ + +#define close_scope _glp_mpl_close_scope +void close_scope(MPL *mpl, DOMAIN *domain); +/* close scope of indexing expression */ + +#define iterated_expression _glp_mpl_iterated_expression +CODE *iterated_expression(MPL *mpl); +/* parse iterated expression */ + +#define domain_arity _glp_mpl_domain_arity +int domain_arity(MPL *mpl, DOMAIN *domain); +/* determine arity of domain */ + +#define set_expression _glp_mpl_set_expression +CODE *set_expression(MPL *mpl); +/* parse set expression */ + +#define branched_expression _glp_mpl_branched_expression +CODE *branched_expression(MPL *mpl); +/* parse conditional expression */ + +#define primary_expression _glp_mpl_primary_expression +CODE *primary_expression(MPL *mpl); +/* parse primary expression */ + +#define error_preceding _glp_mpl_error_preceding +void error_preceding(MPL *mpl, char *opstr); +/* raise error if preceding operand has wrong type */ + +#define error_following _glp_mpl_error_following +void error_following(MPL *mpl, char *opstr); +/* raise error if following operand has wrong type */ + +#define error_dimension _glp_mpl_error_dimension +void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2); +/* raise error if operands have different dimension */ + +#define expression_0 _glp_mpl_expression_0 +CODE *expression_0(MPL *mpl); +/* parse expression of level 0 */ + +#define expression_1 _glp_mpl_expression_1 +CODE *expression_1(MPL *mpl); +/* parse expression of level 1 */ + +#define expression_2 _glp_mpl_expression_2 +CODE *expression_2(MPL *mpl); +/* parse expression of level 2 */ + +#define expression_3 _glp_mpl_expression_3 +CODE *expression_3(MPL *mpl); +/* parse expression of level 3 */ + +#define expression_4 _glp_mpl_expression_4 +CODE *expression_4(MPL *mpl); +/* parse expression of level 4 */ + +#define expression_5 _glp_mpl_expression_5 +CODE *expression_5(MPL *mpl); +/* parse expression of level 5 */ + +#define expression_6 _glp_mpl_expression_6 +CODE *expression_6(MPL *mpl); +/* parse expression of level 6 */ + +#define expression_7 _glp_mpl_expression_7 +CODE *expression_7(MPL *mpl); +/* parse expression of level 7 */ + +#define expression_8 _glp_mpl_expression_8 +CODE *expression_8(MPL *mpl); +/* parse expression of level 8 */ + +#define expression_9 _glp_mpl_expression_9 +CODE *expression_9(MPL *mpl); +/* parse expression of level 9 */ + +#define expression_10 _glp_mpl_expression_10 +CODE *expression_10(MPL *mpl); +/* parse expression of level 10 */ + +#define expression_11 _glp_mpl_expression_11 +CODE *expression_11(MPL *mpl); +/* parse expression of level 11 */ + +#define expression_12 _glp_mpl_expression_12 +CODE *expression_12(MPL *mpl); +/* parse expression of level 12 */ + +#define expression_13 _glp_mpl_expression_13 +CODE *expression_13(MPL *mpl); +/* parse expression of level 13 */ + +#define set_statement _glp_mpl_set_statement +SET *set_statement(MPL *mpl); +/* parse set statement */ + +#define parameter_statement _glp_mpl_parameter_statement +PARAMETER *parameter_statement(MPL *mpl); +/* parse parameter statement */ + +#define variable_statement _glp_mpl_variable_statement +VARIABLE *variable_statement(MPL *mpl); +/* parse variable statement */ + +#define constraint_statement _glp_mpl_constraint_statement +CONSTRAINT *constraint_statement(MPL *mpl); +/* parse constraint statement */ + +#define objective_statement _glp_mpl_objective_statement +CONSTRAINT *objective_statement(MPL *mpl); +/* parse objective statement */ + +#define table_statement _glp_mpl_table_statement +TABLE *table_statement(MPL *mpl); +/* parse table statement */ + +#define solve_statement _glp_mpl_solve_statement +void *solve_statement(MPL *mpl); +/* parse solve statement */ + +#define check_statement _glp_mpl_check_statement +CHECK *check_statement(MPL *mpl); +/* parse check statement */ + +#define display_statement _glp_mpl_display_statement +DISPLAY *display_statement(MPL *mpl); +/* parse display statement */ + +#define printf_statement _glp_mpl_printf_statement +PRINTF *printf_statement(MPL *mpl); +/* parse printf statement */ + +#define for_statement _glp_mpl_for_statement +FOR *for_statement(MPL *mpl); +/* parse for statement */ + +#define end_statement _glp_mpl_end_statement +void end_statement(MPL *mpl); +/* parse end statement */ + +#define simple_statement _glp_mpl_simple_statement +STATEMENT *simple_statement(MPL *mpl, int spec); +/* parse simple statement */ + +#define model_section _glp_mpl_model_section +void model_section(MPL *mpl); +/* parse model section */ + +/**********************************************************************/ +/* * * PROCESSING DATA SECTION * * */ +/**********************************************************************/ + +#if 2 + 2 == 5 +struct SLICE /* see TUPLE */ +{ /* component of slice; the slice itself is associated with its + first component; slices are similar to n-tuples with exception + that some slice components (which are indicated by asterisks) + don't refer to any symbols */ + SYMBOL *sym; + /* symbol, which this component refers to; can be NULL */ + SLICE *next; + /* the next component of slice */ +}; +#endif + +#define create_slice _glp_mpl_create_slice +SLICE *create_slice(MPL *mpl); +/* create slice */ + +#define expand_slice _glp_mpl_expand_slice +SLICE *expand_slice +( MPL *mpl, + SLICE *slice, /* destroyed */ + SYMBOL *sym /* destroyed */ +); +/* append new component to slice */ + +#define slice_dimen _glp_mpl_slice_dimen +int slice_dimen +( MPL *mpl, + SLICE *slice /* not changed */ +); +/* determine dimension of slice */ + +#define slice_arity _glp_mpl_slice_arity +int slice_arity +( MPL *mpl, + SLICE *slice /* not changed */ +); +/* determine arity of slice */ + +#define fake_slice _glp_mpl_fake_slice +SLICE *fake_slice(MPL *mpl, int dim); +/* create fake slice of all asterisks */ + +#define delete_slice _glp_mpl_delete_slice +void delete_slice +( MPL *mpl, + SLICE *slice /* destroyed */ +); +/* delete slice */ + +#define is_number _glp_mpl_is_number +int is_number(MPL *mpl); +/* check if current token is number */ + +#define is_symbol _glp_mpl_is_symbol +int is_symbol(MPL *mpl); +/* check if current token is symbol */ + +#define is_literal _glp_mpl_is_literal +int is_literal(MPL *mpl, char *literal); +/* check if current token is given symbolic literal */ + +#define read_number _glp_mpl_read_number +double read_number(MPL *mpl); +/* read number */ + +#define read_symbol _glp_mpl_read_symbol +SYMBOL *read_symbol(MPL *mpl); +/* read symbol */ + +#define read_slice _glp_mpl_read_slice +SLICE *read_slice +( MPL *mpl, + char *name, /* not changed */ + int dim +); +/* read slice */ + +#define select_set _glp_mpl_select_set +SET *select_set +( MPL *mpl, + char *name /* not changed */ +); +/* select set to saturate it with elemental sets */ + +#define simple_format _glp_mpl_simple_format +void simple_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice /* not changed */ +); +/* read set data block in simple format */ + +#define matrix_format _glp_mpl_matrix_format +void matrix_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice, /* not changed */ + int tr +); +/* read set data block in matrix format */ + +#define set_data _glp_mpl_set_data +void set_data(MPL *mpl); +/* read set data */ + +#define select_parameter _glp_mpl_select_parameter +PARAMETER *select_parameter +( MPL *mpl, + char *name /* not changed */ +); +/* select parameter to saturate it with data */ + +#define set_default _glp_mpl_set_default +void set_default +( MPL *mpl, + PARAMETER *par, /* not changed */ + SYMBOL *altval /* destroyed */ +); +/* set default parameter value */ + +#define read_value _glp_mpl_read_value +MEMBER *read_value +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* destroyed */ +); +/* read value and assign it to parameter member */ + +#define plain_format _glp_mpl_plain_format +void plain_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice /* not changed */ +); +/* read parameter data block in plain format */ + +#define tabular_format _glp_mpl_tabular_format +void tabular_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice, /* not changed */ + int tr +); +/* read parameter data block in tabular format */ + +#define tabbing_format _glp_mpl_tabbing_format +void tabbing_format +( MPL *mpl, + SYMBOL *altval /* not changed */ +); +/* read parameter data block in tabbing format */ + +#define parameter_data _glp_mpl_parameter_data +void parameter_data(MPL *mpl); +/* read parameter data */ + +#define data_section _glp_mpl_data_section +void data_section(MPL *mpl); +/* read data section */ + +/**********************************************************************/ +/* * * FLOATING-POINT NUMBERS * * */ +/**********************************************************************/ + +#define fp_add _glp_mpl_fp_add +double fp_add(MPL *mpl, double x, double y); +/* floating-point addition */ + +#define fp_sub _glp_mpl_fp_sub +double fp_sub(MPL *mpl, double x, double y); +/* floating-point subtraction */ + +#define fp_less _glp_mpl_fp_less +double fp_less(MPL *mpl, double x, double y); +/* floating-point non-negative subtraction */ + +#define fp_mul _glp_mpl_fp_mul +double fp_mul(MPL *mpl, double x, double y); +/* floating-point multiplication */ + +#define fp_div _glp_mpl_fp_div +double fp_div(MPL *mpl, double x, double y); +/* floating-point division */ + +#define fp_idiv _glp_mpl_fp_idiv +double fp_idiv(MPL *mpl, double x, double y); +/* floating-point quotient of exact division */ + +#define fp_mod _glp_mpl_fp_mod +double fp_mod(MPL *mpl, double x, double y); +/* floating-point remainder of exact division */ + +#define fp_power _glp_mpl_fp_power +double fp_power(MPL *mpl, double x, double y); +/* floating-point exponentiation (raise to power) */ + +#define fp_exp _glp_mpl_fp_exp +double fp_exp(MPL *mpl, double x); +/* floating-point base-e exponential */ + +#define fp_log _glp_mpl_fp_log +double fp_log(MPL *mpl, double x); +/* floating-point natural logarithm */ + +#define fp_log10 _glp_mpl_fp_log10 +double fp_log10(MPL *mpl, double x); +/* floating-point common (decimal) logarithm */ + +#define fp_sqrt _glp_mpl_fp_sqrt +double fp_sqrt(MPL *mpl, double x); +/* floating-point square root */ + +#define fp_sin _glp_mpl_fp_sin +double fp_sin(MPL *mpl, double x); +/* floating-point trigonometric sine */ + +#define fp_cos _glp_mpl_fp_cos +double fp_cos(MPL *mpl, double x); +/* floating-point trigonometric cosine */ + +#define fp_tan _glp_mpl_fp_tan +double fp_tan(MPL *mpl, double x); +/* floating-point trigonometric tangent */ + +#define fp_atan _glp_mpl_fp_atan +double fp_atan(MPL *mpl, double x); +/* floating-point trigonometric arctangent */ + +#define fp_atan2 _glp_mpl_fp_atan2 +double fp_atan2(MPL *mpl, double y, double x); +/* floating-point trigonometric arctangent */ + +#define fp_round _glp_mpl_fp_round +double fp_round(MPL *mpl, double x, double n); +/* round floating-point value to n fractional digits */ + +#define fp_trunc _glp_mpl_fp_trunc +double fp_trunc(MPL *mpl, double x, double n); +/* truncate floating-point value to n fractional digits */ + +/**********************************************************************/ +/* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ +/**********************************************************************/ + +#define fp_irand224 _glp_mpl_fp_irand224 +double fp_irand224(MPL *mpl); +/* pseudo-random integer in the range [0, 2^24) */ + +#define fp_uniform01 _glp_mpl_fp_uniform01 +double fp_uniform01(MPL *mpl); +/* pseudo-random number in the range [0, 1) */ + +#define fp_uniform _glp_mpl_uniform +double fp_uniform(MPL *mpl, double a, double b); +/* pseudo-random number in the range [a, b) */ + +#define fp_normal01 _glp_mpl_fp_normal01 +double fp_normal01(MPL *mpl); +/* Gaussian random variate with mu = 0 and sigma = 1 */ + +#define fp_normal _glp_mpl_fp_normal +double fp_normal(MPL *mpl, double mu, double sigma); +/* Gaussian random variate with specified mu and sigma */ + +/**********************************************************************/ +/* * * DATE/TIME * * */ +/**********************************************************************/ + +#define fn_gmtime _glp_mpl_fn_gmtime +double fn_gmtime(MPL *mpl); +/* obtain the current calendar time (UTC) */ + +#define fn_str2time _glp_mpl_fn_str2time +double fn_str2time(MPL *mpl, const char *str, const char *fmt); +/* convert character string to the calendar time */ + +#define fn_time2str _glp_mpl_fn_time2str +void fn_time2str(MPL *mpl, char *str, double t, const char *fmt); +/* convert the calendar time to character string */ + +/**********************************************************************/ +/* * * CHARACTER STRINGS * * */ +/**********************************************************************/ + +#define create_string _glp_mpl_create_string +STRING *create_string +( MPL *mpl, + char buf[MAX_LENGTH+1] /* not changed */ +); +/* create character string */ + +#define copy_string _glp_mpl_copy_string +STRING *copy_string +( MPL *mpl, + STRING *str /* not changed */ +); +/* make copy of character string */ + +#define compare_strings _glp_mpl_compare_strings +int compare_strings +( MPL *mpl, + STRING *str1, /* not changed */ + STRING *str2 /* not changed */ +); +/* compare one character string with another */ + +#define fetch_string _glp_mpl_fetch_string +char *fetch_string +( MPL *mpl, + STRING *str, /* not changed */ + char buf[MAX_LENGTH+1] /* modified */ +); +/* extract content of character string */ + +#define delete_string _glp_mpl_delete_string +void delete_string +( MPL *mpl, + STRING *str /* destroyed */ +); +/* delete character string */ + +/**********************************************************************/ +/* * * SYMBOLS * * */ +/**********************************************************************/ + +struct SYMBOL +{ /* symbol (numeric or abstract quantity) */ + double num; + /* numeric value of symbol (used only if str == NULL) */ + STRING *str; + /* abstract value of symbol (used only if str != NULL) */ +}; + +#define create_symbol_num _glp_mpl_create_symbol_num +SYMBOL *create_symbol_num(MPL *mpl, double num); +/* create symbol of numeric type */ + +#define create_symbol_str _glp_mpl_create_symbol_str +SYMBOL *create_symbol_str +( MPL *mpl, + STRING *str /* destroyed */ +); +/* create symbol of abstract type */ + +#define copy_symbol _glp_mpl_copy_symbol +SYMBOL *copy_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +); +/* make copy of symbol */ + +#define compare_symbols _glp_mpl_compare_symbols +int compare_symbols +( MPL *mpl, + SYMBOL *sym1, /* not changed */ + SYMBOL *sym2 /* not changed */ +); +/* compare one symbol with another */ + +#define delete_symbol _glp_mpl_delete_symbol +void delete_symbol +( MPL *mpl, + SYMBOL *sym /* destroyed */ +); +/* delete symbol */ + +#define format_symbol _glp_mpl_format_symbol +char *format_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +); +/* format symbol for displaying or printing */ + +#define concat_symbols _glp_mpl_concat_symbols +SYMBOL *concat_symbols +( MPL *mpl, + SYMBOL *sym1, /* destroyed */ + SYMBOL *sym2 /* destroyed */ +); +/* concatenate one symbol with another */ + +/**********************************************************************/ +/* * * N-TUPLES * * */ +/**********************************************************************/ + +struct TUPLE +{ /* component of n-tuple; the n-tuple itself is associated with + its first component; (note that 0-tuple has no components) */ + SYMBOL *sym; + /* symbol, which the component refers to; cannot be NULL */ + TUPLE *next; + /* the next component of n-tuple */ +}; + +#define create_tuple _glp_mpl_create_tuple +TUPLE *create_tuple(MPL *mpl); +/* create n-tuple */ + +#define expand_tuple _glp_mpl_expand_tuple +TUPLE *expand_tuple +( MPL *mpl, + TUPLE *tuple, /* destroyed */ + SYMBOL *sym /* destroyed */ +); +/* append symbol to n-tuple */ + +#define tuple_dimen _glp_mpl_tuple_dimen +int tuple_dimen +( MPL *mpl, + TUPLE *tuple /* not changed */ +); +/* determine dimension of n-tuple */ + +#define copy_tuple _glp_mpl_copy_tuple +TUPLE *copy_tuple +( MPL *mpl, + TUPLE *tuple /* not changed */ +); +/* make copy of n-tuple */ + +#define compare_tuples _glp_mpl_compare_tuples +int compare_tuples +( MPL *mpl, + TUPLE *tuple1, /* not changed */ + TUPLE *tuple2 /* not changed */ +); +/* compare one n-tuple with another */ + +#define build_subtuple _glp_mpl_build_subtuple +TUPLE *build_subtuple +( MPL *mpl, + TUPLE *tuple, /* not changed */ + int dim +); +/* build subtuple of given n-tuple */ + +#define delete_tuple _glp_mpl_delete_tuple +void delete_tuple +( MPL *mpl, + TUPLE *tuple /* destroyed */ +); +/* delete n-tuple */ + +#define format_tuple _glp_mpl_format_tuple +char *format_tuple +( MPL *mpl, + int c, + TUPLE *tuple /* not changed */ +); +/* format n-tuple for displaying or printing */ + +/**********************************************************************/ +/* * * ELEMENTAL SETS * * */ +/**********************************************************************/ + +#if 2 + 2 == 5 +struct ELEMSET /* see ARRAY */ +{ /* elemental set of n-tuples; formally it is a "value" assigned + to members of model sets (like numbers and symbols, which are + values assigned to members of model parameters); note that a + simple model set is not an elemental set, it is 0-dimensional + array, the only member of which (if it exists) is assigned an + elemental set */ +#endif + +#define create_elemset _glp_mpl_create_elemset +ELEMSET *create_elemset(MPL *mpl, int dim); +/* create elemental set */ + +#define find_tuple _glp_mpl_find_tuple +MEMBER *find_tuple +( MPL *mpl, + ELEMSET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* check if elemental set contains given n-tuple */ + +#define add_tuple _glp_mpl_add_tuple +MEMBER *add_tuple +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* add new n-tuple to elemental set */ + +#define check_then_add _glp_mpl_check_then_add +MEMBER *check_then_add +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* check and add new n-tuple to elemental set */ + +#define copy_elemset _glp_mpl_copy_elemset +ELEMSET *copy_elemset +( MPL *mpl, + ELEMSET *set /* not changed */ +); +/* make copy of elemental set */ + +#define delete_elemset _glp_mpl_delete_elemset +void delete_elemset +( MPL *mpl, + ELEMSET *set /* destroyed */ +); +/* delete elemental set */ + +#define arelset_size _glp_mpl_arelset_size +int arelset_size(MPL *mpl, double t0, double tf, double dt); +/* compute size of "arithmetic" elemental set */ + +#define arelset_member _glp_mpl_arelset_member +double arelset_member(MPL *mpl, double t0, double tf, double dt, int j); +/* compute member of "arithmetic" elemental set */ + +#define create_arelset _glp_mpl_create_arelset +ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt); +/* create "arithmetic" elemental set */ + +#define set_union _glp_mpl_set_union +ELEMSET *set_union +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* union of two elemental sets */ + +#define set_diff _glp_mpl_set_diff +ELEMSET *set_diff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* difference between two elemental sets */ + +#define set_symdiff _glp_mpl_set_symdiff +ELEMSET *set_symdiff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* symmetric difference between two elemental sets */ + +#define set_inter _glp_mpl_set_inter +ELEMSET *set_inter +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* intersection of two elemental sets */ + +#define set_cross _glp_mpl_set_cross +ELEMSET *set_cross +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +); +/* cross (Cartesian) product of two elemental sets */ + +/**********************************************************************/ +/* * * ELEMENTAL VARIABLES * * */ +/**********************************************************************/ + +struct ELEMVAR +{ /* elemental variable; formally it is a "value" assigned to + members of model variables (like numbers and symbols, which + are values assigned to members of model parameters) */ + int j; + /* LP column number assigned to this elemental variable */ + VARIABLE *var; + /* model variable, which contains this elemental variable */ + MEMBER *memb; + /* array member, which is assigned this elemental variable */ + double lbnd; + /* lower bound */ + double ubnd; + /* upper bound */ + double temp; + /* working quantity used in operations on linear forms; normally + it contains floating-point zero */ +#if 1 /* 15/V-2010 */ + int stat; + double prim, dual; + /* solution components provided by the solver */ +#endif +}; + +/**********************************************************************/ +/* * * LINEAR FORMS * * */ +/**********************************************************************/ + +struct FORMULA +{ /* term of linear form c * x, where c is a coefficient, x is an + elemental variable; the linear form itself is the sum of terms + and is associated with its first term; (note that the linear + form may be empty that means the sum is equal to zero) */ + double coef; + /* coefficient at elemental variable or constant term */ + ELEMVAR *var; + /* reference to elemental variable; NULL means constant term */ + FORMULA *next; + /* the next term of linear form */ +}; + +#define constant_term _glp_mpl_constant_term +FORMULA *constant_term(MPL *mpl, double coef); +/* create constant term */ + +#define single_variable _glp_mpl_single_variable +FORMULA *single_variable +( MPL *mpl, + ELEMVAR *var /* referenced */ +); +/* create single variable */ + +#define copy_formula _glp_mpl_copy_formula +FORMULA *copy_formula +( MPL *mpl, + FORMULA *form /* not changed */ +); +/* make copy of linear form */ + +#define delete_formula _glp_mpl_delete_formula +void delete_formula +( MPL *mpl, + FORMULA *form /* destroyed */ +); +/* delete linear form */ + +#define linear_comb _glp_mpl_linear_comb +FORMULA *linear_comb +( MPL *mpl, + double a, FORMULA *fx, /* destroyed */ + double b, FORMULA *fy /* destroyed */ +); +/* linear combination of two linear forms */ + +#define remove_constant _glp_mpl_remove_constant +FORMULA *remove_constant +( MPL *mpl, + FORMULA *form, /* destroyed */ + double *coef /* modified */ +); +/* remove constant term from linear form */ + +#define reduce_terms _glp_mpl_reduce_terms +FORMULA *reduce_terms +( MPL *mpl, + FORMULA *form /* destroyed */ +); +/* reduce identical terms in linear form */ + +/**********************************************************************/ +/* * * ELEMENTAL CONSTRAINTS * * */ +/**********************************************************************/ + +struct ELEMCON +{ /* elemental constraint; formally it is a "value" assigned to + members of model constraints (like numbers or symbols, which + are values assigned to members of model parameters) */ + int i; + /* LP row number assigned to this elemental constraint */ + CONSTRAINT *con; + /* model constraint, which contains this elemental constraint */ + MEMBER *memb; + /* array member, which is assigned this elemental constraint */ + FORMULA *form; + /* linear form */ + double lbnd; + /* lower bound */ + double ubnd; + /* upper bound */ +#if 1 /* 15/V-2010 */ + int stat; + double prim, dual; + /* solution components provided by the solver */ +#endif +}; + +/**********************************************************************/ +/* * * GENERIC VALUES * * */ +/**********************************************************************/ + +union VALUE +{ /* generic value, which can be assigned to object member or be a + result of evaluation of expression */ + /* indicator that specifies the particular type of generic value + is stored in the corresponding array or pseudo-code descriptor + and can be one of the following: + A_NONE - no value + A_NUMERIC - floating-point number + A_SYMBOLIC - symbol + A_LOGICAL - logical value + A_TUPLE - n-tuple + A_ELEMSET - elemental set + A_ELEMVAR - elemental variable + A_FORMULA - linear form + A_ELEMCON - elemental constraint */ + void *none; /* null */ + double num; /* value */ + SYMBOL *sym; /* value */ + int bit; /* value */ + TUPLE *tuple; /* value */ + ELEMSET *set; /* value */ + ELEMVAR *var; /* reference */ + FORMULA *form; /* value */ + ELEMCON *con; /* reference */ +}; + +#define delete_value _glp_mpl_delete_value +void delete_value +( MPL *mpl, + int type, + VALUE *value /* content destroyed */ +); +/* delete generic value */ + +/**********************************************************************/ +/* * * SYMBOLICALLY INDEXED ARRAYS * * */ +/**********************************************************************/ + +struct ARRAY +{ /* multi-dimensional array, a set of members indexed over simple + or compound sets of symbols; arrays are used to represent the + contents of model objects (i.e. sets, parameters, variables, + constraints, and objectives); arrays also are used as "values" + that are assigned to members of set objects, in which case the + array itself represents an elemental set */ + int type; + /* type of generic values assigned to the array members: + A_NONE - none (members have no assigned values) + A_NUMERIC - floating-point numbers + A_SYMBOLIC - symbols + A_ELEMSET - elemental sets + A_ELEMVAR - elemental variables + A_ELEMCON - elemental constraints */ + int dim; + /* dimension of the array that determines number of components in + n-tuples for all members of the array, dim >= 0; dim = 0 means + the array is 0-dimensional */ + int size; + /* size of the array, i.e. number of its members */ + MEMBER *head; + /* the first array member; NULL means the array is empty */ + MEMBER *tail; + /* the last array member; NULL means the array is empty */ + AVL *tree; + /* the search tree intended to find array members for logarithmic + time; NULL means the search tree doesn't exist */ + ARRAY *prev; + /* the previous array in the translator database */ + ARRAY *next; + /* the next array in the translator database */ +}; + +struct MEMBER +{ /* array member */ + TUPLE *tuple; + /* n-tuple, which identifies the member; number of its components + is the same for all members within the array and determined by + the array dimension; duplicate members are not allowed */ + MEMBER *next; + /* the next array member */ + VALUE value; + /* generic value assigned to the member */ +}; + +#define create_array _glp_mpl_create_array +ARRAY *create_array(MPL *mpl, int type, int dim); +/* create array */ + +#define find_member _glp_mpl_find_member +MEMBER *find_member +( MPL *mpl, + ARRAY *array, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* find array member with given n-tuple */ + +#define add_member _glp_mpl_add_member +MEMBER *add_member +( MPL *mpl, + ARRAY *array, /* modified */ + TUPLE *tuple /* destroyed */ +); +/* add new member to array */ + +#define delete_array _glp_mpl_delete_array +void delete_array +( MPL *mpl, + ARRAY *array /* destroyed */ +); +/* delete array */ + +/**********************************************************************/ +/* * * DOMAINS AND DUMMY INDICES * * */ +/**********************************************************************/ + +struct DOMAIN +{ /* domain (a simple or compound set); syntactically domain looks + like '{ i in I, (j,k) in S, t in T : }'; domains + are used to define sets, over which model objects are indexed, + and also as constituents of iterated operators */ + DOMAIN_BLOCK *list; + /* linked list of domain blocks (in the example above such blocks + are 'i in I', '(j,k) in S', and 't in T'); this list cannot be + empty */ + CODE *code; + /* pseudo-code for computing the logical predicate, which follows + the colon; NULL means no predicate is specified */ +}; + +struct DOMAIN_BLOCK +{ /* domain block; syntactically domain blocks look like 'i in I', + '(j,k) in S', and 't in T' in the example above (in the sequel + sets like I, S, and T are called basic sets) */ + DOMAIN_SLOT *list; + /* linked list of domain slots (i.e. indexing positions); number + of slots in this list is the same as dimension of n-tuples in + the basic set; this list cannot be empty */ + CODE *code; + /* pseudo-code for computing basic set; cannot be NULL */ + TUPLE *backup; + /* if this n-tuple is not empty, current values of dummy indices + in the domain block are the same as components of this n-tuple + (note that this n-tuple may have larger dimension than number + of dummy indices in this block, in which case extra components + are ignored); this n-tuple is used to restore former values of + dummy indices, if they were changed due to recursive calls to + the domain block */ + DOMAIN_BLOCK *next; + /* the next block in the same domain */ +}; + +struct DOMAIN_SLOT +{ /* domain slot; it specifies an individual indexing position and + defines the corresponding dummy index */ + char *name; + /* symbolic name of the dummy index; null pointer means the dummy + index is not explicitly specified */ + CODE *code; + /* pseudo-code for computing symbolic value, at which the dummy + index is bound; NULL means the dummy index is free within the + domain scope */ + SYMBOL *value; + /* current value assigned to the dummy index; NULL means no value + is assigned at the moment */ + CODE *list; + /* linked list of pseudo-codes with operation O_INDEX referring + to this slot; this linked list is used to invalidate resultant + values of the operation, which depend on this dummy index */ + DOMAIN_SLOT *next; + /* the next slot in the same domain block */ +}; + +#define assign_dummy_index _glp_mpl_assign_dummy_index +void assign_dummy_index +( MPL *mpl, + DOMAIN_SLOT *slot, /* modified */ + SYMBOL *value /* not changed */ +); +/* assign new value to dummy index */ + +#define update_dummy_indices _glp_mpl_update_dummy_indices +void update_dummy_indices +( MPL *mpl, + DOMAIN_BLOCK *block /* not changed */ +); +/* update current values of dummy indices */ + +#define enter_domain_block _glp_mpl_enter_domain_block +int enter_domain_block +( MPL *mpl, + DOMAIN_BLOCK *block, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +); +/* enter domain block */ + +#define eval_within_domain _glp_mpl_eval_within_domain +int eval_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +); +/* perform evaluation within domain scope */ + +#define loop_within_domain _glp_mpl_loop_within_domain +void loop_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + void *info, int (*func)(MPL *mpl, void *info) +); +/* perform iterations within domain scope */ + +#define out_of_domain _glp_mpl_out_of_domain +void out_of_domain +( MPL *mpl, + char *name, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* raise domain exception */ + +#define get_domain_tuple _glp_mpl_get_domain_tuple +TUPLE *get_domain_tuple +( MPL *mpl, + DOMAIN *domain /* not changed */ +); +/* obtain current n-tuple from domain */ + +#define clean_domain _glp_mpl_clean_domain +void clean_domain(MPL *mpl, DOMAIN *domain); +/* clean domain */ + +/**********************************************************************/ +/* * * MODEL SETS * * */ +/**********************************************************************/ + +struct SET +{ /* model set */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) set, dim > 0 means set of sets */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional set */ + int dimen; + /* dimension of n-tuples, which members of this set consist of + (note that the model set itself is an array of elemental sets, + which are its members; so, don't confuse this dimension with + dimension of the model set); always non-zero */ + WITHIN *within; + /* list of supersets, which restrict each member of the set to be + in every superset from this list; this list can be empty */ + CODE *assign; + /* pseudo-code for computing assigned value; can be NULL */ + CODE *option; + /* pseudo-code for computing default value; can be NULL */ + GADGET *gadget; + /* plain set used to initialize the array of sets; can be NULL */ + int data; + /* data status flag: + 0 - no data are provided in the data section + 1 - data are provided, but not checked yet + 2 - data are provided and have been checked */ + ARRAY *array; + /* array of members, which are assigned elemental sets */ +}; + +struct WITHIN +{ /* restricting superset list entry */ + CODE *code; + /* pseudo-code for computing the superset; cannot be NULL */ + WITHIN *next; + /* the next entry for the same set or parameter */ +}; + +struct GADGET +{ /* plain set used to initialize the array of sets with data */ + SET *set; + /* pointer to plain set; cannot be NULL */ + int ind[20]; /* ind[dim+dimen]; */ + /* permutation of integers 1, 2, ..., dim+dimen */ +}; + +#define check_elem_set _glp_mpl_check_elem_set +void check_elem_set +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple, /* not changed */ + ELEMSET *refer /* not changed */ +); +/* check elemental set assigned to set member */ + +#define take_member_set _glp_mpl_take_member_set +ELEMSET *take_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain elemental set assigned to set member */ + +#define eval_member_set _glp_mpl_eval_member_set +ELEMSET *eval_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate elemental set assigned to set member */ + +#define eval_whole_set _glp_mpl_eval_whole_set +void eval_whole_set(MPL *mpl, SET *set); +/* evaluate model set over entire domain */ + +#define clean_set _glp_mpl_clean_set +void clean_set(MPL *mpl, SET *set); +/* clean model set */ + +/**********************************************************************/ +/* * * MODEL PARAMETERS * * */ +/**********************************************************************/ + +struct PARAMETER +{ /* model parameter */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) parameter */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional parameter */ + int type; + /* parameter type: + A_NUMERIC - numeric + A_INTEGER - integer + A_BINARY - binary + A_SYMBOLIC - symbolic */ + CONDITION *cond; + /* list of conditions, which restrict each parameter member to + satisfy to every condition from this list; this list is used + only for numeric parameters and can be empty */ + WITHIN *in; + /* list of supersets, which restrict each parameter member to be + in every superset from this list; this list is used only for + symbolic parameters and can be empty */ + CODE *assign; + /* pseudo-code for computing assigned value; can be NULL */ + CODE *option; + /* pseudo-code for computing default value; can be NULL */ + int data; + /* data status flag: + 0 - no data are provided in the data section + 1 - data are provided, but not checked yet + 2 - data are provided and have been checked */ + SYMBOL *defval; + /* default value provided in the data section; can be NULL */ + ARRAY *array; + /* array of members, which are assigned numbers or symbols */ +}; + +struct CONDITION +{ /* restricting condition list entry */ + int rho; + /* flag that specifies the form of the condition: + O_LT - less than + O_LE - less than or equal to + O_EQ - equal to + O_GE - greater than or equal to + O_GT - greater than + O_NE - not equal to */ + CODE *code; + /* pseudo-code for computing the reference value */ + CONDITION *next; + /* the next entry for the same parameter */ +}; + +#define check_value_num _glp_mpl_check_value_num +void check_value_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + double value +); +/* check numeric value assigned to parameter member */ + +#define take_member_num _glp_mpl_take_member_num +double take_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain numeric value assigned to parameter member */ + +#define eval_member_num _glp_mpl_eval_member_num +double eval_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate numeric value assigned to parameter member */ + +#define check_value_sym _glp_mpl_check_value_sym +void check_value_sym +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + SYMBOL *value /* not changed */ +); +/* check symbolic value assigned to parameter member */ + +#define take_member_sym _glp_mpl_take_member_sym +SYMBOL *take_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain symbolic value assigned to parameter member */ + +#define eval_member_sym _glp_mpl_eval_member_sym +SYMBOL *eval_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate symbolic value assigned to parameter member */ + +#define eval_whole_par _glp_mpl_eval_whole_par +void eval_whole_par(MPL *mpl, PARAMETER *par); +/* evaluate model parameter over entire domain */ + +#define clean_parameter _glp_mpl_clean_parameter +void clean_parameter(MPL *mpl, PARAMETER *par); +/* clean model parameter */ + +/**********************************************************************/ +/* * * MODEL VARIABLES * * */ +/**********************************************************************/ + +struct VARIABLE +{ /* model variable */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) variable */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional variable */ + int type; + /* variable type: + A_NUMERIC - continuous + A_INTEGER - integer + A_BINARY - binary */ + CODE *lbnd; + /* pseudo-code for computing lower bound; NULL means lower bound + is not specified */ + CODE *ubnd; + /* pseudo-code for computing upper bound; NULL means upper bound + is not specified */ + /* if both the pointers lbnd and ubnd refer to the same code, the + variable is fixed at the corresponding value */ + ARRAY *array; + /* array of members, which are assigned elemental variables */ +}; + +#define take_member_var _glp_mpl_take_member_var +ELEMVAR *take_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain reference to elemental variable */ + +#define eval_member_var _glp_mpl_eval_member_var +ELEMVAR *eval_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate reference to elemental variable */ + +#define eval_whole_var _glp_mpl_eval_whole_var +void eval_whole_var(MPL *mpl, VARIABLE *var); +/* evaluate model variable over entire domain */ + +#define clean_variable _glp_mpl_clean_variable +void clean_variable(MPL *mpl, VARIABLE *var); +/* clean model variable */ + +/**********************************************************************/ +/* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ +/**********************************************************************/ + +struct CONSTRAINT +{ /* model constraint or objective */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int dim; /* aka arity */ + /* dimension (number of subscripts); dim = 0 means 0-dimensional + (unsubscripted) constraint */ + DOMAIN *domain; + /* subscript domain; NULL for 0-dimensional constraint */ + int type; + /* constraint type: + A_CONSTRAINT - constraint + A_MINIMIZE - objective (minimization) + A_MAXIMIZE - objective (maximization) */ + CODE *code; + /* pseudo-code for computing main linear form; cannot be NULL */ + CODE *lbnd; + /* pseudo-code for computing lower bound; NULL means lower bound + is not specified */ + CODE *ubnd; + /* pseudo-code for computing upper bound; NULL means upper bound + is not specified */ + /* if both the pointers lbnd and ubnd refer to the same code, the + constraint has the form of equation */ + ARRAY *array; + /* array of members, which are assigned elemental constraints */ +}; + +#define take_member_con _glp_mpl_take_member_con +ELEMCON *take_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* obtain reference to elemental constraint */ + +#define eval_member_con _glp_mpl_eval_member_con +ELEMCON *eval_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +); +/* evaluate reference to elemental constraint */ + +#define eval_whole_con _glp_mpl_eval_whole_con +void eval_whole_con(MPL *mpl, CONSTRAINT *con); +/* evaluate model constraint over entire domain */ + +#define clean_constraint _glp_mpl_clean_constraint +void clean_constraint(MPL *mpl, CONSTRAINT *con); +/* clean model constraint */ + +/**********************************************************************/ +/* * * DATA TABLES * * */ +/**********************************************************************/ + +struct TABLE +{ /* data table */ + char *name; + /* symbolic name; cannot be NULL */ + char *alias; + /* alias; NULL means alias is not specified */ + int type; + /* table type: + A_INPUT - input table + A_OUTPUT - output table */ + TABARG *arg; + /* argument list; cannot be empty */ + union + { struct + { SET *set; + /* input set; NULL means the set is not specified */ + TABFLD *fld; + /* field list; cannot be empty */ + TABIN *list; + /* input list; can be empty */ + } in; + struct + { DOMAIN *domain; + /* subscript domain; cannot be NULL */ + TABOUT *list; + /* output list; cannot be empty */ + } out; + } u; +}; + +struct TABARG +{ /* table argument list entry */ + CODE *code; + /* pseudo-code for computing the argument */ + TABARG *next; + /* next entry for the same table */ +}; + +struct TABFLD +{ /* table field list entry */ + char *name; + /* field name; cannot be NULL */ + TABFLD *next; + /* next entry for the same table */ +}; + +struct TABIN +{ /* table input list entry */ + PARAMETER *par; + /* parameter to be read; cannot be NULL */ + char *name; + /* column name; cannot be NULL */ + TABIN *next; + /* next entry for the same table */ +}; + +struct TABOUT +{ /* table output list entry */ + CODE *code; + /* pseudo-code for computing the value to be written */ + char *name; + /* column name; cannot be NULL */ + TABOUT *next; + /* next entry for the same table */ +}; + +struct TABDCA +{ /* table driver communication area */ + int id; + /* driver identifier (set by mpl_tab_drv_open) */ + void *link; + /* driver link pointer (set by mpl_tab_drv_open) */ + int na; + /* number of arguments */ + char **arg; /* char *arg[1+ns]; */ + /* arg[k], 1 <= k <= ns, is pointer to k-th argument */ + int nf; + /* number of fields */ + char **name; /* char *name[1+nc]; */ + /* name[k], 1 <= k <= nc, is name of k-th field */ + int *type; /* int type[1+nc]; */ + /* type[k], 1 <= k <= nc, is type of k-th field: + '?' - value not assigned + 'N' - number + 'S' - character string */ + double *num; /* double num[1+nc]; */ + /* num[k], 1 <= k <= nc, is numeric value of k-th field */ + char **str; + /* str[k], 1 <= k <= nc, is string value of k-th field */ +}; + +#define mpl_tab_num_args _glp_mpl_tab_num_args +int mpl_tab_num_args(TABDCA *dca); + +#define mpl_tab_get_arg _glp_mpl_tab_get_arg +const char *mpl_tab_get_arg(TABDCA *dca, int k); + +#define mpl_tab_num_flds _glp_mpl_tab_num_flds +int mpl_tab_num_flds(TABDCA *dca); + +#define mpl_tab_get_name _glp_mpl_tab_get_name +const char *mpl_tab_get_name(TABDCA *dca, int k); + +#define mpl_tab_get_type _glp_mpl_tab_get_type +int mpl_tab_get_type(TABDCA *dca, int k); + +#define mpl_tab_get_num _glp_mpl_tab_get_num +double mpl_tab_get_num(TABDCA *dca, int k); + +#define mpl_tab_get_str _glp_mpl_tab_get_str +const char *mpl_tab_get_str(TABDCA *dca, int k); + +#define mpl_tab_set_num _glp_mpl_tab_set_num +void mpl_tab_set_num(TABDCA *dca, int k, double num); + +#define mpl_tab_set_str _glp_mpl_tab_set_str +void mpl_tab_set_str(TABDCA *dca, int k, const char *str); + +#define mpl_tab_drv_open _glp_mpl_tab_drv_open +void mpl_tab_drv_open(MPL *mpl, int mode); + +#define mpl_tab_drv_read _glp_mpl_tab_drv_read +int mpl_tab_drv_read(MPL *mpl); + +#define mpl_tab_drv_write _glp_mpl_tab_drv_write +void mpl_tab_drv_write(MPL *mpl); + +#define mpl_tab_drv_close _glp_mpl_tab_drv_close +void mpl_tab_drv_close(MPL *mpl); + +/**********************************************************************/ +/* * * PSEUDO-CODE * * */ +/**********************************************************************/ + +union OPERANDS +{ /* operands that participate in pseudo-code operation (choice of + particular operands depends on the operation code) */ + /*--------------------------------------------------------------*/ + double num; /* O_NUMBER */ + /* floaing-point number to be taken */ + /*--------------------------------------------------------------*/ + char *str; /* O_STRING */ + /* character string to be taken */ + /*--------------------------------------------------------------*/ + struct /* O_INDEX */ + { DOMAIN_SLOT *slot; + /* domain slot, which contains dummy index to be taken */ + CODE *next; + /* the next pseudo-code with op = O_INDEX, which refers to the + same slot as this one; pointer to the beginning of this list + is stored in the corresponding domain slot */ + } index; + /*--------------------------------------------------------------*/ + struct /* O_MEMNUM, O_MEMSYM */ + { PARAMETER *par; + /* model parameter, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional parameter */ + } par; + /*--------------------------------------------------------------*/ + struct /* O_MEMSET */ + { SET *set; + /* model set, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional set */ + } set; + /*--------------------------------------------------------------*/ + struct /* O_MEMVAR */ + { VARIABLE *var; + /* model variable, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripts; NULL for 0-dimensional variable */ +#if 1 /* 15/V-2010 */ + int suff; + /* suffix specified: */ +#define DOT_NONE 0x00 /* none (means variable itself) */ +#define DOT_LB 0x01 /* .lb (lower bound) */ +#define DOT_UB 0x02 /* .ub (upper bound) */ +#define DOT_STATUS 0x03 /* .status (status) */ +#define DOT_VAL 0x04 /* .val (primal value) */ +#define DOT_DUAL 0x05 /* .dual (dual value) */ +#endif + } var; +#if 1 /* 15/V-2010 */ + /*--------------------------------------------------------------*/ + struct /* O_MEMCON */ + { CONSTRAINT *con; + /* model constraint, which contains member to be taken */ + ARG_LIST *list; + /* list of subscripys; NULL for 0-dimensional constraint */ + int suff; + /* suffix specified (see O_MEMVAR above) */ + } con; +#endif + /*--------------------------------------------------------------*/ + ARG_LIST *list; /* O_TUPLE, O_MAKE, n-ary operations */ + /* list of operands */ + /*--------------------------------------------------------------*/ + DOMAIN_BLOCK *slice; /* O_SLICE */ + /* domain block, which specifies slice (i.e. n-tuple that contains + free dummy indices); this operation is never evaluated */ + /*--------------------------------------------------------------*/ + struct /* unary, binary, ternary operations */ + { CODE *x; + /* pseudo-code for computing first operand */ + CODE *y; + /* pseudo-code for computing second operand */ + CODE *z; + /* pseudo-code for computing third operand */ + } arg; + /*--------------------------------------------------------------*/ + struct /* iterated operations */ + { DOMAIN *domain; + /* domain, over which the operation is performed */ + CODE *x; + /* pseudo-code for computing "integrand" */ + } loop; + /*--------------------------------------------------------------*/ +}; + +struct ARG_LIST +{ /* operands list entry */ + CODE *x; + /* pseudo-code for computing operand */ + ARG_LIST *next; + /* the next operand of the same operation */ +}; + +struct CODE +{ /* pseudo-code (internal form of expressions) */ + int op; + /* operation code: */ +#define O_NUMBER 301 /* take floating-point number */ +#define O_STRING 302 /* take character string */ +#define O_INDEX 303 /* take dummy index */ +#define O_MEMNUM 304 /* take member of numeric parameter */ +#define O_MEMSYM 305 /* take member of symbolic parameter */ +#define O_MEMSET 306 /* take member of set */ +#define O_MEMVAR 307 /* take member of variable */ +#define O_MEMCON 308 /* take member of constraint */ +#define O_TUPLE 309 /* make n-tuple */ +#define O_MAKE 310 /* make elemental set of n-tuples */ +#define O_SLICE 311 /* define domain block (dummy op) */ + /* 0-ary operations --------------------*/ +#define O_IRAND224 312 /* pseudo-random in [0, 2^24-1] */ +#define O_UNIFORM01 313 /* pseudo-random in [0, 1) */ +#define O_NORMAL01 314 /* gaussian random, mu = 0, sigma = 1 */ +#define O_GMTIME 315 /* current calendar time (UTC) */ + /* unary operations --------------------*/ +#define O_CVTNUM 316 /* conversion to numeric */ +#define O_CVTSYM 317 /* conversion to symbolic */ +#define O_CVTLOG 318 /* conversion to logical */ +#define O_CVTTUP 319 /* conversion to 1-tuple */ +#define O_CVTLFM 320 /* conversion to linear form */ +#define O_PLUS 321 /* unary plus */ +#define O_MINUS 322 /* unary minus */ +#define O_NOT 323 /* negation (logical "not") */ +#define O_ABS 324 /* absolute value */ +#define O_CEIL 325 /* round upward ("ceiling of x") */ +#define O_FLOOR 326 /* round downward ("floor of x") */ +#define O_EXP 327 /* base-e exponential */ +#define O_LOG 328 /* natural logarithm */ +#define O_LOG10 329 /* common (decimal) logarithm */ +#define O_SQRT 330 /* square root */ +#define O_SIN 331 /* trigonometric sine */ +#define O_COS 332 /* trigonometric cosine */ +#define O_TAN 333 /* trigonometric tangent */ +#define O_ATAN 334 /* trigonometric arctangent */ +#define O_ROUND 335 /* round to nearest integer */ +#define O_TRUNC 336 /* truncate to nearest integer */ +#define O_CARD 337 /* cardinality of set */ +#define O_LENGTH 338 /* length of symbolic value */ + /* binary operations -------------------*/ +#define O_ADD 339 /* addition */ +#define O_SUB 340 /* subtraction */ +#define O_LESS 341 /* non-negative subtraction */ +#define O_MUL 342 /* multiplication */ +#define O_DIV 343 /* division */ +#define O_IDIV 344 /* quotient of exact division */ +#define O_MOD 345 /* remainder of exact division */ +#define O_POWER 346 /* exponentiation (raise to power) */ +#define O_ATAN2 347 /* trigonometric arctangent */ +#define O_ROUND2 348 /* round to n fractional digits */ +#define O_TRUNC2 349 /* truncate to n fractional digits */ +#define O_UNIFORM 350 /* pseudo-random in [a, b) */ +#define O_NORMAL 351 /* gaussian random, given mu and sigma */ +#define O_CONCAT 352 /* concatenation */ +#define O_LT 353 /* comparison on 'less than' */ +#define O_LE 354 /* comparison on 'not greater than' */ +#define O_EQ 355 /* comparison on 'equal to' */ +#define O_GE 356 /* comparison on 'not less than' */ +#define O_GT 357 /* comparison on 'greater than' */ +#define O_NE 358 /* comparison on 'not equal to' */ +#define O_AND 359 /* conjunction (logical "and") */ +#define O_OR 360 /* disjunction (logical "or") */ +#define O_UNION 361 /* union */ +#define O_DIFF 362 /* difference */ +#define O_SYMDIFF 363 /* symmetric difference */ +#define O_INTER 364 /* intersection */ +#define O_CROSS 365 /* cross (Cartesian) product */ +#define O_IN 366 /* test on 'x in Y' */ +#define O_NOTIN 367 /* test on 'x not in Y' */ +#define O_WITHIN 368 /* test on 'X within Y' */ +#define O_NOTWITHIN 369 /* test on 'X not within Y' */ +#define O_SUBSTR 370 /* substring */ +#define O_STR2TIME 371 /* convert string to time */ +#define O_TIME2STR 372 /* convert time to string */ + /* ternary operations ------------------*/ +#define O_DOTS 373 /* build "arithmetic" set */ +#define O_FORK 374 /* if-then-else */ +#define O_SUBSTR3 375 /* substring */ + /* n-ary operations --------------------*/ +#define O_MIN 376 /* minimal value (n-ary) */ +#define O_MAX 377 /* maximal value (n-ary) */ + /* iterated operations -----------------*/ +#define O_SUM 378 /* summation */ +#define O_PROD 379 /* multiplication */ +#define O_MINIMUM 380 /* minimum */ +#define O_MAXIMUM 381 /* maximum */ +#define O_FORALL 382 /* conjunction (A-quantification) */ +#define O_EXISTS 383 /* disjunction (E-quantification) */ +#define O_SETOF 384 /* compute elemental set */ +#define O_BUILD 385 /* build elemental set */ + OPERANDS arg; + /* operands that participate in the operation */ + int type; + /* type of the resultant value: + A_NUMERIC - numeric + A_SYMBOLIC - symbolic + A_LOGICAL - logical + A_TUPLE - n-tuple + A_ELEMSET - elemental set + A_FORMULA - linear form */ + int dim; + /* dimension of the resultant value; for A_TUPLE and A_ELEMSET it + is the dimension of the corresponding n-tuple(s) and cannot be + zero; for other resultant types it is always zero */ + CODE *up; + /* parent pseudo-code, which refers to this pseudo-code as to its + operand; NULL means this pseudo-code has no parent and defines + an expression, which is not contained in another expression */ + int vflag; + /* volatile flag; being set this flag means that this operation + has a side effect; for primary expressions this flag is set + directly by corresponding parsing routines (for example, if + primary expression is a reference to a function that generates + pseudo-random numbers); in other cases this flag is inherited + from operands */ + int valid; + /* if this flag is set, the resultant value, which is a temporary + result of evaluating this operation on particular values of + operands, is valid; if this flag is clear, the resultant value + doesn't exist and therefore not valid; having been evaluated + the resultant value is stored here and not destroyed until the + dummy indices, which this value depends on, have been changed + (and if it doesn't depend on dummy indices at all, it is never + destroyed); thus, if the resultant value is valid, evaluating + routine can immediately take its copy not computing the result + from scratch; this mechanism is similar to moving invariants + out of loops and allows improving efficiency at the expense of + some extra memory needed to keep temporary results */ + /* however, if the volatile flag (see above) is set, even if the + resultant value is valid, evaluating routine computes it as if + it were not valid, i.e. caching is not used in this case */ + VALUE value; + /* resultant value in generic format */ +}; + +#define eval_numeric _glp_mpl_eval_numeric +double eval_numeric(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine numeric value */ + +#define eval_symbolic _glp_mpl_eval_symbolic +SYMBOL *eval_symbolic(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine symbolic value */ + +#define eval_logical _glp_mpl_eval_logical +int eval_logical(MPL *mpl, CODE *code); +/* evaluate pseudo-code to determine logical value */ + +#define eval_tuple _glp_mpl_eval_tuple +TUPLE *eval_tuple(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct n-tuple */ + +#define eval_elemset _glp_mpl_eval_elemset +ELEMSET *eval_elemset(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct elemental set */ + +#define is_member _glp_mpl_is_member +int is_member(MPL *mpl, CODE *code, TUPLE *tuple); +/* check if n-tuple is in set specified by pseudo-code */ + +#define eval_formula _glp_mpl_eval_formula +FORMULA *eval_formula(MPL *mpl, CODE *code); +/* evaluate pseudo-code to construct linear form */ + +#define clean_code _glp_mpl_clean_code +void clean_code(MPL *mpl, CODE *code); +/* clean pseudo-code */ + +/**********************************************************************/ +/* * * MODEL STATEMENTS * * */ +/**********************************************************************/ + +struct CHECK +{ /* check statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + CODE *code; + /* code for computing the predicate to be checked */ +}; + +struct DISPLAY +{ /* display statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + DISPLAY1 *list; + /* display list; cannot be empty */ +}; + +struct DISPLAY1 +{ /* display list entry */ + int type; + /* item type: + A_INDEX - dummy index + A_SET - model set + A_PARAMETER - model parameter + A_VARIABLE - model variable + A_CONSTRAINT - model constraint/objective + A_EXPRESSION - expression */ + union + { DOMAIN_SLOT *slot; + SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + CODE *code; + } u; + /* item to be displayed */ +#if 0 /* 15/V-2010 */ + ARG_LIST *list; + /* optional subscript list (for constraint/objective only) */ +#endif + DISPLAY1 *next; + /* the next entry for the same statement */ +}; + +struct PRINTF +{ /* printf statement */ + DOMAIN *domain; + /* subscript domain; NULL means domain is not used */ + CODE *fmt; + /* pseudo-code for computing format string */ + PRINTF1 *list; + /* printf list; can be empty */ + CODE *fname; + /* pseudo-code for computing filename to redirect the output; + NULL means the output goes to stdout */ + int app; + /* if this flag is set, the output is appended */ +}; + +struct PRINTF1 +{ /* printf list entry */ + CODE *code; + /* pseudo-code for computing value to be printed */ + PRINTF1 *next; + /* the next entry for the same statement */ +}; + +struct FOR +{ /* for statement */ + DOMAIN *domain; + /* subscript domain; cannot be NULL */ + STATEMENT *list; + /* linked list of model statements within this for statement in + the original order */ +}; + +struct STATEMENT +{ /* model statement */ + int line; + /* number of source text line, where statement begins */ + int type; + /* statement type: + A_SET - set statement + A_PARAMETER - parameter statement + A_VARIABLE - variable statement + A_CONSTRAINT - constraint/objective statement + A_TABLE - table statement + A_SOLVE - solve statement + A_CHECK - check statement + A_DISPLAY - display statement + A_PRINTF - printf statement + A_FOR - for statement */ + union + { SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + TABLE *tab; + void *slv; /* currently not used (set to NULL) */ + CHECK *chk; + DISPLAY *dpy; + PRINTF *prt; + FOR *fur; + } u; + /* specific part of statement */ + STATEMENT *next; + /* the next statement; in this list statements follow in the same + order as they appear in the model section */ +}; + +#define execute_table _glp_mpl_execute_table +void execute_table(MPL *mpl, TABLE *tab); +/* execute table statement */ + +#define free_dca _glp_mpl_free_dca +void free_dca(MPL *mpl); +/* free table driver communucation area */ + +#define clean_table _glp_mpl_clean_table +void clean_table(MPL *mpl, TABLE *tab); +/* clean table statement */ + +#define execute_check _glp_mpl_execute_check +void execute_check(MPL *mpl, CHECK *chk); +/* execute check statement */ + +#define clean_check _glp_mpl_clean_check +void clean_check(MPL *mpl, CHECK *chk); +/* clean check statement */ + +#define execute_display _glp_mpl_execute_display +void execute_display(MPL *mpl, DISPLAY *dpy); +/* execute display statement */ + +#define clean_display _glp_mpl_clean_display +void clean_display(MPL *mpl, DISPLAY *dpy); +/* clean display statement */ + +#define execute_printf _glp_mpl_execute_printf +void execute_printf(MPL *mpl, PRINTF *prt); +/* execute printf statement */ + +#define clean_printf _glp_mpl_clean_printf +void clean_printf(MPL *mpl, PRINTF *prt); +/* clean printf statement */ + +#define execute_for _glp_mpl_execute_for +void execute_for(MPL *mpl, FOR *fur); +/* execute for statement */ + +#define clean_for _glp_mpl_clean_for +void clean_for(MPL *mpl, FOR *fur); +/* clean for statement */ + +#define execute_statement _glp_mpl_execute_statement +void execute_statement(MPL *mpl, STATEMENT *stmt); +/* execute specified model statement */ + +#define clean_statement _glp_mpl_clean_statement +void clean_statement(MPL *mpl, STATEMENT *stmt); +/* clean specified model statement */ + +/**********************************************************************/ +/* * * GENERATING AND POSTSOLVING MODEL * * */ +/**********************************************************************/ + +#define alloc_content _glp_mpl_alloc_content +void alloc_content(MPL *mpl); +/* allocate content arrays for all model objects */ + +#define generate_model _glp_mpl_generate_model +void generate_model(MPL *mpl); +/* generate model */ + +#define build_problem _glp_mpl_build_problem +void build_problem(MPL *mpl); +/* build problem instance */ + +#define postsolve_model _glp_mpl_postsolve_model +void postsolve_model(MPL *mpl); +/* postsolve model */ + +#define clean_model _glp_mpl_clean_model +void clean_model(MPL *mpl); +/* clean model content */ + +/**********************************************************************/ +/* * * INPUT/OUTPUT * * */ +/**********************************************************************/ + +#define open_input _glp_mpl_open_input +void open_input(MPL *mpl, char *file); +/* open input text file */ + +#define read_char _glp_mpl_read_char +int read_char(MPL *mpl); +/* read next character from input text file */ + +#define close_input _glp_mpl_close_input +void close_input(MPL *mpl); +/* close input text file */ + +#define open_output _glp_mpl_open_output +void open_output(MPL *mpl, char *file); +/* open output text file */ + +#define write_char _glp_mpl_write_char +void write_char(MPL *mpl, int c); +/* write next character to output text file */ + +#define write_text _glp_mpl_write_text +void write_text(MPL *mpl, char *fmt, ...); +/* format and write text to output text file */ + +#define flush_output _glp_mpl_flush_output +void flush_output(MPL *mpl); +/* finalize writing data to output text file */ + +/**********************************************************************/ +/* * * SOLVER INTERFACE * * */ +/**********************************************************************/ + +#define MPL_FR 401 /* free (unbounded) */ +#define MPL_LO 402 /* lower bound */ +#define MPL_UP 403 /* upper bound */ +#define MPL_DB 404 /* both lower and upper bounds */ +#define MPL_FX 405 /* fixed */ + +#define MPL_ST 411 /* constraint */ +#define MPL_MIN 412 /* objective (minimization) */ +#define MPL_MAX 413 /* objective (maximization) */ + +#define MPL_NUM 421 /* continuous */ +#define MPL_INT 422 /* integer */ +#define MPL_BIN 423 /* binary */ + +#define error _glp_mpl_error +void error(MPL *mpl, char *fmt, ...); +/* print error message and terminate model processing */ + +#define warning _glp_mpl_warning +void warning(MPL *mpl, char *fmt, ...); +/* print warning message and continue model processing */ + +#define mpl_initialize _glp_mpl_initialize +MPL *mpl_initialize(void); +/* create and initialize translator database */ + +#define mpl_read_model _glp_mpl_read_model +int mpl_read_model(MPL *mpl, char *file, int skip_data); +/* read model section and optional data section */ + +#define mpl_read_data _glp_mpl_read_data +int mpl_read_data(MPL *mpl, char *file); +/* read data section */ + +#define mpl_generate _glp_mpl_generate +int mpl_generate(MPL *mpl, char *file); +/* generate model */ + +#define mpl_get_prob_name _glp_mpl_get_prob_name +char *mpl_get_prob_name(MPL *mpl); +/* obtain problem (model) name */ + +#define mpl_get_num_rows _glp_mpl_get_num_rows +int mpl_get_num_rows(MPL *mpl); +/* determine number of rows */ + +#define mpl_get_num_cols _glp_mpl_get_num_cols +int mpl_get_num_cols(MPL *mpl); +/* determine number of columns */ + +#define mpl_get_row_name _glp_mpl_get_row_name +char *mpl_get_row_name(MPL *mpl, int i); +/* obtain row name */ + +#define mpl_get_row_kind _glp_mpl_get_row_kind +int mpl_get_row_kind(MPL *mpl, int i); +/* determine row kind */ + +#define mpl_get_row_bnds _glp_mpl_get_row_bnds +int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); +/* obtain row bounds */ + +#define mpl_get_mat_row _glp_mpl_get_mat_row +int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); +/* obtain row of the constraint matrix */ + +#define mpl_get_row_c0 _glp_mpl_get_row_c0 +double mpl_get_row_c0(MPL *mpl, int i); +/* obtain constant term of free row */ + +#define mpl_get_col_name _glp_mpl_get_col_name +char *mpl_get_col_name(MPL *mpl, int j); +/* obtain column name */ + +#define mpl_get_col_kind _glp_mpl_get_col_kind +int mpl_get_col_kind(MPL *mpl, int j); +/* determine column kind */ + +#define mpl_get_col_bnds _glp_mpl_get_col_bnds +int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); +/* obtain column bounds */ + +#define mpl_has_solve_stmt _glp_mpl_has_solve_stmt +int mpl_has_solve_stmt(MPL *mpl); +/* check if model has solve statement */ + +#if 1 /* 15/V-2010 */ +#define mpl_put_row_soln _glp_mpl_put_row_soln +void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, + double dual); +/* store row (constraint/objective) solution components */ +#endif + +#if 1 /* 15/V-2010 */ +#define mpl_put_col_soln _glp_mpl_put_col_soln +void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, + double dual); +/* store column (variable) solution components */ +#endif + +#if 0 /* 15/V-2010 */ +#define mpl_put_col_value _glp_mpl_put_col_value +void mpl_put_col_value(MPL *mpl, int j, double val); +/* store column value */ +#endif + +#define mpl_postsolve _glp_mpl_postsolve +int mpl_postsolve(MPL *mpl); +/* postsolve model */ + +#define mpl_terminate _glp_mpl_terminate +void mpl_terminate(MPL *mpl); +/* free all resources used by translator */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl1.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl1.c new file mode 100644 index 000000000..7dc3cd796 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl1.c @@ -0,0 +1,4718 @@ +/* mpl1.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" + +#define dmp_get_atomv dmp_get_atom + +/**********************************************************************/ +/* * * PROCESSING MODEL SECTION * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- enter_context - enter current token into context queue. +-- +-- This routine enters the current token into the context queue. */ + +void enter_context(MPL *mpl) +{ char *image, *s; + if (mpl->token == T_EOF) + image = "_|_"; + else if (mpl->token == T_STRING) + image = "'...'"; + else + image = mpl->image; + xassert(0 <= mpl->c_ptr && mpl->c_ptr < CONTEXT_SIZE); + mpl->context[mpl->c_ptr++] = ' '; + if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; + for (s = image; *s != '\0'; s++) + { mpl->context[mpl->c_ptr++] = *s; + if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; + } + return; +} + +/*---------------------------------------------------------------------- +-- print_context - print current content of context queue. +-- +-- This routine prints current content of the context queue. */ + +void print_context(MPL *mpl) +{ int c; + while (mpl->c_ptr > 0) + { mpl->c_ptr--; + c = mpl->context[0]; + memmove(mpl->context, mpl->context+1, CONTEXT_SIZE-1); + mpl->context[CONTEXT_SIZE-1] = (char)c; + } + xprintf("Context: %s%.*s\n", mpl->context[0] == ' ' ? "" : "...", + CONTEXT_SIZE, mpl->context); + return; +} + +/*---------------------------------------------------------------------- +-- get_char - scan next character from input text file. +-- +-- This routine scans a next ASCII character from the input text file. +-- In case of end-of-file, the character is assigned EOF. */ + +void get_char(MPL *mpl) +{ int c; + if (mpl->c == EOF) goto done; + if (mpl->c == '\n') mpl->line++; + c = read_char(mpl); + if (c == EOF) + { if (mpl->c == '\n') + mpl->line--; + else + warning(mpl, "final NL missing before end of file"); + } + else if (c == '\n') + ; + else if (isspace(c)) + c = ' '; + else if (iscntrl(c)) + { enter_context(mpl); + error(mpl, "control character 0x%02X not allowed", c); + } + mpl->c = c; +done: return; +} + +/*---------------------------------------------------------------------- +-- append_char - append character to current token. +-- +-- This routine appends the current character to the current token and +-- then scans a next character. */ + +void append_char(MPL *mpl) +{ xassert(0 <= mpl->imlen && mpl->imlen <= MAX_LENGTH); + if (mpl->imlen == MAX_LENGTH) + { switch (mpl->token) + { case T_NAME: + enter_context(mpl); + error(mpl, "symbolic name %s... too long", mpl->image); + case T_SYMBOL: + enter_context(mpl); + error(mpl, "symbol %s... too long", mpl->image); + case T_NUMBER: + enter_context(mpl); + error(mpl, "numeric literal %s... too long", mpl->image); + case T_STRING: + enter_context(mpl); + error(mpl, "string literal too long"); + default: + xassert(mpl != mpl); + } + } + mpl->image[mpl->imlen++] = (char)mpl->c; + mpl->image[mpl->imlen] = '\0'; + get_char(mpl); + return; +} + +/*---------------------------------------------------------------------- +-- get_token - scan next token from input text file. +-- +-- This routine scans a next token from the input text file using the +-- standard finite automation technique. */ + +void get_token(MPL *mpl) +{ /* save the current token */ + mpl->b_token = mpl->token; + mpl->b_imlen = mpl->imlen; + strcpy(mpl->b_image, mpl->image); + mpl->b_value = mpl->value; + /* if the next token is already scanned, make it current */ + if (mpl->f_scan) + { mpl->f_scan = 0; + mpl->token = mpl->f_token; + mpl->imlen = mpl->f_imlen; + strcpy(mpl->image, mpl->f_image); + mpl->value = mpl->f_value; + goto done; + } +loop: /* nothing has been scanned so far */ + mpl->token = 0; + mpl->imlen = 0; + mpl->image[0] = '\0'; + mpl->value = 0.0; + /* skip any uninteresting characters */ + while (mpl->c == ' ' || mpl->c == '\n') get_char(mpl); + /* recognize and construct the token */ + if (mpl->c == EOF) + { /* end-of-file reached */ + mpl->token = T_EOF; + } + else if (mpl->c == '#') + { /* comment; skip anything until end-of-line */ + while (mpl->c != '\n' && mpl->c != EOF) get_char(mpl); + goto loop; + } + else if (!mpl->flag_d && (isalpha(mpl->c) || mpl->c == '_')) + { /* symbolic name or reserved keyword */ + mpl->token = T_NAME; + while (isalnum(mpl->c) || mpl->c == '_') append_char(mpl); + if (strcmp(mpl->image, "and") == 0) + mpl->token = T_AND; + else if (strcmp(mpl->image, "by") == 0) + mpl->token = T_BY; + else if (strcmp(mpl->image, "cross") == 0) + mpl->token = T_CROSS; + else if (strcmp(mpl->image, "diff") == 0) + mpl->token = T_DIFF; + else if (strcmp(mpl->image, "div") == 0) + mpl->token = T_DIV; + else if (strcmp(mpl->image, "else") == 0) + mpl->token = T_ELSE; + else if (strcmp(mpl->image, "if") == 0) + mpl->token = T_IF; + else if (strcmp(mpl->image, "in") == 0) + mpl->token = T_IN; +#if 1 /* 21/VII-2006 */ + else if (strcmp(mpl->image, "Infinity") == 0) + mpl->token = T_INFINITY; +#endif + else if (strcmp(mpl->image, "inter") == 0) + mpl->token = T_INTER; + else if (strcmp(mpl->image, "less") == 0) + mpl->token = T_LESS; + else if (strcmp(mpl->image, "mod") == 0) + mpl->token = T_MOD; + else if (strcmp(mpl->image, "not") == 0) + mpl->token = T_NOT; + else if (strcmp(mpl->image, "or") == 0) + mpl->token = T_OR; + else if (strcmp(mpl->image, "s") == 0 && mpl->c == '.') + { mpl->token = T_SPTP; + append_char(mpl); + if (mpl->c != 't') +sptp: { enter_context(mpl); + error(mpl, "keyword s.t. incomplete"); + } + append_char(mpl); + if (mpl->c != '.') goto sptp; + append_char(mpl); + } + else if (strcmp(mpl->image, "symdiff") == 0) + mpl->token = T_SYMDIFF; + else if (strcmp(mpl->image, "then") == 0) + mpl->token = T_THEN; + else if (strcmp(mpl->image, "union") == 0) + mpl->token = T_UNION; + else if (strcmp(mpl->image, "within") == 0) + mpl->token = T_WITHIN; + } + else if (!mpl->flag_d && isdigit(mpl->c)) + { /* numeric literal */ + mpl->token = T_NUMBER; + /* scan integer part */ + while (isdigit(mpl->c)) append_char(mpl); + /* scan optional fractional part */ + if (mpl->c == '.') + { append_char(mpl); + if (mpl->c == '.') + { /* hmm, it is not the fractional part, it is dots that + follow the integer part */ + mpl->imlen--; + mpl->image[mpl->imlen] = '\0'; + mpl->f_dots = 1; + goto conv; + } +frac: while (isdigit(mpl->c)) append_char(mpl); + } + /* scan optional decimal exponent */ + if (mpl->c == 'e' || mpl->c == 'E') + { append_char(mpl); + if (mpl->c == '+' || mpl->c == '-') append_char(mpl); + if (!isdigit(mpl->c)) + { enter_context(mpl); + error(mpl, "numeric literal %s incomplete", mpl->image); + } + while (isdigit(mpl->c)) append_char(mpl); + } + /* there must be no letter following the numeric literal */ + if (isalpha(mpl->c) || mpl->c == '_') + { enter_context(mpl); + error(mpl, "symbol %s%c... should be enclosed in quotes", + mpl->image, mpl->c); + } +conv: /* convert numeric literal to floating-point */ + if (str2num(mpl->image, &mpl->value)) +err: { enter_context(mpl); + error(mpl, "cannot convert numeric literal %s to floating-p" + "oint number", mpl->image); + } + } + else if (mpl->c == '\'' || mpl->c == '"') + { /* character string */ + int quote = mpl->c; + mpl->token = T_STRING; + get_char(mpl); + for (;;) + { if (mpl->c == '\n' || mpl->c == EOF) + { enter_context(mpl); + error(mpl, "unexpected end of line; string literal incom" + "plete"); + } + if (mpl->c == quote) + { get_char(mpl); + if (mpl->c != quote) break; + } + append_char(mpl); + } + } + else if (!mpl->flag_d && mpl->c == '+') + mpl->token = T_PLUS, append_char(mpl); + else if (!mpl->flag_d && mpl->c == '-') + mpl->token = T_MINUS, append_char(mpl); + else if (mpl->c == '*') + { mpl->token = T_ASTERISK, append_char(mpl); + if (mpl->c == '*') + mpl->token = T_POWER, append_char(mpl); + } + else if (mpl->c == '/') + { mpl->token = T_SLASH, append_char(mpl); + if (mpl->c == '*') + { /* comment sequence */ + get_char(mpl); + for (;;) + { if (mpl->c == EOF) + { /* do not call enter_context at this point */ + error(mpl, "unexpected end of file; comment sequence " + "incomplete"); + } + else if (mpl->c == '*') + { get_char(mpl); + if (mpl->c == '/') break; + } + else + get_char(mpl); + } + get_char(mpl); + goto loop; + } + } + else if (mpl->c == '^') + mpl->token = T_POWER, append_char(mpl); + else if (mpl->c == '<') + { mpl->token = T_LT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_LE, append_char(mpl); + else if (mpl->c == '>') + mpl->token = T_NE, append_char(mpl); +#if 1 /* 11/II-2008 */ + else if (mpl->c == '-') + mpl->token = T_INPUT, append_char(mpl); +#endif + } + else if (mpl->c == '=') + { mpl->token = T_EQ, append_char(mpl); + if (mpl->c == '=') append_char(mpl); + } + else if (mpl->c == '>') + { mpl->token = T_GT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_GE, append_char(mpl); +#if 1 /* 14/VII-2006 */ + else if (mpl->c == '>') + mpl->token = T_APPEND, append_char(mpl); +#endif + } + else if (mpl->c == '!') + { mpl->token = T_NOT, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_NE, append_char(mpl); + } + else if (mpl->c == '&') + { mpl->token = T_CONCAT, append_char(mpl); + if (mpl->c == '&') + mpl->token = T_AND, append_char(mpl); + } + else if (mpl->c == '|') + { mpl->token = T_BAR, append_char(mpl); + if (mpl->c == '|') + mpl->token = T_OR, append_char(mpl); + } + else if (!mpl->flag_d && mpl->c == '.') + { mpl->token = T_POINT, append_char(mpl); + if (mpl->f_dots) + { /* dots; the first dot was read on the previous call to the + scanner, so the current character is the second dot */ + mpl->token = T_DOTS; + mpl->imlen = 2; + strcpy(mpl->image, ".."); + mpl->f_dots = 0; + } + else if (mpl->c == '.') + mpl->token = T_DOTS, append_char(mpl); + else if (isdigit(mpl->c)) + { /* numeric literal that begins with the decimal point */ + mpl->token = T_NUMBER, append_char(mpl); + goto frac; + } + } + else if (mpl->c == ',') + mpl->token = T_COMMA, append_char(mpl); + else if (mpl->c == ':') + { mpl->token = T_COLON, append_char(mpl); + if (mpl->c == '=') + mpl->token = T_ASSIGN, append_char(mpl); + } + else if (mpl->c == ';') + mpl->token = T_SEMICOLON, append_char(mpl); + else if (mpl->c == '(') + mpl->token = T_LEFT, append_char(mpl); + else if (mpl->c == ')') + mpl->token = T_RIGHT, append_char(mpl); + else if (mpl->c == '[') + mpl->token = T_LBRACKET, append_char(mpl); + else if (mpl->c == ']') + mpl->token = T_RBRACKET, append_char(mpl); + else if (mpl->c == '{') + mpl->token = T_LBRACE, append_char(mpl); + else if (mpl->c == '}') + mpl->token = T_RBRACE, append_char(mpl); +#if 1 /* 11/II-2008 */ + else if (mpl->c == '~') + mpl->token = T_TILDE, append_char(mpl); +#endif + else if (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) + { /* symbol */ + xassert(mpl->flag_d); + mpl->token = T_SYMBOL; + while (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) + append_char(mpl); + switch (str2num(mpl->image, &mpl->value)) + { case 0: + mpl->token = T_NUMBER; + break; + case 1: + goto err; + case 2: + break; + default: + xassert(mpl != mpl); + } + } + else + { enter_context(mpl); + error(mpl, "character %c not allowed", mpl->c); + } + /* enter the current token into the context queue */ + enter_context(mpl); + /* reset the flag, which may be set by indexing_expression() and + is used by expression_list() */ + mpl->flag_x = 0; +done: return; +} + +/*---------------------------------------------------------------------- +-- unget_token - return current token back to input stream. +-- +-- This routine returns the current token back to the input stream, so +-- the previously scanned token becomes the current one. */ + +void unget_token(MPL *mpl) +{ /* save the current token, which becomes the next one */ + xassert(!mpl->f_scan); + mpl->f_scan = 1; + mpl->f_token = mpl->token; + mpl->f_imlen = mpl->imlen; + strcpy(mpl->f_image, mpl->image); + mpl->f_value = mpl->value; + /* restore the previous token, which becomes the current one */ + mpl->token = mpl->b_token; + mpl->imlen = mpl->b_imlen; + strcpy(mpl->image, mpl->b_image); + mpl->value = mpl->b_value; + return; +} + +/*---------------------------------------------------------------------- +-- is_keyword - check if current token is given non-reserved keyword. +-- +-- If the current token is given (non-reserved) keyword, this routine +-- returns non-zero. Otherwise zero is returned. */ + +int is_keyword(MPL *mpl, char *keyword) +{ return + mpl->token == T_NAME && strcmp(mpl->image, keyword) == 0; +} + +/*---------------------------------------------------------------------- +-- is_reserved - check if current token is reserved keyword. +-- +-- If the current token is a reserved keyword, this routine returns +-- non-zero. Otherwise zero is returned. */ + +int is_reserved(MPL *mpl) +{ return + mpl->token == T_AND && mpl->image[0] == 'a' || + mpl->token == T_BY || + mpl->token == T_CROSS || + mpl->token == T_DIFF || + mpl->token == T_DIV || + mpl->token == T_ELSE || + mpl->token == T_IF || + mpl->token == T_IN || + mpl->token == T_INTER || + mpl->token == T_LESS || + mpl->token == T_MOD || + mpl->token == T_NOT && mpl->image[0] == 'n' || + mpl->token == T_OR && mpl->image[0] == 'o' || + mpl->token == T_SYMDIFF || + mpl->token == T_THEN || + mpl->token == T_UNION || + mpl->token == T_WITHIN; +} + +/*---------------------------------------------------------------------- +-- make_code - generate pseudo-code (basic routine). +-- +-- This routine generates specified pseudo-code. It is assumed that all +-- other translator routines use this basic routine. */ + +CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim) +{ CODE *code; + DOMAIN *domain; + DOMAIN_BLOCK *block; + ARG_LIST *e; + /* generate pseudo-code */ + code = alloc(CODE); + code->op = op; + code->vflag = 0; /* is inherited from operand(s) */ + /* copy operands and also make them referring to the pseudo-code + being generated, because the latter becomes the parent for all + its operands */ + memset(&code->arg, '?', sizeof(OPERANDS)); + switch (op) + { case O_NUMBER: + code->arg.num = arg->num; + break; + case O_STRING: + code->arg.str = arg->str; + break; + case O_INDEX: + code->arg.index.slot = arg->index.slot; + code->arg.index.next = arg->index.next; + break; + case O_MEMNUM: + case O_MEMSYM: + for (e = arg->par.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.par.par = arg->par.par; + code->arg.par.list = arg->par.list; + break; + case O_MEMSET: + for (e = arg->set.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.set.set = arg->set.set; + code->arg.set.list = arg->set.list; + break; + case O_MEMVAR: + for (e = arg->var.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.var.var = arg->var.var; + code->arg.var.list = arg->var.list; +#if 1 /* 15/V-2010 */ + code->arg.var.suff = arg->var.suff; +#endif + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + for (e = arg->con.list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.con.con = arg->con.con; + code->arg.con.list = arg->con.list; + code->arg.con.suff = arg->con.suff; + break; +#endif + case O_TUPLE: + case O_MAKE: + for (e = arg->list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.list = arg->list; + break; + case O_SLICE: + xassert(arg->slice != NULL); + code->arg.slice = arg->slice; + break; + case O_IRAND224: + case O_UNIFORM01: + case O_NORMAL01: + case O_GMTIME: + code->vflag = 1; + break; + case O_CVTNUM: + case O_CVTSYM: + case O_CVTLOG: + case O_CVTTUP: + case O_CVTLFM: + case O_PLUS: + case O_MINUS: + case O_NOT: + case O_ABS: + case O_CEIL: + case O_FLOOR: + case O_EXP: + case O_LOG: + case O_LOG10: + case O_SQRT: + case O_SIN: + case O_COS: + case O_TAN: + case O_ATAN: + case O_ROUND: + case O_TRUNC: + case O_CARD: + case O_LENGTH: + /* unary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + code->arg.arg.x = arg->arg.x; + break; + case O_ADD: + case O_SUB: + case O_LESS: + case O_MUL: + case O_DIV: + case O_IDIV: + case O_MOD: + case O_POWER: + case O_ATAN2: + case O_ROUND2: + case O_TRUNC2: + case O_UNIFORM: + if (op == O_UNIFORM) code->vflag = 1; + case O_NORMAL: + if (op == O_NORMAL) code->vflag = 1; + case O_CONCAT: + case O_LT: + case O_LE: + case O_EQ: + case O_GE: + case O_GT: + case O_NE: + case O_AND: + case O_OR: + case O_UNION: + case O_DIFF: + case O_SYMDIFF: + case O_INTER: + case O_CROSS: + case O_IN: + case O_NOTIN: + case O_WITHIN: + case O_NOTWITHIN: + case O_SUBSTR: + case O_STR2TIME: + case O_TIME2STR: + /* binary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + xassert(arg->arg.y != NULL); + xassert(arg->arg.y->up == NULL); + arg->arg.y->up = code; + code->vflag |= arg->arg.y->vflag; + code->arg.arg.x = arg->arg.x; + code->arg.arg.y = arg->arg.y; + break; + case O_DOTS: + case O_FORK: + case O_SUBSTR3: + /* ternary operation */ + xassert(arg->arg.x != NULL); + xassert(arg->arg.x->up == NULL); + arg->arg.x->up = code; + code->vflag |= arg->arg.x->vflag; + xassert(arg->arg.y != NULL); + xassert(arg->arg.y->up == NULL); + arg->arg.y->up = code; + code->vflag |= arg->arg.y->vflag; + if (arg->arg.z != NULL) + { xassert(arg->arg.z->up == NULL); + arg->arg.z->up = code; + code->vflag |= arg->arg.z->vflag; + } + code->arg.arg.x = arg->arg.x; + code->arg.arg.y = arg->arg.y; + code->arg.arg.z = arg->arg.z; + break; + case O_MIN: + case O_MAX: + /* n-ary operation */ + for (e = arg->list; e != NULL; e = e->next) + { xassert(e->x != NULL); + xassert(e->x->up == NULL); + e->x->up = code; + code->vflag |= e->x->vflag; + } + code->arg.list = arg->list; + break; + case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + case O_FORALL: + case O_EXISTS: + case O_SETOF: + case O_BUILD: + /* iterated operation */ + domain = arg->loop.domain; + xassert(domain != NULL); + if (domain->code != NULL) + { xassert(domain->code->up == NULL); + domain->code->up = code; + code->vflag |= domain->code->vflag; + } + for (block = domain->list; block != NULL; block = + block->next) + { xassert(block->code != NULL); + xassert(block->code->up == NULL); + block->code->up = code; + code->vflag |= block->code->vflag; + } + if (arg->loop.x != NULL) + { xassert(arg->loop.x->up == NULL); + arg->loop.x->up = code; + code->vflag |= arg->loop.x->vflag; + } + code->arg.loop.domain = arg->loop.domain; + code->arg.loop.x = arg->loop.x; + break; + default: + xassert(op != op); + } + /* set other attributes of the pseudo-code */ + code->type = type; + code->dim = dim; + code->up = NULL; + code->valid = 0; + memset(&code->value, '?', sizeof(VALUE)); + return code; +} + +/*---------------------------------------------------------------------- +-- make_unary - generate pseudo-code for unary operation. +-- +-- This routine generates pseudo-code for unary operation. */ + +CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + arg.arg.x = x; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- make_binary - generate pseudo-code for binary operation. +-- +-- This routine generates pseudo-code for binary operation. */ + +CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, + int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + xassert(y != NULL); + arg.arg.x = x; + arg.arg.y = y; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- make_ternary - generate pseudo-code for ternary operation. +-- +-- This routine generates pseudo-code for ternary operation. */ + +CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, + int type, int dim) +{ CODE *code; + OPERANDS arg; + xassert(x != NULL); + xassert(y != NULL); + /* third operand can be NULL */ + arg.arg.x = x; + arg.arg.y = y; + arg.arg.z = z; + code = make_code(mpl, op, &arg, type, dim); + return code; +} + +/*---------------------------------------------------------------------- +-- numeric_literal - parse reference to numeric literal. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= */ + +CODE *numeric_literal(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_NUMBER); + arg.num = mpl->value; + code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); + get_token(mpl /* */); + return code; +} + +/*---------------------------------------------------------------------- +-- string_literal - parse reference to string literal. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= */ + +CODE *string_literal(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_STRING); + arg.str = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(arg.str, mpl->image); + code = make_code(mpl, O_STRING, &arg, A_SYMBOLIC, 0); + get_token(mpl /* */); + return code; +} + +/*---------------------------------------------------------------------- +-- create_arg_list - create empty operands list. +-- +-- This routine creates operands list, which is initially empty. */ + +ARG_LIST *create_arg_list(MPL *mpl) +{ ARG_LIST *list; + xassert(mpl == mpl); + list = NULL; + return list; +} + +/*---------------------------------------------------------------------- +-- expand_arg_list - append operand to operands list. +-- +-- This routine appends new operand to specified operands list. */ + +ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x) +{ ARG_LIST *tail, *temp; + xassert(x != NULL); + /* create new operands list entry */ + tail = alloc(ARG_LIST); + tail->x = x; + tail->next = NULL; + /* and append it to the operands list */ + if (list == NULL) + list = tail; + else + { for (temp = list; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return list; +} + +/*---------------------------------------------------------------------- +-- arg_list_len - determine length of operands list. +-- +-- This routine returns the number of operands in operands list. */ + +int arg_list_len(MPL *mpl, ARG_LIST *list) +{ ARG_LIST *temp; + int len; + xassert(mpl == mpl); + len = 0; + for (temp = list; temp != NULL; temp = temp->next) len++; + return len; +} + +/*---------------------------------------------------------------------- +-- subscript_list - parse subscript list. +-- +-- This routine parses subscript list using the syntax: +-- +-- ::= +-- ::= , +-- ::= */ + +ARG_LIST *subscript_list(MPL *mpl) +{ ARG_LIST *list; + CODE *x; + list = create_arg_list(mpl); + for (;;) + { /* parse subscript expression */ + x = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (x->type != A_SYMBOLIC) + error(mpl, "subscript expression has invalid type"); + xassert(x->dim == 0); + /* and append it to the subscript list */ + list = expand_arg_list(mpl, list, x); + /* check a token that follows the subscript expression */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in subscript list"); + } + return list; +} + +#if 1 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- object_reference - parse reference to named object. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- +-- ::= +-- ::= [ ] +-- +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= | .lb | .ub | .status | .val | .dual */ + +CODE *object_reference(MPL *mpl) +{ AVLNODE *node; + DOMAIN_SLOT *slot; + SET *set; + PARAMETER *par; + VARIABLE *var; + CONSTRAINT *con; + ARG_LIST *list; + OPERANDS arg; + CODE *code; + char *name; + int dim, suff; + /* find the object in the symbolic name table */ + xassert(mpl->token == T_NAME); + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + /* check the object type and obtain its dimension */ + switch (avl_get_node_type(node)) + { case A_INDEX: + /* dummy index */ + slot = (DOMAIN_SLOT *)avl_get_node_link(node); + name = slot->name; + dim = 0; + break; + case A_SET: + /* model set */ + set = (SET *)avl_get_node_link(node); + name = set->name; + dim = set->dim; + /* if a set object is referenced in its own declaration and + the dimen attribute is not specified yet, use dimen 1 by + default */ + if (set->dimen == 0) set->dimen = 1; + break; + case A_PARAMETER: + /* model parameter */ + par = (PARAMETER *)avl_get_node_link(node); + name = par->name; + dim = par->dim; + break; + case A_VARIABLE: + /* model variable */ + var = (VARIABLE *)avl_get_node_link(node); + name = var->name; + dim = var->dim; + break; + case A_CONSTRAINT: + /* model constraint or objective */ + con = (CONSTRAINT *)avl_get_node_link(node); + name = con->name; + dim = con->dim; + break; + default: + xassert(node != node); + } + get_token(mpl /* */); + /* parse optional subscript list */ + if (mpl->token == T_LBRACKET) + { /* subscript list is specified */ + if (dim == 0) + error(mpl, "%s cannot be subscripted", name); + get_token(mpl /* [ */); + list = subscript_list(mpl); + if (dim != arg_list_len(mpl, list)) + error(mpl, "%s must have %d subscript%s rather than %d", + name, dim, dim == 1 ? "" : "s", arg_list_len(mpl, list)); + xassert(mpl->token == T_RBRACKET); + get_token(mpl /* ] */); + } + else + { /* subscript list is not specified */ + if (dim != 0) + error(mpl, "%s must be subscripted", name); + list = create_arg_list(mpl); + } + /* parse optional suffix */ + if (!mpl->flag_s && avl_get_node_type(node) == A_VARIABLE) + suff = DOT_NONE; + else + suff = DOT_VAL; + if (mpl->token == T_POINT) + { get_token(mpl /* . */); + if (mpl->token != T_NAME) + error(mpl, "invalid use of period"); + if (!(avl_get_node_type(node) == A_VARIABLE || + avl_get_node_type(node) == A_CONSTRAINT)) + error(mpl, "%s cannot have a suffix", name); + if (strcmp(mpl->image, "lb") == 0) + suff = DOT_LB; + else if (strcmp(mpl->image, "ub") == 0) + suff = DOT_UB; + else if (strcmp(mpl->image, "status") == 0) + suff = DOT_STATUS; + else if (strcmp(mpl->image, "val") == 0) + suff = DOT_VAL; + else if (strcmp(mpl->image, "dual") == 0) + suff = DOT_DUAL; + else + error(mpl, "suffix .%s invalid", mpl->image); + get_token(mpl /* suffix */); + } + /* generate pseudo-code to take value of the object */ + switch (avl_get_node_type(node)) + { case A_INDEX: + arg.index.slot = slot; + arg.index.next = slot->list; + code = make_code(mpl, O_INDEX, &arg, A_SYMBOLIC, 0); + slot->list = code; + break; + case A_SET: + arg.set.set = set; + arg.set.list = list; + code = make_code(mpl, O_MEMSET, &arg, A_ELEMSET, + set->dimen); + break; + case A_PARAMETER: + arg.par.par = par; + arg.par.list = list; + if (par->type == A_SYMBOLIC) + code = make_code(mpl, O_MEMSYM, &arg, A_SYMBOLIC, 0); + else + code = make_code(mpl, O_MEMNUM, &arg, A_NUMERIC, 0); + break; + case A_VARIABLE: + if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL + || suff == DOT_DUAL)) + error(mpl, "invalid reference to status, primal value, o" + "r dual value of variable %s above solve statement", + var->name); + arg.var.var = var; + arg.var.list = list; + arg.var.suff = suff; + code = make_code(mpl, O_MEMVAR, &arg, suff == DOT_NONE ? + A_FORMULA : A_NUMERIC, 0); + break; + case A_CONSTRAINT: + if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL + || suff == DOT_DUAL)) + error(mpl, "invalid reference to status, primal value, o" + "r dual value of %s %s above solve statement", + con->type == A_CONSTRAINT ? "constraint" : "objective" + , con->name); + arg.con.con = con; + arg.con.list = list; + arg.con.suff = suff; + code = make_code(mpl, O_MEMCON, &arg, A_NUMERIC, 0); + break; + default: + xassert(node != node); + } + return code; +} +#endif + +/*---------------------------------------------------------------------- +-- numeric_argument - parse argument passed to built-in function. +-- +-- This routine parses an argument passed to numeric built-in function +-- using the syntax: +-- +-- ::= */ + +CODE *numeric_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_5(mpl); + /* convert the argument to numeric type, if necessary */ + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + /* check that now the argument is of numeric type */ + if (x->type != A_NUMERIC) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim == 0); + return x; +} + +#if 1 /* 15/VII-2006 */ +CODE *symbolic_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_5(mpl); + /* convert the argument to symbolic type, if necessary */ + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + /* check that now the argument is of symbolic type */ + if (x->type != A_SYMBOLIC) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim == 0); + return x; +} +#endif + +#if 1 /* 15/VII-2006 */ +CODE *elemset_argument(MPL *mpl, char *func) +{ CODE *x; + x = expression_9(mpl); + if (x->type != A_ELEMSET) + error(mpl, "argument for %s has invalid type", func); + xassert(x->dim > 0); + return x; +} +#endif + +/*---------------------------------------------------------------------- +-- function_reference - parse reference to built-in function. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= abs ( ) +-- ::= ceil ( ) +-- ::= floor ( ) +-- ::= exp ( ) +-- ::= log ( ) +-- ::= log10 ( ) +-- ::= max ( ) +-- ::= min ( ) +-- ::= sqrt ( ) +-- ::= sin ( ) +-- ::= cos ( ) +-- ::= tan ( ) +-- ::= atan ( ) +-- ::= atan2 ( , ) +-- ::= round ( ) +-- ::= round ( , ) +-- ::= trunc ( ) +-- ::= trunc ( , ) +-- ::= Irand224 ( ) +-- ::= Uniform01 ( ) +-- ::= Uniform ( , ) +-- ::= Normal01 ( ) +-- ::= Normal ( , ) +-- ::= card ( ) +-- ::= length ( ) +-- ::= substr ( , ) +-- ::= substr ( , , ) +-- ::= str2time ( , ) +-- ::= time2str ( , ) +-- ::= gmtime ( ) +-- ::= +-- ::= , */ + +CODE *function_reference(MPL *mpl) +{ CODE *code; + OPERANDS arg; + int op; + char func[15+1]; + /* determine operation code */ + xassert(mpl->token == T_NAME); + if (strcmp(mpl->image, "abs") == 0) + op = O_ABS; + else if (strcmp(mpl->image, "ceil") == 0) + op = O_CEIL; + else if (strcmp(mpl->image, "floor") == 0) + op = O_FLOOR; + else if (strcmp(mpl->image, "exp") == 0) + op = O_EXP; + else if (strcmp(mpl->image, "log") == 0) + op = O_LOG; + else if (strcmp(mpl->image, "log10") == 0) + op = O_LOG10; + else if (strcmp(mpl->image, "sqrt") == 0) + op = O_SQRT; + else if (strcmp(mpl->image, "sin") == 0) + op = O_SIN; + else if (strcmp(mpl->image, "cos") == 0) + op = O_COS; + else if (strcmp(mpl->image, "tan") == 0) + op = O_TAN; + else if (strcmp(mpl->image, "atan") == 0) + op = O_ATAN; + else if (strcmp(mpl->image, "min") == 0) + op = O_MIN; + else if (strcmp(mpl->image, "max") == 0) + op = O_MAX; + else if (strcmp(mpl->image, "round") == 0) + op = O_ROUND; + else if (strcmp(mpl->image, "trunc") == 0) + op = O_TRUNC; + else if (strcmp(mpl->image, "Irand224") == 0) + op = O_IRAND224; + else if (strcmp(mpl->image, "Uniform01") == 0) + op = O_UNIFORM01; + else if (strcmp(mpl->image, "Uniform") == 0) + op = O_UNIFORM; + else if (strcmp(mpl->image, "Normal01") == 0) + op = O_NORMAL01; + else if (strcmp(mpl->image, "Normal") == 0) + op = O_NORMAL; + else if (strcmp(mpl->image, "card") == 0) + op = O_CARD; + else if (strcmp(mpl->image, "length") == 0) + op = O_LENGTH; + else if (strcmp(mpl->image, "substr") == 0) + op = O_SUBSTR; + else if (strcmp(mpl->image, "str2time") == 0) + op = O_STR2TIME; + else if (strcmp(mpl->image, "time2str") == 0) + op = O_TIME2STR; + else if (strcmp(mpl->image, "gmtime") == 0) + op = O_GMTIME; + else + error(mpl, "function %s unknown", mpl->image); + /* save symbolic name of the function */ + strcpy(func, mpl->image); + xassert(strlen(func) < sizeof(func)); + get_token(mpl /* */); + /* check the left parenthesis that follows the function name */ + xassert(mpl->token == T_LEFT); + get_token(mpl /* ( */); + /* parse argument list */ + if (op == O_MIN || op == O_MAX) + { /* min and max allow arbitrary number of arguments */ + arg.list = create_arg_list(mpl); + /* parse argument list */ + for (;;) + { /* parse argument and append it to the operands list */ + arg.list = expand_arg_list(mpl, arg.list, + numeric_argument(mpl, func)); + /* check a token that follows the argument */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "syntax error in argument list for %s", func); + } + } + else if (op == O_IRAND224 || op == O_UNIFORM01 || op == + O_NORMAL01 || op == O_GMTIME) + { /* Irand224, Uniform01, Normal01, gmtime need no arguments */ + if (mpl->token != T_RIGHT) + error(mpl, "%s needs no arguments", func); + } + else if (op == O_UNIFORM || op == O_NORMAL) + { /* Uniform and Normal need two arguments */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = numeric_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_ATAN || op == O_ROUND || op == O_TRUNC) + { /* atan, round, and trunc need one or two arguments */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* parse the second argument, if specified */ + if (mpl->token == T_COMMA) + { switch (op) + { case O_ATAN: op = O_ATAN2; break; + case O_ROUND: op = O_ROUND2; break; + case O_TRUNC: op = O_TRUNC2; break; + default: xassert(op != op); + } + get_token(mpl /* , */); + arg.arg.y = numeric_argument(mpl, func); + } + /* check a token that follows the last argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs one or two arguments", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_SUBSTR) + { /* substr needs two or three arguments */ + /* parse the first argument */ + arg.arg.x = symbolic_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two or three arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = numeric_argument(mpl, func); + /* parse the third argument, if specified */ + if (mpl->token == T_COMMA) + { op = O_SUBSTR3; + get_token(mpl /* , */); + arg.arg.z = numeric_argument(mpl, func); + } + /* check a token that follows the last argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two or three arguments", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_STR2TIME) + { /* str2time needs two arguments, both symbolic */ + /* parse the first argument */ + arg.arg.x = symbolic_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = symbolic_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else if (op == O_TIME2STR) + { /* time2str needs two arguments, numeric and symbolic */ + /* parse the first argument */ + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the first argument */ + if (mpl->token == T_COMMA) + ; + else if (mpl->token == T_RIGHT) + error(mpl, "%s needs two arguments", func); + else + error(mpl, "syntax error in argument for %s", func); + get_token(mpl /* , */); + /* parse the second argument */ + arg.arg.y = symbolic_argument(mpl, func); + /* check a token that follows the second argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs two argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + else + { /* other functions need one argument */ + if (op == O_CARD) + arg.arg.x = elemset_argument(mpl, func); + else if (op == O_LENGTH) + arg.arg.x = symbolic_argument(mpl, func); + else + arg.arg.x = numeric_argument(mpl, func); + /* check a token that follows the argument */ + if (mpl->token == T_COMMA) + error(mpl, "%s needs one argument", func); + else if (mpl->token == T_RIGHT) + ; + else + error(mpl, "syntax error in argument for %s", func); + } + /* make pseudo-code to call the built-in function */ + if (op == O_SUBSTR || op == O_SUBSTR3 || op == O_TIME2STR) + code = make_code(mpl, op, &arg, A_SYMBOLIC, 0); + else + code = make_code(mpl, op, &arg, A_NUMERIC, 0); + /* the reference ends with the right parenthesis */ + xassert(mpl->token == T_RIGHT); + get_token(mpl /* ) */); + return code; +} + +/*---------------------------------------------------------------------- +-- create_domain - create empty domain. +-- +-- This routine creates empty domain, which is initially empty, i.e. +-- has no domain blocks. */ + +DOMAIN *create_domain(MPL *mpl) +{ DOMAIN *domain; + domain = alloc(DOMAIN); + domain->list = NULL; + domain->code = NULL; + return domain; +} + +/*---------------------------------------------------------------------- +-- create_block - create empty domain block. +-- +-- This routine creates empty domain block, which is initially empty, +-- i.e. has no domain slots. */ + +DOMAIN_BLOCK *create_block(MPL *mpl) +{ DOMAIN_BLOCK *block; + block = alloc(DOMAIN_BLOCK); + block->list = NULL; + block->code = NULL; + block->backup = NULL; + block->next = NULL; + return block; +} + +/*---------------------------------------------------------------------- +-- append_block - append domain block to specified domain. +-- +-- This routine adds given domain block to the end of the block list of +-- specified domain. */ + +void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block) +{ DOMAIN_BLOCK *temp; + xassert(mpl == mpl); + xassert(domain != NULL); + xassert(block != NULL); + xassert(block->next == NULL); + if (domain->list == NULL) + domain->list = block; + else + { for (temp = domain->list; temp->next != NULL; temp = + temp->next); + temp->next = block; + } + return; +} + +/*---------------------------------------------------------------------- +-- append_slot - create and append new slot to domain block. +-- +-- This routine creates new domain slot and adds it to the end of slot +-- list of specified domain block. +-- +-- The parameter name is symbolic name of the dummy index associated +-- with the slot (the character string must be allocated). NULL means +-- the dummy index is not explicitly specified. +-- +-- The parameter code is pseudo-code for computing symbolic value, at +-- which the dummy index is bounded. NULL means the dummy index is free +-- in the domain scope. */ + +DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, + CODE *code) +{ DOMAIN_SLOT *slot, *temp; + xassert(block != NULL); + slot = alloc(DOMAIN_SLOT); + slot->name = name; + slot->code = code; + slot->value = NULL; + slot->list = NULL; + slot->next = NULL; + if (block->list == NULL) + block->list = slot; + else + { for (temp = block->list; temp->next != NULL; temp = + temp->next); + temp->next = slot; + } + return slot; +} + +/*---------------------------------------------------------------------- +-- expression_list - parse expression list. +-- +-- This routine parses a list of one or more expressions enclosed into +-- the parentheses using the syntax: +-- +-- ::= ( ) +-- ::= +-- ::= , +-- +-- Note that this construction may have three different meanings: +-- +-- 1. If consists of only one expression, is a parenthesized expression, which may be of any +-- valid type (not necessarily 1-tuple). +-- +-- 2. If consists of several expressions separated by +-- commae, where no expression is undeclared symbolic name, is a n-tuple. +-- +-- 3. If consists of several expressions separated by +-- commae, where at least one expression is undeclared symbolic name +-- (that denotes a dummy index), is a slice and +-- can be only used as constituent of indexing expression. */ + +#define max_dim 20 +/* maximal number of components allowed within parentheses */ + +CODE *expression_list(MPL *mpl) +{ CODE *code; + OPERANDS arg; + struct { char *name; CODE *code; } list[1+max_dim]; + int flag_x, next_token, dim, j, slice = 0; + xassert(mpl->token == T_LEFT); + /* the flag, which allows recognizing undeclared symbolic names + as dummy indices, will be automatically reset by get_token(), + so save it before scanning the next token */ + flag_x = mpl->flag_x; + get_token(mpl /* ( */); + /* parse */ + for (dim = 1; ; dim++) + { if (dim > max_dim) + error(mpl, "too many components within parentheses"); + /* current component of can be either dummy + index or expression */ + if (mpl->token == T_NAME) + { /* symbolic name is recognized as dummy index only if: + the flag, which allows that, is set, and + the name is followed by comma or right parenthesis, and + the name is undeclared */ + get_token(mpl /* */); + next_token = mpl->token; + unget_token(mpl); + if (!(flag_x && + (next_token == T_COMMA || next_token == T_RIGHT) && + avl_find_node(mpl->tree, mpl->image) == NULL)) + { /* this is not dummy index */ + goto expr; + } + /* all dummy indices within the same slice must have unique + symbolic names */ + for (j = 1; j < dim; j++) + { if (list[j].name != NULL && strcmp(list[j].name, + mpl->image) == 0) + error(mpl, "duplicate dummy index %s not allowed", + mpl->image); + } + /* current component of is dummy index */ + list[dim].name + = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(list[dim].name, mpl->image); + list[dim].code = NULL; + get_token(mpl /* */); + /* is a slice, because at least one dummy + index has appeared */ + slice = 1; + /* note that the context ( ) is not allowed, + i.e. in this case is considered as + a parenthesized expression */ + if (dim == 1 && mpl->token == T_RIGHT) + error(mpl, "%s not defined", list[dim].name); + } + else +expr: { /* current component of is expression */ + code = expression_13(mpl); + /* if the current expression is followed by comma or it is + not the very first expression, entire + is n-tuple or slice, in which case the current expression + should be converted to symbolic type, if necessary */ + if (mpl->token == T_COMMA || dim > 1) + { if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); + /* now the expression must be of symbolic type */ + if (code->type != A_SYMBOLIC) + error(mpl, "component expression has invalid type"); + xassert(code->dim == 0); + } + list[dim].name = NULL; + list[dim].code = code; + } + /* check a token that follows the current component */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "right parenthesis missing where expected"); + } + /* generate pseudo-code for */ + if (dim == 1 && !slice) + { /* is a parenthesized expression */ + code = list[1].code; + } + else if (!slice) + { /* is a n-tuple */ + arg.list = create_arg_list(mpl); + for (j = 1; j <= dim; j++) + arg.list = expand_arg_list(mpl, arg.list, list[j].code); + code = make_code(mpl, O_TUPLE, &arg, A_TUPLE, dim); + } + else + { /* is a slice */ + arg.slice = create_block(mpl); + for (j = 1; j <= dim; j++) + append_slot(mpl, arg.slice, list[j].name, list[j].code); + /* note that actually pseudo-codes with op = O_SLICE are never + evaluated */ + code = make_code(mpl, O_SLICE, &arg, A_TUPLE, dim); + } + get_token(mpl /* ) */); + /* if is a slice, there must be the keyword + 'in', which follows the right parenthesis */ + if (slice && mpl->token != T_IN) + error(mpl, "keyword in missing where expected"); + /* if the slice flag is set and there is the keyword 'in', which + follows , the latter must be a slice */ + if (flag_x && mpl->token == T_IN && !slice) + { if (dim == 1) + error(mpl, "syntax error in indexing expression"); + else + error(mpl, "0-ary slice not allowed"); + } + return code; +} + +/*---------------------------------------------------------------------- +-- literal set - parse literal set. +-- +-- This routine parses literal set using the syntax: +-- +-- ::= { } +-- ::= +-- ::= , +-- ::= +-- +-- It is assumed that the left curly brace and the very first member +-- expression that follows it are already parsed. The right curly brace +-- remains unscanned on exit. */ + +CODE *literal_set(MPL *mpl, CODE *code) +{ OPERANDS arg; + int j; + xassert(code != NULL); + arg.list = create_arg_list(mpl); + /* parse */ + for (j = 1; ; j++) + { /* all member expressions must be n-tuples; so, if the current + expression is not n-tuple, convert it to 1-tuple */ + if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); + if (code->type == A_SYMBOLIC) + code = make_unary(mpl, O_CVTTUP, code, A_TUPLE, 1); + /* now the expression must be n-tuple */ + if (code->type != A_TUPLE) + error(mpl, "member expression has invalid type"); + /* all member expressions must have identical dimension */ + if (arg.list != NULL && arg.list->x->dim != code->dim) + error(mpl, "member %d has %d component%s while member %d ha" + "s %d component%s", + j-1, arg.list->x->dim, arg.list->x->dim == 1 ? "" : "s", + j, code->dim, code->dim == 1 ? "" : "s"); + /* append the current expression to the member list */ + arg.list = expand_arg_list(mpl, arg.list, code); + /* check a token that follows the current expression */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACE) + break; + else + error(mpl, "syntax error in literal set"); + /* parse the next expression that follows the comma */ + code = expression_5(mpl); + } + /* generate pseudo-code for */ + code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, arg.list->x->dim); + return code; +} + +/*---------------------------------------------------------------------- +-- indexing_expression - parse indexing expression. +-- +-- This routine parses indexing expression using the syntax: +-- +-- ::= +-- ::= { } +-- ::= { : } +-- ::= +-- ::= , +-- ::= +-- ::= in +-- ::= in +-- ::= +-- ::= ( ) +-- ::= +-- ::= +-- +-- This routine creates domain for , where each +-- domain block corresponds to , and each domain slot +-- corresponds to individual indexing position. */ + +DOMAIN *indexing_expression(MPL *mpl) +{ DOMAIN *domain; + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + CODE *code; + xassert(mpl->token == T_LBRACE); + get_token(mpl /* { */); + if (mpl->token == T_RBRACE) + error(mpl, "empty indexing expression not allowed"); + /* create domain to be constructed */ + domain = create_domain(mpl); + /* parse either or that follows the + left brace */ + for (;;) + { /* domain block for is not created yet */ + block = NULL; + /* pseudo-code for is not generated yet */ + code = NULL; + /* check a token, which begins with */ + if (mpl->token == T_NAME) + { /* it is a symbolic name */ + int next_token; + char *name; + /* symbolic name is recognized as dummy index only if it is + followed by the keyword 'in' and not declared */ + get_token(mpl /* */); + next_token = mpl->token; + unget_token(mpl); + if (!(next_token == T_IN && + avl_find_node(mpl->tree, mpl->image) == NULL)) + { /* this is not dummy index; the symbolic name begins an + expression, which is either or the + very first in */ + goto expr; + } + /* create domain block with one slot, which is assigned the + dummy index */ + block = create_block(mpl); + name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(name, mpl->image); + append_slot(mpl, block, name, NULL); + get_token(mpl /* */); + /* the keyword 'in' is already checked above */ + xassert(mpl->token == T_IN); + get_token(mpl /* in */); + /* that follows the keyword 'in' will be + parsed below */ + } + else if (mpl->token == T_LEFT) + { /* it is the left parenthesis; parse expression that begins + with this parenthesis (the flag is set in order to allow + recognizing slices; see the routine expression_list) */ + mpl->flag_x = 1; + code = expression_9(mpl); + if (code->op != O_SLICE) + { /* this is either or the very first + in */ + goto expr; + } + /* this is a slice; besides the corresponding domain block + is already created by expression_list() */ + block = code->arg.slice; + code = NULL; /* is not parsed yet */ + /* the keyword 'in' following the slice is already checked + by expression_list() */ + xassert(mpl->token == T_IN); + get_token(mpl /* in */); + /* that follows the keyword 'in' will be + parsed below */ + } +expr: /* parse expression that follows either the keyword 'in' (in + which case it can be as well as the + very first in ); note that + this expression can be already parsed above */ + if (code == NULL) code = expression_9(mpl); + /* check the type of the expression just parsed */ + if (code->type != A_ELEMSET) + { /* it is not and therefore it can only + be the very first in ; + however, then there must be no dummy index neither slice + between the left brace and this expression */ + if (block != NULL) + error(mpl, "domain expression has invalid type"); + /* parse the rest part of and make this set + be , i.e. the construction {a, b, c} + is parsed as it were written as {A}, where A = {a, b, c} + is a temporary elemental set */ + code = literal_set(mpl, code); + } + /* now pseudo-code for has been built */ + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + /* if domain block for the current is still + not created, create it for fake slice of the same dimension + as */ + if (block == NULL) + { int j; + block = create_block(mpl); + for (j = 1; j <= code->dim; j++) + append_slot(mpl, block, NULL, NULL); + } + /* number of indexing positions in must be + the same as dimension of n-tuples in basic set */ + { int dim = 0; + for (slot = block->list; slot != NULL; slot = slot->next) + dim++; + if (dim != code->dim) + error(mpl,"%d %s specified for set of dimension %d", + dim, dim == 1 ? "index" : "indices", code->dim); + } + /* store pseudo-code for in the domain block */ + xassert(block->code == NULL); + block->code = code; + /* and append the domain block to the domain */ + append_block(mpl, domain, block); + /* the current has been completely parsed; + include all its dummy indices into the symbolic name table + to make them available for referencing from expressions; + implicit declarations of dummy indices remain valid while + the corresponding domain scope is valid */ + for (slot = block->list; slot != NULL; slot = slot->next) + if (slot->name != NULL) + { AVLNODE *node; + xassert(avl_find_node(mpl->tree, slot->name) == NULL); + node = avl_insert_node(mpl->tree, slot->name); + avl_set_node_type(node, A_INDEX); + avl_set_node_link(node, (void *)slot); + } + /* check a token that follows */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_COLON || mpl->token == T_RBRACE) + break; + else + error(mpl, "syntax error in indexing expression"); + } + /* parse that follows the colon */ + if (mpl->token == T_COLON) + { get_token(mpl /* : */); + code = expression_13(mpl); + /* convert the expression to logical type, if necessary */ + if (code->type == A_SYMBOLIC) + code = make_unary(mpl, O_CVTNUM, code, A_NUMERIC, 0); + if (code->type == A_NUMERIC) + code = make_unary(mpl, O_CVTLOG, code, A_LOGICAL, 0); + /* now the expression must be of logical type */ + if (code->type != A_LOGICAL) + error(mpl, "expression following colon has invalid type"); + xassert(code->dim == 0); + domain->code = code; + /* the right brace must follow the logical expression */ + if (mpl->token != T_RBRACE) + error(mpl, "syntax error in indexing expression"); + } + get_token(mpl /* } */); + return domain; +} + +/*---------------------------------------------------------------------- +-- close_scope - close scope of indexing expression. +-- +-- The routine closes the scope of indexing expression specified by its +-- domain and thereby makes all dummy indices introduced in the indexing +-- expression no longer available for referencing. */ + +void close_scope(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + AVLNODE *node; + xassert(domain != NULL); + /* remove all dummy indices from the symbolic names table */ + for (block = domain->list; block != NULL; block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->name != NULL) + { node = avl_find_node(mpl->tree, slot->name); + xassert(node != NULL); + xassert(avl_get_node_type(node) == A_INDEX); + avl_delete_node(mpl->tree, node); + } + } + } + return; +} + +/*---------------------------------------------------------------------- +-- iterated_expression - parse iterated expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= +-- ::= sum +-- ::= prod +-- ::= min +-- ::= max +-- ::= exists +-- +-- ::= forall +-- +-- ::= setof +-- +-- Note that parsing "integrand" depends on the iterated operator. */ + +#if 1 /* 07/IX-2008 */ +static void link_up(CODE *code) +{ /* if we have something like sum{(i+1,j,k-1) in E} x[i,j,k], + where i and k are dummy indices defined out of the iterated + expression, we should link up pseudo-code for computing i+1 + and k-1 to pseudo-code for computing the iterated expression; + this is needed to invalidate current value of the iterated + expression once i or k have been changed */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + for (block = code->arg.loop.domain->list; block != NULL; + block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code != NULL) + { xassert(slot->code->up == NULL); + slot->code->up = code; + } + } + } + return; +} +#endif + +CODE *iterated_expression(MPL *mpl) +{ CODE *code; + OPERANDS arg; + int op; + char opstr[8]; + /* determine operation code */ + xassert(mpl->token == T_NAME); + if (strcmp(mpl->image, "sum") == 0) + op = O_SUM; + else if (strcmp(mpl->image, "prod") == 0) + op = O_PROD; + else if (strcmp(mpl->image, "min") == 0) + op = O_MINIMUM; + else if (strcmp(mpl->image, "max") == 0) + op = O_MAXIMUM; + else if (strcmp(mpl->image, "forall") == 0) + op = O_FORALL; + else if (strcmp(mpl->image, "exists") == 0) + op = O_EXISTS; + else if (strcmp(mpl->image, "setof") == 0) + op = O_SETOF; + else + error(mpl, "operator %s unknown", mpl->image); + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* */); + /* check the left brace that follows the operator name */ + xassert(mpl->token == T_LBRACE); + /* parse indexing expression that controls iterating */ + arg.loop.domain = indexing_expression(mpl); + /* parse "integrand" expression and generate pseudo-code */ + switch (op) + { case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + arg.loop.x = expression_3(mpl); + /* convert the integrand to numeric type, if necessary */ + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, + A_NUMERIC, 0); + /* now the integrand must be of numeric type or linear form + (the latter is only allowed for the sum operator) */ + if (!(arg.loop.x->type == A_NUMERIC || + op == O_SUM && arg.loop.x->type == A_FORMULA)) +err: error(mpl, "integrand following %s{...} has invalid type" + , opstr); + xassert(arg.loop.x->dim == 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, arg.loop.x->type, 0); + break; + case O_FORALL: + case O_EXISTS: + arg.loop.x = expression_12(mpl); + /* convert the integrand to logical type, if necessary */ + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, + A_NUMERIC, 0); + if (arg.loop.x->type == A_NUMERIC) + arg.loop.x = make_unary(mpl, O_CVTLOG, arg.loop.x, + A_LOGICAL, 0); + /* now the integrand must be of logical type */ + if (arg.loop.x->type != A_LOGICAL) goto err; + xassert(arg.loop.x->dim == 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, A_LOGICAL, 0); + break; + case O_SETOF: + arg.loop.x = expression_5(mpl); + /* convert the integrand to 1-tuple, if necessary */ + if (arg.loop.x->type == A_NUMERIC) + arg.loop.x = make_unary(mpl, O_CVTSYM, arg.loop.x, + A_SYMBOLIC, 0); + if (arg.loop.x->type == A_SYMBOLIC) + arg.loop.x = make_unary(mpl, O_CVTTUP, arg.loop.x, + A_TUPLE, 1); + /* now the integrand must be n-tuple */ + if (arg.loop.x->type != A_TUPLE) goto err; + xassert(arg.loop.x->dim > 0); + /* generate pseudo-code */ + code = make_code(mpl, op, &arg, A_ELEMSET, arg.loop.x->dim); + break; + default: + xassert(op != op); + } + /* close the scope of the indexing expression */ + close_scope(mpl, arg.loop.domain); +#if 1 /* 07/IX-2008 */ + link_up(code); +#endif + return code; +} + +/*---------------------------------------------------------------------- +-- domain_arity - determine arity of domain. +-- +-- This routine returns arity of specified domain, which is number of +-- its free dummy indices. */ + +int domain_arity(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + int arity; + xassert(mpl == mpl); + arity = 0; + for (block = domain->list; block != NULL; block = block->next) + for (slot = block->list; slot != NULL; slot = slot->next) + if (slot->code == NULL) arity++; + return arity; +} + +/*---------------------------------------------------------------------- +-- set_expression - parse set expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= { } +-- ::= */ + +CODE *set_expression(MPL *mpl) +{ CODE *code; + OPERANDS arg; + xassert(mpl->token == T_LBRACE); + get_token(mpl /* { */); + /* check a token that follows the left brace */ + if (mpl->token == T_RBRACE) + { /* it is the right brace, so the resultant is an empty set of + dimension 1 */ + arg.list = NULL; + /* generate pseudo-code to build the resultant set */ + code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, 1); + get_token(mpl /* } */); + } + else + { /* the next token begins an indexing expression */ + unget_token(mpl); + arg.loop.domain = indexing_expression(mpl); + arg.loop.x = NULL; /* integrand is not used */ + /* close the scope of the indexing expression */ + close_scope(mpl, arg.loop.domain); + /* generate pseudo-code to build the resultant set */ + code = make_code(mpl, O_BUILD, &arg, A_ELEMSET, + domain_arity(mpl, arg.loop.domain)); +#if 1 /* 07/IX-2008 */ + link_up(code); +#endif + } + return code; +} + +/*---------------------------------------------------------------------- +-- branched_expression - parse conditional expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= +-- ::= if then +-- ::= if then +-- else +-- ::= */ + +CODE *branched_expression(MPL *mpl) +{ CODE *code, *x, *y, *z; + xassert(mpl->token == T_IF); + get_token(mpl /* if */); + /* parse that follows 'if' */ + x = expression_13(mpl); + /* convert the expression to logical type, if necessary */ + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + /* now the expression must be of logical type */ + if (x->type != A_LOGICAL) + error(mpl, "expression following if has invalid type"); + xassert(x->dim == 0); + /* the keyword 'then' must follow the logical expression */ + if (mpl->token != T_THEN) + error(mpl, "keyword then missing where expected"); + get_token(mpl /* then */); + /* parse that follows 'then' and check its type */ + y = expression_9(mpl); + if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC || + y->type == A_ELEMSET || y->type == A_FORMULA)) + error(mpl, "expression following then has invalid type"); + /* if the expression that follows the keyword 'then' is elemental + set, the keyword 'else' cannot be omitted; otherwise else-part + is optional */ + if (mpl->token != T_ELSE) + { if (y->type == A_ELEMSET) + error(mpl, "keyword else missing where expected"); + z = NULL; + goto skip; + } + get_token(mpl /* else */); + /* parse that follow 'else' and check its type */ + z = expression_9(mpl); + if (!(z->type == A_NUMERIC || z->type == A_SYMBOLIC || + z->type == A_ELEMSET || z->type == A_FORMULA)) + error(mpl, "expression following else has invalid type"); + /* convert to identical types, if necessary */ + if (y->type == A_FORMULA || z->type == A_FORMULA) + { if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + if (z->type == A_SYMBOLIC) + z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); + if (z->type == A_NUMERIC) + z = make_unary(mpl, O_CVTLFM, z, A_FORMULA, 0); + } + if (y->type == A_SYMBOLIC || z->type == A_SYMBOLIC) + { if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + if (z->type == A_NUMERIC) + z = make_unary(mpl, O_CVTSYM, z, A_SYMBOLIC, 0); + } + /* now both expressions must have identical types */ + if (y->type != z->type) + error(mpl, "expressions following then and else have incompati" + "ble types"); + /* and identical dimensions */ + if (y->dim != z->dim) + error(mpl, "expressions following then and else have different" + " dimensions %d and %d, respectively", y->dim, z->dim); +skip: /* generate pseudo-code to perform branching */ + code = make_ternary(mpl, O_FORK, x, y, z, y->type, y->dim); + return code; +} + +/*---------------------------------------------------------------------- +-- primary_expression - parse primary expression. +-- +-- This routine parses primary expression using the syntax: +-- +-- ::= +-- ::= Infinity +-- ::= +-- ::= +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= ( ) +-- ::= ( ) +-- ::= +-- ::= { } +-- ::= +-- ::= +-- +-- For complete list of syntactic rules for see +-- comments to the corresponding parsing routines. */ + +CODE *primary_expression(MPL *mpl) +{ CODE *code; + if (mpl->token == T_NUMBER) + { /* parse numeric literal */ + code = numeric_literal(mpl); + } +#if 1 /* 21/VII-2006 */ + else if (mpl->token == T_INFINITY) + { /* parse "infinity" */ + OPERANDS arg; + arg.num = DBL_MAX; + code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); + get_token(mpl /* Infinity */); + } +#endif + else if (mpl->token == T_STRING) + { /* parse string literal */ + code = string_literal(mpl); + } + else if (mpl->token == T_NAME) + { int next_token; + get_token(mpl /* */); + next_token = mpl->token; + unget_token(mpl); + /* check a token that follows */ + switch (next_token) + { case T_LBRACKET: + /* parse reference to subscripted object */ + code = object_reference(mpl); + break; + case T_LEFT: + /* parse reference to built-in function */ + code = function_reference(mpl); + break; + case T_LBRACE: + /* parse iterated expression */ + code = iterated_expression(mpl); + break; + default: + /* parse reference to unsubscripted object */ + code = object_reference(mpl); + break; + } + } + else if (mpl->token == T_LEFT) + { /* parse parenthesized expression */ + code = expression_list(mpl); + } + else if (mpl->token == T_LBRACE) + { /* parse set expression */ + code = set_expression(mpl); + } + else if (mpl->token == T_IF) + { /* parse conditional expression */ + code = branched_expression(mpl); + } + else if (is_reserved(mpl)) + { /* other reserved keywords cannot be used here */ + error(mpl, "invalid use of reserved keyword %s", mpl->image); + } + else + error(mpl, "syntax error in expression"); + return code; +} + +/*---------------------------------------------------------------------- +-- error_preceding - raise error if preceding operand has wrong type. +-- +-- This routine is called to raise error if operand that precedes some +-- infix operator has invalid type. */ + +void error_preceding(MPL *mpl, char *opstr) +{ error(mpl, "operand preceding %s has invalid type", opstr); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- error_following - raise error if following operand has wrong type. +-- +-- This routine is called to raise error if operand that follows some +-- infix operator has invalid type. */ + +void error_following(MPL *mpl, char *opstr) +{ error(mpl, "operand following %s has invalid type", opstr); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- error_dimension - raise error if operands have different dimension. +-- +-- This routine is called to raise error if two operands of some infix +-- operator have different dimension. */ + +void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2) +{ error(mpl, "operands preceding and following %s have different di" + "mensions %d and %d, respectively", opstr, dim1, dim2); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- expression_0 - parse expression of level 0. +-- +-- This routine parses expression of level 0 using the syntax: +-- +-- ::= */ + +CODE *expression_0(MPL *mpl) +{ CODE *code; + code = primary_expression(mpl); + return code; +} + +/*---------------------------------------------------------------------- +-- expression_1 - parse expression of level 1. +-- +-- This routine parses expression of level 1 using the syntax: +-- +-- ::= +-- ::= +-- ::= +-- ::= ^ | ** */ + +CODE *expression_1(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_0(mpl); + if (mpl->token == T_POWER) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, opstr); + get_token(mpl /* ^ | ** */); + if (mpl->token == T_PLUS || mpl->token == T_MINUS) + y = expression_2(mpl); + else + y = expression_1(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, opstr); + x = make_binary(mpl, O_POWER, x, y, A_NUMERIC, 0); + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_2 - parse expression of level 2. +-- +-- This routine parses expression of level 2 using the syntax: +-- +-- ::= +-- ::= + +-- ::= - */ + +CODE *expression_2(MPL *mpl) +{ CODE *x; + if (mpl->token == T_PLUS) + { get_token(mpl /* + */); + x = expression_1(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_following(mpl, "+"); + x = make_unary(mpl, O_PLUS, x, x->type, 0); + } + else if (mpl->token == T_MINUS) + { get_token(mpl /* - */); + x = expression_1(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_following(mpl, "-"); + x = make_unary(mpl, O_MINUS, x, x->type, 0); + } + else + x = expression_1(mpl); + return x; +} + +/*---------------------------------------------------------------------- +-- expression_3 - parse expression of level 3. +-- +-- This routine parses expression of level 3 using the syntax: +-- +-- ::= +-- ::= * +-- ::= / +-- ::= div +-- ::= mod */ + +CODE *expression_3(MPL *mpl) +{ CODE *x, *y; + x = expression_2(mpl); + for (;;) + { if (mpl->token == T_ASTERISK) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "*"); + get_token(mpl /* * */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "*"); + if (x->type == A_FORMULA && y->type == A_FORMULA) + error(mpl, "multiplication of linear forms not allowed"); + if (x->type == A_NUMERIC && y->type == A_NUMERIC) + x = make_binary(mpl, O_MUL, x, y, A_NUMERIC, 0); + else + x = make_binary(mpl, O_MUL, x, y, A_FORMULA, 0); + } + else if (mpl->token == T_SLASH) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "/"); + get_token(mpl /* / */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "/"); + if (x->type == A_NUMERIC) + x = make_binary(mpl, O_DIV, x, y, A_NUMERIC, 0); + else + x = make_binary(mpl, O_DIV, x, y, A_FORMULA, 0); + } + else if (mpl->token == T_DIV) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "div"); + get_token(mpl /* div */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "div"); + x = make_binary(mpl, O_IDIV, x, y, A_NUMERIC, 0); + } + else if (mpl->token == T_MOD) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "mod"); + get_token(mpl /* mod */); + y = expression_2(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "mod"); + x = make_binary(mpl, O_MOD, x, y, A_NUMERIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_4 - parse expression of level 4. +-- +-- This routine parses expression of level 4 using the syntax: +-- +-- ::= +-- ::= + +-- ::= - +-- ::= less */ + +CODE *expression_4(MPL *mpl) +{ CODE *x, *y; + x = expression_3(mpl); + for (;;) + { if (mpl->token == T_PLUS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "+"); + get_token(mpl /* + */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "+"); + if (x->type == A_NUMERIC && y->type == A_FORMULA) + x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); + if (x->type == A_FORMULA && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + x = make_binary(mpl, O_ADD, x, y, x->type, 0); + } + else if (mpl->token == T_MINUS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) + error_preceding(mpl, "-"); + get_token(mpl /* - */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) + error_following(mpl, "-"); + if (x->type == A_NUMERIC && y->type == A_FORMULA) + x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); + if (x->type == A_FORMULA && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); + x = make_binary(mpl, O_SUB, x, y, x->type, 0); + } + else if (mpl->token == T_LESS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, "less"); + get_token(mpl /* less */); + y = expression_3(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, "less"); + x = make_binary(mpl, O_LESS, x, y, A_NUMERIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_5 - parse expression of level 5. +-- +-- This routine parses expression of level 5 using the syntax: +-- +-- ::= +-- ::= & */ + +CODE *expression_5(MPL *mpl) +{ CODE *x, *y; + x = expression_4(mpl); + for (;;) + { if (mpl->token == T_CONCAT) + { if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type != A_SYMBOLIC) + error_preceding(mpl, "&"); + get_token(mpl /* & */); + y = expression_4(mpl); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + if (y->type != A_SYMBOLIC) + error_following(mpl, "&"); + x = make_binary(mpl, O_CONCAT, x, y, A_SYMBOLIC, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_6 - parse expression of level 6. +-- +-- This routine parses expression of level 6 using the syntax: +-- +-- ::= +-- ::= .. +-- ::= .. by +-- */ + +CODE *expression_6(MPL *mpl) +{ CODE *x, *y, *z; + x = expression_5(mpl); + if (mpl->token == T_DOTS) + { if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, ".."); + get_token(mpl /* .. */); + y = expression_5(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, ".."); + if (mpl->token == T_BY) + { get_token(mpl /* by */); + z = expression_5(mpl); + if (z->type == A_SYMBOLIC) + z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); + if (z->type != A_NUMERIC) + error_following(mpl, "by"); + } + else + z = NULL; + x = make_ternary(mpl, O_DOTS, x, y, z, A_ELEMSET, 1); + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_7 - parse expression of level 7. +-- +-- This routine parses expression of level 7 using the syntax: +-- +-- ::= +-- ::= cross */ + +CODE *expression_7(MPL *mpl) +{ CODE *x, *y; + x = expression_6(mpl); + for (;;) + { if (mpl->token == T_CROSS) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "cross"); + get_token(mpl /* cross */); + y = expression_6(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "cross"); + x = make_binary(mpl, O_CROSS, x, y, A_ELEMSET, + x->dim + y->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_8 - parse expression of level 8. +-- +-- This routine parses expression of level 8 using the syntax: +-- +-- ::= +-- ::= inter */ + +CODE *expression_8(MPL *mpl) +{ CODE *x, *y; + x = expression_7(mpl); + for (;;) + { if (mpl->token == T_INTER) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "inter"); + get_token(mpl /* inter */); + y = expression_7(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "inter"); + if (x->dim != y->dim) + error_dimension(mpl, "inter", x->dim, y->dim); + x = make_binary(mpl, O_INTER, x, y, A_ELEMSET, x->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_9 - parse expression of level 9. +-- +-- This routine parses expression of level 9 using the syntax: +-- +-- ::= +-- ::= union +-- ::= diff +-- ::= symdiff */ + +CODE *expression_9(MPL *mpl) +{ CODE *x, *y; + x = expression_8(mpl); + for (;;) + { if (mpl->token == T_UNION) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "union"); + get_token(mpl /* union */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "union"); + if (x->dim != y->dim) + error_dimension(mpl, "union", x->dim, y->dim); + x = make_binary(mpl, O_UNION, x, y, A_ELEMSET, x->dim); + } + else if (mpl->token == T_DIFF) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "diff"); + get_token(mpl /* diff */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "diff"); + if (x->dim != y->dim) + error_dimension(mpl, "diff", x->dim, y->dim); + x = make_binary(mpl, O_DIFF, x, y, A_ELEMSET, x->dim); + } + else if (mpl->token == T_SYMDIFF) + { if (x->type != A_ELEMSET) + error_preceding(mpl, "symdiff"); + get_token(mpl /* symdiff */); + y = expression_8(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, "symdiff"); + if (x->dim != y->dim) + error_dimension(mpl, "symdiff", x->dim, y->dim); + x = make_binary(mpl, O_SYMDIFF, x, y, A_ELEMSET, x->dim); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_10 - parse expression of level 10. +-- +-- This routine parses expression of level 10 using the syntax: +-- +-- ::= +-- ::= +-- ::= < | <= | = | == | >= | > | <> | != | in | not in | ! in | +-- within | not within | ! within */ + +CODE *expression_10(MPL *mpl) +{ CODE *x, *y; + int op = -1; + char opstr[16]; + x = expression_9(mpl); + strcpy(opstr, ""); + switch (mpl->token) + { case T_LT: + op = O_LT; break; + case T_LE: + op = O_LE; break; + case T_EQ: + op = O_EQ; break; + case T_GE: + op = O_GE; break; + case T_GT: + op = O_GT; break; + case T_NE: + op = O_NE; break; + case T_IN: + op = O_IN; break; + case T_WITHIN: + op = O_WITHIN; break; + case T_NOT: + strcpy(opstr, mpl->image); + get_token(mpl /* not | ! */); + if (mpl->token == T_IN) + op = O_NOTIN; + else if (mpl->token == T_WITHIN) + op = O_NOTWITHIN; + else + error(mpl, "invalid use of %s", opstr); + strcat(opstr, " "); + break; + default: + goto done; + } + strcat(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + switch (op) + { case O_EQ: + case O_NE: +#if 1 /* 02/VIII-2008 */ + case O_LT: + case O_LE: + case O_GT: + case O_GE: +#endif + if (!(x->type == A_NUMERIC || x->type == A_SYMBOLIC)) + error_preceding(mpl, opstr); + get_token(mpl /* */); + y = expression_9(mpl); + if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC)) + error_following(mpl, opstr); + if (x->type == A_NUMERIC && y->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type == A_SYMBOLIC && y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; +#if 0 /* 02/VIII-2008 */ + case O_LT: + case O_LE: + case O_GT: + case O_GE: + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type != A_NUMERIC) + error_preceding(mpl, opstr); + get_token(mpl /* */); + y = expression_9(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type != A_NUMERIC) + error_following(mpl, opstr); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; +#endif + case O_IN: + case O_NOTIN: + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTTUP, x, A_TUPLE, 1); + if (x->type != A_TUPLE) + error_preceding(mpl, opstr); + get_token(mpl /* */); + y = expression_9(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, opstr); + if (x->dim != y->dim) + error_dimension(mpl, opstr, x->dim, y->dim); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; + case O_WITHIN: + case O_NOTWITHIN: + if (x->type != A_ELEMSET) + error_preceding(mpl, opstr); + get_token(mpl /* */); + y = expression_9(mpl); + if (y->type != A_ELEMSET) + error_following(mpl, opstr); + if (x->dim != y->dim) + error_dimension(mpl, opstr, x->dim, y->dim); + x = make_binary(mpl, op, x, y, A_LOGICAL, 0); + break; + default: + xassert(op != op); + } +done: return x; +} + +/*---------------------------------------------------------------------- +-- expression_11 - parse expression of level 11. +-- +-- This routine parses expression of level 11 using the syntax: +-- +-- ::= +-- ::= not +-- ::= ! */ + +CODE *expression_11(MPL *mpl) +{ CODE *x; + char opstr[8]; + if (mpl->token == T_NOT) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* not | ! */); + x = expression_10(mpl); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_unary(mpl, O_NOT, x, A_LOGICAL, 0); + } + else + x = expression_10(mpl); + return x; +} + +/*---------------------------------------------------------------------- +-- expression_12 - parse expression of level 12. +-- +-- This routine parses expression of level 12 using the syntax: +-- +-- ::= +-- ::= and +-- ::= && */ + +CODE *expression_12(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_11(mpl); + for (;;) + { if (mpl->token == T_AND) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_preceding(mpl, opstr); + get_token(mpl /* and | && */); + y = expression_11(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); + if (y->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_binary(mpl, O_AND, x, y, A_LOGICAL, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- expression_13 - parse expression of level 13. +-- +-- This routine parses expression of level 13 using the syntax: +-- +-- ::= +-- ::= or +-- ::= || */ + +CODE *expression_13(MPL *mpl) +{ CODE *x, *y; + char opstr[8]; + x = expression_12(mpl); + for (;;) + { if (mpl->token == T_OR) + { strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + if (x->type == A_SYMBOLIC) + x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); + if (x->type == A_NUMERIC) + x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); + if (x->type != A_LOGICAL) + error_preceding(mpl, opstr); + get_token(mpl /* or | || */); + y = expression_12(mpl); + if (y->type == A_SYMBOLIC) + y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); + if (y->type == A_NUMERIC) + y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); + if (y->type != A_LOGICAL) + error_following(mpl, opstr); + x = make_binary(mpl, O_OR, x, y, A_LOGICAL, 0); + } + else + break; + } + return x; +} + +/*---------------------------------------------------------------------- +-- set_statement - parse set statement. +-- +-- This routine parses set statement using the syntax: +-- +-- ::= set +-- ; +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= , dimen +-- ::= , within +-- ::= , := +-- ::= , default +-- +-- Commae in are optional and may be omitted anywhere. */ + +SET *set_statement(MPL *mpl) +{ SET *set; + int dimen_used = 0; + xassert(is_keyword(mpl, "set")); + get_token(mpl /* set */); + /* symbolic name must follow the keyword 'set' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model set */ + set = alloc(SET); + set->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(set->name, mpl->image); + set->alias = NULL; + set->dim = 0; + set->domain = NULL; + set->dimen = 0; + set->within = NULL; + set->assign = NULL; + set->option = NULL; + set->gadget = NULL; + set->data = 0; + set->array = NULL; + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { set->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(set->alias, mpl->image); + get_token(mpl /* */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { set->domain = indexing_expression(mpl); + set->dim = domain_arity(mpl, set->domain); + } + /* include the set name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, set->name); + avl_set_node_type(node, A_SET); + avl_set_node_link(node, (void *)set); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "dimen")) + { /* dimension of set members */ + int dimen; + get_token(mpl /* dimen */); + if (!(mpl->token == T_NUMBER && + 1.0 <= mpl->value && mpl->value <= 20.0 && + floor(mpl->value) == mpl->value)) + error(mpl, "dimension must be integer between 1 and 20"); + dimen = (int)(mpl->value + 0.5); + if (dimen_used) + error(mpl, "at most one dimension attribute allowed"); + if (set->dimen > 0) + error(mpl, "dimension %d conflicts with dimension %d alr" + "eady determined", dimen, set->dimen); + set->dimen = dimen; + dimen_used = 1; + get_token(mpl /* */); + } + else if (mpl->token == T_WITHIN || mpl->token == T_IN) + { /* restricting superset */ + WITHIN *within, *temp; + if (mpl->token == T_IN && !mpl->as_within) + { warning(mpl, "keyword in understood as within"); + mpl->as_within = 1; + } + get_token(mpl /* within */); + /* create new restricting superset list entry and append it + to the within-list */ + within = alloc(WITHIN); + within->code = NULL; + within->next = NULL; + if (set->within == NULL) + set->within = within; + else + { for (temp = set->within; temp->next != NULL; temp = + temp->next); + temp->next = within; + } + /* parse an expression that follows 'within' */ + within->code = expression_9(mpl); + if (within->code->type != A_ELEMSET) + error(mpl, "expression following within has invalid type" + ); + xassert(within->code->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = within->code->dim; + if (set->dimen != within->code->dim) + error(mpl, "set expression following within must have di" + "mension %d rather than %d", + set->dimen, within->code->dim); + } + else if (mpl->token == T_ASSIGN) + { /* assignment expression */ + if (!(set->assign == NULL && set->option == NULL && + set->gadget == NULL)) +err: error(mpl, "at most one := or default/data allowed"); + get_token(mpl /* := */); + /* parse an expression that follows ':=' */ + set->assign = expression_9(mpl); + if (set->assign->type != A_ELEMSET) + error(mpl, "expression following := has invalid type"); + xassert(set->assign->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = set->assign->dim; + if (set->dimen != set->assign->dim) + error(mpl, "set expression following := must have dimens" + "ion %d rather than %d", + set->dimen, set->assign->dim); + } + else if (is_keyword(mpl, "default")) + { /* expression for default value */ + if (!(set->assign == NULL && set->option == NULL)) goto err; + get_token(mpl /* := */); + /* parse an expression that follows 'default' */ + set->option = expression_9(mpl); + if (set->option->type != A_ELEMSET) + error(mpl, "expression following default has invalid typ" + "e"); + xassert(set->option->dim > 0); + /* check/set dimension of set members */ + if (set->dimen == 0) set->dimen = set->option->dim; + if (set->dimen != set->option->dim) + error(mpl, "set expression following default must have d" + "imension %d rather than %d", + set->dimen, set->option->dim); + } +#if 1 /* 12/XII-2008 */ + else if (is_keyword(mpl, "data")) + { /* gadget to initialize the set by data from plain set */ + GADGET *gadget; + AVLNODE *node; + int i, k, fff[20]; + if (!(set->assign == NULL && set->gadget == NULL)) goto err; + get_token(mpl /* data */); + set->gadget = gadget = alloc(GADGET); + /* set name must follow the keyword 'data' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", + mpl->image); + else + error(mpl, "set name missing where expected"); + /* find the set in the symbolic name table */ + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_SET) +err1: error(mpl, "%s not a plain set", mpl->image); + gadget->set = avl_get_node_link(node); + if (gadget->set->dim != 0) goto err1; + if (gadget->set == set) + error(mpl, "set cannot be initialized by itself"); + /* check and set dimensions */ + if (set->dim >= gadget->set->dimen) +err2: error(mpl, "dimension of %s too small", mpl->image); + if (set->dimen == 0) + set->dimen = gadget->set->dimen - set->dim; + if (set->dim + set->dimen > gadget->set->dimen) + goto err2; + else if (set->dim + set->dimen < gadget->set->dimen) + error(mpl, "dimension of %s too big", mpl->image); + get_token(mpl /* set name */); + /* left parenthesis must follow the set name */ + if (mpl->token == T_LEFT) + get_token(mpl /* ( */); + else + error(mpl, "left parenthesis missing where expected"); + /* parse permutation of component numbers */ + for (k = 0; k < gadget->set->dimen; k++) fff[k] = 0; + k = 0; + for (;;) + { if (mpl->token != T_NUMBER) + error(mpl, "component number missing where expected"); + if (str2int(mpl->image, &i) != 0) +err3: error(mpl, "component number must be integer between " + "1 and %d", gadget->set->dimen); + if (!(1 <= i && i <= gadget->set->dimen)) goto err3; + if (fff[i-1] != 0) + error(mpl, "component %d multiply specified", i); + gadget->ind[k++] = i, fff[i-1] = 1; + xassert(k <= gadget->set->dimen); + get_token(mpl /* number */); + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RIGHT) + break; + else + error(mpl, "syntax error in data attribute"); + } + if (k < gadget->set->dimen) + error(mpl, "there are must be %d components rather than " + "%d", gadget->set->dimen, k); + get_token(mpl /* ) */); + } +#endif + else + error(mpl, "syntax error in set statement"); + } + /* close the domain scope */ + if (set->domain != NULL) close_scope(mpl, set->domain); + /* if dimension of set members is still unknown, set it to 1 */ + if (set->dimen == 0) set->dimen = 1; + /* the set statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return set; +} + +/*---------------------------------------------------------------------- +-- parameter_statement - parse parameter statement. +-- +-- This routine parses parameter statement using the syntax: +-- +-- ::= param +-- ; +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= , integer +-- ::= , binary +-- ::= , symbolic +-- ::= , +-- ::= , in +-- ::= , := +-- ::= , default +-- ::= < | <= | = | == | >= | > | <> | != +-- +-- Commae in are optional and may be omitted anywhere. */ + +PARAMETER *parameter_statement(MPL *mpl) +{ PARAMETER *par; + int integer_used = 0, binary_used = 0, symbolic_used = 0; + xassert(is_keyword(mpl, "param")); + get_token(mpl /* param */); + /* symbolic name must follow the keyword 'param' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model parameter */ + par = alloc(PARAMETER); + par->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(par->name, mpl->image); + par->alias = NULL; + par->dim = 0; + par->domain = NULL; + par->type = A_NUMERIC; + par->cond = NULL; + par->in = NULL; + par->assign = NULL; + par->option = NULL; + par->data = 0; + par->defval = NULL; + par->array = NULL; + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { par->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(par->alias, mpl->image); + get_token(mpl /* */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { par->domain = indexing_expression(mpl); + par->dim = domain_arity(mpl, par->domain); + } + /* include the parameter name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, par->name); + avl_set_node_type(node, A_PARAMETER); + avl_set_node_link(node, (void *)par); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "integer")) + { if (integer_used) + error(mpl, "at most one integer allowed"); + if (par->type == A_SYMBOLIC) + error(mpl, "symbolic parameter cannot be integer"); + if (par->type != A_BINARY) par->type = A_INTEGER; + integer_used = 1; + get_token(mpl /* integer */); + } + else if (is_keyword(mpl, "binary")) +bin: { if (binary_used) + error(mpl, "at most one binary allowed"); + if (par->type == A_SYMBOLIC) + error(mpl, "symbolic parameter cannot be binary"); + par->type = A_BINARY; + binary_used = 1; + get_token(mpl /* binary */); + } + else if (is_keyword(mpl, "logical")) + { if (!mpl->as_binary) + { warning(mpl, "keyword logical understood as binary"); + mpl->as_binary = 1; + } + goto bin; + } + else if (is_keyword(mpl, "symbolic")) + { if (symbolic_used) + error(mpl, "at most one symbolic allowed"); + if (par->type != A_NUMERIC) + error(mpl, "integer or binary parameter cannot be symbol" + "ic"); + /* the parameter may be referenced from expressions given + in the same parameter declaration, so its type must be + completed before parsing that expressions */ + if (!(par->cond == NULL && par->in == NULL && + par->assign == NULL && par->option == NULL)) + error(mpl, "keyword symbolic must precede any other para" + "meter attributes"); + par->type = A_SYMBOLIC; + symbolic_used = 1; + get_token(mpl /* symbolic */); + } + else if (mpl->token == T_LT || mpl->token == T_LE || + mpl->token == T_EQ || mpl->token == T_GE || + mpl->token == T_GT || mpl->token == T_NE) + { /* restricting condition */ + CONDITION *cond, *temp; + char opstr[8]; + /* create new restricting condition list entry and append + it to the conditions list */ + cond = alloc(CONDITION); + switch (mpl->token) + { case T_LT: + cond->rho = O_LT, strcpy(opstr, mpl->image); break; + case T_LE: + cond->rho = O_LE, strcpy(opstr, mpl->image); break; + case T_EQ: + cond->rho = O_EQ, strcpy(opstr, mpl->image); break; + case T_GE: + cond->rho = O_GE, strcpy(opstr, mpl->image); break; + case T_GT: + cond->rho = O_GT, strcpy(opstr, mpl->image); break; + case T_NE: + cond->rho = O_NE, strcpy(opstr, mpl->image); break; + default: + xassert(mpl->token != mpl->token); + } + xassert(strlen(opstr) < sizeof(opstr)); + cond->code = NULL; + cond->next = NULL; + if (par->cond == NULL) + par->cond = cond; + else + { for (temp = par->cond; temp->next != NULL; temp = + temp->next); + temp->next = cond; + } +#if 0 /* 13/VIII-2008 */ + if (par->type == A_SYMBOLIC && + !(cond->rho == O_EQ || cond->rho == O_NE)) + error(mpl, "inequality restriction not allowed"); +#endif + get_token(mpl /* rho */); + /* parse an expression that follows relational operator */ + cond->code = expression_5(mpl); + if (!(cond->code->type == A_NUMERIC || + cond->code->type == A_SYMBOLIC)) + error(mpl, "expression following %s has invalid type", + opstr); + xassert(cond->code->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && cond->code->type == + A_SYMBOLIC) + cond->code = make_unary(mpl, O_CVTNUM, cond->code, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && cond->code->type != + A_SYMBOLIC) + cond->code = make_unary(mpl, O_CVTSYM, cond->code, + A_SYMBOLIC, 0); + } + else if (mpl->token == T_IN || mpl->token == T_WITHIN) + { /* restricting superset */ + WITHIN *in, *temp; + if (mpl->token == T_WITHIN && !mpl->as_in) + { warning(mpl, "keyword within understood as in"); + mpl->as_in = 1; + } + get_token(mpl /* in */); + /* create new restricting superset list entry and append it + to the in-list */ + in = alloc(WITHIN); + in->code = NULL; + in->next = NULL; + if (par->in == NULL) + par->in = in; + else + { for (temp = par->in; temp->next != NULL; temp = + temp->next); + temp->next = in; + } + /* parse an expression that follows 'in' */ + in->code = expression_9(mpl); + if (in->code->type != A_ELEMSET) + error(mpl, "expression following in has invalid type"); + xassert(in->code->dim > 0); + if (in->code->dim != 1) + error(mpl, "set expression following in must have dimens" + "ion 1 rather than %d", in->code->dim); + } + else if (mpl->token == T_ASSIGN) + { /* assignment expression */ + if (!(par->assign == NULL && par->option == NULL)) +err: error(mpl, "at most one := or default allowed"); + get_token(mpl /* := */); + /* parse an expression that follows ':=' */ + par->assign = expression_5(mpl); + /* the expression must be of numeric/symbolic type */ + if (!(par->assign->type == A_NUMERIC || + par->assign->type == A_SYMBOLIC)) + error(mpl, "expression following := has invalid type"); + xassert(par->assign->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && par->assign->type == + A_SYMBOLIC) + par->assign = make_unary(mpl, O_CVTNUM, par->assign, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && par->assign->type != + A_SYMBOLIC) + par->assign = make_unary(mpl, O_CVTSYM, par->assign, + A_SYMBOLIC, 0); + } + else if (is_keyword(mpl, "default")) + { /* expression for default value */ + if (!(par->assign == NULL && par->option == NULL)) goto err; + get_token(mpl /* default */); + /* parse an expression that follows 'default' */ + par->option = expression_5(mpl); + if (!(par->option->type == A_NUMERIC || + par->option->type == A_SYMBOLIC)) + error(mpl, "expression following default has invalid typ" + "e"); + xassert(par->option->dim == 0); + /* convert to the parameter type, if necessary */ + if (par->type != A_SYMBOLIC && par->option->type == + A_SYMBOLIC) + par->option = make_unary(mpl, O_CVTNUM, par->option, + A_NUMERIC, 0); + if (par->type == A_SYMBOLIC && par->option->type != + A_SYMBOLIC) + par->option = make_unary(mpl, O_CVTSYM, par->option, + A_SYMBOLIC, 0); + } + else + error(mpl, "syntax error in parameter statement"); + } + /* close the domain scope */ + if (par->domain != NULL) close_scope(mpl, par->domain); + /* the parameter statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return par; +} + +/*---------------------------------------------------------------------- +-- variable_statement - parse variable statement. +-- +-- This routine parses variable statement using the syntax: +-- +-- ::= var +-- ; +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= , integer +-- ::= , binary +-- ::= , +-- ::= >= | <= | = | == +-- +-- Commae in are optional and may be omitted anywhere. */ + +VARIABLE *variable_statement(MPL *mpl) +{ VARIABLE *var; + int integer_used = 0, binary_used = 0; + xassert(is_keyword(mpl, "var")); + if (mpl->flag_s) + error(mpl, "variable statement must precede solve statement"); + get_token(mpl /* var */); + /* symbolic name must follow the keyword 'var' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model variable */ + var = alloc(VARIABLE); + var->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(var->name, mpl->image); + var->alias = NULL; + var->dim = 0; + var->domain = NULL; + var->type = A_NUMERIC; + var->lbnd = NULL; + var->ubnd = NULL; + var->array = NULL; + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { var->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(var->alias, mpl->image); + get_token(mpl /* */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { var->domain = indexing_expression(mpl); + var->dim = domain_arity(mpl, var->domain); + } + /* include the variable name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, var->name); + avl_set_node_type(node, A_VARIABLE); + avl_set_node_link(node, (void *)var); + } + /* parse the list of optional attributes */ + for (;;) + { if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + if (is_keyword(mpl, "integer")) + { if (integer_used) + error(mpl, "at most one integer allowed"); + if (var->type != A_BINARY) var->type = A_INTEGER; + integer_used = 1; + get_token(mpl /* integer */); + } + else if (is_keyword(mpl, "binary")) +bin: { if (binary_used) + error(mpl, "at most one binary allowed"); + var->type = A_BINARY; + binary_used = 1; + get_token(mpl /* binary */); + } + else if (is_keyword(mpl, "logical")) + { if (!mpl->as_binary) + { warning(mpl, "keyword logical understood as binary"); + mpl->as_binary = 1; + } + goto bin; + } + else if (is_keyword(mpl, "symbolic")) + error(mpl, "variable cannot be symbolic"); + else if (mpl->token == T_GE) + { /* lower bound */ + if (var->lbnd != NULL) + { if (var->lbnd == var->ubnd) + error(mpl, "both fixed value and lower bound not allo" + "wed"); + else + error(mpl, "at most one lower bound allowed"); + } + get_token(mpl /* >= */); + /* parse an expression that specifies the lower bound */ + var->lbnd = expression_5(mpl); + if (var->lbnd->type == A_SYMBOLIC) + var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, + A_NUMERIC, 0); + if (var->lbnd->type != A_NUMERIC) + error(mpl, "expression following >= has invalid type"); + xassert(var->lbnd->dim == 0); + } + else if (mpl->token == T_LE) + { /* upper bound */ + if (var->ubnd != NULL) + { if (var->ubnd == var->lbnd) + error(mpl, "both fixed value and upper bound not allo" + "wed"); + else + error(mpl, "at most one upper bound allowed"); + } + get_token(mpl /* <= */); + /* parse an expression that specifies the upper bound */ + var->ubnd = expression_5(mpl); + if (var->ubnd->type == A_SYMBOLIC) + var->ubnd = make_unary(mpl, O_CVTNUM, var->ubnd, + A_NUMERIC, 0); + if (var->ubnd->type != A_NUMERIC) + error(mpl, "expression following <= has invalid type"); + xassert(var->ubnd->dim == 0); + } + else if (mpl->token == T_EQ) + { /* fixed value */ + char opstr[8]; + if (!(var->lbnd == NULL && var->ubnd == NULL)) + { if (var->lbnd == var->ubnd) + error(mpl, "at most one fixed value allowed"); + else if (var->lbnd != NULL) + error(mpl, "both lower bound and fixed value not allo" + "wed"); + else + error(mpl, "both upper bound and fixed value not allo" + "wed"); + } + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* = | == */); + /* parse an expression that specifies the fixed value */ + var->lbnd = expression_5(mpl); + if (var->lbnd->type == A_SYMBOLIC) + var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, + A_NUMERIC, 0); + if (var->lbnd->type != A_NUMERIC) + error(mpl, "expression following %s has invalid type", + opstr); + xassert(var->lbnd->dim == 0); + /* indicate that the variable is fixed, not bounded */ + var->ubnd = var->lbnd; + } + else if (mpl->token == T_LT || mpl->token == T_GT || + mpl->token == T_NE) + error(mpl, "strict bound not allowed"); + else + error(mpl, "syntax error in variable statement"); + } + /* close the domain scope */ + if (var->domain != NULL) close_scope(mpl, var->domain); + /* the variable statement has been completely parsed */ + xassert(mpl->token == T_SEMICOLON); + get_token(mpl /* ; */); + return var; +} + +/*---------------------------------------------------------------------- +-- constraint_statement - parse constraint statement. +-- +-- This routine parses constraint statement using the syntax: +-- +-- ::= +-- : ; +-- ::= +-- ::= subject to +-- ::= subj to +-- ::= s.t. +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= , >= +-- ::= , <= +-- ::= , = +-- ::= , <= , <= +-- ::= , >= , >= +-- ::= +-- +-- Commae in are optional and may be omitted anywhere. */ + +CONSTRAINT *constraint_statement(MPL *mpl) +{ CONSTRAINT *con; + CODE *first, *second, *third; + int rho; + char opstr[8]; + if (mpl->flag_s) + error(mpl, "constraint statement must precede solve statement") + ; + if (is_keyword(mpl, "subject")) + { get_token(mpl /* subject */); + if (!is_keyword(mpl, "to")) + error(mpl, "keyword subject to incomplete"); + get_token(mpl /* to */); + } + else if (is_keyword(mpl, "subj")) + { get_token(mpl /* subj */); + if (!is_keyword(mpl, "to")) + error(mpl, "keyword subj to incomplete"); + get_token(mpl /* to */); + } + else if (mpl->token == T_SPTP) + get_token(mpl /* s.t. */); + /* the current token must be symbolic name of constraint */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model constraint */ + con = alloc(CONSTRAINT); + con->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(con->name, mpl->image); + con->alias = NULL; + con->dim = 0; + con->domain = NULL; + con->type = A_CONSTRAINT; + con->code = NULL; + con->lbnd = NULL; + con->ubnd = NULL; + con->array = NULL; + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { con->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(con->alias, mpl->image); + get_token(mpl /* */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { con->domain = indexing_expression(mpl); + con->dim = domain_arity(mpl, con->domain); + } + /* include the constraint name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, con->name); + avl_set_node_type(node, A_CONSTRAINT); + avl_set_node_link(node, (void *)con); + } + /* the colon must precede the first expression */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + get_token(mpl /* : */); + /* parse the first expression */ + first = expression_5(mpl); + if (first->type == A_SYMBOLIC) + first = make_unary(mpl, O_CVTNUM, first, A_NUMERIC, 0); + if (!(first->type == A_NUMERIC || first->type == A_FORMULA)) + error(mpl, "expression following colon has invalid type"); + xassert(first->dim == 0); + /* relational operator must follow the first expression */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + switch (mpl->token) + { case T_LE: + case T_GE: + case T_EQ: + break; + case T_LT: + case T_GT: + case T_NE: + error(mpl, "strict inequality not allowed"); + case T_SEMICOLON: + error(mpl, "constraint must be equality or inequality"); + default: + goto err; + } + rho = mpl->token; + strcpy(opstr, mpl->image); + xassert(strlen(opstr) < sizeof(opstr)); + get_token(mpl /* rho */); + /* parse the second expression */ + second = expression_5(mpl); + if (second->type == A_SYMBOLIC) + second = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); + if (!(second->type == A_NUMERIC || second->type == A_FORMULA)) + error(mpl, "expression following %s has invalid type", opstr); + xassert(second->dim == 0); + /* check a token that follow the second expression */ + if (mpl->token == T_COMMA) + { get_token(mpl /* , */); + if (mpl->token == T_SEMICOLON) goto err; + } + if (mpl->token == T_LT || mpl->token == T_LE || + mpl->token == T_EQ || mpl->token == T_GE || + mpl->token == T_GT || mpl->token == T_NE) + { /* it is another relational operator, therefore the constraint + is double inequality */ + if (rho == T_EQ || mpl->token != rho) + error(mpl, "double inequality must be ... <= ... <= ... or " + "... >= ... >= ..."); + /* the first expression cannot be linear form */ + if (first->type == A_FORMULA) + error(mpl, "leftmost expression in double inequality cannot" + " be linear form"); + get_token(mpl /* rho */); + /* parse the third expression */ + third = expression_5(mpl); + if (third->type == A_SYMBOLIC) + third = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); + if (!(third->type == A_NUMERIC || third->type == A_FORMULA)) + error(mpl, "rightmost expression in double inequality const" + "raint has invalid type"); + xassert(third->dim == 0); + /* the third expression also cannot be linear form */ + if (third->type == A_FORMULA) + error(mpl, "rightmost expression in double inequality canno" + "t be linear form"); + } + else + { /* the constraint is equality or single inequality */ + third = NULL; + } + /* close the domain scope */ + if (con->domain != NULL) close_scope(mpl, con->domain); + /* convert all expressions to linear form, if necessary */ + if (first->type != A_FORMULA) + first = make_unary(mpl, O_CVTLFM, first, A_FORMULA, 0); + if (second->type != A_FORMULA) + second = make_unary(mpl, O_CVTLFM, second, A_FORMULA, 0); + if (third != NULL) + third = make_unary(mpl, O_CVTLFM, third, A_FORMULA, 0); + /* arrange expressions in the constraint */ + if (third == NULL) + { /* the constraint is equality or single inequality */ + switch (rho) + { case T_LE: + /* first <= second */ + con->code = first; + con->lbnd = NULL; + con->ubnd = second; + break; + case T_GE: + /* first >= second */ + con->code = first; + con->lbnd = second; + con->ubnd = NULL; + break; + case T_EQ: + /* first = second */ + con->code = first; + con->lbnd = second; + con->ubnd = second; + break; + default: + xassert(rho != rho); + } + } + else + { /* the constraint is double inequality */ + switch (rho) + { case T_LE: + /* first <= second <= third */ + con->code = second; + con->lbnd = first; + con->ubnd = third; + break; + case T_GE: + /* first >= second >= third */ + con->code = second; + con->lbnd = third; + con->ubnd = first; + break; + default: + xassert(rho != rho); + } + } + /* the constraint statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) +err: error(mpl, "syntax error in constraint statement"); + get_token(mpl /* ; */); + return con; +} + +/*---------------------------------------------------------------------- +-- objective_statement - parse objective statement. +-- +-- This routine parses objective statement using the syntax: +-- +-- ::= : +-- ; +-- ::= minimize +-- ::= maximize +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= */ + +CONSTRAINT *objective_statement(MPL *mpl) +{ CONSTRAINT *obj; + int type; + if (is_keyword(mpl, "minimize")) + type = A_MINIMIZE; + else if (is_keyword(mpl, "maximize")) + type = A_MAXIMIZE; + else + xassert(mpl != mpl); + if (mpl->flag_s) + error(mpl, "objective statement must precede solve statement"); + get_token(mpl /* minimize | maximize */); + /* symbolic name must follow the verb 'minimize' or 'maximize' */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create model objective */ + obj = alloc(CONSTRAINT); + obj->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(obj->name, mpl->image); + obj->alias = NULL; + obj->dim = 0; + obj->domain = NULL; + obj->type = type; + obj->code = NULL; + obj->lbnd = NULL; + obj->ubnd = NULL; + obj->array = NULL; + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { obj->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(obj->alias, mpl->image); + get_token(mpl /* */); + } + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { obj->domain = indexing_expression(mpl); + obj->dim = domain_arity(mpl, obj->domain); + } + /* include the constraint name in the symbolic names table */ + { AVLNODE *node; + node = avl_insert_node(mpl->tree, obj->name); + avl_set_node_type(node, A_CONSTRAINT); + avl_set_node_link(node, (void *)obj); + } + /* the colon must precede the objective expression */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + get_token(mpl /* : */); + /* parse the objective expression */ + obj->code = expression_5(mpl); + if (obj->code->type == A_SYMBOLIC) + obj->code = make_unary(mpl, O_CVTNUM, obj->code, A_NUMERIC, 0); + if (obj->code->type == A_NUMERIC) + obj->code = make_unary(mpl, O_CVTLFM, obj->code, A_FORMULA, 0); + if (obj->code->type != A_FORMULA) + error(mpl, "expression following colon has invalid type"); + xassert(obj->code->dim == 0); + /* close the domain scope */ + if (obj->domain != NULL) close_scope(mpl, obj->domain); + /* the objective statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in objective statement"); + get_token(mpl /* ; */); + return obj; +} + +#if 1 /* 11/II-2008 */ +/*********************************************************************** +* table_statement - parse table statement +* +* This routine parses table statement using the syntax: +* +* ::= +*
::= +* +* ::= +* table
IN : +* [ ] , ; +* ::= +* ::= +* ::= +* ::= +* ::= , +* ::= +* ::= <- +* ::= +* ::= , +* ::= +* ::= , +* ::= +* ::= ~ +* +* ::= +* table
OUT : +* ; +* ::= +* ::= +* ::= , +* ::= +* ::= ~ */ + +TABLE *table_statement(MPL *mpl) +{ TABLE *tab; + TABARG *last_arg, *arg; + TABFLD *last_fld, *fld; + TABIN *last_in, *in; + TABOUT *last_out, *out; + AVLNODE *node; + int nflds; + char name[MAX_LENGTH+1]; + xassert(is_keyword(mpl, "table")); + get_token(mpl /* solve */); + /* symbolic name must follow the keyword table */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "symbolic name missing where expected"); + /* there must be no other object with the same name */ + if (avl_find_node(mpl->tree, mpl->image) != NULL) + error(mpl, "%s multiply declared", mpl->image); + /* create data table */ + tab = alloc(TABLE); + tab->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(tab->name, mpl->image); + get_token(mpl /* */); + /* parse optional alias */ + if (mpl->token == T_STRING) + { tab->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(tab->alias, mpl->image); + get_token(mpl /* */); + } + else + tab->alias = NULL; + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { /* this is output table */ + tab->type = A_OUTPUT; + tab->u.out.domain = indexing_expression(mpl); + if (!is_keyword(mpl, "OUT")) + error(mpl, "keyword OUT missing where expected"); + get_token(mpl /* OUT */); + } + else + { /* this is input table */ + tab->type = A_INPUT; + if (!is_keyword(mpl, "IN")) + error(mpl, "keyword IN missing where expected"); + get_token(mpl /* IN */); + } + /* parse argument list */ + tab->arg = last_arg = NULL; + for (;;) + { /* create argument list entry */ + arg = alloc(TABARG); + /* parse argument expression */ + if (mpl->token == T_COMMA || mpl->token == T_COLON || + mpl->token == T_SEMICOLON) + error(mpl, "argument expression missing where expected"); + arg->code = expression_5(mpl); + /* convert the result to symbolic type, if necessary */ + if (arg->code->type == A_NUMERIC) + arg->code = + make_unary(mpl, O_CVTSYM, arg->code, A_SYMBOLIC, 0); + /* check that now the result is of symbolic type */ + if (arg->code->type != A_SYMBOLIC) + error(mpl, "argument expression has invalid type"); + /* add the entry to the end of the list */ + arg->next = NULL; + if (last_arg == NULL) + tab->arg = arg; + else + last_arg->next = arg; + last_arg = arg; + /* argument expression has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_COLON || mpl->token == T_SEMICOLON) + break; + } + xassert(tab->arg != NULL); + /* argument list must end with colon */ + if (mpl->token == T_COLON) + get_token(mpl /* : */); + else + error(mpl, "colon missing where expected"); + /* parse specific part of the table statement */ + switch (tab->type) + { case A_INPUT: goto input_table; + case A_OUTPUT: goto output_table; + default: xassert(tab != tab); + } +input_table: + /* parse optional set name */ + if (mpl->token == T_NAME) + { node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_SET) + error(mpl, "%s not a set", mpl->image); + tab->u.in.set = (SET *)avl_get_node_link(node); + if (tab->u.in.set->assign != NULL) + error(mpl, "%s needs no data", mpl->image); + if (tab->u.in.set->dim != 0) + error(mpl, "%s must be a simple set", mpl->image); + get_token(mpl /* */); + if (mpl->token == T_INPUT) + get_token(mpl /* <- */); + else + error(mpl, "delimiter <- missing where expected"); + } + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + tab->u.in.set = NULL; + /* parse field list */ + tab->u.in.fld = last_fld = NULL; + nflds = 0; + if (mpl->token == T_LBRACKET) + get_token(mpl /* [ */); + else + error(mpl, "field list missing where expected"); + for (;;) + { /* create field list entry */ + fld = alloc(TABFLD); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + fld->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); + strcpy(fld->name, mpl->image); + get_token(mpl /* */); + /* add the entry to the end of the list */ + fld->next = NULL; + if (last_fld == NULL) + tab->u.in.fld = fld; + else + last_fld->next = fld; + last_fld = fld; + nflds++; + /* field name has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in field list"); + } + /* check that the set dimen is equal to the number of fields */ + if (tab->u.in.set != NULL && tab->u.in.set->dimen != nflds) + error(mpl, "there must be %d field%s rather than %d", + tab->u.in.set->dimen, tab->u.in.set->dimen == 1 ? "" : "s", + nflds); + get_token(mpl /* ] */); + /* parse optional input list */ + tab->u.in.list = last_in = NULL; + while (mpl->token == T_COMMA) + { get_token(mpl /* , */); + /* create input list entry */ + in = alloc(TABIN); + /* parse parameter name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "parameter name missing where expected"); + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + if (avl_get_node_type(node) != A_PARAMETER) + error(mpl, "%s not a parameter", mpl->image); + in->par = (PARAMETER *)avl_get_node_link(node); + if (in->par->dim != nflds) + error(mpl, "%s must have %d subscript%s rather than %d", + mpl->image, nflds, nflds == 1 ? "" : "s", in->par->dim); + if (in->par->assign != NULL) + error(mpl, "%s needs no data", mpl->image); + get_token(mpl /* */); + /* parse optional field name */ + if (mpl->token == T_TILDE) + { get_token(mpl /* ~ */); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + get_token(mpl /* */); + } + else + { /* field name is the same as the parameter name */ + xassert(strlen(in->par->name) < sizeof(name)); + strcpy(name, in->par->name); + } + /* assign field name */ + in->name = dmp_get_atomv(mpl->pool, strlen(name)+1); + strcpy(in->name, name); + /* add the entry to the end of the list */ + in->next = NULL; + if (last_in == NULL) + tab->u.in.list = in; + else + last_in->next = in; + last_in = in; + } + goto end_of_table; +output_table: + /* parse output list */ + tab->u.out.list = last_out = NULL; + for (;;) + { /* create output list entry */ + out = alloc(TABOUT); + /* parse expression */ + if (mpl->token == T_COMMA || mpl->token == T_SEMICOLON) + error(mpl, "expression missing where expected"); + if (mpl->token == T_NAME) + { xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + } + else + name[0] = '\0'; + out->code = expression_5(mpl); + /* parse optional field name */ + if (mpl->token == T_TILDE) + { get_token(mpl /* ~ */); + /* parse field name */ + if (mpl->token == T_NAME) + ; + else if (is_reserved(mpl)) + error(mpl, + "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "field name missing where expected"); + xassert(strlen(mpl->image) < sizeof(name)); + strcpy(name, mpl->image); + get_token(mpl /* */); + } + /* assign field name */ + if (name[0] == '\0') + error(mpl, "field name required"); + out->name = dmp_get_atomv(mpl->pool, strlen(name)+1); + strcpy(out->name, name); + /* add the entry to the end of the list */ + out->next = NULL; + if (last_out == NULL) + tab->u.out.list = out; + else + last_out->next = out; + last_out = out; + /* output item has been parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_SEMICOLON) + break; + else + error(mpl, "syntax error in output list"); + } + /* close the domain scope */ + close_scope(mpl,tab->u.out.domain); +end_of_table: + /* the table statement must end with semicolon */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in table statement"); + get_token(mpl /* ; */); + return tab; +} +#endif + +/*---------------------------------------------------------------------- +-- solve_statement - parse solve statement. +-- +-- This routine parses solve statement using the syntax: +-- +-- ::= solve ; +-- +-- The solve statement can be used at most once. */ + +void *solve_statement(MPL *mpl) +{ xassert(is_keyword(mpl, "solve")); + if (mpl->flag_s) + error(mpl, "at most one solve statement allowed"); + mpl->flag_s = 1; + get_token(mpl /* solve */); + /* semicolon must follow solve statement */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in solve statement"); + get_token(mpl /* ; */); + return NULL; +} + +/*---------------------------------------------------------------------- +-- check_statement - parse check statement. +-- +-- This routine parses check statement using the syntax: +-- +-- ::= check : ; +-- ::= +-- ::= +-- +-- If is omitted, colon following it may also be omitted. */ + +CHECK *check_statement(MPL *mpl) +{ CHECK *chk; + xassert(is_keyword(mpl, "check")); + /* create check descriptor */ + chk = alloc(CHECK); + chk->domain = NULL; + chk->code = NULL; + get_token(mpl /* check */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { chk->domain = indexing_expression(mpl); +#if 0 + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); +#endif + } + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse logical expression */ + chk->code = expression_13(mpl); + if (chk->code->type != A_LOGICAL) + error(mpl, "expression has invalid type"); + xassert(chk->code->dim == 0); + /* close the domain scope */ + if (chk->domain != NULL) close_scope(mpl, chk->domain); + /* the check statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in check statement"); + get_token(mpl /* ; */); + return chk; +} + +#if 1 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- display_statement - parse display statement. +-- +-- This routine parses display statement using the syntax: +-- +-- ::= display : ; +-- ::= display ; +-- ::= +-- ::= +-- ::= +-- ::= , +-- ::= +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= +-- ::= [ ] +-- ::= */ + +DISPLAY *display_statement(MPL *mpl) +{ DISPLAY *dpy; + DISPLAY1 *entry, *last_entry; + xassert(is_keyword(mpl, "display")); + /* create display descriptor */ + dpy = alloc(DISPLAY); + dpy->domain = NULL; + dpy->list = last_entry = NULL; + get_token(mpl /* display */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + dpy->domain = indexing_expression(mpl); + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse display list */ + for (;;) + { /* create new display entry */ + entry = alloc(DISPLAY1); + entry->type = 0; + entry->next = NULL; + /* and append it to the display list */ + if (dpy->list == NULL) + dpy->list = entry; + else + last_entry->next = entry; + last_entry = entry; + /* parse display entry */ + if (mpl->token == T_NAME) + { AVLNODE *node; + int next_token; + get_token(mpl /* */); + next_token = mpl->token; + unget_token(mpl); + if (!(next_token == T_COMMA || next_token == T_SEMICOLON)) + { /* symbolic name begins expression */ + goto expr; + } + /* display entry is dummy index or model object */ + node = avl_find_node(mpl->tree, mpl->image); + if (node == NULL) + error(mpl, "%s not defined", mpl->image); + entry->type = avl_get_node_type(node); + switch (avl_get_node_type(node)) + { case A_INDEX: + entry->u.slot = + (DOMAIN_SLOT *)avl_get_node_link(node); + break; + case A_SET: + entry->u.set = (SET *)avl_get_node_link(node); + break; + case A_PARAMETER: + entry->u.par = (PARAMETER *)avl_get_node_link(node); + break; + case A_VARIABLE: + entry->u.var = (VARIABLE *)avl_get_node_link(node); + if (!mpl->flag_s) + error(mpl, "invalid reference to variable %s above" + " solve statement", entry->u.var->name); + break; + case A_CONSTRAINT: + entry->u.con = (CONSTRAINT *)avl_get_node_link(node); + if (!mpl->flag_s) + error(mpl, "invalid reference to %s %s above solve" + " statement", + entry->u.con->type == A_CONSTRAINT ? + "constraint" : "objective", entry->u.con->name); + break; + default: + xassert(node != node); + } + get_token(mpl /* */); + } + else +expr: { /* display entry is expression */ + entry->type = A_EXPRESSION; + entry->u.code = expression_13(mpl); + } + /* check a token that follows the entry parsed */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else + break; + } + /* close the domain scope */ + if (dpy->domain != NULL) close_scope(mpl, dpy->domain); + /* the display statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in display statement"); + get_token(mpl /* ; */); + return dpy; +} +#endif + +/*---------------------------------------------------------------------- +-- printf_statement - parse printf statement. +-- +-- This routine parses print statement using the syntax: +-- +-- ::= ; +-- ::= > ; +-- ::= >> ; +-- ::= printf : +-- ::= printf +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= , +-- ::= +-- ::= */ + +PRINTF *printf_statement(MPL *mpl) +{ PRINTF *prt; + PRINTF1 *entry, *last_entry; + xassert(is_keyword(mpl, "printf")); + /* create printf descriptor */ + prt = alloc(PRINTF); + prt->domain = NULL; + prt->fmt = NULL; + prt->list = last_entry = NULL; + get_token(mpl /* printf */); + /* parse optional indexing expression */ + if (mpl->token == T_LBRACE) + { prt->domain = indexing_expression(mpl); +#if 0 + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); +#endif + } + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse expression for format string */ + prt->fmt = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (prt->fmt->type == A_NUMERIC) + prt->fmt = make_unary(mpl, O_CVTSYM, prt->fmt, A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (prt->fmt->type != A_SYMBOLIC) + error(mpl, "format expression has invalid type"); + /* parse printf list */ + while (mpl->token == T_COMMA) + { get_token(mpl /* , */); + /* create new printf entry */ + entry = alloc(PRINTF1); + entry->code = NULL; + entry->next = NULL; + /* and append it to the printf list */ + if (prt->list == NULL) + prt->list = entry; + else + last_entry->next = entry; + last_entry = entry; + /* parse printf entry */ + entry->code = expression_9(mpl); + if (!(entry->code->type == A_NUMERIC || + entry->code->type == A_SYMBOLIC || + entry->code->type == A_LOGICAL)) + error(mpl, "only numeric, symbolic, or logical expression a" + "llowed"); + } + /* close the domain scope */ + if (prt->domain != NULL) close_scope(mpl, prt->domain); +#if 1 /* 14/VII-2006 */ + /* parse optional redirection */ + prt->fname = NULL, prt->app = 0; + if (mpl->token == T_GT || mpl->token == T_APPEND) + { prt->app = (mpl->token == T_APPEND); + get_token(mpl /* > or >> */); + /* parse expression for file name string */ + prt->fname = expression_5(mpl); + /* convert it to symbolic type, if necessary */ + if (prt->fname->type == A_NUMERIC) + prt->fname = make_unary(mpl, O_CVTSYM, prt->fname, + A_SYMBOLIC, 0); + /* check that now the expression is of symbolic type */ + if (prt->fname->type != A_SYMBOLIC) + error(mpl, "file name expression has invalid type"); + } +#endif + /* the printf statement has been completely parsed */ + if (mpl->token != T_SEMICOLON) + error(mpl, "syntax error in printf statement"); + get_token(mpl /* ; */); + return prt; +} + +/*---------------------------------------------------------------------- +-- for_statement - parse for statement. +-- +-- This routine parses for statement using the syntax: +-- +-- ::= for +-- ::= for { } +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= */ + +FOR *for_statement(MPL *mpl) +{ FOR *fur; + STATEMENT *stmt, *last_stmt; + xassert(is_keyword(mpl, "for")); + /* create for descriptor */ + fur = alloc(FOR); + fur->domain = NULL; + fur->list = last_stmt = NULL; + get_token(mpl /* for */); + /* parse indexing expression */ + if (mpl->token != T_LBRACE) + error(mpl, "indexing expression missing where expected"); + fur->domain = indexing_expression(mpl); + /* skip optional colon */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* parse for statement body */ + if (mpl->token != T_LBRACE) + { /* parse simple statement */ + fur->list = simple_statement(mpl, 1); + } + else + { /* parse compound statement */ + get_token(mpl /* { */); + while (mpl->token != T_RBRACE) + { /* parse statement */ + stmt = simple_statement(mpl, 1); + /* and append it to the end of the statement list */ + if (last_stmt == NULL) + fur->list = stmt; + else + last_stmt->next = stmt; + last_stmt = stmt; + } + get_token(mpl /* } */); + } + /* close the domain scope */ + xassert(fur->domain != NULL); + close_scope(mpl, fur->domain); + /* the for statement has been completely parsed */ + return fur; +} + +/*---------------------------------------------------------------------- +-- end_statement - parse end statement. +-- +-- This routine parses end statement using the syntax: +-- +-- ::= end ; */ + +void end_statement(MPL *mpl) +{ if (!mpl->flag_d && is_keyword(mpl, "end") || + mpl->flag_d && is_literal(mpl, "end")) + { get_token(mpl /* end */); + if (mpl->token == T_SEMICOLON) + get_token(mpl /* ; */); + else + warning(mpl, "no semicolon following end statement; missing" + " semicolon inserted"); + } + else + warning(mpl, "unexpected end of file; missing end statement in" + "serted"); + if (mpl->token != T_EOF) + warning(mpl, "some text detected beyond end statement; text ig" + "nored"); + return; +} + +/*---------------------------------------------------------------------- +-- simple_statement - parse simple statement. +-- +-- This routine parses simple statement using the syntax: +-- +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- ::= +-- +-- If the flag spec is set, some statements cannot be used. */ + +STATEMENT *simple_statement(MPL *mpl, int spec) +{ STATEMENT *stmt; + stmt = alloc(STATEMENT); + stmt->line = mpl->line; + stmt->next = NULL; + if (is_keyword(mpl, "set")) + { if (spec) + error(mpl, "set statement not allowed here"); + stmt->type = A_SET; + stmt->u.set = set_statement(mpl); + } + else if (is_keyword(mpl, "param")) + { if (spec) + error(mpl, "parameter statement not allowed here"); + stmt->type = A_PARAMETER; + stmt->u.par = parameter_statement(mpl); + } + else if (is_keyword(mpl, "var")) + { if (spec) + error(mpl, "variable statement not allowed here"); + stmt->type = A_VARIABLE; + stmt->u.var = variable_statement(mpl); + } + else if (is_keyword(mpl, "subject") || + is_keyword(mpl, "subj") || + mpl->token == T_SPTP) + { if (spec) + error(mpl, "constraint statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = constraint_statement(mpl); + } + else if (is_keyword(mpl, "minimize") || + is_keyword(mpl, "maximize")) + { if (spec) + error(mpl, "objective statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = objective_statement(mpl); + } +#if 1 /* 11/II-2008 */ + else if (is_keyword(mpl, "table")) + { if (spec) + error(mpl, "table statement not allowed here"); + stmt->type = A_TABLE; + stmt->u.tab = table_statement(mpl); + } +#endif + else if (is_keyword(mpl, "solve")) + { if (spec) + error(mpl, "solve statement not allowed here"); + stmt->type = A_SOLVE; + stmt->u.slv = solve_statement(mpl); + } + else if (is_keyword(mpl, "check")) + { stmt->type = A_CHECK; + stmt->u.chk = check_statement(mpl); + } + else if (is_keyword(mpl, "display")) + { stmt->type = A_DISPLAY; + stmt->u.dpy = display_statement(mpl); + } + else if (is_keyword(mpl, "printf")) + { stmt->type = A_PRINTF; + stmt->u.prt = printf_statement(mpl); + } + else if (is_keyword(mpl, "for")) + { stmt->type = A_FOR; + stmt->u.fur = for_statement(mpl); + } + else if (mpl->token == T_NAME) + { if (spec) + error(mpl, "constraint statement not allowed here"); + stmt->type = A_CONSTRAINT; + stmt->u.con = constraint_statement(mpl); + } + else if (is_reserved(mpl)) + error(mpl, "invalid use of reserved keyword %s", mpl->image); + else + error(mpl, "syntax error in model section"); + return stmt; +} + +/*---------------------------------------------------------------------- +-- model_section - parse model section. +-- +-- This routine parses model section using the syntax: +-- +-- ::= +-- ::= +-- +-- Parsing model section is terminated by either the keyword 'data', or +-- the keyword 'end', or the end of file. */ + +void model_section(MPL *mpl) +{ STATEMENT *stmt, *last_stmt; + xassert(mpl->model == NULL); + last_stmt = NULL; + while (!(mpl->token == T_EOF || is_keyword(mpl, "data") || + is_keyword(mpl, "end"))) + { /* parse statement */ + stmt = simple_statement(mpl, 0); + /* and append it to the end of the statement list */ + if (last_stmt == NULL) + mpl->model = stmt; + else + last_stmt->next = stmt; + last_stmt = stmt; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl2.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl2.c new file mode 100644 index 000000000..0f99528b9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl2.c @@ -0,0 +1,1202 @@ +/* mpl2.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" + +/**********************************************************************/ +/* * * PROCESSING DATA SECTION * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_slice - create slice. +-- +-- This routine creates a slice, which initially has no components. */ + +SLICE *create_slice(MPL *mpl) +{ SLICE *slice; + xassert(mpl == mpl); + slice = NULL; + return slice; +} + +/*---------------------------------------------------------------------- +-- expand_slice - append new component to slice. +-- +-- This routine expands slice appending to it either a given symbol or +-- null component, which becomes the last component of the slice. */ + +SLICE *expand_slice +( MPL *mpl, + SLICE *slice, /* destroyed */ + SYMBOL *sym /* destroyed */ +) +{ SLICE *tail, *temp; + /* create a new component */ + tail = dmp_get_atom(mpl->tuples, sizeof(SLICE)); + tail->sym = sym; + tail->next = NULL; + /* and append it to the component list */ + if (slice == NULL) + slice = tail; + else + { for (temp = slice; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return slice; +} + +/*---------------------------------------------------------------------- +-- slice_dimen - determine dimension of slice. +-- +-- This routine returns dimension of slice, which is number of all its +-- components including null ones. */ + +int slice_dimen +( MPL *mpl, + SLICE *slice /* not changed */ +) +{ SLICE *temp; + int dim; + xassert(mpl == mpl); + dim = 0; + for (temp = slice; temp != NULL; temp = temp->next) dim++; + return dim; +} + +/*---------------------------------------------------------------------- +-- slice_arity - determine arity of slice. +-- +-- This routine returns arity of slice, i.e. number of null components +-- (indicated by asterisks) in the slice. */ + +int slice_arity +( MPL *mpl, + SLICE *slice /* not changed */ +) +{ SLICE *temp; + int arity; + xassert(mpl == mpl); + arity = 0; + for (temp = slice; temp != NULL; temp = temp->next) + if (temp->sym == NULL) arity++; + return arity; +} + +/*---------------------------------------------------------------------- +-- fake_slice - create fake slice of all asterisks. +-- +-- This routine creates a fake slice of given dimension, which contains +-- asterisks in all components. Zero dimension is allowed. */ + +SLICE *fake_slice(MPL *mpl, int dim) +{ SLICE *slice; + slice = create_slice(mpl); + while (dim-- > 0) slice = expand_slice(mpl, slice, NULL); + return slice; +} + +/*---------------------------------------------------------------------- +-- delete_slice - delete slice. +-- +-- This routine deletes specified slice. */ + +void delete_slice +( MPL *mpl, + SLICE *slice /* destroyed */ +) +{ SLICE *temp; + while (slice != NULL) + { temp = slice; + slice = temp->next; + if (temp->sym != NULL) delete_symbol(mpl, temp->sym); +xassert(sizeof(SLICE) == sizeof(TUPLE)); + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + return; +} + +/*---------------------------------------------------------------------- +-- is_number - check if current token is number. +-- +-- If the current token is a number, this routine returns non-zero. +-- Otherwise zero is returned. */ + +int is_number(MPL *mpl) +{ return + mpl->token == T_NUMBER; +} + +/*---------------------------------------------------------------------- +-- is_symbol - check if current token is symbol. +-- +-- If the current token is suitable to be a symbol, the routine returns +-- non-zero. Otherwise zero is returned. */ + +int is_symbol(MPL *mpl) +{ return + mpl->token == T_NUMBER || + mpl->token == T_SYMBOL || + mpl->token == T_STRING; +} + +/*---------------------------------------------------------------------- +-- is_literal - check if current token is given symbolic literal. +-- +-- If the current token is given symbolic literal, this routine returns +-- non-zero. Otherwise zero is returned. +-- +-- This routine is used on processing the data section in the same way +-- as the routine is_keyword on processing the model section. */ + +int is_literal(MPL *mpl, char *literal) +{ return + is_symbol(mpl) && strcmp(mpl->image, literal) == 0; +} + +/*---------------------------------------------------------------------- +-- read_number - read number. +-- +-- This routine reads the current token, which must be a number, and +-- returns its numeric value. */ + +double read_number(MPL *mpl) +{ double num; + xassert(is_number(mpl)); + num = mpl->value; + get_token(mpl /* */); + return num; +} + +/*---------------------------------------------------------------------- +-- read_symbol - read symbol. +-- +-- This routine reads the current token, which must be a symbol, and +-- returns its symbolic value. */ + +SYMBOL *read_symbol(MPL *mpl) +{ SYMBOL *sym; + xassert(is_symbol(mpl)); + if (is_number(mpl)) + sym = create_symbol_num(mpl, mpl->value); + else + sym = create_symbol_str(mpl, create_string(mpl, mpl->image)); + get_token(mpl /* */); + return sym; +} + +/*---------------------------------------------------------------------- +-- read_slice - read slice. +-- +-- This routine reads slice using the syntax: +-- +-- ::= [ ] +-- ::= ( ) +-- ::= +-- ::= , +-- ::= +-- ::= * +-- +-- The bracketed form of slice is used for members of multi-dimensional +-- objects while the parenthesized form is used for elemental sets. */ + +SLICE *read_slice +( MPL *mpl, + char *name, /* not changed */ + int dim +) +{ SLICE *slice; + int close; + xassert(name != NULL); + switch (mpl->token) + { case T_LBRACKET: + close = T_RBRACKET; + break; + case T_LEFT: + xassert(dim > 0); + close = T_RIGHT; + break; + default: + xassert(mpl != mpl); + } + if (dim == 0) + error(mpl, "%s cannot be subscripted", name); + get_token(mpl /* ( | [ */); + /* read slice components */ + slice = create_slice(mpl); + for (;;) + { /* the current token must be a symbol or asterisk */ + if (is_symbol(mpl)) + slice = expand_slice(mpl, slice, read_symbol(mpl)); + else if (mpl->token == T_ASTERISK) + { slice = expand_slice(mpl, slice, NULL); + get_token(mpl /* * */); + } + else + error(mpl, "number, symbol, or asterisk missing where expec" + "ted"); + /* check a token that follows the symbol */ + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == close) + break; + else + error(mpl, "syntax error in slice"); + } + /* number of slice components must be the same as the appropriate + dimension */ + if (slice_dimen(mpl, slice) != dim) + { switch (close) + { case T_RBRACKET: + error(mpl, "%s must have %d subscript%s, not %d", name, + dim, dim == 1 ? "" : "s", slice_dimen(mpl, slice)); + break; + case T_RIGHT: + error(mpl, "%s has dimension %d, not %d", name, dim, + slice_dimen(mpl, slice)); + break; + default: + xassert(close != close); + } + } + get_token(mpl /* ) | ] */); + return slice; +} + +/*---------------------------------------------------------------------- +-- select_set - select set to saturate it with elemental sets. +-- +-- This routine selects set to saturate it with elemental sets provided +-- in the data section. */ + +SET *select_set +( MPL *mpl, + char *name /* not changed */ +) +{ SET *set; + AVLNODE *node; + xassert(name != NULL); + node = avl_find_node(mpl->tree, name); + if (node == NULL || avl_get_node_type(node) != A_SET) + error(mpl, "%s not a set", name); + set = (SET *)avl_get_node_link(node); + if (set->assign != NULL || set->gadget != NULL) + error(mpl, "%s needs no data", name); + set->data = 1; + return set; +} + +/*---------------------------------------------------------------------- +-- simple_format - read set data block in simple format. +-- +-- This routine reads set data block using the syntax: +-- +-- ::= , , ... , +-- +-- where are used to construct a complete n-tuple, which is +-- included in elemental set assigned to the set member. Commae between +-- symbols are optional and may be omitted anywhere. +-- +-- Number of components in the slice must be the same as dimension of +-- n-tuples in elemental sets assigned to the set members. To construct +-- complete n-tuple the routine replaces null positions in the slice by +-- corresponding . +-- +-- If the slice contains at least one null position, the current token +-- must be symbol. Otherwise, the routine reads no symbols to construct +-- the n-tuple, so the current token is not checked. */ + +void simple_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice /* not changed */ +) +{ TUPLE *tuple; + SLICE *temp; + SYMBOL *sym, *with = NULL; + xassert(set != NULL); + xassert(memb != NULL); + xassert(slice != NULL); + xassert(set->dimen == slice_dimen(mpl, slice)); + xassert(memb->value.set->dim == set->dimen); + if (slice_arity(mpl, slice) > 0) xassert(is_symbol(mpl)); + /* read symbols and construct complete n-tuple */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed; read symbol */ + if (!is_symbol(mpl)) + { int lack = slice_arity(mpl, temp); + /* with cannot be null due to assertion above */ + xassert(with != NULL); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, with)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, with)); + } + sym = read_symbol(mpl); + if (with == NULL) with = sym; + } + else + { /* copy symbol from the slice */ + sym = copy_symbol(mpl, temp->sym); + } + /* append the symbol to the n-tuple */ + tuple = expand_tuple(mpl, tuple, sym); + /* skip optional comma *between* */ + if (temp->next != NULL && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* add constructed n-tuple to elemental set */ + check_then_add(mpl, memb->value.set, tuple); + return; +} + +/*---------------------------------------------------------------------- +-- matrix_format - read set data block in matrix format. +-- +-- This routine reads set data block using the syntax: +-- +-- ::= ... := +-- +/- +/- ... +/- +-- +/- +/- ... +/- +-- . . . . . . . . . . . +-- +/- +/- ... +/- +-- +-- where are symbols that denote rows of the matrix, +-- are symbols that denote columns of the matrix, "+" and "-" indicate +-- whether corresponding n-tuple needs to be included in the elemental +-- set or not, respectively. +-- +-- Number of the slice components must be the same as dimension of the +-- elemental set. The slice must have two null positions. To construct +-- complete n-tuple for particular element of the matrix the routine +-- replaces first null position of the slice by the corresponding +-- (or , if the flag tr is on) and second null position by the +-- corresponding (or by , if the flag tr is on). */ + +void matrix_format +( MPL *mpl, + SET *set, /* not changed */ + MEMBER *memb, /* modified */ + SLICE *slice, /* not changed */ + int tr +) +{ SLICE *list, *col, *temp; + TUPLE *tuple; + SYMBOL *row; + xassert(set != NULL); + xassert(memb != NULL); + xassert(slice != NULL); + xassert(set->dimen == slice_dimen(mpl, slice)); + xassert(memb->value.set->dim == set->dimen); + xassert(slice_arity(mpl, slice) == 2); + /* read the matrix heading that contains column symbols (there + may be no columns at all) */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* read column symbol and append it to the column list */ + if (!is_symbol(mpl)) + error(mpl, "number, symbol, or := missing where expected"); + list = expand_slice(mpl, list, read_symbol(mpl)); + } + get_token(mpl /* := */); + /* read zero or more rows that contain matrix data */ + while (is_symbol(mpl)) + { /* read row symbol (if the matrix has no columns, row symbols + are just ignored) */ + row = read_symbol(mpl); + /* read the matrix row accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { int which = 0; + /* check indicator */ + if (is_literal(mpl, "+")) + ; + else if (is_literal(mpl, "-")) + { get_token(mpl /* - */); + continue; + } + else + { int lack = slice_dimen(mpl, col); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, row)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, row)); + } + /* construct complete n-tuple */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed */ + switch (++which) + { case 1: + /* substitute in the first null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? col->sym : row)); + break; + case 2: + /* substitute in the second null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? row : col->sym)); + break; + default: + xassert(which != which); + } + } + else + { /* copy symbol from the slice */ + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + } + } + xassert(which == 2); + /* add constructed n-tuple to elemental set */ + check_then_add(mpl, memb->value.set, tuple); + get_token(mpl /* + */); + } + /* delete the row symbol */ + delete_symbol(mpl, row); + } + /* delete the column list */ + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- set_data - read set data. +-- +-- This routine reads set data using the syntax: +-- +-- ::= set ; +-- ::= set [ ] ; +-- ::= +-- ::= +-- ::= , := +-- ::= , ( ) +-- ::= , +-- ::= , : +-- ::= , (tr) +-- ::= , (tr) : +-- +-- Commae in are optional and may be omitted anywhere. */ + +void set_data(MPL *mpl) +{ SET *set; + TUPLE *tuple; + MEMBER *memb; + SLICE *slice; + int tr = 0; + xassert(is_literal(mpl, "set")); + get_token(mpl /* set */); + /* symbolic name of set must follows the keyword 'set' */ + if (!is_symbol(mpl)) + error(mpl, "set name missing where expected"); + /* select the set to saturate it with data */ + set = select_set(mpl, mpl->image); + get_token(mpl /* */); + /* read optional subscript list, which identifies member of the + set to be read */ + tuple = create_tuple(mpl); + if (mpl->token == T_LBRACKET) + { /* subscript list is specified */ + if (set->dim == 0) + error(mpl, "%s cannot be subscripted", set->name); + get_token(mpl /* [ */); + /* read symbols and construct subscript list */ + for (;;) + { if (!is_symbol(mpl)) + error(mpl, "number or symbol missing where expected"); + tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); + if (mpl->token == T_COMMA) + get_token(mpl /* , */); + else if (mpl->token == T_RBRACKET) + break; + else + error(mpl, "syntax error in subscript list"); + } + if (set->dim != tuple_dimen(mpl, tuple)) + error(mpl, "%s must have %d subscript%s rather than %d", + set->name, set->dim, set->dim == 1 ? "" : "s", + tuple_dimen(mpl, tuple)); + get_token(mpl /* ] */); + } + else + { /* subscript list is not specified */ + if (set->dim != 0) + error(mpl, "%s must be subscripted", set->name); + } + /* there must be no member with the same subscript list */ + if (find_member(mpl, set->array, tuple) != NULL) + error(mpl, "%s%s already defined", + set->name, format_tuple(mpl, '[', tuple)); + /* add new member to the set and assign it empty elemental set */ + memb = add_member(mpl, set->array, tuple); + memb->value.set = create_elemset(mpl, set->dimen); + /* create an initial fake slice of all asterisks */ + slice = fake_slice(mpl, set->dimen); + /* read zero or more data assignments */ + for (;;) + { /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* process assignment element */ + if (mpl->token == T_ASSIGN) + { /* assignment ligature is non-significant element */ + get_token(mpl /* := */); + } + else if (mpl->token == T_LEFT) + { /* left parenthesis begins either new slice or "transpose" + indicator */ + int is_tr; + get_token(mpl /* ( */); + is_tr = is_literal(mpl, "tr"); + unget_token(mpl /* ( */); + if (is_tr) goto left; + /* delete the current slice and read new one */ + delete_slice(mpl, slice); + slice = read_slice(mpl, set->name, set->dimen); + /* each new slice resets the "transpose" indicator */ + tr = 0; + /* if the new slice is 0-ary, formally there is one 0-tuple + (in the simple format) that follows it */ + if (slice_arity(mpl, slice) == 0) + simple_format(mpl, set, memb, slice); + } + else if (is_symbol(mpl)) + { /* number or symbol begins data in the simple format */ + simple_format(mpl, set, memb, slice); + } + else if (mpl->token == T_COLON) + { /* colon begins data in the matrix format */ + if (slice_arity(mpl, slice) != 2) +err1: error(mpl, "slice currently used must specify 2 asterisk" + "s, not %d", slice_arity(mpl, slice)); + get_token(mpl /* : */); + /* read elemental set data in the matrix format */ + matrix_format(mpl, set, memb, slice, tr); + } + else if (mpl->token == T_LEFT) +left: { /* left parenthesis begins the "transpose" indicator, which + is followed by data in the matrix format */ + get_token(mpl /* ( */); + if (!is_literal(mpl, "tr")) +err2: error(mpl, "transpose indicator (tr) incomplete"); + if (slice_arity(mpl, slice) != 2) goto err1; + get_token(mpl /* tr */); + if (mpl->token != T_RIGHT) goto err2; + get_token(mpl /* ) */); + /* in this case the colon is optional */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* set the "transpose" indicator */ + tr = 1; + /* read elemental set data in the matrix format */ + matrix_format(mpl, set, memb, slice, tr); + } + else if (mpl->token == T_SEMICOLON) + { /* semicolon terminates the data block */ + get_token(mpl /* ; */); + break; + } + else + error(mpl, "syntax error in set data block"); + } + /* delete the current slice */ + delete_slice(mpl, slice); + return; +} + +/*---------------------------------------------------------------------- +-- select_parameter - select parameter to saturate it with data. +-- +-- This routine selects parameter to saturate it with data provided in +-- the data section. */ + +PARAMETER *select_parameter +( MPL *mpl, + char *name /* not changed */ +) +{ PARAMETER *par; + AVLNODE *node; + xassert(name != NULL); + node = avl_find_node(mpl->tree, name); + if (node == NULL || avl_get_node_type(node) != A_PARAMETER) + error(mpl, "%s not a parameter", name); + par = (PARAMETER *)avl_get_node_link(node); + if (par->assign != NULL) + error(mpl, "%s needs no data", name); + if (par->data) + error(mpl, "%s already provided with data", name); + par->data = 1; + return par; +} + +/*---------------------------------------------------------------------- +-- set_default - set default parameter value. +-- +-- This routine sets default value for specified parameter. */ + +void set_default +( MPL *mpl, + PARAMETER *par, /* not changed */ + SYMBOL *altval /* destroyed */ +) +{ xassert(par != NULL); + xassert(altval != NULL); + if (par->option != NULL) + error(mpl, "default value for %s already specified in model se" + "ction", par->name); + xassert(par->defval == NULL); + par->defval = altval; + return; +} + +/*---------------------------------------------------------------------- +-- read_value - read value and assign it to parameter member. +-- +-- This routine reads numeric or symbolic value from the input stream +-- and assigns to new parameter member specified by its n-tuple, which +-- (the member) is created and added to the parameter array. */ + +MEMBER *read_value +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(par != NULL); + xassert(is_symbol(mpl)); + /* there must be no member with the same n-tuple */ + if (find_member(mpl, par->array, tuple) != NULL) + error(mpl, "%s%s already defined", + par->name, format_tuple(mpl, '[', tuple)); + /* create new parameter member with given n-tuple */ + memb = add_member(mpl, par->array, tuple); + /* read value and assigns it to the new parameter member */ + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + if (!is_number(mpl)) + error(mpl, "%s requires numeric data", par->name); + memb->value.num = read_number(mpl); + break; + case A_SYMBOLIC: + memb->value.sym = read_symbol(mpl); + break; + default: + xassert(par != par); + } + return memb; +} + +/*---------------------------------------------------------------------- +-- plain_format - read parameter data block in plain format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- ::= , , ... , , +-- +-- where are used to determine a complete subscript list for +-- parameter member, is a numeric or symbolic value assigned to +-- the parameter member. Commae between data items are optional and may +-- be omitted anywhere. +-- +-- Number of components in the slice must be the same as dimension of +-- the parameter. To construct the complete subscript list the routine +-- replaces null positions in the slice by corresponding . */ + +void plain_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice /* not changed */ +) +{ TUPLE *tuple; + SLICE *temp; + SYMBOL *sym, *with = NULL; + xassert(par != NULL); + xassert(par->dim == slice_dimen(mpl, slice)); + xassert(is_symbol(mpl)); + /* read symbols and construct complete subscript list */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed; read symbol */ + if (!is_symbol(mpl)) + { int lack = slice_arity(mpl, temp) + 1; + xassert(with != NULL); + xassert(lack > 1); + error(mpl, "%d items missing in data group beginning wit" + "h %s", lack, format_symbol(mpl, with)); + } + sym = read_symbol(mpl); + if (with == NULL) with = sym; + } + else + { /* copy symbol from the slice */ + sym = copy_symbol(mpl, temp->sym); + } + /* append the symbol to the subscript list */ + tuple = expand_tuple(mpl, tuple, sym); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + } + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { xassert(with != NULL); + error(mpl, "one item missing in data group beginning with %s", + format_symbol(mpl, with)); + } + read_value(mpl, par, tuple); + return; +} + +/*---------------------------------------------------------------------- +-- tabular_format - read parameter data block in tabular format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- ::= ... := +-- ... +-- ... +-- . . . . . . . . . . . +-- ... +-- +-- where are symbols that denote rows of the table, +-- are symbols that denote columns of the table, are numeric +-- or symbolic values assigned to the corresponding parameter members. +-- If is specified as single point, no value is provided. +-- +-- Number of components in the slice must be the same as dimension of +-- the parameter. The slice must have two null positions. To construct +-- complete subscript list for particular the routine replaces +-- the first null position of the slice by the corresponding (or +-- , if the flag tr is on) and the second null position by the +-- corresponding (or by , if the flag tr is on). */ + +void tabular_format +( MPL *mpl, + PARAMETER *par, /* not changed */ + SLICE *slice, /* not changed */ + int tr +) +{ SLICE *list, *col, *temp; + TUPLE *tuple; + SYMBOL *row; + xassert(par != NULL); + xassert(par->dim == slice_dimen(mpl, slice)); + xassert(slice_arity(mpl, slice) == 2); + /* read the table heading that contains column symbols (the table + may have no columns) */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* read column symbol and append it to the column list */ + if (!is_symbol(mpl)) + error(mpl, "number, symbol, or := missing where expected"); + list = expand_slice(mpl, list, read_symbol(mpl)); + } + get_token(mpl /* := */); + /* read zero or more rows that contain tabular data */ + while (is_symbol(mpl)) + { /* read row symbol (if the table has no columns, these symbols + are just ignored) */ + row = read_symbol(mpl); + /* read values accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { int which = 0; + /* if the token is single point, no value is provided */ + if (is_literal(mpl, ".")) + { get_token(mpl /* . */); + continue; + } + /* construct complete subscript list */ + tuple = create_tuple(mpl); + for (temp = slice; temp != NULL; temp = temp->next) + { if (temp->sym == NULL) + { /* substitution is needed */ + switch (++which) + { case 1: + /* substitute in the first null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? col->sym : row)); + break; + case 2: + /* substitute in the second null position */ + tuple = expand_tuple(mpl, tuple, + copy_symbol(mpl, tr ? row : col->sym)); + break; + default: + xassert(which != which); + } + } + else + { /* copy symbol from the slice */ + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + } + } + xassert(which == 2); + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, col); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, row)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, row)); + } + read_value(mpl, par, tuple); + } + /* delete the row symbol */ + delete_symbol(mpl, row); + } + /* delete the column list */ + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- tabbing_format - read parameter data block in tabbing format. +-- +-- This routine reads parameter data block using the syntax: +-- +-- ::= , ... , , := , +-- , ... , , , ... , , +-- , ... , , , ... , , +-- . . . . . . . . . . . . . . . . . +-- , ... , , , ... , +-- ::= +-- ::= : +-- +-- where are names of parameters (all the parameters must be +-- subscripted and have identical dimensions), are symbols +-- used to define subscripts of parameter members, are numeric +-- or symbolic values assigned to the corresponding parameter members. +-- Optional may specify a simple set, in which case n-tuples +-- built of for each row of the data table (i.e. subscripts +-- of parameter members) are added to the specified set. Commae between +-- data items are optional and may be omitted anywhere. +-- +-- If the parameter altval is not NULL, it specifies a default value +-- provided for all the parameters specified in the data block. */ + +void tabbing_format +( MPL *mpl, + SYMBOL *altval /* not changed */ +) +{ SET *set = NULL; + PARAMETER *par; + SLICE *list, *col; + TUPLE *tuple; + int next_token, j, dim = 0; + char *last_name = NULL; + /* read the optional */ + if (is_symbol(mpl)) + { get_token(mpl /* */); + next_token = mpl->token; + unget_token(mpl /* */); + if (next_token == T_COLON) + { /* select the set to saturate it with data */ + set = select_set(mpl, mpl->image); + /* the set must be simple (i.e. not set of sets) */ + if (set->dim != 0) + error(mpl, "%s must be a simple set", set->name); + /* and must not be defined yet */ + if (set->array->head != NULL) + error(mpl, "%s already defined", set->name); + /* add new (the only) member to the set and assign it empty + elemental set */ + add_member(mpl, set->array, NULL)->value.set = + create_elemset(mpl, set->dimen); + last_name = set->name, dim = set->dimen; + get_token(mpl /* */); + xassert(mpl->token == T_COLON); + get_token(mpl /* : */); + } + } + /* read the table heading that contains parameter names */ + list = create_slice(mpl); + while (mpl->token != T_ASSIGN) + { /* there must be symbolic name of parameter */ + if (!is_symbol(mpl)) + error(mpl, "parameter name or := missing where expected"); + /* select the parameter to saturate it with data */ + par = select_parameter(mpl, mpl->image); + /* the parameter must be subscripted */ + if (par->dim == 0) + error(mpl, "%s not a subscripted parameter", mpl->image); + /* the set (if specified) and all the parameters in the data + block must have identical dimension */ + if (dim != 0 && par->dim != dim) + { xassert(last_name != NULL); + error(mpl, "%s has dimension %d while %s has dimension %d", + last_name, dim, par->name, par->dim); + } + /* set default value for the parameter (if specified) */ + if (altval != NULL) + set_default(mpl, par, copy_symbol(mpl, altval)); + /* append the parameter to the column list */ + list = expand_slice(mpl, list, (SYMBOL *)par); + last_name = par->name, dim = par->dim; + get_token(mpl /* */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + } + if (slice_dimen(mpl, list) == 0) + error(mpl, "at least one parameter name required"); + get_token(mpl /* := */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read rows that contain tabbing data */ + while (is_symbol(mpl)) + { /* read subscript list */ + tuple = create_tuple(mpl); + for (j = 1; j <= dim; j++) + { /* read j-th subscript */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, list) + dim - j + 1; + xassert(tuple != NULL); + xassert(lack > 1); + error(mpl, "%d items missing in data group beginning wit" + "h %s", lack, format_symbol(mpl, tuple->sym)); + } + /* read and append j-th subscript to the n-tuple */ + tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); + /* skip optional comma *between* */ + if (j < dim && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* if the set is specified, add to it new n-tuple, which is a + copy of the subscript list just read */ + if (set != NULL) + check_then_add(mpl, set->array->head->value.set, + copy_tuple(mpl, tuple)); + /* skip optional comma between and */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read values accordingly to the column list */ + for (col = list; col != NULL; col = col->next) + { /* if the token is single point, no value is provided */ + if (is_literal(mpl, ".")) + { get_token(mpl /* . */); + continue; + } + /* read value and assign it to new parameter member */ + if (!is_symbol(mpl)) + { int lack = slice_dimen(mpl, col); + xassert(tuple != NULL); + if (lack == 1) + error(mpl, "one item missing in data group beginning " + "with %s", format_symbol(mpl, tuple->sym)); + else + error(mpl, "%d items missing in data group beginning " + "with %s", lack, format_symbol(mpl, tuple->sym)); + } + read_value(mpl, (PARAMETER *)col->sym, copy_tuple(mpl, + tuple)); + /* skip optional comma preceding the next value */ + if (col->next != NULL && mpl->token == T_COMMA) + get_token(mpl /* , */); + } + /* delete the original subscript list */ + delete_tuple(mpl, tuple); + /* skip optional comma (only if there is next data group) */ + if (mpl->token == T_COMMA) + { get_token(mpl /* , */); + if (!is_symbol(mpl)) unget_token(mpl /* , */); + } + } + /* delete the column list (it contains parameters, not symbols, + so nullify it before) */ + for (col = list; col != NULL; col = col->next) col->sym = NULL; + delete_slice(mpl, list); + return; +} + +/*---------------------------------------------------------------------- +-- parameter_data - read parameter data. +-- +-- This routine reads parameter data using the syntax: +-- +-- ::= param : ; +-- ::= param +-- ; +-- ::= +-- ::= +-- ::= default +-- ::= +-- ::= , := +-- ::= , [ ] +-- ::= , +-- ::= , : +-- ::= , (tr) +-- ::= , (tr) : +-- +-- Commae in are optional and may be omitted anywhere. */ + +void parameter_data(MPL *mpl) +{ PARAMETER *par; + SYMBOL *altval = NULL; + SLICE *slice; + int tr = 0; + xassert(is_literal(mpl, "param")); + get_token(mpl /* param */); + /* read optional default value */ + if (is_literal(mpl, "default")) + { get_token(mpl /* default */); + if (!is_symbol(mpl)) + error(mpl, "default value missing where expected"); + altval = read_symbol(mpl); + /* if the default value follows the keyword 'param', the next + token must be only the colon */ + if (mpl->token != T_COLON) + error(mpl, "colon missing where expected"); + } + /* being used after the keyword 'param' or the optional default + value the colon begins data in the tabbing format */ + if (mpl->token == T_COLON) + { get_token(mpl /* : */); + /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* read parameter data in the tabbing format */ + tabbing_format(mpl, altval); + /* on reading data in the tabbing format the default value is + always copied, so delete the original symbol */ + if (altval != NULL) delete_symbol(mpl, altval); + /* the next token must be only semicolon */ + if (mpl->token != T_SEMICOLON) + error(mpl, "symbol, number, or semicolon missing where expe" + "cted"); + get_token(mpl /* ; */); + goto done; + } + /* in other cases there must be symbolic name of parameter, which + follows the keyword 'param' */ + if (!is_symbol(mpl)) + error(mpl, "parameter name missing where expected"); + /* select the parameter to saturate it with data */ + par = select_parameter(mpl, mpl->image); + get_token(mpl /* */); + /* read optional default value */ + if (is_literal(mpl, "default")) + { get_token(mpl /* default */); + if (!is_symbol(mpl)) + error(mpl, "default value missing where expected"); + altval = read_symbol(mpl); + /* set default value for the parameter */ + set_default(mpl, par, altval); + } + /* create initial fake slice of all asterisks */ + slice = fake_slice(mpl, par->dim); + /* read zero or more data assignments */ + for (;;) + { /* skip optional comma */ + if (mpl->token == T_COMMA) get_token(mpl /* , */); + /* process current assignment */ + if (mpl->token == T_ASSIGN) + { /* assignment ligature is non-significant element */ + get_token(mpl /* := */); + } + else if (mpl->token == T_LBRACKET) + { /* left bracket begins new slice; delete the current slice + and read new one */ + delete_slice(mpl, slice); + slice = read_slice(mpl, par->name, par->dim); + /* each new slice resets the "transpose" indicator */ + tr = 0; + } + else if (is_symbol(mpl)) + { /* number or symbol begins data in the plain format */ + plain_format(mpl, par, slice); + } + else if (mpl->token == T_COLON) + { /* colon begins data in the tabular format */ + if (par->dim == 0) +err1: error(mpl, "%s not a subscripted parameter", + par->name); + if (slice_arity(mpl, slice) != 2) +err2: error(mpl, "slice currently used must specify 2 asterisk" + "s, not %d", slice_arity(mpl, slice)); + get_token(mpl /* : */); + /* read parameter data in the tabular format */ + tabular_format(mpl, par, slice, tr); + } + else if (mpl->token == T_LEFT) + { /* left parenthesis begins the "transpose" indicator, which + is followed by data in the tabular format */ + get_token(mpl /* ( */); + if (!is_literal(mpl, "tr")) +err3: error(mpl, "transpose indicator (tr) incomplete"); + if (par->dim == 0) goto err1; + if (slice_arity(mpl, slice) != 2) goto err2; + get_token(mpl /* tr */); + if (mpl->token != T_RIGHT) goto err3; + get_token(mpl /* ) */); + /* in this case the colon is optional */ + if (mpl->token == T_COLON) get_token(mpl /* : */); + /* set the "transpose" indicator */ + tr = 1; + /* read parameter data in the tabular format */ + tabular_format(mpl, par, slice, tr); + } + else if (mpl->token == T_SEMICOLON) + { /* semicolon terminates the data block */ + get_token(mpl /* ; */); + break; + } + else + error(mpl, "syntax error in parameter data block"); + } + /* delete the current slice */ + delete_slice(mpl, slice); +done: return; +} + +/*---------------------------------------------------------------------- +-- data_section - read data section. +-- +-- This routine reads data section using the syntax: +-- +-- ::= +-- ::= ; +-- ::= +-- ::= +-- +-- Reading data section is terminated by either the keyword 'end' or +-- the end of file. */ + +void data_section(MPL *mpl) +{ while (!(mpl->token == T_EOF || is_literal(mpl, "end"))) + { if (is_literal(mpl, "set")) + set_data(mpl); + else if (is_literal(mpl, "param")) + parameter_data(mpl); + else + error(mpl, "syntax error in data section"); + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl3.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl3.c new file mode 100644 index 000000000..2489db27d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl3.c @@ -0,0 +1,6100 @@ +/* mpl3.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" + +/**********************************************************************/ +/* * * FLOATING-POINT NUMBERS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- fp_add - floating-point addition. +-- +-- This routine computes the sum x + y. */ + +double fp_add(MPL *mpl, double x, double y) +{ if (x > 0.0 && y > 0.0 && x > + 0.999 * DBL_MAX - y || + x < 0.0 && y < 0.0 && x < - 0.999 * DBL_MAX - y) + error(mpl, "%.*g + %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x + y; +} + +/*---------------------------------------------------------------------- +-- fp_sub - floating-point subtraction. +-- +-- This routine computes the difference x - y. */ + +double fp_sub(MPL *mpl, double x, double y) +{ if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y || + x < 0.0 && y > 0.0 && x < - 0.999 * DBL_MAX + y) + error(mpl, "%.*g - %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x - y; +} + +/*---------------------------------------------------------------------- +-- fp_less - floating-point non-negative subtraction. +-- +-- This routine computes the non-negative difference max(0, x - y). */ + +double fp_less(MPL *mpl, double x, double y) +{ if (x < y) return 0.0; + if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y) + error(mpl, "%.*g less %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x - y; +} + +/*---------------------------------------------------------------------- +-- fp_mul - floating-point multiplication. +-- +-- This routine computes the product x * y. */ + +double fp_mul(MPL *mpl, double x, double y) +{ if (fabs(y) > 1.0 && fabs(x) > (0.999 * DBL_MAX) / fabs(y)) + error(mpl, "%.*g * %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x * y; +} + +/*---------------------------------------------------------------------- +-- fp_div - floating-point division. +-- +-- This routine computes the quotient x / y. */ + +double fp_div(MPL *mpl, double x, double y) +{ if (fabs(y) < DBL_MIN) + error(mpl, "%.*g / %.*g; floating-point zero divide", + DBL_DIG, x, DBL_DIG, y); + if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) + error(mpl, "%.*g / %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + return x / y; +} + +/*---------------------------------------------------------------------- +-- fp_idiv - floating-point quotient of exact division. +-- +-- This routine computes the quotient of exact division x div y. */ + +double fp_idiv(MPL *mpl, double x, double y) +{ if (fabs(y) < DBL_MIN) + error(mpl, "%.*g div %.*g; floating-point zero divide", + DBL_DIG, x, DBL_DIG, y); + if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) + error(mpl, "%.*g div %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + x /= y; + return x > 0.0 ? floor(x) : x < 0.0 ? ceil(x) : 0.0; +} + +/*---------------------------------------------------------------------- +-- fp_mod - floating-point remainder of exact division. +-- +-- This routine computes the remainder of exact division x mod y. +-- +-- NOTE: By definition x mod y = x - y * floor(x / y). */ + +double fp_mod(MPL *mpl, double x, double y) +{ double r; + xassert(mpl == mpl); + if (x == 0.0) + r = 0.0; + else if (y == 0.0) + r = x; + else + { r = fmod(fabs(x), fabs(y)); + if (r != 0.0) + { if (x < 0.0) r = - r; + if (x > 0.0 && y < 0.0 || x < 0.0 && y > 0.0) r += y; + } + } + return r; +} + +/*---------------------------------------------------------------------- +-- fp_power - floating-point exponentiation (raise to power). +-- +-- This routine computes the exponentiation x ** y. */ + +double fp_power(MPL *mpl, double x, double y) +{ double r; + if (x == 0.0 && y <= 0.0 || x < 0.0 && y != floor(y)) + error(mpl, "%.*g ** %.*g; result undefined", + DBL_DIG, x, DBL_DIG, y); + if (x == 0.0) goto eval; + if (fabs(x) > 1.0 && y > +1.0 && + +log(fabs(x)) > (0.999 * log(DBL_MAX)) / y || + fabs(x) < 1.0 && y < -1.0 && + +log(fabs(x)) < (0.999 * log(DBL_MAX)) / y) + error(mpl, "%.*g ** %.*g; floating-point overflow", + DBL_DIG, x, DBL_DIG, y); + if (fabs(x) > 1.0 && y < -1.0 && + -log(fabs(x)) < (0.999 * log(DBL_MAX)) / y || + fabs(x) < 1.0 && y > +1.0 && + -log(fabs(x)) > (0.999 * log(DBL_MAX)) / y) + r = 0.0; + else +eval: r = pow(x, y); + return r; +} + +/*---------------------------------------------------------------------- +-- fp_exp - floating-point base-e exponential. +-- +-- This routine computes the base-e exponential e ** x. */ + +double fp_exp(MPL *mpl, double x) +{ if (x > 0.999 * log(DBL_MAX)) + error(mpl, "exp(%.*g); floating-point overflow", DBL_DIG, x); + return exp(x); +} + +/*---------------------------------------------------------------------- +-- fp_log - floating-point natural logarithm. +-- +-- This routine computes the natural logarithm log x. */ + +double fp_log(MPL *mpl, double x) +{ if (x <= 0.0) + error(mpl, "log(%.*g); non-positive argument", DBL_DIG, x); + return log(x); +} + +/*---------------------------------------------------------------------- +-- fp_log10 - floating-point common (decimal) logarithm. +-- +-- This routine computes the common (decimal) logarithm lg x. */ + +double fp_log10(MPL *mpl, double x) +{ if (x <= 0.0) + error(mpl, "log10(%.*g); non-positive argument", DBL_DIG, x); + return log10(x); +} + +/*---------------------------------------------------------------------- +-- fp_sqrt - floating-point square root. +-- +-- This routine computes the square root x ** 0.5. */ + +double fp_sqrt(MPL *mpl, double x) +{ if (x < 0.0) + error(mpl, "sqrt(%.*g); negative argument", DBL_DIG, x); + return sqrt(x); +} + +/*---------------------------------------------------------------------- +-- fp_sin - floating-point trigonometric sine. +-- +-- This routine computes the trigonometric sine sin(x). */ + +double fp_sin(MPL *mpl, double x) +{ if (!(-1e6 <= x && x <= +1e6)) + error(mpl, "sin(%.*g); argument too large", DBL_DIG, x); + return sin(x); +} + +/*---------------------------------------------------------------------- +-- fp_cos - floating-point trigonometric cosine. +-- +-- This routine computes the trigonometric cosine cos(x). */ + +double fp_cos(MPL *mpl, double x) +{ if (!(-1e6 <= x && x <= +1e6)) + error(mpl, "cos(%.*g); argument too large", DBL_DIG, x); + return cos(x); +} + +/*---------------------------------------------------------------------- +-- fp_tan - floating-point trigonometric tangent. +-- +-- This routine computes the trigonometric tangent tan(x). */ + +double fp_tan(MPL *mpl, double x) +{ if (!(-1e6 <= x && x <= +1e6)) + error(mpl, "tan(%.*g); argument too large", DBL_DIG, x); + return tan(x); +} + +/*---------------------------------------------------------------------- +-- fp_atan - floating-point trigonometric arctangent. +-- +-- This routine computes the trigonometric arctangent atan(x). */ + +double fp_atan(MPL *mpl, double x) +{ xassert(mpl == mpl); + return atan(x); +} + +/*---------------------------------------------------------------------- +-- fp_atan2 - floating-point trigonometric arctangent. +-- +-- This routine computes the trigonometric arctangent atan(y / x). */ + +double fp_atan2(MPL *mpl, double y, double x) +{ xassert(mpl == mpl); + return atan2(y, x); +} + +/*---------------------------------------------------------------------- +-- fp_round - round floating-point value to n fractional digits. +-- +-- This routine rounds given floating-point value x to n fractional +-- digits with the formula: +-- +-- round(x, n) = floor(x * 10^n + 0.5) / 10^n. +-- +-- The parameter n is assumed to be integer. */ + +double fp_round(MPL *mpl, double x, double n) +{ double ten_to_n; + if (n != floor(n)) + error(mpl, "round(%.*g, %.*g); non-integer second argument", + DBL_DIG, x, DBL_DIG, n); + if (n <= DBL_DIG + 2) + { ten_to_n = pow(10.0, n); + if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) + { x = floor(x * ten_to_n + 0.5); + if (x != 0.0) x /= ten_to_n; + } + } + return x; +} + +/*---------------------------------------------------------------------- +-- fp_trunc - truncate floating-point value to n fractional digits. +-- +-- This routine truncates given floating-point value x to n fractional +-- digits with the formula: +-- +-- ( floor(x * 10^n) / 10^n, if x >= 0 +-- trunc(x, n) = < +-- ( ceil(x * 10^n) / 10^n, if x < 0 +-- +-- The parameter n is assumed to be integer. */ + +double fp_trunc(MPL *mpl, double x, double n) +{ double ten_to_n; + if (n != floor(n)) + error(mpl, "trunc(%.*g, %.*g); non-integer second argument", + DBL_DIG, x, DBL_DIG, n); + if (n <= DBL_DIG + 2) + { ten_to_n = pow(10.0, n); + if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) + { x = (x >= 0.0 ? floor(x * ten_to_n) : ceil(x * ten_to_n)); + if (x != 0.0) x /= ten_to_n; + } + } + return x; +} + +/**********************************************************************/ +/* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- fp_irand224 - pseudo-random integer in the range [0, 2^24). +-- +-- This routine returns a next pseudo-random integer (converted to +-- floating-point) which is uniformly distributed between 0 and 2^24-1, +-- inclusive. */ + +#define two_to_the_24 0x1000000 + +double fp_irand224(MPL *mpl) +{ return + (double)rng_unif_rand(mpl->rand, two_to_the_24); +} + +/*---------------------------------------------------------------------- +-- fp_uniform01 - pseudo-random number in the range [0, 1). +-- +-- This routine returns a next pseudo-random number which is uniformly +-- distributed in the range [0, 1). */ + +#define two_to_the_31 ((unsigned int)0x80000000) + +double fp_uniform01(MPL *mpl) +{ return + (double)rng_next_rand(mpl->rand) / (double)two_to_the_31; +} + +/*---------------------------------------------------------------------- +-- fp_uniform - pseudo-random number in the range [a, b). +-- +-- This routine returns a next pseudo-random number which is uniformly +-- distributed in the range [a, b). */ + +double fp_uniform(MPL *mpl, double a, double b) +{ double x; + if (a >= b) + error(mpl, "Uniform(%.*g, %.*g); invalid range", + DBL_DIG, a, DBL_DIG, b); + x = fp_uniform01(mpl); +#if 0 + x = a * (1.0 - x) + b * x; +#else + x = fp_add(mpl, a * (1.0 - x), b * x); +#endif + return x; +} + +/*---------------------------------------------------------------------- +-- fp_normal01 - Gaussian random variate with mu = 0 and sigma = 1. +-- +-- This routine returns a Gaussian random variate with zero mean and +-- unit standard deviation. The polar (Box-Mueller) method is used. +-- +-- This code is a modified version of the routine gsl_ran_gaussian from +-- the GNU Scientific Library Version 1.0. */ + +double fp_normal01(MPL *mpl) +{ double x, y, r2; + do + { /* choose x, y in uniform square (-1,-1) to (+1,+1) */ + x = -1.0 + 2.0 * fp_uniform01(mpl); + y = -1.0 + 2.0 * fp_uniform01(mpl); + /* see if it is in the unit circle */ + r2 = x * x + y * y; + } while (r2 > 1.0 || r2 == 0.0); + /* Box-Muller transform */ + return y * sqrt(-2.0 * log (r2) / r2); +} + +/*---------------------------------------------------------------------- +-- fp_normal - Gaussian random variate with specified mu and sigma. +-- +-- This routine returns a Gaussian random variate with mean mu and +-- standard deviation sigma. */ + +double fp_normal(MPL *mpl, double mu, double sigma) +{ double x; +#if 0 + x = mu + sigma * fp_normal01(mpl); +#else + x = fp_add(mpl, mu, fp_mul(mpl, sigma, fp_normal01(mpl))); +#endif + return x; +} + +/**********************************************************************/ +/* * * SEGMENTED CHARACTER STRINGS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_string - create character string. +-- +-- This routine creates a segmented character string, which is exactly +-- equivalent to specified character string. */ + +STRING *create_string +( MPL *mpl, + char buf[MAX_LENGTH+1] /* not changed */ +) +#if 0 +{ STRING *head, *tail; + int i, j; + xassert(buf != NULL); + xassert(strlen(buf) <= MAX_LENGTH); + head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); + for (i = j = 0; ; i++) + { if ((tail->seg[j++] = buf[i]) == '\0') break; + if (j == STRSEG_SIZE) +tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))), j = 0; + } + tail->next = NULL; + return head; +} +#else +{ STRING *str; + xassert(strlen(buf) <= MAX_LENGTH); + str = dmp_get_atom(mpl->strings, strlen(buf)+1); + strcpy(str, buf); + return str; +} +#endif + +/*---------------------------------------------------------------------- +-- copy_string - make copy of character string. +-- +-- This routine returns an exact copy of segmented character string. */ + +STRING *copy_string +( MPL *mpl, + STRING *str /* not changed */ +) +#if 0 +{ STRING *head, *tail; + xassert(str != NULL); + head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); + for (; str != NULL; str = str->next) + { memcpy(tail->seg, str->seg, STRSEG_SIZE); + if (str->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))); + } + tail->next = NULL; + return head; +} +#else +{ xassert(mpl == mpl); + return create_string(mpl, str); +} +#endif + +/*---------------------------------------------------------------------- +-- compare_strings - compare one character string with another. +-- +-- This routine compares one segmented character strings with another +-- and returns the result of comparison as follows: +-- +-- = 0 - both strings are identical; +-- < 0 - the first string precedes the second one; +-- > 0 - the first string follows the second one. */ + +int compare_strings +( MPL *mpl, + STRING *str1, /* not changed */ + STRING *str2 /* not changed */ +) +#if 0 +{ int j, c1, c2; + xassert(mpl == mpl); + for (;; str1 = str1->next, str2 = str2->next) + { xassert(str1 != NULL); + xassert(str2 != NULL); + for (j = 0; j < STRSEG_SIZE; j++) + { c1 = (unsigned char)str1->seg[j]; + c2 = (unsigned char)str2->seg[j]; + if (c1 < c2) return -1; + if (c1 > c2) return +1; + if (c1 == '\0') goto done; + } + } +done: return 0; +} +#else +{ xassert(mpl == mpl); + return strcmp(str1, str2); +} +#endif + +/*---------------------------------------------------------------------- +-- fetch_string - extract content of character string. +-- +-- This routine returns a character string, which is exactly equivalent +-- to specified segmented character string. */ + +char *fetch_string +( MPL *mpl, + STRING *str, /* not changed */ + char buf[MAX_LENGTH+1] /* modified */ +) +#if 0 +{ int i, j; + xassert(mpl == mpl); + xassert(buf != NULL); + for (i = 0; ; str = str->next) + { xassert(str != NULL); + for (j = 0; j < STRSEG_SIZE; j++) + if ((buf[i++] = str->seg[j]) == '\0') goto done; + } +done: xassert(strlen(buf) <= MAX_LENGTH); + return buf; +} +#else +{ xassert(mpl == mpl); + return strcpy(buf, str); +} +#endif + +/*---------------------------------------------------------------------- +-- delete_string - delete character string. +-- +-- This routine deletes specified segmented character string. */ + +void delete_string +( MPL *mpl, + STRING *str /* destroyed */ +) +#if 0 +{ STRING *temp; + xassert(str != NULL); + while (str != NULL) + { temp = str; + str = str->next; + dmp_free_atom(mpl->strings, temp, sizeof(STRING)); + } + return; +} +#else +{ dmp_free_atom(mpl->strings, str, strlen(str)+1); + return; +} +#endif + +/**********************************************************************/ +/* * * SYMBOLS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_symbol_num - create symbol of numeric type. +-- +-- This routine creates a symbol, which has a numeric value specified +-- as floating-point number. */ + +SYMBOL *create_symbol_num(MPL *mpl, double num) +{ SYMBOL *sym; + sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + sym->num = num; + sym->str = NULL; + return sym; +} + +/*---------------------------------------------------------------------- +-- create_symbol_str - create symbol of abstract type. +-- +-- This routine creates a symbol, which has an abstract value specified +-- as segmented character string. */ + +SYMBOL *create_symbol_str +( MPL *mpl, + STRING *str /* destroyed */ +) +{ SYMBOL *sym; + xassert(str != NULL); + sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + sym->num = 0.0; + sym->str = str; + return sym; +} + +/*---------------------------------------------------------------------- +-- copy_symbol - make copy of symbol. +-- +-- This routine returns an exact copy of symbol. */ + +SYMBOL *copy_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +) +{ SYMBOL *copy; + xassert(sym != NULL); + copy = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); + if (sym->str == NULL) + { copy->num = sym->num; + copy->str = NULL; + } + else + { copy->num = 0.0; + copy->str = copy_string(mpl, sym->str); + } + return copy; +} + +/*---------------------------------------------------------------------- +-- compare_symbols - compare one symbol with another. +-- +-- This routine compares one symbol with another and returns the result +-- of comparison as follows: +-- +-- = 0 - both symbols are identical; +-- < 0 - the first symbol precedes the second one; +-- > 0 - the first symbol follows the second one. +-- +-- Note that the linear order, in which symbols follow each other, is +-- implementation-dependent. It may be not an alphabetical order. */ + +int compare_symbols +( MPL *mpl, + SYMBOL *sym1, /* not changed */ + SYMBOL *sym2 /* not changed */ +) +{ xassert(sym1 != NULL); + xassert(sym2 != NULL); + /* let all numeric quantities precede all symbolic quantities */ + if (sym1->str == NULL && sym2->str == NULL) + { if (sym1->num < sym2->num) return -1; + if (sym1->num > sym2->num) return +1; + return 0; + } + if (sym1->str == NULL) return -1; + if (sym2->str == NULL) return +1; + return compare_strings(mpl, sym1->str, sym2->str); +} + +/*---------------------------------------------------------------------- +-- delete_symbol - delete symbol. +-- +-- This routine deletes specified symbol. */ + +void delete_symbol +( MPL *mpl, + SYMBOL *sym /* destroyed */ +) +{ xassert(sym != NULL); + if (sym->str != NULL) delete_string(mpl, sym->str); + dmp_free_atom(mpl->symbols, sym, sizeof(SYMBOL)); + return; +} + +/*---------------------------------------------------------------------- +-- format_symbol - format symbol for displaying or printing. +-- +-- This routine converts specified symbol to a charater string, which +-- is suitable for displaying or printing. +-- +-- The resultant string is never longer than 255 characters. If it gets +-- longer, it is truncated from the right and appended by dots. */ + +char *format_symbol +( MPL *mpl, + SYMBOL *sym /* not changed */ +) +{ char *buf = mpl->sym_buf; + xassert(sym != NULL); + if (sym->str == NULL) + sprintf(buf, "%.*g", DBL_DIG, sym->num); + else + { char str[MAX_LENGTH+1]; + int quoted, j, len; + fetch_string(mpl, sym->str, str); + if (!(isalpha((unsigned char)str[0]) || str[0] == '_')) + quoted = 1; + else + { quoted = 0; + for (j = 1; str[j] != '\0'; j++) + { if (!(isalnum((unsigned char)str[j]) || + strchr("+-._", (unsigned char)str[j]) != NULL)) + { quoted = 1; + break; + } + } + } +# define safe_append(c) \ + (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) + buf[0] = '\0', len = 0; + if (quoted) safe_append('\''); + for (j = 0; str[j] != '\0'; j++) + { if (quoted && str[j] == '\'') safe_append('\''); + safe_append(str[j]); + } + if (quoted) safe_append('\''); +# undef safe_append + buf[len] = '\0'; + if (len == 255) strcpy(buf+252, "..."); + } + xassert(strlen(buf) <= 255); + return buf; +} + +/*---------------------------------------------------------------------- +-- concat_symbols - concatenate one symbol with another. +-- +-- This routine concatenates values of two given symbols and assigns +-- the resultant character string to a new symbol, which is returned on +-- exit. Both original symbols are destroyed. */ + +SYMBOL *concat_symbols +( MPL *mpl, + SYMBOL *sym1, /* destroyed */ + SYMBOL *sym2 /* destroyed */ +) +{ char str1[MAX_LENGTH+1], str2[MAX_LENGTH+1]; + xassert(MAX_LENGTH >= DBL_DIG + DBL_DIG); + if (sym1->str == NULL) + sprintf(str1, "%.*g", DBL_DIG, sym1->num); + else + fetch_string(mpl, sym1->str, str1); + if (sym2->str == NULL) + sprintf(str2, "%.*g", DBL_DIG, sym2->num); + else + fetch_string(mpl, sym2->str, str2); + if (strlen(str1) + strlen(str2) > MAX_LENGTH) + { char buf[255+1]; + strcpy(buf, format_symbol(mpl, sym1)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s & %s; resultant symbol exceeds %d characters", + buf, format_symbol(mpl, sym2), MAX_LENGTH); + } + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + return create_symbol_str(mpl, create_string(mpl, strcat(str1, + str2))); +} + +/**********************************************************************/ +/* * * N-TUPLES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_tuple - create n-tuple. +-- +-- This routine creates a n-tuple, which initially has no components, +-- i.e. which is 0-tuple. */ + +TUPLE *create_tuple(MPL *mpl) +{ TUPLE *tuple; + xassert(mpl == mpl); + tuple = NULL; + return tuple; +} + +/*---------------------------------------------------------------------- +-- expand_tuple - append symbol to n-tuple. +-- +-- This routine expands n-tuple appending to it a given symbol, which +-- becomes its new last component. */ + +TUPLE *expand_tuple +( MPL *mpl, + TUPLE *tuple, /* destroyed */ + SYMBOL *sym /* destroyed */ +) +{ TUPLE *tail, *temp; + xassert(sym != NULL); + /* create a new component */ + tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + tail->sym = sym; + tail->next = NULL; + /* and append it to the component list */ + if (tuple == NULL) + tuple = tail; + else + { for (temp = tuple; temp->next != NULL; temp = temp->next); + temp->next = tail; + } + return tuple; +} + +/*---------------------------------------------------------------------- +-- tuple_dimen - determine dimension of n-tuple. +-- +-- This routine returns dimension of n-tuple, i.e. number of components +-- in the n-tuple. */ + +int tuple_dimen +( MPL *mpl, + TUPLE *tuple /* not changed */ +) +{ TUPLE *temp; + int dim = 0; + xassert(mpl == mpl); + for (temp = tuple; temp != NULL; temp = temp->next) dim++; + return dim; +} + +/*---------------------------------------------------------------------- +-- copy_tuple - make copy of n-tuple. +-- +-- This routine returns an exact copy of n-tuple. */ + +TUPLE *copy_tuple +( MPL *mpl, + TUPLE *tuple /* not changed */ +) +{ TUPLE *head, *tail; + if (tuple == NULL) + head = NULL; + else + { head = tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + for (; tuple != NULL; tuple = tuple->next) + { xassert(tuple->sym != NULL); + tail->sym = copy_symbol(mpl, tuple->sym); + if (tuple->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); + } + tail->next = NULL; + } + return head; +} + +/*---------------------------------------------------------------------- +-- compare_tuples - compare one n-tuple with another. +-- +-- This routine compares two given n-tuples, which must have the same +-- dimension (not checked for the sake of efficiency), and returns one +-- of the following codes: +-- +-- = 0 - both n-tuples are identical; +-- < 0 - the first n-tuple precedes the second one; +-- > 0 - the first n-tuple follows the second one. +-- +-- Note that the linear order, in which n-tuples follow each other, is +-- implementation-dependent. It may be not an alphabetical order. */ + +int compare_tuples +( MPL *mpl, + TUPLE *tuple1, /* not changed */ + TUPLE *tuple2 /* not changed */ +) +{ TUPLE *item1, *item2; + int ret; + xassert(mpl == mpl); + for (item1 = tuple1, item2 = tuple2; item1 != NULL; + item1 = item1->next, item2 = item2->next) + { xassert(item2 != NULL); + xassert(item1->sym != NULL); + xassert(item2->sym != NULL); + ret = compare_symbols(mpl, item1->sym, item2->sym); + if (ret != 0) return ret; + } + xassert(item2 == NULL); + return 0; +} + +/*---------------------------------------------------------------------- +-- build_subtuple - build subtuple of given n-tuple. +-- +-- This routine builds subtuple, which consists of first dim components +-- of given n-tuple. */ + +TUPLE *build_subtuple +( MPL *mpl, + TUPLE *tuple, /* not changed */ + int dim +) +{ TUPLE *head, *temp; + int j; + head = create_tuple(mpl); + for (j = 1, temp = tuple; j <= dim; j++, temp = temp->next) + { xassert(temp != NULL); + head = expand_tuple(mpl, head, copy_symbol(mpl, temp->sym)); + } + return head; +} + +/*---------------------------------------------------------------------- +-- delete_tuple - delete n-tuple. +-- +-- This routine deletes specified n-tuple. */ + +void delete_tuple +( MPL *mpl, + TUPLE *tuple /* destroyed */ +) +{ TUPLE *temp; + while (tuple != NULL) + { temp = tuple; + tuple = temp->next; + xassert(temp->sym != NULL); + delete_symbol(mpl, temp->sym); + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + return; +} + +/*---------------------------------------------------------------------- +-- format_tuple - format n-tuple for displaying or printing. +-- +-- This routine converts specified n-tuple to a character string, which +-- is suitable for displaying or printing. +-- +-- The resultant string is never longer than 255 characters. If it gets +-- longer, it is truncated from the right and appended by dots. */ + +char *format_tuple +( MPL *mpl, + int c, + TUPLE *tuple /* not changed */ +) +{ TUPLE *temp; + int dim, j, len; + char *buf = mpl->tup_buf, str[255+1], *save; +# define safe_append(c) \ + (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) + buf[0] = '\0', len = 0; + dim = tuple_dimen(mpl, tuple); + if (c == '[' && dim > 0) safe_append('['); + if (c == '(' && dim > 1) safe_append('('); + for (temp = tuple; temp != NULL; temp = temp->next) + { if (temp != tuple) safe_append(','); + xassert(temp->sym != NULL); + save = mpl->sym_buf; + mpl->sym_buf = str; + format_symbol(mpl, temp->sym); + mpl->sym_buf = save; + xassert(strlen(str) < sizeof(str)); + for (j = 0; str[j] != '\0'; j++) safe_append(str[j]); + } + if (c == '[' && dim > 0) safe_append(']'); + if (c == '(' && dim > 1) safe_append(')'); +# undef safe_append + buf[len] = '\0'; + if (len == 255) strcpy(buf+252, "..."); + xassert(strlen(buf) <= 255); + return buf; +} + +/**********************************************************************/ +/* * * ELEMENTAL SETS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_elemset - create elemental set. +-- +-- This routine creates an elemental set, whose members are n-tuples of +-- specified dimension. Being created the set is initially empty. */ + +ELEMSET *create_elemset(MPL *mpl, int dim) +{ ELEMSET *set; + xassert(dim > 0); + set = create_array(mpl, A_NONE, dim); + return set; +} + +/*---------------------------------------------------------------------- +-- find_tuple - check if elemental set contains given n-tuple. +-- +-- This routine finds given n-tuple in specified elemental set in order +-- to check if the set contains that n-tuple. If the n-tuple is found, +-- the routine returns pointer to corresponding array member. Otherwise +-- null pointer is returned. */ + +MEMBER *find_tuple +( MPL *mpl, + ELEMSET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim == tuple_dimen(mpl, tuple)); + return find_member(mpl, set, tuple); +} + +/*---------------------------------------------------------------------- +-- add_tuple - add new n-tuple to elemental set. +-- +-- This routine adds given n-tuple to specified elemental set. +-- +-- For the sake of efficiency this routine doesn't check whether the +-- set already contains the same n-tuple or not. Therefore the calling +-- program should use the routine find_tuple (if necessary) in order to +-- make sure that the given n-tuple is not contained in the set, since +-- duplicate n-tuples within the same set are not allowed. */ + +MEMBER *add_tuple +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim == tuple_dimen(mpl, tuple)); + memb = add_member(mpl, set, tuple); + memb->value.none = NULL; + return memb; +} + +/*---------------------------------------------------------------------- +-- check_then_add - check and add new n-tuple to elemental set. +-- +-- This routine is equivalent to the routine add_tuple except that it +-- does check for duplicate n-tuples. */ + +MEMBER *check_then_add +( MPL *mpl, + ELEMSET *set, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ if (find_tuple(mpl, set, tuple) != NULL) + error(mpl, "duplicate tuple %s detected", format_tuple(mpl, + '(', tuple)); + return add_tuple(mpl, set, tuple); +} + +/*---------------------------------------------------------------------- +-- copy_elemset - make copy of elemental set. +-- +-- This routine makes an exact copy of elemental set. */ + +ELEMSET *copy_elemset +( MPL *mpl, + ELEMSET *set /* not changed */ +) +{ ELEMSET *copy; + MEMBER *memb; + xassert(set != NULL); + xassert(set->type == A_NONE); + xassert(set->dim > 0); + copy = create_elemset(mpl, set->dim); + for (memb = set->head; memb != NULL; memb = memb->next) + add_tuple(mpl, copy, copy_tuple(mpl, memb->tuple)); + return copy; +} + +/*---------------------------------------------------------------------- +-- delete_elemset - delete elemental set. +-- +-- This routine deletes specified elemental set. */ + +void delete_elemset +( MPL *mpl, + ELEMSET *set /* destroyed */ +) +{ xassert(set != NULL); + xassert(set->type == A_NONE); + delete_array(mpl, set); + return; +} + +/*---------------------------------------------------------------------- +-- arelset_size - compute size of "arithmetic" elemental set. +-- +-- This routine computes the size of "arithmetic" elemental set, which +-- is specified in the form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- The size is computed using the formula: +-- +-- n = max(0, floor((tf - t0) / dt) + 1). */ + +int arelset_size(MPL *mpl, double t0, double tf, double dt) +{ double temp; + if (dt == 0.0) + error(mpl, "%.*g .. %.*g by %.*g; zero stride not allowed", + DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); + if (tf > 0.0 && t0 < 0.0 && tf > + 0.999 * DBL_MAX + t0) + temp = +DBL_MAX; + else if (tf < 0.0 && t0 > 0.0 && tf < - 0.999 * DBL_MAX + t0) + temp = -DBL_MAX; + else + temp = tf - t0; + if (fabs(dt) < 1.0 && fabs(temp) > (0.999 * DBL_MAX) * fabs(dt)) + { if (temp > 0.0 && dt > 0.0 || temp < 0.0 && dt < 0.0) + temp = +DBL_MAX; + else + temp = 0.0; + } + else + { temp = floor(temp / dt) + 1.0; + if (temp < 0.0) temp = 0.0; + } + xassert(temp >= 0.0); + if (temp > (double)(INT_MAX - 1)) + error(mpl, "%.*g .. %.*g by %.*g; set too large", + DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); + return (int)(temp + 0.5); +} + +/*---------------------------------------------------------------------- +-- arelset_member - compute member of "arithmetic" elemental set. +-- +-- This routine returns a numeric value of symbol, which is equivalent +-- to j-th member of given "arithmetic" elemental set specified in the +-- form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- The symbol value is computed with the formula: +-- +-- j-th member = t0 + (j - 1) * dt, +-- +-- The number j must satisfy to the restriction 1 <= j <= n, where n is +-- the set size computed by the routine arelset_size. */ + +double arelset_member(MPL *mpl, double t0, double tf, double dt, int j) +{ xassert(1 <= j && j <= arelset_size(mpl, t0, tf, dt)); + return t0 + (double)(j - 1) * dt; +} + +/*---------------------------------------------------------------------- +-- create_arelset - create "arithmetic" elemental set. +-- +-- This routine creates "arithmetic" elemental set, which is specified +-- in the form of arithmetic progression: +-- +-- { t0 .. tf by dt }. +-- +-- Components of this set are 1-tuples. */ + +ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt) +{ ELEMSET *set; + int j, n; + set = create_elemset(mpl, 1); + n = arelset_size(mpl, t0, tf, dt); + for (j = 1; j <= n; j++) + { add_tuple + ( mpl, + set, + expand_tuple + ( mpl, + create_tuple(mpl), + create_symbol_num + ( mpl, + arelset_member(mpl, t0, tf, dt, j) + ) + ) + ); + } + return set; +} + +/*---------------------------------------------------------------------- +-- set_union - union of two elemental sets. +-- +-- This routine computes the union: +-- +-- X U Y = { j | (j in X) or (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_union +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + for (memb = Y->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, X, memb->tuple) == NULL) + add_tuple(mpl, X, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, Y); + return X; +} + +/*---------------------------------------------------------------------- +-- set_diff - difference between two elemental sets. +-- +-- This routine computes the difference: +-- +-- X \ Y = { j | (j in X) and (j not in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_diff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_symdiff - symmetric difference between two elemental sets. +-- +-- This routine computes the symmetric difference: +-- +-- X (+) Y = (X \ Y) U (Y \ X), +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_symdiff +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + /* Z := X \ Y */ + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + /* Z := Z U (Y \ X) */ + for (memb = Y->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, X, memb->tuple) == NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_inter - intersection of two elemental sets. +-- +-- This routine computes the intersection: +-- +-- X ^ Y = { j | (j in X) and (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_inter +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memb; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + xassert(X->dim == Y->dim); + Z = create_elemset(mpl, X->dim); + for (memb = X->head; memb != NULL; memb = memb->next) + { if (find_tuple(mpl, Y, memb->tuple) != NULL) + add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/*---------------------------------------------------------------------- +-- set_cross - cross (Cartesian) product of two elemental sets. +-- +-- This routine computes the cross (Cartesian) product: +-- +-- X x Y = { (i,j) | (i in X) and (j in Y) }, +-- +-- where X and Y are given elemental sets (destroyed on exit). */ + +ELEMSET *set_cross +( MPL *mpl, + ELEMSET *X, /* destroyed */ + ELEMSET *Y /* destroyed */ +) +{ ELEMSET *Z; + MEMBER *memx, *memy; + TUPLE *tuple, *temp; + xassert(X != NULL); + xassert(X->type == A_NONE); + xassert(X->dim > 0); + xassert(Y != NULL); + xassert(Y->type == A_NONE); + xassert(Y->dim > 0); + Z = create_elemset(mpl, X->dim + Y->dim); + for (memx = X->head; memx != NULL; memx = memx->next) + { for (memy = Y->head; memy != NULL; memy = memy->next) + { tuple = copy_tuple(mpl, memx->tuple); + for (temp = memy->tuple; temp != NULL; temp = temp->next) + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + temp->sym)); + add_tuple(mpl, Z, tuple); + } + } + delete_elemset(mpl, X); + delete_elemset(mpl, Y); + return Z; +} + +/**********************************************************************/ +/* * * ELEMENTAL VARIABLES * * */ +/**********************************************************************/ + +/* (there are no specific routines for elemental variables) */ + +/**********************************************************************/ +/* * * LINEAR FORMS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- constant_term - create constant term. +-- +-- This routine creates the linear form, which is a constant term. */ + +FORMULA *constant_term(MPL *mpl, double coef) +{ FORMULA *form; + if (coef == 0.0) + form = NULL; + else + { form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + form->coef = coef; + form->var = NULL; + form->next = NULL; + } + return form; +} + +/*---------------------------------------------------------------------- +-- single_variable - create single variable. +-- +-- This routine creates the linear form, which is a single elemental +-- variable. */ + +FORMULA *single_variable +( MPL *mpl, + ELEMVAR *var /* referenced */ +) +{ FORMULA *form; + xassert(var != NULL); + form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + form->coef = 1.0; + form->var = var; + form->next = NULL; + return form; +} + +/*---------------------------------------------------------------------- +-- copy_formula - make copy of linear form. +-- +-- This routine returns an exact copy of linear form. */ + +FORMULA *copy_formula +( MPL *mpl, + FORMULA *form /* not changed */ +) +{ FORMULA *head, *tail; + if (form == NULL) + head = NULL; + else + { head = tail = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + for (; form != NULL; form = form->next) + { tail->coef = form->coef; + tail->var = form->var; + if (form->next != NULL) +tail = (tail->next = dmp_get_atom(mpl->formulae, sizeof(FORMULA))); + } + tail->next = NULL; + } + return head; +} + +/*---------------------------------------------------------------------- +-- delete_formula - delete linear form. +-- +-- This routine deletes specified linear form. */ + +void delete_formula +( MPL *mpl, + FORMULA *form /* destroyed */ +) +{ FORMULA *temp; + while (form != NULL) + { temp = form; + form = form->next; + dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); + } + return; +} + +/*---------------------------------------------------------------------- +-- linear_comb - linear combination of two linear forms. +-- +-- This routine computes the linear combination: +-- +-- a * fx + b * fy, +-- +-- where a and b are numeric coefficients, fx and fy are linear forms +-- (destroyed on exit). */ + +FORMULA *linear_comb +( MPL *mpl, + double a, FORMULA *fx, /* destroyed */ + double b, FORMULA *fy /* destroyed */ +) +{ FORMULA *form = NULL, *term, *temp; + double c0 = 0.0; + for (term = fx; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, fp_mul(mpl, a, term->coef)); + else + term->var->temp = + fp_add(mpl, term->var->temp, fp_mul(mpl, a, term->coef)); + } + for (term = fy; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, fp_mul(mpl, b, term->coef)); + else + term->var->temp = + fp_add(mpl, term->var->temp, fp_mul(mpl, b, term->coef)); + } + for (term = fx; term != NULL; term = term->next) + { if (term->var != NULL && term->var->temp != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = term->var->temp, temp->var = term->var; + temp->next = form, form = temp; + term->var->temp = 0.0; + } + } + for (term = fy; term != NULL; term = term->next) + { if (term->var != NULL && term->var->temp != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = term->var->temp, temp->var = term->var; + temp->next = form, form = temp; + term->var->temp = 0.0; + } + } + if (c0 != 0.0) + { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); + temp->coef = c0, temp->var = NULL; + temp->next = form, form = temp; + } + delete_formula(mpl, fx); + delete_formula(mpl, fy); + return form; +} + +/*---------------------------------------------------------------------- +-- remove_constant - remove constant term from linear form. +-- +-- This routine removes constant term from linear form and stores its +-- value to given location. */ + +FORMULA *remove_constant +( MPL *mpl, + FORMULA *form, /* destroyed */ + double *coef /* modified */ +) +{ FORMULA *head = NULL, *temp; + *coef = 0.0; + while (form != NULL) + { temp = form; + form = form->next; + if (temp->var == NULL) + { /* constant term */ + *coef = fp_add(mpl, *coef, temp->coef); + dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); + } + else + { /* linear term */ + temp->next = head; + head = temp; + } + } + return head; +} + +/*---------------------------------------------------------------------- +-- reduce_terms - reduce identical terms in linear form. +-- +-- This routine reduces identical terms in specified linear form. */ + +FORMULA *reduce_terms +( MPL *mpl, + FORMULA *form /* destroyed */ +) +{ FORMULA *term, *next_term; + double c0 = 0.0; + for (term = form; term != NULL; term = term->next) + { if (term->var == NULL) + c0 = fp_add(mpl, c0, term->coef); + else + term->var->temp = fp_add(mpl, term->var->temp, term->coef); + } + next_term = form, form = NULL; + for (term = next_term; term != NULL; term = next_term) + { next_term = term->next; + if (term->var == NULL && c0 != 0.0) + { term->coef = c0, c0 = 0.0; + term->next = form, form = term; + } + else if (term->var != NULL && term->var->temp != 0.0) + { term->coef = term->var->temp, term->var->temp = 0.0; + term->next = form, form = term; + } + else + dmp_free_atom(mpl->formulae, term, sizeof(FORMULA)); + } + return form; +} + +/**********************************************************************/ +/* * * ELEMENTAL CONSTRAINTS * * */ +/**********************************************************************/ + +/* (there are no specific routines for elemental constraints) */ + +/**********************************************************************/ +/* * * GENERIC VALUES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- delete_value - delete generic value. +-- +-- This routine deletes specified generic value. +-- +-- NOTE: The generic value to be deleted must be valid. */ + +void delete_value +( MPL *mpl, + int type, + VALUE *value /* content destroyed */ +) +{ xassert(value != NULL); + switch (type) + { case A_NONE: + value->none = NULL; + break; + case A_NUMERIC: + value->num = 0.0; + break; + case A_SYMBOLIC: + delete_symbol(mpl, value->sym), value->sym = NULL; + break; + case A_LOGICAL: + value->bit = 0; + break; + case A_TUPLE: + delete_tuple(mpl, value->tuple), value->tuple = NULL; + break; + case A_ELEMSET: + delete_elemset(mpl, value->set), value->set = NULL; + break; + case A_ELEMVAR: + value->var = NULL; + break; + case A_FORMULA: + delete_formula(mpl, value->form), value->form = NULL; + break; + case A_ELEMCON: + value->con = NULL; + break; + default: + xassert(type != type); + } + return; +} + +/**********************************************************************/ +/* * * SYMBOLICALLY INDEXED ARRAYS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- create_array - create array. +-- +-- This routine creates an array of specified type and dimension. Being +-- created the array is initially empty. +-- +-- The type indicator determines generic values, which can be assigned +-- to the array members: +-- +-- A_NONE - none (members have no assigned values) +-- A_NUMERIC - floating-point numbers +-- A_SYMBOLIC - symbols +-- A_ELEMSET - elemental sets +-- A_ELEMVAR - elemental variables +-- A_ELEMCON - elemental constraints +-- +-- The dimension may be 0, in which case the array consists of the only +-- member (such arrays represent 0-dimensional objects). */ + +ARRAY *create_array(MPL *mpl, int type, int dim) +{ ARRAY *array; + xassert(type == A_NONE || type == A_NUMERIC || + type == A_SYMBOLIC || type == A_ELEMSET || + type == A_ELEMVAR || type == A_ELEMCON); + xassert(dim >= 0); + array = dmp_get_atom(mpl->arrays, sizeof(ARRAY)); + array->type = type; + array->dim = dim; + array->size = 0; + array->head = NULL; + array->tail = NULL; + array->tree = NULL; + array->prev = NULL; + array->next = mpl->a_list; + /* include the array in the global array list */ + if (array->next != NULL) array->next->prev = array; + mpl->a_list = array; + return array; +} + +/*---------------------------------------------------------------------- +-- find_member - find array member with given n-tuple. +-- +-- This routine finds an array member, which has given n-tuple. If the +-- array is short, the linear search is used. Otherwise the routine +-- autimatically creates the search tree (i.e. the array index) to find +-- members for logarithmic time. */ + +static int compare_member_tuples(void *info, const void *key1, + const void *key2) +{ /* this is an auxiliary routine used to compare keys, which are + n-tuples assigned to array members */ + return compare_tuples((MPL *)info, (TUPLE *)key1, (TUPLE *)key2); +} + +MEMBER *find_member +( MPL *mpl, + ARRAY *array, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* the n-tuple must have the same dimension as the array */ + xassert(tuple_dimen(mpl, tuple) == array->dim); + /* if the array is large enough, create the search tree and index + all existing members of the array */ + if (array->size > 30 && array->tree == NULL) + { array->tree = avl_create_tree(compare_member_tuples, mpl); + for (memb = array->head; memb != NULL; memb = memb->next) +avl_set_node_link(avl_insert_node(array->tree, memb->tuple), + (void *)memb); + } + /* find a member, which has the given tuple */ + if (array->tree == NULL) + { /* the search tree doesn't exist; use the linear search */ + for (memb = array->head; memb != NULL; memb = memb->next) + if (compare_tuples(mpl, memb->tuple, tuple) == 0) break; + } + else + { /* the search tree exists; use the binary search */ + AVLNODE *node; + node = avl_find_node(array->tree, tuple); +memb = (MEMBER *)(node == NULL ? NULL : avl_get_node_link(node)); + } + return memb; +} + +/*---------------------------------------------------------------------- +-- add_member - add new member to array. +-- +-- This routine creates a new member with given n-tuple and adds it to +-- specified array. +-- +-- For the sake of efficiency this routine doesn't check whether the +-- array already contains a member with the given n-tuple or not. Thus, +-- if necessary, the calling program should use the routine find_member +-- in order to be sure that the array contains no member with the same +-- n-tuple, because members with duplicate n-tuples are not allowed. +-- +-- This routine assigns no generic value to the new member, because the +-- calling program must do that. */ + +MEMBER *add_member +( MPL *mpl, + ARRAY *array, /* modified */ + TUPLE *tuple /* destroyed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* the n-tuple must have the same dimension as the array */ + xassert(tuple_dimen(mpl, tuple) == array->dim); + /* create new member */ + memb = dmp_get_atom(mpl->members, sizeof(MEMBER)); + memb->tuple = tuple; + memb->next = NULL; + memset(&memb->value, '?', sizeof(VALUE)); + /* and append it to the member list */ + array->size++; + if (array->head == NULL) + array->head = memb; + else + array->tail->next = memb; + array->tail = memb; + /* if the search tree exists, index the new member */ + if (array->tree != NULL) +avl_set_node_link(avl_insert_node(array->tree, memb->tuple), + (void *)memb); + return memb; +} + +/*---------------------------------------------------------------------- +-- delete_array - delete array. +-- +-- This routine deletes specified array. +-- +-- Generic values assigned to the array members are not deleted by this +-- routine. The calling program itself must delete all assigned generic +-- values before deleting the array. */ + +void delete_array +( MPL *mpl, + ARRAY *array /* destroyed */ +) +{ MEMBER *memb; + xassert(array != NULL); + /* delete all existing array members */ + while (array->head != NULL) + { memb = array->head; + array->head = memb->next; + delete_tuple(mpl, memb->tuple); + dmp_free_atom(mpl->members, memb, sizeof(MEMBER)); + } + /* if the search tree exists, also delete it */ + if (array->tree != NULL) avl_delete_tree(array->tree); + /* remove the array from the global array list */ + if (array->prev == NULL) + mpl->a_list = array->next; + else + array->prev->next = array->next; + if (array->next == NULL) + ; + else + array->next->prev = array->prev; + /* delete the array descriptor */ + dmp_free_atom(mpl->arrays, array, sizeof(ARRAY)); + return; +} + +/**********************************************************************/ +/* * * DOMAINS AND DUMMY INDICES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- assign_dummy_index - assign new value to dummy index. +-- +-- This routine assigns new value to specified dummy index and, that is +-- important, invalidates all temporary resultant values, which depends +-- on that dummy index. */ + +void assign_dummy_index +( MPL *mpl, + DOMAIN_SLOT *slot, /* modified */ + SYMBOL *value /* not changed */ +) +{ CODE *leaf, *code; + xassert(slot != NULL); + xassert(value != NULL); + /* delete the current value assigned to the dummy index */ + if (slot->value != NULL) + { /* if the current value and the new one are identical, actual + assignment is not needed */ + if (compare_symbols(mpl, slot->value, value) == 0) goto done; + /* delete a symbol, which is the current value */ + delete_symbol(mpl, slot->value), slot->value = NULL; + } + /* now walk through all the pseudo-codes with op = O_INDEX, which + refer to the dummy index to be changed (these pseudo-codes are + leaves in the forest of *all* expressions in the database) */ + for (leaf = slot->list; leaf != NULL; leaf = leaf->arg.index. + next) + { xassert(leaf->op == O_INDEX); + /* invalidate all resultant values, which depend on the dummy + index, walking from the current leaf toward the root of the + corresponding expression tree */ + for (code = leaf; code != NULL; code = code->up) + { if (code->valid) + { /* invalidate and delete resultant value */ + code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + } + } + /* assign new value to the dummy index */ + slot->value = copy_symbol(mpl, value); +done: return; +} + +/*---------------------------------------------------------------------- +-- update_dummy_indices - update current values of dummy indices. +-- +-- This routine assigns components of "backup" n-tuple to dummy indices +-- of specified domain block. If no "backup" n-tuple is defined for the +-- domain block, values of the dummy indices remain untouched. */ + +void update_dummy_indices +( MPL *mpl, + DOMAIN_BLOCK *block /* not changed */ +) +{ DOMAIN_SLOT *slot; + TUPLE *temp; + if (block->backup != NULL) + { for (slot = block->list, temp = block->backup; slot != NULL; + slot = slot->next, temp = temp->next) + { xassert(temp != NULL); + xassert(temp->sym != NULL); + assign_dummy_index(mpl, slot, temp->sym); + } + } + return; +} + +/*---------------------------------------------------------------------- +-- enter_domain_block - enter domain block. +-- +-- Let specified domain block have the form: +-- +-- { ..., (j1, j2, ..., jn) in J, ... } +-- +-- where j1, j2, ..., jn are dummy indices, J is a basic set. +-- +-- This routine does the following: +-- +-- 1. Checks if the given n-tuple is a member of the basic set J. Note +-- that J being *out of the scope* of the domain block cannot depend +-- on the dummy indices in the same and inner domain blocks, so it +-- can be computed before the dummy indices are assigned new values. +-- If this check fails, the routine returns with non-zero code. +-- +-- 2. Saves current values of the dummy indices j1, j2, ..., jn. +-- +-- 3. Assigns new values, which are components of the given n-tuple, to +-- the dummy indices j1, j2, ..., jn. If dimension of the n-tuple is +-- larger than n, its extra components n+1, n+2, ... are not used. +-- +-- 4. Calls the formal routine func which either enters the next domain +-- block or evaluates some code within the domain scope. +-- +-- 5. Restores former values of the dummy indices j1, j2, ..., jn. +-- +-- Since current values assigned to the dummy indices on entry to this +-- routine are restored on exit, the formal routine func is allowed to +-- call this routine recursively. */ + +int enter_domain_block +( MPL *mpl, + DOMAIN_BLOCK *block, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +) +{ TUPLE *backup; + int ret = 0; + /* check if the given n-tuple is a member of the basic set */ + xassert(block->code != NULL); + if (!is_member(mpl, block->code, tuple)) + { ret = 1; + goto done; + } + /* save reference to "backup" n-tuple, which was used to assign + current values of the dummy indices (it is sufficient to save + reference, not value, because that n-tuple is defined in some + outer level of recursion and therefore cannot be changed on + this and deeper recursive calls) */ + backup = block->backup; + /* set up new "backup" n-tuple, which defines new values of the + dummy indices */ + block->backup = tuple; + /* assign new values to the dummy indices */ + update_dummy_indices(mpl, block); + /* call the formal routine that does the rest part of the job */ + func(mpl, info); + /* restore reference to the former "backup" n-tuple */ + block->backup = backup; + /* restore former values of the dummy indices; note that if the + domain block just escaped has no other active instances which + may exist due to recursion (it is indicated by a null pointer + to the former n-tuple), former values of the dummy indices are + undefined; therefore in this case the routine keeps currently + assigned values of the dummy indices that involves keeping all + dependent temporary results and thereby, if this domain block + is not used recursively, allows improving efficiency */ + update_dummy_indices(mpl, block); +done: return ret; +} + +/*---------------------------------------------------------------------- +-- eval_within_domain - perform evaluation within domain scope. +-- +-- This routine assigns new values (symbols) to all dummy indices of +-- specified domain and calls the formal routine func, which is used to +-- evaluate some code in the domain scope. Each free dummy index in the +-- domain is assigned a value specified in the corresponding component +-- of given n-tuple. Non-free dummy indices are assigned values, which +-- are computed by this routine. +-- +-- Number of components in the given n-tuple must be the same as number +-- of free indices in the domain. +-- +-- If the given n-tuple is not a member of the domain set, the routine +-- func is not called, and non-zero code is returned. +-- +-- For the sake of convenience it is allowed to specify domain as NULL +-- (then n-tuple also must be 0-tuple, i.e. empty), in which case this +-- routine just calls the routine func and returns zero. +-- +-- This routine allows recursive calls from the routine func providing +-- correct values of dummy indices for each instance. +-- +-- NOTE: The n-tuple passed to this routine must not be changed by any +-- other routines called from the formal routine func until this +-- routine has returned. */ + +struct eval_domain_info +{ /* working info used by the routine eval_within_domain */ + DOMAIN *domain; + /* domain, which has to be entered */ + DOMAIN_BLOCK *block; + /* domain block, which is currently processed */ + TUPLE *tuple; + /* tail of original n-tuple, whose components have to be assigned + to free dummy indices in the current domain block */ + void *info; + /* transit pointer passed to the formal routine func */ + void (*func)(MPL *mpl, void *info); + /* routine, which has to be executed in the domain scope */ + int failure; + /* this flag indicates that given n-tuple is not a member of the + domain set */ +}; + +static void eval_domain_func(MPL *mpl, void *_my_info) +{ /* this routine recursively enters into the domain scope and then + calls the routine func */ + struct eval_domain_info *my_info = _my_info; + if (my_info->block != NULL) + { /* the current domain block to be entered exists */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *tuple = NULL, *temp = NULL; + /* save pointer to the current domain block */ + block = my_info->block; + /* and get ready to enter the next block (if it exists) */ + my_info->block = block->next; + /* construct temporary n-tuple, whose components correspond to + dummy indices (slots) of the current domain; components of + the temporary n-tuple that correspond to free dummy indices + are assigned references (not values!) to symbols specified + in the corresponding components of the given n-tuple, while + other components that correspond to non-free dummy indices + are assigned symbolic values computed here */ + for (slot = block->list; slot != NULL; slot = slot->next) + { /* create component that corresponds to the current slot */ + if (tuple == NULL) + tuple = temp = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); + else +temp = (temp->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); + if (slot->code == NULL) + { /* dummy index is free; take reference to symbol, which + is specified in the corresponding component of given + n-tuple */ + xassert(my_info->tuple != NULL); + temp->sym = my_info->tuple->sym; + xassert(temp->sym != NULL); + my_info->tuple = my_info->tuple->next; + } + else + { /* dummy index is non-free; compute symbolic value to be + temporarily assigned to the dummy index */ + temp->sym = eval_symbolic(mpl, slot->code); + } + } + temp->next = NULL; + /* enter the current domain block */ + if (enter_domain_block(mpl, block, tuple, my_info, + eval_domain_func)) my_info->failure = 1; + /* delete temporary n-tuple as well as symbols that correspond + to non-free dummy indices (they were computed here) */ + for (slot = block->list; slot != NULL; slot = slot->next) + { xassert(tuple != NULL); + temp = tuple; + tuple = tuple->next; + if (slot->code != NULL) + { /* dummy index is non-free; delete symbolic value */ + delete_symbol(mpl, temp->sym); + } + /* delete component that corresponds to the current slot */ + dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); + } + } + else + { /* there are no more domain blocks, i.e. we have reached the + domain scope */ + xassert(my_info->tuple == NULL); + /* check optional predicate specified for the domain */ + if (my_info->domain->code != NULL && !eval_logical(mpl, + my_info->domain->code)) + { /* the predicate is false */ + my_info->failure = 2; + } + else + { /* the predicate is true; do the job */ + my_info->func(mpl, my_info->info); + } + } + return; +} + +int eval_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + TUPLE *tuple, /* not changed */ + void *info, void (*func)(MPL *mpl, void *info) +) +{ /* this routine performs evaluation within domain scope */ + struct eval_domain_info _my_info, *my_info = &_my_info; + if (domain == NULL) + { xassert(tuple == NULL); + func(mpl, info); + my_info->failure = 0; + } + else + { xassert(tuple != NULL); + my_info->domain = domain; + my_info->block = domain->list; + my_info->tuple = tuple; + my_info->info = info; + my_info->func = func; + my_info->failure = 0; + /* enter the very first domain block */ + eval_domain_func(mpl, my_info); + } + return my_info->failure; +} + +/*---------------------------------------------------------------------- +-- loop_within_domain - perform iterations within domain scope. +-- +-- This routine iteratively assigns new values (symbols) to the dummy +-- indices of specified domain by enumerating all n-tuples, which are +-- members of the domain set, and for every n-tuple it calls the formal +-- routine func to evaluate some code within the domain scope. +-- +-- If the routine func returns non-zero, enumeration within the domain +-- is prematurely terminated. +-- +-- For the sake of convenience it is allowed to specify domain as NULL, +-- in which case this routine just calls the routine func only once and +-- returns zero. +-- +-- This routine allows recursive calls from the routine func providing +-- correct values of dummy indices for each instance. */ + +struct loop_domain_info +{ /* working info used by the routine loop_within_domain */ + DOMAIN *domain; + /* domain, which has to be entered */ + DOMAIN_BLOCK *block; + /* domain block, which is currently processed */ + int looping; + /* clearing this flag leads to terminating enumeration */ + void *info; + /* transit pointer passed to the formal routine func */ + int (*func)(MPL *mpl, void *info); + /* routine, which needs to be executed in the domain scope */ +}; + +static void loop_domain_func(MPL *mpl, void *_my_info) +{ /* this routine enumerates all n-tuples in the basic set of the + current domain block, enters recursively into the domain scope + for every n-tuple, and then calls the routine func */ + struct loop_domain_info *my_info = _my_info; + if (my_info->block != NULL) + { /* the current domain block to be entered exists */ + DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *bound; + /* save pointer to the current domain block */ + block = my_info->block; + /* and get ready to enter the next block (if it exists) */ + my_info->block = block->next; + /* compute symbolic values, at which non-free dummy indices of + the current domain block are bound; since that values don't + depend on free dummy indices of the current block, they can + be computed once out of the enumeration loop */ + bound = create_tuple(mpl); + for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code != NULL) + bound = expand_tuple(mpl, bound, eval_symbolic(mpl, + slot->code)); + } + /* start enumeration */ + xassert(block->code != NULL); + if (block->code->op == O_DOTS) + { /* the basic set is "arithmetic", in which case it doesn't + need to be computed explicitly */ + TUPLE *tuple; + int n, j; + double t0, tf, dt; + /* compute "parameters" of the basic set */ + t0 = eval_numeric(mpl, block->code->arg.arg.x); + tf = eval_numeric(mpl, block->code->arg.arg.y); + if (block->code->arg.arg.z == NULL) + dt = 1.0; + else + dt = eval_numeric(mpl, block->code->arg.arg.z); + /* determine cardinality of the basic set */ + n = arelset_size(mpl, t0, tf, dt); + /* create dummy 1-tuple for members of the basic set */ + tuple = expand_tuple(mpl, create_tuple(mpl), + create_symbol_num(mpl, 0.0)); + /* in case of "arithmetic" set there is exactly one dummy + index, which cannot be non-free */ + xassert(bound == NULL); + /* walk through 1-tuples of the basic set */ + for (j = 1; j <= n && my_info->looping; j++) + { /* construct dummy 1-tuple for the current member */ + tuple->sym->num = arelset_member(mpl, t0, tf, dt, j); + /* enter the current domain block */ + enter_domain_block(mpl, block, tuple, my_info, + loop_domain_func); + } + /* delete dummy 1-tuple */ + delete_tuple(mpl, tuple); + } + else + { /* the basic set is of general kind, in which case it needs + to be explicitly computed */ + ELEMSET *set; + MEMBER *memb; + TUPLE *temp1, *temp2; + /* compute the basic set */ + set = eval_elemset(mpl, block->code); + /* walk through all n-tuples of the basic set */ + for (memb = set->head; memb != NULL && my_info->looping; + memb = memb->next) + { /* all components of the current n-tuple that correspond + to non-free dummy indices must be feasible; otherwise + the n-tuple is not in the basic set */ + temp1 = memb->tuple; + temp2 = bound; + for (slot = block->list; slot != NULL; slot = slot->next) + { xassert(temp1 != NULL); + if (slot->code != NULL) + { /* non-free dummy index */ + xassert(temp2 != NULL); + if (compare_symbols(mpl, temp1->sym, temp2->sym) + != 0) + { /* the n-tuple is not in the basic set */ + goto skip; + } + temp2 = temp2->next; + } + temp1 = temp1->next; + } + xassert(temp1 == NULL); + xassert(temp2 == NULL); + /* enter the current domain block */ + enter_domain_block(mpl, block, memb->tuple, my_info, + loop_domain_func); +skip: ; + } + /* delete the basic set */ + delete_elemset(mpl, set); + } + /* delete symbolic values binding non-free dummy indices */ + delete_tuple(mpl, bound); + /* restore pointer to the current domain block */ + my_info->block = block; + } + else + { /* there are no more domain blocks, i.e. we have reached the + domain scope */ + /* check optional predicate specified for the domain */ + if (my_info->domain->code != NULL && !eval_logical(mpl, + my_info->domain->code)) + { /* the predicate is false */ + /* nop */; + } + else + { /* the predicate is true; do the job */ + my_info->looping = !my_info->func(mpl, my_info->info); + } + } + return; +} + +void loop_within_domain +( MPL *mpl, + DOMAIN *domain, /* not changed */ + void *info, int (*func)(MPL *mpl, void *info) +) +{ /* this routine performs iterations within domain scope */ + struct loop_domain_info _my_info, *my_info = &_my_info; + if (domain == NULL) + func(mpl, info); + else + { my_info->domain = domain; + my_info->block = domain->list; + my_info->looping = 1; + my_info->info = info; + my_info->func = func; + /* enter the very first domain block */ + loop_domain_func(mpl, my_info); + } + return; +} + +/*---------------------------------------------------------------------- +-- out_of_domain - raise domain exception. +-- +-- This routine is called when a reference is made to a member of some +-- model object, but its n-tuple is out of the object domain. */ + +void out_of_domain +( MPL *mpl, + char *name, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ xassert(name != NULL); + xassert(tuple != NULL); + error(mpl, "%s%s out of domain", name, format_tuple(mpl, '[', + tuple)); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- get_domain_tuple - obtain current n-tuple from domain. +-- +-- This routine constructs n-tuple, whose components are current values +-- assigned to *free* dummy indices of specified domain. +-- +-- For the sake of convenience it is allowed to specify domain as NULL, +-- in which case this routine returns 0-tuple. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +TUPLE *get_domain_tuple +( MPL *mpl, + DOMAIN *domain /* not changed */ +) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + TUPLE *tuple; + tuple = create_tuple(mpl); + if (domain != NULL) + { for (block = domain->list; block != NULL; block = block->next) + { for (slot = block->list; slot != NULL; slot = slot->next) + { if (slot->code == NULL) + { xassert(slot->value != NULL); + tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, + slot->value)); + } + } + } + } + return tuple; +} + +/*---------------------------------------------------------------------- +-- clean_domain - clean domain. +-- +-- This routine cleans specified domain that assumes deleting all stuff +-- dynamically allocated during the generation phase. */ + +void clean_domain(MPL *mpl, DOMAIN *domain) +{ DOMAIN_BLOCK *block; + DOMAIN_SLOT *slot; + /* if no domain is specified, do nothing */ + if (domain == NULL) goto done; + /* clean all domain blocks */ + for (block = domain->list; block != NULL; block = block->next) + { /* clean all domain slots */ + for (slot = block->list; slot != NULL; slot = slot->next) + { /* clean pseudo-code for computing bound value */ + clean_code(mpl, slot->code); + /* delete symbolic value assigned to dummy index */ + if (slot->value != NULL) + delete_symbol(mpl, slot->value), slot->value = NULL; + } + /* clean pseudo-code for computing basic set */ + clean_code(mpl, block->code); + } + /* clean pseudo-code for computing domain predicate */ + clean_code(mpl, domain->code); +done: return; +} + +/**********************************************************************/ +/* * * MODEL SETS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- check_elem_set - check elemental set assigned to set member. +-- +-- This routine checks if given elemental set being assigned to member +-- of specified model set satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_elem_set +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple, /* not changed */ + ELEMSET *refer /* not changed */ +) +{ WITHIN *within; + MEMBER *memb; + int eqno; + /* elemental set must be within all specified supersets */ + for (within = set->within, eqno = 1; within != NULL; within = + within->next, eqno++) + { xassert(within->code != NULL); + for (memb = refer->head; memb != NULL; memb = memb->next) + { if (!is_member(mpl, within->code, memb->tuple)) + { char buf[255+1]; + strcpy(buf, format_tuple(mpl, '(', memb->tuple)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s contains %s which not within specified " + "set; see (%d)", set->name, format_tuple(mpl, '[', + tuple), buf, eqno); + } + } + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_set - obtain elemental set assigned to set member. +-- +-- This routine obtains a reference to elemental set assigned to given +-- member of specified model set and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMSET *take_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMSET *refer; + /* find member in the set array */ + memb = find_member(mpl, set->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.set; + } + else if (set->assign != NULL) + { /* compute value using assignment expression */ + refer = eval_elemset(mpl, set->assign); +add: /* check that the elemental set satisfies to all restrictions, + assign it to new member, and add the member to the array */ + check_elem_set(mpl, set, tuple, refer); + memb = add_member(mpl, set->array, copy_tuple(mpl, tuple)); + memb->value.set = refer; + } + else if (set->option != NULL) + { /* compute default elemental set */ + refer = eval_elemset(mpl, set->option); + goto add; + } + else + { /* no value (elemental set) is provided */ + error(mpl, "no value for %s%s", set->name, format_tuple(mpl, + '[', tuple)); + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_set - evaluate elemental set assigned to set member. +-- +-- This routine evaluates a reference to elemental set assigned to given +-- member of specified model set and returns it on exit. */ + +struct eval_set_info +{ /* working info used by the routine eval_member_set */ + SET *set; + /* model set */ + TUPLE *tuple; + /* n-tuple, which defines set member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + ELEMSET *refer; + /* evaluated reference to elemental set */ +}; + +static void eval_set_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_set_info *info = _info; + if (info->memb != NULL) + { /* checking call; check elemental set being assigned */ + check_elem_set(mpl, info->set, info->memb->tuple, + info->memb->value.set); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->refer = take_member_set(mpl, info->set, info->tuple); + } + return; +} + +#if 1 /* 12/XII-2008 */ +static void saturate_set(MPL *mpl, SET *set) +{ GADGET *gadget = set->gadget; + ELEMSET *data; + MEMBER *elem, *memb; + TUPLE *tuple, *work[20]; + int i; + xprintf("Generating %s...\n", set->name); + eval_whole_set(mpl, gadget->set); + /* gadget set must have exactly one member */ + xassert(gadget->set->array != NULL); + xassert(gadget->set->array->head != NULL); + xassert(gadget->set->array->head == gadget->set->array->tail); + data = gadget->set->array->head->value.set; + xassert(data->type == A_NONE); + xassert(data->dim == gadget->set->dimen); + /* walk thru all elements of the plain set */ + for (elem = data->head; elem != NULL; elem = elem->next) + { /* create a copy of n-tuple */ + tuple = copy_tuple(mpl, elem->tuple); + /* rearrange component of the n-tuple */ + for (i = 0; i < gadget->set->dimen; i++) + work[i] = NULL; + for (i = 0; tuple != NULL; tuple = tuple->next) + work[gadget->ind[i++]-1] = tuple; + xassert(i == gadget->set->dimen); + for (i = 0; i < gadget->set->dimen; i++) + { xassert(work[i] != NULL); + work[i]->next = work[i+1]; + } + /* construct subscript list from first set->dim components */ + if (set->dim == 0) + tuple = NULL; + else + tuple = work[0], work[set->dim-1]->next = NULL; + /* find corresponding member of the set to be initialized */ + memb = find_member(mpl, set->array, tuple); + if (memb == NULL) + { /* not found; add new member to the set and assign it empty + elemental set */ + memb = add_member(mpl, set->array, tuple); + memb->value.set = create_elemset(mpl, set->dimen); + } + else + { /* found; free subscript list */ + delete_tuple(mpl, tuple); + } + /* construct new n-tuple from rest set->dimen components */ + tuple = work[set->dim]; + xassert(set->dim + set->dimen == gadget->set->dimen); + work[gadget->set->dimen-1]->next = NULL; + /* and add it to the elemental set assigned to the member + (no check for duplicates is needed) */ + add_tuple(mpl, memb->value.set, tuple); + } + /* the set has been saturated with data */ + set->data = 1; + return; +} +#endif + +ELEMSET *eval_member_set /* returns reference, not value */ +( MPL *mpl, + SET *set, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates set member */ + struct eval_set_info _info, *info = &_info; + xassert(set->dim == tuple_dimen(mpl, tuple)); + info->set = set; + info->tuple = tuple; +#if 1 /* 12/XII-2008 */ + if (set->gadget != NULL && set->data == 0) + { /* initialize the set with data from a plain set */ + saturate_set(mpl, set); + } +#endif + if (set->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting supersets; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = set->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same set during the check */ + set->data = 2; + /* check elemental sets assigned to array members in the data + section until the marked member has been reached */ + for (info->memb = set->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, set->domain, info->memb->tuple, + info, eval_set_func)) + out_of_domain(mpl, set->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->set->domain, info->tuple, info, + eval_set_func)) + out_of_domain(mpl, set->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_set - evaluate model set over entire domain. +-- +-- This routine evaluates all members of specified model set over entire +-- domain. */ + +static int whole_set_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + SET *set = (SET *)info; + TUPLE *tuple = get_domain_tuple(mpl, set->domain); + eval_member_set(mpl, set, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_set(MPL *mpl, SET *set) +{ loop_within_domain(mpl, set->domain, set, whole_set_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean set - clean model set. +-- +-- This routine cleans specified model set that assumes deleting all +-- stuff dynamically allocated during the generation phase. */ + +void clean_set(MPL *mpl, SET *set) +{ WITHIN *within; + MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, set->domain); + /* clean pseudo-code for computing supersets */ + for (within = set->within; within != NULL; within = within->next) + clean_code(mpl, within->code); + /* clean pseudo-code for computing assigned value */ + clean_code(mpl, set->assign); + /* clean pseudo-code for computing default value */ + clean_code(mpl, set->option); + /* reset data status flag */ + set->data = 0; + /* delete content array */ + for (memb = set->array->head; memb != NULL; memb = memb->next) + delete_value(mpl, set->array->type, &memb->value); + delete_array(mpl, set->array), set->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL PARAMETERS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- check_value_num - check numeric value assigned to parameter member. +-- +-- This routine checks if numeric value being assigned to some member +-- of specified numeric model parameter satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_value_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + double value +) +{ CONDITION *cond; + WITHIN *in; + int eqno; + /* the value must satisfy to the parameter type */ + switch (par->type) + { case A_NUMERIC: + break; + case A_INTEGER: + if (value != floor(value)) + error(mpl, "%s%s = %.*g not integer", par->name, + format_tuple(mpl, '[', tuple), DBL_DIG, value); + break; + case A_BINARY: + if (!(value == 0.0 || value == 1.0)) + error(mpl, "%s%s = %.*g not binary", par->name, + format_tuple(mpl, '[', tuple), DBL_DIG, value); + break; + default: + xassert(par != par); + } + /* the value must satisfy to all specified conditions */ + for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, + eqno++) + { double bound; + char *rho; + xassert(cond->code != NULL); + bound = eval_numeric(mpl, cond->code); + switch (cond->rho) + { case O_LT: + if (!(value < bound)) + { rho = "<"; +err: error(mpl, "%s%s = %.*g not %s %.*g; see (%d)", + par->name, format_tuple(mpl, '[', tuple), DBL_DIG, + value, rho, DBL_DIG, bound, eqno); + } + break; + case O_LE: + if (!(value <= bound)) { rho = "<="; goto err; } + break; + case O_EQ: + if (!(value == bound)) { rho = "="; goto err; } + break; + case O_GE: + if (!(value >= bound)) { rho = ">="; goto err; } + break; + case O_GT: + if (!(value > bound)) { rho = ">"; goto err; } + break; + case O_NE: + if (!(value != bound)) { rho = "<>"; goto err; } + break; + default: + xassert(cond != cond); + } + } + /* the value must be in all specified supersets */ + for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) + { TUPLE *dummy; + xassert(in->code != NULL); + xassert(in->code->dim == 1); + dummy = expand_tuple(mpl, create_tuple(mpl), + create_symbol_num(mpl, value)); + if (!is_member(mpl, in->code, dummy)) + error(mpl, "%s%s = %.*g not in specified set; see (%d)", + par->name, format_tuple(mpl, '[', tuple), DBL_DIG, + value, eqno); + delete_tuple(mpl, dummy); + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_num - obtain num. value assigned to parameter member. +-- +-- This routine obtains a numeric value assigned to member of specified +-- numeric model parameter and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +double take_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + double value; + /* find member in the parameter array */ + memb = find_member(mpl, par->array, tuple); + if (memb != NULL) + { /* member exists, so just take its value */ + value = memb->value.num; + } + else if (par->assign != NULL) + { /* compute value using assignment expression */ + value = eval_numeric(mpl, par->assign); +add: /* check that the value satisfies to all restrictions, assign + it to new member, and add the member to the array */ + check_value_num(mpl, par, tuple, value); + memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); + memb->value.num = value; + } + else if (par->option != NULL) + { /* compute default value */ + value = eval_numeric(mpl, par->option); + goto add; + } + else if (par->defval != NULL) + { /* take default value provided in the data section */ + if (par->defval->str != NULL) + error(mpl, "cannot convert %s to floating-point number", + format_symbol(mpl, par->defval)); + value = par->defval->num; + goto add; + } + else + { /* no value is provided */ + error(mpl, "no value for %s%s", par->name, format_tuple(mpl, + '[', tuple)); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_member_num - evaluate num. value assigned to parameter member. +-- +-- This routine evaluates a numeric value assigned to given member of +-- specified numeric model parameter and returns it on exit. */ + +struct eval_num_info +{ /* working info used by the routine eval_member_num */ + PARAMETER *par; + /* model parameter */ + TUPLE *tuple; + /* n-tuple, which defines parameter member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + double value; + /* evaluated numeric value */ +}; + +static void eval_num_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_num_info *info = _info; + if (info->memb != NULL) + { /* checking call; check numeric value being assigned */ + check_value_num(mpl, info->par, info->memb->tuple, + info->memb->value.num); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->value = take_member_num(mpl, info->par, info->tuple); + } + return; +} + +double eval_member_num +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates numeric parameter member */ + struct eval_num_info _info, *info = &_info; + xassert(par->type == A_NUMERIC || par->type == A_INTEGER || + par->type == A_BINARY); + xassert(par->dim == tuple_dimen(mpl, tuple)); + info->par = par; + info->tuple = tuple; + if (par->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting conditions; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = par->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same parameter during the check */ + par->data = 2; + /* check values assigned to array members in the data section + until the marked member has been reached */ + for (info->memb = par->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, par->domain, info->memb->tuple, + info, eval_num_func)) + out_of_domain(mpl, par->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->par->domain, info->tuple, info, + eval_num_func)) + out_of_domain(mpl, par->name, info->tuple); + /* bring evaluated value to the calling program */ + return info->value; +} + +/*---------------------------------------------------------------------- +-- check_value_sym - check symbolic value assigned to parameter member. +-- +-- This routine checks if symbolic value being assigned to some member +-- of specified symbolic model parameter satisfies to all restrictions. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +void check_value_sym +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple, /* not changed */ + SYMBOL *value /* not changed */ +) +{ CONDITION *cond; + WITHIN *in; + int eqno; + /* the value must satisfy to all specified conditions */ + for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, + eqno++) + { SYMBOL *bound; + char buf[255+1]; + xassert(cond->code != NULL); + bound = eval_symbolic(mpl, cond->code); + switch (cond->rho) + { +#if 1 /* 13/VIII-2008 */ + case O_LT: + if (!(compare_symbols(mpl, value, bound) < 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not < %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + case O_LE: + if (!(compare_symbols(mpl, value, bound) <= 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not <= %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#endif + case O_EQ: + if (!(compare_symbols(mpl, value, bound) == 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not = %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#if 1 /* 13/VIII-2008 */ + case O_GE: + if (!(compare_symbols(mpl, value, bound) >= 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not >= %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + case O_GT: + if (!(compare_symbols(mpl, value, bound) > 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not > %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; +#endif + case O_NE: + if (!(compare_symbols(mpl, value, bound) != 0)) + { strcpy(buf, format_symbol(mpl, bound)); + xassert(strlen(buf) < sizeof(buf)); + error(mpl, "%s%s = %s not <> %s", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), buf, eqno); + } + break; + default: + xassert(cond != cond); + } + delete_symbol(mpl, bound); + } + /* the value must be in all specified supersets */ + for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) + { TUPLE *dummy; + xassert(in->code != NULL); + xassert(in->code->dim == 1); + dummy = expand_tuple(mpl, create_tuple(mpl), copy_symbol(mpl, + value)); + if (!is_member(mpl, in->code, dummy)) + error(mpl, "%s%s = %s not in specified set; see (%d)", + par->name, format_tuple(mpl, '[', tuple), + format_symbol(mpl, value), eqno); + delete_tuple(mpl, dummy); + } + return; +} + +/*---------------------------------------------------------------------- +-- take_member_sym - obtain symb. value assigned to parameter member. +-- +-- This routine obtains a symbolic value assigned to member of specified +-- symbolic model parameter and returns it on exit. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +SYMBOL *take_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + SYMBOL *value; + /* find member in the parameter array */ + memb = find_member(mpl, par->array, tuple); + if (memb != NULL) + { /* member exists, so just take its value */ + value = copy_symbol(mpl, memb->value.sym); + } + else if (par->assign != NULL) + { /* compute value using assignment expression */ + value = eval_symbolic(mpl, par->assign); +add: /* check that the value satisfies to all restrictions, assign + it to new member, and add the member to the array */ + check_value_sym(mpl, par, tuple, value); + memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); + memb->value.sym = copy_symbol(mpl, value); + } + else if (par->option != NULL) + { /* compute default value */ + value = eval_symbolic(mpl, par->option); + goto add; + } + else if (par->defval != NULL) + { /* take default value provided in the data section */ + value = copy_symbol(mpl, par->defval); + goto add; + } + else + { /* no value is provided */ + error(mpl, "no value for %s%s", par->name, format_tuple(mpl, + '[', tuple)); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_member_sym - evaluate symb. value assigned to parameter member. +-- +-- This routine evaluates a symbolic value assigned to given member of +-- specified symbolic model parameter and returns it on exit. */ + +struct eval_sym_info +{ /* working info used by the routine eval_member_sym */ + PARAMETER *par; + /* model parameter */ + TUPLE *tuple; + /* n-tuple, which defines parameter member */ + MEMBER *memb; + /* normally this pointer is NULL; the routine uses this pointer + to check data provided in the data section, in which case it + points to a member currently checked; this check is performed + automatically only once when a reference to any member occurs + for the first time */ + SYMBOL *value; + /* evaluated symbolic value */ +}; + +static void eval_sym_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_sym_info *info = _info; + if (info->memb != NULL) + { /* checking call; check symbolic value being assigned */ + check_value_sym(mpl, info->par, info->memb->tuple, + info->memb->value.sym); + } + else + { /* normal call; evaluate member, which has given n-tuple */ + info->value = take_member_sym(mpl, info->par, info->tuple); + } + return; +} + +SYMBOL *eval_member_sym /* returns value, not reference */ +( MPL *mpl, + PARAMETER *par, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates symbolic parameter member */ + struct eval_sym_info _info, *info = &_info; + xassert(par->type == A_SYMBOLIC); + xassert(par->dim == tuple_dimen(mpl, tuple)); + info->par = par; + info->tuple = tuple; + if (par->data == 1) + { /* check data, which are provided in the data section, but not + checked yet */ + /* save pointer to the last array member; note that during the + check new members may be added beyond the last member due to + references to the same parameter from default expression as + well as from expressions that define restricting conditions; + however, values assigned to the new members will be checked + by other routine, so we don't need to check them here */ + MEMBER *tail = par->array->tail; + /* change the data status to prevent infinite recursive loop + due to references to the same parameter during the check */ + par->data = 2; + /* check values assigned to array members in the data section + until the marked member has been reached */ + for (info->memb = par->array->head; info->memb != NULL; + info->memb = info->memb->next) + { if (eval_within_domain(mpl, par->domain, info->memb->tuple, + info, eval_sym_func)) + out_of_domain(mpl, par->name, info->memb->tuple); + if (info->memb == tail) break; + } + /* the check has been finished */ + } + /* evaluate member, which has given n-tuple */ + info->memb = NULL; + if (eval_within_domain(mpl, info->par->domain, info->tuple, info, + eval_sym_func)) + out_of_domain(mpl, par->name, info->tuple); + /* bring evaluated value to the calling program */ + return info->value; +} + +/*---------------------------------------------------------------------- +-- eval_whole_par - evaluate model parameter over entire domain. +-- +-- This routine evaluates all members of specified model parameter over +-- entire domain. */ + +static int whole_par_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + PARAMETER *par = (PARAMETER *)info; + TUPLE *tuple = get_domain_tuple(mpl, par->domain); + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + eval_member_num(mpl, par, tuple); + break; + case A_SYMBOLIC: + delete_symbol(mpl, eval_member_sym(mpl, par, tuple)); + break; + default: + xassert(par != par); + } + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_par(MPL *mpl, PARAMETER *par) +{ loop_within_domain(mpl, par->domain, par, whole_par_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_parameter - clean model parameter. +-- +-- This routine cleans specified model parameter that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_parameter(MPL *mpl, PARAMETER *par) +{ CONDITION *cond; + WITHIN *in; + MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, par->domain); + /* clean pseudo-code for computing restricting conditions */ + for (cond = par->cond; cond != NULL; cond = cond->next) + clean_code(mpl, cond->code); + /* clean pseudo-code for computing restricting supersets */ + for (in = par->in; in != NULL; in = in->next) + clean_code(mpl, in->code); + /* clean pseudo-code for computing assigned value */ + clean_code(mpl, par->assign); + /* clean pseudo-code for computing default value */ + clean_code(mpl, par->option); + /* reset data status flag */ + par->data = 0; + /* delete default symbolic value */ + if (par->defval != NULL) + delete_symbol(mpl, par->defval), par->defval = NULL; + /* delete content array */ + for (memb = par->array->head; memb != NULL; memb = memb->next) + delete_value(mpl, par->array->type, &memb->value); + delete_array(mpl, par->array), par->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL VARIABLES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- take_member_var - obtain reference to elemental variable. +-- +-- This routine obtains a reference to elemental variable assigned to +-- given member of specified model variable and returns it on exit. If +-- necessary, new elemental variable is created. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMVAR *take_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMVAR *refer; + /* find member in the variable array */ + memb = find_member(mpl, var->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.var; + } + else + { /* member is referenced for the first time and therefore does + not exist; create new elemental variable, assign it to new + member, and add the member to the variable array */ + memb = add_member(mpl, var->array, copy_tuple(mpl, tuple)); + refer = (memb->value.var = + dmp_get_atom(mpl->elemvars, sizeof(ELEMVAR))); + refer->j = 0; + refer->var = var; + refer->memb = memb; + /* compute lower bound */ + if (var->lbnd == NULL) + refer->lbnd = 0.0; + else + refer->lbnd = eval_numeric(mpl, var->lbnd); + /* compute upper bound */ + if (var->ubnd == NULL) + refer->ubnd = 0.0; + else if (var->ubnd == var->lbnd) + refer->ubnd = refer->lbnd; + else + refer->ubnd = eval_numeric(mpl, var->ubnd); + /* nullify working quantity */ + refer->temp = 0.0; +#if 1 /* 15/V-2010 */ + /* solution has not been obtained by the solver yet */ + refer->stat = 0; + refer->prim = refer->dual = 0.0; +#endif + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_var - evaluate reference to elemental variable. +-- +-- This routine evaluates a reference to elemental variable assigned to +-- member of specified model variable and returns it on exit. */ + +struct eval_var_info +{ /* working info used by the routine eval_member_var */ + VARIABLE *var; + /* model variable */ + TUPLE *tuple; + /* n-tuple, which defines variable member */ + ELEMVAR *refer; + /* evaluated reference to elemental variable */ +}; + +static void eval_var_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_var_info *info = _info; + info->refer = take_member_var(mpl, info->var, info->tuple); + return; +} + +ELEMVAR *eval_member_var /* returns reference */ +( MPL *mpl, + VARIABLE *var, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates variable member */ + struct eval_var_info _info, *info = &_info; + xassert(var->dim == tuple_dimen(mpl, tuple)); + info->var = var; + info->tuple = tuple; + /* evaluate member, which has given n-tuple */ + if (eval_within_domain(mpl, info->var->domain, info->tuple, info, + eval_var_func)) + out_of_domain(mpl, var->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_var - evaluate model variable over entire domain. +-- +-- This routine evaluates all members of specified model variable over +-- entire domain. */ + +static int whole_var_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + VARIABLE *var = (VARIABLE *)info; + TUPLE *tuple = get_domain_tuple(mpl, var->domain); + eval_member_var(mpl, var, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_var(MPL *mpl, VARIABLE *var) +{ loop_within_domain(mpl, var->domain, var, whole_var_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_variable - clean model variable. +-- +-- This routine cleans specified model variable that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_variable(MPL *mpl, VARIABLE *var) +{ MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, var->domain); + /* clean code for computing lower bound */ + clean_code(mpl, var->lbnd); + /* clean code for computing upper bound */ + if (var->ubnd != var->lbnd) clean_code(mpl, var->ubnd); + /* delete content array */ + for (memb = var->array->head; memb != NULL; memb = memb->next) + dmp_free_atom(mpl->elemvars, memb->value.var, sizeof(ELEMVAR)); + delete_array(mpl, var->array), var->array = NULL; + return; +} + +/**********************************************************************/ +/* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- take_member_con - obtain reference to elemental constraint. +-- +-- This routine obtains a reference to elemental constraint assigned +-- to given member of specified model constraint and returns it on exit. +-- If necessary, new elemental constraint is created. +-- +-- NOTE: This routine must not be called out of domain scope. */ + +ELEMCON *take_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ MEMBER *memb; + ELEMCON *refer; + /* find member in the constraint array */ + memb = find_member(mpl, con->array, tuple); + if (memb != NULL) + { /* member exists, so just take the reference */ + refer = memb->value.con; + } + else + { /* member is referenced for the first time and therefore does + not exist; create new elemental constraint, assign it to new + member, and add the member to the constraint array */ + memb = add_member(mpl, con->array, copy_tuple(mpl, tuple)); + refer = (memb->value.con = + dmp_get_atom(mpl->elemcons, sizeof(ELEMCON))); + refer->i = 0; + refer->con = con; + refer->memb = memb; + /* compute linear form */ + xassert(con->code != NULL); + refer->form = eval_formula(mpl, con->code); + /* compute lower and upper bounds */ + if (con->lbnd == NULL && con->ubnd == NULL) + { /* objective has no bounds */ + double temp; + xassert(con->type == A_MINIMIZE || con->type == A_MAXIMIZE); + /* carry the constant term to the right-hand side */ + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = refer->ubnd = - temp; + } + else if (con->lbnd != NULL && con->ubnd == NULL) + { /* constraint a * x + b >= c * y + d is transformed to the + standard form a * x - c * y >= d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->lbnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = - temp; + refer->ubnd = 0.0; + } + else if (con->lbnd == NULL && con->ubnd != NULL) + { /* constraint a * x + b <= c * y + d is transformed to the + standard form a * x - c * y <= d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->ubnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = 0.0; + refer->ubnd = - temp; + } + else if (con->lbnd == con->ubnd) + { /* constraint a * x + b = c * y + d is transformed to the + standard form a * x - c * y = d - b */ + double temp; + xassert(con->type == A_CONSTRAINT); + refer->form = linear_comb(mpl, + +1.0, refer->form, + -1.0, eval_formula(mpl, con->lbnd)); + refer->form = remove_constant(mpl, refer->form, &temp); + refer->lbnd = refer->ubnd = - temp; + } + else + { /* ranged constraint c <= a * x + b <= d is transformed to + the standard form c - b <= a * x <= d - b */ + double temp, temp1, temp2; + xassert(con->type == A_CONSTRAINT); + refer->form = remove_constant(mpl, refer->form, &temp); + xassert(remove_constant(mpl, eval_formula(mpl, con->lbnd), + &temp1) == NULL); + xassert(remove_constant(mpl, eval_formula(mpl, con->ubnd), + &temp2) == NULL); + refer->lbnd = fp_sub(mpl, temp1, temp); + refer->ubnd = fp_sub(mpl, temp2, temp); + } +#if 1 /* 15/V-2010 */ + /* solution has not been obtained by the solver yet */ + refer->stat = 0; + refer->prim = refer->dual = 0.0; +#endif + } + return refer; +} + +/*---------------------------------------------------------------------- +-- eval_member_con - evaluate reference to elemental constraint. +-- +-- This routine evaluates a reference to elemental constraint assigned +-- to member of specified model constraint and returns it on exit. */ + +struct eval_con_info +{ /* working info used by the routine eval_member_con */ + CONSTRAINT *con; + /* model constraint */ + TUPLE *tuple; + /* n-tuple, which defines constraint member */ + ELEMCON *refer; + /* evaluated reference to elemental constraint */ +}; + +static void eval_con_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine to work within domain scope */ + struct eval_con_info *info = _info; + info->refer = take_member_con(mpl, info->con, info->tuple); + return; +} + +ELEMCON *eval_member_con /* returns reference */ +( MPL *mpl, + CONSTRAINT *con, /* not changed */ + TUPLE *tuple /* not changed */ +) +{ /* this routine evaluates constraint member */ + struct eval_con_info _info, *info = &_info; + xassert(con->dim == tuple_dimen(mpl, tuple)); + info->con = con; + info->tuple = tuple; + /* evaluate member, which has given n-tuple */ + if (eval_within_domain(mpl, info->con->domain, info->tuple, info, + eval_con_func)) + out_of_domain(mpl, con->name, info->tuple); + /* bring evaluated reference to the calling program */ + return info->refer; +} + +/*---------------------------------------------------------------------- +-- eval_whole_con - evaluate model constraint over entire domain. +-- +-- This routine evaluates all members of specified model constraint over +-- entire domain. */ + +static int whole_con_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + CONSTRAINT *con = (CONSTRAINT *)info; + TUPLE *tuple = get_domain_tuple(mpl, con->domain); + eval_member_con(mpl, con, tuple); + delete_tuple(mpl, tuple); + return 0; +} + +void eval_whole_con(MPL *mpl, CONSTRAINT *con) +{ loop_within_domain(mpl, con->domain, con, whole_con_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_constraint - clean model constraint. +-- +-- This routine cleans specified model constraint that assumes deleting +-- all stuff dynamically allocated during the generation phase. */ + +void clean_constraint(MPL *mpl, CONSTRAINT *con) +{ MEMBER *memb; + /* clean subscript domain */ + clean_domain(mpl, con->domain); + /* clean code for computing main linear form */ + clean_code(mpl, con->code); + /* clean code for computing lower bound */ + clean_code(mpl, con->lbnd); + /* clean code for computing upper bound */ + if (con->ubnd != con->lbnd) clean_code(mpl, con->ubnd); + /* delete content array */ + for (memb = con->array->head; memb != NULL; memb = memb->next) + { delete_formula(mpl, memb->value.con->form); + dmp_free_atom(mpl->elemcons, memb->value.con, sizeof(ELEMCON)); + } + delete_array(mpl, con->array), con->array = NULL; + return; +} + +/**********************************************************************/ +/* * * PSEUDO-CODE * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- eval_numeric - evaluate pseudo-code to determine numeric value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- numeric value, which is returned on exit. */ + +struct iter_num_info +{ /* working info used by the routine iter_num_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + double value; + /* resultant value */ +}; + +static int iter_num_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on numeric "integrand" within domain scope */ + struct iter_num_info *info = _info; + double temp; + temp = eval_numeric(mpl, info->code->arg.loop.x); + switch (info->code->op) + { case O_SUM: + /* summation over domain */ + info->value = fp_add(mpl, info->value, temp); + break; + case O_PROD: + /* multiplication over domain */ + info->value = fp_mul(mpl, info->value, temp); + break; + case O_MINIMUM: + /* minimum over domain */ + if (info->value > temp) info->value = temp; + break; + case O_MAXIMUM: + /* maximum over domain */ + if (info->value < temp) info->value = temp; + break; + default: + xassert(info != info); + } + return 0; +} + +double eval_numeric(MPL *mpl, CODE *code) +{ double value; + xassert(code != NULL); + xassert(code->type == A_NUMERIC); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = code->value.num; + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_NUMBER: + /* take floating-point number */ + value = code->arg.num; + break; + case O_MEMNUM: + /* take member of numeric parameter */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = eval_member_num(mpl, code->arg.par.par, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_MEMVAR: + /* take computed value of elemental variable */ + { TUPLE *tuple; + ARG_LIST *e; +#if 1 /* 15/V-2010 */ + ELEMVAR *var; +#endif + tuple = create_tuple(mpl); + for (e = code->arg.var.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); +#if 0 /* 15/V-2010 */ + value = eval_member_var(mpl, code->arg.var.var, tuple) + ->value; +#else + var = eval_member_var(mpl, code->arg.var.var, tuple); + switch (code->arg.var.suff) + { case DOT_LB: + if (var->var->lbnd == NULL) + value = -DBL_MAX; + else + value = var->lbnd; + break; + case DOT_UB: + if (var->var->ubnd == NULL) + value = +DBL_MAX; + else + value = var->ubnd; + break; + case DOT_STATUS: + value = var->stat; + break; + case DOT_VAL: + value = var->prim; + break; + case DOT_DUAL: + value = var->dual; + break; + default: + xassert(code != code); + } +#endif + delete_tuple(mpl, tuple); + } + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + /* take computed value of elemental constraint */ + { TUPLE *tuple; + ARG_LIST *e; + ELEMCON *con; + tuple = create_tuple(mpl); + for (e = code->arg.con.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + con = eval_member_con(mpl, code->arg.con.con, tuple); + switch (code->arg.con.suff) + { case DOT_LB: + if (con->con->lbnd == NULL) + value = -DBL_MAX; + else + value = con->lbnd; + break; + case DOT_UB: + if (con->con->ubnd == NULL) + value = +DBL_MAX; + else + value = con->ubnd; + break; + case DOT_STATUS: + value = con->stat; + break; + case DOT_VAL: + value = con->prim; + break; + case DOT_DUAL: + value = con->dual; + break; + default: + xassert(code != code); + } + delete_tuple(mpl, tuple); + } + break; +#endif + case O_IRAND224: + /* pseudo-random in [0, 2^24-1] */ + value = fp_irand224(mpl); + break; + case O_UNIFORM01: + /* pseudo-random in [0, 1) */ + value = fp_uniform01(mpl); + break; + case O_NORMAL01: + /* gaussian random, mu = 0, sigma = 1 */ + value = fp_normal01(mpl); + break; + case O_GMTIME: + /* current calendar time */ + value = fn_gmtime(mpl); + break; + case O_CVTNUM: + /* conversion to numeric */ + { SYMBOL *sym; + sym = eval_symbolic(mpl, code->arg.arg.x); +#if 0 /* 23/XI-2008 */ + if (sym->str != NULL) + error(mpl, "cannot convert %s to floating-point numbe" + "r", format_symbol(mpl, sym)); + value = sym->num; +#else + if (sym->str == NULL) + value = sym->num; + else + { if (str2num(sym->str, &value)) + error(mpl, "cannot convert %s to floating-point nu" + "mber", format_symbol(mpl, sym)); + } +#endif + delete_symbol(mpl, sym); + } + break; + case O_PLUS: + /* unary plus */ + value = + eval_numeric(mpl, code->arg.arg.x); + break; + case O_MINUS: + /* unary minus */ + value = - eval_numeric(mpl, code->arg.arg.x); + break; + case O_ABS: + /* absolute value */ + value = fabs(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_CEIL: + /* round upward ("ceiling of x") */ + value = ceil(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_FLOOR: + /* round downward ("floor of x") */ + value = floor(eval_numeric(mpl, code->arg.arg.x)); + break; + case O_EXP: + /* base-e exponential */ + value = fp_exp(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_LOG: + /* natural logarithm */ + value = fp_log(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_LOG10: + /* common (decimal) logarithm */ + value = fp_log10(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_SQRT: + /* square root */ + value = fp_sqrt(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_SIN: + /* trigonometric sine */ + value = fp_sin(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_COS: + /* trigonometric cosine */ + value = fp_cos(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_TAN: + /* trigonometric tangent */ + value = fp_tan(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_ATAN: + /* trigonometric arctangent (one argument) */ + value = fp_atan(mpl, eval_numeric(mpl, code->arg.arg.x)); + break; + case O_ATAN2: + /* trigonometric arctangent (two arguments) */ + value = fp_atan2(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_ROUND: + /* round to nearest integer */ + value = fp_round(mpl, + eval_numeric(mpl, code->arg.arg.x), 0.0); + break; + case O_ROUND2: + /* round to n fractional digits */ + value = fp_round(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_TRUNC: + /* truncate to nearest integer */ + value = fp_trunc(mpl, + eval_numeric(mpl, code->arg.arg.x), 0.0); + break; + case O_TRUNC2: + /* truncate to n fractional digits */ + value = fp_trunc(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_ADD: + /* addition */ + value = fp_add(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_SUB: + /* subtraction */ + value = fp_sub(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_LESS: + /* non-negative subtraction */ + value = fp_less(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_MUL: + /* multiplication */ + value = fp_mul(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_DIV: + /* division */ + value = fp_div(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_IDIV: + /* quotient of exact division */ + value = fp_idiv(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_MOD: + /* remainder of exact division */ + value = fp_mod(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_POWER: + /* exponentiation (raise to power) */ + value = fp_power(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_UNIFORM: + /* pseudo-random in [a, b) */ + value = fp_uniform(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_NORMAL: + /* gaussian random, given mu and sigma */ + value = fp_normal(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y)); + break; + case O_CARD: + { ELEMSET *set; + set = eval_elemset(mpl, code->arg.arg.x); + value = set->size; + delete_array(mpl, set); + } + break; + case O_LENGTH: + { SYMBOL *sym; + char str[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, code->arg.arg.x); + if (sym->str == NULL) + sprintf(str, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, str); + delete_symbol(mpl, sym); + value = strlen(str); + } + break; + case O_STR2TIME: + { SYMBOL *sym; + char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, code->arg.arg.x); + if (sym->str == NULL) + sprintf(str, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, str); + delete_symbol(mpl, sym); + sym = eval_symbolic(mpl, code->arg.arg.y); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + value = fn_str2time(mpl, str, fmt); + } + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_numeric(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = 0.0; + else + value = eval_numeric(mpl, code->arg.arg.z); + break; + case O_MIN: + /* minimal value (n-ary) */ + { ARG_LIST *e; + double temp; + value = +DBL_MAX; + for (e = code->arg.list; e != NULL; e = e->next) + { temp = eval_numeric(mpl, e->x); + if (value > temp) value = temp; + } + } + break; + case O_MAX: + /* maximal value (n-ary) */ + { ARG_LIST *e; + double temp; + value = -DBL_MAX; + for (e = code->arg.list; e != NULL; e = e->next) + { temp = eval_numeric(mpl, e->x); + if (value < temp) value = temp; + } + } + break; + case O_SUM: + /* summation over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = 0.0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + value = info->value; + } + break; + case O_PROD: + /* multiplication over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = 1.0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + value = info->value; + } + break; + case O_MINIMUM: + /* minimum over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = +DBL_MAX; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + if (info->value == +DBL_MAX) + error(mpl, "min{} over empty set; result undefined"); + value = info->value; + } + break; + case O_MAXIMUM: + /* maximum over domain */ + { struct iter_num_info _info, *info = &_info; + info->code = code; + info->value = -DBL_MAX; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_num_func); + if (info->value == -DBL_MAX) + error(mpl, "max{} over empty set; result undefined"); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.num = value; +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_symbolic - evaluate pseudo-code to determine symbolic value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- symbolic value, which is returned on exit. */ + +SYMBOL *eval_symbolic(MPL *mpl, CODE *code) +{ SYMBOL *value; + xassert(code != NULL); + xassert(code->type == A_SYMBOLIC); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_symbol(mpl, code->value.sym); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_STRING: + /* take character string */ + value = create_symbol_str(mpl, create_string(mpl, + code->arg.str)); + break; + case O_INDEX: + /* take dummy index */ + xassert(code->arg.index.slot->value != NULL); + value = copy_symbol(mpl, code->arg.index.slot->value); + break; + case O_MEMSYM: + /* take member of symbolic parameter */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = eval_member_sym(mpl, code->arg.par.par, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_CVTSYM: + /* conversion to symbolic */ + value = create_symbol_num(mpl, eval_numeric(mpl, + code->arg.arg.x)); + break; + case O_CONCAT: + /* concatenation */ + value = concat_symbols(mpl, + eval_symbolic(mpl, code->arg.arg.x), + eval_symbolic(mpl, code->arg.arg.y)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_symbolic(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = create_symbol_num(mpl, 0.0); + else + value = eval_symbolic(mpl, code->arg.arg.z); + break; + case O_SUBSTR: + case O_SUBSTR3: + { double pos, len; + char str[MAX_LENGTH+1]; + value = eval_symbolic(mpl, code->arg.arg.x); + if (value->str == NULL) + sprintf(str, "%.*g", DBL_DIG, value->num); + else + fetch_string(mpl, value->str, str); + delete_symbol(mpl, value); + if (code->op == O_SUBSTR) + { pos = eval_numeric(mpl, code->arg.arg.y); + if (pos != floor(pos)) + error(mpl, "substr('...', %.*g); non-integer secon" + "d argument", DBL_DIG, pos); + if (pos < 1 || pos > strlen(str) + 1) + error(mpl, "substr('...', %.*g); substring out of " + "range", DBL_DIG, pos); + } + else + { pos = eval_numeric(mpl, code->arg.arg.y); + len = eval_numeric(mpl, code->arg.arg.z); + if (pos != floor(pos) || len != floor(len)) + error(mpl, "substr('...', %.*g, %.*g); non-integer" + " second and/or third argument", DBL_DIG, pos, + DBL_DIG, len); + if (pos < 1 || len < 0 || pos + len > strlen(str) + 1) + error(mpl, "substr('...', %.*g, %.*g); substring o" + "ut of range", DBL_DIG, pos, DBL_DIG, len); + str[(int)pos + (int)len - 1] = '\0'; + } + value = create_symbol_str(mpl, create_string(mpl, str + + (int)pos - 1)); + } + break; + case O_TIME2STR: + { double num; + SYMBOL *sym; + char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; + num = eval_numeric(mpl, code->arg.arg.x); + sym = eval_symbolic(mpl, code->arg.arg.y); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + fn_time2str(mpl, str, num, fmt); + value = create_symbol_str(mpl, create_string(mpl, str)); + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.sym = copy_symbol(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_logical - evaluate pseudo-code to determine logical value. +-- +-- This routine evaluates specified pseudo-code to determine resultant +-- logical value, which is returned on exit. */ + +struct iter_log_info +{ /* working info used by the routine iter_log_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + int value; + /* resultant value */ +}; + +static int iter_log_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on logical "integrand" within domain scope */ + struct iter_log_info *info = _info; + int ret = 0; + switch (info->code->op) + { case O_FORALL: + /* conjunction over domain */ + info->value &= eval_logical(mpl, info->code->arg.loop.x); + if (!info->value) ret = 1; + break; + case O_EXISTS: + /* disjunction over domain */ + info->value |= eval_logical(mpl, info->code->arg.loop.x); + if (info->value) ret = 1; + break; + default: + xassert(info != info); + } + return ret; +} + +int eval_logical(MPL *mpl, CODE *code) +{ int value; + xassert(code->type == A_LOGICAL); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = code->value.bit; + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_CVTLOG: + /* conversion to logical */ + value = (eval_numeric(mpl, code->arg.arg.x) != 0.0); + break; + case O_NOT: + /* negation (logical "not") */ + value = !eval_logical(mpl, code->arg.arg.x); + break; + case O_LT: + /* comparison on 'less than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) < + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) < + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) < 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_LE: + /* comparison on 'not greater than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) <= + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) <= + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) <= 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_EQ: + /* comparison on 'equal to' */ + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) == + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) == 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } + break; + case O_GE: + /* comparison on 'not less than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) >= + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) >= + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) >= 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_GT: + /* comparison on 'greater than' */ +#if 0 /* 02/VIII-2008 */ + value = (eval_numeric(mpl, code->arg.arg.x) > + eval_numeric(mpl, code->arg.arg.y)); +#else + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) > + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) > 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } +#endif + break; + case O_NE: + /* comparison on 'not equal to' */ + xassert(code->arg.arg.x != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + value = (eval_numeric(mpl, code->arg.arg.x) != + eval_numeric(mpl, code->arg.arg.y)); + else + { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); + SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); + value = (compare_symbols(mpl, sym1, sym2) != 0); + delete_symbol(mpl, sym1); + delete_symbol(mpl, sym2); + } + break; + case O_AND: + /* conjunction (logical "and") */ + value = eval_logical(mpl, code->arg.arg.x) && + eval_logical(mpl, code->arg.arg.y); + break; + case O_OR: + /* disjunction (logical "or") */ + value = eval_logical(mpl, code->arg.arg.x) || + eval_logical(mpl, code->arg.arg.y); + break; + case O_IN: + /* test on 'x in Y' */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code->arg.arg.x); + value = is_member(mpl, code->arg.arg.y, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_NOTIN: + /* test on 'x not in Y' */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code->arg.arg.x); + value = !is_member(mpl, code->arg.arg.y, tuple); + delete_tuple(mpl, tuple); + } + break; + case O_WITHIN: + /* test on 'X within Y' */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code->arg.arg.x); + value = 1; + for (memb = set->head; memb != NULL; memb = memb->next) + { if (!is_member(mpl, code->arg.arg.y, memb->tuple)) + { value = 0; + break; + } + } + delete_elemset(mpl, set); + } + break; + case O_NOTWITHIN: + /* test on 'X not within Y' */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code->arg.arg.x); + value = 1; + for (memb = set->head; memb != NULL; memb = memb->next) + { if (is_member(mpl, code->arg.arg.y, memb->tuple)) + { value = 0; + break; + } + } + delete_elemset(mpl, set); + } + break; + case O_FORALL: + /* conjunction (A-quantification) */ + { struct iter_log_info _info, *info = &_info; + info->code = code; + info->value = 1; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_log_func); + value = info->value; + } + break; + case O_EXISTS: + /* disjunction (E-quantification) */ + { struct iter_log_info _info, *info = &_info; + info->code = code; + info->value = 0; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_log_func); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.bit = value; +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_tuple - evaluate pseudo-code to construct n-tuple. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- n-tuple, which is returned on exit. */ + +TUPLE *eval_tuple(MPL *mpl, CODE *code) +{ TUPLE *value; + xassert(code != NULL); + xassert(code->type == A_TUPLE); + xassert(code->dim > 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_tuple(mpl, code->value.tuple); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_TUPLE: + /* make n-tuple */ + { ARG_LIST *e; + value = create_tuple(mpl); + for (e = code->arg.list; e != NULL; e = e->next) + value = expand_tuple(mpl, value, eval_symbolic(mpl, + e->x)); + } + break; + case O_CVTTUP: + /* convert to 1-tuple */ + value = expand_tuple(mpl, create_tuple(mpl), + eval_symbolic(mpl, code->arg.arg.x)); + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.tuple = copy_tuple(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- eval_elemset - evaluate pseudo-code to construct elemental set. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- elemental set, which is returned on exit. */ + +struct iter_set_info +{ /* working info used by the routine iter_set_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + ELEMSET *value; + /* resultant value */ +}; + +static int iter_set_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on n-tuple "integrand" within domain scope */ + struct iter_set_info *info = _info; + TUPLE *tuple; + switch (info->code->op) + { case O_SETOF: + /* compute next n-tuple and add it to the set; in this case + duplicate n-tuples are silently ignored */ + tuple = eval_tuple(mpl, info->code->arg.loop.x); + if (find_tuple(mpl, info->value, tuple) == NULL) + add_tuple(mpl, info->value, tuple); + else + delete_tuple(mpl, tuple); + break; + case O_BUILD: + /* construct next n-tuple using current values assigned to + *free* dummy indices as its components and add it to the + set; in this case duplicate n-tuples cannot appear */ + add_tuple(mpl, info->value, get_domain_tuple(mpl, + info->code->arg.loop.domain)); + break; + default: + xassert(info != info); + } + return 0; +} + +ELEMSET *eval_elemset(MPL *mpl, CODE *code) +{ ELEMSET *value; + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_elemset(mpl, code->value.set); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_MEMSET: + /* take member of set */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.set.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); + value = copy_elemset(mpl, + eval_member_set(mpl, code->arg.set.set, tuple)); + delete_tuple(mpl, tuple); + } + break; + case O_MAKE: + /* make elemental set of n-tuples */ + { ARG_LIST *e; + value = create_elemset(mpl, code->dim); + for (e = code->arg.list; e != NULL; e = e->next) + check_then_add(mpl, value, eval_tuple(mpl, e->x)); + } + break; + case O_UNION: + /* union of two elemental sets */ + value = set_union(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_DIFF: + /* difference between two elemental sets */ + value = set_diff(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_SYMDIFF: + /* symmetric difference between two elemental sets */ + value = set_symdiff(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_INTER: + /* intersection of two elemental sets */ + value = set_inter(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_CROSS: + /* cross (Cartesian) product of two elemental sets */ + value = set_cross(mpl, + eval_elemset(mpl, code->arg.arg.x), + eval_elemset(mpl, code->arg.arg.y)); + break; + case O_DOTS: + /* build "arithmetic" elemental set */ + value = create_arelset(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_numeric(mpl, code->arg.arg.y), + code->arg.arg.z == NULL ? 1.0 : eval_numeric(mpl, + code->arg.arg.z)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_elemset(mpl, code->arg.arg.y); + else + value = eval_elemset(mpl, code->arg.arg.z); + break; + case O_SETOF: + /* compute elemental set */ + { struct iter_set_info _info, *info = &_info; + info->code = code; + info->value = create_elemset(mpl, code->dim); + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_set_func); + value = info->value; + } + break; + case O_BUILD: + /* build elemental set identical to domain set */ + { struct iter_set_info _info, *info = &_info; + info->code = code; + info->value = create_elemset(mpl, code->dim); + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_set_func); + value = info->value; + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.set = copy_elemset(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- is_member - check if n-tuple is in set specified by pseudo-code. +-- +-- This routine checks if given n-tuple is a member of elemental set +-- specified in the form of pseudo-code (i.e. by expression). +-- +-- The n-tuple may have more components that dimension of the elemental +-- set, in which case the extra components are ignored. */ + +static void null_func(MPL *mpl, void *info) +{ /* this is dummy routine used to enter the domain scope */ + xassert(mpl == mpl); + xassert(info == NULL); + return; +} + +int is_member(MPL *mpl, CODE *code, TUPLE *tuple) +{ int value; + xassert(code != NULL); + xassert(code->type == A_ELEMSET); + xassert(code->dim > 0); + xassert(tuple != NULL); + switch (code->op) + { case O_MEMSET: + /* check if given n-tuple is member of elemental set, which + is assigned to member of model set */ + { ARG_LIST *e; + TUPLE *temp; + ELEMSET *set; + /* evaluate reference to elemental set */ + temp = create_tuple(mpl); + for (e = code->arg.set.list; e != NULL; e = e->next) + temp = expand_tuple(mpl, temp, eval_symbolic(mpl, + e->x)); + set = eval_member_set(mpl, code->arg.set.set, temp); + delete_tuple(mpl, temp); + /* check if the n-tuple is contained in the set array */ + temp = build_subtuple(mpl, tuple, set->dim); + value = (find_tuple(mpl, set, temp) != NULL); + delete_tuple(mpl, temp); + } + break; + case O_MAKE: + /* check if given n-tuple is member of literal set */ + { ARG_LIST *e; + TUPLE *temp, *that; + value = 0; + temp = build_subtuple(mpl, tuple, code->dim); + for (e = code->arg.list; e != NULL; e = e->next) + { that = eval_tuple(mpl, e->x); + value = (compare_tuples(mpl, temp, that) == 0); + delete_tuple(mpl, that); + if (value) break; + } + delete_tuple(mpl, temp); + } + break; + case O_UNION: + value = is_member(mpl, code->arg.arg.x, tuple) || + is_member(mpl, code->arg.arg.y, tuple); + break; + case O_DIFF: + value = is_member(mpl, code->arg.arg.x, tuple) && + !is_member(mpl, code->arg.arg.y, tuple); + break; + case O_SYMDIFF: + { int in1 = is_member(mpl, code->arg.arg.x, tuple); + int in2 = is_member(mpl, code->arg.arg.y, tuple); + value = (in1 && !in2) || (!in1 && in2); + } + break; + case O_INTER: + value = is_member(mpl, code->arg.arg.x, tuple) && + is_member(mpl, code->arg.arg.y, tuple); + break; + case O_CROSS: + { int j; + value = is_member(mpl, code->arg.arg.x, tuple); + if (value) + { for (j = 1; j <= code->arg.arg.x->dim; j++) + { xassert(tuple != NULL); + tuple = tuple->next; + } + value = is_member(mpl, code->arg.arg.y, tuple); + } + } + break; + case O_DOTS: + /* check if given 1-tuple is member of "arithmetic" set */ + { int j; + double x, t0, tf, dt; + xassert(code->dim == 1); + /* compute "parameters" of the "arithmetic" set */ + t0 = eval_numeric(mpl, code->arg.arg.x); + tf = eval_numeric(mpl, code->arg.arg.y); + if (code->arg.arg.z == NULL) + dt = 1.0; + else + dt = eval_numeric(mpl, code->arg.arg.z); + /* make sure the parameters are correct */ + arelset_size(mpl, t0, tf, dt); + /* if component of 1-tuple is symbolic, not numeric, the + 1-tuple cannot be member of "arithmetic" set */ + xassert(tuple->sym != NULL); + if (tuple->sym->str != NULL) + { value = 0; + break; + } + /* determine numeric value of the component */ + x = tuple->sym->num; + /* if the component value is out of the set range, the + 1-tuple is not in the set */ + if (dt > 0.0 && !(t0 <= x && x <= tf) || + dt < 0.0 && !(tf <= x && x <= t0)) + { value = 0; + break; + } + /* estimate ordinal number of the 1-tuple in the set */ + j = (int)(((x - t0) / dt) + 0.5) + 1; + /* perform the main check */ + value = (arelset_member(mpl, t0, tf, dt, j) == x); + } + break; + case O_FORK: + /* check if given n-tuple is member of conditional set */ + if (eval_logical(mpl, code->arg.arg.x)) + value = is_member(mpl, code->arg.arg.y, tuple); + else + value = is_member(mpl, code->arg.arg.z, tuple); + break; + case O_SETOF: + /* check if given n-tuple is member of computed set */ + /* it is not clear how to efficiently perform the check not + computing the entire elemental set :+( */ + error(mpl, "implementation restriction; in/within setof{} n" + "ot allowed"); + break; + case O_BUILD: + /* check if given n-tuple is member of domain set */ + { TUPLE *temp; + temp = build_subtuple(mpl, tuple, code->dim); + /* try to enter the domain scope; if it is successful, + the n-tuple is in the domain set */ + value = (eval_within_domain(mpl, code->arg.loop.domain, + temp, NULL, null_func) == 0); + delete_tuple(mpl, temp); + } + break; + default: + xassert(code != code); + } + return value; +} + +/*---------------------------------------------------------------------- +-- eval_formula - evaluate pseudo-code to construct linear form. +-- +-- This routine evaluates specified pseudo-code to construct resultant +-- linear form, which is returned on exit. */ + +struct iter_form_info +{ /* working info used by the routine iter_form_func */ + CODE *code; + /* pseudo-code for iterated operation to be performed */ + FORMULA *value; + /* resultant value */ + FORMULA *tail; + /* pointer to the last term */ +}; + +static int iter_form_func(MPL *mpl, void *_info) +{ /* this is auxiliary routine used to perform iterated operation + on linear form "integrand" within domain scope */ + struct iter_form_info *info = _info; + switch (info->code->op) + { case O_SUM: + /* summation over domain */ +#if 0 + info->value = + linear_comb(mpl, + +1.0, info->value, + +1.0, eval_formula(mpl, info->code->arg.loop.x)); +#else + /* the routine linear_comb needs to look through all terms + of both linear forms to reduce identical terms, so using + it here is not a good idea (for example, evaluation of + sum{i in 1..n} x[i] required quadratic time); the better + idea is to gather all terms of the integrand in one list + and reduce identical terms only once after all terms of + the resultant linear form have been evaluated */ + { FORMULA *form, *term; + form = eval_formula(mpl, info->code->arg.loop.x); + if (info->value == NULL) + { xassert(info->tail == NULL); + info->value = form; + } + else + { xassert(info->tail != NULL); + info->tail->next = form; + } + for (term = form; term != NULL; term = term->next) + info->tail = term; + } +#endif + break; + default: + xassert(info != info); + } + return 0; +} + +FORMULA *eval_formula(MPL *mpl, CODE *code) +{ FORMULA *value; + xassert(code != NULL); + xassert(code->type == A_FORMULA); + xassert(code->dim == 0); + /* if the operation has a side effect, invalidate and delete the + resultant value */ + if (code->vflag && code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* if resultant value is valid, no evaluation is needed */ + if (code->valid) + { value = copy_formula(mpl, code->value.form); + goto done; + } + /* evaluate pseudo-code recursively */ + switch (code->op) + { case O_MEMVAR: + /* take member of variable */ + { TUPLE *tuple; + ARG_LIST *e; + tuple = create_tuple(mpl); + for (e = code->arg.var.list; e != NULL; e = e->next) + tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, + e->x)); +#if 1 /* 15/V-2010 */ + xassert(code->arg.var.suff == DOT_NONE); +#endif + value = single_variable(mpl, + eval_member_var(mpl, code->arg.var.var, tuple)); + delete_tuple(mpl, tuple); + } + break; + case O_CVTLFM: + /* convert to linear form */ + value = constant_term(mpl, eval_numeric(mpl, + code->arg.arg.x)); + break; + case O_PLUS: + /* unary plus */ + value = linear_comb(mpl, + 0.0, constant_term(mpl, 0.0), + +1.0, eval_formula(mpl, code->arg.arg.x)); + break; + case O_MINUS: + /* unary minus */ + value = linear_comb(mpl, + 0.0, constant_term(mpl, 0.0), + -1.0, eval_formula(mpl, code->arg.arg.x)); + break; + case O_ADD: + /* addition */ + value = linear_comb(mpl, + +1.0, eval_formula(mpl, code->arg.arg.x), + +1.0, eval_formula(mpl, code->arg.arg.y)); + break; + case O_SUB: + /* subtraction */ + value = linear_comb(mpl, + +1.0, eval_formula(mpl, code->arg.arg.x), + -1.0, eval_formula(mpl, code->arg.arg.y)); + break; + case O_MUL: + /* multiplication */ + xassert(code->arg.arg.x != NULL); + xassert(code->arg.arg.y != NULL); + if (code->arg.arg.x->type == A_NUMERIC) + { xassert(code->arg.arg.y->type == A_FORMULA); + value = linear_comb(mpl, + eval_numeric(mpl, code->arg.arg.x), + eval_formula(mpl, code->arg.arg.y), + 0.0, constant_term(mpl, 0.0)); + } + else + { xassert(code->arg.arg.x->type == A_FORMULA); + xassert(code->arg.arg.y->type == A_NUMERIC); + value = linear_comb(mpl, + eval_numeric(mpl, code->arg.arg.y), + eval_formula(mpl, code->arg.arg.x), + 0.0, constant_term(mpl, 0.0)); + } + break; + case O_DIV: + /* division */ + value = linear_comb(mpl, + fp_div(mpl, 1.0, eval_numeric(mpl, code->arg.arg.y)), + eval_formula(mpl, code->arg.arg.x), + 0.0, constant_term(mpl, 0.0)); + break; + case O_FORK: + /* if-then-else */ + if (eval_logical(mpl, code->arg.arg.x)) + value = eval_formula(mpl, code->arg.arg.y); + else if (code->arg.arg.z == NULL) + value = constant_term(mpl, 0.0); + else + value = eval_formula(mpl, code->arg.arg.z); + break; + case O_SUM: + /* summation over domain */ + { struct iter_form_info _info, *info = &_info; + info->code = code; + info->value = constant_term(mpl, 0.0); + info->tail = NULL; + loop_within_domain(mpl, code->arg.loop.domain, info, + iter_form_func); + value = reduce_terms(mpl, info->value); + } + break; + default: + xassert(code != code); + } + /* save resultant value */ + xassert(!code->valid); + code->valid = 1; + code->value.form = copy_formula(mpl, value); +done: return value; +} + +/*---------------------------------------------------------------------- +-- clean_code - clean pseudo-code. +-- +-- This routine recursively cleans specified pseudo-code that assumes +-- deleting all temporary resultant values. */ + +void clean_code(MPL *mpl, CODE *code) +{ ARG_LIST *e; + /* if no pseudo-code is specified, do nothing */ + if (code == NULL) goto done; + /* if resultant value is valid (exists), delete it */ + if (code->valid) + { code->valid = 0; + delete_value(mpl, code->type, &code->value); + } + /* recursively clean pseudo-code for operands */ + switch (code->op) + { case O_NUMBER: + case O_STRING: + case O_INDEX: + break; + case O_MEMNUM: + case O_MEMSYM: + for (e = code->arg.par.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_MEMSET: + for (e = code->arg.set.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_MEMVAR: + for (e = code->arg.var.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; +#if 1 /* 15/V-2010 */ + case O_MEMCON: + for (e = code->arg.con.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; +#endif + case O_TUPLE: + case O_MAKE: + for (e = code->arg.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_SLICE: + xassert(code != code); + case O_IRAND224: + case O_UNIFORM01: + case O_NORMAL01: + case O_GMTIME: + break; + case O_CVTNUM: + case O_CVTSYM: + case O_CVTLOG: + case O_CVTTUP: + case O_CVTLFM: + case O_PLUS: + case O_MINUS: + case O_NOT: + case O_ABS: + case O_CEIL: + case O_FLOOR: + case O_EXP: + case O_LOG: + case O_LOG10: + case O_SQRT: + case O_SIN: + case O_COS: + case O_TAN: + case O_ATAN: + case O_ROUND: + case O_TRUNC: + case O_CARD: + case O_LENGTH: + /* unary operation */ + clean_code(mpl, code->arg.arg.x); + break; + case O_ADD: + case O_SUB: + case O_LESS: + case O_MUL: + case O_DIV: + case O_IDIV: + case O_MOD: + case O_POWER: + case O_ATAN2: + case O_ROUND2: + case O_TRUNC2: + case O_UNIFORM: + case O_NORMAL: + case O_CONCAT: + case O_LT: + case O_LE: + case O_EQ: + case O_GE: + case O_GT: + case O_NE: + case O_AND: + case O_OR: + case O_UNION: + case O_DIFF: + case O_SYMDIFF: + case O_INTER: + case O_CROSS: + case O_IN: + case O_NOTIN: + case O_WITHIN: + case O_NOTWITHIN: + case O_SUBSTR: + case O_STR2TIME: + case O_TIME2STR: + /* binary operation */ + clean_code(mpl, code->arg.arg.x); + clean_code(mpl, code->arg.arg.y); + break; + case O_DOTS: + case O_FORK: + case O_SUBSTR3: + /* ternary operation */ + clean_code(mpl, code->arg.arg.x); + clean_code(mpl, code->arg.arg.y); + clean_code(mpl, code->arg.arg.z); + break; + case O_MIN: + case O_MAX: + /* n-ary operation */ + for (e = code->arg.list; e != NULL; e = e->next) + clean_code(mpl, e->x); + break; + case O_SUM: + case O_PROD: + case O_MINIMUM: + case O_MAXIMUM: + case O_FORALL: + case O_EXISTS: + case O_SETOF: + case O_BUILD: + /* iterated operation */ + clean_domain(mpl, code->arg.loop.domain); + clean_code(mpl, code->arg.loop.x); + break; + default: + xassert(code->op != code->op); + } +done: return; +} + +#if 1 /* 11/II-2008 */ +/**********************************************************************/ +/* * * DATA TABLES * * */ +/**********************************************************************/ + +int mpl_tab_num_args(TABDCA *dca) +{ /* returns the number of arguments */ + return dca->na; +} + +const char *mpl_tab_get_arg(TABDCA *dca, int k) +{ /* returns pointer to k-th argument */ + xassert(1 <= k && k <= dca->na); + return dca->arg[k]; +} + +int mpl_tab_num_flds(TABDCA *dca) +{ /* returns the number of fields */ + return dca->nf; +} + +const char *mpl_tab_get_name(TABDCA *dca, int k) +{ /* returns pointer to name of k-th field */ + xassert(1 <= k && k <= dca->nf); + return dca->name[k]; +} + +int mpl_tab_get_type(TABDCA *dca, int k) +{ /* returns type of k-th field */ + xassert(1 <= k && k <= dca->nf); + return dca->type[k]; +} + +double mpl_tab_get_num(TABDCA *dca, int k) +{ /* returns numeric value of k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == 'N'); + return dca->num[k]; +} + +const char *mpl_tab_get_str(TABDCA *dca, int k) +{ /* returns pointer to string value of k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == 'S'); + xassert(dca->str[k] != NULL); + return dca->str[k]; +} + +void mpl_tab_set_num(TABDCA *dca, int k, double num) +{ /* assign numeric value to k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == '?'); + dca->type[k] = 'N'; + dca->num[k] = num; + return; +} + +void mpl_tab_set_str(TABDCA *dca, int k, const char *str) +{ /* assign string value to k-th field */ + xassert(1 <= k && k <= dca->nf); + xassert(dca->type[k] == '?'); + xassert(strlen(str) <= MAX_LENGTH); + xassert(dca->str[k] != NULL); + dca->type[k] = 'S'; + strcpy(dca->str[k], str); + return; +} + +static int write_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + TABLE *tab = info; + TABDCA *dca = mpl->dca; + TABOUT *out; + SYMBOL *sym; + int k; + char buf[MAX_LENGTH+1]; + /* evaluate field values */ + k = 0; + for (out = tab->u.out.list; out != NULL; out = out->next) + { k++; + switch (out->code->type) + { case A_NUMERIC: + dca->type[k] = 'N'; + dca->num[k] = eval_numeric(mpl, out->code); + dca->str[k][0] = '\0'; + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, out->code); + if (sym->str == NULL) + { dca->type[k] = 'N'; + dca->num[k] = sym->num; + dca->str[k][0] = '\0'; + } + else + { dca->type[k] = 'S'; + dca->num[k] = 0.0; + fetch_string(mpl, sym->str, buf); + strcpy(dca->str[k], buf); + } + delete_symbol(mpl, sym); + break; + default: + xassert(out != out); + } + } + /* write record to output table */ + mpl_tab_drv_write(mpl); + return 0; +} + +void execute_table(MPL *mpl, TABLE *tab) +{ /* execute table statement */ + TABARG *arg; + TABFLD *fld; + TABIN *in; + TABOUT *out; + TABDCA *dca; + SET *set; + int k; + char buf[MAX_LENGTH+1]; + /* allocate table driver communication area */ + xassert(mpl->dca == NULL); + mpl->dca = dca = xmalloc(sizeof(TABDCA)); + dca->id = 0; + dca->link = NULL; + dca->na = 0; + dca->arg = NULL; + dca->nf = 0; + dca->name = NULL; + dca->type = NULL; + dca->num = NULL; + dca->str = NULL; + /* allocate arguments */ + xassert(dca->na == 0); + for (arg = tab->arg; arg != NULL; arg = arg->next) + dca->na++; + dca->arg = xcalloc(1+dca->na, sizeof(char *)); +#if 1 /* 28/IX-2008 */ + for (k = 1; k <= dca->na; k++) dca->arg[k] = NULL; +#endif + /* evaluate argument values */ + k = 0; + for (arg = tab->arg; arg != NULL; arg = arg->next) + { SYMBOL *sym; + k++; + xassert(arg->code->type == A_SYMBOLIC); + sym = eval_symbolic(mpl, arg->code); + if (sym->str == NULL) + sprintf(buf, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, buf); + delete_symbol(mpl, sym); + dca->arg[k] = xmalloc(strlen(buf)+1); + strcpy(dca->arg[k], buf); + } + /* perform table input/output */ + switch (tab->type) + { case A_INPUT: goto read_table; + case A_OUTPUT: goto write_table; + default: xassert(tab != tab); + } +read_table: + /* read data from input table */ + /* add the only member to the control set and assign it empty + elemental set */ + set = tab->u.in.set; + if (set != NULL) + { if (set->data) + error(mpl, "%s already provided with data", set->name); + xassert(set->array->head == NULL); + add_member(mpl, set->array, NULL)->value.set = + create_elemset(mpl, set->dimen); + set->data = 1; + } + /* check parameters specified in the input list */ + for (in = tab->u.in.list; in != NULL; in = in->next) + { if (in->par->data) + error(mpl, "%s already provided with data", in->par->name); + in->par->data = 1; + } + /* allocate and initialize fields */ + xassert(dca->nf == 0); + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + dca->nf++; + for (in = tab->u.in.list; in != NULL; in = in->next) + dca->nf++; + dca->name = xcalloc(1+dca->nf, sizeof(char *)); + dca->type = xcalloc(1+dca->nf, sizeof(int)); + dca->num = xcalloc(1+dca->nf, sizeof(double)); + dca->str = xcalloc(1+dca->nf, sizeof(char *)); + k = 0; + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + { k++; + dca->name[k] = fld->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + for (in = tab->u.in.list; in != NULL; in = in->next) + { k++; + dca->name[k] = in->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + /* open input table */ + mpl_tab_drv_open(mpl, 'R'); + /* read and process records */ + for (;;) + { TUPLE *tup; + /* reset field types */ + for (k = 1; k <= dca->nf; k++) + dca->type[k] = '?'; + /* read next record */ + if (mpl_tab_drv_read(mpl)) break; + /* all fields must be set by the driver */ + for (k = 1; k <= dca->nf; k++) + { if (dca->type[k] == '?') + error(mpl, "field %s missing in input table", + dca->name[k]); + } + /* construct n-tuple */ + tup = create_tuple(mpl); + k = 0; + for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) + { k++; + xassert(k <= dca->nf); + switch (dca->type[k]) + { case 'N': + tup = expand_tuple(mpl, tup, create_symbol_num(mpl, + dca->num[k])); + break; + case 'S': + xassert(strlen(dca->str[k]) <= MAX_LENGTH); + tup = expand_tuple(mpl, tup, create_symbol_str(mpl, + create_string(mpl, dca->str[k]))); + break; + default: + xassert(dca != dca); + } + } + /* add n-tuple just read to the control set */ + if (tab->u.in.set != NULL) + check_then_add(mpl, tab->u.in.set->array->head->value.set, + copy_tuple(mpl, tup)); + /* assign values to the parameters in the input list */ + for (in = tab->u.in.list; in != NULL; in = in->next) + { MEMBER *memb; + k++; + xassert(k <= dca->nf); + /* there must be no member with the same n-tuple */ + if (find_member(mpl, in->par->array, tup) != NULL) + error(mpl, "%s%s already defined", in->par->name, + format_tuple(mpl, '[', tup)); + /* create new parameter member with given n-tuple */ + memb = add_member(mpl, in->par->array, copy_tuple(mpl, tup)) + ; + /* assign value to the parameter member */ + switch (in->par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + if (dca->type[k] != 'N') + error(mpl, "%s requires numeric data", + in->par->name); + memb->value.num = dca->num[k]; + break; + case A_SYMBOLIC: + switch (dca->type[k]) + { case 'N': + memb->value.sym = create_symbol_num(mpl, + dca->num[k]); + break; + case 'S': + xassert(strlen(dca->str[k]) <= MAX_LENGTH); + memb->value.sym = create_symbol_str(mpl, + create_string(mpl,dca->str[k])); + break; + default: + xassert(dca != dca); + } + break; + default: + xassert(in != in); + } + } + /* n-tuple is no more needed */ + delete_tuple(mpl, tup); + } + /* close input table */ + mpl_tab_drv_close(mpl); + goto done; +write_table: + /* write data to output table */ + /* allocate and initialize fields */ + xassert(dca->nf == 0); + for (out = tab->u.out.list; out != NULL; out = out->next) + dca->nf++; + dca->name = xcalloc(1+dca->nf, sizeof(char *)); + dca->type = xcalloc(1+dca->nf, sizeof(int)); + dca->num = xcalloc(1+dca->nf, sizeof(double)); + dca->str = xcalloc(1+dca->nf, sizeof(char *)); + k = 0; + for (out = tab->u.out.list; out != NULL; out = out->next) + { k++; + dca->name[k] = out->name; + dca->type[k] = '?'; + dca->num[k] = 0.0; + dca->str[k] = xmalloc(MAX_LENGTH+1); + dca->str[k][0] = '\0'; + } + /* open output table */ + mpl_tab_drv_open(mpl, 'W'); + /* evaluate fields and write records */ + loop_within_domain(mpl, tab->u.out.domain, tab, write_func); + /* close output table */ + mpl_tab_drv_close(mpl); +done: /* free table driver communication area */ + free_dca(mpl); + return; +} + +void free_dca(MPL *mpl) +{ /* free table driver communucation area */ + TABDCA *dca = mpl->dca; + int k; + if (dca != NULL) + { if (dca->link != NULL) + mpl_tab_drv_close(mpl); + if (dca->arg != NULL) + { for (k = 1; k <= dca->na; k++) +#if 1 /* 28/IX-2008 */ + if (dca->arg[k] != NULL) +#endif + xfree(dca->arg[k]); + xfree(dca->arg); + } + if (dca->name != NULL) xfree(dca->name); + if (dca->type != NULL) xfree(dca->type); + if (dca->num != NULL) xfree(dca->num); + if (dca->str != NULL) + { for (k = 1; k <= dca->nf; k++) + xfree(dca->str[k]); + xfree(dca->str); + } + xfree(dca), mpl->dca = NULL; + } + return; +} + +void clean_table(MPL *mpl, TABLE *tab) +{ /* clean table statement */ + TABARG *arg; + TABOUT *out; + /* clean string list */ + for (arg = tab->arg; arg != NULL; arg = arg->next) + clean_code(mpl, arg->code); + switch (tab->type) + { case A_INPUT: + break; + case A_OUTPUT: + /* clean subscript domain */ + clean_domain(mpl, tab->u.out.domain); + /* clean output list */ + for (out = tab->u.out.list; out != NULL; out = out->next) + clean_code(mpl, out->code); + break; + default: + xassert(tab != tab); + } + return; +} +#endif + +/**********************************************************************/ +/* * * MODEL STATEMENTS * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- execute_check - execute check statement. +-- +-- This routine executes specified check statement. */ + +static int check_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + CHECK *chk = (CHECK *)info; + if (!eval_logical(mpl, chk->code)) + error(mpl, "check%s failed", format_tuple(mpl, '[', + get_domain_tuple(mpl, chk->domain))); + return 0; +} + +void execute_check(MPL *mpl, CHECK *chk) +{ loop_within_domain(mpl, chk->domain, chk, check_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_check - clean check statement. +-- +-- This routine cleans specified check statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_check(MPL *mpl, CHECK *chk) +{ /* clean subscript domain */ + clean_domain(mpl, chk->domain); + /* clean pseudo-code for computing predicate */ + clean_code(mpl, chk->code); + return; +} + +/*---------------------------------------------------------------------- +-- execute_display - execute display statement. +-- +-- This routine executes specified display statement. */ + +static void display_set(MPL *mpl, SET *set, MEMBER *memb) +{ /* display member of model set */ + ELEMSET *s = memb->value.set; + MEMBER *m; + write_text(mpl, "%s%s%s\n", set->name, + format_tuple(mpl, '[', memb->tuple), + s->head == NULL ? " is empty" : ":"); + for (m = s->head; m != NULL; m = m->next) + write_text(mpl, " %s\n", format_tuple(mpl, '(', m->tuple)); + return; +} + +static void display_par(MPL *mpl, PARAMETER *par, MEMBER *memb) +{ /* display member of model parameter */ + switch (par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + write_text(mpl, "%s%s = %.*g\n", par->name, + format_tuple(mpl, '[', memb->tuple), + DBL_DIG, memb->value.num); + break; + case A_SYMBOLIC: + write_text(mpl, "%s%s = %s\n", par->name, + format_tuple(mpl, '[', memb->tuple), + format_symbol(mpl, memb->value.sym)); + break; + default: + xassert(par != par); + } + return; +} + +#if 1 /* 15/V-2010 */ +static void display_var(MPL *mpl, VARIABLE *var, MEMBER *memb, + int suff) +{ /* display member of model variable */ + if (suff == DOT_NONE || suff == DOT_VAL) + write_text(mpl, "%s%s.val = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->prim); + else if (suff == DOT_LB) + write_text(mpl, "%s%s.lb = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->var->lbnd == NULL ? -DBL_MAX : + memb->value.var->lbnd); + else if (suff == DOT_UB) + write_text(mpl, "%s%s.ub = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->var->ubnd == NULL ? +DBL_MAX : + memb->value.var->ubnd); + else if (suff == DOT_STATUS) + write_text(mpl, "%s%s.status = %d\n", var->name, format_tuple + (mpl, '[', memb->tuple), memb->value.var->stat); + else if (suff == DOT_DUAL) + write_text(mpl, "%s%s.dual = %.*g\n", var->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.var->dual); + else + xassert(suff != suff); + return; +} +#endif + +#if 1 /* 15/V-2010 */ +static void display_con(MPL *mpl, CONSTRAINT *con, MEMBER *memb, + int suff) +{ /* display member of model constraint */ + if (suff == DOT_NONE || suff == DOT_VAL) + write_text(mpl, "%s%s.val = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->prim); + else if (suff == DOT_LB) + write_text(mpl, "%s%s.lb = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->con->lbnd == NULL ? -DBL_MAX : + memb->value.con->lbnd); + else if (suff == DOT_UB) + write_text(mpl, "%s%s.ub = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->con->ubnd == NULL ? +DBL_MAX : + memb->value.con->ubnd); + else if (suff == DOT_STATUS) + write_text(mpl, "%s%s.status = %d\n", con->name, format_tuple + (mpl, '[', memb->tuple), memb->value.con->stat); + else if (suff == DOT_DUAL) + write_text(mpl, "%s%s.dual = %.*g\n", con->name, + format_tuple(mpl, '[', memb->tuple), DBL_DIG, + memb->value.con->dual); + else + xassert(suff != suff); + return; +} +#endif + +static void display_memb(MPL *mpl, CODE *code) +{ /* display member specified by pseudo-code */ + MEMBER memb; + ARG_LIST *e; + xassert(code->op == O_MEMNUM || code->op == O_MEMSYM + || code->op == O_MEMSET || code->op == O_MEMVAR + || code->op == O_MEMCON); + memb.tuple = create_tuple(mpl); + for (e = code->arg.par.list; e != NULL; e = e->next) + memb.tuple = expand_tuple(mpl, memb.tuple, eval_symbolic(mpl, + e->x)); + switch (code->op) + { case O_MEMNUM: + memb.value.num = eval_member_num(mpl, code->arg.par.par, + memb.tuple); + display_par(mpl, code->arg.par.par, &memb); + break; + case O_MEMSYM: + memb.value.sym = eval_member_sym(mpl, code->arg.par.par, + memb.tuple); + display_par(mpl, code->arg.par.par, &memb); + delete_symbol(mpl, memb.value.sym); + break; + case O_MEMSET: + memb.value.set = eval_member_set(mpl, code->arg.set.set, + memb.tuple); + display_set(mpl, code->arg.set.set, &memb); + break; + case O_MEMVAR: + memb.value.var = eval_member_var(mpl, code->arg.var.var, + memb.tuple); + display_var + (mpl, code->arg.var.var, &memb, code->arg.var.suff); + break; + case O_MEMCON: + memb.value.con = eval_member_con(mpl, code->arg.con.con, + memb.tuple); + display_con + (mpl, code->arg.con.con, &memb, code->arg.con.suff); + break; + default: + xassert(code != code); + } + delete_tuple(mpl, memb.tuple); + return; +} + +static void display_code(MPL *mpl, CODE *code) +{ /* display value of expression */ + switch (code->type) + { case A_NUMERIC: + /* numeric value */ + { double num; + num = eval_numeric(mpl, code); + write_text(mpl, "%.*g\n", DBL_DIG, num); + } + break; + case A_SYMBOLIC: + /* symbolic value */ + { SYMBOL *sym; + sym = eval_symbolic(mpl, code); + write_text(mpl, "%s\n", format_symbol(mpl, sym)); + delete_symbol(mpl, sym); + } + break; + case A_LOGICAL: + /* logical value */ + { int bit; + bit = eval_logical(mpl, code); + write_text(mpl, "%s\n", bit ? "true" : "false"); + } + break; + case A_TUPLE: + /* n-tuple */ + { TUPLE *tuple; + tuple = eval_tuple(mpl, code); + write_text(mpl, "%s\n", format_tuple(mpl, '(', tuple)); + delete_tuple(mpl, tuple); + } + break; + case A_ELEMSET: + /* elemental set */ + { ELEMSET *set; + MEMBER *memb; + set = eval_elemset(mpl, code); + if (set->head == 0) + write_text(mpl, "set is empty\n"); + for (memb = set->head; memb != NULL; memb = memb->next) + write_text(mpl, " %s\n", format_tuple(mpl, '(', + memb->tuple)); + delete_elemset(mpl, set); + } + break; + case A_FORMULA: + /* linear form */ + { FORMULA *form, *term; + form = eval_formula(mpl, code); + if (form == NULL) + write_text(mpl, "linear form is empty\n"); + for (term = form; term != NULL; term = term->next) + { if (term->var == NULL) + write_text(mpl, " %.*g\n", term->coef); + else + write_text(mpl, " %.*g %s%s\n", DBL_DIG, + term->coef, term->var->var->name, + format_tuple(mpl, '[', term->var->memb->tuple)); + } + delete_formula(mpl, form); + } + break; + default: + xassert(code != code); + } + return; +} + +static int display_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + DISPLAY *dpy = (DISPLAY *)info; + DISPLAY1 *entry; + for (entry = dpy->list; entry != NULL; entry = entry->next) + { if (entry->type == A_INDEX) + { /* dummy index */ + DOMAIN_SLOT *slot = entry->u.slot; + write_text(mpl, "%s = %s\n", slot->name, + format_symbol(mpl, slot->value)); + } + else if (entry->type == A_SET) + { /* model set */ + SET *set = entry->u.set; + MEMBER *memb; + if (set->assign != NULL) + { /* the set has assignment expression; evaluate all its + members over entire domain */ + eval_whole_set(mpl, set); + } + else + { /* the set has no assignment expression; refer to its + any existing member ignoring resultant value to check + the data provided the data section */ +#if 1 /* 12/XII-2008 */ + if (set->gadget != NULL && set->data == 0) + { /* initialize the set with data from a plain set */ + saturate_set(mpl, set); + } +#endif + if (set->array->head != NULL) + eval_member_set(mpl, set, set->array->head->tuple); + } + /* display all members of the set array */ + if (set->array->head == NULL) + write_text(mpl, "%s has empty content\n", set->name); + for (memb = set->array->head; memb != NULL; memb = + memb->next) display_set(mpl, set, memb); + } + else if (entry->type == A_PARAMETER) + { /* model parameter */ + PARAMETER *par = entry->u.par; + MEMBER *memb; + if (par->assign != NULL) + { /* the parameter has an assignment expression; evaluate + all its member over entire domain */ + eval_whole_par(mpl, par); + } + else + { /* the parameter has no assignment expression; refer to + its any existing member ignoring resultant value to + check the data provided in the data section */ + if (par->array->head != NULL) + { if (par->type != A_SYMBOLIC) + eval_member_num(mpl, par, par->array->head->tuple); + else + delete_symbol(mpl, eval_member_sym(mpl, par, + par->array->head->tuple)); + } + } + /* display all members of the parameter array */ + if (par->array->head == NULL) + write_text(mpl, "%s has empty content\n", par->name); + for (memb = par->array->head; memb != NULL; memb = + memb->next) display_par(mpl, par, memb); + } + else if (entry->type == A_VARIABLE) + { /* model variable */ + VARIABLE *var = entry->u.var; + MEMBER *memb; + xassert(mpl->flag_p); + /* display all members of the variable array */ + if (var->array->head == NULL) + write_text(mpl, "%s has empty content\n", var->name); + for (memb = var->array->head; memb != NULL; memb = + memb->next) display_var(mpl, var, memb, DOT_NONE); + } + else if (entry->type == A_CONSTRAINT) + { /* model constraint */ + CONSTRAINT *con = entry->u.con; + MEMBER *memb; + xassert(mpl->flag_p); + /* display all members of the constraint array */ + if (con->array->head == NULL) + write_text(mpl, "%s has empty content\n", con->name); + for (memb = con->array->head; memb != NULL; memb = + memb->next) display_con(mpl, con, memb, DOT_NONE); + } + else if (entry->type == A_EXPRESSION) + { /* expression */ + CODE *code = entry->u.code; + if (code->op == O_MEMNUM || code->op == O_MEMSYM || + code->op == O_MEMSET || code->op == O_MEMVAR || + code->op == O_MEMCON) + display_memb(mpl, code); + else + display_code(mpl, code); + } + else + xassert(entry != entry); + } + return 0; +} + +void execute_display(MPL *mpl, DISPLAY *dpy) +{ loop_within_domain(mpl, dpy->domain, dpy, display_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_display - clean display statement. +-- +-- This routine cleans specified display statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_display(MPL *mpl, DISPLAY *dpy) +{ DISPLAY1 *d; +#if 0 /* 15/V-2010 */ + ARG_LIST *e; +#endif + /* clean subscript domain */ + clean_domain(mpl, dpy->domain); + /* clean display list */ + for (d = dpy->list; d != NULL; d = d->next) + { /* clean pseudo-code for computing expression */ + if (d->type == A_EXPRESSION) + clean_code(mpl, d->u.code); +#if 0 /* 15/V-2010 */ + /* clean pseudo-code for computing subscripts */ + for (e = d->list; e != NULL; e = e->next) + clean_code(mpl, e->x); +#endif + } + return; +} + +/*---------------------------------------------------------------------- +-- execute_printf - execute printf statement. +-- +-- This routine executes specified printf statement. */ + +#if 1 /* 14/VII-2006 */ +static void print_char(MPL *mpl, int c) +{ if (mpl->prt_fp == NULL) + write_char(mpl, c); + else +#if 0 /* 04/VIII-2013 */ + xfputc(c, mpl->prt_fp); +#else + { unsigned char buf[1]; + buf[0] = (unsigned char)c; + glp_write(mpl->prt_fp, buf, 1); + } +#endif + return; +} + +static void print_text(MPL *mpl, char *fmt, ...) +{ va_list arg; + char buf[OUTBUF_SIZE], *c; + va_start(arg, fmt); + vsprintf(buf, fmt, arg); + xassert(strlen(buf) < sizeof(buf)); + va_end(arg); + for (c = buf; *c != '\0'; c++) print_char(mpl, *c); + return; +} +#endif + +static int printf_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + PRINTF *prt = (PRINTF *)info; + PRINTF1 *entry; + SYMBOL *sym; + char fmt[MAX_LENGTH+1], *c, *from, save; + /* evaluate format control string */ + sym = eval_symbolic(mpl, prt->fmt); + if (sym->str == NULL) + sprintf(fmt, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fmt); + delete_symbol(mpl, sym); + /* scan format control string and perform formatting output */ + entry = prt->list; + for (c = fmt; *c != '\0'; c++) + { if (*c == '%') + { /* scan format specifier */ + from = c++; + if (*c == '%') + { print_char(mpl, '%'); + continue; + } + if (entry == NULL) break; + /* scan optional flags */ + while (*c == '-' || *c == '+' || *c == ' ' || *c == '#' || + *c == '0') c++; + /* scan optional minimum field width */ + while (isdigit((unsigned char)*c)) c++; + /* scan optional precision */ + if (*c == '.') + { c++; + while (isdigit((unsigned char)*c)) c++; + } + /* scan conversion specifier and perform formatting */ + save = *(c+1), *(c+1) = '\0'; + if (*c == 'd' || *c == 'i' || *c == 'e' || *c == 'E' || + *c == 'f' || *c == 'F' || *c == 'g' || *c == 'G') + { /* the specifier requires numeric value */ + double value; + xassert(entry != NULL); + switch (entry->code->type) + { case A_NUMERIC: + value = eval_numeric(mpl, entry->code); + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, entry->code); + if (sym->str != NULL) + error(mpl, "cannot convert %s to floating-point" + " number", format_symbol(mpl, sym)); + value = sym->num; + delete_symbol(mpl, sym); + break; + case A_LOGICAL: + if (eval_logical(mpl, entry->code)) + value = 1.0; + else + value = 0.0; + break; + default: + xassert(entry != entry); + } + if (*c == 'd' || *c == 'i') + { double int_max = (double)INT_MAX; + if (!(-int_max <= value && value <= +int_max)) + error(mpl, "cannot convert %.*g to integer", + DBL_DIG, value); + print_text(mpl, from, (int)floor(value + 0.5)); + } + else + print_text(mpl, from, value); + } + else if (*c == 's') + { /* the specifier requires symbolic value */ + char value[MAX_LENGTH+1]; + switch (entry->code->type) + { case A_NUMERIC: + sprintf(value, "%.*g", DBL_DIG, eval_numeric(mpl, + entry->code)); + break; + case A_LOGICAL: + if (eval_logical(mpl, entry->code)) + strcpy(value, "T"); + else + strcpy(value, "F"); + break; + case A_SYMBOLIC: + sym = eval_symbolic(mpl, entry->code); + if (sym->str == NULL) + sprintf(value, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, value); + delete_symbol(mpl, sym); + break; + default: + xassert(entry != entry); + } + print_text(mpl, from, value); + } + else + error(mpl, "format specifier missing or invalid"); + *(c+1) = save; + entry = entry->next; + } + else if (*c == '\\') + { /* write some control character */ + c++; + if (*c == 't') + print_char(mpl, '\t'); + else if (*c == 'n') + print_char(mpl, '\n'); +#if 1 /* 28/X-2010 */ + else if (*c == '\0') + { /* format string ends with backslash */ + error(mpl, "invalid use of escape character \\ in format" + " control string"); + } +#endif + else + print_char(mpl, *c); + } + else + { /* write character without formatting */ + print_char(mpl, *c); + } + } + return 0; +} + +#if 0 /* 14/VII-2006 */ +void execute_printf(MPL *mpl, PRINTF *prt) +{ loop_within_domain(mpl, prt->domain, prt, printf_func); + return; +} +#else +void execute_printf(MPL *mpl, PRINTF *prt) +{ if (prt->fname == NULL) + { /* switch to the standard output */ + if (mpl->prt_fp != NULL) + { glp_close(mpl->prt_fp), mpl->prt_fp = NULL; + xfree(mpl->prt_file), mpl->prt_file = NULL; + } + } + else + { /* evaluate file name string */ + SYMBOL *sym; + char fname[MAX_LENGTH+1]; + sym = eval_symbolic(mpl, prt->fname); + if (sym->str == NULL) + sprintf(fname, "%.*g", DBL_DIG, sym->num); + else + fetch_string(mpl, sym->str, fname); + delete_symbol(mpl, sym); + /* close the current print file, if necessary */ + if (mpl->prt_fp != NULL && + (!prt->app || strcmp(mpl->prt_file, fname) != 0)) + { glp_close(mpl->prt_fp), mpl->prt_fp = NULL; + xfree(mpl->prt_file), mpl->prt_file = NULL; + } + /* open the specified print file, if necessary */ + if (mpl->prt_fp == NULL) + { mpl->prt_fp = glp_open(fname, prt->app ? "a" : "w"); + if (mpl->prt_fp == NULL) + error(mpl, "unable to open '%s' for writing - %s", + fname, get_err_msg()); + mpl->prt_file = xmalloc(strlen(fname)+1); + strcpy(mpl->prt_file, fname); + } + } + loop_within_domain(mpl, prt->domain, prt, printf_func); + if (mpl->prt_fp != NULL) + { +#if 0 /* FIXME */ + xfflush(mpl->prt_fp); +#endif + if (glp_ioerr(mpl->prt_fp)) + error(mpl, "writing error to '%s' - %s", mpl->prt_file, + get_err_msg()); + } + return; +} +#endif + +/*---------------------------------------------------------------------- +-- clean_printf - clean printf statement. +-- +-- This routine cleans specified printf statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_printf(MPL *mpl, PRINTF *prt) +{ PRINTF1 *p; + /* clean subscript domain */ + clean_domain(mpl, prt->domain); + /* clean pseudo-code for computing format string */ + clean_code(mpl, prt->fmt); + /* clean printf list */ + for (p = prt->list; p != NULL; p = p->next) + { /* clean pseudo-code for computing value to be printed */ + clean_code(mpl, p->code); + } +#if 1 /* 14/VII-2006 */ + /* clean pseudo-code for computing file name string */ + clean_code(mpl, prt->fname); +#endif + return; +} + +/*---------------------------------------------------------------------- +-- execute_for - execute for statement. +-- +-- This routine executes specified for statement. */ + +static int for_func(MPL *mpl, void *info) +{ /* this is auxiliary routine to work within domain scope */ + FOR *fur = (FOR *)info; + STATEMENT *stmt, *save; + save = mpl->stmt; + for (stmt = fur->list; stmt != NULL; stmt = stmt->next) + execute_statement(mpl, stmt); + mpl->stmt = save; + return 0; +} + +void execute_for(MPL *mpl, FOR *fur) +{ loop_within_domain(mpl, fur->domain, fur, for_func); + return; +} + +/*---------------------------------------------------------------------- +-- clean_for - clean for statement. +-- +-- This routine cleans specified for statement that assumes deleting all +-- stuff dynamically allocated on generating/postsolving phase. */ + +void clean_for(MPL *mpl, FOR *fur) +{ STATEMENT *stmt; + /* clean subscript domain */ + clean_domain(mpl, fur->domain); + /* clean all sub-statements */ + for (stmt = fur->list; stmt != NULL; stmt = stmt->next) + clean_statement(mpl, stmt); + return; +} + +/*---------------------------------------------------------------------- +-- execute_statement - execute specified model statement. +-- +-- This routine executes specified model statement. */ + +void execute_statement(MPL *mpl, STATEMENT *stmt) +{ mpl->stmt = stmt; + switch (stmt->type) + { case A_SET: + case A_PARAMETER: + case A_VARIABLE: + break; + case A_CONSTRAINT: + xprintf("Generating %s...\n", stmt->u.con->name); + eval_whole_con(mpl, stmt->u.con); + break; + case A_TABLE: + switch (stmt->u.tab->type) + { case A_INPUT: + xprintf("Reading %s...\n", stmt->u.tab->name); + break; + case A_OUTPUT: + xprintf("Writing %s...\n", stmt->u.tab->name); + break; + default: + xassert(stmt != stmt); + } + execute_table(mpl, stmt->u.tab); + break; + case A_SOLVE: + break; + case A_CHECK: + xprintf("Checking (line %d)...\n", stmt->line); + execute_check(mpl, stmt->u.chk); + break; + case A_DISPLAY: + write_text(mpl, "Display statement at line %d\n", + stmt->line); + execute_display(mpl, stmt->u.dpy); + break; + case A_PRINTF: + execute_printf(mpl, stmt->u.prt); + break; + case A_FOR: + execute_for(mpl, stmt->u.fur); + break; + default: + xassert(stmt != stmt); + } + return; +} + +/*---------------------------------------------------------------------- +-- clean_statement - clean specified model statement. +-- +-- This routine cleans specified model statement that assumes deleting +-- all stuff dynamically allocated on generating/postsolving phase. */ + +void clean_statement(MPL *mpl, STATEMENT *stmt) +{ switch(stmt->type) + { case A_SET: + clean_set(mpl, stmt->u.set); break; + case A_PARAMETER: + clean_parameter(mpl, stmt->u.par); break; + case A_VARIABLE: + clean_variable(mpl, stmt->u.var); break; + case A_CONSTRAINT: + clean_constraint(mpl, stmt->u.con); break; +#if 1 /* 11/II-2008 */ + case A_TABLE: + clean_table(mpl, stmt->u.tab); break; +#endif + case A_SOLVE: + break; + case A_CHECK: + clean_check(mpl, stmt->u.chk); break; + case A_DISPLAY: + clean_display(mpl, stmt->u.dpy); break; + case A_PRINTF: + clean_printf(mpl, stmt->u.prt); break; + case A_FOR: + clean_for(mpl, stmt->u.fur); break; + default: + xassert(stmt != stmt); + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl4.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl4.c new file mode 100644 index 000000000..6e80499c9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl4.c @@ -0,0 +1,1426 @@ +/* mpl4.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" + +#define xfault xerror +#define xfprintf glp_format +#define dmp_create_poolx(size) dmp_create_pool() + +/**********************************************************************/ +/* * * GENERATING AND POSTSOLVING MODEL * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- alloc_content - allocate content arrays for all model objects. +-- +-- This routine allocates content arrays for all existing model objects +-- and thereby finalizes creating model. +-- +-- This routine must be called immediately after reading model section, +-- i.e. before reading data section or generating model. */ + +void alloc_content(MPL *mpl) +{ STATEMENT *stmt; + /* walk through all model statements */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { switch (stmt->type) + { case A_SET: + /* model set */ + xassert(stmt->u.set->array == NULL); + stmt->u.set->array = create_array(mpl, A_ELEMSET, + stmt->u.set->dim); + break; + case A_PARAMETER: + /* model parameter */ + xassert(stmt->u.par->array == NULL); + switch (stmt->u.par->type) + { case A_NUMERIC: + case A_INTEGER: + case A_BINARY: + stmt->u.par->array = create_array(mpl, A_NUMERIC, + stmt->u.par->dim); + break; + case A_SYMBOLIC: + stmt->u.par->array = create_array(mpl, A_SYMBOLIC, + stmt->u.par->dim); + break; + default: + xassert(stmt != stmt); + } + break; + case A_VARIABLE: + /* model variable */ + xassert(stmt->u.var->array == NULL); + stmt->u.var->array = create_array(mpl, A_ELEMVAR, + stmt->u.var->dim); + break; + case A_CONSTRAINT: + /* model constraint/objective */ + xassert(stmt->u.con->array == NULL); + stmt->u.con->array = create_array(mpl, A_ELEMCON, + stmt->u.con->dim); + break; +#if 1 /* 11/II-2008 */ + case A_TABLE: +#endif + case A_SOLVE: + case A_CHECK: + case A_DISPLAY: + case A_PRINTF: + case A_FOR: + /* functional statements have no content array */ + break; + default: + xassert(stmt != stmt); + } + } + return; +} + +/*---------------------------------------------------------------------- +-- generate_model - generate model. +-- +-- This routine executes the model statements which precede the solve +-- statement. */ + +void generate_model(MPL *mpl) +{ STATEMENT *stmt; + xassert(!mpl->flag_p); + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { execute_statement(mpl, stmt); + if (mpl->stmt->type == A_SOLVE) break; + } + mpl->stmt = stmt; + return; +} + +/*---------------------------------------------------------------------- +-- build_problem - build problem instance. +-- +-- This routine builds lists of rows and columns for problem instance, +-- which corresponds to the generated model. */ + +void build_problem(MPL *mpl) +{ STATEMENT *stmt; + MEMBER *memb; + VARIABLE *v; + CONSTRAINT *c; + FORMULA *t; + int i, j; + xassert(mpl->m == 0); + xassert(mpl->n == 0); + xassert(mpl->row == NULL); + xassert(mpl->col == NULL); + /* check that all elemental variables has zero column numbers */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + xassert(memb->value.var->j == 0); + } + } + /* assign row numbers to elemental constraints and objectives */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_CONSTRAINT) + { c = stmt->u.con; + for (memb = c->array->head; memb != NULL; memb = memb->next) + { xassert(memb->value.con->i == 0); + memb->value.con->i = ++mpl->m; + /* walk through linear form and mark elemental variables, + which are referenced at least once */ + for (t = memb->value.con->form; t != NULL; t = t->next) + { xassert(t->var != NULL); + t->var->memb->value.var->j = -1; + } + } + } + } + /* assign column numbers to marked elemental variables */ + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + if (memb->value.var->j != 0) memb->value.var->j = + ++mpl->n; + } + } + /* build list of rows */ + mpl->row = xcalloc(1+mpl->m, sizeof(ELEMCON *)); + for (i = 1; i <= mpl->m; i++) mpl->row[i] = NULL; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_CONSTRAINT) + { c = stmt->u.con; + for (memb = c->array->head; memb != NULL; memb = memb->next) + { i = memb->value.con->i; + xassert(1 <= i && i <= mpl->m); + xassert(mpl->row[i] == NULL); + mpl->row[i] = memb->value.con; + } + } + } + for (i = 1; i <= mpl->m; i++) xassert(mpl->row[i] != NULL); + /* build list of columns */ + mpl->col = xcalloc(1+mpl->n, sizeof(ELEMVAR *)); + for (j = 1; j <= mpl->n; j++) mpl->col[j] = NULL; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + { if (stmt->type == A_VARIABLE) + { v = stmt->u.var; + for (memb = v->array->head; memb != NULL; memb = memb->next) + { j = memb->value.var->j; + if (j == 0) continue; + xassert(1 <= j && j <= mpl->n); + xassert(mpl->col[j] == NULL); + mpl->col[j] = memb->value.var; + } + } + } + for (j = 1; j <= mpl->n; j++) xassert(mpl->col[j] != NULL); + return; +} + +/*---------------------------------------------------------------------- +-- postsolve_model - postsolve model. +-- +-- This routine executes the model statements which follow the solve +-- statement. */ + +void postsolve_model(MPL *mpl) +{ STATEMENT *stmt; + xassert(!mpl->flag_p); + mpl->flag_p = 1; + for (stmt = mpl->stmt; stmt != NULL; stmt = stmt->next) + execute_statement(mpl, stmt); + mpl->stmt = NULL; + return; +} + +/*---------------------------------------------------------------------- +-- clean_model - clean model content. +-- +-- This routine cleans the model content that assumes deleting all stuff +-- dynamically allocated on generating/postsolving phase. +-- +-- Actually cleaning model content is not needed. This function is used +-- mainly to be sure that there were no logical errors on using dynamic +-- memory pools during the generation phase. +-- +-- NOTE: This routine must not be called if any errors were detected on +-- the generation phase. */ + +void clean_model(MPL *mpl) +{ STATEMENT *stmt; + for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) + clean_statement(mpl, stmt); + /* check that all atoms have been returned to their pools */ + if (dmp_in_use(mpl->strings) != 0) + error(mpl, "internal logic error: %d string segment(s) were lo" + "st", dmp_in_use(mpl->strings)); + if (dmp_in_use(mpl->symbols) != 0) + error(mpl, "internal logic error: %d symbol(s) were lost", + dmp_in_use(mpl->symbols)); + if (dmp_in_use(mpl->tuples) != 0) + error(mpl, "internal logic error: %d n-tuple component(s) were" + " lost", dmp_in_use(mpl->tuples)); + if (dmp_in_use(mpl->arrays) != 0) + error(mpl, "internal logic error: %d array(s) were lost", + dmp_in_use(mpl->arrays)); + if (dmp_in_use(mpl->members) != 0) + error(mpl, "internal logic error: %d array member(s) were lost" + , dmp_in_use(mpl->members)); + if (dmp_in_use(mpl->elemvars) != 0) + error(mpl, "internal logic error: %d elemental variable(s) wer" + "e lost", dmp_in_use(mpl->elemvars)); + if (dmp_in_use(mpl->formulae) != 0) + error(mpl, "internal logic error: %d linear term(s) were lost", + dmp_in_use(mpl->formulae)); + if (dmp_in_use(mpl->elemcons) != 0) + error(mpl, "internal logic error: %d elemental constraint(s) w" + "ere lost", dmp_in_use(mpl->elemcons)); + return; +} + +/**********************************************************************/ +/* * * INPUT/OUTPUT * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- open_input - open input text file. +-- +-- This routine opens the input text file for scanning. */ + +void open_input(MPL *mpl, char *file) +{ mpl->line = 0; + mpl->c = '\n'; + mpl->token = 0; + mpl->imlen = 0; + mpl->image[0] = '\0'; + mpl->value = 0.0; + mpl->b_token = T_EOF; + mpl->b_imlen = 0; + mpl->b_image[0] = '\0'; + mpl->b_value = 0.0; + mpl->f_dots = 0; + mpl->f_scan = 0; + mpl->f_token = 0; + mpl->f_imlen = 0; + mpl->f_image[0] = '\0'; + mpl->f_value = 0.0; + memset(mpl->context, ' ', CONTEXT_SIZE); + mpl->c_ptr = 0; + xassert(mpl->in_fp == NULL); + mpl->in_fp = glp_open(file, "r"); + if (mpl->in_fp == NULL) + error(mpl, "unable to open %s - %s", file, get_err_msg()); + mpl->in_file = file; + /* scan the very first character */ + get_char(mpl); + /* scan the very first token */ + get_token(mpl); + return; +} + +/*---------------------------------------------------------------------- +-- read_char - read next character from input text file. +-- +-- This routine returns a next ASCII character read from the input text +-- file. If the end of file has been reached, EOF is returned. */ + +int read_char(MPL *mpl) +{ int c; + xassert(mpl->in_fp != NULL); + c = glp_getc(mpl->in_fp); + if (c < 0) + { if (glp_ioerr(mpl->in_fp)) + error(mpl, "read error on %s - %s", mpl->in_file, + get_err_msg()); + c = EOF; + } + return c; +} + +/*---------------------------------------------------------------------- +-- close_input - close input text file. +-- +-- This routine closes the input text file. */ + +void close_input(MPL *mpl) +{ xassert(mpl->in_fp != NULL); + glp_close(mpl->in_fp); + mpl->in_fp = NULL; + mpl->in_file = NULL; + return; +} + +/*---------------------------------------------------------------------- +-- open_output - open output text file. +-- +-- This routine opens the output text file for writing data produced by +-- display and printf statements. */ + +void open_output(MPL *mpl, char *file) +{ xassert(mpl->out_fp == NULL); + if (file == NULL) + { file = ""; + mpl->out_fp = (void *)stdout; + } + else + { mpl->out_fp = glp_open(file, "w"); + if (mpl->out_fp == NULL) + error(mpl, "unable to create %s - %s", file, get_err_msg()); + } + mpl->out_file = xmalloc(strlen(file)+1); + strcpy(mpl->out_file, file); + return; +} + +/*---------------------------------------------------------------------- +-- write_char - write next character to output text file. +-- +-- This routine writes an ASCII character to the output text file. */ + +void write_char(MPL *mpl, int c) +{ xassert(mpl->out_fp != NULL); + if (mpl->out_fp == (void *)stdout) + xprintf("%c", c); + else + xfprintf(mpl->out_fp, "%c", c); + return; +} + +/*---------------------------------------------------------------------- +-- write_text - format and write text to output text file. +-- +-- This routine formats a text using the format control string and then +-- writes this text to the output text file. */ + +void write_text(MPL *mpl, char *fmt, ...) +{ va_list arg; + char buf[OUTBUF_SIZE], *c; + va_start(arg, fmt); + vsprintf(buf, fmt, arg); + xassert(strlen(buf) < sizeof(buf)); + va_end(arg); + for (c = buf; *c != '\0'; c++) write_char(mpl, *c); + return; +} + +/*---------------------------------------------------------------------- +-- flush_output - finalize writing data to output text file. +-- +-- This routine finalizes writing data to the output text file. */ + +void flush_output(MPL *mpl) +{ xassert(mpl->out_fp != NULL); + if (mpl->out_fp != (void *)stdout) + { +#if 0 /* FIXME */ + xfflush(mpl->out_fp); +#endif + if (glp_ioerr(mpl->out_fp)) + error(mpl, "write error on %s - %s", mpl->out_file, + get_err_msg()); + } + return; +} + +/**********************************************************************/ +/* * * SOLVER INTERFACE * * */ +/**********************************************************************/ + +/*---------------------------------------------------------------------- +-- error - print error message and terminate model processing. +-- +-- This routine formats and prints an error message and then terminates +-- model processing. */ + +void error(MPL *mpl, char *fmt, ...) +{ va_list arg; + char msg[4095+1]; + va_start(arg, fmt); + vsprintf(msg, fmt, arg); + xassert(strlen(msg) < sizeof(msg)); + va_end(arg); + switch (mpl->phase) + { case 1: + case 2: + /* translation phase */ + xprintf("%s:%d: %s\n", + mpl->in_file == NULL ? "(unknown)" : mpl->in_file, + mpl->line, msg); + print_context(mpl); + break; + case 3: + /* generation/postsolve phase */ + xprintf("%s:%d: %s\n", + mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, + mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); + break; + default: + xassert(mpl != mpl); + } + mpl->phase = 4; + longjmp(mpl->jump, 1); + /* no return */ +} + +/*---------------------------------------------------------------------- +-- warning - print warning message and continue model processing. +-- +-- This routine formats and prints a warning message and returns to the +-- calling program. */ + +void warning(MPL *mpl, char *fmt, ...) +{ va_list arg; + char msg[4095+1]; + va_start(arg, fmt); + vsprintf(msg, fmt, arg); + xassert(strlen(msg) < sizeof(msg)); + va_end(arg); + switch (mpl->phase) + { case 1: + case 2: + /* translation phase */ + xprintf("%s:%d: warning: %s\n", + mpl->in_file == NULL ? "(unknown)" : mpl->in_file, + mpl->line, msg); + break; + case 3: + /* generation/postsolve phase */ + xprintf("%s:%d: warning: %s\n", + mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, + mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); + break; + default: + xassert(mpl != mpl); + } + return; +} + +/*---------------------------------------------------------------------- +-- mpl_initialize - create and initialize translator database. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- MPL *mpl_initialize(void); +-- +-- *Description* +-- +-- The routine mpl_initialize creates and initializes the database used +-- by the GNU MathProg translator. +-- +-- *Returns* +-- +-- The routine returns a pointer to the database created. */ + +MPL *mpl_initialize(void) +{ MPL *mpl; + mpl = xmalloc(sizeof(MPL)); + /* scanning segment */ + mpl->line = 0; + mpl->c = 0; + mpl->token = 0; + mpl->imlen = 0; + mpl->image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->image[0] = '\0'; + mpl->value = 0.0; + mpl->b_token = 0; + mpl->b_imlen = 0; + mpl->b_image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->b_image[0] = '\0'; + mpl->b_value = 0.0; + mpl->f_dots = 0; + mpl->f_scan = 0; + mpl->f_token = 0; + mpl->f_imlen = 0; + mpl->f_image = xcalloc(MAX_LENGTH+1, sizeof(char)); + mpl->f_image[0] = '\0'; + mpl->f_value = 0.0; + mpl->context = xcalloc(CONTEXT_SIZE, sizeof(char)); + memset(mpl->context, ' ', CONTEXT_SIZE); + mpl->c_ptr = 0; + mpl->flag_d = 0; + /* translating segment */ + mpl->pool = dmp_create_poolx(0); + mpl->tree = avl_create_tree(avl_strcmp, NULL); + mpl->model = NULL; + mpl->flag_x = 0; + mpl->as_within = 0; + mpl->as_in = 0; + mpl->as_binary = 0; + mpl->flag_s = 0; + /* common segment */ + mpl->strings = dmp_create_poolx(sizeof(STRING)); + mpl->symbols = dmp_create_poolx(sizeof(SYMBOL)); + mpl->tuples = dmp_create_poolx(sizeof(TUPLE)); + mpl->arrays = dmp_create_poolx(sizeof(ARRAY)); + mpl->members = dmp_create_poolx(sizeof(MEMBER)); + mpl->elemvars = dmp_create_poolx(sizeof(ELEMVAR)); + mpl->formulae = dmp_create_poolx(sizeof(FORMULA)); + mpl->elemcons = dmp_create_poolx(sizeof(ELEMCON)); + mpl->a_list = NULL; + mpl->sym_buf = xcalloc(255+1, sizeof(char)); + mpl->sym_buf[0] = '\0'; + mpl->tup_buf = xcalloc(255+1, sizeof(char)); + mpl->tup_buf[0] = '\0'; + /* generating/postsolving segment */ + mpl->rand = rng_create_rand(); + mpl->flag_p = 0; + mpl->stmt = NULL; +#if 1 /* 11/II-2008 */ + mpl->dca = NULL; +#endif + mpl->m = 0; + mpl->n = 0; + mpl->row = NULL; + mpl->col = NULL; + /* input/output segment */ + mpl->in_fp = NULL; + mpl->in_file = NULL; + mpl->out_fp = NULL; + mpl->out_file = NULL; + mpl->prt_fp = NULL; + mpl->prt_file = NULL; + /* solver interface segment */ + if (setjmp(mpl->jump)) xassert(mpl != mpl); + mpl->phase = 0; + mpl->mod_file = NULL; + mpl->mpl_buf = xcalloc(255+1, sizeof(char)); + mpl->mpl_buf[0] = '\0'; + return mpl; +} + +/*---------------------------------------------------------------------- +-- mpl_read_model - read model section and optional data section. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_read_model(MPL *mpl, char *file, int skip_data); +-- +-- *Description* +-- +-- The routine mpl_read_model reads model section and optionally data +-- section, which may follow the model section, from the text file, +-- whose name is the character string file, performs translating model +-- statements and data blocks, and stores all the information in the +-- translator database. +-- +-- The parameter skip_data is a flag. If the input file contains the +-- data section and this flag is set, the data section is not read as +-- if there were no data section and a warning message is issued. This +-- allows reading the data section from another input file. +-- +-- This routine should be called once after the routine mpl_initialize +-- and before other API routines. +-- +-- *Returns* +-- +-- The routine mpl_read_model returns one the following codes: +-- +-- 1 - translation successful. The input text file contains only model +-- section. In this case the calling program may call the routine +-- mpl_read_data to read data section from another file. +-- 2 - translation successful. The input text file contains both model +-- and data section. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_read_model(MPL *mpl, char *file, int skip_data) +{ if (mpl->phase != 0) + xfault("mpl_read_model: invalid call sequence\n"); + if (file == NULL) + xfault("mpl_read_model: no input filename specified\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* translate model section */ + mpl->phase = 1; + xprintf("Reading model section from %s...\n", file); + open_input(mpl, file); + model_section(mpl); + if (mpl->model == NULL) + error(mpl, "empty model section not allowed"); + /* save name of the input text file containing model section for + error diagnostics during the generation phase */ + mpl->mod_file = xcalloc(strlen(file)+1, sizeof(char)); + strcpy(mpl->mod_file, mpl->in_file); + /* allocate content arrays for all model objects */ + alloc_content(mpl); + /* optional data section may begin with the keyword 'data' */ + if (is_keyword(mpl, "data")) + { if (skip_data) + { warning(mpl, "data section ignored"); + goto skip; + } + mpl->flag_d = 1; + get_token(mpl /* data */); + if (mpl->token != T_SEMICOLON) + error(mpl, "semicolon missing where expected"); + get_token(mpl /* ; */); + /* translate data section */ + mpl->phase = 2; + xprintf("Reading data section from %s...\n", file); + data_section(mpl); + } + /* process end statement */ + end_statement(mpl); +skip: xprintf("%d line%s were read\n", + mpl->line, mpl->line == 1 ? "" : "s"); + close_input(mpl); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_read_data - read data section. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_read_data(MPL *mpl, char *file); +-- +-- *Description* +-- +-- The routine mpl_read_data reads data section from the text file, +-- whose name is the character string file, performs translating data +-- blocks, and stores the data read in the translator database. +-- +-- If this routine is used, it should be called once after the routine +-- mpl_read_model and if the latter returned the code 1. +-- +-- *Returns* +-- +-- The routine mpl_read_data returns one of the following codes: +-- +-- 2 - data section has been successfully processed. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_read_data(MPL *mpl, char *file) +#if 0 /* 02/X-2008 */ +{ if (mpl->phase != 1) +#else +{ if (!(mpl->phase == 1 || mpl->phase == 2)) +#endif + xfault("mpl_read_data: invalid call sequence\n"); + if (file == NULL) + xfault("mpl_read_data: no input filename specified\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* process data section */ + mpl->phase = 2; + xprintf("Reading data section from %s...\n", file); + mpl->flag_d = 1; + open_input(mpl, file); + /* in this case the keyword 'data' is optional */ + if (is_literal(mpl, "data")) + { get_token(mpl /* data */); + if (mpl->token != T_SEMICOLON) + error(mpl, "semicolon missing where expected"); + get_token(mpl /* ; */); + } + data_section(mpl); + /* process end statement */ + end_statement(mpl); + xprintf("%d line%s were read\n", + mpl->line, mpl->line == 1 ? "" : "s"); + close_input(mpl); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_generate - generate model. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_generate(MPL *mpl, char *file); +-- +-- *Description* +-- +-- The routine mpl_generate generates the model using its description +-- stored in the translator database. This phase means generating all +-- variables, constraints, and objectives, executing check and display +-- statements, which precede the solve statement (if it is presented), +-- and building the problem instance. +-- +-- The character string file specifies the name of output text file, to +-- which output produced by display statements should be written. It is +-- allowed to specify NULL, in which case the output goes to stdout via +-- the routine print. +-- +-- This routine should be called once after the routine mpl_read_model +-- or mpl_read_data and if one of the latters returned the code 2. +-- +-- *Returns* +-- +-- The routine mpl_generate returns one of the following codes: +-- +-- 3 - model has been successfully generated. In this case the calling +-- program may call other api routines to obtain components of the +-- problem instance from the translator database. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_generate(MPL *mpl, char *file) +{ if (!(mpl->phase == 1 || mpl->phase == 2)) + xfault("mpl_generate: invalid call sequence\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* generate model */ + mpl->phase = 3; + open_output(mpl, file); + generate_model(mpl); + flush_output(mpl); + /* build problem instance */ + build_problem(mpl); + /* generation phase has been finished */ + xprintf("Model has been successfully generated\n"); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_get_prob_name - obtain problem (model) name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_prob_name(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_prob_name returns a pointer to internal buffer, +-- which contains symbolic name of the problem (model). +-- +-- *Note* +-- +-- Currently MathProg has no feature to assign a symbolic name to the +-- model. Therefore the routine mpl_get_prob_name tries to construct +-- such name using the name of input text file containing model section, +-- although this is not a good idea (due to portability problems). */ + +char *mpl_get_prob_name(MPL *mpl) +{ char *name = mpl->mpl_buf; + char *file = mpl->mod_file; + int k; + if (mpl->phase != 3) + xfault("mpl_get_prob_name: invalid call sequence\n"); + for (;;) + { if (strchr(file, '/') != NULL) + file = strchr(file, '/') + 1; + else if (strchr(file, '\\') != NULL) + file = strchr(file, '\\') + 1; + else if (strchr(file, ':') != NULL) + file = strchr(file, ':') + 1; + else + break; + } + for (k = 0; ; k++) + { if (k == 255) break; + if (!(isalnum((unsigned char)*file) || *file == '_')) break; + name[k] = *file++; + } + if (k == 0) + strcpy(name, "Unknown"); + else + name[k] = '\0'; + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_num_rows - determine number of rows. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_num_rows(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_num_rows returns total number of rows in the +-- problem, where each row is an individual constraint or objective. */ + +int mpl_get_num_rows(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_get_num_rows: invalid call sequence\n"); + return mpl->m; +} + +/*---------------------------------------------------------------------- +-- mpl_get_num_cols - determine number of columns. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_num_cols(MPL *mpl); +-- +-- *Returns* +-- +-- The routine mpl_get_num_cols returns total number of columns in the +-- problem, where each column is an individual variable. */ + +int mpl_get_num_cols(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_get_num_cols: invalid call sequence\n"); + return mpl->n; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_name - obtain row name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_row_name(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_name returns a pointer to internal buffer, +-- which contains symbolic name of i-th row of the problem. */ + +char *mpl_get_row_name(MPL *mpl, int i) +{ char *name = mpl->mpl_buf, *t; + int len; + if (mpl->phase != 3) + xfault("mpl_get_row_name: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_name: i = %d; row number out of range\n", + i); + strcpy(name, mpl->row[i]->con->name); + len = strlen(name); + xassert(len <= 255); + t = format_tuple(mpl, '[', mpl->row[i]->memb->tuple); + while (*t) + { if (len == 255) break; + name[len++] = *t++; + } + name[len] = '\0'; + if (len == 255) strcpy(name+252, "..."); + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_kind - determine row kind. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_row_kind(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_kind returns the kind of i-th row, which can +-- be one of the following: +-- +-- MPL_ST - non-free (constraint) row; +-- MPL_MIN - free (objective) row to be minimized; +-- MPL_MAX - free (objective) row to be maximized. */ + +int mpl_get_row_kind(MPL *mpl, int i) +{ int kind; + if (mpl->phase != 3) + xfault("mpl_get_row_kind: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_kind: i = %d; row number out of range\n", + i); + switch (mpl->row[i]->con->type) + { case A_CONSTRAINT: + kind = MPL_ST; break; + case A_MINIMIZE: + kind = MPL_MIN; break; + case A_MAXIMIZE: + kind = MPL_MAX; break; + default: + xassert(mpl != mpl); + } + return kind; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_bnds - obtain row bounds. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); +-- +-- *Description* +-- +-- The routine mpl_get_row_bnds stores lower and upper bounds of i-th +-- row of the problem to the locations, which the parameters lb and ub +-- point to, respectively. Besides the routine returns the type of the +-- i-th row. +-- +-- If some of the parameters lb and ub is NULL, the corresponding bound +-- value is not stored. +-- +-- Types and bounds have the following meaning: +-- +-- Type Bounds Note +-- ----------------------------------------------------------- +-- MPL_FR -inf < f(x) < +inf Free linear form +-- MPL_LO lb <= f(x) < +inf Inequality f(x) >= lb +-- MPL_UP -inf < f(x) <= ub Inequality f(x) <= ub +-- MPL_DB lb <= f(x) <= ub Inequality lb <= f(x) <= ub +-- MPL_FX f(x) = lb Equality f(x) = lb +-- +-- where f(x) is the corresponding linear form of the i-th row. +-- +-- If the row has no lower bound, *lb is set to zero; if the row has +-- no upper bound, *ub is set to zero; and if the row is of fixed type, +-- both *lb and *ub are set to the same value. +-- +-- *Returns* +-- +-- The routine returns the type of the i-th row as it is stated in the +-- table above. */ + +int mpl_get_row_bnds(MPL *mpl, int i, double *_lb, double *_ub) +{ ELEMCON *con; + int type; + double lb, ub; + if (mpl->phase != 3) + xfault("mpl_get_row_bnds: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_bnds: i = %d; row number out of range\n", + i); + con = mpl->row[i]; +#if 0 /* 21/VII-2006 */ + if (con->con->lbnd == NULL && con->con->ubnd == NULL) + type = MPL_FR, lb = ub = 0.0; + else if (con->con->ubnd == NULL) + type = MPL_LO, lb = con->lbnd, ub = 0.0; + else if (con->con->lbnd == NULL) + type = MPL_UP, lb = 0.0, ub = con->ubnd; + else if (con->con->lbnd != con->con->ubnd) + type = MPL_DB, lb = con->lbnd, ub = con->ubnd; + else + type = MPL_FX, lb = ub = con->lbnd; +#else + lb = (con->con->lbnd == NULL ? -DBL_MAX : con->lbnd); + ub = (con->con->ubnd == NULL ? +DBL_MAX : con->ubnd); + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = MPL_FR, lb = ub = 0.0; + else if (ub == +DBL_MAX) + type = MPL_LO, ub = 0.0; + else if (lb == -DBL_MAX) + type = MPL_UP, lb = 0.0; + else if (con->con->lbnd != con->con->ubnd) + type = MPL_DB; + else + type = MPL_FX; +#endif + if (_lb != NULL) *_lb = lb; + if (_ub != NULL) *_ub = ub; + return type; +} + +/*---------------------------------------------------------------------- +-- mpl_get_mat_row - obtain row of the constraint matrix. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); +-- +-- *Description* +-- +-- The routine mpl_get_mat_row stores column indices and numeric values +-- of constraint coefficients for the i-th row to locations ndx[1], ..., +-- ndx[len] and val[1], ..., val[len], respectively, where 0 <= len <= n +-- is number of (structural) non-zero constraint coefficients, and n is +-- number of columns in the problem. +-- +-- If the parameter ndx is NULL, column indices are not stored. If the +-- parameter val is NULL, numeric values are not stored. +-- +-- Note that free rows may have constant terms, which are not part of +-- the constraint matrix and therefore not reported by this routine. The +-- constant term of a particular row can be obtained, if necessary, via +-- the routine mpl_get_row_c0. +-- +-- *Returns* +-- +-- The routine mpl_get_mat_row returns len, which is length of i-th row +-- of the constraint matrix (i.e. number of non-zero coefficients). */ + +int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]) +{ FORMULA *term; + int len = 0; + if (mpl->phase != 3) + xfault("mpl_get_mat_row: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_mat_row: i = %d; row number out of range\n", + i); + for (term = mpl->row[i]->form; term != NULL; term = term->next) + { xassert(term->var != NULL); + len++; + xassert(len <= mpl->n); + if (ndx != NULL) ndx[len] = term->var->j; + if (val != NULL) val[len] = term->coef; + } + return len; +} + +/*---------------------------------------------------------------------- +-- mpl_get_row_c0 - obtain constant term of free row. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- double mpl_get_row_c0(MPL *mpl, int i); +-- +-- *Returns* +-- +-- The routine mpl_get_row_c0 returns numeric value of constant term of +-- i-th row. +-- +-- Note that only free rows may have non-zero constant terms. Therefore +-- if i-th row is not free, the routine returns zero. */ + +double mpl_get_row_c0(MPL *mpl, int i) +{ ELEMCON *con; + double c0; + if (mpl->phase != 3) + xfault("mpl_get_row_c0: invalid call sequence\n"); + if (!(1 <= i && i <= mpl->m)) + xfault("mpl_get_row_c0: i = %d; row number out of range\n", + i); + con = mpl->row[i]; + if (con->con->lbnd == NULL && con->con->ubnd == NULL) + c0 = - con->lbnd; + else + c0 = 0.0; + return c0; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_name - obtain column name. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- char *mpl_get_col_name(MPL *mpl, int j); +-- +-- *Returns* +-- +-- The routine mpl_get_col_name returns a pointer to internal buffer, +-- which contains symbolic name of j-th column of the problem. */ + +char *mpl_get_col_name(MPL *mpl, int j) +{ char *name = mpl->mpl_buf, *t; + int len; + if (mpl->phase != 3) + xfault("mpl_get_col_name: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_name: j = %d; column number out of range\n" + , j); + strcpy(name, mpl->col[j]->var->name); + len = strlen(name); + xassert(len <= 255); + t = format_tuple(mpl, '[', mpl->col[j]->memb->tuple); + while (*t) + { if (len == 255) break; + name[len++] = *t++; + } + name[len] = '\0'; + if (len == 255) strcpy(name+252, "..."); + xassert(strlen(name) <= 255); + return name; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_kind - determine column kind. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_col_kind(MPL *mpl, int j); +-- +-- *Returns* +-- +-- The routine mpl_get_col_kind returns the kind of j-th column, which +-- can be one of the following: +-- +-- MPL_NUM - continuous variable; +-- MPL_INT - integer variable; +-- MPL_BIN - binary variable. +-- +-- Note that column kinds are defined independently on type and bounds +-- (reported by the routine mpl_get_col_bnds) of corresponding columns. +-- This means, in particular, that bounds of an integer column may be +-- fractional, or a binary column may have lower and upper bounds that +-- are not 0 and 1 (or it may have no lower/upper bound at all). */ + +int mpl_get_col_kind(MPL *mpl, int j) +{ int kind; + if (mpl->phase != 3) + xfault("mpl_get_col_kind: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_kind: j = %d; column number out of range\n" + , j); + switch (mpl->col[j]->var->type) + { case A_NUMERIC: + kind = MPL_NUM; break; + case A_INTEGER: + kind = MPL_INT; break; + case A_BINARY: + kind = MPL_BIN; break; + default: + xassert(mpl != mpl); + } + return kind; +} + +/*---------------------------------------------------------------------- +-- mpl_get_col_bnds - obtain column bounds. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); +-- +-- *Description* +-- +-- The routine mpl_get_col_bnds stores lower and upper bound of j-th +-- column of the problem to the locations, which the parameters lb and +-- ub point to, respectively. Besides the routine returns the type of +-- the j-th column. +-- +-- If some of the parameters lb and ub is NULL, the corresponding bound +-- value is not stored. +-- +-- Types and bounds have the following meaning: +-- +-- Type Bounds Note +-- ------------------------------------------------------ +-- MPL_FR -inf < x < +inf Free (unbounded) variable +-- MPL_LO lb <= x < +inf Variable with lower bound +-- MPL_UP -inf < x <= ub Variable with upper bound +-- MPL_DB lb <= x <= ub Double-bounded variable +-- MPL_FX x = lb Fixed variable +-- +-- where x is individual variable corresponding to the j-th column. +-- +-- If the column has no lower bound, *lb is set to zero; if the column +-- has no upper bound, *ub is set to zero; and if the column is of fixed +-- type, both *lb and *ub are set to the same value. +-- +-- *Returns* +-- +-- The routine returns the type of the j-th column as it is stated in +-- the table above. */ + +int mpl_get_col_bnds(MPL *mpl, int j, double *_lb, double *_ub) +{ ELEMVAR *var; + int type; + double lb, ub; + if (mpl->phase != 3) + xfault("mpl_get_col_bnds: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault("mpl_get_col_bnds: j = %d; column number out of range\n" + , j); + var = mpl->col[j]; +#if 0 /* 21/VII-2006 */ + if (var->var->lbnd == NULL && var->var->ubnd == NULL) + type = MPL_FR, lb = ub = 0.0; + else if (var->var->ubnd == NULL) + type = MPL_LO, lb = var->lbnd, ub = 0.0; + else if (var->var->lbnd == NULL) + type = MPL_UP, lb = 0.0, ub = var->ubnd; + else if (var->var->lbnd != var->var->ubnd) + type = MPL_DB, lb = var->lbnd, ub = var->ubnd; + else + type = MPL_FX, lb = ub = var->lbnd; +#else + lb = (var->var->lbnd == NULL ? -DBL_MAX : var->lbnd); + ub = (var->var->ubnd == NULL ? +DBL_MAX : var->ubnd); + if (lb == -DBL_MAX && ub == +DBL_MAX) + type = MPL_FR, lb = ub = 0.0; + else if (ub == +DBL_MAX) + type = MPL_LO, ub = 0.0; + else if (lb == -DBL_MAX) + type = MPL_UP, lb = 0.0; + else if (var->var->lbnd != var->var->ubnd) + type = MPL_DB; + else + type = MPL_FX; +#endif + if (_lb != NULL) *_lb = lb; + if (_ub != NULL) *_ub = ub; + return type; +} + +/*---------------------------------------------------------------------- +-- mpl_has_solve_stmt - check if model has solve statement. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_has_solve_stmt(MPL *mpl); +-- +-- *Returns* +-- +-- If the model has the solve statement, the routine returns non-zero, +-- otherwise zero is returned. */ + +int mpl_has_solve_stmt(MPL *mpl) +{ if (mpl->phase != 3) + xfault("mpl_has_solve_stmt: invalid call sequence\n"); + return mpl->flag_s; +} + +#if 1 /* 15/V-2010 */ +void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, + double dual) +{ /* store row (constraint/objective) solution components */ + xassert(mpl->phase == 3); + xassert(1 <= i && i <= mpl->m); + mpl->row[i]->stat = stat; + mpl->row[i]->prim = prim; + mpl->row[i]->dual = dual; + return; +} +#endif + +#if 1 /* 15/V-2010 */ +void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, + double dual) +{ /* store column (variable) solution components */ + xassert(mpl->phase == 3); + xassert(1 <= j && j <= mpl->n); + mpl->col[j]->stat = stat; + mpl->col[j]->prim = prim; + mpl->col[j]->dual = dual; + return; +} +#endif + +#if 0 /* 15/V-2010 */ +/*---------------------------------------------------------------------- +-- mpl_put_col_value - store column value. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- void mpl_put_col_value(MPL *mpl, int j, double val); +-- +-- *Description* +-- +-- The routine mpl_put_col_value stores numeric value of j-th column +-- into the translator database. It is assumed that the column value is +-- provided by the solver. */ + +void mpl_put_col_value(MPL *mpl, int j, double val) +{ if (mpl->phase != 3) + xfault("mpl_put_col_value: invalid call sequence\n"); + if (!(1 <= j && j <= mpl->n)) + xfault( + "mpl_put_col_value: j = %d; column number out of range\n", j); + mpl->col[j]->prim = val; + return; +} +#endif + +/*---------------------------------------------------------------------- +-- mpl_postsolve - postsolve model. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- int mpl_postsolve(MPL *mpl); +-- +-- *Description* +-- +-- The routine mpl_postsolve performs postsolving of the model using +-- its description stored in the translator database. This phase means +-- executing statements, which follow the solve statement. +-- +-- If this routine is used, it should be called once after the routine +-- mpl_generate and if the latter returned the code 3. +-- +-- *Returns* +-- +-- The routine mpl_postsolve returns one of the following codes: +-- +-- 3 - model has been successfully postsolved. +-- 4 - processing failed due to some errors. In this case the calling +-- program should call the routine mpl_terminate to terminate model +-- processing. */ + +int mpl_postsolve(MPL *mpl) +{ if (!(mpl->phase == 3 && !mpl->flag_p)) + xfault("mpl_postsolve: invalid call sequence\n"); + /* set up error handler */ + if (setjmp(mpl->jump)) goto done; + /* perform postsolving */ + postsolve_model(mpl); + flush_output(mpl); + /* postsolving phase has been finished */ + xprintf("Model has been successfully processed\n"); +done: /* return to the calling program */ + return mpl->phase; +} + +/*---------------------------------------------------------------------- +-- mpl_terminate - free all resources used by translator. +-- +-- *Synopsis* +-- +-- #include "glpmpl.h" +-- void mpl_terminate(MPL *mpl); +-- +-- *Description* +-- +-- The routine mpl_terminate frees all the resources used by the GNU +-- MathProg translator. */ + +void mpl_terminate(MPL *mpl) +{ if (setjmp(mpl->jump)) xassert(mpl != mpl); + switch (mpl->phase) + { case 0: + case 1: + case 2: + case 3: + /* there were no errors; clean the model content */ + clean_model(mpl); + xassert(mpl->a_list == NULL); +#if 1 /* 11/II-2008 */ + xassert(mpl->dca == NULL); +#endif + break; + case 4: + /* model processing has been finished due to error; delete + search trees, which may be created for some arrays */ + { ARRAY *a; + for (a = mpl->a_list; a != NULL; a = a->next) + if (a->tree != NULL) avl_delete_tree(a->tree); + } +#if 1 /* 11/II-2008 */ + free_dca(mpl); +#endif + break; + default: + xassert(mpl != mpl); + } + /* delete the translator database */ + xfree(mpl->image); + xfree(mpl->b_image); + xfree(mpl->f_image); + xfree(mpl->context); + dmp_delete_pool(mpl->pool); + avl_delete_tree(mpl->tree); + dmp_delete_pool(mpl->strings); + dmp_delete_pool(mpl->symbols); + dmp_delete_pool(mpl->tuples); + dmp_delete_pool(mpl->arrays); + dmp_delete_pool(mpl->members); + dmp_delete_pool(mpl->elemvars); + dmp_delete_pool(mpl->formulae); + dmp_delete_pool(mpl->elemcons); + xfree(mpl->sym_buf); + xfree(mpl->tup_buf); + rng_delete_rand(mpl->rand); + if (mpl->row != NULL) xfree(mpl->row); + if (mpl->col != NULL) xfree(mpl->col); + if (mpl->in_fp != NULL) glp_close(mpl->in_fp); + if (mpl->out_fp != NULL && mpl->out_fp != (void *)stdout) + glp_close(mpl->out_fp); + if (mpl->out_file != NULL) xfree(mpl->out_file); + if (mpl->prt_fp != NULL) glp_close(mpl->prt_fp); + if (mpl->prt_file != NULL) xfree(mpl->prt_file); + if (mpl->mod_file != NULL) xfree(mpl->mod_file); + xfree(mpl->mpl_buf); + xfree(mpl); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl5.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl5.c new file mode 100644 index 000000000..c5374c9c6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl5.c @@ -0,0 +1,566 @@ +/* mpl5.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Authors: Andrew Makhorin +* Heinrich Schuchardt +* +* Copyright (C) 2003-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#if 1 /* 11/VI-2013 */ +#include "jd.h" +#endif +#include "mpl.h" + +double fn_gmtime(MPL *mpl) +{ /* obtain the current calendar time (UTC) */ + time_t timer; + struct tm *tm; + int j; + time(&timer); + if (timer == (time_t)(-1)) +err: error(mpl, "gmtime(); unable to obtain current calendar time"); +#if 0 /* 29/I-2017 */ + tm = gmtime(&timer); +#else + tm = xgmtime(&timer); +#endif + if (tm == NULL) goto err; + j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); + if (j < 0) goto err; + return (((double)(j - jday(1, 1, 1970)) * 24.0 + + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + + (double)tm->tm_sec; +} + +static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday", "Sunday" }; + +static char *moon[] = { "January", "February", "March", "April", "May", + "June", "July", "August", "September", "October", "November", + "December" }; + +static void error1(MPL *mpl, const char *str, const char *s, + const char *fmt, const char *f, const char *msg) +{ xprintf("Input string passed to str2time:\n"); + xprintf("%s\n", str); + xprintf("%*s\n", (s - str) + 1, "^"); + xprintf("Format string passed to str2time:\n"); + xprintf("%s\n", fmt); + xprintf("%*s\n", (f - fmt) + 1, "^"); + error(mpl, "%s", msg); + /* no return */ +} + +double fn_str2time(MPL *mpl, const char *str, const char *fmt) +{ /* convert character string to the calendar time */ + int j, year, month, day, hh, mm, ss, zone; + const char *s, *f; + year = month = day = hh = mm = ss = -1, zone = INT_MAX; + s = str; + for (f = fmt; *f != '\0'; f++) + { if (*f == '%') + { f++; + if (*f == 'b' || *f == 'h') + { /* the abbreviated month name */ + int k; + char *name; + if (month >= 0) + error1(mpl, str, s, fmt, f, "month multiply specified" + ); + while (*s == ' ') s++; + for (month = 1; month <= 12; month++) + { name = moon[month-1]; + for (k = 0; k <= 2; k++) + { if (toupper((unsigned char)s[k]) != + toupper((unsigned char)name[k])) goto next; + } + s += 3; + for (k = 3; name[k] != '\0'; k++) + { if (toupper((unsigned char)*s) != + toupper((unsigned char)name[k])) break; + s++; + } + break; +next: ; + } + if (month > 12) + error1(mpl, str, s, fmt, f, "abbreviated month name m" + "issing or invalid"); + } + else if (*f == 'd') + { /* the day of the month as a decimal number (01..31) */ + if (day >= 0) + error1(mpl, str, s, fmt, f, "day multiply specified"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "day missing or invalid"); + day = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + day = 10 * day + ((*s++) - '0'); + if (!(1 <= day && day <= 31)) + error1(mpl, str, s, fmt, f, "day out of range"); + } + else if (*f == 'H') + { /* the hour as a decimal number, using a 24-hour clock + (00..23) */ + if (hh >= 0) + error1(mpl, str, s, fmt, f, "hour multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "hour missing or invalid") + ; + hh = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + hh = 10 * hh + ((*s++) - '0'); + if (!(0 <= hh && hh <= 23)) + error1(mpl, str, s, fmt, f, "hour out of range"); + } + else if (*f == 'm') + { /* the month as a decimal number (01..12) */ + if (month >= 0) + error1(mpl, str, s, fmt, f, "month multiply specified" + ); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "month missing or invalid" + ); + month = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + month = 10 * month + ((*s++) - '0'); + if (!(1 <= month && month <= 12)) + error1(mpl, str, s, fmt, f, "month out of range"); + } + else if (*f == 'M') + { /* the minute as a decimal number (00..59) */ + if (mm >= 0) + error1(mpl, str, s, fmt, f, "minute multiply specifie" + "d"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "minute missing or invali" + "d"); + mm = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + mm = 10 * mm + ((*s++) - '0'); + if (!(0 <= mm && mm <= 59)) + error1(mpl, str, s, fmt, f, "minute out of range"); + } + else if (*f == 'S') + { /* the second as a decimal number (00..60) */ + if (ss >= 0) + error1(mpl, str, s, fmt, f, "second multiply specifie" + "d"); + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "second missing or invali" + "d"); + ss = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + ss = 10 * ss + ((*s++) - '0'); + if (!(0 <= ss && ss <= 60)) + error1(mpl, str, s, fmt, f, "second out of range"); + } + else if (*f == 'y') + { /* the year without a century as a decimal number + (00..99); the values 00 to 68 mean the years 2000 to + 2068 while the values 69 to 99 mean the years 1969 to + 1999 */ + if (year >= 0) + error1(mpl, str, s, fmt, f, "year multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "year missing or invalid") + ; + year = (*s++) - '0'; + if ('0' <= *s && *s <= '9') + year = 10 * year + ((*s++) - '0'); + year += (year >= 69 ? 1900 : 2000); + } + else if (*f == 'Y') + { /* the year as a decimal number, using the Gregorian + calendar */ + if (year >= 0) + error1(mpl, str, s, fmt, f, "year multiply specified") + ; + while (*s == ' ') s++; + if (!('0' <= *s && *s <= '9')) + error1(mpl, str, s, fmt, f, "year missing or invalid") + ; + year = 0; + for (j = 1; j <= 4; j++) + { if (!('0' <= *s && *s <= '9')) break; + year = 10 * year + ((*s++) - '0'); + } + if (!(1 <= year && year <= 4000)) + error1(mpl, str, s, fmt, f, "year out of range"); + } + else if (*f == 'z') + { /* time zone offset in the form zhhmm */ + int z, hh, mm; + if (zone != INT_MAX) + error1(mpl, str, s, fmt, f, "time zone offset multipl" + "y specified"); + while (*s == ' ') s++; + if (*s == 'Z') + { z = hh = mm = 0, s++; + goto skip; + } + if (*s == '+') + z = +1, s++; + else if (*s == '-') + z = -1, s++; + else + error1(mpl, str, s, fmt, f, "time zone offset sign mi" + "ssing"); + hh = 0; + for (j = 1; j <= 2; j++) + { if (!('0' <= *s && *s <= '9')) +err1: error1(mpl, str, s, fmt, f, "time zone offset valu" + "e incomplete or invalid"); + hh = 10 * hh + ((*s++) - '0'); + } + if (hh > 23) +err2: error1(mpl, str, s, fmt, f, "time zone offset value o" + "ut of range"); + if (*s == ':') + { s++; + if (!('0' <= *s && *s <= '9')) goto err1; + } + mm = 0; + if (!('0' <= *s && *s <= '9')) goto skip; + for (j = 1; j <= 2; j++) + { if (!('0' <= *s && *s <= '9')) goto err1; + mm = 10 * mm + ((*s++) - '0'); + } + if (mm > 59) goto err2; +skip: zone = z * (60 * hh + mm); + } + else if (*f == '%') + { /* literal % character */ + goto test; + } + else + error1(mpl, str, s, fmt, f, "invalid conversion specifie" + "r"); + } + else if (*f == ' ') + ; + else +test: { /* check a matching character in the input string */ + if (*s != *f) + error1(mpl, str, s, fmt, f, "character mismatch"); + s++; + } + } + if (year < 0) year = 1970; + if (month < 0) month = 1; + if (day < 0) day = 1; + if (hh < 0) hh = 0; + if (mm < 0) mm = 0; + if (ss < 0) ss = 0; + if (zone == INT_MAX) zone = 0; + j = jday(day, month, year); + xassert(j >= 0); + return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)hh) * + 60.0 + (double)mm) * 60.0 + (double)ss - 60.0 * (double)zone; +} + +static void error2(MPL *mpl, const char *fmt, const char *f, + const char *msg) +{ xprintf("Format string passed to time2str:\n"); + xprintf("%s\n", fmt); + xprintf("%*s\n", (f - fmt) + 1, "^"); + error(mpl, "%s", msg); + /* no return */ +} + +static int weekday(int j) +{ /* determine weekday number (1 = Mon, ..., 7 = Sun) */ + return (j + jday(1, 1, 1970)) % 7 + 1; +} + +static int firstday(int year) +{ /* determine the first day of the first week for a specified year + according to ISO 8601 */ + int j; + /* if 1 January is Monday, Tuesday, Wednesday or Thursday, it is + in week 01; if 1 January is Friday, Saturday or Sunday, it is + in week 52 or 53 of the previous year */ + j = jday(1, 1, year) - jday(1, 1, 1970); + switch (weekday(j)) + { case 1: /* 1 Jan is Mon */ j += 0; break; + case 2: /* 1 Jan is Tue */ j -= 1; break; + case 3: /* 1 Jan is Wed */ j -= 2; break; + case 4: /* 1 Jan is Thu */ j -= 3; break; + case 5: /* 1 Jan is Fri */ j += 3; break; + case 6: /* 1 Jan is Sat */ j += 2; break; + case 7: /* 1 Jan is Sun */ j += 1; break; + default: xassert(j != j); + } + /* the first day of the week must be Monday */ + xassert(weekday(j) == 1); + return j; +} + +void fn_time2str(MPL *mpl, char *str, double t, const char *fmt) +{ /* convert the calendar time to character string */ + int j, year, month, day, hh, mm, ss, len; + double temp; + const char *f; + char buf[MAX_LENGTH+1]; + if (!(-62135596800.0 <= t && t <= 64092211199.0)) + error(mpl, "time2str(%.*g,...); argument out of range", + DBL_DIG, t); + t = floor(t + 0.5); + temp = fabs(t) / 86400.0; + j = (int)floor(temp); + if (t < 0.0) + { if (temp == floor(temp)) + j = - j; + else + j = - (j + 1); + } + xassert(jdate(j + jday(1, 1, 1970), &day, &month, &year) == 0); + ss = (int)(t - 86400.0 * (double)j); + xassert(0 <= ss && ss < 86400); + mm = ss / 60, ss %= 60; + hh = mm / 60, mm %= 60; + len = 0; + for (f = fmt; *f != '\0'; f++) + { if (*f == '%') + { f++; + if (*f == 'a') + { /* the abbreviated weekday name */ + memcpy(buf, week[weekday(j)-1], 3), buf[3] = '\0'; + } + else if (*f == 'A') + { /* the full weekday name */ + strcpy(buf, week[weekday(j)-1]); + } + else if (*f == 'b' || *f == 'h') + { /* the abbreviated month name */ + memcpy(buf, moon[month-1], 3), buf[3] = '\0'; + } + else if (*f == 'B') + { /* the full month name */ + strcpy(buf, moon[month-1]); + } + else if (*f == 'C') + { /* the century of the year */ + sprintf(buf, "%02d", year / 100); + } + else if (*f == 'd') + { /* the day of the month as a decimal number (01..31) */ + sprintf(buf, "%02d", day); + } + else if (*f == 'D') + { /* the date using the format %m/%d/%y */ + sprintf(buf, "%02d/%02d/%02d", month, day, year % 100); + } + else if (*f == 'e') + { /* the day of the month like with %d, but padded with + blank (1..31) */ + sprintf(buf, "%2d", day); + } + else if (*f == 'F') + { /* the date using the format %Y-%m-%d */ + sprintf(buf, "%04d-%02d-%02d", year, month, day); + } + else if (*f == 'g') + { /* the year corresponding to the ISO week number, but + without the century (range 00 through 99); this has + the same format and value as %y, except that if the + ISO week number (see %V) belongs to the previous or + next year, that year is used instead */ + int iso; + if (j < firstday(year)) + iso = year - 1; + else if (j < firstday(year + 1)) + iso = year; + else + iso = year + 1; + sprintf(buf, "%02d", iso % 100); + } + else if (*f == 'G') + { /* the year corresponding to the ISO week number; this + has the same format and value as %Y, excepth that if + the ISO week number (see %V) belongs to the previous + or next year, that year is used instead */ + int iso; + if (j < firstday(year)) + iso = year - 1; + else if (j < firstday(year + 1)) + iso = year; + else + iso = year + 1; + sprintf(buf, "%04d", iso); + } + else if (*f == 'H') + { /* the hour as a decimal number, using a 24-hour clock + (00..23) */ + sprintf(buf, "%02d", hh); + } + else if (*f == 'I') + { /* the hour as a decimal number, using a 12-hour clock + (01..12) */ + sprintf(buf, "%02d", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); + } + else if (*f == 'j') + { /* the day of the year as a decimal number (001..366) */ + sprintf(buf, "%03d", + jday(day, month, year) - jday(1, 1, year) + 1); + } + else if (*f == 'k') + { /* the hour as a decimal number, using a 24-hour clock + like %H, but padded with blank (0..23) */ + sprintf(buf, "%2d", hh); + } + else if (*f == 'l') + { /* the hour as a decimal number, using a 12-hour clock + like %I, but padded with blank (1..12) */ + sprintf(buf, "%2d", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); + } + else if (*f == 'm') + { /* the month as a decimal number (01..12) */ + sprintf(buf, "%02d", month); + } + else if (*f == 'M') + { /* the minute as a decimal number (00..59) */ + sprintf(buf, "%02d", mm); + } + else if (*f == 'p') + { /* either AM or PM, according to the given time value; + noon is treated as PM and midnight as AM */ + strcpy(buf, hh <= 11 ? "AM" : "PM"); + } + else if (*f == 'P') + { /* either am or pm, according to the given time value; + noon is treated as pm and midnight as am */ + strcpy(buf, hh <= 11 ? "am" : "pm"); + } + else if (*f == 'r') + { /* the calendar time using the format %I:%M:%S %p */ + sprintf(buf, "%02d:%02d:%02d %s", + hh == 0 ? 12 : hh <= 12 ? hh : hh - 12, + mm, ss, hh <= 11 ? "AM" : "PM"); + } + else if (*f == 'R') + { /* the hour and minute using the format %H:%M */ + sprintf(buf, "%02d:%02d", hh, mm); + } + else if (*f == 'S') + { /* the second as a decimal number (00..59) */ + sprintf(buf, "%02d", ss); + } + else if (*f == 'T') + { /* the time of day using the format %H:%M:%S */ + sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); + } + else if (*f == 'u') + { /* the day of the week as a decimal number (1..7), + Monday being 1 */ + sprintf(buf, "%d", weekday(j)); + } + else if (*f == 'U') + { /* the week number of the current year as a decimal + number (range 00 through 53), starting with the first + Sunday as the first day of the first week; days + preceding the first Sunday in the year are considered + to be in week 00 */ +#if 1 /* 09/I-2009 */ +#undef sun +/* causes compilation error in SunOS */ +#endif + int sun; + /* sun = the first Sunday of the year */ + sun = jday(1, 1, year) - jday(1, 1, 1970); + sun += (7 - weekday(sun)); + sprintf(buf, "%02d", (j + 7 - sun) / 7); + } + else if (*f == 'V') + { /* the ISO week number as a decimal number (range 01 + through 53); ISO weeks start with Monday and end with + Sunday; week 01 of a year is the first week which has + the majority of its days in that year; week 01 of + a year can contain days from the previous year; the + week before week 01 of a year is the last week (52 or + 53) of the previous year even if it contains days + from the new year */ + int iso; + if (j < firstday(year)) + iso = j - firstday(year - 1); + else if (j < firstday(year + 1)) + iso = j - firstday(year); + else + iso = j - firstday(year + 1); + sprintf(buf, "%02d", iso / 7 + 1); + } + else if (*f == 'w') + { /* the day of the week as a decimal number (0..6), + Sunday being 0 */ + sprintf(buf, "%d", weekday(j) % 7); + } + else if (*f == 'W') + { /* the week number of the current year as a decimal + number (range 00 through 53), starting with the first + Monday as the first day of the first week; days + preceding the first Monday in the year are considered + to be in week 00 */ + int mon; + /* mon = the first Monday of the year */ + mon = jday(1, 1, year) - jday(1, 1, 1970); + mon += (8 - weekday(mon)) % 7; + sprintf(buf, "%02d", (j + 7 - mon) / 7); + } + else if (*f == 'y') + { /* the year without a century as a decimal number + (00..99) */ + sprintf(buf, "%02d", year % 100); + } + else if (*f == 'Y') + { /* the year as a decimal number, using the Gregorian + calendar */ + sprintf(buf, "%04d", year); + } + else if (*f == '%') + { /* a literal % character */ + buf[0] = '%', buf[1] = '\0'; + } + else + error2(mpl, fmt, f, "invalid conversion specifier"); + } + else + buf[0] = *f, buf[1] = '\0'; + if (len + strlen(buf) > MAX_LENGTH) + error(mpl, "time2str; output string length exceeds %d chara" + "cters", MAX_LENGTH); + memcpy(str+len, buf, strlen(buf)); + len += strlen(buf); + } + str[len] = '\0'; + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl6.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl6.c new file mode 100644 index 000000000..ac2a03930 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mpl6.c @@ -0,0 +1,1039 @@ +/* mpl6.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2003-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "mpl.h" +#include "mplsql.h" + +/**********************************************************************/ + +#define CSV_FIELD_MAX 50 +/* maximal number of fields in record */ + +#define CSV_FDLEN_MAX 100 +/* maximal field length */ + +struct csv +{ /* comma-separated values file */ + int mode; + /* 'R' = reading; 'W' = writing */ + char *fname; + /* name of csv file */ + FILE *fp; + /* stream assigned to csv file */ + jmp_buf jump; + /* address for non-local go to in case of error */ + int count; + /* record count */ + /*--------------------------------------------------------------*/ + /* used only for input csv file */ + int c; + /* current character or EOF */ + int what; + /* current marker: */ +#define CSV_EOF 0 /* end-of-file */ +#define CSV_EOR 1 /* end-of-record */ +#define CSV_NUM 2 /* floating-point number */ +#define CSV_STR 3 /* character string */ + char field[CSV_FDLEN_MAX+1]; + /* current field just read */ + int nf; + /* number of fields in the csv file */ + int ref[1+CSV_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ +#if 1 /* 01/VI-2010 */ + int nskip; + /* number of comment records preceding the header record */ +#endif +}; + +#undef read_char + +static void read_char(struct csv *csv) +{ /* read character from csv data file */ + int c; + xassert(csv->c != EOF); + if (csv->c == '\n') csv->count++; +loop: c = fgetc(csv->fp); + if (ferror(csv->fp)) + { xprintf("%s:%d: read error - %s\n", csv->fname, csv->count, +#if 0 /* 29/I-2017 */ + strerror(errno)); +#else + xstrerr(errno)); +#endif + longjmp(csv->jump, 0); + } + if (feof(csv->fp)) + { if (csv->c == '\n') + { csv->count--; + c = EOF; + } + else + { xprintf("%s:%d: warning: missing final end-of-line\n", + csv->fname, csv->count); + c = '\n'; + } + } + else if (c == '\r') + goto loop; + else if (c == '\n') + ; + else if (iscntrl(c)) + { xprintf("%s:%d: invalid control character 0x%02X\n", + csv->fname, csv->count, c); + longjmp(csv->jump, 0); + } + csv->c = c; + return; +} + +static void read_field(struct csv *csv) +{ /* read field from csv data file */ + /* check for end of file */ + if (csv->c == EOF) + { csv->what = CSV_EOF; + strcpy(csv->field, "EOF"); + goto done; + } + /* check for end of record */ + if (csv->c == '\n') + { csv->what = CSV_EOR; + strcpy(csv->field, "EOR"); + read_char(csv); + if (csv->c == ',') +err1: { xprintf("%s:%d: empty field not allowed\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + if (csv->c == '\n') + { xprintf("%s:%d: empty record not allowed\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } +#if 1 /* 01/VI-2010 */ + /* skip comment records; may appear only before the very first + record containing field names */ + if (csv->c == '#' && csv->count == 1) + { while (csv->c == '#') + { while (csv->c != '\n') + read_char(csv); + read_char(csv); + csv->nskip++; + } + } +#endif + goto done; + } + /* skip comma before next field */ + if (csv->c == ',') + read_char(csv); + /* read field */ + if (csv->c == '\'' || csv->c == '"') + { /* read a field enclosed in quotes */ + int quote = csv->c, len = 0; + csv->what = CSV_STR; + /* skip opening quote */ + read_char(csv); + /* read field characters within quotes */ + for (;;) + { /* check for closing quote and read it */ + if (csv->c == quote) + { read_char(csv); + if (csv->c == quote) + ; + else if (csv->c == ',' || csv->c == '\n') + break; + else + { xprintf("%s:%d: invalid field\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + } + /* check the current field length */ + if (len == CSV_FDLEN_MAX) +err2: { xprintf("%s:%d: field too long\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + /* add the current character to the field */ + csv->field[len++] = (char)csv->c; + /* read the next character */ + read_char(csv); + } + /* the field has been read */ + if (len == 0) goto err1; + csv->field[len] = '\0'; + } + else + { /* read a field not enclosed in quotes */ + int len = 0; + double temp; + csv->what = CSV_NUM; + while (!(csv->c == ',' || csv->c == '\n')) + { /* quotes within the field are not allowed */ + if (csv->c == '\'' || csv->c == '"') + { xprintf("%s:%d: invalid use of single or double quote wi" + "thin field\n", csv->fname, csv->count); + longjmp(csv->jump, 0); + } + /* check the current field length */ + if (len == CSV_FDLEN_MAX) goto err2; + /* add the current character to the field */ + csv->field[len++] = (char)csv->c; + /* read the next character */ + read_char(csv); + } + /* the field has been read */ + if (len == 0) goto err1; + csv->field[len] = '\0'; + /* check the field type */ + if (str2num(csv->field, &temp)) csv->what = CSV_STR; + } +done: return; +} + +static struct csv *csv_open_file(TABDCA *dca, int mode) +{ /* open csv data file */ + struct csv *csv; + /* create control structure */ + csv = xmalloc(sizeof(struct csv)); + csv->mode = mode; + csv->fname = NULL; + csv->fp = NULL; + if (setjmp(csv->jump)) goto fail; + csv->count = 0; + csv->c = '\n'; + csv->what = 0; + csv->field[0] = '\0'; + csv->nf = 0; + /* try to open the csv data file */ + if (mpl_tab_num_args(dca) < 2) + { xprintf("csv_driver: file name not specified\n"); + longjmp(csv->jump, 0); + } + csv->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); + strcpy(csv->fname, mpl_tab_get_arg(dca, 2)); + if (mode == 'R') + { /* open the file for reading */ + int k; + csv->fp = fopen(csv->fname, "r"); + if (csv->fp == NULL) + { xprintf("csv_driver: unable to open %s - %s\n", +#if 0 /* 29/I-2017 */ + csv->fname, strerror(errno)); +#else + csv->fname, xstrerr(errno)); +#endif + longjmp(csv->jump, 0); + } +#if 1 /* 01/VI-2010 */ + csv->nskip = 0; +#endif + /* skip fake new-line */ + read_field(csv); + xassert(csv->what == CSV_EOR); + /* read field names */ + xassert(csv->nf == 0); + for (;;) + { read_field(csv); + if (csv->what == CSV_EOR) + break; + if (csv->what != CSV_STR) + { xprintf("%s:%d: invalid field name\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + if (csv->nf == CSV_FIELD_MAX) + { xprintf("%s:%d: too many fields\n", csv->fname, + csv->count); + longjmp(csv->jump, 0); + } + csv->nf++; + /* find corresponding field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + { if (strcmp(mpl_tab_get_name(dca, k), csv->field) == 0) + break; + } + csv->ref[csv->nf] = k; + } + /* find dummy RECNO field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; + csv->ref[0] = k; + } + else if (mode == 'W') + { /* open the file for writing */ + int k, nf; + csv->fp = fopen(csv->fname, "w"); + if (csv->fp == NULL) + { xprintf("csv_driver: unable to create %s - %s\n", +#if 0 /* 29/I-2017 */ + csv->fname, strerror(errno)); +#else + csv->fname, xstrerr(errno)); +#endif + longjmp(csv->jump, 0); + } + /* write field names */ + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + fprintf(csv->fp, "%s%c", mpl_tab_get_name(dca, k), + k < nf ? ',' : '\n'); + csv->count++; + } + else + xassert(mode != mode); + /* the file has been open */ + return csv; +fail: /* the file cannot be open */ + if (csv->fname != NULL) xfree(csv->fname); + if (csv->fp != NULL) fclose(csv->fp); + xfree(csv); + return NULL; +} + +static int csv_read_record(TABDCA *dca, struct csv *csv) +{ /* read next record from csv data file */ + int k, ret = 0; + xassert(csv->mode == 'R'); + if (setjmp(csv->jump)) + { ret = 1; + goto done; + } + /* read dummy RECNO field */ + if (csv->ref[0] > 0) +#if 0 /* 01/VI-2010 */ + mpl_tab_set_num(dca, csv->ref[0], csv->count-1); +#else + mpl_tab_set_num(dca, csv->ref[0], csv->count-csv->nskip-1); +#endif + /* read fields */ + for (k = 1; k <= csv->nf; k++) + { read_field(csv); + if (csv->what == CSV_EOF) + { /* end-of-file reached */ + xassert(k == 1); + ret = -1; + goto done; + } + else if (csv->what == CSV_EOR) + { /* end-of-record reached */ + int lack = csv->nf - k + 1; + if (lack == 1) + xprintf("%s:%d: one field missing\n", csv->fname, + csv->count); + else + xprintf("%s:%d: %d fields missing\n", csv->fname, + csv->count, lack); + longjmp(csv->jump, 0); + } + else if (csv->what == CSV_NUM) + { /* floating-point number */ + if (csv->ref[k] > 0) + { double num; + xassert(str2num(csv->field, &num) == 0); + mpl_tab_set_num(dca, csv->ref[k], num); + } + } + else if (csv->what == CSV_STR) + { /* character string */ + if (csv->ref[k] > 0) + mpl_tab_set_str(dca, csv->ref[k], csv->field); + } + else + xassert(csv != csv); + } + /* now there must be NL */ + read_field(csv); + xassert(csv->what != CSV_EOF); + if (csv->what != CSV_EOR) + { xprintf("%s:%d: too many fields\n", csv->fname, csv->count); + longjmp(csv->jump, 0); + } +done: return ret; +} + +static int csv_write_record(TABDCA *dca, struct csv *csv) +{ /* write next record to csv data file */ + int k, nf, ret = 0; + const char *c; + xassert(csv->mode == 'W'); + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + fprintf(csv->fp, "%.*g", DBL_DIG, + mpl_tab_get_num(dca, k)); + break; + case 'S': + fputc('"', csv->fp); + for (c = mpl_tab_get_str(dca, k); *c != '\0'; c++) + { if (*c == '"') + fputc('"', csv->fp), fputc('"', csv->fp); + else + fputc(*c, csv->fp); + } + fputc('"', csv->fp); + break; + default: + xassert(dca != dca); + } + fputc(k < nf ? ',' : '\n', csv->fp); + } + csv->count++; + if (ferror(csv->fp)) + { xprintf("%s:%d: write error - %s\n", csv->fname, csv->count, +#if 0 /* 29/I-2017 */ + strerror(errno)); +#else + xstrerr(errno)); +#endif + ret = 1; + } + return ret; +} + +static int csv_close_file(TABDCA *dca, struct csv *csv) +{ /* close csv data file */ + int ret = 0; + xassert(dca == dca); + if (csv->mode == 'W') + { fflush(csv->fp); + if (ferror(csv->fp)) + { xprintf("%s:%d: write error - %s\n", csv->fname, +#if 0 /* 29/I-2017 */ + csv->count, strerror(errno)); +#else + csv->count, xstrerr(errno)); +#endif + ret = 1; + } + } + xfree(csv->fname); + fclose(csv->fp); + xfree(csv); + return ret; +} + +/**********************************************************************/ + +#define DBF_FIELD_MAX 50 +/* maximal number of fields in record */ + +#define DBF_FDLEN_MAX 100 +/* maximal field length */ + +struct dbf +{ /* xBASE data file */ + int mode; + /* 'R' = reading; 'W' = writing */ + char *fname; + /* name of xBASE file */ + FILE *fp; + /* stream assigned to xBASE file */ + jmp_buf jump; + /* address for non-local go to in case of error */ + int offset; + /* offset of a byte to be read next */ + int count; + /* record count */ + int nf; + /* number of fields */ + int ref[1+DBF_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + int type[1+DBF_FIELD_MAX]; + /* type[k] is type of k-th field */ + int len[1+DBF_FIELD_MAX]; + /* len[k] is length of k-th field */ + int prec[1+DBF_FIELD_MAX]; + /* prec[k] is precision of k-th field */ +}; + +static int read_byte(struct dbf *dbf) +{ /* read byte from xBASE data file */ + int b; + b = fgetc(dbf->fp); + if (ferror(dbf->fp)) + { xprintf("%s:0x%X: read error - %s\n", dbf->fname, +#if 0 /* 29/I-2017 */ + dbf->offset, strerror(errno)); +#else + dbf->offset, xstrerr(errno)); +#endif + longjmp(dbf->jump, 0); + } + if (feof(dbf->fp)) + { xprintf("%s:0x%X: unexpected end of file\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + xassert(0x00 <= b && b <= 0xFF); + dbf->offset++; + return b; +} + +static void read_header(TABDCA *dca, struct dbf *dbf) +{ /* read xBASE data file header */ + int b, j, k, recl; + char name[10+1]; + /* (ignored) */ + for (j = 1; j <= 10; j++) + read_byte(dbf); + /* length of each record, in bytes */ + recl = read_byte(dbf); + recl += read_byte(dbf) << 8; + /* (ignored) */ + for (j = 1; j <= 20; j++) + read_byte(dbf); + /* field descriptor array */ + xassert(dbf->nf == 0); + for (;;) + { /* check for end of array */ + b = read_byte(dbf); + if (b == 0x0D) break; + if (dbf->nf == DBF_FIELD_MAX) + { xprintf("%s:0x%X: too many fields\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->nf++; + /* field name */ + name[0] = (char)b; + for (j = 1; j < 10; j++) + { b = read_byte(dbf); + name[j] = (char)b; + } + name[10] = '\0'; + b = read_byte(dbf); + if (b != 0x00) + { xprintf("%s:0x%X: invalid field name\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* find corresponding field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), name) == 0) break; + dbf->ref[dbf->nf] = k; + /* field type */ + b = read_byte(dbf); + if (!(b == 'C' || b == 'N')) + { xprintf("%s:0x%X: invalid field type\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->type[dbf->nf] = b; + /* (ignored) */ + for (j = 1; j <= 4; j++) + read_byte(dbf); + /* field length */ + b = read_byte(dbf); + if (b == 0) + { xprintf("%s:0x%X: invalid field length\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + if (b > DBF_FDLEN_MAX) + { xprintf("%s:0x%X: field too long\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + dbf->len[dbf->nf] = b; + recl -= b; + /* (ignored) */ + for (j = 1; j <= 15; j++) + read_byte(dbf); + } + if (recl != 1) + { xprintf("%s:0x%X: invalid file header\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* find dummy RECNO field in the table statement */ + for (k = mpl_tab_num_flds(dca); k >= 1; k--) + if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; + dbf->ref[0] = k; + return; +} + +static void parse_third_arg(TABDCA *dca, struct dbf *dbf) +{ /* parse xBASE file format (third argument) */ + int j, k, temp; + const char *arg; + dbf->nf = mpl_tab_num_flds(dca); + arg = mpl_tab_get_arg(dca, 3), j = 0; + for (k = 1; k <= dbf->nf; k++) + { /* parse specification of k-th field */ + if (arg[j] == '\0') + { xprintf("xBASE driver: field %s: specification missing\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* parse field type */ + if (arg[j] == 'C' || arg[j] == 'N') + dbf->type[k] = arg[j], j++; + else + { xprintf("xBASE driver: field %s: invalid field type\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* check for left parenthesis */ + if (arg[j] == '(') + j++; + else +err: { xprintf("xBASE driver: field %s: invalid field format\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + /* parse field length */ + temp = 0; + while (isdigit(arg[j])) + { if (temp > DBF_FDLEN_MAX) break; + temp = 10 * temp + (arg[j] - '0'), j++; + } + if (!(1 <= temp && temp <= DBF_FDLEN_MAX)) + { xprintf("xBASE driver: field %s: invalid field length\n", + mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + dbf->len[k] = temp; + /* parse optional field precision */ + if (dbf->type[k] == 'N' && arg[j] == ',') + { j++; + temp = 0; + while (isdigit(arg[j])) + { if (temp > dbf->len[k]) break; + temp = 10 * temp + (arg[j] - '0'), j++; + } + if (temp > dbf->len[k]) + { xprintf("xBASE driver: field %s: invalid field precision" + "\n", mpl_tab_get_name(dca, k)); + longjmp(dbf->jump, 0); + } + dbf->prec[k] = temp; + } + else + dbf->prec[k] = 0; + /* check for right parenthesis */ + if (arg[j] == ')') + j++; + else + goto err; + } + /* ignore other specifications */ + return; +} + +static void write_byte(struct dbf *dbf, int b) +{ /* write byte to xBASE data file */ + fputc(b, dbf->fp); + dbf->offset++; + return; +} + +static void write_header(TABDCA *dca, struct dbf *dbf) +{ /* write xBASE data file header */ + int j, k, temp; + const char *name; + /* version number */ + write_byte(dbf, 0x03 /* file without DBT */); + /* date of last update (YYMMDD) */ + write_byte(dbf, 70 /* 1970 */); + write_byte(dbf, 1 /* January */); + write_byte(dbf, 1 /* 1st */); + /* number of records (unknown so far) */ + for (j = 1; j <= 4; j++) + write_byte(dbf, 0xFF); + /* length of the header, in bytes */ + temp = 32 + dbf->nf * 32 + 1; + write_byte(dbf, temp); + write_byte(dbf, temp >> 8); + /* length of each record, in bytes */ + temp = 1; + for (k = 1; k <= dbf->nf; k++) + temp += dbf->len[k]; + write_byte(dbf, temp); + write_byte(dbf, temp >> 8); + /* (reserved) */ + for (j = 1; j <= 20; j++) + write_byte(dbf, 0x00); + /* field descriptor array */ + for (k = 1; k <= dbf->nf; k++) + { /* field name (terminated by 0x00) */ + name = mpl_tab_get_name(dca, k); + for (j = 0; j < 10 && name[j] != '\0'; j++) + write_byte(dbf, name[j]); + for (j = j; j < 11; j++) + write_byte(dbf, 0x00); + /* field type */ + write_byte(dbf, dbf->type[k]); + /* (reserved) */ + for (j = 1; j <= 4; j++) + write_byte(dbf, 0x00); + /* field length */ + write_byte(dbf, dbf->len[k]); + /* field precision */ + write_byte(dbf, dbf->prec[k]); + /* (reserved) */ + for (j = 1; j <= 14; j++) + write_byte(dbf, 0x00); + } + /* end of header */ + write_byte(dbf, 0x0D); + return; +} + +static struct dbf *dbf_open_file(TABDCA *dca, int mode) +{ /* open xBASE data file */ + struct dbf *dbf; + /* create control structure */ + dbf = xmalloc(sizeof(struct dbf)); + dbf->mode = mode; + dbf->fname = NULL; + dbf->fp = NULL; + if (setjmp(dbf->jump)) goto fail; + dbf->offset = 0; + dbf->count = 0; + dbf->nf = 0; + /* try to open the xBASE data file */ + if (mpl_tab_num_args(dca) < 2) + { xprintf("xBASE driver: file name not specified\n"); + longjmp(dbf->jump, 0); + } + dbf->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); + strcpy(dbf->fname, mpl_tab_get_arg(dca, 2)); + if (mode == 'R') + { /* open the file for reading */ + dbf->fp = fopen(dbf->fname, "rb"); + if (dbf->fp == NULL) + { xprintf("xBASE driver: unable to open %s - %s\n", +#if 0 /* 29/I-2017 */ + dbf->fname, strerror(errno)); +#else + dbf->fname, xstrerr(errno)); +#endif + longjmp(dbf->jump, 0); + } + read_header(dca, dbf); + } + else if (mode == 'W') + { /* open the file for writing */ + if (mpl_tab_num_args(dca) < 3) + { xprintf("xBASE driver: file format not specified\n"); + longjmp(dbf->jump, 0); + } + parse_third_arg(dca, dbf); + dbf->fp = fopen(dbf->fname, "wb"); + if (dbf->fp == NULL) + { xprintf("xBASE driver: unable to create %s - %s\n", +#if 0 /* 29/I-2017 */ + dbf->fname, strerror(errno)); +#else + dbf->fname, xstrerr(errno)); +#endif + longjmp(dbf->jump, 0); + } + write_header(dca, dbf); + } + else + xassert(mode != mode); + /* the file has been open */ + return dbf; +fail: /* the file cannot be open */ + if (dbf->fname != NULL) xfree(dbf->fname); + if (dbf->fp != NULL) fclose(dbf->fp); + xfree(dbf); + return NULL; +} + +static int dbf_read_record(TABDCA *dca, struct dbf *dbf) +{ /* read next record from xBASE data file */ + int b, j, k, ret = 0; + char buf[DBF_FDLEN_MAX+1]; + xassert(dbf->mode == 'R'); + if (setjmp(dbf->jump)) + { ret = 1; + goto done; + } + /* check record flag */ + b = read_byte(dbf); + if (b == 0x1A) + { /* end of data */ + ret = -1; + goto done; + } + if (b != 0x20) + { xprintf("%s:0x%X: invalid record flag\n", dbf->fname, + dbf->offset); + longjmp(dbf->jump, 0); + } + /* read dummy RECNO field */ + if (dbf->ref[0] > 0) + mpl_tab_set_num(dca, dbf->ref[0], dbf->count+1); + /* read fields */ + for (k = 1; k <= dbf->nf; k++) + { /* read k-th field */ + for (j = 0; j < dbf->len[k]; j++) + buf[j] = (char)read_byte(dbf); + buf[dbf->len[k]] = '\0'; + /* set field value */ + if (dbf->type[k] == 'C') + { /* character field */ + if (dbf->ref[k] > 0) + mpl_tab_set_str(dca, dbf->ref[k], strtrim(buf)); + } + else if (dbf->type[k] == 'N') + { /* numeric field */ + if (dbf->ref[k] > 0) + { double num; + strspx(buf); + xassert(str2num(buf, &num) == 0); + mpl_tab_set_num(dca, dbf->ref[k], num); + } + } + else + xassert(dbf != dbf); + } + /* increase record count */ + dbf->count++; +done: return ret; +} + +static int dbf_write_record(TABDCA *dca, struct dbf *dbf) +{ /* write next record to xBASE data file */ + int j, k, ret = 0; + char buf[255+1]; + xassert(dbf->mode == 'W'); + if (setjmp(dbf->jump)) + { ret = 1; + goto done; + } + /* record flag */ + write_byte(dbf, 0x20); + xassert(dbf->nf == mpl_tab_num_flds(dca)); + for (k = 1; k <= dbf->nf; k++) + { if (dbf->type[k] == 'C') + { /* character field */ + const char *str; + if (mpl_tab_get_type(dca, k) == 'N') + { sprintf(buf, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); + str = buf; + } + else if (mpl_tab_get_type(dca, k) == 'S') + str = mpl_tab_get_str(dca, k); + else + xassert(dca != dca); + if ((int)strlen(str) > dbf->len[k]) + { xprintf("xBASE driver: field %s: cannot convert %.15s..." + " to field format\n", mpl_tab_get_name(dca, k), str); + longjmp(dbf->jump, 0); + } + for (j = 0; j < dbf->len[k] && str[j] != '\0'; j++) + write_byte(dbf, str[j]); + for (j = j; j < dbf->len[k]; j++) + write_byte(dbf, ' '); + } + else if (dbf->type[k] == 'N') + { /* numeric field */ + double num = mpl_tab_get_num(dca, k); + if (fabs(num) > 1e20) +err: { xprintf("xBASE driver: field %s: cannot convert %g to fi" + "eld format\n", mpl_tab_get_name(dca, k), num); + longjmp(dbf->jump, 0); + } + sprintf(buf, "%*.*f", dbf->len[k], dbf->prec[k], num); + xassert(strlen(buf) < sizeof(buf)); + if ((int)strlen(buf) != dbf->len[k]) goto err; + for (j = 0; j < dbf->len[k]; j++) + write_byte(dbf, buf[j]); + } + else + xassert(dbf != dbf); + } + /* increase record count */ + dbf->count++; +done: return ret; +} + +static int dbf_close_file(TABDCA *dca, struct dbf *dbf) +{ /* close xBASE data file */ + int ret = 0; + xassert(dca == dca); + if (dbf->mode == 'W') + { if (setjmp(dbf->jump)) + { ret = 1; + goto skip; + } + /* end-of-file flag */ + write_byte(dbf, 0x1A); + /* number of records */ + dbf->offset = 4; + if (fseek(dbf->fp, dbf->offset, SEEK_SET)) + { xprintf("%s:0x%X: seek error - %s\n", dbf->fname, +#if 0 /* 29/I-2017 */ + dbf->offset, strerror(errno)); +#else + dbf->offset, xstrerr(errno)); +#endif + longjmp(dbf->jump, 0); + } + write_byte(dbf, dbf->count); + write_byte(dbf, dbf->count >> 8); + write_byte(dbf, dbf->count >> 16); + write_byte(dbf, dbf->count >> 24); + fflush(dbf->fp); + if (ferror(dbf->fp)) + { xprintf("%s:0x%X: write error - %s\n", dbf->fname, +#if 0 /* 29/I-2017 */ + dbf->offset, strerror(errno)); +#else + dbf->offset, xstrerr(errno)); +#endif + longjmp(dbf->jump, 0); + } +skip: ; + } + xfree(dbf->fname); + fclose(dbf->fp); + xfree(dbf); + return ret; +} + +/**********************************************************************/ + +#define TAB_CSV 1 +#define TAB_XBASE 2 +#define TAB_ODBC 3 +#define TAB_MYSQL 4 + +void mpl_tab_drv_open(MPL *mpl, int mode) +{ TABDCA *dca = mpl->dca; + xassert(dca->id == 0); + xassert(dca->link == NULL); + xassert(dca->na >= 1); + if (strcmp(dca->arg[1], "CSV") == 0) + { dca->id = TAB_CSV; + dca->link = csv_open_file(dca, mode); + } + else if (strcmp(dca->arg[1], "xBASE") == 0) + { dca->id = TAB_XBASE; + dca->link = dbf_open_file(dca, mode); + } + else if (strcmp(dca->arg[1], "ODBC") == 0 || + strcmp(dca->arg[1], "iODBC") == 0) + { dca->id = TAB_ODBC; + dca->link = db_iodbc_open(dca, mode); + } + else if (strcmp(dca->arg[1], "MySQL") == 0) + { dca->id = TAB_MYSQL; + dca->link = db_mysql_open(dca, mode); + } + else + xprintf("Invalid table driver '%s'\n", dca->arg[1]); + if (dca->link == NULL) + error(mpl, "error on opening table %s", + mpl->stmt->u.tab->name); + return; +} + +int mpl_tab_drv_read(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_read_record(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_read_record(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_read(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_read(dca, dca->link); + break; + default: + xassert(dca != dca); + } + if (ret > 0) + error(mpl, "error on reading data from table %s", + mpl->stmt->u.tab->name); + return ret; +} + +void mpl_tab_drv_write(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_write_record(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_write_record(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_write(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_write(dca, dca->link); + break; + default: + xassert(dca != dca); + } + if (ret) + error(mpl, "error on writing data to table %s", + mpl->stmt->u.tab->name); + return; +} + +void mpl_tab_drv_close(MPL *mpl) +{ TABDCA *dca = mpl->dca; + int ret; + switch (dca->id) + { case TAB_CSV: + ret = csv_close_file(dca, dca->link); + break; + case TAB_XBASE: + ret = dbf_close_file(dca, dca->link); + break; + case TAB_ODBC: + ret = db_iodbc_close(dca, dca->link); + break; + case TAB_MYSQL: + ret = db_mysql_close(dca, dca->link); + break; + default: + xassert(dca != dca); + } + dca->id = 0; + dca->link = NULL; + if (ret) + error(mpl, "error on closing table %s", + mpl->stmt->u.tab->name); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.c b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.c new file mode 100644 index 000000000..fcd2afa65 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.c @@ -0,0 +1,1659 @@ +/* mplsql.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Heinrich Schuchardt . +* +* Copyright (C) 2003-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "mpl.h" +#include "mplsql.h" + +#ifdef ODBC_DLNAME +#define HAVE_ODBC +#define libodbc ODBC_DLNAME +#define h_odbc (get_env_ptr()->h_odbc) +#endif + +#ifdef MYSQL_DLNAME +#define HAVE_MYSQL +#define libmysql MYSQL_DLNAME +#define h_mysql (get_env_ptr()->h_mysql) +#endif + +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char + **sqllines); +static void *db_mysql_open_int(TABDCA *dca, int mode, const char + **sqllines); + +/**********************************************************************/ + +#if defined(HAVE_ODBC) || defined(HAVE_MYSQL) + +#define SQL_FIELD_MAX 100 +/* maximal field count */ + +#define SQL_FDLEN_MAX 255 +/* maximal field length */ + +/*********************************************************************** +* NAME +* +* args_concat - concatenate arguments +* +* SYNOPSIS +* +* static char **args_concat(TABDCA *dca); +* +* DESCRIPTION +* +* The arguments passed in dca are SQL statements. A SQL statement may +* be split over multiple arguments. The last argument of a SQL +* statement will be terminated with a semilocon. Each SQL statement is +* merged into a single zero terminated string. Boundaries between +* arguments are replaced by space. +* +* RETURNS +* +* Buffer with SQL statements */ + +static char **args_concat(TABDCA *dca) +{ + const char *arg; + int i; + int j; + int j0; + int j1; + size_t len; + int lentot; + int narg; + int nline = 0; + char **sqllines = NULL; + + narg = mpl_tab_num_args(dca); + /* The SQL statements start with argument 3. */ + if (narg < 3) + return NULL; + /* Count the SQL statements */ + for (j = 3; j <= narg; j++) + { + arg = mpl_tab_get_arg(dca, j); + len = strlen(arg); + if (arg[len-1] == ';' || j == narg) + nline ++; + } + /* Allocate string buffer. */ + sqllines = (char **) xmalloc((nline+1) * sizeof(char **)); + /* Join arguments */ + sqllines[0] = NULL; + j0 = 3; + i = 0; + lentot = 0; + for (j = 3; j <= narg; j++) + { + arg = mpl_tab_get_arg(dca, j); + len = strlen(arg); + /* add length of part */ + lentot += len; + /* add length of space separating parts or 0x00 at end of SQL + statement */ + lentot++; + if (arg[len-1] == ';' || j == narg) + { /* Join arguments for a single SQL statement */ + sqllines[i] = xmalloc(lentot); + sqllines[i+1] = NULL; + sqllines[i][0] = 0x00; + for (j1 = j0; j1 <= j; j1++) + { if(j1>j0) + strcat(sqllines[i], " "); + strcat(sqllines[i], mpl_tab_get_arg(dca, j1)); + } + len = strlen(sqllines[i]); + if (sqllines[i][len-1] == ';') + sqllines[i][len-1] = 0x00; + j0 = j+1; + i++; + lentot = 0; + } + } + return sqllines; +} + +/*********************************************************************** +* NAME +* +* free_buffer - free multiline string buffer +* +* SYNOPSIS +* +* static void free_buffer(char **buf); +* +* DESCRIPTION +* +* buf is a list of strings terminated by NULL. +* The memory for the strings and for the list is released. */ + +static void free_buffer(char **buf) +{ int i; + + for(i = 0; buf[i] != NULL; i++) + xfree(buf[i]); + xfree(buf); +} + +static int db_escaped_string_length(const char* from) +/* length of escaped string */ +{ + int count; + const char *pointer; + + for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++, + count++) + { + switch (*pointer) + { + case '\'': + count++; + break; + } + } + + return count; +} + +static void db_escape_string (char *to, const char *from) +/* escape string*/ +{ + const char *source = from; + char *target = to; + size_t remaining; + + remaining = strlen(from); + + if (to == NULL) + to = (char *) (from + remaining); + + while (remaining > 0) + { + switch (*source) + { + case '\'': + *target = '\''; + target++; + *target = '\''; + break; + + default: + *target = *source; + } + source++; + target++; + remaining--; + } + + /* Write the terminating NUL character. */ + *target = '\0'; +} + +static char *db_generate_select_stmt(TABDCA *dca) +/* generate select statement */ +{ + char *arg; + char const *field; + char *query; + int j; + int narg; + int nf; + int total; + + total = 50; + nf = mpl_tab_num_flds(dca); + narg = mpl_tab_num_args(dca); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + total += strlen(field); + total += 2; + } + arg = (char *) mpl_tab_get_arg(dca, narg); + total += strlen(arg); + query = xmalloc( total * sizeof(char)); + strcpy (query, "SELECT "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + strcat(query, field); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " FROM "); + strcat(query, arg); + return query; +} + +static char *db_generate_insert_stmt(TABDCA *dca) +/* generate insert statement */ +{ + char *arg; + char const *field; + char *query; + int j; + int narg; + int nf; + int total; + + total = 50; + nf = mpl_tab_num_flds(dca); + narg = mpl_tab_num_args(dca); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + total += strlen(field); + total += 5; + } + arg = (char *) mpl_tab_get_arg(dca, narg); + total += strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, "INSERT INTO "); + strcat(query, arg); + strcat(query, " ( "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + field = mpl_tab_get_name(dca, j); + strcat(query, field); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " ) VALUES ( "); + for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) + { + strcat(query, "?"); + if ( j < nf ) + strcat(query, ", "); + } + strcat(query, " )"); + return query; +} + +#endif + +/**********************************************************************/ + +#ifndef HAVE_ODBC + +void *db_iodbc_open(TABDCA *dca, int mode) +{ xassert(dca == dca); + xassert(mode == mode); + xprintf("iODBC table driver not supported\n"); + return NULL; +} + +int db_iodbc_read(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_iodbc_write(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_iodbc_close(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +#else + +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) +#include +#endif + +#include +#include + +struct db_odbc +{ + int mode; /*'R' = Read, 'W' = Write*/ + SQLHDBC hdbc; /*connection handle*/ + SQLHENV henv; /*environment handle*/ + SQLHSTMT hstmt; /*statement handle*/ + SQLSMALLINT nresultcols; /* columns in result*/ + SQLULEN collen[SQL_FIELD_MAX+1]; + SQLLEN outlen[SQL_FIELD_MAX+1]; + SQLSMALLINT coltype[SQL_FIELD_MAX+1]; + SQLCHAR data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; +#if 1 /* 12/I-2014 */ + SQLDOUBLE datanum[SQL_FIELD_MAX+1]; +#endif + SQLCHAR colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; + int isnumeric[SQL_FIELD_MAX+1]; + int nf; + /* number of fields in the csv file */ + int ref[1+SQL_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + SQLCHAR *query; + /* query generated by db_iodbc_open */ +}; + +SQLRETURN SQL_API dl_SQLAllocHandle ( + SQLSMALLINT HandleType, + SQLHANDLE InputHandle, + SQLHANDLE *OutputHandle) +{ + typedef SQLRETURN SQL_API ep_SQLAllocHandle( + SQLSMALLINT HandleType, + SQLHANDLE InputHandle, + SQLHANDLE *OutputHandle); + + ep_SQLAllocHandle *fn; + fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle"); + xassert(fn != NULL); + return (*fn)(HandleType, InputHandle, OutputHandle); +} + +SQLRETURN SQL_API dl_SQLBindCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, + SQLLEN *StrLen_or_Ind) +{ + typedef SQLRETURN SQL_API ep_SQLBindCol( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLSMALLINT TargetType, + SQLPOINTER TargetValue, + SQLLEN BufferLength, + SQLLEN *StrLen_or_Ind); + ep_SQLBindCol *fn; + fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnNumber, TargetType, + TargetValue, BufferLength, StrLen_or_Ind); +} + +SQLRETURN SQL_API dl_SQLCloseCursor ( + SQLHSTMT StatementHandle) +{ + typedef SQLRETURN SQL_API ep_SQLCloseCursor ( + SQLHSTMT StatementHandle); + + ep_SQLCloseCursor *fn; + fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor"); + xassert(fn != NULL); + return (*fn)(StatementHandle); +} + + +SQLRETURN SQL_API dl_SQLDisconnect ( + SQLHDBC ConnectionHandle) +{ + typedef SQLRETURN SQL_API ep_SQLDisconnect( + SQLHDBC ConnectionHandle); + + ep_SQLDisconnect *fn; + fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle); +} + +SQLRETURN SQL_API dl_SQLDriverConnect ( + SQLHDBC hdbc, + SQLHWND hwnd, + SQLCHAR *szConnStrIn, + SQLSMALLINT cbConnStrIn, + SQLCHAR *szConnStrOut, + SQLSMALLINT cbConnStrOutMax, + SQLSMALLINT *pcbConnStrOut, + SQLUSMALLINT fDriverCompletion) +{ + typedef SQLRETURN SQL_API ep_SQLDriverConnect( + SQLHDBC hdbc, + SQLHWND hwnd, + SQLCHAR * szConnStrIn, + SQLSMALLINT cbConnStrIn, + SQLCHAR * szConnStrOut, + SQLSMALLINT cbConnStrOutMax, + SQLSMALLINT * pcbConnStrOut, + SQLUSMALLINT fDriverCompletion); + + ep_SQLDriverConnect *fn; + fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect"); + xassert(fn != NULL); + return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, + cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); +} + +SQLRETURN SQL_API dl_SQLEndTran ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT CompletionType) +{ + typedef SQLRETURN SQL_API ep_SQLEndTran ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT CompletionType); + + ep_SQLEndTran *fn; + fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle, CompletionType); +} + +SQLRETURN SQL_API dl_SQLExecDirect ( + SQLHSTMT StatementHandle, + SQLCHAR * StatementText, + SQLINTEGER TextLength) +{ + typedef SQLRETURN SQL_API ep_SQLExecDirect ( + SQLHSTMT StatementHandle, + SQLCHAR * StatementText, + SQLINTEGER TextLength); + + ep_SQLExecDirect *fn; + fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect"); + xassert(fn != NULL); + return (*fn)(StatementHandle, StatementText, TextLength); +} + +SQLRETURN SQL_API dl_SQLFetch ( + SQLHSTMT StatementHandle) +{ + typedef SQLRETURN SQL_API ep_SQLFetch ( + SQLHSTMT StatementHandle); + + ep_SQLFetch *fn; + fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch"); + xassert(fn != NULL); + return (*fn)(StatementHandle); +} + +SQLRETURN SQL_API dl_SQLFreeHandle ( + SQLSMALLINT HandleType, + SQLHANDLE Handle) +{ + typedef SQLRETURN SQL_API ep_SQLFreeHandle ( + SQLSMALLINT HandleType, + SQLHANDLE Handle); + + ep_SQLFreeHandle *fn; + fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle); +} + +SQLRETURN SQL_API dl_SQLDescribeCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLCHAR * ColumnName, + SQLSMALLINT BufferLength, + SQLSMALLINT * NameLength, + SQLSMALLINT * DataType, + SQLULEN * ColumnSize, + SQLSMALLINT * DecimalDigits, + SQLSMALLINT * Nullable) +{ + typedef SQLRETURN SQL_API ep_SQLDescribeCol ( + SQLHSTMT StatementHandle, + SQLUSMALLINT ColumnNumber, + SQLCHAR *ColumnName, + SQLSMALLINT BufferLength, + SQLSMALLINT *NameLength, + SQLSMALLINT *DataType, + SQLULEN *ColumnSize, + SQLSMALLINT *DecimalDigits, + SQLSMALLINT *Nullable); + + ep_SQLDescribeCol *fn; + fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnNumber, ColumnName, + BufferLength, NameLength, + DataType, ColumnSize, DecimalDigits, Nullable); +} + +SQLRETURN SQL_API dl_SQLGetDiagRec ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, + SQLINTEGER *NativeError, + SQLCHAR *MessageText, + SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength) +{ + typedef SQLRETURN SQL_API ep_SQLGetDiagRec ( + SQLSMALLINT HandleType, + SQLHANDLE Handle, + SQLSMALLINT RecNumber, + SQLCHAR *Sqlstate, + SQLINTEGER *NativeError, + SQLCHAR *MessageText, + SQLSMALLINT BufferLength, + SQLSMALLINT *TextLength); + + ep_SQLGetDiagRec *fn; + fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec"); + xassert(fn != NULL); + return (*fn)(HandleType, Handle, RecNumber, Sqlstate, + NativeError, MessageText, BufferLength, TextLength); +} + +SQLRETURN SQL_API dl_SQLGetInfo ( + SQLHDBC ConnectionHandle, + SQLUSMALLINT InfoType, + SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLGetInfo ( + SQLHDBC ConnectionHandle, + SQLUSMALLINT InfoType, + SQLPOINTER InfoValue, + SQLSMALLINT BufferLength, + SQLSMALLINT *StringLength); + + ep_SQLGetInfo *fn; + fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength, + StringLength); +} + +SQLRETURN SQL_API dl_SQLNumResultCols ( + SQLHSTMT StatementHandle, + SQLSMALLINT *ColumnCount) +{ + typedef SQLRETURN SQL_API ep_SQLNumResultCols ( + SQLHSTMT StatementHandle, + SQLSMALLINT *ColumnCount); + + ep_SQLNumResultCols *fn; + fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols"); + xassert(fn != NULL); + return (*fn)(StatementHandle, ColumnCount); +} + +SQLRETURN SQL_API dl_SQLSetConnectAttr ( + SQLHDBC ConnectionHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLSetConnectAttr ( + SQLHDBC ConnectionHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength); + + ep_SQLSetConnectAttr *fn; + fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr"); + xassert(fn != NULL); + return (*fn)(ConnectionHandle, Attribute, Value, StringLength); +} + +SQLRETURN SQL_API dl_SQLSetEnvAttr ( + SQLHENV EnvironmentHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength) +{ + typedef SQLRETURN SQL_API ep_SQLSetEnvAttr ( + SQLHENV EnvironmentHandle, + SQLINTEGER Attribute, + SQLPOINTER Value, + SQLINTEGER StringLength); + + ep_SQLSetEnvAttr *fn; + fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr"); + xassert(fn != NULL); + return (*fn)(EnvironmentHandle, Attribute, Value, StringLength); +} + +static void extract_error( + char *fn, + SQLHANDLE handle, + SQLSMALLINT type); + +static int is_numeric( + SQLSMALLINT coltype); + +/*********************************************************************** +* NAME +* +* db_iodbc_open - open connection to ODBC data base +* +* SYNOPSIS +* +* #include "mplsql.h" +* void *db_iodbc_open(TABDCA *dca, int mode); +* +* DESCRIPTION +* +* The routine db_iodbc_open opens a connection to an ODBC data base. +* It then executes the sql statements passed. +* +* In the case of table read the SELECT statement is executed. +* +* In the case of table write the INSERT statement is prepared. +* RETURNS +* +* The routine returns a pointer to data storage area created. */ +void *db_iodbc_open(TABDCA *dca, int mode) +{ void *ret; + char **sqllines; + + sqllines = args_concat(dca); + if (sqllines == NULL) + { xprintf("Missing arguments in table statement.\n" + "Please, supply table driver, dsn, and query.\n"); + return NULL; + } + ret = db_iodbc_open_int(dca, mode, (const char **) sqllines); + free_buffer(sqllines); + return ret; +} + +static void *db_iodbc_open_int(TABDCA *dca, int mode, const char + **sqllines) +{ + struct db_odbc *sql; + SQLRETURN ret; + SQLCHAR FAR *dsn; + SQLCHAR info[256]; + SQLSMALLINT colnamelen; + SQLSMALLINT nullable; + SQLSMALLINT scale; + const char *arg; + int narg; + int i, j; + int total; + + if (libodbc == NULL) + { + xprintf("No loader for shared ODBC library available\n"); + return NULL; + } + + if (h_odbc == NULL) + { + h_odbc = xdlopen(libodbc); + if (h_odbc == NULL) + { xprintf("unable to open library %s\n", libodbc); + xprintf("%s\n", get_err_msg()); + return NULL; + } + } + + sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc)); + if (sql == NULL) + return NULL; + + sql->mode = mode; + sql->hdbc = NULL; + sql->henv = NULL; + sql->hstmt = NULL; + sql->query = NULL; + narg = mpl_tab_num_args(dca); + + dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2); + /* allocate an environment handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, + &(sql->henv)); + /* set attribute to enable application to run as ODBC 3.0 + application */ + ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION, + (void *) SQL_OV_ODBC3, 0); + /* allocate a connection handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc)); + /* connect */ + ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0, + NULL, SQL_DRIVER_COMPLETE); + if (SQL_SUCCEEDED(ret)) + { /* output information about data base connection */ + xprintf("Connected to "); + dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s ", info); + dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s - ", info); + dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info, + sizeof(info), NULL); + xprintf("%s\n", info); + } + else + { /* describe error */ + xprintf("Failed to connect\n"); + extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql); + return NULL; + } + /* set AUTOCOMMIT on*/ + ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT, + (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0); + /* allocate a statement handle */ + ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt)); + + /* initialization queries */ + for(j = 0; sqllines[j+1] != NULL; j++) + { + sql->query = (SQLCHAR *) sqllines[j]; + xprintf("%s\n", sql->query); + ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS); + switch (ret) + { + case SQL_SUCCESS: + case SQL_SUCCESS_WITH_INFO: + case SQL_NO_DATA_FOUND: + break; + default: + xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", + sql->query); + extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql); + return NULL; + } + /* commit statement */ + dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); + } + + if ( sql->mode == 'R' ) + { sql->nf = mpl_tab_num_flds(dca); + for(j = 0; sqllines[j] != NULL; j++) + arg = sqllines[j]; + total = strlen(arg); + if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) + { + total = strlen(arg); + sql->query = xmalloc( (total+1) * sizeof(char)); + strcpy (sql->query, arg); + } + else + { + sql->query = db_generate_select_stmt(dca); + } + xprintf("%s\n", sql->query); + if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) != + SQL_SUCCESS) + { + xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query); + extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql->query); + xfree(sql); + return NULL; + } + xfree(sql->query); + /* determine number of result columns */ + ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols); + total = sql->nresultcols; + if (total > SQL_FIELD_MAX) + { xprintf("db_iodbc_open: Too many fields (> %d) in query.\n" + "\"%s\"\n", SQL_FIELD_MAX, sql->query); + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + xfree(sql->query); + return NULL; + } + for (i = 1; i <= total; i++) + { /* return a set of attributes for a column */ + ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i, + sql->colname[i], SQL_FDLEN_MAX, + &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale, + &nullable); + sql->isnumeric[i] = is_numeric(sql->coltype[i]); + /* bind columns to program vars, converting all types to CHAR*/ + if (sql->isnumeric[i]) +#if 0 /* 12/I-2014 */ + { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, sql->data[i], +#else + { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, &sql->datanum[i], +#endif + SQL_FDLEN_MAX, &(sql->outlen[i])); + } else + { dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i], + SQL_FDLEN_MAX, &(sql->outlen[i])); + } + for (j = sql->nf; j >= 1; j--) + { if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0) + break; + } + sql->ref[i] = j; + } + } + else if ( sql->mode == 'W' ) + { for(j = 0; sqllines[j] != NULL; j++) + arg = sqllines[j]; + if ( NULL != strchr(arg, '?') ) + { + total = strlen(arg); + sql->query = xmalloc( (total+1) * sizeof(char)); + strcpy (sql->query, arg); + } + else + { + sql->query = db_generate_insert_stmt(dca); + } + xprintf("%s\n", sql->query); + } + return sql; +} + +int db_iodbc_read(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + SQLRETURN ret; + char buf[SQL_FDLEN_MAX+1]; + int i; + int len; + double num; + + sql = (struct db_odbc *) link; + + xassert(sql != NULL); + xassert(sql->mode == 'R'); + + ret=dl_SQLFetch(sql->hstmt); + if (ret== SQL_ERROR) + return -1; + if (ret== SQL_NO_DATA_FOUND) + return -1; /*EOF*/ + for (i=1; i <= sql->nresultcols; i++) + { + if (sql->ref[i] > 0) + { + len = sql->outlen[i]; + if (len != SQL_NULL_DATA) + { + if (sql->isnumeric[i]) + { mpl_tab_set_num(dca, sql->ref[i], +#if 0 /* 12/I-2014 */ + *((const double *) sql->data[i])); +#else + (const double) sql->datanum[i]); +#endif + } + else + { if (len > SQL_FDLEN_MAX) + len = SQL_FDLEN_MAX; + else if (len < 0) + len = 0; + strncpy(buf, (const char *) sql->data[i], len); + buf[len] = 0x00; + mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); + } + } + } + } + return 0; +} + +int db_iodbc_write(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + char *part; + char *query; + char *template; + char num[50]; + int k; + int len; + int nf; + + sql = (struct db_odbc *) link; + xassert(sql != NULL); + xassert(sql->mode == 'W'); + + len = strlen(sql->query); + template = (char *) xmalloc( (len + 1) * sizeof(char) ); + strcpy(template, sql->query); + + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + len += 20; + break; + case 'S': + len += db_escaped_string_length(mpl_tab_get_str(dca, k)); + len += 2; + break; + default: + xassert(dca != dca); + } + } + query = xmalloc( (len + 1 ) * sizeof(char) ); + query[0] = 0x00; +#if 0 /* 29/I-2017 */ + for (k = 1, part = strtok (template, "?"); (part != NULL); + part = strtok (NULL, "?"), k++) +#else + for (k = 1, part = xstrtok (template, "?"); (part != NULL); + part = xstrtok (NULL, "?"), k++) +#endif + { + if (k > nf) break; + strcat( query, part ); + switch (mpl_tab_get_type(dca, k)) + { case 'N': +#if 0 /* 02/XI-2010 by xypron */ + sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); +#else + sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); +#endif + strcat( query, num ); + break; + case 'S': + strcat( query, "'"); + db_escape_string( query + strlen(query), + mpl_tab_get_str(dca, k) ); + strcat( query, "'"); + break; + default: + xassert(dca != dca); + } + } + if (part != NULL) + strcat(query, part); + if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS) + != SQL_SUCCESS) + { + xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query); + extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC); + xfree(query); + xfree(template); + return 1; + } + + xfree(query); + xfree(template); + return 0; +} + +int db_iodbc_close(TABDCA *dca, void *link) +{ + struct db_odbc *sql; + + sql = (struct db_odbc *) link; + xassert(sql != NULL); + /* Commit */ + if ( sql->mode == 'W' ) + dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); + if ( sql->mode == 'R' ) + dl_SQLCloseCursor(sql->hstmt); + + dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); + dl_SQLDisconnect(sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); + dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); + if ( sql->mode == 'W' ) + xfree(sql->query); + xfree(sql); + dca->link = NULL; + return 0; +} + +static void extract_error( + char *fn, + SQLHANDLE handle, + SQLSMALLINT type) +{ + SQLINTEGER i = 0; + SQLINTEGER native; + SQLCHAR state[ 7 ]; + SQLCHAR text[256]; + SQLSMALLINT len; + SQLRETURN ret; + + xprintf("\nThe driver reported the following diagnostics whilst " + "running %s\n", fn); + + do + { + ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text, + sizeof(text), &len ); + if (SQL_SUCCEEDED(ret)) + xprintf("%s:%ld:%ld:%s\n", state, i, native, text); + } + while( ret == SQL_SUCCESS ); +} + +static int is_numeric(SQLSMALLINT coltype) +{ + int ret = 0; + switch (coltype) + { + case SQL_DECIMAL: + case SQL_NUMERIC: + case SQL_SMALLINT: + case SQL_INTEGER: + case SQL_REAL: + case SQL_FLOAT: + case SQL_DOUBLE: + case SQL_TINYINT: + case SQL_BIGINT: + ret = 1; + break; + } + return ret; +} + +#endif + +/**********************************************************************/ + +#ifndef HAVE_MYSQL + +void *db_mysql_open(TABDCA *dca, int mode) +{ xassert(dca == dca); + xassert(mode == mode); + xprintf("MySQL table driver not supported\n"); + return NULL; +} + +int db_mysql_read(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_mysql_write(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +int db_mysql_close(TABDCA *dca, void *link) +{ xassert(dca != dca); + xassert(link != link); + return 0; +} + +#else + +#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) +#include +#endif + +#ifdef __CYGWIN__ +#define byte_defined 1 +#endif + +#if 0 /* 12/II-2014; to fix namespace bug */ +#include +#include +#endif +#include + +struct db_mysql +{ + int mode; /*'R' = Read, 'W' = Write*/ + MYSQL *con; /*connection*/ + MYSQL_RES *res; /*result*/ + int nf; + /* number of fields in the csv file */ + int ref[1+SQL_FIELD_MAX]; + /* ref[k] = k', if k-th field of the csv file corresponds to + k'-th field in the table statement; if ref[k] = 0, k-th field + of the csv file is ignored */ + char *query; + /* query generated by db_mysql_open */ +}; + +void STDCALL dl_mysql_close(MYSQL *sock) +{ + typedef void STDCALL ep_mysql_close(MYSQL *sock); + + ep_mysql_close *fn; + fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close"); + xassert(fn != NULL); + return (*fn)(sock); +} + +const char * STDCALL dl_mysql_error(MYSQL *mysql) +{ + typedef const char * STDCALL ep_mysql_error(MYSQL *mysql); + + ep_mysql_error *fn; + fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res) +{ + typedef MYSQL_FIELD * STDCALL + ep_mysql_fetch_fields(MYSQL_RES *res); + + ep_mysql_fetch_fields *fn; + fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields"); + xassert(fn != NULL); + return (*fn)(res); +} + +unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result) +{ + typedef unsigned long * STDCALL + ep_mysql_fetch_lengths(MYSQL_RES *result); + + ep_mysql_fetch_lengths *fn; + fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql, + "mysql_fetch_lengths"); + xassert(fn != NULL); + return (*fn)(result); +} + +MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result) +{ + typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result); + + ep_mysql_fetch_row *fn; + fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row"); + xassert(fn != NULL); + return (*fn)(result); +} + +unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql) +{ + typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql); + + ep_mysql_field_count *fn; + fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +MYSQL * STDCALL dl_mysql_init(MYSQL *mysql) +{ + typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql); + + ep_mysql_init *fn; + fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res) +{ + typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res); + + ep_mysql_num_fields *fn; + fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields"); + xassert(fn != NULL); + return (*fn)(res); +} + +int STDCALL dl_mysql_query(MYSQL *mysql, const char *q) +{ + typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q); + + ep_mysql_query *fn; + fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query"); + xassert(fn != NULL); + return (*fn)(mysql, q); +} + +MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag) +{ + typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql, + const char *host, + const char *user, + const char *passwd, + const char *db, + unsigned int port, + const char *unix_socket, + unsigned long clientflag); + + ep_mysql_real_connect *fn; + fn = (ep_mysql_real_connect *) xdlsym(h_mysql, + "mysql_real_connect"); + xassert(fn != NULL); + return (*fn)(mysql, host, user, passwd, db, port, unix_socket, + clientflag); +} + +MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql) +{ + typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql); + ep_mysql_use_result *fn; + fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result"); + xassert(fn != NULL); + return (*fn)(mysql); +} + +/*********************************************************************** +* NAME +* +* db_mysql_open - open connection to ODBC data base +* +* SYNOPSIS +* +* #include "mplsql.h" +* void *db_mysql_open(TABDCA *dca, int mode); +* +* DESCRIPTION +* +* The routine db_mysql_open opens a connection to a MySQL data base. +* It then executes the sql statements passed. +* +* In the case of table read the SELECT statement is executed. +* +* In the case of table write the INSERT statement is prepared. +* RETURNS +* +* The routine returns a pointer to data storage area created. */ + +void *db_mysql_open(TABDCA *dca, int mode) +{ void *ret; + char **sqllines; + + sqllines = args_concat(dca); + if (sqllines == NULL) + { xprintf("Missing arguments in table statement.\n" + "Please, supply table driver, dsn, and query.\n"); + return NULL; + } + ret = db_mysql_open_int(dca, mode, (const char **) sqllines); + free_buffer(sqllines); + return ret; +} + +static void *db_mysql_open_int(TABDCA *dca, int mode, const char + **sqllines) +{ + struct db_mysql *sql = NULL; + char *arg = NULL; + const char *field; + MYSQL_FIELD *fields; + char *keyword; + char *value; + char *query; + char *dsn; +/* "Server=[server_name];Database=[database_name];UID=[username];*/ +/* PWD=[password];Port=[port]"*/ + char *server = NULL; /* Server */ + char *user = NULL; /* UID */ + char *password = NULL; /* PWD */ + char *database = NULL; /* Database */ + unsigned int port = 0; /* Port */ + int narg; + int i, j, total; + + if (libmysql == NULL) + { + xprintf("No loader for shared MySQL library available\n"); + return NULL; + } + + if (h_mysql == NULL) + { + h_mysql = xdlopen(libmysql); + if (h_mysql == NULL) + { xprintf("unable to open library %s\n", libmysql); + xprintf("%s\n", get_err_msg()); + return NULL; + } + } + + sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql)); + if (sql == NULL) + return NULL; + sql->mode = mode; + sql->res = NULL; + sql->query = NULL; + sql->nf = mpl_tab_num_flds(dca); + + narg = mpl_tab_num_args(dca); + if (narg < 3 ) + xprintf("MySQL driver: string list too short \n"); + + /* get connection string*/ + dsn = (char *) mpl_tab_get_arg(dca, 2); + /* copy connection string*/ + i = strlen(dsn); + i++; + arg = xmalloc(i * sizeof(char)); + strcpy(arg, dsn); + /*tokenize connection string*/ +#if 0 /* 29/I-2017 */ + for (i = 1, keyword = strtok (arg, "="); (keyword != NULL); + keyword = strtok (NULL, "="), i++) +#else + for (i = 1, keyword = xstrtok (arg, "="); (keyword != NULL); + keyword = xstrtok (NULL, "="), i++) +#endif + { +#if 0 /* 29/I-2017 */ + value = strtok (NULL, ";"); +#else + value = xstrtok (NULL, ";"); +#endif + if (value==NULL) + { + xprintf("db_mysql_open: Missing value for keyword %s\n", + keyword); + xfree(arg); + xfree(sql); + return NULL; + } + if (0 == strcmp(keyword, "Server")) + server = value; + else if (0 == strcmp(keyword, "Database")) + database = value; + else if (0 == strcmp(keyword, "UID")) + user = value; + else if (0 == strcmp(keyword, "PWD")) + password = value; + else if (0 == strcmp(keyword, "Port")) + port = (unsigned int) atol(value); + } + /* Connect to database */ + sql->con = dl_mysql_init(NULL); + if (!dl_mysql_real_connect(sql->con, server, user, password, database, + port, NULL, 0)) + { + xprintf("db_mysql_open: Connect failed\n"); + xprintf("%s\n", dl_mysql_error(sql->con)); + xfree(arg); + xfree(sql); + return NULL; + } + xfree(arg); + + for(j = 0; sqllines[j+1] != NULL; j++) + { query = (char *) sqllines[j]; + xprintf("%s\n", query); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(sql); + return NULL; + } + } + + if ( sql->mode == 'R' ) + { sql->nf = mpl_tab_num_flds(dca); + for(j = 0; sqllines[j] != NULL; j++) + arg = (char *) sqllines[j]; + total = strlen(arg); + if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) + { + total = strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, arg); + } + else + { + query = db_generate_select_stmt(dca); + } + xprintf("%s\n", query); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(query); + xfree(sql); + return NULL; + } + xfree(query); + sql->res = dl_mysql_use_result(sql->con); + if (sql->res) + { + /* create references between query results and table fields*/ + total = dl_mysql_num_fields(sql->res); + if (total > SQL_FIELD_MAX) + { xprintf("db_mysql_open: Too many fields (> %d) in query.\n" + "\"%s\"\n", SQL_FIELD_MAX, query); + xprintf("%s\n",dl_mysql_error(sql->con)); + dl_mysql_close(sql->con); + xfree(query); + xfree(sql); + return NULL; + } + fields = dl_mysql_fetch_fields(sql->res); + for (i = 1; i <= total; i++) + { + for (j = sql->nf; j >= 1; j--) + { + if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name) + == 0) + break; + } + sql->ref[i] = j; + } + } + else + { + if(dl_mysql_field_count(sql->con) == 0) + { + xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n", + query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(sql); + return NULL; + } + else + { + xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(sql); + return NULL; + } + } + } + else if ( sql->mode == 'W' ) + { for(j = 0; sqllines[j] != NULL; j++) + arg = (char *) sqllines[j]; + if ( NULL != strchr(arg, '?') ) + { + total = strlen(arg); + query = xmalloc( (total+1) * sizeof(char)); + strcpy (query, arg); + } + else + query = db_generate_insert_stmt(dca); + sql->query = query; + xprintf("%s\n", query); + } + return sql; +} + +int db_mysql_read(TABDCA *dca, void *link) +{ struct db_mysql *sql; + char buf[255+1]; + char **row; + unsigned long *lengths; + MYSQL_FIELD *fields; + double num; + int len; + unsigned long num_fields; + int i; + + sql = (struct db_mysql *) link; + + xassert(sql != NULL); + xassert(sql->mode == 'R'); + if (NULL == sql->res) + { + xprintf("db_mysql_read: no result set available"); + return 1; + } + if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) { + return -1; /*EOF*/ + } + lengths = dl_mysql_fetch_lengths(sql->res); + fields = dl_mysql_fetch_fields(sql->res); + num_fields = dl_mysql_num_fields(sql->res); + for (i=1; i <= num_fields; i++) + { + if (row[i-1] != NULL) + { len = (size_t) lengths[i-1]; + if (len > 255) + len = 255; + strncpy(buf, (const char *) row[i-1], len); + buf[len] = 0x00; + if (0 != (fields[i-1].flags & NUM_FLAG)) + { strspx(buf); /* remove spaces*/ + if (str2num(buf, &num) != 0) + { xprintf("'%s' cannot be converted to a number.\n", buf); + return 1; + } + if (sql->ref[i] > 0) + mpl_tab_set_num(dca, sql->ref[i], num); + } + else + { if (sql->ref[i] > 0) + mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); + } + } + } + return 0; +} + +int db_mysql_write(TABDCA *dca, void *link) +{ + struct db_mysql *sql; + char *part; + char *query; + char *template; + char num[50]; + int k; + int len; + int nf; + + sql = (struct db_mysql *) link; + xassert(sql != NULL); + xassert(sql->mode == 'W'); + + len = strlen(sql->query); + template = (char *) xmalloc( (len + 1) * sizeof(char) ); + strcpy(template, sql->query); + + nf = mpl_tab_num_flds(dca); + for (k = 1; k <= nf; k++) + { switch (mpl_tab_get_type(dca, k)) + { case 'N': + len += 20; + break; + case 'S': + len += db_escaped_string_length(mpl_tab_get_str(dca, k)); + len += 2; + break; + default: + xassert(dca != dca); + } + } + query = xmalloc( (len + 1 ) * sizeof(char) ); + query[0] = 0x00; +#if 0 /* 29/I-2017 */ + for (k = 1, part = strtok (template, "?"); (part != NULL); + part = strtok (NULL, "?"), k++) +#else + for (k = 1, part = xstrtok (template, "?"); (part != NULL); + part = xstrtok (NULL, "?"), k++) +#endif + { + if (k > nf) break; + strcat( query, part ); + switch (mpl_tab_get_type(dca, k)) + { case 'N': +#if 0 /* 02/XI-2010 by xypron */ + sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); +#else + sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); +#endif + strcat( query, num ); + break; + case 'S': + strcat( query, "'"); + db_escape_string( query + strlen(query), + mpl_tab_get_str(dca, k) ); + strcat( query, "'"); + break; + default: + xassert(dca != dca); + } + } + if (part != NULL) + strcat(query, part); + if (dl_mysql_query(sql->con, query)) + { + xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query); + xprintf("%s\n",dl_mysql_error(sql->con)); + xfree(query); + xfree(template); + return 1; + } + + xfree(query); + xfree(template); + return 0; + } + +int db_mysql_close(TABDCA *dca, void *link) +{ + struct db_mysql *sql; + + sql = (struct db_mysql *) link; + xassert(sql != NULL); + dl_mysql_close(sql->con); + if ( sql->mode == 'W' ) + xfree(sql->query); + xfree(sql); + dca->link = NULL; + return 0; +} + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.h b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.h new file mode 100644 index 000000000..11d438bbd --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/mpl/mplsql.h @@ -0,0 +1,63 @@ +/* mplsql.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Heinrich Schuchardt . +* +* Copyright (C) 2003-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef MPLSQL_H +#define MPLSQL_H + +#define db_iodbc_open _glp_db_iodbc_open +void *db_iodbc_open(TABDCA *dca, int mode); +/* open iODBC database connection */ + +#define db_iodbc_read _glp_db_iodbc_read +int db_iodbc_read(TABDCA *dca, void *link); +/* read data from iODBC */ + +#define db_iodbc_write _glp_db_iodbc_write +int db_iodbc_write(TABDCA *dca, void *link); +/* write data to iODBC */ + +#define db_iodbc_close _glp_db_iodbc_close +int db_iodbc_close(TABDCA *dca, void *link); +/* close iODBC database connection */ + +#define db_mysql_open _glp_db_mysql_open +void *db_mysql_open(TABDCA *dca, int mode); +/* open MySQL database connection */ + +#define db_mysql_read _glp_db_mysql_read +int db_mysql_read(TABDCA *dca, void *link); +/* read data from MySQL */ + +#define db_mysql_write _glp_db_mysql_write +int db_mysql_write(TABDCA *dca, void *link); +/* write data to MySQL */ + +#define db_mysql_close _glp_db_mysql_close +int db_mysql_close(TABDCA *dca, void *link); +/* close MySQL database connection */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp.h b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp.h new file mode 100644 index 000000000..428cb23c6 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp.h @@ -0,0 +1,645 @@ +/* npp.h (LP/MIP preprocessor) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef NPP_H +#define NPP_H + +#include "prob.h" + +#if 0 /* 20/XI-2017 */ +typedef struct NPP NPP; +#else +typedef struct glp_prep NPP; +#endif +typedef struct NPPROW NPPROW; +typedef struct NPPCOL NPPCOL; +typedef struct NPPAIJ NPPAIJ; +typedef struct NPPTSE NPPTSE; +typedef struct NPPLFE NPPLFE; + +#if 0 /* 20/XI-2017 */ +struct NPP +#else +struct glp_prep +#endif +{ /* LP/MIP preprocessor workspace */ + /*--------------------------------------------------------------*/ + /* original problem segment */ + int orig_dir; + /* optimization direction flag: + GLP_MIN - minimization + GLP_MAX - maximization */ + int orig_m; + /* number of rows */ + int orig_n; + /* number of columns */ + int orig_nnz; + /* number of non-zero constraint coefficients */ + /*--------------------------------------------------------------*/ + /* transformed problem segment (always minimization) */ + DMP *pool; + /* memory pool to store problem components */ + char *name; + /* problem name (1 to 255 chars); NULL means no name is assigned + to the problem */ + char *obj; + /* objective function name (1 to 255 chars); NULL means no name + is assigned to the objective function */ + double c0; + /* constant term of the objective function */ + int nrows; + /* number of rows introduced into the problem; this count + increases by one every time a new row is added and never + decreases; thus, actual number of rows may be less than nrows + due to row deletions */ + int ncols; + /* number of columns introduced into the problem; this count + increases by one every time a new column is added and never + decreases; thus, actual number of column may be less than + ncols due to column deletions */ + NPPROW *r_head; + /* pointer to the beginning of the row list */ + NPPROW *r_tail; + /* pointer to the end of the row list */ + NPPCOL *c_head; + /* pointer to the beginning of the column list */ + NPPCOL *c_tail; + /* pointer to the end of the column list */ + /*--------------------------------------------------------------*/ + /* transformation history */ + DMP *stack; + /* memory pool to store transformation entries */ + NPPTSE *top; + /* pointer to most recent transformation entry */ +#if 0 /* 16/XII-2009 */ + int count[1+25]; + /* transformation statistics */ +#endif + /*--------------------------------------------------------------*/ + /* resultant (preprocessed) problem segment */ + int m; + /* number of rows */ + int n; + /* number of columns */ + int nnz; + /* number of non-zero constraint coefficients */ + int *row_ref; /* int row_ref[1+m]; */ + /* row_ref[i], 1 <= i <= m, is the reference number assigned to + a row, which is i-th row of the resultant problem */ + int *col_ref; /* int col_ref[1+n]; */ + /* col_ref[j], 1 <= j <= n, is the reference number assigned to + a column, which is j-th column of the resultant problem */ + /*--------------------------------------------------------------*/ + /* recovered solution segment */ + int sol; + /* solution indicator: + GLP_SOL - basic solution + GLP_IPT - interior-point solution + GLP_MIP - mixed integer solution */ + int scaling; + /* scaling option: + GLP_OFF - scaling is disabled + GLP_ON - scaling is enabled */ + int p_stat; + /* status of primal basic solution: + GLP_UNDEF - primal solution is undefined + GLP_FEAS - primal solution is feasible + GLP_INFEAS - primal solution is infeasible + GLP_NOFEAS - no primal feasible solution exists */ + int d_stat; + /* status of dual basic solution: + GLP_UNDEF - dual solution is undefined + GLP_FEAS - dual solution is feasible + GLP_INFEAS - dual solution is infeasible + GLP_NOFEAS - no dual feasible solution exists */ + int t_stat; + /* status of interior-point solution: + GLP_UNDEF - interior solution is undefined + GLP_OPT - interior solution is optimal */ + int i_stat; + /* status of mixed integer solution: + GLP_UNDEF - integer solution is undefined + GLP_OPT - integer solution is optimal + GLP_FEAS - integer solution is feasible + GLP_NOFEAS - no integer solution exists */ + char *r_stat; /* char r_stat[1+nrows]; */ + /* r_stat[i], 1 <= i <= nrows, is status of i-th row: + GLP_BS - inactive constraint + GLP_NL - active constraint on lower bound + GLP_NU - active constraint on upper bound + GLP_NF - active free row + GLP_NS - active equality constraint */ + char *c_stat; /* char c_stat[1+nrows]; */ + /* c_stat[j], 1 <= j <= nrows, is status of j-th column: + GLP_BS - basic variable + GLP_NL - non-basic variable on lower bound + GLP_NU - non-basic variable on upper bound + GLP_NF - non-basic free variable + GLP_NS - non-basic fixed variable */ + double *r_pi; /* double r_pi[1+nrows]; */ + /* r_pi[i], 1 <= i <= nrows, is Lagrange multiplier (dual value) + for i-th row (constraint) */ + double *c_value; /* double c_value[1+ncols]; */ + /* c_value[j], 1 <= j <= ncols, is primal value of j-th column + (structural variable) */ +}; + +struct NPPROW +{ /* row (constraint) */ + int i; + /* reference number assigned to the row, 1 <= i <= nrows */ + char *name; + /* row name (1 to 255 chars); NULL means no name is assigned to + the row */ + double lb; + /* lower bound; -DBL_MAX means the row has no lower bound */ + double ub; + /* upper bound; +DBL_MAX means the row has no upper bound */ + NPPAIJ *ptr; + /* pointer to the linked list of constraint coefficients */ + int temp; + /* working field used by preprocessor routines */ + NPPROW *prev; + /* pointer to previous row in the row list */ + NPPROW *next; + /* pointer to next row in the row list */ +}; + +struct NPPCOL +{ /* column (variable) */ + int j; + /* reference number assigned to the column, 1 <= j <= ncols */ + char *name; + /* column name (1 to 255 chars); NULL means no name is assigned + to the column */ + char is_int; + /* 0 means continuous variable; 1 means integer variable */ + double lb; + /* lower bound; -DBL_MAX means the column has no lower bound */ + double ub; + /* upper bound; +DBL_MAX means the column has no upper bound */ + double coef; + /* objective coefficient */ + NPPAIJ *ptr; + /* pointer to the linked list of constraint coefficients */ + int temp; + /* working field used by preprocessor routines */ +#if 1 /* 28/XII-2009 */ + union + { double ll; + /* implied column lower bound */ + int pos; + /* vertex ordinal number corresponding to this binary column + in the conflict graph (0, if the vertex does not exist) */ + } ll; + union + { double uu; + /* implied column upper bound */ + int neg; + /* vertex ordinal number corresponding to complement of this + binary column in the conflict graph (0, if the vertex does + not exist) */ + } uu; +#endif + NPPCOL *prev; + /* pointer to previous column in the column list */ + NPPCOL *next; + /* pointer to next column in the column list */ +}; + +struct NPPAIJ +{ /* constraint coefficient */ + NPPROW *row; + /* pointer to corresponding row */ + NPPCOL *col; + /* pointer to corresponding column */ + double val; + /* (non-zero) coefficient value */ + NPPAIJ *r_prev; + /* pointer to previous coefficient in the same row */ + NPPAIJ *r_next; + /* pointer to next coefficient in the same row */ + NPPAIJ *c_prev; + /* pointer to previous coefficient in the same column */ + NPPAIJ *c_next; + /* pointer to next coefficient in the same column */ +}; + +struct NPPTSE +{ /* transformation stack entry */ + int (*func)(NPP *npp, void *info); + /* pointer to routine performing back transformation */ + void *info; + /* pointer to specific info (depends on the transformation) */ + NPPTSE *link; + /* pointer to another entry created *before* this entry */ +}; + +struct NPPLFE +{ /* linear form element */ + int ref; + /* row/column reference number */ + double val; + /* (non-zero) coefficient value */ + NPPLFE *next; + /* pointer to another element */ +}; + +#define npp_create_wksp _glp_npp_create_wksp +NPP *npp_create_wksp(void); +/* create LP/MIP preprocessor workspace */ + +#define npp_insert_row _glp_npp_insert_row +void npp_insert_row(NPP *npp, NPPROW *row, int where); +/* insert row to the row list */ + +#define npp_remove_row _glp_npp_remove_row +void npp_remove_row(NPP *npp, NPPROW *row); +/* remove row from the row list */ + +#define npp_activate_row _glp_npp_activate_row +void npp_activate_row(NPP *npp, NPPROW *row); +/* make row active */ + +#define npp_deactivate_row _glp_npp_deactivate_row +void npp_deactivate_row(NPP *npp, NPPROW *row); +/* make row inactive */ + +#define npp_insert_col _glp_npp_insert_col +void npp_insert_col(NPP *npp, NPPCOL *col, int where); +/* insert column to the column list */ + +#define npp_remove_col _glp_npp_remove_col +void npp_remove_col(NPP *npp, NPPCOL *col); +/* remove column from the column list */ + +#define npp_activate_col _glp_npp_activate_col +void npp_activate_col(NPP *npp, NPPCOL *col); +/* make column active */ + +#define npp_deactivate_col _glp_npp_deactivate_col +void npp_deactivate_col(NPP *npp, NPPCOL *col); +/* make column inactive */ + +#define npp_add_row _glp_npp_add_row +NPPROW *npp_add_row(NPP *npp); +/* add new row to the current problem */ + +#define npp_add_col _glp_npp_add_col +NPPCOL *npp_add_col(NPP *npp); +/* add new column to the current problem */ + +#define npp_add_aij _glp_npp_add_aij +NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val); +/* add new element to the constraint matrix */ + +#define npp_row_nnz _glp_npp_row_nnz +int npp_row_nnz(NPP *npp, NPPROW *row); +/* count number of non-zero coefficients in row */ + +#define npp_col_nnz _glp_npp_col_nnz +int npp_col_nnz(NPP *npp, NPPCOL *col); +/* count number of non-zero coefficients in column */ + +#define npp_push_tse _glp_npp_push_tse +void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), + int size); +/* push new entry to the transformation stack */ + +#define npp_erase_row _glp_npp_erase_row +void npp_erase_row(NPP *npp, NPPROW *row); +/* erase row content to make it empty */ + +#define npp_del_row _glp_npp_del_row +void npp_del_row(NPP *npp, NPPROW *row); +/* remove row from the current problem */ + +#define npp_del_col _glp_npp_del_col +void npp_del_col(NPP *npp, NPPCOL *col); +/* remove column from the current problem */ + +#define npp_del_aij _glp_npp_del_aij +void npp_del_aij(NPP *npp, NPPAIJ *aij); +/* remove element from the constraint matrix */ + +#define npp_load_prob _glp_npp_load_prob +void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, + int scaling); +/* load original problem into the preprocessor workspace */ + +#define npp_build_prob _glp_npp_build_prob +void npp_build_prob(NPP *npp, glp_prob *prob); +/* build resultant (preprocessed) problem */ + +#define npp_postprocess _glp_npp_postprocess +void npp_postprocess(NPP *npp, glp_prob *prob); +/* postprocess solution from the resultant problem */ + +#define npp_unload_sol _glp_npp_unload_sol +void npp_unload_sol(NPP *npp, glp_prob *orig); +/* store solution to the original problem */ + +#define npp_delete_wksp _glp_npp_delete_wksp +void npp_delete_wksp(NPP *npp); +/* delete LP/MIP preprocessor workspace */ + +#define npp_error() + +#define npp_free_row _glp_npp_free_row +void npp_free_row(NPP *npp, NPPROW *p); +/* process free (unbounded) row */ + +#define npp_geq_row _glp_npp_geq_row +void npp_geq_row(NPP *npp, NPPROW *p); +/* process row of 'not less than' type */ + +#define npp_leq_row _glp_npp_leq_row +void npp_leq_row(NPP *npp, NPPROW *p); +/* process row of 'not greater than' type */ + +#define npp_free_col _glp_npp_free_col +void npp_free_col(NPP *npp, NPPCOL *q); +/* process free (unbounded) column */ + +#define npp_lbnd_col _glp_npp_lbnd_col +void npp_lbnd_col(NPP *npp, NPPCOL *q); +/* process column with (non-zero) lower bound */ + +#define npp_ubnd_col _glp_npp_ubnd_col +void npp_ubnd_col(NPP *npp, NPPCOL *q); +/* process column with upper bound */ + +#define npp_dbnd_col _glp_npp_dbnd_col +void npp_dbnd_col(NPP *npp, NPPCOL *q); +/* process non-negative column with upper bound */ + +#define npp_fixed_col _glp_npp_fixed_col +void npp_fixed_col(NPP *npp, NPPCOL *q); +/* process fixed column */ + +#define npp_make_equality _glp_npp_make_equality +int npp_make_equality(NPP *npp, NPPROW *p); +/* process row with almost identical bounds */ + +#define npp_make_fixed _glp_npp_make_fixed +int npp_make_fixed(NPP *npp, NPPCOL *q); +/* process column with almost identical bounds */ + +#define npp_empty_row _glp_npp_empty_row +int npp_empty_row(NPP *npp, NPPROW *p); +/* process empty row */ + +#define npp_empty_col _glp_npp_empty_col +int npp_empty_col(NPP *npp, NPPCOL *q); +/* process empty column */ + +#define npp_implied_value _glp_npp_implied_value +int npp_implied_value(NPP *npp, NPPCOL *q, double s); +/* process implied column value */ + +#define npp_eq_singlet _glp_npp_eq_singlet +int npp_eq_singlet(NPP *npp, NPPROW *p); +/* process row singleton (equality constraint) */ + +#define npp_implied_lower _glp_npp_implied_lower +int npp_implied_lower(NPP *npp, NPPCOL *q, double l); +/* process implied column lower bound */ + +#define npp_implied_upper _glp_npp_implied_upper +int npp_implied_upper(NPP *npp, NPPCOL *q, double u); +/* process implied upper bound of column */ + +#define npp_ineq_singlet _glp_npp_ineq_singlet +int npp_ineq_singlet(NPP *npp, NPPROW *p); +/* process row singleton (inequality constraint) */ + +#define npp_implied_slack _glp_npp_implied_slack +void npp_implied_slack(NPP *npp, NPPCOL *q); +/* process column singleton (implied slack variable) */ + +#define npp_implied_free _glp_npp_implied_free +int npp_implied_free(NPP *npp, NPPCOL *q); +/* process column singleton (implied free variable) */ + +#define npp_eq_doublet _glp_npp_eq_doublet +NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); +/* process row doubleton (equality constraint) */ + +#define npp_forcing_row _glp_npp_forcing_row +int npp_forcing_row(NPP *npp, NPPROW *p, int at); +/* process forcing row */ + +#define npp_analyze_row _glp_npp_analyze_row +int npp_analyze_row(NPP *npp, NPPROW *p); +/* perform general row analysis */ + +#define npp_inactive_bound _glp_npp_inactive_bound +void npp_inactive_bound(NPP *npp, NPPROW *p, int which); +/* remove row lower/upper inactive bound */ + +#define npp_implied_bounds _glp_npp_implied_bounds +void npp_implied_bounds(NPP *npp, NPPROW *p); +/* determine implied column bounds */ + +#define npp_binarize_prob _glp_npp_binarize_prob +int npp_binarize_prob(NPP *npp); +/* binarize MIP problem */ + +#define npp_is_packing _glp_npp_is_packing +int npp_is_packing(NPP *npp, NPPROW *row); +/* test if constraint is packing inequality */ + +#define npp_hidden_packing _glp_npp_hidden_packing +int npp_hidden_packing(NPP *npp, NPPROW *row); +/* identify hidden packing inequality */ + +#define npp_implied_packing _glp_npp_implied_packing +int npp_implied_packing(NPP *npp, NPPROW *row, int which, + NPPCOL *var[], char set[]); +/* identify implied packing inequality */ + +#define npp_is_covering _glp_npp_is_covering +int npp_is_covering(NPP *npp, NPPROW *row); +/* test if constraint is covering inequality */ + +#define npp_hidden_covering _glp_npp_hidden_covering +int npp_hidden_covering(NPP *npp, NPPROW *row); +/* identify hidden covering inequality */ + +#define npp_is_partitioning _glp_npp_is_partitioning +int npp_is_partitioning(NPP *npp, NPPROW *row); +/* test if constraint is partitioning equality */ + +#define npp_reduce_ineq_coef _glp_npp_reduce_ineq_coef +int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); +/* reduce inequality constraint coefficients */ + +#define npp_clean_prob _glp_npp_clean_prob +void npp_clean_prob(NPP *npp); +/* perform initial LP/MIP processing */ + +#define npp_process_row _glp_npp_process_row +int npp_process_row(NPP *npp, NPPROW *row, int hard); +/* perform basic row processing */ + +#define npp_improve_bounds _glp_npp_improve_bounds +int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); +/* improve current column bounds */ + +#define npp_process_col _glp_npp_process_col +int npp_process_col(NPP *npp, NPPCOL *col); +/* perform basic column processing */ + +#define npp_process_prob _glp_npp_process_prob +int npp_process_prob(NPP *npp, int hard); +/* perform basic LP/MIP processing */ + +#define npp_simplex _glp_npp_simplex +int npp_simplex(NPP *npp, const glp_smcp *parm); +/* process LP prior to applying primal/dual simplex method */ + +#define npp_integer _glp_npp_integer +int npp_integer(NPP *npp, const glp_iocp *parm); +/* process MIP prior to applying branch-and-bound method */ + +/**********************************************************************/ + +#define npp_sat_free_row _glp_npp_sat_free_row +void npp_sat_free_row(NPP *npp, NPPROW *p); +/* process free (unbounded) row */ + +#define npp_sat_fixed_col _glp_npp_sat_fixed_col +int npp_sat_fixed_col(NPP *npp, NPPCOL *q); +/* process fixed column */ + +#define npp_sat_is_bin_comb _glp_npp_sat_is_bin_comb +int npp_sat_is_bin_comb(NPP *npp, NPPROW *row); +/* test if row is binary combination */ + +#define npp_sat_num_pos_coef _glp_npp_sat_num_pos_coef +int npp_sat_num_pos_coef(NPP *npp, NPPROW *row); +/* determine number of positive coefficients */ + +#define npp_sat_num_neg_coef _glp_npp_sat_num_neg_coef +int npp_sat_num_neg_coef(NPP *npp, NPPROW *row); +/* determine number of negative coefficients */ + +#define npp_sat_is_cover_ineq _glp_npp_sat_is_cover_ineq +int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row); +/* test if row is covering inequality */ + +#define npp_sat_is_pack_ineq _glp_npp_sat_is_pack_ineq +int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row); +/* test if row is packing inequality */ + +#define npp_sat_is_partn_eq _glp_npp_sat_is_partn_eq +int npp_sat_is_partn_eq(NPP *npp, NPPROW *row); +/* test if row is partitioning equality */ + +#define npp_sat_reverse_row _glp_npp_sat_reverse_row +int npp_sat_reverse_row(NPP *npp, NPPROW *row); +/* multiply both sides of row by -1 */ + +#define npp_sat_split_pack _glp_npp_sat_split_pack +NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nnn); +/* split packing inequality */ + +#define npp_sat_encode_pack _glp_npp_sat_encode_pack +void npp_sat_encode_pack(NPP *npp, NPPROW *row); +/* encode packing inequality */ + +typedef struct NPPLIT NPPLIT; +typedef struct NPPLSE NPPLSE; +typedef struct NPPSED NPPSED; + +struct NPPLIT +{ /* literal (binary variable or its negation) */ + NPPCOL *col; + /* pointer to binary variable; NULL means constant false */ + int neg; + /* negation flag: + 0 - literal is variable (or constant false) + 1 - literal is negation of variable (or constant true) */ +}; + +struct NPPLSE +{ /* literal set element */ + NPPLIT lit; + /* literal */ + NPPLSE *next; + /* pointer to another element */ +}; + +struct NPPSED +{ /* summation encoding descriptor */ + /* this struct describes the equality + x + y + z = s + 2 * c, + which was encoded as CNF and included into the transformed + problem; here x and y are literals, z is either a literal or + constant zero, s and c are binary variables modeling, resp., + the low and high (carry) sum bits */ + NPPLIT x, y, z; + /* literals; if z.col = NULL, z is constant zero */ + NPPCOL *s, *c; + /* binary variables modeling the sum bits */ +}; + +#define npp_sat_encode_sum2 _glp_npp_sat_encode_sum2 +void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed); +/* encode 2-bit summation */ + +#define npp_sat_encode_sum3 _glp_npp_sat_encode_sum3 +void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed); +/* encode 3-bit summation */ + +#define npp_sat_encode_sum_ax _glp_npp_sat_encode_sum_ax +int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]); +/* encode linear combination of 0-1 variables */ + +#define npp_sat_normalize_clause _glp_npp_sat_normalize_clause +int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]); +/* normalize clause */ + +#define npp_sat_encode_clause _glp_npp_sat_encode_clause +NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]); +/* translate clause to cover inequality */ + +#define npp_sat_encode_geq _glp_npp_sat_encode_geq +int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs); +/* encode "not less than" constraint */ + +#define npp_sat_encode_leq _glp_npp_sat_encode_leq +int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs); +/* encode "not greater than" constraint */ + +#define npp_sat_encode_row _glp_npp_sat_encode_row +int npp_sat_encode_row(NPP *npp, NPPROW *row); +/* encode constraint (row) of general type */ + +#define npp_sat_encode_prob _glp_npp_sat_encode_prob +int npp_sat_encode_prob(NPP *npp); +/* encode 0-1 feasibility problem */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp1.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp1.c new file mode 100644 index 000000000..51758bad3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp1.c @@ -0,0 +1,937 @@ +/* npp1.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +NPP *npp_create_wksp(void) +{ /* create LP/MIP preprocessor workspace */ + NPP *npp; + npp = xmalloc(sizeof(NPP)); + npp->orig_dir = 0; + npp->orig_m = npp->orig_n = npp->orig_nnz = 0; + npp->pool = dmp_create_pool(); + npp->name = npp->obj = NULL; + npp->c0 = 0.0; + npp->nrows = npp->ncols = 0; + npp->r_head = npp->r_tail = NULL; + npp->c_head = npp->c_tail = NULL; + npp->stack = dmp_create_pool(); + npp->top = NULL; +#if 0 /* 16/XII-2009 */ + memset(&npp->count, 0, sizeof(npp->count)); +#endif + npp->m = npp->n = npp->nnz = 0; + npp->row_ref = npp->col_ref = NULL; + npp->sol = npp->scaling = 0; + npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0; + npp->r_stat = NULL; + /*npp->r_prim =*/ npp->r_pi = NULL; + npp->c_stat = NULL; + npp->c_value = /*npp->c_dual =*/ NULL; + return npp; +} + +void npp_insert_row(NPP *npp, NPPROW *row, int where) +{ /* insert row to the row list */ + if (where == 0) + { /* insert row to the beginning of the row list */ + row->prev = NULL; + row->next = npp->r_head; + if (row->next == NULL) + npp->r_tail = row; + else + row->next->prev = row; + npp->r_head = row; + } + else + { /* insert row to the end of the row list */ + row->prev = npp->r_tail; + row->next = NULL; + if (row->prev == NULL) + npp->r_head = row; + else + row->prev->next = row; + npp->r_tail = row; + } + return; +} + +void npp_remove_row(NPP *npp, NPPROW *row) +{ /* remove row from the row list */ + if (row->prev == NULL) + npp->r_head = row->next; + else + row->prev->next = row->next; + if (row->next == NULL) + npp->r_tail = row->prev; + else + row->next->prev = row->prev; + return; +} + +void npp_activate_row(NPP *npp, NPPROW *row) +{ /* make row active */ + if (!row->temp) + { row->temp = 1; + /* move the row to the beginning of the row list */ + npp_remove_row(npp, row); + npp_insert_row(npp, row, 0); + } + return; +} + +void npp_deactivate_row(NPP *npp, NPPROW *row) +{ /* make row inactive */ + if (row->temp) + { row->temp = 0; + /* move the row to the end of the row list */ + npp_remove_row(npp, row); + npp_insert_row(npp, row, 1); + } + return; +} + +void npp_insert_col(NPP *npp, NPPCOL *col, int where) +{ /* insert column to the column list */ + if (where == 0) + { /* insert column to the beginning of the column list */ + col->prev = NULL; + col->next = npp->c_head; + if (col->next == NULL) + npp->c_tail = col; + else + col->next->prev = col; + npp->c_head = col; + } + else + { /* insert column to the end of the column list */ + col->prev = npp->c_tail; + col->next = NULL; + if (col->prev == NULL) + npp->c_head = col; + else + col->prev->next = col; + npp->c_tail = col; + } + return; +} + +void npp_remove_col(NPP *npp, NPPCOL *col) +{ /* remove column from the column list */ + if (col->prev == NULL) + npp->c_head = col->next; + else + col->prev->next = col->next; + if (col->next == NULL) + npp->c_tail = col->prev; + else + col->next->prev = col->prev; + return; +} + +void npp_activate_col(NPP *npp, NPPCOL *col) +{ /* make column active */ + if (!col->temp) + { col->temp = 1; + /* move the column to the beginning of the column list */ + npp_remove_col(npp, col); + npp_insert_col(npp, col, 0); + } + return; +} + +void npp_deactivate_col(NPP *npp, NPPCOL *col) +{ /* make column inactive */ + if (col->temp) + { col->temp = 0; + /* move the column to the end of the column list */ + npp_remove_col(npp, col); + npp_insert_col(npp, col, 1); + } + return; +} + +NPPROW *npp_add_row(NPP *npp) +{ /* add new row to the current problem */ + NPPROW *row; + row = dmp_get_atom(npp->pool, sizeof(NPPROW)); + row->i = ++(npp->nrows); + row->name = NULL; + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + row->ptr = NULL; + row->temp = 0; + npp_insert_row(npp, row, 1); + return row; +} + +NPPCOL *npp_add_col(NPP *npp) +{ /* add new column to the current problem */ + NPPCOL *col; + col = dmp_get_atom(npp->pool, sizeof(NPPCOL)); + col->j = ++(npp->ncols); + col->name = NULL; +#if 0 + col->kind = GLP_CV; +#else + col->is_int = 0; +#endif + col->lb = col->ub = col->coef = 0.0; + col->ptr = NULL; + col->temp = 0; + npp_insert_col(npp, col, 1); + return col; +} + +NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val) +{ /* add new element to the constraint matrix */ + NPPAIJ *aij; + aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ)); + aij->row = row; + aij->col = col; + aij->val = val; + aij->r_prev = NULL; + aij->r_next = row->ptr; + aij->c_prev = NULL; + aij->c_next = col->ptr; + if (aij->r_next != NULL) + aij->r_next->r_prev = aij; + if (aij->c_next != NULL) + aij->c_next->c_prev = aij; + row->ptr = col->ptr = aij; + return aij; +} + +int npp_row_nnz(NPP *npp, NPPROW *row) +{ /* count number of non-zero coefficients in row */ + NPPAIJ *aij; + int nnz; + xassert(npp == npp); + nnz = 0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + nnz++; + return nnz; +} + +int npp_col_nnz(NPP *npp, NPPCOL *col) +{ /* count number of non-zero coefficients in column */ + NPPAIJ *aij; + int nnz; + xassert(npp == npp); + nnz = 0; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + nnz++; + return nnz; +} + +void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), + int size) +{ /* push new entry to the transformation stack */ + NPPTSE *tse; + tse = dmp_get_atom(npp->stack, sizeof(NPPTSE)); + tse->func = func; + tse->info = dmp_get_atom(npp->stack, size); + tse->link = npp->top; + npp->top = tse; + return tse->info; +} + +#if 1 /* 23/XII-2009 */ +void npp_erase_row(NPP *npp, NPPROW *row) +{ /* erase row content to make it empty */ + NPPAIJ *aij; + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } + return; +} +#endif + +void npp_del_row(NPP *npp, NPPROW *row) +{ /* remove row from the current problem */ +#if 0 /* 23/XII-2009 */ + NPPAIJ *aij; +#endif + if (row->name != NULL) + dmp_free_atom(npp->pool, row->name, strlen(row->name)+1); +#if 0 /* 23/XII-2009 */ + while (row->ptr != NULL) + { aij = row->ptr; + row->ptr = aij->r_next; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } +#else + npp_erase_row(npp, row); +#endif + npp_remove_row(npp, row); + dmp_free_atom(npp->pool, row, sizeof(NPPROW)); + return; +} + +void npp_del_col(NPP *npp, NPPCOL *col) +{ /* remove column from the current problem */ + NPPAIJ *aij; + if (col->name != NULL) + dmp_free_atom(npp->pool, col->name, strlen(col->name)+1); + while (col->ptr != NULL) + { aij = col->ptr; + col->ptr = aij->c_next; + if (aij->r_prev == NULL) + aij->row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + } + npp_remove_col(npp, col); + dmp_free_atom(npp->pool, col, sizeof(NPPCOL)); + return; +} + +void npp_del_aij(NPP *npp, NPPAIJ *aij) +{ /* remove element from the constraint matrix */ + if (aij->r_prev == NULL) + aij->row->ptr = aij->r_next; + else + aij->r_prev->r_next = aij->r_next; + if (aij->r_next == NULL) + ; + else + aij->r_next->r_prev = aij->r_prev; + if (aij->c_prev == NULL) + aij->col->ptr = aij->c_next; + else + aij->c_prev->c_next = aij->c_next; + if (aij->c_next == NULL) + ; + else + aij->c_next->c_prev = aij->c_prev; + dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); + return; +} + +void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, + int scaling) +{ /* load original problem into the preprocessor workspace */ + int m = orig->m; + int n = orig->n; + NPPROW **link; + int i, j; + double dir; + xassert(names == GLP_OFF || names == GLP_ON); + xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP); + xassert(scaling == GLP_OFF || scaling == GLP_ON); + if (sol == GLP_MIP) xassert(!scaling); + npp->orig_dir = orig->dir; + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + npp->orig_m = m; + npp->orig_n = n; + npp->orig_nnz = orig->nnz; + if (names && orig->name != NULL) + { npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1); + strcpy(npp->name, orig->name); + } + if (names && orig->obj != NULL) + { npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1); + strcpy(npp->obj, orig->obj); + } + npp->c0 = dir * orig->c0; + /* load rows */ + link = xcalloc(1+m, sizeof(NPPROW *)); + for (i = 1; i <= m; i++) + { GLPROW *rrr = orig->row[i]; + NPPROW *row; + link[i] = row = npp_add_row(npp); + xassert(row->i == i); + if (names && rrr->name != NULL) + { row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1); + strcpy(row->name, rrr->name); + } + if (!scaling) + { if (rrr->type == GLP_FR) + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + else if (rrr->type == GLP_LO) + row->lb = rrr->lb, row->ub = +DBL_MAX; + else if (rrr->type == GLP_UP) + row->lb = -DBL_MAX, row->ub = rrr->ub; + else if (rrr->type == GLP_DB) + row->lb = rrr->lb, row->ub = rrr->ub; + else if (rrr->type == GLP_FX) + row->lb = row->ub = rrr->lb; + else + xassert(rrr != rrr); + } + else + { double rii = rrr->rii; + if (rrr->type == GLP_FR) + row->lb = -DBL_MAX, row->ub = +DBL_MAX; + else if (rrr->type == GLP_LO) + row->lb = rrr->lb * rii, row->ub = +DBL_MAX; + else if (rrr->type == GLP_UP) + row->lb = -DBL_MAX, row->ub = rrr->ub * rii; + else if (rrr->type == GLP_DB) + row->lb = rrr->lb * rii, row->ub = rrr->ub * rii; + else if (rrr->type == GLP_FX) + row->lb = row->ub = rrr->lb * rii; + else + xassert(rrr != rrr); + } + } + /* load columns and constraint coefficients */ + for (j = 1; j <= n; j++) + { GLPCOL *ccc = orig->col[j]; + GLPAIJ *aaa; + NPPCOL *col; + col = npp_add_col(npp); + xassert(col->j == j); + if (names && ccc->name != NULL) + { col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1); + strcpy(col->name, ccc->name); + } + if (sol == GLP_MIP) +#if 0 + col->kind = ccc->kind; +#else + col->is_int = (char)(ccc->kind == GLP_IV); +#endif + if (!scaling) + { if (ccc->type == GLP_FR) + col->lb = -DBL_MAX, col->ub = +DBL_MAX; + else if (ccc->type == GLP_LO) + col->lb = ccc->lb, col->ub = +DBL_MAX; + else if (ccc->type == GLP_UP) + col->lb = -DBL_MAX, col->ub = ccc->ub; + else if (ccc->type == GLP_DB) + col->lb = ccc->lb, col->ub = ccc->ub; + else if (ccc->type == GLP_FX) + col->lb = col->ub = ccc->lb; + else + xassert(ccc != ccc); + col->coef = dir * ccc->coef; + for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) + npp_add_aij(npp, link[aaa->row->i], col, aaa->val); + } + else + { double sjj = ccc->sjj; + if (ccc->type == GLP_FR) + col->lb = -DBL_MAX, col->ub = +DBL_MAX; + else if (ccc->type == GLP_LO) + col->lb = ccc->lb / sjj, col->ub = +DBL_MAX; + else if (ccc->type == GLP_UP) + col->lb = -DBL_MAX, col->ub = ccc->ub / sjj; + else if (ccc->type == GLP_DB) + col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj; + else if (ccc->type == GLP_FX) + col->lb = col->ub = ccc->lb / sjj; + else + xassert(ccc != ccc); + col->coef = dir * ccc->coef * sjj; + for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) + npp_add_aij(npp, link[aaa->row->i], col, + aaa->row->rii * aaa->val * sjj); + } + } + xfree(link); + /* keep solution indicator and scaling option */ + npp->sol = sol; + npp->scaling = scaling; + return; +} + +void npp_build_prob(NPP *npp, glp_prob *prob) +{ /* build resultant (preprocessed) problem */ + NPPROW *row; + NPPCOL *col; + NPPAIJ *aij; + int i, j, type, len, *ind; + double dir, *val; + glp_erase_prob(prob); + glp_set_prob_name(prob, npp->name); + glp_set_obj_name(prob, npp->obj); + glp_set_obj_dir(prob, npp->orig_dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + glp_set_obj_coef(prob, 0, dir * npp->c0); + /* build rows */ + for (row = npp->r_head; row != NULL; row = row->next) + { row->temp = i = glp_add_rows(prob, 1); + glp_set_row_name(prob, i, row->name); + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + type = GLP_FR; + else if (row->ub == +DBL_MAX) + type = GLP_LO; + else if (row->lb == -DBL_MAX) + type = GLP_UP; + else if (row->lb != row->ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_row_bnds(prob, i, type, row->lb, row->ub); + } + /* build columns and the constraint matrix */ + ind = xcalloc(1+prob->m, sizeof(int)); + val = xcalloc(1+prob->m, sizeof(double)); + for (col = npp->c_head; col != NULL; col = col->next) + { j = glp_add_cols(prob, 1); + glp_set_col_name(prob, j, col->name); +#if 0 + glp_set_col_kind(prob, j, col->kind); +#else + glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV); +#endif + if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) + type = GLP_FR; + else if (col->ub == +DBL_MAX) + type = GLP_LO; + else if (col->lb == -DBL_MAX) + type = GLP_UP; + else if (col->lb != col->ub) + type = GLP_DB; + else + type = GLP_FX; + glp_set_col_bnds(prob, j, type, col->lb, col->ub); + glp_set_obj_coef(prob, j, dir * col->coef); + len = 0; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { len++; + ind[len] = aij->row->temp; + val[len] = aij->val; + } + glp_set_mat_col(prob, j, len, ind, val); + } + xfree(ind); + xfree(val); + /* resultant problem has been built */ + npp->m = prob->m; + npp->n = prob->n; + npp->nnz = prob->nnz; + npp->row_ref = xcalloc(1+npp->m, sizeof(int)); + npp->col_ref = xcalloc(1+npp->n, sizeof(int)); + for (row = npp->r_head, i = 0; row != NULL; row = row->next) + npp->row_ref[++i] = row->i; + for (col = npp->c_head, j = 0; col != NULL; col = col->next) + npp->col_ref[++j] = col->j; + /* transformed problem segment is no longer needed */ + dmp_delete_pool(npp->pool), npp->pool = NULL; + npp->name = npp->obj = NULL; + npp->c0 = 0.0; + npp->r_head = npp->r_tail = NULL; + npp->c_head = npp->c_tail = NULL; + return; +} + +void npp_postprocess(NPP *npp, glp_prob *prob) +{ /* postprocess solution from the resultant problem */ + GLPROW *row; + GLPCOL *col; + NPPTSE *tse; + int i, j, k; + double dir; + xassert(npp->orig_dir == prob->dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); +#if 0 /* 11/VII-2013; due to call from ios_main */ + xassert(npp->m == prob->m); +#else + if (npp->sol != GLP_MIP) + xassert(npp->m == prob->m); +#endif + xassert(npp->n == prob->n); +#if 0 /* 11/VII-2013; due to call from ios_main */ + xassert(npp->nnz == prob->nnz); +#else + if (npp->sol != GLP_MIP) + xassert(npp->nnz == prob->nnz); +#endif + /* copy solution status */ + if (npp->sol == GLP_SOL) + { npp->p_stat = prob->pbs_stat; + npp->d_stat = prob->dbs_stat; + } + else if (npp->sol == GLP_IPT) + npp->t_stat = prob->ipt_stat; + else if (npp->sol == GLP_MIP) + npp->i_stat = prob->mip_stat; + else + xassert(npp != npp); + /* allocate solution arrays */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat == NULL) + npp->r_stat = xcalloc(1+npp->nrows, sizeof(char)); + for (i = 1; i <= npp->nrows; i++) + npp->r_stat[i] = 0; + if (npp->c_stat == NULL) + npp->c_stat = xcalloc(1+npp->ncols, sizeof(char)); + for (j = 1; j <= npp->ncols; j++) + npp->c_stat[j] = 0; + } +#if 0 + if (npp->r_prim == NULL) + npp->r_prim = xcalloc(1+npp->nrows, sizeof(double)); + for (i = 1; i <= npp->nrows; i++) + npp->r_prim[i] = DBL_MAX; +#endif + if (npp->c_value == NULL) + npp->c_value = xcalloc(1+npp->ncols, sizeof(double)); + for (j = 1; j <= npp->ncols; j++) + npp->c_value[j] = DBL_MAX; + if (npp->sol != GLP_MIP) + { if (npp->r_pi == NULL) + npp->r_pi = xcalloc(1+npp->nrows, sizeof(double)); + for (i = 1; i <= npp->nrows; i++) + npp->r_pi[i] = DBL_MAX; +#if 0 + if (npp->c_dual == NULL) + npp->c_dual = xcalloc(1+npp->ncols, sizeof(double)); + for (j = 1; j <= npp->ncols; j++) + npp->c_dual[j] = DBL_MAX; +#endif + } + /* copy solution components from the resultant problem */ + if (npp->sol == GLP_SOL) + { for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + npp->r_stat[k] = (char)row->stat; + /*npp->r_prim[k] = row->prim;*/ + npp->r_pi[k] = dir * row->dual; + } + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_stat[k] = (char)col->stat; + npp->c_value[k] = col->prim; + /*npp->c_dual[k] = dir * col->dual;*/ + } + } + else if (npp->sol == GLP_IPT) + { for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + /*npp->r_prim[k] = row->pval;*/ + npp->r_pi[k] = dir * row->dval; + } + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_value[k] = col->pval; + /*npp->c_dual[k] = dir * col->dval;*/ + } + } + else if (npp->sol == GLP_MIP) + { +#if 0 + for (i = 1; i <= npp->m; i++) + { row = prob->row[i]; + k = npp->row_ref[i]; + /*npp->r_prim[k] = row->mipx;*/ + } +#endif + for (j = 1; j <= npp->n; j++) + { col = prob->col[j]; + k = npp->col_ref[j]; + npp->c_value[k] = col->mipx; + } + } + else + xassert(npp != npp); + /* perform postprocessing to construct solution to the original + problem */ + for (tse = npp->top; tse != NULL; tse = tse->link) + { xassert(tse->func != NULL); + xassert(tse->func(npp, tse->info) == 0); + } + return; +} + +void npp_unload_sol(NPP *npp, glp_prob *orig) +{ /* store solution to the original problem */ + GLPROW *row; + GLPCOL *col; + int i, j; + double dir; + xassert(npp->orig_dir == orig->dir); + if (npp->orig_dir == GLP_MIN) + dir = +1.0; + else if (npp->orig_dir == GLP_MAX) + dir = -1.0; + else + xassert(npp != npp); + xassert(npp->orig_m == orig->m); + xassert(npp->orig_n == orig->n); + xassert(npp->orig_nnz == orig->nnz); + if (npp->sol == GLP_SOL) + { /* store basic solution */ + orig->valid = 0; + orig->pbs_stat = npp->p_stat; + orig->dbs_stat = npp->d_stat; + orig->obj_val = orig->c0; + orig->some = 0; + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + row->stat = npp->r_stat[i]; + if (!npp->scaling) + { /*row->prim = npp->r_prim[i];*/ + row->dual = dir * npp->r_pi[i]; + } + else + { /*row->prim = npp->r_prim[i] / row->rii;*/ + row->dual = dir * npp->r_pi[i] * row->rii; + } + if (row->stat == GLP_BS) + row->dual = 0.0; + else if (row->stat == GLP_NL) + { xassert(row->type == GLP_LO || row->type == GLP_DB); + row->prim = row->lb; + } + else if (row->stat == GLP_NU) + { xassert(row->type == GLP_UP || row->type == GLP_DB); + row->prim = row->ub; + } + else if (row->stat == GLP_NF) + { xassert(row->type == GLP_FR); + row->prim = 0.0; + } + else if (row->stat == GLP_NS) + { xassert(row->type == GLP_FX); + row->prim = row->lb; + } + else + xassert(row != row); + } + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + col->stat = npp->c_stat[j]; + if (!npp->scaling) + { col->prim = npp->c_value[j]; + /*col->dual = dir * npp->c_dual[j];*/ + } + else + { col->prim = npp->c_value[j] * col->sjj; + /*col->dual = dir * npp->c_dual[j] / col->sjj;*/ + } + if (col->stat == GLP_BS) + col->dual = 0.0; +#if 1 + else if (col->stat == GLP_NL) + { xassert(col->type == GLP_LO || col->type == GLP_DB); + col->prim = col->lb; + } + else if (col->stat == GLP_NU) + { xassert(col->type == GLP_UP || col->type == GLP_DB); + col->prim = col->ub; + } + else if (col->stat == GLP_NF) + { xassert(col->type == GLP_FR); + col->prim = 0.0; + } + else if (col->stat == GLP_NS) + { xassert(col->type == GLP_FX); + col->prim = col->lb; + } + else + xassert(col != col); +#endif + orig->obj_val += col->coef * col->prim; + } +#if 1 + /* compute primal values of inactive rows */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + if (row->stat == GLP_BS) + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->prim; + row->prim = temp; + } + } + /* compute reduced costs of active columns */ + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + if (col->stat != GLP_BS) + { GLPAIJ *aij; + double temp; + temp = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + temp -= aij->val * aij->row->dual; + col->dual = temp; + } + } +#endif + } + else if (npp->sol == GLP_IPT) + { /* store interior-point solution */ + orig->ipt_stat = npp->t_stat; + orig->ipt_obj = orig->c0; + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + if (!npp->scaling) + { /*row->pval = npp->r_prim[i];*/ + row->dval = dir * npp->r_pi[i]; + } + else + { /*row->pval = npp->r_prim[i] / row->rii;*/ + row->dval = dir * npp->r_pi[i] * row->rii; + } + } + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + if (!npp->scaling) + { col->pval = npp->c_value[j]; + /*col->dval = dir * npp->c_dual[j];*/ + } + else + { col->pval = npp->c_value[j] * col->sjj; + /*col->dval = dir * npp->c_dual[j] / col->sjj;*/ + } + orig->ipt_obj += col->coef * col->pval; + } +#if 1 + /* compute row primal values */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->pval; + row->pval = temp; + } + } + /* compute column dual values */ + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + { GLPAIJ *aij; + double temp; + temp = col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + temp -= aij->val * aij->row->dval; + col->dval = temp; + } + } +#endif + } + else if (npp->sol == GLP_MIP) + { /* store MIP solution */ + xassert(!npp->scaling); + orig->mip_stat = npp->i_stat; + orig->mip_obj = orig->c0; +#if 0 + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + /*row->mipx = npp->r_prim[i];*/ + } +#endif + for (j = 1; j <= orig->n; j++) + { col = orig->col[j]; + col->mipx = npp->c_value[j]; + if (col->kind == GLP_IV) + xassert(col->mipx == floor(col->mipx)); + orig->mip_obj += col->coef * col->mipx; + } +#if 1 + /* compute row primal values */ + for (i = 1; i <= orig->m; i++) + { row = orig->row[i]; + { GLPAIJ *aij; + double temp; + temp = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + temp += aij->val * aij->col->mipx; + row->mipx = temp; + } + } +#endif + } + else + xassert(npp != npp); + return; +} + +void npp_delete_wksp(NPP *npp) +{ /* delete LP/MIP preprocessor workspace */ + if (npp->pool != NULL) + dmp_delete_pool(npp->pool); + if (npp->stack != NULL) + dmp_delete_pool(npp->stack); + if (npp->row_ref != NULL) + xfree(npp->row_ref); + if (npp->col_ref != NULL) + xfree(npp->col_ref); + if (npp->r_stat != NULL) + xfree(npp->r_stat); +#if 0 + if (npp->r_prim != NULL) + xfree(npp->r_prim); +#endif + if (npp->r_pi != NULL) + xfree(npp->r_pi); + if (npp->c_stat != NULL) + xfree(npp->c_stat); + if (npp->c_value != NULL) + xfree(npp->c_value); +#if 0 + if (npp->c_dual != NULL) + xfree(npp->c_dual); +#endif + xfree(npp); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp2.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp2.c new file mode 100644 index 000000000..4efcf1d17 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp2.c @@ -0,0 +1,1433 @@ +/* npp2.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* npp_free_row - process free (unbounded) row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_free_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_free_row processes row p, which is free (i.e. has +* no finite bounds): +* +* -inf < sum a[p,j] x[j] < +inf. (1) +* j +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) cannot be active, so it is redundant and can be +* removed from the original problem. +* +* Removing row p leads to removing a column of multiplier pi[p] for +* this row in the dual system. Since row p has no bounds, pi[p] = 0, +* so removing the column does not affect the dual solution. +* +* RECOVERING BASIC SOLUTION +* +* In solution to the original problem row p is inactive constraint, +* so it is assigned status GLP_BS, and multiplier pi[p] is assigned +* zero value. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* In solution to the original problem row p is inactive constraint, +* so its multiplier pi[p] is assigned zero value. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct free_row +{ /* free (unbounded) row */ + int p; + /* row reference number */ +}; + +static int rcv_free_row(NPP *npp, void *info); + +void npp_free_row(NPP *npp, NPPROW *p) +{ /* process free (unbounded) row */ + struct free_row *info; + /* the row must be free */ + xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_free_row, sizeof(struct free_row)); + info->p = p->i; + /* remove the row from the problem */ + npp_del_row(npp, p); + return; +} + +static int rcv_free_row(NPP *npp, void *_info) +{ /* recover free (unbounded) row */ + struct free_row *info = _info; + if (npp->sol == GLP_SOL) + npp->r_stat[info->p] = GLP_BS; + if (npp->sol != GLP_MIP) + npp->r_pi[info->p] = 0.0; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_geq_row - process row of 'not less than' type +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_geq_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_geq_row processes row p, which is 'not less than' +* inequality constraint: +* +* L[p] <= sum a[p,j] x[j] (<= U[p]), (1) +* j +* +* where L[p] < U[p], and upper bound may not exist (U[p] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) can be replaced by equality constraint: +* +* sum a[p,j] x[j] - s = L[p], (2) +* j +* +* where +* +* 0 <= s (<= U[p] - L[p]) (3) +* +* is a non-negative surplus variable. +* +* Since in the primal system there appears column s having the only +* non-zero coefficient in row p, in the dual system there appears a +* new row: +* +* (-1) pi[p] + lambda = 0, (4) +* +* where (-1) is coefficient of column s in row p, pi[p] is multiplier +* of row p, lambda is multiplier of column q, 0 is coefficient of +* column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and status of column q in solution to the transformed +* problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+--------------------+------------------+ +* | Status of row p | Status of column s | Status of row p | +* +-----------------+--------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_BS | GLP_NU | GLP_BS | +* | GLP_NS | GLP_BS | GLP_BS | +* | GLP_NS | GLP_NL | GLP_NL | +* | GLP_NS | GLP_NU | GLP_NU | +* +-----------------+--------------------+------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* 1. In solution to the transformed problem row p and column q cannot +* be basic at the same time; otherwise the basis matrix would have +* two linear dependent columns: unity column of auxiliary variable +* of row p and unity column of variable s. +* +* 2. Though in the transformed problem row p is equality constraint, +* it may be basic due to primal degenerate solution. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct ineq_row +{ /* inequality constraint row */ + int p; + /* row reference number */ + int s; + /* column reference number for slack/surplus variable */ +}; + +static int rcv_geq_row(NPP *npp, void *info); + +void npp_geq_row(NPP *npp, NPPROW *p) +{ /* process row of 'not less than' type */ + struct ineq_row *info; + NPPCOL *s; + /* the row must have lower bound */ + xassert(p->lb != -DBL_MAX); + xassert(p->lb < p->ub); + /* create column for surplus variable */ + s = npp_add_col(npp); + s->lb = 0.0; + s->ub = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub - p->lb); + /* and add it to the transformed problem */ + npp_add_aij(npp, p, s, -1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_geq_row, sizeof(struct ineq_row)); + info->p = p->i; + info->s = s->j; + /* replace the row by equality constraint */ + p->ub = p->lb; + return; +} + +static int rcv_geq_row(NPP *npp, void *_info) +{ /* recover row of 'not less than' type */ + struct ineq_row *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL || + npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_BS; + else + { npp_error(); + return 1; + } + } + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->r_stat[info->p] = GLP_NL; + else if (npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_NU; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_leq_row - process row of 'not greater than' type +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_leq_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_leq_row processes row p, which is 'not greater than' +* inequality constraint: +* +* (L[p] <=) sum a[p,j] x[j] <= U[p], (1) +* j +* +* where L[p] < U[p], and lower bound may not exist (L[p] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Constraint (1) can be replaced by equality constraint: +* +* sum a[p,j] x[j] + s = L[p], (2) +* j +* +* where +* +* 0 <= s (<= U[p] - L[p]) (3) +* +* is a non-negative slack variable. +* +* Since in the primal system there appears column s having the only +* non-zero coefficient in row p, in the dual system there appears a +* new row: +* +* (+1) pi[p] + lambda = 0, (4) +* +* where (+1) is coefficient of column s in row p, pi[p] is multiplier +* of row p, lambda is multiplier of column q, 0 is coefficient of +* column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and status of column q in solution to the transformed +* problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+--------------------+------------------+ +* | Status of row p | Status of column s | Status of row p | +* +-----------------+--------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_BS | GLP_NU | GLP_BS | +* | GLP_NS | GLP_BS | GLP_BS | +* | GLP_NS | GLP_NL | GLP_NU | +* | GLP_NS | GLP_NU | GLP_NL | +* +-----------------+--------------------+------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* 1. In solution to the transformed problem row p and column q cannot +* be basic at the same time; otherwise the basis matrix would have +* two linear dependent columns: unity column of auxiliary variable +* of row p and unity column of variable s. +* +* 2. Though in the transformed problem row p is equality constraint, +* it may be basic due to primal degeneracy. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem +* is the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +static int rcv_leq_row(NPP *npp, void *info); + +void npp_leq_row(NPP *npp, NPPROW *p) +{ /* process row of 'not greater than' type */ + struct ineq_row *info; + NPPCOL *s; + /* the row must have upper bound */ + xassert(p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* create column for slack variable */ + s = npp_add_col(npp); + s->lb = 0.0; + s->ub = (p->lb == -DBL_MAX ? +DBL_MAX : p->ub - p->lb); + /* and add it to the transformed problem */ + npp_add_aij(npp, p, s, +1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_leq_row, sizeof(struct ineq_row)); + info->p = p->i; + info->s = s->j; + /* replace the row by equality constraint */ + p->lb = p->ub; + return; +} + +static int rcv_leq_row(NPP *npp, void *_info) +{ /* recover row of 'not greater than' type */ + struct ineq_row *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL || + npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_BS; + else + { npp_error(); + return 1; + } + } + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->r_stat[info->p] = GLP_NU; + else if (npp->c_stat[info->s] == GLP_NU) + npp->r_stat[info->p] = GLP_NL; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_free_col - process free (unbounded) column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_free_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_free_col processes column q, which is free (i.e. has +* no finite bounds): +* +* -oo < x[q] < +oo. (1) +* +* PROBLEM TRANSFORMATION +* +* Free (unbounded) variable can be replaced by the difference of two +* non-negative variables: +* +* x[q] = s' - s'', s', s'' >= 0. (2) +* +* Assuming that in the transformed problem x[q] becomes s', +* transformation (2) causes new column s'' to appear, which differs +* from column s' only in the sign of coefficients in constraint and +* objective rows. Thus, if in the dual system the following row +* corresponds to column s': +* +* sum a[i,q] pi[i] + lambda' = c[q], (3) +* i +* +* the row which corresponds to column s'' is the following: +* +* sum (-a[i,q]) pi[i] + lambda'' = -c[q]. (4) +* i +* +* Then from (3) and (4) it follows that: +* +* lambda' + lambda'' = 0 => lambda' = lmabda'' = 0, (5) +* +* where lambda' and lambda'' are multipliers for columns s' and s'', +* resp. +* +* RECOVERING BASIC SOLUTION +* +* With respect to (5) status of column q in solution to the original +* problem is determined by statuses of columns s' and s'' in solution +* to the transformed problem as follows: +* +* +--------------------------------------+------------------+ +* | Transformed problem | Original problem | +* +------------------+-------------------+------------------+ +* | Status of col s' | Status of col s'' | Status of col q | +* +------------------+-------------------+------------------+ +* | GLP_BS | GLP_BS | N/A | +* | GLP_BS | GLP_NL | GLP_BS | +* | GLP_NL | GLP_BS | GLP_BS | +* | GLP_NL | GLP_NL | GLP_NF | +* +------------------+-------------------+------------------+ +* +* Value of column q is computed with formula (2). +* +* 1. In solution to the transformed problem columns s' and s'' cannot +* be basic at the same time, because they differ only in the sign, +* hence, are linear dependent. +* +* 2. Though column q is free, it can be non-basic due to dual +* degeneracy. +* +* 3. If column q is integral, columns s' and s'' are also integral. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +struct free_col +{ /* free (unbounded) column */ + int q; + /* column reference number for variables x[q] and s' */ + int s; + /* column reference number for variable s'' */ +}; + +static int rcv_free_col(NPP *npp, void *info); + +void npp_free_col(NPP *npp, NPPCOL *q) +{ /* process free (unbounded) column */ + struct free_col *info; + NPPCOL *s; + NPPAIJ *aij; + /* the column must be free */ + xassert(q->lb == -DBL_MAX && q->ub == +DBL_MAX); + /* variable x[q] becomes s' */ + q->lb = 0.0, q->ub = +DBL_MAX; + /* create variable s'' */ + s = npp_add_col(npp); + s->is_int = q->is_int; + s->lb = 0.0, s->ub = +DBL_MAX; + /* duplicate objective coefficient */ + s->coef = -q->coef; + /* duplicate column of the constraint matrix */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + npp_add_aij(npp, aij->row, s, -aij->val); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_free_col, sizeof(struct free_col)); + info->q = q->j; + info->s = s->j; + return; +} + +static int rcv_free_col(NPP *npp, void *_info) +{ /* recover free (unbounded) column */ + struct free_col *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + { npp_error(); + return 1; + } + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_BS; + else + { npp_error(); + return -1; + } + } + else if (npp->c_stat[info->q] == GLP_NL) + { if (npp->c_stat[info->s] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NF; + else + { npp_error(); + return -1; + } + } + else + { npp_error(); + return -1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] -= npp->c_value[info->s]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_lbnd_col - process column with (non-zero) lower bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_lbnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_lbnd_col processes column q, which has (non-zero) +* lower bound: +* +* l[q] <= x[q] (<= u[q]), (1) +* +* where l[q] < u[q], and upper bound may not exist (u[q] = +oo). +* +* PROBLEM TRANSFORMATION +* +* Column q can be replaced as follows: +* +* x[q] = l[q] + s, (2) +* +* where +* +* 0 <= s (<= u[q] - l[q]) (3) +* +* is a non-negative variable. +* +* Substituting x[q] from (2) into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] (l[q] + s) + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] s + c~0, +* +* where +* +* c~0 = c0 + c[q] l[q] (4) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] (l[q] + s) <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] l[q], U~[i] = U[i] - a[i,q] l[q] (5) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* Transformation (2) does not affect the dual system. +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is the same +* as in solution to the transformed problem (GLP_BS, GLP_NL or GLP_NU). +* Value of column q is computed with formula (2). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +struct bnd_col +{ /* bounded column */ + int q; + /* column reference number for variables x[q] and s */ + double bnd; + /* lower/upper bound l[q] or u[q] */ +}; + +static int rcv_lbnd_col(NPP *npp, void *info); + +void npp_lbnd_col(NPP *npp, NPPCOL *q) +{ /* process column with (non-zero) lower bound */ + struct bnd_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must have non-zero lower bound */ + xassert(q->lb != 0.0); + xassert(q->lb != -DBL_MAX); + xassert(q->lb < q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_lbnd_col, sizeof(struct bnd_col)); + info->q = q->j; + info->bnd = q->lb; + /* substitute x[q] into objective row */ + npp->c0 += q->coef * q->lb; + /* substitute x[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->lb; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->lb; + } + } + /* column x[q] becomes column s */ + if (q->ub != +DBL_MAX) + q->ub -= q->lb; + q->lb = 0.0; + return; +} + +static int rcv_lbnd_col(NPP *npp, void *_info) +{ /* recover column with (non-zero) lower bound */ + struct bnd_col *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS || + npp->c_stat[info->q] == GLP_NL || + npp->c_stat[info->q] == GLP_NU) + npp->c_stat[info->q] = npp->c_stat[info->q]; + else + { npp_error(); + return 1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] = info->bnd + npp->c_value[info->q]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_ubnd_col - process column with upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_ubnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_ubnd_col processes column q, which has upper bound: +* +* (l[q] <=) x[q] <= u[q], (1) +* +* where l[q] < u[q], and lower bound may not exist (l[q] = -oo). +* +* PROBLEM TRANSFORMATION +* +* Column q can be replaced as follows: +* +* x[q] = u[q] - s, (2) +* +* where +* +* 0 <= s (<= u[q] - l[q]) (3) +* +* is a non-negative variable. +* +* Substituting x[q] from (2) into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] (u[q] - s) + c0 = +* j!=q +* +* = sum c[j] x[j] - c[q] s + c~0, +* +* where +* +* c~0 = c0 + c[q] u[q] (4) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] (u[q] - s) <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] - a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] u[q], U~[i] = U[i] - a[i,q] u[q] (5) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* Note that in the transformed problem coefficients c[q] and a[i,q] +* change their sign. Thus, the row of the dual system corresponding to +* column q: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] (6) +* i +* +* in the transformed problem becomes the following: +* +* sum (-a[i,q]) pi[i] + lambda[s] = -c[q]. (7) +* i +* +* Therefore: +* +* lambda[q] = - lambda[s], (8) +* +* where lambda[q] is multiplier for column q, lambda[s] is multiplier +* for column s. +* +* RECOVERING BASIC SOLUTION +* +* With respect to (8) status of column q in solution to the original +* problem is determined by status of column s in solution to the +* transformed problem as follows: +* +* +-----------------------+--------------------+ +* | Status of column s | Status of column q | +* | (transformed problem) | (original problem) | +* +-----------------------+--------------------+ +* | GLP_BS | GLP_BS | +* | GLP_NL | GLP_NU | +* | GLP_NU | GLP_NL | +* +-----------------------+--------------------+ +* +* Value of column q is computed with formula (2). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (2). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (2). */ + +static int rcv_ubnd_col(NPP *npp, void *info); + +void npp_ubnd_col(NPP *npp, NPPCOL *q) +{ /* process column with upper bound */ + struct bnd_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must have upper bound */ + xassert(q->ub != +DBL_MAX); + xassert(q->lb < q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_ubnd_col, sizeof(struct bnd_col)); + info->q = q->j; + info->bnd = q->ub; + /* substitute x[q] into objective row */ + npp->c0 += q->coef * q->ub; + q->coef = -q->coef; + /* substitute x[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->ub); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->ub; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->ub; + } + aij->val = -aij->val; + } + /* column x[q] becomes column s */ + if (q->lb != -DBL_MAX) + q->ub -= q->lb; + else + q->ub = +DBL_MAX; + q->lb = 0.0; + return; +} + +static int rcv_ubnd_col(NPP *npp, void *_info) +{ /* recover column with upper bound */ + struct bnd_col *info = _info; + if (npp->sol == GLP_BS) + { if (npp->c_stat[info->q] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->q] == GLP_NL) + npp->c_stat[info->q] = GLP_NU; + else if (npp->c_stat[info->q] == GLP_NU) + npp->c_stat[info->q] = GLP_NL; + else + { npp_error(); + return 1; + } + } + /* compute value of x[q] with formula (2) */ + npp->c_value[info->q] = info->bnd - npp->c_value[info->q]; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_dbnd_col - process non-negative column with upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_dbnd_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_dbnd_col processes column q, which is non-negative +* and has upper bound: +* +* 0 <= x[q] <= u[q], (1) +* +* where u[q] > 0. +* +* PROBLEM TRANSFORMATION +* +* Upper bound of column q can be replaced by the following equality +* constraint: +* +* x[q] + s = u[q], (2) +* +* where s >= 0 is a non-negative complement variable. +* +* Since in the primal system along with new row (2) there appears a +* new column s having the only non-zero coefficient in this row, in +* the dual system there appears a new row: +* +* (+1)pi + lambda[s] = 0, (3) +* +* where (+1) is coefficient at column s in row (2), pi is multiplier +* for row (2), lambda[s] is multiplier for column s, 0 is coefficient +* at column s in the objective row. +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is determined +* by its status and status of column s in solution to the transformed +* problem as follows: +* +* +-----------------------------------+------------------+ +* | Transformed problem | Original problem | +* +-----------------+-----------------+------------------+ +* | Status of col q | Status of col s | Status of col q | +* +-----------------+-----------------+------------------+ +* | GLP_BS | GLP_BS | GLP_BS | +* | GLP_BS | GLP_NL | GLP_NU | +* | GLP_NL | GLP_BS | GLP_NL | +* | GLP_NL | GLP_NL | GLP_NL (*) | +* +-----------------+-----------------+------------------+ +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* 1. Formally, in solution to the transformed problem columns q and s +* cannot be non-basic at the same time, since the constraint (2) +* would be violated. However, if u[q] is close to zero, violation +* may be less than a working precision even if both columns q and s +* are non-basic. In this degenerate case row (2) can be only basic, +* i.e. non-active constraint (otherwise corresponding row of the +* basis matrix would be zero). This allows to pivot out auxiliary +* variable and pivot in column s, in which case the row becomes +* active while column s becomes basic. +* +* 2. If column q is integral, column s is also integral. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. */ + +struct dbnd_col +{ /* double-bounded column */ + int q; + /* column reference number for variable x[q] */ + int s; + /* column reference number for complement variable s */ +}; + +static int rcv_dbnd_col(NPP *npp, void *info); + +void npp_dbnd_col(NPP *npp, NPPCOL *q) +{ /* process non-negative column with upper bound */ + struct dbnd_col *info; + NPPROW *p; + NPPCOL *s; + /* the column must be non-negative with upper bound */ + xassert(q->lb == 0.0); + xassert(q->ub > 0.0); + xassert(q->ub != +DBL_MAX); + /* create variable s */ + s = npp_add_col(npp); + s->is_int = q->is_int; + s->lb = 0.0, s->ub = +DBL_MAX; + /* create equality constraint (2) */ + p = npp_add_row(npp); + p->lb = p->ub = q->ub; + npp_add_aij(npp, p, q, +1.0); + npp_add_aij(npp, p, s, +1.0); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_dbnd_col, sizeof(struct dbnd_col)); + info->q = q->j; + info->s = s->j; + /* remove upper bound of x[q] */ + q->ub = +DBL_MAX; + return; +} + +static int rcv_dbnd_col(NPP *npp, void *_info) +{ /* recover non-negative column with upper bound */ + struct dbnd_col *info = _info; + if (npp->sol == GLP_BS) + { if (npp->c_stat[info->q] == GLP_BS) + { if (npp->c_stat[info->s] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NU; + else + { npp_error(); + return 1; + } + } + else if (npp->c_stat[info->q] == GLP_NL) + { if (npp->c_stat[info->s] == GLP_BS || + npp->c_stat[info->s] == GLP_NL) + npp->c_stat[info->q] = GLP_NL; + else + { npp_error(); + return 1; + } + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_fixed_col - process fixed column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_fixed_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_fixed_col processes column q, which is fixed: +* +* x[q] = s[q], (1) +* +* where s[q] is a fixed column value. +* +* PROBLEM TRANSFORMATION +* +* The value of a fixed column can be substituted into the objective +* and constraint rows that allows removing the column from the problem. +* +* Substituting x[q] = s[q] into the objective row, we have: +* +* z = sum c[j] x[j] + c0 = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c[q] s[q] + c0 = +* j!=q +* +* = sum c[j] x[j] + c~0, +* j!=q +* +* where +* +* c~0 = c0 + c[q] s[q] (2) +* +* is the constant term of the objective in the transformed problem. +* Similarly, substituting x[q] = s[q] into constraint row i, we have: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] s[q], U~[i] = U[i] - a[i,q] s[q] (3) +* +* are lower and upper bounds of row i in the transformed problem, +* resp. +* +* RECOVERING BASIC SOLUTION +* +* Column q is assigned status GLP_NS and its value is assigned s[q]. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is assigned s[q]. +* +* RECOVERING MIP SOLUTION +* +* Value of column q is assigned s[q]. */ + +struct fixed_col +{ /* fixed column */ + int q; + /* column reference number for variable x[q] */ + double s; + /* value, at which x[q] is fixed */ +}; + +static int rcv_fixed_col(NPP *npp, void *info); + +void npp_fixed_col(NPP *npp, NPPCOL *q) +{ /* process fixed column */ + struct fixed_col *info; + NPPROW *i; + NPPAIJ *aij; + /* the column must be fixed */ + xassert(q->lb == q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_fixed_col, sizeof(struct fixed_col)); + info->q = q->j; + info->s = q->lb; + /* substitute x[q] = s[q] into objective row */ + npp->c0 += q->coef * q->lb; + /* substitute x[q] = s[q] into constraint rows */ + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb == i->ub) + i->ub = (i->lb -= aij->val * q->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= aij->val * q->lb; + if (i->ub != +DBL_MAX) + i->ub -= aij->val * q->lb; + } + } + /* remove the column from the problem */ + npp_del_col(npp, q); + return; +} + +static int rcv_fixed_col(NPP *npp, void *_info) +{ /* recover fixed column */ + struct fixed_col *info = _info; + if (npp->sol == GLP_SOL) + npp->c_stat[info->q] = GLP_NS; + npp->c_value[info->q] = info->s; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_make_equality - process row with almost identical bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_make_equality(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_make_equality processes row p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* where -oo < L[p] < U[p] < +oo, i.e. which is double-sided inequality +* constraint. +* +* RETURNS +* +* 0 - row bounds have not been changed; +* +* 1 - row has been replaced by equality constraint. +* +* PROBLEM TRANSFORMATION +* +* If bounds of row (1) are very close to each other: +* +* U[p] - L[p] <= eps, (2) +* +* where eps is an absolute tolerance for row value, the row can be +* replaced by the following almost equivalent equiality constraint: +* +* sum a[p,j] x[j] = b, (3) +* j +* +* where b = (L[p] + U[p]) / 2. If the right-hand side in (3) happens +* to be very close to its nearest integer: +* +* |b - floor(b + 0.5)| <= eps, (4) +* +* it is reasonable to use this nearest integer as the right-hand side. +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status and the sign of its multiplier pi[p] in solution to +* the transformed problem as follows: +* +* +-----------------------+---------+--------------------+ +* | Status of row p | Sign of | Status of row p | +* | (transformed problem) | pi[p] | (original problem) | +* +-----------------------+---------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NS | + | GLP_NL | +* | GLP_NS | - | GLP_NU | +* +-----------------------+---------+--------------------+ +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING INTERIOR POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct make_equality +{ /* row with almost identical bounds */ + int p; + /* row reference number */ +}; + +static int rcv_make_equality(NPP *npp, void *info); + +int npp_make_equality(NPP *npp, NPPROW *p) +{ /* process row with almost identical bounds */ + struct make_equality *info; + double b, eps, nint; + /* the row must be double-sided inequality */ + xassert(p->lb != -DBL_MAX); + xassert(p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* check row bounds */ + eps = 1e-9 + 1e-12 * fabs(p->lb); + if (p->ub - p->lb > eps) return 0; + /* row bounds are very close to each other */ + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_make_equality, sizeof(struct make_equality)); + info->p = p->i; + /* compute right-hand side */ + b = 0.5 * (p->ub + p->lb); + nint = floor(b + 0.5); + if (fabs(b - nint) <= eps) b = nint; + /* replace row p by almost equivalent equality constraint */ + p->lb = p->ub = b; + return 1; +} + +int rcv_make_equality(NPP *npp, void *_info) +{ /* recover row with almost identical bounds */ + struct make_equality *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->r_stat[info->p] == GLP_NS) + { if (npp->r_pi[info->p] >= 0.0) + npp->r_stat[info->p] = GLP_NL; + else + npp->r_stat[info->p] = GLP_NU; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_make_fixed - process column with almost identical bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_make_fixed(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_make_fixed processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where -oo < l[q] < u[q] < +oo, i.e. which has both lower and upper +* bounds. +* +* RETURNS +* +* 0 - column bounds have not been changed; +* +* 1 - column has been fixed. +* +* PROBLEM TRANSFORMATION +* +* If bounds of column (1) are very close to each other: +* +* u[q] - l[q] <= eps, (2) +* +* where eps is an absolute tolerance for column value, the column can +* be fixed: +* +* x[q] = s[q], (3) +* +* where s[q] = (l[q] + u[q]) / 2. And if the fixed column value s[q] +* happens to be very close to its nearest integer: +* +* |s[q] - floor(s[q] + 0.5)| <= eps, (4) +* +* it is reasonable to use this nearest integer as the fixed value. +* +* RECOVERING BASIC SOLUTION +* +* In the dual system of the original (as well as transformed) problem +* column q corresponds to the following row: +* +* sum a[i,q] pi[i] + lambda[q] = c[q]. (5) +* i +* +* Since multipliers pi[i] are known for all rows from solution to the +* transformed problem, formula (5) allows computing value of multiplier +* (reduced cost) for column q: +* +* lambda[q] = c[q] - sum a[i,q] pi[i]. (6) +* i +* +* Status of column q in solution to the original problem is determined +* by its status and the sign of its multiplier lambda[q] in solution to +* the transformed problem as follows: +* +* +-----------------------+-----------+--------------------+ +* | Status of column q | Sign of | Status of column q | +* | (transformed problem) | lambda[q] | (original problem) | +* +-----------------------+-----------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NS | + | GLP_NL | +* | GLP_NS | - | GLP_NU | +* +-----------------------+-----------+--------------------+ +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING INTERIOR POINT SOLUTION +* +* Value of column q in solution to the original problem is the same as +* in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct make_fixed +{ /* column with almost identical bounds */ + int q; + /* column reference number */ + double c; + /* objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q] */ +}; + +static int rcv_make_fixed(NPP *npp, void *info); + +int npp_make_fixed(NPP *npp, NPPCOL *q) +{ /* process column with almost identical bounds */ + struct make_fixed *info; + NPPAIJ *aij; + NPPLFE *lfe; + double s, eps, nint; + /* the column must be double-bounded */ + xassert(q->lb != -DBL_MAX); + xassert(q->ub != +DBL_MAX); + xassert(q->lb < q->ub); + /* check column bounds */ + eps = 1e-9 + 1e-12 * fabs(q->lb); + if (q->ub - q->lb > eps) return 0; + /* column bounds are very close to each other */ + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_make_fixed, sizeof(struct make_fixed)); + info->q = q->j; + info->c = q->coef; + info->ptr = NULL; + /* save column coefficients a[i,q] (needed for basic solution + only) */ + if (npp->sol == GLP_SOL) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* compute column fixed value */ + s = 0.5 * (q->ub + q->lb); + nint = floor(s + 0.5); + if (fabs(s - nint) <= eps) s = nint; + /* make column q fixed */ + q->lb = q->ub = s; + return 1; +} + +static int rcv_make_fixed(NPP *npp, void *_info) +{ /* recover column with almost identical bounds */ + struct make_fixed *info = _info; + NPPLFE *lfe; + double lambda; + if (npp->sol == GLP_SOL) + { if (npp->c_stat[info->q] == GLP_BS) + npp->c_stat[info->q] = GLP_BS; + else if (npp->c_stat[info->q] == GLP_NS) + { /* compute multiplier for column q with formula (6) */ + lambda = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + lambda -= lfe->val * npp->r_pi[lfe->ref]; + /* assign status to non-basic column */ + if (lambda >= 0.0) + npp->c_stat[info->q] = GLP_NL; + else + npp->c_stat[info->q] = GLP_NU; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp3.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp3.c new file mode 100644 index 000000000..883af1277 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp3.c @@ -0,0 +1,2861 @@ +/* npp3.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* npp_empty_row - process empty row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_empty_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_empty_row processes row p, which is empty, i.e. +* coefficients at all columns in this row are zero: +* +* L[p] <= sum 0 x[j] <= U[p], (1) +* +* where L[p] <= U[p]. +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no primal feasible solution. +* +* PROBLEM TRANSFORMATION +* +* If the following conditions hold: +* +* L[p] <= +eps, U[p] >= -eps, (2) +* +* where eps is an absolute tolerance for row value, the row p is +* redundant. In this case it can be replaced by equivalent redundant +* row, which is free (unbounded), and then removed from the problem. +* Otherwise, the row p is infeasible and, thus, the problem has no +* primal feasible solution. +* +* RECOVERING BASIC SOLUTION +* +* See the routine npp_free_row. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* See the routine npp_free_row. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +int npp_empty_row(NPP *npp, NPPROW *p) +{ /* process empty row */ + double eps = 1e-3; + /* the row must be empty */ + xassert(p->ptr == NULL); + /* check primal feasibility */ + if (p->lb > +eps || p->ub < -eps) + return 1; + /* replace the row by equivalent free (unbounded) row */ + p->lb = -DBL_MAX, p->ub = +DBL_MAX; + /* and process it */ + npp_free_row(npp, p); + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_empty_col - process empty column +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_empty_col(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_empty_col processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] <= u[q], which is empty, i.e. has zero coefficients in +* all constraint rows. +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no dual feasible solution. +* +* PROBLEM TRANSFORMATION +* +* The row of the dual system corresponding to the empty column is the +* following: +* +* sum 0 pi[i] + lambda[q] = c[q], (2) +* i +* +* from which it follows that: +* +* lambda[q] = c[q]. (3) +* +* If the following condition holds: +* +* c[q] < - eps, (4) +* +* where eps is an absolute tolerance for column multiplier, the lower +* column bound l[q] must be active to provide dual feasibility (note +* that being preprocessed the problem is always minimization). In this +* case the column can be fixed on its lower bound and removed from the +* problem (if the column is integral, its bounds are also assumed to +* be integral). And if the column has no lower bound (l[q] = -oo), the +* problem has no dual feasible solution. +* +* If the following condition holds: +* +* c[q] > + eps, (5) +* +* the upper column bound u[q] must be active to provide dual +* feasibility. In this case the column can be fixed on its upper bound +* and removed from the problem. And if the column has no upper bound +* (u[q] = +oo), the problem has no dual feasible solution. +* +* Finally, if the following condition holds: +* +* - eps <= c[q] <= +eps, (6) +* +* dual feasibility does not depend on a particular value of column q. +* In this case the column can be fixed either on its lower bound (if +* l[q] > -oo) or on its upper bound (if u[q] < +oo) or at zero (if the +* column is unbounded) and then removed from the problem. +* +* RECOVERING BASIC SOLUTION +* +* See the routine npp_fixed_col. Having been recovered the column +* is assigned status GLP_NS. However, if actually it is not fixed +* (l[q] < u[q]), its status should be changed to GLP_NL, GLP_NU, or +* GLP_NF depending on which bound it was fixed on transformation stage. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* See the routine npp_fixed_col. +* +* RECOVERING MIP SOLUTION +* +* See the routine npp_fixed_col. */ + +struct empty_col +{ /* empty column */ + int q; + /* column reference number */ + char stat; + /* status in basic solution */ +}; + +static int rcv_empty_col(NPP *npp, void *info); + +int npp_empty_col(NPP *npp, NPPCOL *q) +{ /* process empty column */ + struct empty_col *info; + double eps = 1e-3; + /* the column must be empty */ + xassert(q->ptr == NULL); + /* check dual feasibility */ + if (q->coef > +eps && q->lb == -DBL_MAX) + return 1; + if (q->coef < -eps && q->ub == +DBL_MAX) + return 1; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_empty_col, sizeof(struct empty_col)); + info->q = q->j; + /* fix the column */ + if (q->lb == -DBL_MAX && q->ub == +DBL_MAX) + { /* free column */ + info->stat = GLP_NF; + q->lb = q->ub = 0.0; + } + else if (q->ub == +DBL_MAX) +lo: { /* column with lower bound */ + info->stat = GLP_NL; + q->ub = q->lb; + } + else if (q->lb == -DBL_MAX) +up: { /* column with upper bound */ + info->stat = GLP_NU; + q->lb = q->ub; + } + else if (q->lb != q->ub) + { /* double-bounded column */ + if (q->coef >= +DBL_EPSILON) goto lo; + if (q->coef <= -DBL_EPSILON) goto up; + if (fabs(q->lb) <= fabs(q->ub)) goto lo; else goto up; + } + else + { /* fixed column */ + info->stat = GLP_NS; + } + /* process fixed column */ + npp_fixed_col(npp, q); + return 0; +} + +static int rcv_empty_col(NPP *npp, void *_info) +{ /* recover empty column */ + struct empty_col *info = _info; + if (npp->sol == GLP_SOL) + npp->c_stat[info->q] = info->stat; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_value - process implied column value +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_value(NPP *npp, NPPCOL *q, double s); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_value processes its +* implied value s[q]. If this implied value satisfies to the current +* column bounds and integrality condition, the routine fixes column q +* at the given point. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - column has been fixed; +* +* 1 - implied value violates to current column bounds; +* +* 2 - implied value violates integrality condition. +* +* ALGORITHM +* +* Implied column value s[q] satisfies to the current column bounds if +* the following condition holds: +* +* l[q] - eps <= s[q] <= u[q] + eps, (2) +* +* where eps is an absolute tolerance for column value. If the column +* is integral, the following condition also must hold: +* +* |s[q] - floor(s[q]+0.5)| <= eps, (3) +* +* where floor(s[q]+0.5) is the nearest integer to s[q]. +* +* If both condition (2) and (3) are satisfied, the column can be fixed +* at the value s[q], or, if it is integral, at floor(s[q]+0.5). +* Otherwise, if s[q] violates (2) or (3), the problem has no feasible +* solution. +* +* Note: If s[q] is close to l[q] or u[q], it seems to be reasonable to +* fix the column at its lower or upper bound, resp. rather than at the +* implied value. */ + +int npp_implied_value(NPP *npp, NPPCOL *q, double s) +{ /* process implied column value */ + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* check integrality */ + if (q->is_int) + { nint = floor(s + 0.5); + if (fabs(s - nint) <= 1e-5) + s = nint; + else + return 2; + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); + if (s < q->lb - eps) return 1; + /* if s[q] is close to l[q], fix column at its lower bound + rather than at the implied value */ + if (s < q->lb + 1e-3 * eps) + { q->ub = q->lb; + return 0; + } + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); + if (s > q->ub + eps) return 1; + /* if s[q] is close to u[q], fix column at its upper bound + rather than at the implied value */ + if (s > q->ub - 1e-3 * eps) + { q->lb = q->ub; + return 0; + } + } + /* fix column at the implied value */ + q->lb = q->ub = s; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_eq_singlet - process row singleton (equality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_eq_singlet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_eq_singlet processes row p, which is equiality +* constraint having the only non-zero coefficient: +* +* a[p,q] x[q] = b. (1) +* +* RETURNS +* +* 0 - success; +* +* 1 - problem has no primal feasible solution; +* +* 2 - problem has no integer feasible solution. +* +* PROBLEM TRANSFORMATION +* +* The equality constraint defines implied value of column q: +* +* x[q] = s[q] = b / a[p,q]. (2) +* +* If the implied value s[q] satisfies to the column bounds (see the +* routine npp_implied_value), the column can be fixed at s[q] and +* removed from the problem. In this case row p becomes redundant, so +* it can be replaced by equivalent free row and also removed from the +* problem. +* +* Note that the routine removes from the problem only row p. Column q +* becomes fixed, however, it is kept in the problem. +* +* RECOVERING BASIC SOLUTION +* +* In solution to the original problem row p is assigned status GLP_NS +* (active equality constraint), and column q is assigned status GLP_BS +* (basic column). +* +* Multiplier for row p can be computed as follows. In the dual system +* of the original problem column q corresponds to the following row: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] ==> +* i +* +* sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q]. +* i!=p +* +* Therefore: +* +* 1 +* pi[p] = ------ (c[q] - lambda[q] - sum a[i,q] pi[i]), (3) +* a[p,q] i!=q +* +* where lambda[q] = 0 (since column[q] is basic), and pi[i] for all +* i != p are known in solution to the transformed problem. +* +* Value of column q in solution to the original problem is assigned +* its implied value s[q]. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Multiplier for row p is computed with formula (3). Value of column +* q is assigned its implied value s[q]. +* +* RECOVERING MIP SOLUTION +* +* Value of column q is assigned its implied value s[q]. */ + +struct eq_singlet +{ /* row singleton (equality constraint) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double c; + /* objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_eq_singlet(NPP *npp, void *info); + +int npp_eq_singlet(NPP *npp, NPPROW *p) +{ /* process row singleton (equality constraint) */ + struct eq_singlet *info; + NPPCOL *q; + NPPAIJ *aij; + NPPLFE *lfe; + int ret; + double s; + /* the row must be singleton equality constraint */ + xassert(p->lb == p->ub); + xassert(p->ptr != NULL && p->ptr->r_next == NULL); + /* compute and process implied column value */ + aij = p->ptr; + q = aij->col; + s = p->lb / aij->val; + ret = npp_implied_value(npp, q, s); + xassert(0 <= ret && ret <= 2); + if (ret != 0) return ret; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_eq_singlet, sizeof(struct eq_singlet)); + info->p = p->i; + info->q = q->j; + info->apq = aij->val; + info->c = q->coef; + info->ptr = NULL; + /* save column coefficients a[i,q], i != p (not needed for MIP + solution) */ + if (npp->sol != GLP_MIP) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { if (aij->row == p) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* remove the row from the problem */ + npp_del_row(npp, p); + return 0; +} + +static int rcv_eq_singlet(NPP *npp, void *_info) +{ /* recover row singleton (equality constraint) */ + struct eq_singlet *info = _info; + NPPLFE *lfe; + double temp; + if (npp->sol == GLP_SOL) + { /* column q must be already recovered as GLP_NS */ + if (npp->c_stat[info->q] != GLP_NS) + { npp_error(); + return 1; + } + npp->r_stat[info->p] = GLP_NS; + npp->c_stat[info->q] = GLP_BS; + } + if (npp->sol != GLP_MIP) + { /* compute multiplier for row p with formula (3) */ + temp = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + temp -= lfe->val * npp->r_pi[lfe->ref]; + npp->r_pi[info->p] = temp / info->apq; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_lower - process implied column lower bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_lower(NPP *npp, NPPCOL *q, double l); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_lower processes its +* implied lower bound l'[q]. As the result the current column lower +* bound may increase. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - current column lower bound has not changed; +* +* 1 - current column lower bound has changed, but not significantly; +* +* 2 - current column lower bound has significantly changed; +* +* 3 - column has been fixed on its upper bound; +* +* 4 - implied lower bound violates current column upper bound. +* +* ALGORITHM +* +* If column q is integral, before processing its implied lower bound +* should be rounded up: +* +* ( floor(l'[q]+0.5), if |l'[q] - floor(l'[q]+0.5)| <= eps +* l'[q] := < (2) +* ( ceil(l'[q]), otherwise +* +* where floor(l'[q]+0.5) is the nearest integer to l'[q], ceil(l'[q]) +* is smallest integer not less than l'[q], and eps is an absolute +* tolerance for column value. +* +* Processing implied column lower bound l'[q] includes the following +* cases: +* +* 1) if l'[q] < l[q] + eps, implied lower bound is redundant; +* +* 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound +* l[q] can be strengthened by replacing it with l'[q]. If in this +* case new column lower bound becomes close to current column upper +* bound u[q], the column can be fixed on its upper bound; +* +* 3) if l'[q] > u[q] + eps, implied lower bound violates current +* column upper bound u[q], in which case the problem has no primal +* feasible solution. */ + +int npp_implied_lower(NPP *npp, NPPCOL *q, double l) +{ /* process implied column lower bound */ + int ret; + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* implied lower bound must be finite */ + xassert(l != -DBL_MAX); + /* if column is integral, round up l'[q] */ + if (q->is_int) + { nint = floor(l + 0.5); + if (fabs(l - nint) <= 1e-5) + l = nint; + else + l = ceil(l); + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->lb)); + if (l < q->lb + eps) + { ret = 0; /* redundant */ + goto done; + } + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); + if (l > q->ub + eps) + { ret = 4; /* infeasible */ + goto done; + } + /* if l'[q] is close to u[q], fix column at its upper bound */ + if (l > q->ub - 1e-3 * eps) + { q->lb = q->ub; + ret = 3; /* fixed */ + goto done; + } + } + /* check if column lower bound changes significantly */ + if (q->lb == -DBL_MAX) + ret = 2; /* significantly */ + else if (q->is_int && l > q->lb + 0.5) + ret = 2; /* significantly */ + else if (l > q->lb + 0.30 * (1.0 + fabs(q->lb))) + ret = 2; /* significantly */ + else + ret = 1; /* not significantly */ + /* set new column lower bound */ + q->lb = l; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_implied_upper - process implied column upper bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_upper(NPP *npp, NPPCOL *q, double u); +* +* DESCRIPTION +* +* For column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], the routine npp_implied_upper processes its +* implied upper bound u'[q]. As the result the current column upper +* bound may decrease. Note that the column is kept in the problem in +* any case. +* +* RETURNS +* +* 0 - current column upper bound has not changed; +* +* 1 - current column upper bound has changed, but not significantly; +* +* 2 - current column upper bound has significantly changed; +* +* 3 - column has been fixed on its lower bound; +* +* 4 - implied upper bound violates current column lower bound. +* +* ALGORITHM +* +* If column q is integral, before processing its implied upper bound +* should be rounded down: +* +* ( floor(u'[q]+0.5), if |u'[q] - floor(l'[q]+0.5)| <= eps +* u'[q] := < (2) +* ( floor(l'[q]), otherwise +* +* where floor(u'[q]+0.5) is the nearest integer to u'[q], +* floor(u'[q]) is largest integer not greater than u'[q], and eps is +* an absolute tolerance for column value. +* +* Processing implied column upper bound u'[q] includes the following +* cases: +* +* 1) if u'[q] > u[q] - eps, implied upper bound is redundant; +* +* 2) if l[q] - eps <= u[q] <= u[q] - eps, current column upper bound +* u[q] can be strengthened by replacing it with u'[q]. If in this +* case new column upper bound becomes close to current column lower +* bound, the column can be fixed on its lower bound; +* +* 3) if u'[q] < l[q] - eps, implied upper bound violates current +* column lower bound l[q], in which case the problem has no primal +* feasible solution. */ + +int npp_implied_upper(NPP *npp, NPPCOL *q, double u) +{ int ret; + double eps, nint; + xassert(npp == npp); + /* column must not be fixed */ + xassert(q->lb < q->ub); + /* implied upper bound must be finite */ + xassert(u != +DBL_MAX); + /* if column is integral, round down u'[q] */ + if (q->is_int) + { nint = floor(u + 0.5); + if (fabs(u - nint) <= 1e-5) + u = nint; + else + u = floor(u); + } + /* check current column upper bound */ + if (q->ub != +DBL_MAX) + { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->ub)); + if (u > q->ub - eps) + { ret = 0; /* redundant */ + goto done; + } + } + /* check current column lower bound */ + if (q->lb != -DBL_MAX) + { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); + if (u < q->lb - eps) + { ret = 4; /* infeasible */ + goto done; + } + /* if u'[q] is close to l[q], fix column at its lower bound */ + if (u < q->lb + 1e-3 * eps) + { q->ub = q->lb; + ret = 3; /* fixed */ + goto done; + } + } + /* check if column upper bound changes significantly */ + if (q->ub == +DBL_MAX) + ret = 2; /* significantly */ + else if (q->is_int && u < q->ub - 0.5) + ret = 2; /* significantly */ + else if (u < q->ub - 0.30 * (1.0 + fabs(q->ub))) + ret = 2; /* significantly */ + else + ret = 1; /* not significantly */ + /* set new column upper bound */ + q->ub = u; +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_ineq_singlet - process row singleton (inequality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_ineq_singlet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_ineq_singlet processes row p, which is inequality +* constraint having the only non-zero coefficient: +* +* L[p] <= a[p,q] * x[q] <= U[p], (1) +* +* where L[p] < U[p], L[p] > -oo and/or U[p] < +oo. +* +* RETURNS +* +* 0 - current column bounds have not changed; +* +* 1 - current column bounds have changed, but not significantly; +* +* 2 - current column bounds have significantly changed; +* +* 3 - column has been fixed on its lower or upper bound; +* +* 4 - problem has no primal feasible solution. +* +* PROBLEM TRANSFORMATION +* +* Inequality constraint (1) defines implied bounds of column q: +* +* ( L[p] / a[p,q], if a[p,q] > 0 +* l'[q] = < (2) +* ( U[p] / a[p,q], if a[p,q] < 0 +* +* ( U[p] / a[p,q], if a[p,q] > 0 +* u'[q] = < (3) +* ( L[p] / a[p,q], if a[p,q] < 0 +* +* If these implied bounds do not violate current bounds of column q: +* +* l[q] <= x[q] <= u[q], (4) +* +* they can be used to strengthen the current column bounds: +* +* l[q] := max(l[q], l'[q]), (5) +* +* u[q] := min(u[q], u'[q]). (6) +* +* (See the routines npp_implied_lower and npp_implied_upper.) +* +* Once bounds of row p (1) have been carried over column q, the row +* becomes redundant, so it can be replaced by equivalent free row and +* removed from the problem. +* +* Note that the routine removes from the problem only row p. Column q, +* even it has been fixed, is kept in the problem. +* +* RECOVERING BASIC SOLUTION +* +* Note that the row in the dual system corresponding to column q is +* the following: +* +* sum a[i,q] pi[i] + lambda[q] = c[q] ==> +* i +* (7) +* sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q], +* i!=p +* +* where pi[i] for all i != p are known in solution to the transformed +* problem. Row p does not exist in the transformed problem, so it has +* zero multiplier there. This allows computing multiplier for column q +* in solution to the transformed problem: +* +* lambda~[q] = c[q] - sum a[i,q] pi[i]. (8) +* i!=p +* +* Let in solution to the transformed problem column q be non-basic +* with lower bound active (GLP_NL, lambda~[q] >= 0), and this lower +* bound be implied one l'[q]. From the original problem's standpoint +* this then means that actually the original column lower bound l[q] +* is inactive, and active is that row bound L[p] or U[p] that defines +* the implied bound l'[q] (2). In this case in solution to the +* original problem column q is assigned status GLP_BS while row p is +* assigned status GLP_NL (if a[p,q] > 0) or GLP_NU (if a[p,q] < 0). +* Since now column q is basic, its multiplier lambda[q] is zero. This +* allows using (7) and (8) to find multiplier for row p in solution to +* the original problem: +* +* 1 +* pi[p] = ------ (c[q] - sum a[i,q] pi[i]) = lambda~[q] / a[p,q] (9) +* a[p,q] i!=p +* +* Now let in solution to the transformed problem column q be non-basic +* with upper bound active (GLP_NU, lambda~[q] <= 0), and this upper +* bound be implied one u'[q]. As in the previous case this then means +* that from the original problem's standpoint actually the original +* column upper bound u[q] is inactive, and active is that row bound +* L[p] or U[p] that defines the implied bound u'[q] (3). In this case +* in solution to the original problem column q is assigned status +* GLP_BS, row p is assigned status GLP_NU (if a[p,q] > 0) or GLP_NL +* (if a[p,q] < 0), and its multiplier is computed with formula (9). +* +* Strengthening bounds of column q according to (5) and (6) may make +* it fixed. Thus, if in solution to the transformed problem column q is +* non-basic and fixed (GLP_NS), we can suppose that if lambda~[q] > 0, +* column q has active lower bound (GLP_NL), and if lambda~[q] < 0, +* column q has active upper bound (GLP_NU), reducing this case to two +* previous ones. If, however, lambda~[q] is close to zero or +* corresponding bound of row p does not exist (this may happen if +* lambda~[q] has wrong sign due to round-off errors, in which case it +* is expected to be close to zero, since solution is assumed to be dual +* feasible), column q can be assigned status GLP_BS (basic), and row p +* can be made active on its existing bound. In the latter case row +* multiplier pi[p] computed with formula (9) will be also close to +* zero, and dual feasibility will be kept. +* +* In all other cases, namely, if in solution to the transformed +* problem column q is basic (GLP_BS), or non-basic with original lower +* bound l[q] active (GLP_NL), or non-basic with original upper bound +* u[q] active (GLP_NU), constraint (1) is inactive. So in solution to +* the original problem status of column q remains unchanged, row p is +* assigned status GLP_BS, and its multiplier pi[p] is assigned zero +* value. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* First, value of multiplier for column q in solution to the original +* problem is computed with formula (8). If lambda~[q] > 0 and column q +* has implied lower bound, or if lambda~[q] < 0 and column q has +* implied upper bound, this means that from the original problem's +* standpoint actually row p has corresponding active bound, in which +* case its multiplier pi[p] is computed with formula (9). In other +* cases, when the sign of lambda~[q] corresponds to original bound of +* column q, or when lambda~[q] =~ 0, value of row multiplier pi[p] is +* assigned zero value. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct ineq_singlet +{ /* row singleton (inequality constraint) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double c; + /* objective coefficient at x[q] */ + double lb; + /* row lower bound */ + double ub; + /* row upper bound */ + char lb_changed; + /* this flag is set if column lower bound was changed */ + char ub_changed; + /* this flag is set if column upper bound was changed */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_ineq_singlet(NPP *npp, void *info); + +int npp_ineq_singlet(NPP *npp, NPPROW *p) +{ /* process row singleton (inequality constraint) */ + struct ineq_singlet *info; + NPPCOL *q; + NPPAIJ *apq, *aij; + NPPLFE *lfe; + int lb_changed, ub_changed; + double ll, uu; + /* the row must be singleton inequality constraint */ + xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + xassert(p->ptr != NULL && p->ptr->r_next == NULL); + /* compute implied column bounds */ + apq = p->ptr; + q = apq->col; + xassert(q->lb < q->ub); + if (apq->val > 0.0) + { ll = (p->lb == -DBL_MAX ? -DBL_MAX : p->lb / apq->val); + uu = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub / apq->val); + } + else + { ll = (p->ub == +DBL_MAX ? -DBL_MAX : p->ub / apq->val); + uu = (p->lb == -DBL_MAX ? +DBL_MAX : p->lb / apq->val); + } + /* process implied column lower bound */ + if (ll == -DBL_MAX) + lb_changed = 0; + else + { lb_changed = npp_implied_lower(npp, q, ll); + xassert(0 <= lb_changed && lb_changed <= 4); + if (lb_changed == 4) return 4; /* infeasible */ + } + /* process implied column upper bound */ + if (uu == +DBL_MAX) + ub_changed = 0; + else if (lb_changed == 3) + { /* column was fixed on its upper bound due to l'[q] = u[q] */ + /* note that L[p] < U[p], so l'[q] = u[q] < u'[q] */ + ub_changed = 0; + } + else + { ub_changed = npp_implied_upper(npp, q, uu); + xassert(0 <= ub_changed && ub_changed <= 4); + if (ub_changed == 4) return 4; /* infeasible */ + } + /* if neither lower nor upper column bound was changed, the row + is originally redundant and can be replaced by free row */ + if (!lb_changed && !ub_changed) + { p->lb = -DBL_MAX, p->ub = +DBL_MAX; + npp_free_row(npp, p); + return 0; + } + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_ineq_singlet, sizeof(struct ineq_singlet)); + info->p = p->i; + info->q = q->j; + info->apq = apq->val; + info->c = q->coef; + info->lb = p->lb; + info->ub = p->ub; + info->lb_changed = (char)lb_changed; + info->ub_changed = (char)ub_changed; + info->ptr = NULL; + /* save column coefficients a[i,q], i != p (not needed for MIP + solution) */ + if (npp->sol != GLP_MIP) + { for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { if (aij == apq) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + } + /* remove the row from the problem */ + npp_del_row(npp, p); + return lb_changed >= ub_changed ? lb_changed : ub_changed; +} + +static int rcv_ineq_singlet(NPP *npp, void *_info) +{ /* recover row singleton (inequality constraint) */ + struct ineq_singlet *info = _info; + NPPLFE *lfe; + double lambda; + if (npp->sol == GLP_MIP) goto done; + /* compute lambda~[q] in solution to the transformed problem + with formula (8) */ + lambda = info->c; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + lambda -= lfe->val * npp->r_pi[lfe->ref]; + if (npp->sol == GLP_SOL) + { /* recover basic solution */ + if (npp->c_stat[info->q] == GLP_BS) + { /* column q is basic, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + else if (npp->c_stat[info->q] == GLP_NL) +nl: { /* column q is non-basic with lower bound active */ + if (info->lb_changed) + { /* it is implied bound, so actually row p is active + while column q is basic */ + npp->r_stat[info->p] = + (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* it is original bound, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + } + else if (npp->c_stat[info->q] == GLP_NU) +nu: { /* column q is non-basic with upper bound active */ + if (info->ub_changed) + { /* it is implied bound, so actually row p is active + while column q is basic */ + npp->r_stat[info->p] = + (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* it is original bound, so row p is inactive */ + npp->r_stat[info->p] = GLP_BS; + npp->r_pi[info->p] = 0.0; + } + } + else if (npp->c_stat[info->q] == GLP_NS) + { /* column q is non-basic and fixed; note, however, that in + in the original problem it is non-fixed */ + if (lambda > +1e-7) + { if (info->apq > 0.0 && info->lb != -DBL_MAX || + info->apq < 0.0 && info->ub != +DBL_MAX || + !info->lb_changed) + { /* either corresponding bound of row p exists or + column q remains non-basic with its original lower + bound active */ + npp->c_stat[info->q] = GLP_NL; + goto nl; + } + } + if (lambda < -1e-7) + { if (info->apq > 0.0 && info->ub != +DBL_MAX || + info->apq < 0.0 && info->lb != -DBL_MAX || + !info->ub_changed) + { /* either corresponding bound of row p exists or + column q remains non-basic with its original upper + bound active */ + npp->c_stat[info->q] = GLP_NU; + goto nu; + } + } + /* either lambda~[q] is close to zero, or corresponding + bound of row p does not exist, because lambda~[q] has + wrong sign due to round-off errors; in the latter case + lambda~[q] is also assumed to be close to zero; so, we + can make row p active on its existing bound and column q + basic; pi[p] will have wrong sign, but it also will be + close to zero (rarus casus of dual degeneracy) */ + if (info->lb != -DBL_MAX && info->ub == +DBL_MAX) + { /* row lower bound exists, but upper bound doesn't */ + npp->r_stat[info->p] = GLP_NL; + } + else if (info->lb == -DBL_MAX && info->ub != +DBL_MAX) + { /* row upper bound exists, but lower bound doesn't */ + npp->r_stat[info->p] = GLP_NU; + } + else if (info->lb != -DBL_MAX && info->ub != +DBL_MAX) + { /* both row lower and upper bounds exist */ + /* to choose proper active row bound we should not use + lambda~[q], because its value being close to zero is + unreliable; so we choose that bound which provides + primal feasibility for original constraint (1) */ + if (info->apq * npp->c_value[info->q] <= + 0.5 * (info->lb + info->ub)) + npp->r_stat[info->p] = GLP_NL; + else + npp->r_stat[info->p] = GLP_NU; + } + else + { npp_error(); + return 1; + } + npp->c_stat[info->q] = GLP_BS; + npp->r_pi[info->p] = lambda / info->apq; + } + else + { npp_error(); + return 1; + } + } + if (npp->sol == GLP_IPT) + { /* recover interior-point solution */ + if (lambda > +DBL_EPSILON && info->lb_changed || + lambda < -DBL_EPSILON && info->ub_changed) + { /* actually row p has corresponding active bound */ + npp->r_pi[info->p] = lambda / info->apq; + } + else + { /* either bounds of column q are both inactive or its + original bound is active */ + npp->r_pi[info->p] = 0.0; + } + } +done: return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_slack - process column singleton (implied slack variable) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_implied_slack(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_implied_slack processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], having the only non-zero coefficient in row p, +* which is equality constraint: +* +* sum a[p,j] x[j] + a[p,q] x[q] = b. (2) +* j!=q +* +* PROBLEM TRANSFORMATION +* +* (If x[q] is integral, this transformation must not be used.) +* +* The term a[p,q] x[q] in constraint (2) can be considered as a slack +* variable that allows to carry bounds of column q over row p and then +* remove column q from the problem. +* +* Constraint (2) can be written as follows: +* +* sum a[p,j] x[j] = b - a[p,q] x[q]. (3) +* j!=q +* +* According to (1) constraint (3) is equivalent to the following +* inequality constraint: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (4) +* j!=q +* +* where +* +* ( b - a[p,q] u[q], if a[p,q] > 0 +* L[p] = < (5) +* ( b - a[p,q] l[q], if a[p,q] < 0 +* +* ( b - a[p,q] l[q], if a[p,q] > 0 +* U[p] = < (6) +* ( b - a[p,q] u[q], if a[p,q] < 0 +* +* From (2) it follows that: +* +* 1 +* x[q] = ------ (b - sum a[p,j] x[j]). (7) +* a[p,q] j!=q +* +* In order to eliminate x[q] from the objective row we substitute it +* from (6) to that row: +* +* z = sum c[j] x[j] + c[q] x[q] + c[0] = +* j!=q +* 1 +* = sum c[j] x[j] + c[q] [------ (b - sum a[p,j] x[j])] + c0 = +* j!=q a[p,q] j!=q +* +* = sum c~[j] x[j] + c~[0], +* j!=q +* a[p,j] b +* c~[j] = c[j] - c[q] ------, c~0 = c0 - c[q] ------ (8) +* a[p,q] a[p,q] +* +* are values of objective coefficients and constant term, resp., in +* the transformed problem. +* +* Note that column q is column singleton, so in the dual system of the +* original problem it corresponds to the following row singleton: +* +* a[p,q] pi[p] + lambda[q] = c[q]. (9) +* +* In the transformed problem row (9) would be the following: +* +* a[p,q] pi~[p] + lambda[q] = c~[q] = 0. (10) +* +* Subtracting (10) from (9) we have: +* +* a[p,q] (pi[p] - pi~[p]) = c[q] +* +* that gives the following formula to compute multiplier for row p in +* solution to the original problem using its value in solution to the +* transformed problem: +* +* pi[p] = pi~[p] + c[q] / a[p,q]. (11) +* +* RECOVERING BASIC SOLUTION +* +* Status of column q in solution to the original problem is defined +* by status of row p in solution to the transformed problem and the +* sign of coefficient a[p,q] in the original inequality constraint (2) +* as follows: +* +* +-----------------------+---------+--------------------+ +* | Status of row p | Sign of | Status of column q | +* | (transformed problem) | a[p,q] | (original problem) | +* +-----------------------+---------+--------------------+ +* | GLP_BS | + / - | GLP_BS | +* | GLP_NL | + | GLP_NU | +* | GLP_NL | - | GLP_NL | +* | GLP_NU | + | GLP_NL | +* | GLP_NU | - | GLP_NU | +* | GLP_NF | + / - | GLP_NF | +* +-----------------------+---------+--------------------+ +* +* Value of column q is computed with formula (7). Since originally row +* p is equality constraint, its status is assigned GLP_NS, and value of +* its multiplier pi[p] is computed with formula (11). +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of column q is computed with formula (7). Row multiplier value +* pi[p] is computed with formula (11). +* +* RECOVERING MIP SOLUTION +* +* Value of column q is computed with formula (7). */ + +struct implied_slack +{ /* column singleton (implied slack variable) */ + int p; + /* row reference number */ + int q; + /* column reference number */ + double apq; + /* constraint coefficient a[p,q] */ + double b; + /* right-hand side of original equality constraint */ + double c; + /* original objective coefficient at x[q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[p,j], j != q */ +}; + +static int rcv_implied_slack(NPP *npp, void *info); + +void npp_implied_slack(NPP *npp, NPPCOL *q) +{ /* process column singleton (implied slack variable) */ + struct implied_slack *info; + NPPROW *p; + NPPAIJ *aij; + NPPLFE *lfe; + /* the column must be non-integral non-fixed singleton */ + xassert(!q->is_int); + xassert(q->lb < q->ub); + xassert(q->ptr != NULL && q->ptr->c_next == NULL); + /* corresponding row must be equality constraint */ + aij = q->ptr; + p = aij->row; + xassert(p->lb == p->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_implied_slack, sizeof(struct implied_slack)); + info->p = p->i; + info->q = q->j; + info->apq = aij->val; + info->b = p->lb; + info->c = q->coef; + info->ptr = NULL; + /* save row coefficients a[p,j], j != q, and substitute x[q] + into the objective row */ + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->col == q) continue; /* skip a[p,q] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->col->j; + lfe->val = aij->val; + lfe->next = info->ptr; + info->ptr = lfe; + aij->col->coef -= info->c * (aij->val / info->apq); + } + npp->c0 += info->c * (info->b / info->apq); + /* compute new row bounds */ + if (info->apq > 0.0) + { p->lb = (q->ub == +DBL_MAX ? + -DBL_MAX : info->b - info->apq * q->ub); + p->ub = (q->lb == -DBL_MAX ? + +DBL_MAX : info->b - info->apq * q->lb); + } + else + { p->lb = (q->lb == -DBL_MAX ? + -DBL_MAX : info->b - info->apq * q->lb); + p->ub = (q->ub == +DBL_MAX ? + +DBL_MAX : info->b - info->apq * q->ub); + } + /* remove the column from the problem */ + npp_del_col(npp, q); + return; +} + +static int rcv_implied_slack(NPP *npp, void *_info) +{ /* recover column singleton (implied slack variable) */ + struct implied_slack *info = _info; + NPPLFE *lfe; + double temp; + if (npp->sol == GLP_SOL) + { /* assign statuses to row p and column q */ + if (npp->r_stat[info->p] == GLP_BS || + npp->r_stat[info->p] == GLP_NF) + npp->c_stat[info->q] = npp->r_stat[info->p]; + else if (npp->r_stat[info->p] == GLP_NL) + npp->c_stat[info->q] = + (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); + else if (npp->r_stat[info->p] == GLP_NU) + npp->c_stat[info->q] = + (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); + else + { npp_error(); + return 1; + } + npp->r_stat[info->p] = GLP_NS; + } + if (npp->sol != GLP_MIP) + { /* compute multiplier for row p */ + npp->r_pi[info->p] += info->c / info->apq; + } + /* compute value of column q */ + temp = info->b; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + temp -= lfe->val * npp->c_value[lfe->ref]; + npp->c_value[info->q] = temp / info->apq; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_free - process column singleton (implied free variable) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_free(NPP *npp, NPPCOL *q); +* +* DESCRIPTION +* +* The routine npp_implied_free processes column q: +* +* l[q] <= x[q] <= u[q], (1) +* +* having non-zero coefficient in the only row p, which is inequality +* constraint: +* +* L[p] <= sum a[p,j] x[j] + a[p,q] x[q] <= U[p], (2) +* j!=q +* +* where l[q] < u[q], L[p] < U[p], L[p] > -oo and/or U[p] < +oo. +* +* RETURNS +* +* 0 - success; +* +* 1 - column lower and/or upper bound(s) can be active; +* +* 2 - problem has no dual feasible solution. +* +* PROBLEM TRANSFORMATION +* +* Constraint (2) can be written as follows: +* +* L[p] - sum a[p,j] x[j] <= a[p,q] x[q] <= U[p] - sum a[p,j] x[j], +* j!=q j!=q +* +* from which it follows that: +* +* alfa <= a[p,q] x[q] <= beta, (3) +* +* where +* +* alfa = inf(L[p] - sum a[p,j] x[j]) = +* j!=q +* +* = L[p] - sup sum a[p,j] x[j] = (4) +* j!=q +* +* = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j], +* j in Jp j in Jn +* +* beta = sup(L[p] - sum a[p,j] x[j]) = +* j!=q +* +* = L[p] - inf sum a[p,j] x[j] = (5) +* j!=q +* +* = L[p] - sum a[p,j] l[j] - sum a[p,j] u[j], +* j in Jp j in Jn +* +* Jp = {j != q: a[p,j] > 0}, Jn = {j != q: a[p,j] < 0}. (6) +* +* Inequality (3) defines implied bounds of variable x[q]: +* +* l'[q] <= x[q] <= u'[q], (7) +* +* where +* +* ( alfa / a[p,q], if a[p,q] > 0 +* l'[q] = < (8a) +* ( beta / a[p,q], if a[p,q] < 0 +* +* ( beta / a[p,q], if a[p,q] > 0 +* u'[q] = < (8b) +* ( alfa / a[p,q], if a[p,q] < 0 +* +* Thus, if l'[q] > l[q] - eps and u'[q] < u[q] + eps, where eps is +* an absolute tolerance for column value, column bounds (1) cannot be +* active, in which case column q can be replaced by equivalent free +* (unbounded) column. +* +* Note that column q is column singleton, so in the dual system of the +* original problem it corresponds to the following row singleton: +* +* a[p,q] pi[p] + lambda[q] = c[q], (9) +* +* from which it follows that: +* +* pi[p] = (c[q] - lambda[q]) / a[p,q]. (10) +* +* Let x[q] be implied free (unbounded) variable. Then column q can be +* only basic, so its multiplier lambda[q] is equal to zero, and from +* (10) we have: +* +* pi[p] = c[q] / a[p,q]. (11) +* +* There are possible three cases: +* +* 1) pi[p] < -eps, where eps is an absolute tolerance for row +* multiplier. In this case, to provide dual feasibility of the +* original problem, row p must be active on its lower bound, and +* if its lower bound does not exist (L[p] = -oo), the problem has +* no dual feasible solution; +* +* 2) pi[p] > +eps. In this case row p must be active on its upper +* bound, and if its upper bound does not exist (U[p] = +oo), the +* problem has no dual feasible solution; +* +* 3) -eps <= pi[p] <= +eps. In this case any (either lower or upper) +* bound of row p can be active, because this does not affect dual +* feasibility. +* +* Thus, in all three cases original inequality constraint (2) can be +* replaced by equality constraint, where the right-hand side is either +* lower or upper bound of row p, and bounds of column q can be removed +* that makes it free (unbounded). (May note that this transformation +* can be followed by transformation "Column singleton (implied slack +* variable)" performed by the routine npp_implied_slack.) +* +* RECOVERING BASIC SOLUTION +* +* Status of row p in solution to the original problem is determined +* by its status in solution to the transformed problem and its bound, +* which was choosen to be active: +* +* +-----------------------+--------+--------------------+ +* | Status of row p | Active | Status of row p | +* | (transformed problem) | bound | (original problem) | +* +-----------------------+--------+--------------------+ +* | GLP_BS | L[p] | GLP_BS | +* | GLP_BS | U[p] | GLP_BS | +* | GLP_NS | L[p] | GLP_NL | +* | GLP_NS | U[p] | GLP_NU | +* +-----------------------+--------+--------------------+ +* +* Value of row multiplier pi[p] (as well as value of column q) in +* solution to the original problem is the same as in solution to the +* transformed problem. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of row multiplier pi[p] in solution to the original problem is +* the same as in solution to the transformed problem. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct implied_free +{ /* column singleton (implied free variable) */ + int p; + /* row reference number */ + char stat; + /* row status: + GLP_NL - active constraint on lower bound + GLP_NU - active constraint on upper bound */ +}; + +static int rcv_implied_free(NPP *npp, void *info); + +int npp_implied_free(NPP *npp, NPPCOL *q) +{ /* process column singleton (implied free variable) */ + struct implied_free *info; + NPPROW *p; + NPPAIJ *apq, *aij; + double alfa, beta, l, u, pi, eps; + /* the column must be non-fixed singleton */ + xassert(q->lb < q->ub); + xassert(q->ptr != NULL && q->ptr->c_next == NULL); + /* corresponding row must be inequality constraint */ + apq = q->ptr; + p = apq->row; + xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); + xassert(p->lb < p->ub); + /* compute alfa */ + alfa = p->lb; + if (alfa != -DBL_MAX) + { for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij == apq) continue; /* skip a[p,q] */ + if (aij->val > 0.0) + { if (aij->col->ub == +DBL_MAX) + { alfa = -DBL_MAX; + break; + } + alfa -= aij->val * aij->col->ub; + } + else /* < 0.0 */ + { if (aij->col->lb == -DBL_MAX) + { alfa = -DBL_MAX; + break; + } + alfa -= aij->val * aij->col->lb; + } + } + } + /* compute beta */ + beta = p->ub; + if (beta != +DBL_MAX) + { for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij == apq) continue; /* skip a[p,q] */ + if (aij->val > 0.0) + { if (aij->col->lb == -DBL_MAX) + { beta = +DBL_MAX; + break; + } + beta -= aij->val * aij->col->lb; + } + else /* < 0.0 */ + { if (aij->col->ub == +DBL_MAX) + { beta = +DBL_MAX; + break; + } + beta -= aij->val * aij->col->ub; + } + } + } + /* compute implied column lower bound l'[q] */ + if (apq->val > 0.0) + l = (alfa == -DBL_MAX ? -DBL_MAX : alfa / apq->val); + else /* < 0.0 */ + l = (beta == +DBL_MAX ? -DBL_MAX : beta / apq->val); + /* compute implied column upper bound u'[q] */ + if (apq->val > 0.0) + u = (beta == +DBL_MAX ? +DBL_MAX : beta / apq->val); + else + u = (alfa == -DBL_MAX ? +DBL_MAX : alfa / apq->val); + /* check if column lower bound l[q] can be active */ + if (q->lb != -DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(q->lb); + if (l < q->lb - eps) return 1; /* yes, it can */ + } + /* check if column upper bound u[q] can be active */ + if (q->ub != +DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(q->ub); + if (u > q->ub + eps) return 1; /* yes, it can */ + } + /* okay; make column q free (unbounded) */ + q->lb = -DBL_MAX, q->ub = +DBL_MAX; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_implied_free, sizeof(struct implied_free)); + info->p = p->i; + info->stat = -1; + /* compute row multiplier pi[p] */ + pi = q->coef / apq->val; + /* check dual feasibility for row p */ + if (pi > +DBL_EPSILON) + { /* lower bound L[p] must be active */ + if (p->lb != -DBL_MAX) +nl: { info->stat = GLP_NL; + p->ub = p->lb; + } + else + { if (pi > +1e-5) return 2; /* dual infeasibility */ + /* take a chance on U[p] */ + xassert(p->ub != +DBL_MAX); + goto nu; + } + } + else if (pi < -DBL_EPSILON) + { /* upper bound U[p] must be active */ + if (p->ub != +DBL_MAX) +nu: { info->stat = GLP_NU; + p->lb = p->ub; + } + else + { if (pi < -1e-5) return 2; /* dual infeasibility */ + /* take a chance on L[p] */ + xassert(p->lb != -DBL_MAX); + goto nl; + } + } + else + { /* any bound (either L[p] or U[p]) can be made active */ + if (p->ub == +DBL_MAX) + { xassert(p->lb != -DBL_MAX); + goto nl; + } + if (p->lb == -DBL_MAX) + { xassert(p->ub != +DBL_MAX); + goto nu; + } + if (fabs(p->lb) <= fabs(p->ub)) goto nl; else goto nu; + } + return 0; +} + +static int rcv_implied_free(NPP *npp, void *_info) +{ /* recover column singleton (implied free variable) */ + struct implied_free *info = _info; + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else if (npp->r_stat[info->p] == GLP_NS) + { xassert(info->stat == GLP_NL || info->stat == GLP_NU); + npp->r_stat[info->p] = info->stat; + } + else + { npp_error(); + return 1; + } + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_eq_doublet - process row doubleton (equality constraint) +* +* SYNOPSIS +* +* #include "glpnpp.h" +* NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_eq_doublet processes row p, which is equality +* constraint having exactly two non-zero coefficients: +* +* a[p,q] x[q] + a[p,r] x[r] = b. (1) +* +* As the result of processing one of columns q or r is eliminated from +* all other rows and, thus, becomes column singleton of type "implied +* slack variable". Row p is not changed and along with column q and r +* remains in the problem. +* +* RETURNS +* +* The routine npp_eq_doublet returns pointer to the descriptor of that +* column q or r which has been eliminated. If, due to some reason, the +* elimination was not performed, the routine returns NULL. +* +* PROBLEM TRANSFORMATION +* +* First, we decide which column q or r will be eliminated. Let it be +* column q. Consider i-th constraint row, where column q has non-zero +* coefficient a[i,q] != 0: +* +* L[i] <= sum a[i,j] x[j] <= U[i]. (2) +* j +* +* In order to eliminate column q from row (2) we subtract from it row +* (1) multiplied by gamma[i] = a[i,q] / a[p,q], i.e. we replace in the +* transformed problem row (2) by its linear combination with row (1). +* This transformation changes only coefficients in columns q and r, +* and bounds of row i as follows: +* +* a~[i,q] = a[i,q] - gamma[i] a[p,q] = 0, (3) +* +* a~[i,r] = a[i,r] - gamma[i] a[p,r], (4) +* +* L~[i] = L[i] - gamma[i] b, (5) +* +* U~[i] = U[i] - gamma[i] b. (6) +* +* RECOVERING BASIC SOLUTION +* +* The transformation of the primal system of the original problem: +* +* L <= A x <= U (7) +* +* is equivalent to multiplying from the left a transformation matrix F +* by components of this primal system, which in the transformed problem +* becomes the following: +* +* F L <= F A x <= F U ==> L~ <= A~x <= U~. (8) +* +* The matrix F has the following structure: +* +* ( 1 -gamma[1] ) +* ( ) +* ( 1 -gamma[2] ) +* ( ) +* ( ... ... ) +* ( ) +* F = ( 1 -gamma[p-1] ) (9) +* ( ) +* ( 1 ) +* ( ) +* ( -gamma[p+1] 1 ) +* ( ) +* ( ... ... ) +* +* where its column containing elements -gamma[i] corresponds to row p +* of the primal system. +* +* From (8) it follows that the dual system of the original problem: +* +* A'pi + lambda = c, (10) +* +* in the transformed problem becomes the following: +* +* A'F'inv(F')pi + lambda = c ==> (A~)'pi~ + lambda = c, (11) +* +* where: +* +* pi~ = inv(F')pi (12) +* +* is the vector of row multipliers in the transformed problem. Thus: +* +* pi = F'pi~. (13) +* +* Therefore, as it follows from (13), value of multiplier for row p in +* solution to the original problem can be computed as follows: +* +* pi[p] = pi~[p] - sum gamma[i] pi~[i], (14) +* i +* +* where pi~[i] = pi[i] is multiplier for row i (i != p). +* +* Note that the statuses of all rows and columns are not changed. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Multiplier for row p in solution to the original problem is computed +* with formula (14). +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct eq_doublet +{ /* row doubleton (equality constraint) */ + int p; + /* row reference number */ + double apq; + /* constraint coefficient a[p,q] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,q], i != p */ +}; + +static int rcv_eq_doublet(NPP *npp, void *info); + +NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p) +{ /* process row doubleton (equality constraint) */ + struct eq_doublet *info; + NPPROW *i; + NPPCOL *q, *r; + NPPAIJ *apq, *apr, *aiq, *air, *next; + NPPLFE *lfe; + double gamma; + /* the row must be doubleton equality constraint */ + xassert(p->lb == p->ub); + xassert(p->ptr != NULL && p->ptr->r_next != NULL && + p->ptr->r_next->r_next == NULL); + /* choose column to be eliminated */ + { NPPAIJ *a1, *a2; + a1 = p->ptr, a2 = a1->r_next; + if (fabs(a2->val) < 0.001 * fabs(a1->val)) + { /* only first column can be eliminated, because second one + has too small constraint coefficient */ + apq = a1, apr = a2; + } + else if (fabs(a1->val) < 0.001 * fabs(a2->val)) + { /* only second column can be eliminated, because first one + has too small constraint coefficient */ + apq = a2, apr = a1; + } + else + { /* both columns are appropriate; choose that one which is + shorter to minimize fill-in */ + if (npp_col_nnz(npp, a1->col) <= npp_col_nnz(npp, a2->col)) + { /* first column is shorter */ + apq = a1, apr = a2; + } + else + { /* second column is shorter */ + apq = a2, apr = a1; + } + } + } + /* now columns q and r have been chosen */ + q = apq->col, r = apr->col; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_eq_doublet, sizeof(struct eq_doublet)); + info->p = p->i; + info->apq = apq->val; + info->ptr = NULL; + /* transform each row i (i != p), where a[i,q] != 0, to eliminate + column q */ + for (aiq = q->ptr; aiq != NULL; aiq = next) + { next = aiq->c_next; + if (aiq == apq) continue; /* skip row p */ + i = aiq->row; /* row i to be transformed */ + /* save constraint coefficient a[i,q] */ + if (npp->sol != GLP_MIP) + { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = i->i; + lfe->val = aiq->val; + lfe->next = info->ptr; + info->ptr = lfe; + } + /* find coefficient a[i,r] in row i */ + for (air = i->ptr; air != NULL; air = air->r_next) + if (air->col == r) break; + /* if a[i,r] does not exist, create a[i,r] = 0 */ + if (air == NULL) + air = npp_add_aij(npp, i, r, 0.0); + /* compute gamma[i] = a[i,q] / a[p,q] */ + gamma = aiq->val / apq->val; + /* (row i) := (row i) - gamma[i] * (row p); see (3)-(6) */ + /* new a[i,q] is exact zero due to elimnation; remove it from + row i */ + npp_del_aij(npp, aiq); + /* compute new a[i,r] */ + air->val -= gamma * apr->val; + /* if new a[i,r] is close to zero due to numeric cancelation, + remove it from row i */ + if (fabs(air->val) <= 1e-10) + npp_del_aij(npp, air); + /* compute new lower and upper bounds of row i */ + if (i->lb == i->ub) + i->lb = i->ub = (i->lb - gamma * p->lb); + else + { if (i->lb != -DBL_MAX) + i->lb -= gamma * p->lb; + if (i->ub != +DBL_MAX) + i->ub -= gamma * p->lb; + } + } + return q; +} + +static int rcv_eq_doublet(NPP *npp, void *_info) +{ /* recover row doubleton (equality constraint) */ + struct eq_doublet *info = _info; + NPPLFE *lfe; + double gamma, temp; + /* we assume that processing row p is followed by processing + column q as singleton of type "implied slack variable", in + which case row p must always be active equality constraint */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] != GLP_NS) + { npp_error(); + return 1; + } + } + if (npp->sol != GLP_MIP) + { /* compute value of multiplier for row p; see (14) */ + temp = npp->r_pi[info->p]; + for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) + { gamma = lfe->val / info->apq; /* a[i,q] / a[p,q] */ + temp -= gamma * npp->r_pi[lfe->ref]; + } + npp->r_pi[info->p] = temp; + } + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_forcing_row - process forcing row +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_forcing_row(NPP *npp, NPPROW *p, int at); +* +* DESCRIPTION +* +* The routine npp_forcing row processes row p of general format: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] < u[j] for all a[p,j] != 0. It is also +* assumed that: +* +* 1) if at = 0 then |L[p] - U'[p]| <= eps, where U'[p] is implied +* row upper bound (see below), eps is an absolute tolerance for row +* value; +* +* 2) if at = 1 then |U[p] - L'[p]| <= eps, where L'[p] is implied +* row lower bound (see below). +* +* RETURNS +* +* 0 - success; +* +* 1 - cannot fix columns due to too small constraint coefficients. +* +* PROBLEM TRANSFORMATION +* +* Implied lower and upper bounds of row (1) are determined by bounds +* of corresponding columns (variables) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* If L[p] =~ U'[p] (at = 0), solution can be primal feasible only when +* all variables take their boundary values as defined by (4): +* +* ( u[j], if j in Jp +* x[j] = < (6) +* ( l[j], if j in Jn +* +* Similarly, if U[p] =~ L'[p] (at = 1), solution can be primal feasible +* only when all variables take their boundary values as defined by (3): +* +* ( l[j], if j in Jp +* x[j] = < (7) +* ( u[j], if j in Jn +* +* Condition (6) or (7) allows fixing all columns (variables x[j]) +* in row (1) on their bounds and then removing them from the problem +* (see the routine npp_fixed_col). Due to this row p becomes redundant, +* so it can be replaced by equivalent free (unbounded) row and also +* removed from the problem (see the routine npp_free_row). +* +* 1. To apply this transformation row (1) should not have coefficients +* whose magnitude is too small, i.e. all a[p,j] should satisfy to +* the following condition: +* +* |a[p,j]| >= eps * max(1, |a[p,k]|), (8) +* k +* where eps is a relative tolerance for constraint coefficients. +* Otherwise, fixing columns may be numerically unreliable and may +* lead to wrong solution. +* +* 2. The routine fixes columns and remove bounds of row p, however, +* it does not remove the row and columns from the problem. +* +* RECOVERING BASIC SOLUTION +* +* In the transformed problem row p being inactive constraint is +* assigned status GLP_BS (as the result of transformation of free +* row), and all columns in this row are assigned status GLP_NS (as the +* result of transformation of fixed columns). +* +* Note that in the dual system of the transformed (as well as original) +* problem every column j in row p corresponds to the following row: +* +* sum a[i,j] pi[i] + a[p,j] pi[p] + lambda[j] = c[j], (9) +* i!=p +* +* from which it follows that: +* +* lambda[j] = c[j] - sum a[i,j] pi[i] - a[p,j] pi[p]. (10) +* i!=p +* +* In the transformed problem values of all multipliers pi[i] are known +* (including pi[i], whose value is zero, since row p is inactive). +* Thus, using formula (10) it is possible to compute values of +* multipliers lambda[j] for all columns in row p. +* +* Note also that in the original problem all columns in row p are +* bounded, not fixed. So status GLP_NS assigned to every such column +* must be changed to GLP_NL or GLP_NU depending on which bound the +* corresponding column has been fixed. This status change may lead to +* dual feasibility violation for solution of the original problem, +* because now column multipliers must satisfy to the following +* condition: +* +* ( >= 0, if status of column j is GLP_NL, +* lambda[j] < (11) +* ( <= 0, if status of column j is GLP_NU. +* +* If this condition holds, solution to the original problem is the +* same as to the transformed problem. Otherwise, we have to perform +* one degenerate pivoting step of the primal simplex method to obtain +* dual feasible (hence, optimal) solution to the original problem as +* follows. If, on problem transformation, row p was made active on its +* lower bound (case at = 0), we change its status to GLP_NL (or GLP_NS) +* and start increasing its multiplier pi[p]. Otherwise, if row p was +* made active on its upper bound (case at = 1), we change its status +* to GLP_NU (or GLP_NS) and start decreasing pi[p]. From (10) it +* follows that: +* +* delta lambda[j] = - a[p,j] * delta pi[p] = - a[p,j] pi[p]. (12) +* +* Simple analysis of formulae (3)-(5) shows that changing pi[p] in the +* specified direction causes increasing lambda[j] for every column j +* assigned status GLP_NL (delta lambda[j] > 0) and decreasing lambda[j] +* for every column j assigned status GLP_NU (delta lambda[j] < 0). It +* is understood that once the last lambda[q], which violates condition +* (11), has reached zero, multipliers lambda[j] for all columns get +* valid signs. Such column q can be determined as follows. Let d[j] be +* initial value of lambda[j] (i.e. reduced cost of column j) in the +* transformed problem computed with formula (10) when pi[p] = 0. Then +* lambda[j] = d[j] + delta lambda[j], and from (12) it follows that +* lambda[j] becomes zero if: +* +* delta lambda[j] = - a[p,j] pi[p] = - d[j] ==> +* (13) +* pi[p] = d[j] / a[p,j]. +* +* Therefore, the last column q, for which lambda[q] becomes zero, can +* be determined from the following condition: +* +* |d[q] / a[p,q]| = max |pi[p]| = max |d[j] / a[p,j]|, (14) +* j in D j in D +* +* where D is a set of columns j whose, reduced costs d[j] have invalid +* signs, i.e. violate condition (11). (Thus, if D is empty, solution +* to the original problem is the same as solution to the transformed +* problem, and no correction is needed as was noticed above.) In +* solution to the original problem column q is assigned status GLP_BS, +* since it replaces column of auxiliary variable of row p (becoming +* active) in the basis, and multiplier for row p is assigned its new +* value, which is pi[p] = d[q] / a[p,q]. Note that due to primal +* degeneracy values of all columns having non-zero coefficients in row +* p remain unchanged. +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* Value of multiplier pi[p] in solution to the original problem is +* corrected in the same way as for basic solution. Values of all +* columns having non-zero coefficients in row p remain unchanged. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct forcing_col +{ /* column fixed on its bound by forcing row */ + int j; + /* column reference number */ + char stat; + /* original column status: + GLP_NL - fixed on lower bound + GLP_NU - fixed on upper bound */ + double a; + /* constraint coefficient a[p,j] */ + double c; + /* objective coefficient c[j] */ + NPPLFE *ptr; + /* list of non-zero coefficients a[i,j], i != p */ + struct forcing_col *next; + /* pointer to another column fixed by forcing row */ +}; + +struct forcing_row +{ /* forcing row */ + int p; + /* row reference number */ + char stat; + /* status assigned to the row if it becomes active: + GLP_NS - active equality constraint + GLP_NL - inequality constraint with lower bound active + GLP_NU - inequality constraint with upper bound active */ + struct forcing_col *ptr; + /* list of all columns having non-zero constraint coefficient + a[p,j] in the forcing row */ +}; + +static int rcv_forcing_row(NPP *npp, void *info); + +int npp_forcing_row(NPP *npp, NPPROW *p, int at) +{ /* process forcing row */ + struct forcing_row *info; + struct forcing_col *col = NULL; + NPPCOL *j; + NPPAIJ *apj, *aij; + NPPLFE *lfe; + double big; + xassert(at == 0 || at == 1); + /* determine maximal magnitude of the row coefficients */ + big = 1.0; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + if (big < fabs(apj->val)) big = fabs(apj->val); + /* if there are too small coefficients in the row, transformation + should not be applied */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + if (fabs(apj->val) < 1e-7 * big) return 1; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_forcing_row, sizeof(struct forcing_row)); + info->p = p->i; + if (p->lb == p->ub) + { /* equality constraint */ + info->stat = GLP_NS; + } + else if (at == 0) + { /* inequality constraint; case L[p] = U'[p] */ + info->stat = GLP_NL; + xassert(p->lb != -DBL_MAX); + } + else /* at == 1 */ + { /* inequality constraint; case U[p] = L'[p] */ + info->stat = GLP_NU; + xassert(p->ub != +DBL_MAX); + } + info->ptr = NULL; + /* scan the forcing row, fix columns at corresponding bounds, and + save column information (the latter is not needed for MIP) */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { /* column j has non-zero coefficient in the forcing row */ + j = apj->col; + /* it must be non-fixed */ + xassert(j->lb < j->ub); + /* allocate stack entry to save column information */ + if (npp->sol != GLP_MIP) + { col = dmp_get_atom(npp->stack, sizeof(struct forcing_col)); + col->j = j->j; + col->stat = -1; /* will be set below */ + col->a = apj->val; + col->c = j->coef; + col->ptr = NULL; + col->next = info->ptr; + info->ptr = col; + } + /* fix column j */ + if (at == 0 && apj->val < 0.0 || at != 0 && apj->val > 0.0) + { /* at its lower bound */ + if (npp->sol != GLP_MIP) + col->stat = GLP_NL; + xassert(j->lb != -DBL_MAX); + j->ub = j->lb; + } + else + { /* at its upper bound */ + if (npp->sol != GLP_MIP) + col->stat = GLP_NU; + xassert(j->ub != +DBL_MAX); + j->lb = j->ub; + } + /* save column coefficients a[i,j], i != p */ + if (npp->sol != GLP_MIP) + { for (aij = j->ptr; aij != NULL; aij = aij->c_next) + { if (aij == apj) continue; /* skip a[p,j] */ + lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); + lfe->ref = aij->row->i; + lfe->val = aij->val; + lfe->next = col->ptr; + col->ptr = lfe; + } + } + } + /* make the row free (unbounded) */ + p->lb = -DBL_MAX, p->ub = +DBL_MAX; + return 0; +} + +static int rcv_forcing_row(NPP *npp, void *_info) +{ /* recover forcing row */ + struct forcing_row *info = _info; + struct forcing_col *col, *piv; + NPPLFE *lfe; + double d, big, temp; + if (npp->sol == GLP_MIP) goto done; + /* initially solution to the original problem is the same as + to the transformed problem, where row p is inactive constraint + with pi[p] = 0, and all columns are non-basic */ + if (npp->sol == GLP_SOL) + { if (npp->r_stat[info->p] != GLP_BS) + { npp_error(); + return 1; + } + for (col = info->ptr; col != NULL; col = col->next) + { if (npp->c_stat[col->j] != GLP_NS) + { npp_error(); + return 1; + } + npp->c_stat[col->j] = col->stat; /* original status */ + } + } + /* compute reduced costs d[j] for all columns with formula (10) + and store them in col.c instead objective coefficients */ + for (col = info->ptr; col != NULL; col = col->next) + { d = col->c; + for (lfe = col->ptr; lfe != NULL; lfe = lfe->next) + d -= lfe->val * npp->r_pi[lfe->ref]; + col->c = d; + } + /* consider columns j, whose multipliers lambda[j] has wrong + sign in solution to the transformed problem (where lambda[j] = + d[j]), and choose column q, whose multipler lambda[q] reaches + zero last on changing row multiplier pi[p]; see (14) */ + piv = NULL, big = 0.0; + for (col = info->ptr; col != NULL; col = col->next) + { d = col->c; /* d[j] */ + temp = fabs(d / col->a); + if (col->stat == GLP_NL) + { /* column j has active lower bound */ + if (d < 0.0 && big < temp) + piv = col, big = temp; + } + else if (col->stat == GLP_NU) + { /* column j has active upper bound */ + if (d > 0.0 && big < temp) + piv = col, big = temp; + } + else + { npp_error(); + return 1; + } + } + /* if column q does not exist, no correction is needed */ + if (piv != NULL) + { /* correct solution; row p becomes active constraint while + column q becomes basic */ + if (npp->sol == GLP_SOL) + { npp->r_stat[info->p] = info->stat; + npp->c_stat[piv->j] = GLP_BS; + } + /* assign new value to row multiplier pi[p] = d[p] / a[p,q] */ + npp->r_pi[info->p] = piv->c / piv->a; + } +done: return 0; +} + +/*********************************************************************** +* NAME +* +* npp_analyze_row - perform general row analysis +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_analyze_row(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_analyze_row performs analysis of row p of general +* format: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* j +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0. +* +* RETURNS +* +* 0x?0 - row lower bound does not exist or is redundant; +* +* 0x?1 - row lower bound can be active; +* +* 0x?2 - row lower bound is a forcing bound; +* +* 0x0? - row upper bound does not exist or is redundant; +* +* 0x1? - row upper bound can be active; +* +* 0x2? - row upper bound is a forcing bound; +* +* 0x33 - row bounds are inconsistent with column bounds. +* +* ALGORITHM +* +* Analysis of row (1) is based on analysis of its implied lower and +* upper bounds, which are determined by bounds of corresponding columns +* (variables) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* (Note that bounds of all columns in row p are assumed to be correct, +* so L'[p] <= U'[p].) +* +* Analysis of row lower bound L[p] includes the following cases: +* +* 1) if L[p] > U'[p] + eps, where eps is an absolute tolerance for row +* value, row lower bound L[p] and implied row upper bound U'[p] are +* inconsistent, ergo, the problem has no primal feasible solution; +* +* 2) if U'[p] - eps <= L[p] <= U'[p] + eps, i.e. if L[p] =~ U'[p], +* the row is a forcing row on its lower bound (see description of +* the routine npp_forcing_row); +* +* 3) if L[p] > L'[p] + eps, row lower bound L[p] can be active (this +* conclusion does not account other rows in the problem); +* +* 4) if L[p] <= L'[p] + eps, row lower bound L[p] cannot be active, so +* it is redundant and can be removed (replaced by -oo). +* +* Analysis of row upper bound U[p] is performed in a similar way and +* includes the following cases: +* +* 1) if U[p] < L'[p] - eps, row upper bound U[p] and implied row lower +* bound L'[p] are inconsistent, ergo the problem has no primal +* feasible solution; +* +* 2) if L'[p] - eps <= U[p] <= L'[p] + eps, i.e. if U[p] =~ L'[p], +* the row is a forcing row on its upper bound (see description of +* the routine npp_forcing_row); +* +* 3) if U[p] < U'[p] - eps, row upper bound U[p] can be active (this +* conclusion does not account other rows in the problem); +* +* 4) if U[p] >= U'[p] - eps, row upper bound U[p] cannot be active, so +* it is redundant and can be removed (replaced by +oo). */ + +int npp_analyze_row(NPP *npp, NPPROW *p) +{ /* perform general row analysis */ + NPPAIJ *aij; + int ret = 0x00; + double l, u, eps; + xassert(npp == npp); + /* compute implied lower bound L'[p]; see (3) */ + l = 0.0; + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + { if (aij->col->lb == -DBL_MAX) + { l = -DBL_MAX; + break; + } + l += aij->val * aij->col->lb; + } + else /* aij->val < 0.0 */ + { if (aij->col->ub == +DBL_MAX) + { l = -DBL_MAX; + break; + } + l += aij->val * aij->col->ub; + } + } + /* compute implied upper bound U'[p]; see (4) */ + u = 0.0; + for (aij = p->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + { if (aij->col->ub == +DBL_MAX) + { u = +DBL_MAX; + break; + } + u += aij->val * aij->col->ub; + } + else /* aij->val < 0.0 */ + { if (aij->col->lb == -DBL_MAX) + { u = +DBL_MAX; + break; + } + u += aij->val * aij->col->lb; + } + } + /* column bounds are assumed correct, so L'[p] <= U'[p] */ + /* check if row lower bound is consistent */ + if (p->lb != -DBL_MAX) + { eps = 1e-3 + 1e-6 * fabs(p->lb); + if (p->lb - eps > u) + { ret = 0x33; + goto done; + } + } + /* check if row upper bound is consistent */ + if (p->ub != +DBL_MAX) + { eps = 1e-3 + 1e-6 * fabs(p->ub); + if (p->ub + eps < l) + { ret = 0x33; + goto done; + } + } + /* check if row lower bound can be active/forcing */ + if (p->lb != -DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(p->lb); + if (p->lb - eps > l) + { if (p->lb + eps <= u) + ret |= 0x01; + else + ret |= 0x02; + } + } + /* check if row upper bound can be active/forcing */ + if (p->ub != +DBL_MAX) + { eps = 1e-9 + 1e-12 * fabs(p->ub); + if (p->ub + eps < u) + { /* check if the upper bound is forcing */ + if (p->ub - eps >= l) + ret |= 0x10; + else + ret |= 0x20; + } + } +done: return ret; +} + +/*********************************************************************** +* NAME +* +* npp_inactive_bound - remove row lower/upper inactive bound +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_inactive_bound(NPP *npp, NPPROW *p, int which); +* +* DESCRIPTION +* +* The routine npp_inactive_bound removes lower (if which = 0) or upper +* (if which = 1) bound of row p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], +* +* which (bound) is assumed to be redundant. +* +* PROBLEM TRANSFORMATION +* +* If which = 0, current lower bound L[p] of row p is assigned -oo. +* If which = 1, current upper bound U[p] of row p is assigned +oo. +* +* RECOVERING BASIC SOLUTION +* +* If in solution to the transformed problem row p is inactive +* constraint (GLP_BS), its status is not changed in solution to the +* original problem. Otherwise, status of row p in solution to the +* original problem is defined by its type before transformation and +* its status in solution to the transformed problem as follows: +* +* +---------------------+-------+---------------+---------------+ +* | Row | Flag | Row status in | Row status in | +* | type | which | transfmd soln | original soln | +* +---------------------+-------+---------------+---------------+ +* | sum >= L[p] | 0 | GLP_NF | GLP_NL | +* | sum <= U[p] | 1 | GLP_NF | GLP_NU | +* | L[p] <= sum <= U[p] | 0 | GLP_NU | GLP_NU | +* | L[p] <= sum <= U[p] | 1 | GLP_NL | GLP_NL | +* | sum = L[p] = U[p] | 0 | GLP_NU | GLP_NS | +* | sum = L[p] = U[p] | 1 | GLP_NL | GLP_NS | +* +---------------------+-------+---------------+---------------+ +* +* RECOVERING INTERIOR-POINT SOLUTION +* +* None needed. +* +* RECOVERING MIP SOLUTION +* +* None needed. */ + +struct inactive_bound +{ /* row inactive bound */ + int p; + /* row reference number */ + char stat; + /* row status (if active constraint) */ +}; + +static int rcv_inactive_bound(NPP *npp, void *info); + +void npp_inactive_bound(NPP *npp, NPPROW *p, int which) +{ /* remove row lower/upper inactive bound */ + struct inactive_bound *info; + if (npp->sol == GLP_SOL) + { /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_inactive_bound, sizeof(struct inactive_bound)); + info->p = p->i; + if (p->ub == +DBL_MAX) + info->stat = GLP_NL; + else if (p->lb == -DBL_MAX) + info->stat = GLP_NU; + else if (p->lb != p->ub) + info->stat = (char)(which == 0 ? GLP_NU : GLP_NL); + else + info->stat = GLP_NS; + } + /* remove row inactive bound */ + if (which == 0) + { xassert(p->lb != -DBL_MAX); + p->lb = -DBL_MAX; + } + else if (which == 1) + { xassert(p->ub != +DBL_MAX); + p->ub = +DBL_MAX; + } + else + xassert(which != which); + return; +} + +static int rcv_inactive_bound(NPP *npp, void *_info) +{ /* recover row status */ + struct inactive_bound *info = _info; + if (npp->sol != GLP_SOL) + { npp_error(); + return 1; + } + if (npp->r_stat[info->p] == GLP_BS) + npp->r_stat[info->p] = GLP_BS; + else + npp->r_stat[info->p] = info->stat; + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_implied_bounds - determine implied column bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_implied_bounds(NPP *npp, NPPROW *p); +* +* DESCRIPTION +* +* The routine npp_implied_bounds inspects general row (constraint) p: +* +* L[p] <= sum a[p,j] x[j] <= U[p], (1) +* +* l[j] <= x[j] <= u[j], (2) +* +* where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0, to compute +* implied bounds of columns (variables x[j]) in this row. +* +* The routine stores implied column bounds l'[j] and u'[j] in column +* descriptors (NPPCOL); it does not change current column bounds l[j] +* and u[j]. (Implied column bounds can be then used to strengthen the +* current column bounds; see the routines npp_implied_lower and +* npp_implied_upper). +* +* ALGORITHM +* +* Current column bounds (2) define implied lower and upper bounds of +* row (1) as follows: +* +* L'[p] = inf sum a[p,j] x[j] = +* j +* (3) +* = sum a[p,j] l[j] + sum a[p,j] u[j], +* j in Jp j in Jn +* +* U'[p] = sup sum a[p,j] x[j] = +* (4) +* = sum a[p,j] u[j] + sum a[p,j] l[j], +* j in Jp j in Jn +* +* Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) +* +* (Note that bounds of all columns in row p are assumed to be correct, +* so L'[p] <= U'[p].) +* +* If L[p] > L'[p] and/or U[p] < U'[p], the lower and/or upper bound of +* row (1) can be active, in which case such row defines implied bounds +* of its variables. +* +* Let x[k] be some variable having in row (1) coefficient a[p,k] != 0. +* Consider a case when row lower bound can be active (L[p] > L'[p]): +* +* sum a[p,j] x[j] >= L[p] ==> +* j +* +* sum a[p,j] x[j] + a[p,k] x[k] >= L[p] ==> +* j!=k +* (6) +* a[p,k] x[k] >= L[p] - sum a[p,j] x[j] ==> +* j!=k +* +* a[p,k] x[k] >= L[p,k], +* +* where +* +* L[p,k] = inf(L[p] - sum a[p,j] x[j]) = +* j!=k +* +* = L[p] - sup sum a[p,j] x[j] = (7) +* j!=k +* +* = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j]. +* j in Jp\{k} j in Jn\{k} +* +* Thus: +* +* x[k] >= l'[k] = L[p,k] / a[p,k], if a[p,k] > 0, (8) +* +* x[k] <= u'[k] = L[p,k] / a[p,k], if a[p,k] < 0. (9) +* +* where l'[k] and u'[k] are implied lower and upper bounds of variable +* x[k], resp. +* +* Now consider a similar case when row upper bound can be active +* (U[p] < U'[p]): +* +* sum a[p,j] x[j] <= U[p] ==> +* j +* +* sum a[p,j] x[j] + a[p,k] x[k] <= U[p] ==> +* j!=k +* (10) +* a[p,k] x[k] <= U[p] - sum a[p,j] x[j] ==> +* j!=k +* +* a[p,k] x[k] <= U[p,k], +* +* where: +* +* U[p,k] = sup(U[p] - sum a[p,j] x[j]) = +* j!=k +* +* = U[p] - inf sum a[p,j] x[j] = (11) +* j!=k +* +* = U[p] - sum a[p,j] l[j] - sum a[p,j] u[j]. +* j in Jp\{k} j in Jn\{k} +* +* Thus: +* +* x[k] <= u'[k] = U[p,k] / a[p,k], if a[p,k] > 0, (12) +* +* x[k] >= l'[k] = U[p,k] / a[p,k], if a[p,k] < 0. (13) +* +* Note that in formulae (8), (9), (12), and (13) coefficient a[p,k] +* must not be too small in magnitude relatively to other non-zero +* coefficients in row (1), i.e. the following condition must hold: +* +* |a[p,k]| >= eps * max(1, |a[p,j]|), (14) +* j +* +* where eps is a relative tolerance for constraint coefficients. +* Otherwise the implied column bounds can be numerical inreliable. For +* example, using formula (8) for the following inequality constraint: +* +* 1e-12 x1 - x2 - x3 >= 0, +* +* where x1 >= -1, x2, x3, >= 0, may lead to numerically unreliable +* conclusion that x1 >= 0. +* +* Using formulae (8), (9), (12), and (13) to compute implied bounds +* for one variable requires |J| operations, where J = {j: a[p,j] != 0}, +* because this needs computing L[p,k] and U[p,k]. Thus, computing +* implied bounds for all variables in row (1) would require |J|^2 +* operations, that is not a good technique. However, the total number +* of operations can be reduced to |J| as follows. +* +* Let a[p,k] > 0. Then from (7) and (11) we have: +* +* L[p,k] = L[p] - (U'[p] - a[p,k] u[k]) = +* +* = L[p] - U'[p] + a[p,k] u[k], +* +* U[p,k] = U[p] - (L'[p] - a[p,k] l[k]) = +* +* = U[p] - L'[p] + a[p,k] l[k], +* +* where L'[p] and U'[p] are implied row lower and upper bounds defined +* by formulae (3) and (4). Substituting these expressions into (8) and +* (12) gives: +* +* l'[k] = L[p,k] / a[p,k] = u[k] + (L[p] - U'[p]) / a[p,k], (15) +* +* u'[k] = U[p,k] / a[p,k] = l[k] + (U[p] - L'[p]) / a[p,k]. (16) +* +* Similarly, if a[p,k] < 0, according to (7) and (11) we have: +* +* L[p,k] = L[p] - (U'[p] - a[p,k] l[k]) = +* +* = L[p] - U'[p] + a[p,k] l[k], +* +* U[p,k] = U[p] - (L'[p] - a[p,k] u[k]) = +* +* = U[p] - L'[p] + a[p,k] u[k], +* +* and substituting these expressions into (8) and (12) gives: +* +* l'[k] = U[p,k] / a[p,k] = u[k] + (U[p] - L'[p]) / a[p,k], (17) +* +* u'[k] = L[p,k] / a[p,k] = l[k] + (L[p] - U'[p]) / a[p,k]. (18) +* +* Note that formulae (15)-(18) can be used only if L'[p] and U'[p] +* exist. However, if for some variable x[j] it happens that l[j] = -oo +* and/or u[j] = +oo, values of L'[p] (if a[p,j] > 0) and/or U'[p] (if +* a[p,j] < 0) are undefined. Consider, therefore, the most general +* situation, when some column bounds (2) may not exist. +* +* Let: +* +* J' = {j : (a[p,j] > 0 and l[j] = -oo) or +* (19) +* (a[p,j] < 0 and u[j] = +oo)}. +* +* Then (assuming that row upper bound U[p] can be active) the following +* three cases are possible: +* +* 1) |J'| = 0. In this case L'[p] exists, thus, for all variables x[j] +* in row (1) we can use formulae (16) and (17); +* +* 2) J' = {k}. In this case L'[p] = -oo, however, U[p,k] (11) exists, +* so for variable x[k] we can use formulae (12) and (13). Note that +* for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] < 0) +* or u'[j] = +oo (if a[p,j] > 0); +* +* 3) |J'| > 1. In this case for all variables x[j] in row [1] we have +* l'[j] = -oo (if a[p,j] < 0) or u'[j] = +oo (if a[p,j] > 0). +* +* Similarly, let: +* +* J'' = {j : (a[p,j] > 0 and u[j] = +oo) or +* (20) +* (a[p,j] < 0 and l[j] = -oo)}. +* +* Then (assuming that row lower bound L[p] can be active) the following +* three cases are possible: +* +* 1) |J''| = 0. In this case U'[p] exists, thus, for all variables x[j] +* in row (1) we can use formulae (15) and (18); +* +* 2) J'' = {k}. In this case U'[p] = +oo, however, L[p,k] (7) exists, +* so for variable x[k] we can use formulae (8) and (9). Note that +* for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] > 0) +* or u'[j] = +oo (if a[p,j] < 0); +* +* 3) |J''| > 1. In this case for all variables x[j] in row (1) we have +* l'[j] = -oo (if a[p,j] > 0) or u'[j] = +oo (if a[p,j] < 0). */ + +void npp_implied_bounds(NPP *npp, NPPROW *p) +{ NPPAIJ *apj, *apk; + double big, eps, temp; + xassert(npp == npp); + /* initialize implied bounds for all variables and determine + maximal magnitude of row coefficients a[p,j] */ + big = 1.0; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { apj->col->ll.ll = -DBL_MAX, apj->col->uu.uu = +DBL_MAX; + if (big < fabs(apj->val)) big = fabs(apj->val); + } + eps = 1e-6 * big; + /* process row lower bound (assuming that it can be active) */ + if (p->lb != -DBL_MAX) + { apk = NULL; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val > 0.0 && apj->col->ub == +DBL_MAX || + apj->val < 0.0 && apj->col->lb == -DBL_MAX) + { if (apk == NULL) + apk = apj; + else + goto skip1; + } + } + /* if a[p,k] = NULL then |J'| = 0 else J' = { k } */ + temp = p->lb; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj == apk) + /* skip a[p,k] */; + else if (apj->val > 0.0) + temp -= apj->val * apj->col->ub; + else /* apj->val < 0.0 */ + temp -= apj->val * apj->col->lb; + } + /* compute column implied bounds */ + if (apk == NULL) + { /* temp = L[p] - U'[p] */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val >= +eps) + { /* l'[j] := u[j] + (L[p] - U'[p]) / a[p,j] */ + apj->col->ll.ll = apj->col->ub + temp / apj->val; + } + else if (apj->val <= -eps) + { /* u'[j] := l[j] + (L[p] - U'[p]) / a[p,j] */ + apj->col->uu.uu = apj->col->lb + temp / apj->val; + } + } + } + else + { /* temp = L[p,k] */ + if (apk->val >= +eps) + { /* l'[k] := L[p,k] / a[p,k] */ + apk->col->ll.ll = temp / apk->val; + } + else if (apk->val <= -eps) + { /* u'[k] := L[p,k] / a[p,k] */ + apk->col->uu.uu = temp / apk->val; + } + } +skip1: ; + } + /* process row upper bound (assuming that it can be active) */ + if (p->ub != +DBL_MAX) + { apk = NULL; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val > 0.0 && apj->col->lb == -DBL_MAX || + apj->val < 0.0 && apj->col->ub == +DBL_MAX) + { if (apk == NULL) + apk = apj; + else + goto skip2; + } + } + /* if a[p,k] = NULL then |J''| = 0 else J'' = { k } */ + temp = p->ub; + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj == apk) + /* skip a[p,k] */; + else if (apj->val > 0.0) + temp -= apj->val * apj->col->lb; + else /* apj->val < 0.0 */ + temp -= apj->val * apj->col->ub; + } + /* compute column implied bounds */ + if (apk == NULL) + { /* temp = U[p] - L'[p] */ + for (apj = p->ptr; apj != NULL; apj = apj->r_next) + { if (apj->val >= +eps) + { /* u'[j] := l[j] + (U[p] - L'[p]) / a[p,j] */ + apj->col->uu.uu = apj->col->lb + temp / apj->val; + } + else if (apj->val <= -eps) + { /* l'[j] := u[j] + (U[p] - L'[p]) / a[p,j] */ + apj->col->ll.ll = apj->col->ub + temp / apj->val; + } + } + } + else + { /* temp = U[p,k] */ + if (apk->val >= +eps) + { /* u'[k] := U[p,k] / a[p,k] */ + apk->col->uu.uu = temp / apk->val; + } + else if (apk->val <= -eps) + { /* l'[k] := U[p,k] / a[p,k] */ + apk->col->ll.ll = temp / apk->val; + } + } +skip2: ; + } + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp4.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp4.c new file mode 100644 index 000000000..d7dd0e868 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp4.c @@ -0,0 +1,1414 @@ +/* npp4.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* npp_binarize_prob - binarize MIP problem +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_binarize_prob(NPP *npp); +* +* DESCRIPTION +* +* The routine npp_binarize_prob replaces in the original MIP problem +* every integer variable: +* +* l[q] <= x[q] <= u[q], (1) +* +* where l[q] < u[q], by an equivalent sum of binary variables. +* +* RETURNS +* +* The routine returns the number of integer variables for which the +* transformation failed, because u[q] - l[q] > d_max. +* +* PROBLEM TRANSFORMATION +* +* If variable x[q] has non-zero lower bound, it is first processed +* with the routine npp_lbnd_col. Thus, we can assume that: +* +* 0 <= x[q] <= u[q]. (2) +* +* If u[q] = 1, variable x[q] is already binary, so further processing +* is not needed. Let, therefore, that 2 <= u[q] <= d_max, and n be a +* smallest integer such that u[q] <= 2^n - 1 (n >= 2, since u[q] >= 2). +* Then variable x[q] can be replaced by the following sum: +* +* n-1 +* x[q] = sum 2^k x[k], (3) +* k=0 +* +* where x[k] are binary columns (variables). If u[q] < 2^n - 1, the +* following additional inequality constraint must be also included in +* the transformed problem: +* +* n-1 +* sum 2^k x[k] <= u[q]. (4) +* k=0 +* +* Note: Assuming that in the transformed problem x[q] becomes binary +* variable x[0], this transformation causes new n-1 binary variables +* to appear. +* +* Substituting x[q] from (3) to the objective row gives: +* +* z = sum c[j] x[j] + c[0] = +* j +* +* = sum c[j] x[j] + c[q] x[q] + c[0] = +* j!=q +* n-1 +* = sum c[j] x[j] + c[q] sum 2^k x[k] + c[0] = +* j!=q k=0 +* n-1 +* = sum c[j] x[j] + sum c[k] x[k] + c[0], +* j!=q k=0 +* +* where: +* +* c[k] = 2^k c[q], k = 0, ..., n-1. (5) +* +* And substituting x[q] from (3) to i-th constraint row i gives: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* n-1 +* L[i] <= sum a[i,j] x[j] + a[i,q] sum 2^k x[k] <= U[i] ==> +* j!=q k=0 +* n-1 +* L[i] <= sum a[i,j] x[j] + sum a[i,k] x[k] <= U[i], +* j!=q k=0 +* +* where: +* +* a[i,k] = 2^k a[i,q], k = 0, ..., n-1. (6) +* +* RECOVERING SOLUTION +* +* Value of variable x[q] is computed with formula (3). */ + +struct binarize +{ int q; + /* column reference number for x[q] = x[0] */ + int j; + /* column reference number for x[1]; x[2] has reference number + j+1, x[3] - j+2, etc. */ + int n; + /* total number of binary variables, n >= 2 */ +}; + +static int rcv_binarize_prob(NPP *npp, void *info); + +int npp_binarize_prob(NPP *npp) +{ /* binarize MIP problem */ + struct binarize *info; + NPPROW *row; + NPPCOL *col, *bin; + NPPAIJ *aij; + int u, n, k, temp, nfails, nvars, nbins, nrows; + /* new variables will be added to the end of the column list, so + we go from the end to beginning of the column list */ + nfails = nvars = nbins = nrows = 0; + for (col = npp->c_tail; col != NULL; col = col->prev) + { /* skip continuous variable */ + if (!col->is_int) continue; + /* skip fixed variable */ + if (col->lb == col->ub) continue; + /* skip binary variable */ + if (col->lb == 0.0 && col->ub == 1.0) continue; + /* check if the transformation is applicable */ + if (col->lb < -1e6 || col->ub > +1e6 || + col->ub - col->lb > 4095.0) + { /* unfortunately, not */ + nfails++; + continue; + } + /* process integer non-binary variable x[q] */ + nvars++; + /* make x[q] non-negative, if its lower bound is non-zero */ + if (col->lb != 0.0) + npp_lbnd_col(npp, col); + /* now 0 <= x[q] <= u[q] */ + xassert(col->lb == 0.0); + u = (int)col->ub; + xassert(col->ub == (double)u); + /* if x[q] is binary, further processing is not needed */ + if (u == 1) continue; + /* determine smallest n such that u <= 2^n - 1 (thus, n is the + number of binary variables needed) */ + n = 2, temp = 4; + while (u >= temp) + n++, temp += temp; + nbins += n; + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_binarize_prob, sizeof(struct binarize)); + info->q = col->j; + info->j = 0; /* will be set below */ + info->n = n; + /* if u < 2^n - 1, we need one additional row for (4) */ + if (u < temp - 1) + { row = npp_add_row(npp), nrows++; + row->lb = -DBL_MAX, row->ub = u; + } + else + row = NULL; + /* in the transformed problem variable x[q] becomes binary + variable x[0], so its objective and constraint coefficients + are not changed */ + col->ub = 1.0; + /* include x[0] into constraint (4) */ + if (row != NULL) + npp_add_aij(npp, row, col, 1.0); + /* add other binary variables x[1], ..., x[n-1] */ + for (k = 1, temp = 2; k < n; k++, temp += temp) + { /* add new binary variable x[k] */ + bin = npp_add_col(npp); + bin->is_int = 1; + bin->lb = 0.0, bin->ub = 1.0; + bin->coef = (double)temp * col->coef; + /* store column reference number for x[1] */ + if (info->j == 0) + info->j = bin->j; + else + xassert(info->j + (k-1) == bin->j); + /* duplicate constraint coefficients for x[k]; this also + automatically includes x[k] into constraint (4) */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_add_aij(npp, aij->row, bin, (double)temp * aij->val); + } + } + if (nvars > 0) + xprintf("%d integer variable(s) were replaced by %d binary one" + "s\n", nvars, nbins); + if (nrows > 0) + xprintf("%d row(s) were added due to binarization\n", nrows); + if (nfails > 0) + xprintf("Binarization failed for %d integer variable(s)\n", + nfails); + return nfails; +} + +static int rcv_binarize_prob(NPP *npp, void *_info) +{ /* recovery binarized variable */ + struct binarize *info = _info; + int k, temp; + double sum; + /* compute value of x[q]; see formula (3) */ + sum = npp->c_value[info->q]; + for (k = 1, temp = 2; k < info->n; k++, temp += temp) + sum += (double)temp * npp->c_value[info->j + (k-1)]; + npp->c_value[info->q] = sum; + return 0; +} + +/**********************************************************************/ + +struct elem +{ /* linear form element a[j] x[j] */ + double aj; + /* non-zero coefficient value */ + NPPCOL *xj; + /* pointer to variable (column) */ + struct elem *next; + /* pointer to another term */ +}; + +static struct elem *copy_form(NPP *npp, NPPROW *row, double s) +{ /* copy linear form */ + NPPAIJ *aij; + struct elem *ptr, *e; + ptr = NULL; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { e = dmp_get_atom(npp->pool, sizeof(struct elem)); + e->aj = s * aij->val; + e->xj = aij->col; + e->next = ptr; + ptr = e; + } + return ptr; +} + +static void drop_form(NPP *npp, struct elem *ptr) +{ /* drop linear form */ + struct elem *e; + while (ptr != NULL) + { e = ptr; + ptr = e->next; + dmp_free_atom(npp->pool, e, sizeof(struct elem)); + } + return; +} + +/*********************************************************************** +* NAME +* +* npp_is_packing - test if constraint is packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_packing(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is packing inequality (see below), +* the routine npp_is_packing returns non-zero. Otherwise, it returns +* zero. +* +* PACKING INEQUALITIES +* +* In canonical format the packing inequality is the following: +* +* sum x[j] <= 1, (1) +* j in J +* +* where all variables x[j] are binary. This inequality expresses the +* condition that in any integer feasible solution at most one variable +* from set J can take non-zero (unity) value while other variables +* must be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because +* if J is empty or |J| = 1, the inequality (1) is redundant. +* +* In general case the packing inequality may include original variables +* x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] <= 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] gives the packing inequality in generalized format: +* +* sum x[j] - sum x[j] <= 1 - |Jn|. (3) +* j in Jp j in Jn */ + +int npp_is_packing(NPP *npp, NPPROW *row) +{ /* test if constraint is packing inequality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (!(row->lb == -DBL_MAX && row->ub != +DBL_MAX)) + return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->ub != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_hidden_packing - identify hidden packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_hidden_packing(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_hidden_packing processes specified inequality +* constraint, which includes only binary variables, and the number of +* the variables is not less than two. If the original inequality is +* equivalent to a packing inequality, the routine replaces it by this +* equivalent inequality. If the original constraint is double-sided +* inequality, it is replaced by a pair of single-sided inequalities, +* if necessary. +* +* RETURNS +* +* If the original inequality constraint was replaced by equivalent +* packing inequality, the routine npp_hidden_packing returns non-zero. +* Otherwise, it returns zero. +* +* PROBLEM TRANSFORMATION +* +* Consider an inequality constraint: +* +* sum a[j] x[j] <= b, (1) +* j in J +* +* where all variables x[j] are binary, and |J| >= 2. (In case of '>=' +* inequality it can be transformed to '<=' format by multiplying both +* its sides by -1.) +* +* Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution +* x[j] = 1 - x~[j] for all j in Jn, we have: +* +* sum a[j] x[j] <= b ==> +* j in J +* +* sum a[j] x[j] + sum a[j] x[j] <= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] + sum a[j] (1 - x~[j]) <= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] - sum a[j] x~[j] <= b - sum a[j]. +* j in Jp j in Jn j in Jn +* +* Thus, meaning the transformation above, we can assume that in +* inequality (1) all coefficients a[j] are positive. Moreover, we can +* assume that a[j] <= b. In fact, let a[j] > b; then the following +* three cases are possible: +* +* 1) b < 0. In this case inequality (1) is infeasible, so the problem +* has no feasible solution (see the routine npp_analyze_row); +* +* 2) b = 0. In this case inequality (1) is a forcing inequality on its +* upper bound (see the routine npp_forcing row), from which it +* follows that all variables x[j] should be fixed at zero; +* +* 3) b > 0. In this case inequality (1) defines an implied zero upper +* bound for variable x[j] (see the routine npp_implied_bounds), from +* which it follows that x[j] should be fixed at zero. +* +* It is assumed that all three cases listed above have been recognized +* by the routine npp_process_prob, which performs basic MIP processing +* prior to a call the routine npp_hidden_packing. So, if one of these +* cases occurs, we should just skip processing such constraint. +* +* Thus, let 0 < a[j] <= b. Then it is obvious that constraint (1) is +* equivalent to packing inquality only if: +* +* a[j] + a[k] > b + eps (2) +* +* for all j, k in J, j != k, where eps is an absolute tolerance for +* row (linear form) value. Checking the condition (2) for all j and k, +* j != k, requires time O(|J|^2). However, this time can be reduced to +* O(|J|), if use minimal a[j] and a[k], in which case it is sufficient +* to check the condition (2) only once. +* +* Once the original inequality (1) is replaced by equivalent packing +* inequality, we need to perform back substitution x~[j] = 1 - x[j] for +* all j in Jn (see above). +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int hidden_packing(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] <= b; + 0 - specified row is NOT hidden packing inequality; + 1 - specified row is packing inequality; + 2 - specified row is hidden packing inequality. */ + struct elem *e, *ej, *ek; + int neg; + double b = *_b, eps; + xassert(npp == npp); + /* a[j] must be non-zero, x[j] must be binary, for all j in J */ + for (e = ptr; e != NULL; e = e->next) + { xassert(e->aj != 0.0); + xassert(e->xj->is_int); + xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); + } + /* check if the specified inequality constraint already has the + form of packing inequality */ + neg = 0; /* neg is |Jn| */ + for (e = ptr; e != NULL; e = e->next) + { if (e->aj == +1.0) + ; + else if (e->aj == -1.0) + neg++; + else + break; + } + if (e == NULL) + { /* all coefficients a[j] are +1 or -1; check rhs b */ + if (b == (double)(1 - neg)) + { /* it is packing inequality; no processing is needed */ + return 1; + } + } + /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] + positive; the result is a~[j] = |a[j]| and new rhs b */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0) b -= e->aj; + /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ + /* if a[j] > b, skip processing--this case must not appear */ + for (e = ptr; e != NULL; e = e->next) + if (fabs(e->aj) > b) return 0; + /* now 0 < a[j] <= b for all j in J */ + /* find two minimal coefficients a[j] and a[k], j != k */ + ej = NULL; + for (e = ptr; e != NULL; e = e->next) + if (ej == NULL || fabs(ej->aj) > fabs(e->aj)) ej = e; + xassert(ej != NULL); + ek = NULL; + for (e = ptr; e != NULL; e = e->next) + if (e != ej) + if (ek == NULL || fabs(ek->aj) > fabs(e->aj)) ek = e; + xassert(ek != NULL); + /* the specified constraint is equivalent to packing inequality + iff a[j] + a[k] > b + eps */ + eps = 1e-3 + 1e-6 * fabs(b); + if (fabs(ej->aj) + fabs(ek->aj) <= b + eps) return 0; + /* perform back substitution x~[j] = 1 - x[j] and construct the + final equivalent packing inequality in generalized format */ + b = 1.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + e->aj = +1.0; + else /* e->aj < 0.0 */ + e->aj = -1.0, b -= 1.0; + } + *_b = b; + return 2; +} + +int npp_hidden_packing(NPP *npp, NPPROW *row) +{ /* identify hidden packing inequality */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, ret, count = 0; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; + ptr = copy_form(npp, row, +1.0); + b = + row->ub; + } + else + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; + ptr = copy_form(npp, row, -1.0); + b = - row->lb; + } + /* now the inequality has the form "sum a[j] x[j] <= b" */ + ret = hidden_packing(npp, ptr, &b); + xassert(0 <= ret && ret <= 2); + if (kase == 1 && ret == 1 || ret == 2) + { /* the original inequality has been identified as hidden + packing inequality */ + count++; +#ifdef GLP_DEBUG + xprintf("Original constraint:\n"); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xprintf(" %+g x%d", aij->val, aij->col->j); + if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); + if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); + xprintf("\n"); + xprintf("Equivalent packing inequality:\n"); + for (e = ptr; e != NULL; e = e->next) + xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); + xprintf(", <= %g\n", b); +#endif + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + else + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = -DBL_MAX, row->ub = b; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing lower bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_implied_packing - identify implied packing inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_implied_packing(NPP *npp, NPPROW *row, int which, +* NPPCOL *var[], char set[]); +* +* DESCRIPTION +* +* The routine npp_implied_packing processes specified row (constraint) +* of general format: +* +* L <= sum a[j] x[j] <= U. (1) +* j +* +* If which = 0, only lower bound L, which must exist, is considered, +* while upper bound U is ignored. Similarly, if which = 1, only upper +* bound U, which must exist, is considered, while lower bound L is +* ignored. Thus, if the specified row is a double-sided inequality or +* equality constraint, this routine should be called twice for both +* lower and upper bounds. +* +* The routine npp_implied_packing attempts to find a non-trivial (i.e. +* having not less than two binary variables) packing inequality: +* +* sum x[j] - sum x[j] <= 1 - |Jn|, (2) +* j in Jp j in Jn +* +* which is relaxation of the constraint (1) in the sense that any +* solution satisfying to that constraint also satisfies to the packing +* inequality (2). If such relaxation exists, the routine stores +* pointers to descriptors of corresponding binary variables and their +* flags, resp., to locations var[1], var[2], ..., var[len] and set[1], +* set[2], ..., set[len], where set[j] = 0 means that j in Jp and +* set[j] = 1 means that j in Jn. +* +* RETURNS +* +* The routine npp_implied_packing returns len, which is the total +* number of binary variables in the packing inequality found, len >= 2. +* However, if the relaxation does not exist, the routine returns zero. +* +* ALGORITHM +* +* If which = 0, the constraint coefficients (1) are multiplied by -1 +* and b is assigned -L; if which = 1, the constraint coefficients (1) +* are not changed and b is assigned +U. In both cases the specified +* constraint gets the following format: +* +* sum a[j] x[j] <= b. (3) +* j +* +* (Note that (3) is a relaxation of (1), because one of bounds L or U +* is ignored.) +* +* Let J be set of binary variables, Kp be set of non-binary (integer +* or continuous) variables with a[j] > 0, and Kn be set of non-binary +* variables with a[j] < 0. Then the inequality (3) can be written as +* follows: +* +* sum a[j] x[j] <= b - sum a[j] x[j] - sum a[j] x[j]. (4) +* j in J j in Kp j in Kn +* +* To get rid of non-binary variables we can replace the inequality (4) +* by the following relaxed inequality: +* +* sum a[j] x[j] <= b~, (5) +* j in J +* +* where: +* +* b~ = sup(b - sum a[j] x[j] - sum a[j] x[j]) = +* j in Kp j in Kn +* +* = b - inf sum a[j] x[j] - inf sum a[j] x[j] = (6) +* j in Kp j in Kn +* +* = b - sum a[j] l[j] - sum a[j] u[j]. +* j in Kp j in Kn +* +* Note that if lower bound l[j] (if j in Kp) or upper bound u[j] +* (if j in Kn) of some non-binary variable x[j] does not exist, then +* formally b = +oo, in which case further analysis is not performed. +* +* Let Bp = {j in J: a[j] > 0}, Bn = {j in J: a[j] < 0}. To make all +* the inequality coefficients in (5) positive, we replace all x[j] in +* Bn by their complementaries, substituting x[j] = 1 - x~[j] for all +* j in Bn, that gives: +* +* sum a[j] x[j] - sum a[j] x~[j] <= b~ - sum a[j]. (7) +* j in Bp j in Bn j in Bn +* +* This inequality is a relaxation of the original constraint (1), and +* it is a binary knapsack inequality. Writing it in the standard format +* we have: +* +* sum alfa[j] z[j] <= beta, (8) +* j in J +* +* where: +* ( + a[j], if j in Bp, +* alfa[j] = < (9) +* ( - a[j], if j in Bn, +* +* ( x[j], if j in Bp, +* z[j] = < (10) +* ( 1 - x[j], if j in Bn, +* +* beta = b~ - sum a[j]. (11) +* j in Bn +* +* In the inequality (8) all coefficients are positive, therefore, the +* packing relaxation to be found for this inequality is the following: +* +* sum z[j] <= 1. (12) +* j in P +* +* It is obvious that set P within J, which we would like to find, must +* satisfy to the following condition: +* +* alfa[j] + alfa[k] > beta + eps for all j, k in P, j != k, (13) +* +* where eps is an absolute tolerance for value of the linear form. +* Thus, it is natural to take P = {j: alpha[j] > (beta + eps) / 2}. +* Moreover, if in the equality (8) there exist coefficients alfa[k], +* for which alfa[k] <= (beta + eps) / 2, but which, nevertheless, +* satisfies to the condition (13) for all j in P, *one* corresponding +* variable z[k] (having, for example, maximal coefficient alfa[k]) can +* be included in set P, that allows increasing the number of binary +* variables in (12) by one. +* +* Once the set P has been built, for the inequality (12) we need to +* perform back substitution according to (10) in order to express it +* through the original binary variables. As the result of such back +* substitution the relaxed packing inequality get its final format (2), +* where Jp = J intersect Bp, and Jn = J intersect Bn. */ + +int npp_implied_packing(NPP *npp, NPPROW *row, int which, + NPPCOL *var[], char set[]) +{ struct elem *ptr, *e, *i, *k; + int len = 0; + double b, eps; + /* build inequality (3) */ + if (which == 0) + { ptr = copy_form(npp, row, -1.0); + xassert(row->lb != -DBL_MAX); + b = - row->lb; + } + else if (which == 1) + { ptr = copy_form(npp, row, +1.0); + xassert(row->ub != +DBL_MAX); + b = + row->ub; + } + /* remove non-binary variables to build relaxed inequality (5); + compute its right-hand side b~ with formula (6) */ + for (e = ptr; e != NULL; e = e->next) + { if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) + { /* x[j] is non-binary variable */ + if (e->aj > 0.0) + { if (e->xj->lb == -DBL_MAX) goto done; + b -= e->aj * e->xj->lb; + } + else /* e->aj < 0.0 */ + { if (e->xj->ub == +DBL_MAX) goto done; + b -= e->aj * e->xj->ub; + } + /* a[j] = 0 means that variable x[j] is removed */ + e->aj = 0.0; + } + } + /* substitute x[j] = 1 - x~[j] to build knapsack inequality (8); + compute its right-hand side beta with formula (11) */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0.0) b -= e->aj; + /* if beta is close to zero, the knapsack inequality is either + infeasible or forcing inequality; this must never happen, so + we skip further analysis */ + if (b < 1e-3) goto done; + /* build set P as well as sets Jp and Jn, and determine x[k] as + explained above in comments to the routine */ + eps = 1e-3 + 1e-6 * b; + i = k = NULL; + for (e = ptr; e != NULL; e = e->next) + { /* note that alfa[j] = |a[j]| */ + if (fabs(e->aj) > 0.5 * (b + eps)) + { /* alfa[j] > (b + eps) / 2; include x[j] in set P, i.e. in + set Jp or Jn */ + var[++len] = e->xj; + set[len] = (char)(e->aj > 0.0 ? 0 : 1); + /* alfa[i] = min alfa[j] over all j included in set P */ + if (i == NULL || fabs(i->aj) > fabs(e->aj)) i = e; + } + else if (fabs(e->aj) >= 1e-3) + { /* alfa[k] = max alfa[j] over all j not included in set P; + we skip coefficient a[j] if it is close to zero to avoid + numerically unreliable results */ + if (k == NULL || fabs(k->aj) < fabs(e->aj)) k = e; + } + } + /* if alfa[k] satisfies to condition (13) for all j in P, include + x[k] in P */ + if (i != NULL && k != NULL && fabs(i->aj) + fabs(k->aj) > b + eps) + { var[++len] = k->xj; + set[len] = (char)(k->aj > 0.0 ? 0 : 1); + } + /* trivial packing inequality being redundant must never appear, + so we just ignore it */ + if (len < 2) len = 0; +done: drop_form(npp, ptr); + return len; +} + +/*********************************************************************** +* NAME +* +* npp_is_covering - test if constraint is covering inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_covering(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is covering inequality (see below), +* the routine npp_is_covering returns non-zero. Otherwise, it returns +* zero. +* +* COVERING INEQUALITIES +* +* In canonical format the covering inequality is the following: +* +* sum x[j] >= 1, (1) +* j in J +* +* where all variables x[j] are binary. This inequality expresses the +* condition that in any integer feasible solution variables in set J +* cannot be all equal to zero at the same time, i.e. at least one +* variable must take non-zero (unity) value. W.l.o.g. it is assumed +* that |J| >= 2, because if J is empty, the inequality (1) is +* infeasible, and if |J| = 1, the inequality (1) is a forcing row. +* +* In general case the covering inequality may include original +* variables x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] >= 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] gives the packing inequality in generalized format: +* +* sum x[j] - sum x[j] >= 1 - |Jn|. (3) +* j in Jp j in Jn +* +* (May note that the inequality (3) cuts off infeasible solutions, +* where x[j] = 0 for all j in Jp and x[j] = 1 for all j in Jn.) +* +* NOTE: If |J| = 2, the inequality (3) is equivalent to packing +* inequality (see the routine npp_is_packing). */ + +int npp_is_covering(NPP *npp, NPPROW *row) +{ /* test if constraint is covering inequality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (!(row->lb != -DBL_MAX && row->ub == +DBL_MAX)) + return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->lb != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_hidden_covering - identify hidden covering inequality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_hidden_covering(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_hidden_covering processes specified inequality +* constraint, which includes only binary variables, and the number of +* the variables is not less than three. If the original inequality is +* equivalent to a covering inequality (see below), the routine +* replaces it by the equivalent inequality. If the original constraint +* is double-sided inequality, it is replaced by a pair of single-sided +* inequalities, if necessary. +* +* RETURNS +* +* If the original inequality constraint was replaced by equivalent +* covering inequality, the routine npp_hidden_covering returns +* non-zero. Otherwise, it returns zero. +* +* PROBLEM TRANSFORMATION +* +* Consider an inequality constraint: +* +* sum a[j] x[j] >= b, (1) +* j in J +* +* where all variables x[j] are binary, and |J| >= 3. (In case of '<=' +* inequality it can be transformed to '>=' format by multiplying both +* its sides by -1.) +* +* Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution +* x[j] = 1 - x~[j] for all j in Jn, we have: +* +* sum a[j] x[j] >= b ==> +* j in J +* +* sum a[j] x[j] + sum a[j] x[j] >= b ==> +* j in Jp j in Jn +* +* sum a[j] x[j] + sum a[j] (1 - x~[j]) >= b ==> +* j in Jp j in Jn +* +* sum m a[j] x[j] - sum a[j] x~[j] >= b - sum a[j]. +* j in Jp j in Jn j in Jn +* +* Thus, meaning the transformation above, we can assume that in +* inequality (1) all coefficients a[j] are positive. Moreover, we can +* assume that b > 0, because otherwise the inequality (1) would be +* redundant (see the routine npp_analyze_row). It is then obvious that +* constraint (1) is equivalent to covering inequality only if: +* +* a[j] >= b, (2) +* +* for all j in J. +* +* Once the original inequality (1) is replaced by equivalent covering +* inequality, we need to perform back substitution x~[j] = 1 - x[j] for +* all j in Jn (see above). +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int hidden_covering(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] >= b; + 0 - specified row is NOT hidden covering inequality; + 1 - specified row is covering inequality; + 2 - specified row is hidden covering inequality. */ + struct elem *e; + int neg; + double b = *_b, eps; + xassert(npp == npp); + /* a[j] must be non-zero, x[j] must be binary, for all j in J */ + for (e = ptr; e != NULL; e = e->next) + { xassert(e->aj != 0.0); + xassert(e->xj->is_int); + xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); + } + /* check if the specified inequality constraint already has the + form of covering inequality */ + neg = 0; /* neg is |Jn| */ + for (e = ptr; e != NULL; e = e->next) + { if (e->aj == +1.0) + ; + else if (e->aj == -1.0) + neg++; + else + break; + } + if (e == NULL) + { /* all coefficients a[j] are +1 or -1; check rhs b */ + if (b == (double)(1 - neg)) + { /* it is covering inequality; no processing is needed */ + return 1; + } + } + /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] + positive; the result is a~[j] = |a[j]| and new rhs b */ + for (e = ptr; e != NULL; e = e->next) + if (e->aj < 0) b -= e->aj; + /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ + /* if b <= 0, skip processing--this case must not appear */ + if (b < 1e-3) return 0; + /* now a[j] > 0 for all j in J, and b > 0 */ + /* the specified constraint is equivalent to covering inequality + iff a[j] >= b for all j in J */ + eps = 1e-9 + 1e-12 * fabs(b); + for (e = ptr; e != NULL; e = e->next) + if (fabs(e->aj) < b - eps) return 0; + /* perform back substitution x~[j] = 1 - x[j] and construct the + final equivalent covering inequality in generalized format */ + b = 1.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + e->aj = +1.0; + else /* e->aj < 0.0 */ + e->aj = -1.0, b -= 1.0; + } + *_b = b; + return 2; +} + +int npp_hidden_covering(NPP *npp, NPPROW *row) +{ /* identify hidden covering inequality */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, ret, count = 0; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; + ptr = copy_form(npp, row, +1.0); + b = + row->lb; + } + else + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; + ptr = copy_form(npp, row, -1.0); + b = - row->ub; + } + /* now the inequality has the form "sum a[j] x[j] >= b" */ + ret = hidden_covering(npp, ptr, &b); + xassert(0 <= ret && ret <= 2); + if (kase == 1 && ret == 1 || ret == 2) + { /* the original inequality has been identified as hidden + covering inequality */ + count++; +#ifdef GLP_DEBUG + xprintf("Original constraint:\n"); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + xprintf(" %+g x%d", aij->val, aij->col->j); + if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); + if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); + xprintf("\n"); + xprintf("Equivalent covering inequality:\n"); + for (e = ptr; e != NULL; e = e->next) + xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); + xprintf(", >= %g\n", b); +#endif + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + else + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = b, row->ub = +DBL_MAX; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing upper bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_is_partitioning - test if constraint is partitioning equality +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_is_partitioning(NPP *npp, NPPROW *row); +* +* RETURNS +* +* If the specified row (constraint) is partitioning equality (see +* below), the routine npp_is_partitioning returns non-zero. Otherwise, +* it returns zero. +* +* PARTITIONING EQUALITIES +* +* In canonical format the partitioning equality is the following: +* +* sum x[j] = 1, (1) +* j in J +* +* where all variables x[j] are binary. This equality expresses the +* condition that in any integer feasible solution exactly one variable +* in set J must take non-zero (unity) value while other variables must +* be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because if +* J is empty, the inequality (1) is infeasible, and if |J| = 1, the +* inequality (1) is a fixing row. +* +* In general case the partitioning equality may include original +* variables x[j] as well as their complements x~[j]: +* +* sum x[j] + sum x~[j] = 1, (2) +* j in Jp j in Jn +* +* where Jp and Jn are not intersected. Therefore, using substitution +* x~[j] = 1 - x[j] leads to the partitioning equality in generalized +* format: +* +* sum x[j] - sum x[j] = 1 - |Jn|. (3) +* j in Jp j in Jn */ + +int npp_is_partitioning(NPP *npp, NPPROW *row) +{ /* test if constraint is partitioning equality */ + NPPCOL *col; + NPPAIJ *aij; + int b; + xassert(npp == npp); + if (row->lb != row->ub) return 0; + b = 1; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; + if (aij->val == +1.0) + ; + else if (aij->val == -1.0) + b--; + else + return 0; + } + if (row->lb != (double)b) return 0; + return 1; +} + +/*********************************************************************** +* NAME +* +* npp_reduce_ineq_coef - reduce inequality constraint coefficients +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); +* +* DESCRIPTION +* +* The routine npp_reduce_ineq_coef processes specified inequality +* constraint attempting to replace it by an equivalent constraint, +* where magnitude of coefficients at binary variables is smaller than +* in the original constraint. If the inequality is double-sided, it is +* replaced by a pair of single-sided inequalities, if necessary. +* +* RETURNS +* +* The routine npp_reduce_ineq_coef returns the number of coefficients +* reduced. +* +* BACKGROUND +* +* Consider an inequality constraint: +* +* sum a[j] x[j] >= b. (1) +* j in J +* +* (In case of '<=' inequality it can be transformed to '>=' format by +* multiplying both its sides by -1.) Let x[k] be a binary variable; +* other variables can be integer as well as continuous. We can write +* constraint (1) as follows: +* +* a[k] x[k] + t[k] >= b, (2) +* +* where: +* +* t[k] = sum a[j] x[j]. (3) +* j in J\{k} +* +* Since x[k] is binary, constraint (2) is equivalent to disjunction of +* the following two constraints: +* +* x[k] = 0, t[k] >= b (4) +* +* OR +* +* x[k] = 1, t[k] >= b - a[k]. (5) +* +* Let also that for the partial sum t[k] be known some its implied +* lower bound inf t[k]. +* +* Case a[k] > 0. Let inf t[k] < b, since otherwise both constraints +* (4) and (5) and therefore constraint (2) are redundant. +* If inf t[k] > b - a[k], only constraint (5) is redundant, in which +* case it can be replaced with the following redundant and therefore +* equivalent constraint: +* +* t[k] >= b - a'[k] = inf t[k], (6) +* +* where: +* +* a'[k] = b - inf t[k]. (7) +* +* Thus, the original constraint (2) is equivalent to the following +* constraint with coefficient at variable x[k] changed: +* +* a'[k] x[k] + t[k] >= b. (8) +* +* From inf t[k] < b it follows that a'[k] > 0, i.e. the coefficient +* at x[k] keeps its sign. And from inf t[k] > b - a[k] it follows that +* a'[k] < a[k], i.e. the coefficient reduces in magnitude. +* +* Case a[k] < 0. Let inf t[k] < b - a[k], since otherwise both +* constraints (4) and (5) and therefore constraint (2) are redundant. +* If inf t[k] > b, only constraint (4) is redundant, in which case it +* can be replaced with the following redundant and therefore equivalent +* constraint: +* +* t[k] >= b' = inf t[k]. (9) +* +* Rewriting constraint (5) as follows: +* +* t[k] >= b - a[k] = b' - a'[k], (10) +* +* where: +* +* a'[k] = a[k] + b' - b = a[k] + inf t[k] - b, (11) +* +* we can see that disjunction of constraint (9) and (10) is equivalent +* to disjunction of constraint (4) and (5), from which it follows that +* the original constraint (2) is equivalent to the following constraint +* with both coefficient at variable x[k] and right-hand side changed: +* +* a'[k] x[k] + t[k] >= b'. (12) +* +* From inf t[k] < b - a[k] it follows that a'[k] < 0, i.e. the +* coefficient at x[k] keeps its sign. And from inf t[k] > b it follows +* that a'[k] > a[k], i.e. the coefficient reduces in magnitude. +* +* PROBLEM TRANSFORMATION +* +* In the routine npp_reduce_ineq_coef the following implied lower +* bound of the partial sum (3) is used: +* +* inf t[k] = sum a[j] l[j] + sum a[j] u[j], (13) +* j in Jp\{k} k in Jn\{k} +* +* where Jp = {j : a[j] > 0}, Jn = {j : a[j] < 0}, l[j] and u[j] are +* lower and upper bounds, resp., of variable x[j]. +* +* In order to compute inf t[k] more efficiently, the following formula, +* which is equivalent to (13), is actually used: +* +* ( h - a[k] l[k] = h, if a[k] > 0, +* inf t[k] = < (14) +* ( h - a[k] u[k] = h - a[k], if a[k] < 0, +* +* where: +* +* h = sum a[j] l[j] + sum a[j] u[j] (15) +* j in Jp j in Jn +* +* is the implied lower bound of row (1). +* +* Reduction of positive coefficient (a[k] > 0) does not change value +* of h, since l[k] = 0. In case of reduction of negative coefficient +* (a[k] < 0) from (11) it follows that: +* +* delta a[k] = a'[k] - a[k] = inf t[k] - b (> 0), (16) +* +* so new value of h (accounting that u[k] = 1) can be computed as +* follows: +* +* h := h + delta a[k] = h + (inf t[k] - b). (17) +* +* RECOVERING SOLUTION +* +* None needed. */ + +static int reduce_ineq_coef(NPP *npp, struct elem *ptr, double *_b) +{ /* process inequality constraint: sum a[j] x[j] >= b */ + /* returns: the number of coefficients reduced */ + struct elem *e; + int count = 0; + double h, inf_t, new_a, b = *_b; + xassert(npp == npp); + /* compute h; see (15) */ + h = 0.0; + for (e = ptr; e != NULL; e = e->next) + { if (e->aj > 0.0) + { if (e->xj->lb == -DBL_MAX) goto done; + h += e->aj * e->xj->lb; + } + else /* e->aj < 0.0 */ + { if (e->xj->ub == +DBL_MAX) goto done; + h += e->aj * e->xj->ub; + } + } + /* perform reduction of coefficients at binary variables */ + for (e = ptr; e != NULL; e = e->next) + { /* skip non-binary variable */ + if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) + continue; + if (e->aj > 0.0) + { /* compute inf t[k]; see (14) */ + inf_t = h; + if (b - e->aj < inf_t && inf_t < b) + { /* compute reduced coefficient a'[k]; see (7) */ + new_a = b - inf_t; + if (new_a >= +1e-3 && + e->aj - new_a >= 0.01 * (1.0 + e->aj)) + { /* accept a'[k] */ +#ifdef GLP_DEBUG + xprintf("+"); +#endif + e->aj = new_a; + count++; + } + } + } + else /* e->aj < 0.0 */ + { /* compute inf t[k]; see (14) */ + inf_t = h - e->aj; + if (b < inf_t && inf_t < b - e->aj) + { /* compute reduced coefficient a'[k]; see (11) */ + new_a = e->aj + (inf_t - b); + if (new_a <= -1e-3 && + new_a - e->aj >= 0.01 * (1.0 - e->aj)) + { /* accept a'[k] */ +#ifdef GLP_DEBUG + xprintf("-"); +#endif + e->aj = new_a; + /* update h; see (17) */ + h += (inf_t - b); + /* compute b'; see (9) */ + b = inf_t; + count++; + } + } + } + } + *_b = b; +done: return count; +} + +int npp_reduce_ineq_coef(NPP *npp, NPPROW *row) +{ /* reduce inequality constraint coefficients */ + NPPROW *copy; + NPPAIJ *aij; + struct elem *ptr, *e; + int kase, count[2]; + double b; + /* the row must be inequality constraint */ + xassert(row->lb < row->ub); + count[0] = count[1] = 0; + for (kase = 0; kase <= 1; kase++) + { if (kase == 0) + { /* process row lower bound */ + if (row->lb == -DBL_MAX) continue; +#ifdef GLP_DEBUG + xprintf("L"); +#endif + ptr = copy_form(npp, row, +1.0); + b = + row->lb; + } + else + { /* process row upper bound */ + if (row->ub == +DBL_MAX) continue; +#ifdef GLP_DEBUG + xprintf("U"); +#endif + ptr = copy_form(npp, row, -1.0); + b = - row->ub; + } + /* now the inequality has the form "sum a[j] x[j] >= b" */ + count[kase] = reduce_ineq_coef(npp, ptr, &b); + if (count[kase] > 0) + { /* the original inequality has been replaced by equivalent + one with coefficients reduced */ + if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) + { /* the original row is single-sided inequality; no copy + is needed */ + copy = NULL; + } + else + { /* the original row is double-sided inequality; we need + to create its copy for other bound before replacing it + with the equivalent inequality */ +#ifdef GLP_DEBUG + xprintf("*"); +#endif + copy = npp_add_row(npp); + if (kase == 0) + { /* the copy is for upper bound */ + copy->lb = -DBL_MAX, copy->ub = row->ub; + } + else + { /* the copy is for lower bound */ + copy->lb = row->lb, copy->ub = +DBL_MAX; + } + /* copy original row coefficients */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, copy, aij->col, aij->val); + } + /* replace the original inequality by equivalent one */ + npp_erase_row(npp, row); + row->lb = b, row->ub = +DBL_MAX; + for (e = ptr; e != NULL; e = e->next) + npp_add_aij(npp, row, e->xj, e->aj); + /* continue processing upper bound for the copy */ + if (copy != NULL) row = copy; + } + drop_form(npp, ptr); + } + return count[0] + count[1]; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp5.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp5.c new file mode 100644 index 000000000..2fad496de --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp5.c @@ -0,0 +1,809 @@ +/* npp5.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2009-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +/*********************************************************************** +* NAME +* +* npp_clean_prob - perform initial LP/MIP processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* void npp_clean_prob(NPP *npp); +* +* DESCRIPTION +* +* The routine npp_clean_prob performs initial LP/MIP processing that +* currently includes: +* +* 1) removing free rows; +* +* 2) replacing double-sided constraint rows with almost identical +* bounds, by equality constraint rows; +* +* 3) removing fixed columns; +* +* 4) replacing double-bounded columns with almost identical bounds by +* fixed columns and removing those columns; +* +* 5) initial processing constraint coefficients (not implemented); +* +* 6) initial processing objective coefficients (not implemented). */ + +void npp_clean_prob(NPP *npp) +{ /* perform initial LP/MIP processing */ + NPPROW *row, *next_row; + NPPCOL *col, *next_col; + int ret; + xassert(npp == npp); + /* process rows which originally are free */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* process free row */ +#ifdef GLP_DEBUG + xprintf("1"); +#endif + npp_free_row(npp, row); + /* row was deleted */ + } + } + /* process rows which originally are double-sided inequalities */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb != -DBL_MAX && row->ub != +DBL_MAX && + row->lb < row->ub) + { ret = npp_make_equality(npp, row); + if (ret == 0) + ; + else if (ret == 1) + { /* row was replaced by equality constraint */ +#ifdef GLP_DEBUG + xprintf("2"); +#endif + } + else + xassert(ret != ret); + } + } + /* process columns which are originally fixed */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb == col->ub) + { /* process fixed column */ +#ifdef GLP_DEBUG + xprintf("3"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + } + /* process columns which are originally double-bounded */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb != -DBL_MAX && col->ub != +DBL_MAX && + col->lb < col->ub) + { ret = npp_make_fixed(npp, col); + if (ret == 0) + ; + else if (ret == 1) + { /* column was replaced by fixed column; process it */ +#ifdef GLP_DEBUG + xprintf("4"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + } + } + return; +} + +/*********************************************************************** +* NAME +* +* npp_process_row - perform basic row processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_row(NPP *npp, NPPROW *row, int hard); +* +* DESCRIPTION +* +* The routine npp_process_row performs basic row processing that +* currently includes: +* +* 1) removing empty row; +* +* 2) removing equality constraint row singleton and corresponding +* column; +* +* 3) removing inequality constraint row singleton and corresponding +* column if it was fixed; +* +* 4) performing general row analysis; +* +* 5) removing redundant row bounds; +* +* 6) removing forcing row and corresponding columns; +* +* 7) removing row which becomes free due to redundant bounds; +* +* 8) computing implied bounds for all columns in the row and using +* them to strengthen current column bounds (MIP only, optional, +* performed if the flag hard is on). +* +* Additionally the routine may activate affected rows and/or columns +* for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_row(NPP *npp, NPPROW *row, int hard) +{ /* perform basic row processing */ + NPPCOL *col; + NPPAIJ *aij, *next_aij, *aaa; + int ret; + /* row must not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* start processing row */ + if (row->ptr == NULL) + { /* empty row */ + ret = npp_empty_row(npp, row); + if (ret == 0) + { /* row was deleted */ +#ifdef GLP_DEBUG + xprintf("A"); +#endif + return 0; + } + else if (ret == 1) + { /* primal infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + if (row->ptr->r_next == NULL) + { /* row singleton */ + col = row->ptr->col; + if (row->lb == row->ub) + { /* equality constraint */ + ret = npp_eq_singlet(npp, row); + if (ret == 0) + { /* column was fixed, row was deleted */ +#ifdef GLP_DEBUG + xprintf("B"); +#endif + /* activate rows affected by column */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_activate_row(npp, aij->row); + /* process fixed column */ + npp_fixed_col(npp, col); + /* column was deleted */ + return 0; + } + else if (ret == 1 || ret == 2) + { /* primal/integer infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + else + { /* inequality constraint */ + ret = npp_ineq_singlet(npp, row); + if (0 <= ret && ret <= 3) + { /* row was deleted */ +#ifdef GLP_DEBUG + xprintf("C"); +#endif + /* activate column, since its length was changed due to + row deletion */ + npp_activate_col(npp, col); + if (ret >= 2) + { /* column bounds changed significantly or column was + fixed */ + /* activate rows affected by column */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + npp_activate_row(npp, aij->row); + } + if (ret == 3) + { /* column was fixed; process it */ +#ifdef GLP_DEBUG + xprintf("D"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + } + return 0; + } + else if (ret == 4) + { /* primal infeasibility */ + return GLP_ENOPFS; + } + else + xassert(ret != ret); + } + } +#if 0 + /* sometimes this causes too large round-off errors; probably + pivot coefficient should be chosen more carefully */ + if (row->ptr->r_next->r_next == NULL) + { /* row doubleton */ + if (row->lb == row->ub) + { /* equality constraint */ + if (!(row->ptr->col->is_int || + row->ptr->r_next->col->is_int)) + { /* both columns are continuous */ + NPPCOL *q; + q = npp_eq_doublet(npp, row); + if (q != NULL) + { /* column q was eliminated */ +#ifdef GLP_DEBUG + xprintf("E"); +#endif + /* now column q is singleton of type "implied slack + variable"; we process it here to make sure that on + recovering basic solution the row is always active + equality constraint (as required by the routine + rcv_eq_doublet) */ + xassert(npp_process_col(npp, q) == 0); + /* column q was deleted; note that row p also may be + deleted */ + return 0; + } + } + } + } +#endif + /* general row analysis */ + ret = npp_analyze_row(npp, row); + xassert(0x00 <= ret && ret <= 0xFF); + if (ret == 0x33) + { /* row bounds are inconsistent with column bounds */ + return GLP_ENOPFS; + } + if ((ret & 0x0F) == 0x00) + { /* row lower bound does not exist or redundant */ + if (row->lb != -DBL_MAX) + { /* remove redundant row lower bound */ +#ifdef GLP_DEBUG + xprintf("F"); +#endif + npp_inactive_bound(npp, row, 0); + } + } + else if ((ret & 0x0F) == 0x01) + { /* row lower bound can be active */ + /* see below */ + } + else if ((ret & 0x0F) == 0x02) + { /* row lower bound is a forcing bound */ +#ifdef GLP_DEBUG + xprintf("G"); +#endif + /* process forcing row */ + if (npp_forcing_row(npp, row, 0) == 0) +fixup: { /* columns were fixed, row was made free */ + for (aij = row->ptr; aij != NULL; aij = next_aij) + { /* process column fixed by forcing row */ +#ifdef GLP_DEBUG + xprintf("H"); +#endif + col = aij->col; + next_aij = aij->r_next; + /* activate rows affected by column */ + for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) + npp_activate_row(npp, aaa->row); + /* process fixed column */ + npp_fixed_col(npp, col); + /* column was deleted */ + } + /* process free row (which now is empty due to deletion of + all its columns) */ + npp_free_row(npp, row); + /* row was deleted */ + return 0; + } + } + else + xassert(ret != ret); + if ((ret & 0xF0) == 0x00) + { /* row upper bound does not exist or redundant */ + if (row->ub != +DBL_MAX) + { /* remove redundant row upper bound */ +#ifdef GLP_DEBUG + xprintf("I"); +#endif + npp_inactive_bound(npp, row, 1); + } + } + else if ((ret & 0xF0) == 0x10) + { /* row upper bound can be active */ + /* see below */ + } + else if ((ret & 0xF0) == 0x20) + { /* row upper bound is a forcing bound */ +#ifdef GLP_DEBUG + xprintf("J"); +#endif + /* process forcing row */ + if (npp_forcing_row(npp, row, 1) == 0) goto fixup; + } + else + xassert(ret != ret); + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* row became free due to redundant bounds removal */ +#ifdef GLP_DEBUG + xprintf("K"); +#endif + /* activate its columns, since their length will change due + to row deletion */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_activate_col(npp, aij->col); + /* process free row */ + npp_free_row(npp, row); + /* row was deleted */ + return 0; + } +#if 1 /* 23/XII-2009 */ + /* row lower and/or upper bounds can be active */ + if (npp->sol == GLP_MIP && hard) + { /* improve current column bounds (optional) */ + if (npp_improve_bounds(npp, row, 1) < 0) + return GLP_ENOPFS; + } +#endif + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_improve_bounds - improve current column bounds +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); +* +* DESCRIPTION +* +* The routine npp_improve_bounds analyzes specified row (inequality +* or equality constraint) to determine implied column bounds and then +* uses these bounds to improve (strengthen) current column bounds. +* +* If the flag is on and current column bounds changed significantly +* or the column was fixed, the routine activate rows affected by the +* column for further processing. (This feature is intended to be used +* in the main loop of the routine npp_process_row.) +* +* NOTE: This operation can be used for MIP problem only. +* +* RETURNS +* +* The routine npp_improve_bounds returns the number of significantly +* changed bounds plus the number of column having been fixed due to +* bound improvements. However, if the routine detects primal/integer +* infeasibility, it returns a negative value. */ + +int npp_improve_bounds(NPP *npp, NPPROW *row, int flag) +{ /* improve current column bounds */ + NPPCOL *col; + NPPAIJ *aij, *next_aij, *aaa; + int kase, ret, count = 0; + double lb, ub; + xassert(npp->sol == GLP_MIP); + /* row must not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* determine implied column bounds */ + npp_implied_bounds(npp, row); + /* and use these bounds to strengthen current column bounds */ + for (aij = row->ptr; aij != NULL; aij = next_aij) + { col = aij->col; + next_aij = aij->r_next; + for (kase = 0; kase <= 1; kase++) + { /* save current column bounds */ + lb = col->lb, ub = col->ub; + if (kase == 0) + { /* process implied column lower bound */ + if (col->ll.ll == -DBL_MAX) continue; + ret = npp_implied_lower(npp, col, col->ll.ll); + } + else + { /* process implied column upper bound */ + if (col->uu.uu == +DBL_MAX) continue; + ret = npp_implied_upper(npp, col, col->uu.uu); + } + if (ret == 0 || ret == 1) + { /* current column bounds did not change or changed, but + not significantly; restore current column bounds */ + col->lb = lb, col->ub = ub; + } + else if (ret == 2 || ret == 3) + { /* current column bounds changed significantly or column + was fixed */ +#ifdef GLP_DEBUG + xprintf("L"); +#endif + count++; + /* activate other rows affected by column, if required */ + if (flag) + { for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) + { if (aaa->row != row) + npp_activate_row(npp, aaa->row); + } + } + if (ret == 3) + { /* process fixed column */ +#ifdef GLP_DEBUG + xprintf("M"); +#endif + npp_fixed_col(npp, col); + /* column was deleted */ + break; /* for kase */ + } + } + else if (ret == 4) + { /* primal/integer infeasibility */ + return -1; + } + else + xassert(ret != ret); + } + } + return count; +} + +/*********************************************************************** +* NAME +* +* npp_process_col - perform basic column processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_col(NPP *npp, NPPCOL *col); +* +* DESCRIPTION +* +* The routine npp_process_col performs basic column processing that +* currently includes: +* +* 1) fixing and removing empty column; +* +* 2) removing column singleton, which is implied slack variable, and +* corresponding row if it becomes free; +* +* 3) removing bounds of column, which is implied free variable, and +* replacing corresponding row by equality constraint. +* +* Additionally the routine may activate affected rows and/or columns +* for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_col(NPP *npp, NPPCOL *col) +{ /* perform basic column processing */ + NPPROW *row; + NPPAIJ *aij; + int ret; + /* column must not be fixed */ + xassert(col->lb < col->ub); + /* start processing column */ + if (col->ptr == NULL) + { /* empty column */ + ret = npp_empty_col(npp, col); + if (ret == 0) + { /* column was fixed and deleted */ +#ifdef GLP_DEBUG + xprintf("N"); +#endif + return 0; + } + else if (ret == 1) + { /* dual infeasibility */ + return GLP_ENODFS; + } + else + xassert(ret != ret); + } + if (col->ptr->c_next == NULL) + { /* column singleton */ + row = col->ptr->row; + if (row->lb == row->ub) + { /* equality constraint */ + if (!col->is_int) +slack: { /* implied slack variable */ +#ifdef GLP_DEBUG + xprintf("O"); +#endif + npp_implied_slack(npp, col); + /* column was deleted */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + { /* row became free due to implied slack variable */ +#ifdef GLP_DEBUG + xprintf("P"); +#endif + /* activate columns affected by row */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_activate_col(npp, aij->col); + /* process free row */ + npp_free_row(npp, row); + /* row was deleted */ + } + else + { /* row became inequality constraint; activate it + since its length changed due to column deletion */ + npp_activate_row(npp, row); + } + return 0; + } + } + else + { /* inequality constraint */ + if (!col->is_int) + { ret = npp_implied_free(npp, col); + if (ret == 0) + { /* implied free variable */ +#ifdef GLP_DEBUG + xprintf("Q"); +#endif + /* column bounds were removed, row was replaced by + equality constraint */ + goto slack; + } + else if (ret == 1) + { /* column is not implied free variable, because its + lower and/or upper bounds can be active */ + } + else if (ret == 2) + { /* dual infeasibility */ + return GLP_ENODFS; + } + } + } + } + /* column still exists */ + return 0; +} + +/*********************************************************************** +* NAME +* +* npp_process_prob - perform basic LP/MIP processing +* +* SYNOPSIS +* +* #include "glpnpp.h" +* int npp_process_prob(NPP *npp, int hard); +* +* DESCRIPTION +* +* The routine npp_process_prob performs basic LP/MIP processing that +* currently includes: +* +* 1) initial LP/MIP processing (see the routine npp_clean_prob), +* +* 2) basic row processing (see the routine npp_process_row), and +* +* 3) basic column processing (see the routine npp_process_col). +* +* If the flag hard is on, the routine attempts to improve current +* column bounds multiple times within the main processing loop, in +* which case this feature may take a time. Otherwise, if the flag hard +* is off, improving column bounds is performed only once at the end of +* the main loop. (Note that this feature is used for MIP only.) +* +* The routine uses two sets: the set of active rows and the set of +* active columns. Rows/columns are marked by a flag (the field temp in +* NPPROW/NPPCOL). If the flag is non-zero, the row/column is active, +* in which case it is placed in the beginning of the row/column list; +* otherwise, if the flag is zero, the row/column is inactive, in which +* case it is placed in the end of the row/column list. If a row/column +* being currently processed may affect other rows/columns, the latters +* are activated for further processing. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ENODFS dual infeasibility detected. */ + +int npp_process_prob(NPP *npp, int hard) +{ /* perform basic LP/MIP processing */ + NPPROW *row; + NPPCOL *col; + int processing, ret; + /* perform initial LP/MIP processing */ + npp_clean_prob(npp); + /* activate all remaining rows and columns */ + for (row = npp->r_head; row != NULL; row = row->next) + row->temp = 1; + for (col = npp->c_head; col != NULL; col = col->next) + col->temp = 1; + /* main processing loop */ + processing = 1; + while (processing) + { processing = 0; + /* process all active rows */ + for (;;) + { row = npp->r_head; + if (row == NULL || !row->temp) break; + npp_deactivate_row(npp, row); + ret = npp_process_row(npp, row, hard); + if (ret != 0) goto done; + processing = 1; + } + /* process all active columns */ + for (;;) + { col = npp->c_head; + if (col == NULL || !col->temp) break; + npp_deactivate_col(npp, col); + ret = npp_process_col(npp, col); + if (ret != 0) goto done; + processing = 1; + } + } +#if 1 /* 23/XII-2009 */ + if (npp->sol == GLP_MIP && !hard) + { /* improve current column bounds (optional) */ + for (row = npp->r_head; row != NULL; row = row->next) + { if (npp_improve_bounds(npp, row, 0) < 0) + { ret = GLP_ENOPFS; + goto done; + } + } + } +#endif + /* all seems ok */ + ret = 0; +done: xassert(ret == 0 || ret == GLP_ENOPFS || ret == GLP_ENODFS); +#ifdef GLP_DEBUG + xprintf("\n"); +#endif + return ret; +} + +/**********************************************************************/ + +int npp_simplex(NPP *npp, const glp_smcp *parm) +{ /* process LP prior to applying primal/dual simplex method */ + int ret; + xassert(npp->sol == GLP_SOL); + xassert(parm == parm); + ret = npp_process_prob(npp, 0); + return ret; +} + +/**********************************************************************/ + +int npp_integer(NPP *npp, const glp_iocp *parm) +{ /* process MIP prior to applying branch-and-bound method */ + NPPROW *row, *prev_row; + NPPCOL *col; + NPPAIJ *aij; + int count, ret; + xassert(npp->sol == GLP_MIP); + xassert(parm == parm); + /*==============================================================*/ + /* perform basic MIP processing */ + ret = npp_process_prob(npp, 1); + if (ret != 0) goto done; + /*==============================================================*/ + /* binarize problem, if required */ + if (parm->binarize) + npp_binarize_prob(npp); + /*==============================================================*/ + /* identify hidden packing inequalities */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip free row */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + /* skip row having less than two variables */ + if (row->ptr == NULL || row->ptr->r_next == NULL) continue; + /* skip row having non-binary variables */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + break; + } + if (aij != NULL) continue; + count += npp_hidden_packing(npp, row); + } + if (count > 0) + xprintf("%d hidden packing inequaliti(es) were detected\n", + count); + /*==============================================================*/ + /* identify hidden covering inequalities */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip free row */ + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + /* skip row having less than three variables */ + if (row->ptr == NULL || row->ptr->r_next == NULL || + row->ptr->r_next->r_next == NULL) continue; + /* skip row having non-binary variables */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + break; + } + if (aij != NULL) continue; + count += npp_hidden_covering(npp, row); + } + if (count > 0) + xprintf("%d hidden covering inequaliti(es) were detected\n", + count); + /*==============================================================*/ + /* reduce inequality constraint coefficients */ + count = 0; + /* new rows will be added to the end of the row list, so we go + from the end to beginning of the row list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* skip equality constraint */ + if (row->lb == row->ub) continue; + count += npp_reduce_ineq_coef(npp, row); + } + if (count > 0) + xprintf("%d constraint coefficient(s) were reduced\n", count); + /*==============================================================*/ +#ifdef GLP_DEBUG + routine(npp); +#endif + /*==============================================================*/ + /* all seems ok */ + ret = 0; +done: return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp6.c b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp6.c new file mode 100644 index 000000000..b57f86154 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/npp/npp6.c @@ -0,0 +1,1500 @@ +/* npp6.c (translate feasibility problem to CNF-SAT) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2011-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "npp.h" + +/*********************************************************************** +* npp_sat_free_row - process free (unbounded) row +* +* This routine processes row p, which is free (i.e. has no finite +* bounds): +* +* -inf < sum a[p,j] x[j] < +inf. (1) +* +* The constraint (1) cannot be active and therefore it is redundant, +* so the routine simply removes it from the original problem. */ + +void npp_sat_free_row(NPP *npp, NPPROW *p) +{ /* the row should be free */ + xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); + /* remove the row from the problem */ + npp_del_row(npp, p); + return; +} + +/*********************************************************************** +* npp_sat_fixed_col - process fixed column +* +* This routine processes column q, which is fixed: +* +* x[q] = s[q], (1) +* +* where s[q] is a fixed column value. +* +* The routine substitutes fixed value s[q] into constraint rows and +* then removes column x[q] from the original problem. +* +* Substitution of x[q] = s[q] into row i gives: +* +* L[i] <= sum a[i,j] x[j] <= U[i] ==> +* j +* +* L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> +* j!=q +* +* L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> +* j!=q +* +* L~[i] <= sum a[i,j] x[j] <= U~[i], +* j!=q +* +* where +* +* L~[i] = L[i] - a[i,q] s[q], (2) +* +* U~[i] = U[i] - a[i,q] s[q] (3) +* +* are, respectively, lower and upper bound of row i in the transformed +* problem. +* +* On recovering solution x[q] is assigned the value of s[q]. */ + +struct sat_fixed_col +{ /* fixed column */ + int q; + /* column reference number for variable x[q] */ + int s; + /* value, at which x[q] is fixed */ +}; + +static int rcv_sat_fixed_col(NPP *, void *); + +int npp_sat_fixed_col(NPP *npp, NPPCOL *q) +{ struct sat_fixed_col *info; + NPPROW *i; + NPPAIJ *aij; + int temp; + /* the column should be fixed */ + xassert(q->lb == q->ub); + /* create transformation stack entry */ + info = npp_push_tse(npp, + rcv_sat_fixed_col, sizeof(struct sat_fixed_col)); + info->q = q->j; + info->s = (int)q->lb; + xassert((double)info->s == q->lb); + /* substitute x[q] = s[q] into constraint rows */ + if (info->s == 0) + goto skip; + for (aij = q->ptr; aij != NULL; aij = aij->c_next) + { i = aij->row; + if (i->lb != -DBL_MAX) + { i->lb -= aij->val * (double)info->s; + temp = (int)i->lb; + if ((double)temp != i->lb) + return 1; /* integer arithmetic error */ + } + if (i->ub != +DBL_MAX) + { i->ub -= aij->val * (double)info->s; + temp = (int)i->ub; + if ((double)temp != i->ub) + return 2; /* integer arithmetic error */ + } + } +skip: /* remove the column from the problem */ + npp_del_col(npp, q); + return 0; +} + +static int rcv_sat_fixed_col(NPP *npp, void *info_) +{ struct sat_fixed_col *info = info_; + npp->c_value[info->q] = (double)info->s; + return 0; +} + +/*********************************************************************** +* npp_sat_is_bin_comb - test if row is binary combination +* +* This routine tests if the specified row is a binary combination, +* i.e. all its constraint coefficients are +1 and -1 and all variables +* are binary. If the test was passed, the routine returns non-zero, +* otherwise zero. */ + +int npp_sat_is_bin_comb(NPP *npp, NPPROW *row) +{ NPPCOL *col; + NPPAIJ *aij; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (!(aij->val == +1.0 || aij->val == -1.0)) + return 0; /* non-unity coefficient */ + col = aij->col; + if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) + return 0; /* non-binary column */ + } + return 1; /* test was passed */ +} + +/*********************************************************************** +* npp_sat_num_pos_coef - determine number of positive coefficients +* +* This routine returns the number of positive coefficients in the +* specified row. */ + +int npp_sat_num_pos_coef(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int num = 0; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val > 0.0) + num++; + } + return num; +} + +/*********************************************************************** +* npp_sat_num_neg_coef - determine number of negative coefficients +* +* This routine returns the number of negative coefficients in the +* specified row. */ + +int npp_sat_num_neg_coef(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int num = 0; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val < 0.0) + num++; + } + return num; +} + +/*********************************************************************** +* npp_sat_is_cover_ineq - test if row is covering inequality +* +* The canonical form of a covering inequality is the following: +* +* sum x[j] >= 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a covering inequality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] >= 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] <= |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the inequality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the inequality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a covering inequality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) + { /* row is inequality of '>=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + } + } + else if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) + { /* row is inequality of '<=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a covering inequality */ + return 0; +} + +/*********************************************************************** +* npp_sat_is_pack_ineq - test if row is packing inequality +* +* The canonical form of a packing inequality is the following: +* +* sum x[j] <= 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a packing inequality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] <= 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] >= |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the inequality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the inequality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a packing inequality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) + { /* row is inequality of '<=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->ub == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + } + } + else if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) + { /* row is inequality of '>=' type */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a packing inequality */ + return 0; +} + +/*********************************************************************** +* npp_sat_is_partn_eq - test if row is partitioning equality +* +* The canonical form of a partitioning equality is the following: +* +* sum x[j] = 1, (1) +* j in J +* +* where all x[j] are binary variables. +* +* In general case a partitioning equality may have one of the following +* two forms: +* +* sum x[j] - sum x[j] = 1 - |J-|, (2) +* j in J+ j in J- +* +* +* sum x[j] - sum x[j] = |J+| - 1. (3) +* j in J+ j in J- +* +* Obviously, the equality (2) can be transformed to the form (1) by +* substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the +* negation of variable x[j]. And the equality (3) can be transformed +* to (2) by multiplying both left- and right-hand sides by -1. +* +* This routine returns one of the following codes: +* +* 0, if the specified row is not a partitioning equality; +* +* 1, if the specified row has the form (2); +* +* 2, if the specified row has the form (3). */ + +int npp_sat_is_partn_eq(NPP *npp, NPPROW *row) +{ xassert(npp == npp); + if (row->lb == row->ub) + { /* row is equality constraint */ + if (npp_sat_is_bin_comb(npp, row)) + { /* row is a binary combination */ + if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) + { /* row has the form (2) */ + return 1; + } + if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) + { /* row has the form (3) */ + return 2; + } + } + } + /* row is not a partitioning equality */ + return 0; +} + +/*********************************************************************** +* npp_sat_reverse_row - multiply both sides of row by -1 +* +* This routines multiplies by -1 both left- and right-hand sides of +* the specified row: +* +* L <= sum x[j] <= U, +* +* that results in the following row: +* +* -U <= sum (-x[j]) <= -L. +* +* If no integer overflow occured, the routine returns zero, otherwise +* non-zero. */ + +int npp_sat_reverse_row(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + int temp, ret = 0; + double old_lb, old_ub; + xassert(npp == npp); + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { aij->val = -aij->val; + temp = (int)aij->val; + if ((double)temp != aij->val) + ret = 1; + } + old_lb = row->lb, old_ub = row->ub; + if (old_ub == +DBL_MAX) + row->lb = -DBL_MAX; + else + { row->lb = -old_ub; + temp = (int)row->lb; + if ((double)temp != row->lb) + ret = 2; + } + if (old_lb == -DBL_MAX) + row->ub = +DBL_MAX; + else + { row->ub = -old_lb; + temp = (int)row->ub; + if ((double)temp != row->ub) + ret = 3; + } + return ret; +} + +/*********************************************************************** +* npp_sat_split_pack - split packing inequality +* +* Let there be given a packing inequality in canonical form: +* +* sum t[j] <= 1, (1) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable. +* And let J = J1 U J2 is a partition of the set of literals. Then the +* inequality (1) is obviously equivalent to the following two packing +* inequalities: +* +* sum t[j] <= y <--> sum t[j] + (1 - y) <= 1, (2) +* j in J1 j in J1 +* +* sum t[j] <= 1 - y <--> sum t[j] + y <= 1, (3) +* j in J2 j in J2 +* +* where y is a new binary variable added to the transformed problem. +* +* Assuming that the specified row is a packing inequality (1), this +* routine constructs the set J1 by including there first nlit literals +* (terms) from the specified row, and the set J2 = J \ J1. Then the +* routine creates a new row, which corresponds to inequality (2), and +* replaces the specified row with inequality (3). */ + +NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nlit) +{ NPPROW *rrr; + NPPCOL *col; + NPPAIJ *aij; + int k; + /* original row should be packing inequality (1) */ + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* and nlit should be less than the number of literals (terms) + in the original row */ + xassert(0 < nlit && nlit < npp_row_nnz(npp, row)); + /* create new row corresponding to inequality (2) */ + rrr = npp_add_row(npp); + rrr->lb = -DBL_MAX, rrr->ub = 1.0; + /* move first nlit literals (terms) from the original row to the + new row; the original row becomes inequality (3) */ + for (k = 1; k <= nlit; k++) + { aij = row->ptr; + xassert(aij != NULL); + /* add literal to the new row */ + npp_add_aij(npp, rrr, aij->col, aij->val); + /* correct rhs */ + if (aij->val < 0.0) + rrr->ub -= 1.0, row->ub += 1.0; + /* remove literal from the original row */ + npp_del_aij(npp, aij); + } + /* create new binary variable y */ + col = npp_add_col(npp); + col->is_int = 1, col->lb = 0.0, col->ub = 1.0; + /* include literal (1 - y) in the new row */ + npp_add_aij(npp, rrr, col, -1.0); + rrr->ub -= 1.0; + /* include literal y in the original row */ + npp_add_aij(npp, row, col, +1.0); + return rrr; +} + +/*********************************************************************** +* npp_sat_encode_pack - encode packing inequality +* +* Given a packing inequality in canonical form: +* +* sum t[j] <= 1, (1) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable, +* this routine translates it to CNF by replacing it with the following +* equivalent set of edge packing inequalities: +* +* t[j] + t[k] <= 1 for all j, k in J, j != k. (2) +* +* Then the routine transforms each edge packing inequality (2) to +* corresponding covering inequality (that encodes two-literal clause) +* by multiplying both its part by -1: +* +* - t[j] - t[k] >= -1 <--> (1 - t[j]) + (1 - t[k]) >= 1. (3) +* +* On exit the routine removes the original row from the problem. */ + +void npp_sat_encode_pack(NPP *npp, NPPROW *row) +{ NPPROW *rrr; + NPPAIJ *aij, *aik; + /* original row should be packing inequality (1) */ + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* create equivalent system of covering inequalities (3) */ + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { /* due to symmetry only one of inequalities t[j] + t[k] <= 1 + and t[k] <= t[j] <= 1 can be considered */ + for (aik = aij->r_next; aik != NULL; aik = aik->r_next) + { /* create edge packing inequality (2) */ + rrr = npp_add_row(npp); + rrr->lb = -DBL_MAX, rrr->ub = 1.0; + npp_add_aij(npp, rrr, aij->col, aij->val); + if (aij->val < 0.0) + rrr->ub -= 1.0; + npp_add_aij(npp, rrr, aik->col, aik->val); + if (aik->val < 0.0) + rrr->ub -= 1.0; + /* and transform it to covering inequality (3) */ + npp_sat_reverse_row(npp, rrr); + xassert(npp_sat_is_cover_ineq(npp, rrr) == 1); + } + } + /* remove the original row from the problem */ + npp_del_row(npp, row); + return; +} + +/*********************************************************************** +* npp_sat_encode_sum2 - encode 2-bit summation +* +* Given a set containing two literals x and y this routine encodes +* the equality +* +* x + y = s + 2 * c, (1) +* +* where +* +* s = (x + y) % 2 (2) +* +* is a binary variable modeling the low sum bit, and +* +* c = (x + y) / 2 (3) +* +* is a binary variable modeling the high (carry) sum bit. */ + +void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed) +{ NPPROW *row; + int x, y, s, c; + /* the set should contain exactly two literals */ + xassert(set != NULL); + xassert(set->next != NULL); + xassert(set->next->next == NULL); + sed->x = set->lit; + xassert(sed->x.neg == 0 || sed->x.neg == 1); + sed->y = set->next->lit; + xassert(sed->y.neg == 0 || sed->y.neg == 1); + sed->z.col = NULL, sed->z.neg = 0; + /* perform encoding s = (x + y) % 2 */ + sed->s = npp_add_col(npp); + sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (s = 0; s <= 1; s++) + { if ((x + y) % 2 != s) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (s == 0) + npp_add_aij(npp, row, sed->s, +1.0); + else + { npp_add_aij(npp, row, sed->s, -1.0); + row->lb -= 1.0; + } + } + } + } + } + /* perform encoding c = (x + y) / 2 */ + sed->c = npp_add_col(npp); + sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (c = 0; c <= 1; c++) + { if ((x + y) / 2 != c) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (c == 0) + npp_add_aij(npp, row, sed->c, +1.0); + else + { npp_add_aij(npp, row, sed->c, -1.0); + row->lb -= 1.0; + } + } + } + } + } + return; +} + +/*********************************************************************** +* npp_sat_encode_sum3 - encode 3-bit summation +* +* Given a set containing at least three literals this routine chooses +* some literals x, y, z from that set and encodes the equality +* +* x + y + z = s + 2 * c, (1) +* +* where +* +* s = (x + y + z) % 2 (2) +* +* is a binary variable modeling the low sum bit, and +* +* c = (x + y + z) / 2 (3) +* +* is a binary variable modeling the high (carry) sum bit. */ + +void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed) +{ NPPROW *row; + int x, y, z, s, c; + /* the set should contain at least three literals */ + xassert(set != NULL); + xassert(set->next != NULL); + xassert(set->next->next != NULL); + sed->x = set->lit; + xassert(sed->x.neg == 0 || sed->x.neg == 1); + sed->y = set->next->lit; + xassert(sed->y.neg == 0 || sed->y.neg == 1); + sed->z = set->next->next->lit; + xassert(sed->z.neg == 0 || sed->z.neg == 1); + /* perform encoding s = (x + y + z) % 2 */ + sed->s = npp_add_col(npp); + sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (z = 0; z <= 1; z++) + { for (s = 0; s <= 1; s++) + { if ((x + y + z) % 2 != s) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (z == sed->z.neg) + npp_add_aij(npp, row, sed->z.col, +1.0); + else + { npp_add_aij(npp, row, sed->z.col, -1.0); + row->lb -= 1.0; + } + if (s == 0) + npp_add_aij(npp, row, sed->s, +1.0); + else + { npp_add_aij(npp, row, sed->s, -1.0); + row->lb -= 1.0; + } + } + } + } + } + } + /* perform encoding c = (x + y + z) / 2 */ + sed->c = npp_add_col(npp); + sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; + for (x = 0; x <= 1; x++) + { for (y = 0; y <= 1; y++) + { for (z = 0; z <= 1; z++) + { for (c = 0; c <= 1; c++) + { if ((x + y + z) / 2 != c) + { /* generate CNF clause to disable infeasible + combination */ + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + if (x == sed->x.neg) + npp_add_aij(npp, row, sed->x.col, +1.0); + else + { npp_add_aij(npp, row, sed->x.col, -1.0); + row->lb -= 1.0; + } + if (y == sed->y.neg) + npp_add_aij(npp, row, sed->y.col, +1.0); + else + { npp_add_aij(npp, row, sed->y.col, -1.0); + row->lb -= 1.0; + } + if (z == sed->z.neg) + npp_add_aij(npp, row, sed->z.col, +1.0); + else + { npp_add_aij(npp, row, sed->z.col, -1.0); + row->lb -= 1.0; + } + if (c == 0) + npp_add_aij(npp, row, sed->c, +1.0); + else + { npp_add_aij(npp, row, sed->c, -1.0); + row->lb -= 1.0; + } + } + } + } + } + } + return; +} + +/*********************************************************************** +* npp_sat_encode_sum_ax - encode linear combination of 0-1 variables +* +* PURPOSE +* +* Given a linear combination of binary variables: +* +* sum a[j] x[j], (1) +* j +* +* which is the linear form of the specified row, this routine encodes +* (i.e. translates to CNF) the following equality: +* +* n +* sum |a[j]| t[j] = sum 2**(k-1) * y[k], (2) +* j k=1 +* +* where t[j] = x[j] (if a[j] > 0) or t[j] = 1 - x[j] (if a[j] < 0), +* and y[k] is either t[j] or a new literal created by the routine or +* a constant zero. Note that the sum in the right-hand side of (2) can +* be thought as a n-bit representation of the sum in the left-hand +* side, which is a non-negative integer number. +* +* ALGORITHM +* +* First, the number of bits, n, sufficient to represent any value in +* the left-hand side of (2) is determined. Obviously, n is the number +* of bits sufficient to represent the sum (sum |a[j]|). +* +* Let +* +* n +* |a[j]| = sum 2**(k-1) b[j,k], (3) +* k=1 +* +* where b[j,k] is k-th bit in a n-bit representation of |a[j]|. Then +* +* m n +* sum |a[j]| * t[j] = sum 2**(k-1) sum b[j,k] * t[j]. (4) +* j k=1 j=1 +* +* Introducing the set +* +* J[k] = { j : b[j,k] = 1 } (5) +* +* allows rewriting (4) as follows: +* +* n +* sum |a[j]| * t[j] = sum 2**(k-1) sum t[j]. (6) +* j k=1 j in J[k] +* +* Thus, our goal is to provide |J[k]| <= 1 for all k, in which case +* we will have the representation (1). +* +* Let |J[k]| = 2, i.e. J[k] has exactly two literals u and v. In this +* case we can apply the following transformation: +* +* u + v = s + 2 * c, (7) +* +* where s and c are, respectively, low (sum) and high (carry) bits of +* the sum of two bits. This allows to replace two literals u and v in +* J[k] by one literal s, and carry out literal c to J[k+1]. +* +* If |J[k]| >= 3, i.e. J[k] has at least three literals u, v, and w, +* we can apply the following transformation: +* +* u + v + w = s + 2 * c. (8) +* +* Again, literal s replaces literals u, v, and w in J[k], and literal +* c goes into J[k+1]. +* +* On exit the routine stores each literal from J[k] in element y[k], +* 1 <= k <= n. If J[k] is empty, y[k] is set to constant false. +* +* RETURNS +* +* The routine returns n, the number of literals in the right-hand side +* of (2), 0 <= n <= NBIT_MAX. If the sum (sum |a[j]|) is too large, so +* more than NBIT_MAX (= 31) literals are needed to encode the original +* linear combination, the routine returns a negative value. */ + +#define NBIT_MAX 31 +/* maximal number of literals in the right hand-side of (2) */ + +static NPPLSE *remove_lse(NPP *npp, NPPLSE *set, NPPCOL *col) +{ /* remove specified literal from specified literal set */ + NPPLSE *lse, *prev = NULL; + for (lse = set; lse != NULL; prev = lse, lse = lse->next) + if (lse->lit.col == col) break; + xassert(lse != NULL); + if (prev == NULL) + set = lse->next; + else + prev->next = lse->next; + dmp_free_atom(npp->pool, lse, sizeof(NPPLSE)); + return set; +} + +int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]) +{ NPPAIJ *aij; + NPPLSE *set[1+NBIT_MAX], *lse; + NPPSED sed; + int k, n, temp; + double sum; + /* compute the sum (sum |a[j]|) */ + sum = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + sum += fabs(aij->val); + /* determine n, the number of bits in the sum */ + temp = (int)sum; + if ((double)temp != sum) + return -1; /* integer arithmetic error */ + for (n = 0; temp > 0; n++, temp >>= 1); + xassert(0 <= n && n <= NBIT_MAX); + /* build initial sets J[k], 1 <= k <= n; see (5) */ + /* set[k] is a pointer to the list of literals in J[k] */ + for (k = 1; k <= n; k++) + set[k] = NULL; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { temp = (int)fabs(aij->val); + xassert((int)temp == fabs(aij->val)); + for (k = 1; temp > 0; k++, temp >>= 1) + { if (temp & 1) + { xassert(k <= n); + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = aij->col; + lse->lit.neg = (aij->val > 0.0 ? 0 : 1); + lse->next = set[k]; + set[k] = lse; + } + } + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* reduce J[k] and set y[k] */ + for (;;) + { if (set[k] == NULL) + { /* J[k] is empty */ + /* set y[k] to constant false */ + y[k].col = NULL, y[k].neg = 0; + break; + } + if (set[k]->next == NULL) + { /* J[k] contains one literal */ + /* set y[k] to that literal */ + y[k] = set[k]->lit; + dmp_free_atom(npp->pool, set[k], sizeof(NPPLSE)); + break; + } + if (set[k]->next->next == NULL) + { /* J[k] contains two literals */ + /* apply transformation (7) */ + npp_sat_encode_sum2(npp, set[k], &sed); + } + else + { /* J[k] contains at least three literals */ + /* apply transformation (8) */ + npp_sat_encode_sum3(npp, set[k], &sed); + /* remove third literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.z.col); + } + /* remove second literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.y.col); + /* remove first literal from set[k] */ + set[k] = remove_lse(npp, set[k], sed.x.col); + /* include new literal s to set[k] */ + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = sed.s, lse->lit.neg = 0; + lse->next = set[k]; + set[k] = lse; + /* include new literal c to set[k+1] */ + xassert(k < n); /* FIXME: can "overflow" happen? */ + lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); + lse->lit.col = sed.c, lse->lit.neg = 0; + lse->next = set[k+1]; + set[k+1] = lse; + } + } + return n; +} + +/*********************************************************************** +* npp_sat_normalize_clause - normalize clause +* +* This routine normalizes the specified clause, which is a disjunction +* of literals, by replacing multiple literals, which refer to the same +* binary variable, with a single literal. +* +* On exit the routine returns the number of literals in the resulting +* clause. However, if the specified clause includes both a literal and +* its negation, the routine returns a negative value meaning that the +* clause is equivalent to the value true. */ + +int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]) +{ int j, k, new_size; + xassert(npp == npp); + xassert(size >= 0); + new_size = 0; + for (k = 1; k <= size; k++) + { for (j = 1; j <= new_size; j++) + { if (lit[k].col == lit[j].col) + { /* lit[k] refers to the same variable as lit[j], which + is already included in the resulting clause */ + if (lit[k].neg == lit[j].neg) + { /* ignore lit[k] due to the idempotent law */ + goto skip; + } + else + { /* lit[k] is NOT lit[j]; the clause is equivalent to + the value true */ + return -1; + } + } + } + /* include lit[k] in the resulting clause */ + lit[++new_size] = lit[k]; +skip: ; + } + return new_size; +} + +/*********************************************************************** +* npp_sat_encode_clause - translate clause to cover inequality +* +* Given a clause +* +* OR t[j], (1) +* j in J +* +* where t[j] is a literal, i.e. t[j] = x[j] or t[j] = NOT x[j], this +* routine translates it to the following equivalent cover inequality, +* which is added to the transformed problem: +* +* sum t[j] >= 1, (2) +* j in J +* +* where t[j] = x[j] or t[j] = 1 - x[j]. +* +* If necessary, the clause should be normalized before a call to this +* routine. */ + +NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]) +{ NPPROW *row; + int k; + xassert(size >= 1); + row = npp_add_row(npp); + row->lb = 1.0, row->ub = +DBL_MAX; + for (k = 1; k <= size; k++) + { xassert(lit[k].col != NULL); + if (lit[k].neg == 0) + npp_add_aij(npp, row, lit[k].col, +1.0); + else if (lit[k].neg == 1) + { npp_add_aij(npp, row, lit[k].col, -1.0); + row->lb -= 1.0; + } + else + xassert(lit != lit); + } + return row; +} + +/*********************************************************************** +* npp_sat_encode_geq - encode "not less than" constraint +* +* PURPOSE +* +* This routine translates to CNF the following constraint: +* +* n +* sum 2**(k-1) * y[k] >= b, (1) +* k=1 +* +* where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) +* or constant false (zero), b is a given lower bound. +* +* ALGORITHM +* +* If b < 0, the constraint is redundant, so assume that b >= 0. Let +* +* n +* b = sum 2**(k-1) b[k], (2) +* k=1 +* +* where b[k] is k-th binary digit of b. (Note that if b >= 2**n and +* therefore cannot be represented in the form (2), the constraint (1) +* is infeasible.) In this case the condition (1) is equivalent to the +* following condition: +* +* y[n] y[n-1] ... y[2] y[1] >= b[n] b[n-1] ... b[2] b[1], (3) +* +* where ">=" is understood lexicographically. +* +* Algorithmically the condition (3) can be tested as follows: +* +* for (k = n; k >= 1; k--) +* { if (y[k] < b[k]) +* y is less than b; +* if (y[k] > b[k]) +* y is greater than b; +* } +* y is equal to b; +* +* Thus, y is less than b iff there exists k, 1 <= k <= n, for which +* the following condition is satisfied: +* +* y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] < b[k]. (4) +* +* Negating the condition (4) we have that y is not less than b iff for +* all k, 1 <= k <= n, the following condition is satisfied: +* +* y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] >= b[k]. (5) +* +* Note that if b[k] = 0, the literal y[k] >= b[k] is always true, in +* which case the entire clause (5) is true and can be omitted. +* +* RETURNS +* +* Normally the routine returns zero. However, if the constraint (1) is +* infeasible, the routine returns non-zero. */ + +int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs) +{ NPPLIT lit[1+NBIT_MAX]; + int j, k, size, temp, b[1+NBIT_MAX]; + xassert(0 <= n && n <= NBIT_MAX); + /* if the constraint (1) is redundant, do nothing */ + if (rhs < 0) + return 0; + /* determine binary digits of b according to (2) */ + for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) + b[k] = temp & 1; + if (temp != 0) + { /* b >= 2**n; the constraint (1) is infeasible */ + return 1; + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* build the clause (5) for current k */ + size = 0; /* clause size = number of literals */ + /* add literal y[k] >= b[k] */ + if (b[k] == 0) + { /* b[k] = 0 -> the literal is true */ + goto skip; + } + else if (y[k].col == NULL) + { /* y[k] = 0, b[k] = 1 -> the literal is false */ + xassert(y[k].neg == 0); + } + else + { /* add literal y[k] = 1 */ + lit[++size] = y[k]; + } + for (j = k+1; j <= n; j++) + { /* add literal y[j] != b[j] */ + if (y[j].col == NULL) + { xassert(y[j].neg == 0); + if (b[j] == 0) + { /* y[j] = 0, b[j] = 0 -> the literal is false */ + continue; + } + else + { /* y[j] = 0, b[j] = 1 -> the literal is true */ + goto skip; + } + } + else + { lit[++size] = y[j]; + if (b[j] != 0) + lit[size].neg = 1 - lit[size].neg; + } + } + /* normalize the clause */ + size = npp_sat_normalize_clause(npp, size, lit); + if (size < 0) + { /* the clause is equivalent to the value true */ + goto skip; + } + if (size == 0) + { /* the clause is equivalent to the value false; this means + that the constraint (1) is infeasible */ + return 2; + } + /* translate the clause to corresponding cover inequality */ + npp_sat_encode_clause(npp, size, lit); +skip: ; + } + return 0; +} + +/*********************************************************************** +* npp_sat_encode_leq - encode "not greater than" constraint +* +* PURPOSE +* +* This routine translates to CNF the following constraint: +* +* n +* sum 2**(k-1) * y[k] <= b, (1) +* k=1 +* +* where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) +* or constant false (zero), b is a given upper bound. +* +* ALGORITHM +* +* If b < 0, the constraint is infeasible, so assume that b >= 0. Let +* +* n +* b = sum 2**(k-1) b[k], (2) +* k=1 +* +* where b[k] is k-th binary digit of b. (Note that if b >= 2**n and +* therefore cannot be represented in the form (2), the constraint (1) +* is redundant.) In this case the condition (1) is equivalent to the +* following condition: +* +* y[n] y[n-1] ... y[2] y[1] <= b[n] b[n-1] ... b[2] b[1], (3) +* +* where "<=" is understood lexicographically. +* +* Algorithmically the condition (3) can be tested as follows: +* +* for (k = n; k >= 1; k--) +* { if (y[k] < b[k]) +* y is less than b; +* if (y[k] > b[k]) +* y is greater than b; +* } +* y is equal to b; +* +* Thus, y is greater than b iff there exists k, 1 <= k <= n, for which +* the following condition is satisfied: +* +* y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] > b[k]. (4) +* +* Negating the condition (4) we have that y is not greater than b iff +* for all k, 1 <= k <= n, the following condition is satisfied: +* +* y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] <= b[k]. (5) +* +* Note that if b[k] = 1, the literal y[k] <= b[k] is always true, in +* which case the entire clause (5) is true and can be omitted. +* +* RETURNS +* +* Normally the routine returns zero. However, if the constraint (1) is +* infeasible, the routine returns non-zero. */ + +int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs) +{ NPPLIT lit[1+NBIT_MAX]; + int j, k, size, temp, b[1+NBIT_MAX]; + xassert(0 <= n && n <= NBIT_MAX); + /* check if the constraint (1) is infeasible */ + if (rhs < 0) + return 1; + /* determine binary digits of b according to (2) */ + for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) + b[k] = temp & 1; + if (temp != 0) + { /* b >= 2**n; the constraint (1) is redundant */ + return 0; + } + /* main transformation loop */ + for (k = 1; k <= n; k++) + { /* build the clause (5) for current k */ + size = 0; /* clause size = number of literals */ + /* add literal y[k] <= b[k] */ + if (b[k] == 1) + { /* b[k] = 1 -> the literal is true */ + goto skip; + } + else if (y[k].col == NULL) + { /* y[k] = 0, b[k] = 0 -> the literal is true */ + xassert(y[k].neg == 0); + goto skip; + } + else + { /* add literal y[k] = 0 */ + lit[++size] = y[k]; + lit[size].neg = 1 - lit[size].neg; + } + for (j = k+1; j <= n; j++) + { /* add literal y[j] != b[j] */ + if (y[j].col == NULL) + { xassert(y[j].neg == 0); + if (b[j] == 0) + { /* y[j] = 0, b[j] = 0 -> the literal is false */ + continue; + } + else + { /* y[j] = 0, b[j] = 1 -> the literal is true */ + goto skip; + } + } + else + { lit[++size] = y[j]; + if (b[j] != 0) + lit[size].neg = 1 - lit[size].neg; + } + } + /* normalize the clause */ + size = npp_sat_normalize_clause(npp, size, lit); + if (size < 0) + { /* the clause is equivalent to the value true */ + goto skip; + } + if (size == 0) + { /* the clause is equivalent to the value false; this means + that the constraint (1) is infeasible */ + return 2; + } + /* translate the clause to corresponding cover inequality */ + npp_sat_encode_clause(npp, size, lit); +skip: ; + } + return 0; +} + +/*********************************************************************** +* npp_sat_encode_row - encode constraint (row) of general type +* +* PURPOSE +* +* This routine translates to CNF the following constraint (row): +* +* L <= sum a[j] x[j] <= U, (1) +* j +* +* where all x[j] are binary variables. +* +* ALGORITHM +* +* First, the routine performs substitution x[j] = t[j] for j in J+ +* and x[j] = 1 - t[j] for j in J-, where J+ = { j : a[j] > 0 } and +* J- = { j : a[j] < 0 }. This gives: +* +* L <= sum a[j] t[j] + sum a[j] (1 - t[j]) <= U ==> +* j in J+ j in J- +* +* L' <= sum |a[j]| t[j] <= U', (2) +* j +* +* where +* +* L' = L - sum a[j], U' = U - sum a[j]. (3) +* j in J- j in J- +* +* (Actually only new bounds L' and U' are computed.) +* +* Then the routine translates to CNF the following equality: +* +* n +* sum |a[j]| t[j] = sum 2**(k-1) * y[k], (4) +* j k=1 +* +* where y[k] is either some t[j] or a new literal or a constant zero +* (see the routine npp_sat_encode_sum_ax). +* +* Finally, the routine translates to CNF the following conditions: +* +* n +* sum 2**(k-1) * y[k] >= L' (5) +* k=1 +* +* and +* +* n +* sum 2**(k-1) * y[k] <= U' (6) +* k=1 +* +* (see the routines npp_sat_encode_geq and npp_sat_encode_leq). +* +* All resulting clauses are encoded as cover inequalities and included +* into the transformed problem. +* +* Note that on exit the routine removes the specified constraint (row) +* from the original problem. +* +* RETURNS +* +* The routine returns one of the following codes: +* +* 0 - translation was successful; +* 1 - constraint (1) was found infeasible; +* 2 - integer arithmetic error occured. */ + +int npp_sat_encode_row(NPP *npp, NPPROW *row) +{ NPPAIJ *aij; + NPPLIT y[1+NBIT_MAX]; + int n, rhs; + double lb, ub; + /* the row should not be free */ + xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); + /* compute new bounds L' and U' (3) */ + lb = row->lb; + ub = row->ub; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + { if (aij->val < 0.0) + { if (lb != -DBL_MAX) + lb -= aij->val; + if (ub != -DBL_MAX) + ub -= aij->val; + } + } + /* encode the equality (4) */ + n = npp_sat_encode_sum_ax(npp, row, y); + if (n < 0) + return 2; /* integer arithmetic error */ + /* encode the condition (5) */ + if (lb != -DBL_MAX) + { rhs = (int)lb; + if ((double)rhs != lb) + return 2; /* integer arithmetic error */ + if (npp_sat_encode_geq(npp, n, y, rhs) != 0) + return 1; /* original constraint is infeasible */ + } + /* encode the condition (6) */ + if (ub != +DBL_MAX) + { rhs = (int)ub; + if ((double)rhs != ub) + return 2; /* integer arithmetic error */ + if (npp_sat_encode_leq(npp, n, y, rhs) != 0) + return 1; /* original constraint is infeasible */ + } + /* remove the specified row from the problem */ + npp_del_row(npp, row); + return 0; +} + +/*********************************************************************** +* npp_sat_encode_prob - encode 0-1 feasibility problem +* +* This routine translates the specified 0-1 feasibility problem to an +* equivalent SAT-CNF problem. +* +* N.B. Currently this is a very crude implementation. +* +* RETURNS +* +* 0 success; +* +* GLP_ENOPFS primal/integer infeasibility detected; +* +* GLP_ERANGE integer overflow occured. */ + +int npp_sat_encode_prob(NPP *npp) +{ NPPROW *row, *next_row, *prev_row; + NPPCOL *col, *next_col; + int cover = 0, pack = 0, partn = 0, ret; + /* process and remove free rows */ + for (row = npp->r_head; row != NULL; row = next_row) + { next_row = row->next; + if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) + npp_sat_free_row(npp, row); + } + /* process and remove fixed columns */ + for (col = npp->c_head; col != NULL; col = next_col) + { next_col = col->next; + if (col->lb == col->ub) + xassert(npp_sat_fixed_col(npp, col) == 0); + } + /* only binary variables should remain */ + for (col = npp->c_head; col != NULL; col = col->next) + xassert(col->is_int && col->lb == 0.0 && col->ub == 1.0); + /* new rows may be added to the end of the row list, so we walk + from the end to beginning of the list */ + for (row = npp->r_tail; row != NULL; row = prev_row) + { prev_row = row->prev; + /* process special cases */ + ret = npp_sat_is_cover_ineq(npp, row); + if (ret != 0) + { /* row is covering inequality */ + cover++; + /* since it already encodes a clause, just transform it to + canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_cover_ineq(npp, row); + } + xassert(ret == 1); + continue; + } + ret = npp_sat_is_partn_eq(npp, row); + if (ret != 0) + { /* row is partitioning equality */ + NPPROW *cov; + NPPAIJ *aij; + partn++; + /* transform it to canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_partn_eq(npp, row); + } + xassert(ret == 1); + /* and split it into covering and packing inequalities, + both in canonical forms */ + cov = npp_add_row(npp); + cov->lb = row->lb, cov->ub = +DBL_MAX; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + npp_add_aij(npp, cov, aij->col, aij->val); + xassert(npp_sat_is_cover_ineq(npp, cov) == 1); + /* the cover inequality already encodes a clause and do + not need any further processing */ + row->lb = -DBL_MAX; + xassert(npp_sat_is_pack_ineq(npp, row) == 1); + /* the packing inequality will be processed below */ + pack--; + } + ret = npp_sat_is_pack_ineq(npp, row); + if (ret != 0) + { /* row is packing inequality */ + NPPROW *rrr; + int nlit, desired_nlit = 4; + pack++; + /* transform it to canonical form */ + if (ret == 2) + { xassert(npp_sat_reverse_row(npp, row) == 0); + ret = npp_sat_is_pack_ineq(npp, row); + } + xassert(ret == 1); + /* process the packing inequality */ + for (;;) + { /* determine the number of literals in the remaining + inequality */ + nlit = npp_row_nnz(npp, row); + if (nlit <= desired_nlit) + break; + /* split the current inequality into one having not more + than desired_nlit literals and remaining one */ + rrr = npp_sat_split_pack(npp, row, desired_nlit-1); + /* translate the former inequality to CNF and remove it + from the original problem */ + npp_sat_encode_pack(npp, rrr); + } + /* translate the remaining inequality to CNF and remove it + from the original problem */ + npp_sat_encode_pack(npp, row); + continue; + } + /* translate row of general type to CNF and remove it from the + original problem */ + ret = npp_sat_encode_row(npp, row); + if (ret == 0) + ; + else if (ret == 1) + ret = GLP_ENOPFS; + else if (ret == 2) + ret = GLP_ERANGE; + else + xassert(ret != ret); + if (ret != 0) + goto done; + } + ret = 0; + if (cover != 0) + xprintf("%d covering inequalities\n", cover); + if (pack != 0) + xprintf("%d packing inequalities\n", pack); + if (partn != 0) + xprintf("%d partitioning equalities\n", partn); +done: return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/proxy/main.c b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/main.c new file mode 100644 index 000000000..a7d1e2b87 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/main.c @@ -0,0 +1,87 @@ +/* Last update: 08-May-2013 */ + +#include +#include +#include + +#include "glpk.h" +#include "proxy.h" + +/**********************************************************************/ +int main(int argc, char **argv) +/**********************************************************************/ +{ + glp_prob *lp; + int ncols, status; + double *initsol, zstar, *xstar; + + /* check arguments */ + if ( (argc == 1) || (argc > 3) ) { + printf("ERROR: Usage: ts <(possibly) xml initsols>\n" + ); + exit(1); + } + + /* creating the problem */ + lp = glp_create_prob(); + glp_set_prob_name(lp, "Proxy"); + + /* reading the problem */ + glp_term_out(GLP_OFF); +#if 0 /* by mao */ + status = glp_read_lp(lp, NULL, argv[1]); +#else + status = glp_read_mps(lp, GLP_MPS_FILE, NULL, argv[1]); +#endif + glp_term_out(GLP_ON); + if ( status ) { + printf("Problem %s does not exist!!!, status %d\n", + argv[1], status); + exit(1); + } + + ncols = glp_get_num_cols(lp); + + initsol = (double *) calloc(ncols+1, sizeof(double)); + + if (argc == 3) { + FILE *fp=fopen(argv[2],"r"); + char tmp[256]={0x0}; + int counter = 1; + while(fp!=NULL && fgets(tmp, sizeof(tmp),fp)!=NULL) + { + char *valini = strstr(tmp, "value"); + if (valini!=NULL){ + int num; + double dnum; + valini +=7; + sscanf(valini, "%d%*s",&num); + dnum = (double)num; + initsol[counter] = dnum; + counter++; + } + } + fclose(fp); + } + + xstar = (double *) calloc(ncols+1, sizeof(double)); + + if (argc == 3) { + status = proxy(lp, &zstar, xstar, initsol, 0.0, 0, 1); + } + else { + status = proxy(lp, &zstar, xstar, NULL, 0.0, 0, 1); + } + + printf("Status = %d; ZSTAR = %f\n",status,zstar); + /* + int i; + for (i=1; i< ncols+1; i++) { + printf("XSTAR[%d] = %f\n",i, xstar[i]); + } + */ + + glp_delete_prob(lp); + + return 0; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.c b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.c new file mode 100644 index 000000000..7d8900031 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.c @@ -0,0 +1,1073 @@ +/* proxy.c (proximity search heuristic algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Giorgio Sartor <0gioker0@gmail.com>. +* +* Copyright (C) 2013, 2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +* +************************************************************************ +* +* THIS CODE IS AN IMPLEMENTATION OF THE ALGORITHM PROPOSED IN +* +* M. Fischetti, M. Monaci, +* "Proximity Search for 0-1 Mixed-Integer Convex Programming" +* Technical Report DEI, University of Padua, March 2013. +* +* AVAILABLE AT +* http://www.dei.unipd.it/~fisch/papers/proximity_search.pdf +* +* THE CODE HAS BEEN WRITTEN BY GIORGIO SARTOR, " 0gioker0@gmail.com " +* +* BASIC IDEA: +* +* The initial feasible solution x_tilde is defined. This initial +* solution can be found by an ad-hoc heuristic and proxy can be used to +* refine it by exploiting an underlying MIP model whose solution from +* scratch turned out to be problematic. Otherwise, x_tilde can be found +* by running the GLPK mip solver until a first feasible solution is +* found, setting a conservative time limit of 10 minutes (by default). +* Time limit can be modified passing variable tlim [ms]. +* +* Then the cutoff tolerance "delta" is defined. The default tolerance +* is 1% of the last feasible solution obj value--rounded to integer if +* all the variables and obj coefficients are integer. +* +* Next, the objective function c' x is replaced by the Hamming distance +* between x (the actual obj coefficients) and x_tilde (the given +* solution). Distance is only computed wrt the binary variables. +* +* The GLPK solver is then invoked to hopefully find a new incumbent +* x_star with cost c' x_star <= c' x_tilde - delta. A crucial property +* here is that the root-node solution of the LP relaxation is expected +* to be not too different from x_tilde, as this latter solution would +* be optimal without the cutoff constraint, that for a small delta can +* typically be fulfilled with just local adjustments. +* +* If no new solution x_star is found within the time limit the +* algorithm stops. Of course, if the MIP solver proved infeasibility +* for the given delta, we have that c' x_tilde - delta is a valid lower +* bound (in case of minimazation) on the optimal value of the original +* MIP. +* +* The new solution x_star, if any, is possibly improved by solving a +* simplified problem (refinement) where all binary variables have been +* fixed to their value in x_star so as to find the best solution within +* the neighborhood. +* +* Finally, the approach is reapplied on x_star (that replaces x_tilde) +* so as to recenter the distance Hamming function and by modifying the +* cutoff tolerance delta. +* +* In this way, there will be a series of hopefully not-too-difficult +* sub-MIPs to solve, each leading to an improvement of the incumbent. +* More aggressive policies on the definition of tolerance delta can +* lead to a better performance, but would require an ad-hoc tuning. +* +************************************************************************ +* +* int proxy(glp_prob *lp, double *zstar, double *xstar, +* const double[] initsol, double rel_impr, int tlim, +* int verbose) +* +* lp : GLPK problem pointer to a MIP with binary variables +* +* zstar : the value of objective function of the best solution found +* +* xstar : best solution with components xstar[1],...,xstar[ncols] +* +* initsol : pointer to a initial feasible solution, see +* glp_ios_heur_sol +* If initsol = NULL, the procedure finds the first solution +* by itself. +* +* rel_impr : minimum relative obj improvement to be achieved at each +* internal step; if <= 0.0 a default value of 0.01 (1%) is +* used; for some problems (e.g., set covering with small +* integer costs) a more-conservative choice of 0.001 (0.1%) +* can lead to a better final solution; values larger than +* 0.05 (5%) are typically too aggressive and do not work +* well. +* +* tlim : time limit to find a new solution, in ms. +* If tlim = 0, it is set to its default value, 600000 ms +* +* verbose : if 1 the output is activated. If 0 only errors are +* displayed +* +* The procedure returns -1 if an error occurred, 0 otherwise (possibly, +* time limit) +* +***********************************************************************/ + +/**********************************************************************/ +/* 1. INCLUDE */ +/**********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "proxy.h" + +/**********************************************************************/ +/* 2. PARAMETERS AND CONSTANTS */ +/**********************************************************************/ + +#define TDAY 86400.0 +#define TRUE 1 +#define FALSE 0 +#define EPS 1e-6 +#define RINF 1e38 +#define MAXVAL 1e20 +#define MINVAL -1e20 +#if 0 /* by gioker */ + #define PROXY_DEBUG +#endif + +/**********************************************************************/ +/* 3. GLOBAL VARIABLES */ +/**********************************************************************/ + +struct csa { + +int integer_obj; /* TRUE if each feasible solution has an + integral cost */ +int b_vars_exist; /* TRUE if there is at least one binary + variable in the problem */ +int i_vars_exist; /* TRUE if there is at least one general + integer variable in the problem */ +const double *startsol; /* Pointer to the initial solution */ + +int *ckind; /* Store the kind of the structural variables + of the problem */ +double *clb; /* Store the lower bound on the structural + variables of the problem */ +double *cub; /* Store the upper bound on the structural + variables of the problem */ +double *true_obj; /* Store the obj coefficients of the problem */ + +int dir; /* Minimization or maximization problem */ +int ncols; /* Number of structural variables of the + problem */ + +time_t GLOtstart; /* starting time of the algorithm */ + +glp_prob *lp_ref; /* glp problem for refining only*/ + +}; + +/**********************************************************************/ +/* 4. FUNCTIONS PROTOTYPES */ +/**********************************************************************/ + +static void callback(glp_tree *tree, void *info); +static void get_info(struct csa *csa, glp_prob *lp); +static int is_integer(struct csa *csa); +static void check_integrality(struct csa *csa); +static int check_ref(struct csa *csa, glp_prob *lp, double *xref); +static double second(void); +static int add_cutoff(struct csa *csa, glp_prob *lp); +static void get_sol(struct csa *csa, glp_prob *lp, double *xstar); +static double elapsed_time(struct csa *csa); +static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, + int *ckind, double *clb, double *cub); +static double update_cutoff(struct csa *csa, glp_prob *lp, + double zstar, int index, double rel_impr); +static double compute_delta(struct csa *csa, double z, + double rel_impr); +static double objval(int ncols, double *x, double *true_obj); +static void array_copy(int begin, int end, double *source, + double *destination); +static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, + int *ckind, double *xref, int *tlim, int tref_lim, + int verbose); +static void deallocate(struct csa *csa, int refine); + +/**********************************************************************/ +/* 5. FUNCTIONS */ +/**********************************************************************/ + +int proxy(glp_prob *lp, double *zfinal, double *xfinal, + const double initsol[], double rel_impr, int tlim, + int verbose) + +{ struct csa csa_, *csa = &csa_; + glp_iocp parm; + glp_smcp parm_lp; + size_t tpeak; + int refine, tref_lim, err, cutoff_row, niter, status, i, tout; + double *xref, *xstar, zstar, tela, cutoff, zz; + + memset(csa, 0, sizeof(struct csa)); + + + /********** **********/ + /********** RETRIEVING PROBLEM INFO **********/ + /********** **********/ + + /* getting problem direction (min or max) */ + csa->dir = glp_get_obj_dir(lp); + + /* getting number of variables */ + csa->ncols = glp_get_num_cols(lp); + + /* getting kind, bounds and obj coefficient of each variable + information is stored in ckind, cub, clb, true_obj */ + get_info(csa, lp); + + /* checking if the objective function is always integral */ + check_integrality(csa); + + /* Proximity search cannot be used if there are no binary + variables */ + if (csa->b_vars_exist == FALSE) { + if (verbose) { + xprintf("The problem has not binary variables. Proximity se" + "arch cannot be used.\n"); + } + tfree(csa->ckind); + tfree(csa->clb); + tfree(csa->cub); + tfree(csa->true_obj); + return -1; + } + + /* checking if the problem needs refinement, i.e., not all + variables are binary. If so, the routine creates a copy of the + lp problem named lp_ref and initializes the solution xref to + zero. */ + xref = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(xref, 0, sizeof(double)*(csa->ncols+1)); +#endif + refine = check_ref(csa, lp, xref); +#ifdef PROXY_DEBUG + xprintf("REFINE = %d\n",refine); +#endif + + /* Initializing the solution */ + xstar = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(xstar, 0, sizeof(double)*(csa->ncols+1)); +#endif + + /********** **********/ + /********** FINDING FIRST SOLUTION **********/ + /********** **********/ + + if (verbose) { + xprintf("Applying PROXY heuristic...\n"); + } + + /* get the initial time */ + csa->GLOtstart = second(); + + /* setting the optimization parameters */ + glp_init_iocp(&parm); + glp_init_smcp(&parm_lp); +#if 0 /* by gioker */ + /* Preprocessing should be disabled because the mip passed + to proxy is already preprocessed */ + parm.presolve = GLP_ON; +#endif +#if 1 /* by mao */ + /* best projection backtracking seems to be more efficient to find + any integer feasible solution */ + parm.bt_tech = GLP_BT_BPH; +#endif + + /* Setting the default value of the minimum relative improvement + to 1% */ + if ( rel_impr <= 0.0 ) { + rel_impr = 0.01; + } + + /* Setting the default value of time limit to 10 minutes */ + if (tlim <= 0) { + tlim = INT_MAX; + } + if (verbose) { + xprintf("Proxy's time limit set to %d seconds.\n",tlim/1000); + xprintf("Proxy's relative improvement " + "set to %2.2lf %c.\n",rel_impr*100,37); + } + + parm_lp.tm_lim = tlim; + + parm.mip_gap = 9999999.9; /* to stop the optimization at the first + feasible solution found */ + + /* finding the first solution */ + if (verbose) { + xprintf("Searching for a feasible solution...\n"); + } + + /* verifying the existence of an input starting solution */ + if (initsol != NULL) { + csa->startsol = initsol; + parm.cb_func = callback; + parm.cb_info = csa; + if (verbose) { + xprintf("Input solution found.\n"); + } + } + + tout = glp_term_out(GLP_OFF); + err = glp_simplex(lp,&parm_lp); + glp_term_out(tout); + + status = glp_get_status(lp); + + if (status != GLP_OPT) { + if (verbose) { + xprintf("Proxy heuristic terminated.\n"); + } +#ifdef PROXY_DEBUG + /* For debug only */ + xprintf("GLP_SIMPLEX status = %d\n",status); + xprintf("GLP_SIMPLEX error code = %d\n",err); +#endif + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy could not " + "find optimal solution to LP relaxation.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + parm.tm_lim = tlim - tela*1000; + tref_lim = (tlim - tela *1000) / 20; + + tout = glp_term_out(GLP_OFF); + err = glp_intopt(lp, &parm); + glp_term_out(tout); + + status = glp_mip_status(lp); + + /***** If no solution was found *****/ + + if (status == GLP_NOFEAS || status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy could not " + "find an initial integer feasible solution.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + } + else { + if (verbose) { + xprintf("Proxy could not " + "find an initial integer feasible solution.\n"); + xprintf("Proxy heuristic aborted.\n"); + } + } + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + return -1; + } + + /* getting the first solution and its value */ + get_sol(csa, lp,xstar); + zstar = glp_mip_obj_val(lp); + + if (verbose) { + xprintf(">>>>> first solution = %e;\n", zstar); + } + + /* If a feasible solution was found but the time limit is + exceeded */ + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic terminated.\n"); + } + goto done; + } + + tela = elapsed_time(csa); + tpeak = 0; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + if (verbose) { + xprintf("Time used: %3.1lf secs. Memory used: %2.1lf Mb\n", + tela,(double)tpeak/1048576); + xprintf("Starting proximity search...\n"); + } + + /********** **********/ + /********** PREPARING THE PROBLEM FOR PROXY **********/ + /********** **********/ + + /* adding a dummy cutoff constraint */ + cutoff_row = add_cutoff(csa, lp); + + /* proximity search needs minimization direction + even if the problem is a maximization one */ + if (csa->dir == GLP_MAX) { + glp_set_obj_dir(lp, GLP_MIN); + } + + /********** **********/ + /********** STARTING PROXIMITY SEARCH **********/ + /********** **********/ + + + niter = 0; + + while (TRUE) { + niter++; + + /********** CHANGING THE OBJ FUNCTION **********/ + + redefine_obj(lp,xstar, csa->ncols, csa->ckind, csa->clb, + csa->cub); + + /********** UPDATING THE CUTOFF CONSTRAINT **********/ + + cutoff = update_cutoff(csa, lp,zstar, cutoff_row, rel_impr); + +#ifdef PROXY_DEBUG + xprintf("TRUE_OBJ[0] = %f\n",csa->true_obj[0]); + xprintf("ZSTAR = %f\n",zstar); + xprintf("CUTOFF = %f\n",cutoff); +#endif + + /********** SEARCHING FOR A BETTER SOLUTION **********/ + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + goto done; + } +#ifdef PROXY_DEBUG + xprintf("TELA = %3.1lf\n",tela*1000); + xprintf("TLIM = %3.1lf\n",tlim - tela*1000); +#endif + parm_lp.tm_lim = tlim -tela*1000; + + tout = glp_term_out(GLP_OFF); + err = glp_simplex(lp,&parm_lp); + glp_term_out(tout); + + status = glp_get_status(lp); + + if (status != GLP_OPT) { + if (status == GLP_NOFEAS) { + if (verbose) { + xprintf("Bound exceeded = %f. ",cutoff); + } + } + if (verbose) { + xprintf("Proxy heuristic terminated.\n"); + } +#ifdef PROXY_DEBUG + xprintf("GLP_SIMPLEX status = %d\n",status); + xprintf("GLP_SIMPLEX error code = %d\n",err); +#endif + goto done; + } + + tela = elapsed_time(csa); + if (tlim-tela*1000 <= 0) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + goto done; + } + parm.tm_lim = tlim - tela*1000; + parm.cb_func = NULL; +#if 0 /* by gioker */ + /* Preprocessing should be disabled because the mip passed + to proxy is already preprocessed */ + parm.presolve = GLP_ON; +#endif + tout = glp_term_out(GLP_OFF); + err = glp_intopt(lp, &parm); + glp_term_out(tout); + + /********** MANAGEMENT OF THE SOLUTION **********/ + + status = glp_mip_status(lp); + + /***** No feasible solutions *****/ + + if (status == GLP_NOFEAS) { + if (verbose) { + xprintf("Bound exceeded = %f. Proxy heuristic " + "terminated.\n",cutoff); + } + goto done; + } + + /***** Undefined solution *****/ + + if (status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { + if (verbose) { + xprintf("Time limit exceeded. Proxy heuristic " + "terminated.\n"); + } + } + else { + if (verbose) { + xprintf("Proxy terminated unexpectedly.\n"); +#ifdef PROXY_DEBUG + xprintf("GLP_INTOPT error code = %d\n",err); +#endif + } + } + goto done; + } + + /***** Feasible solution *****/ + + if ((status == GLP_FEAS) || (status == GLP_OPT)) { + + /* getting the solution and computing its value */ + get_sol(csa, lp,xstar); + zz = objval(csa->ncols, xstar, csa->true_obj); + + /* Comparing the incumbent solution with the current best + one */ +#ifdef PROXY_DEBUG + xprintf("ZZ = %f\n",zz); + xprintf("ZSTAR = %f\n",zstar); + xprintf("REFINE = %d\n",refine); +#endif + if (((zzdir == GLP_MIN)) || + ((zz>zstar) && (csa->dir == GLP_MAX))) { + + /* refining (possibly) the solution */ + if (refine) { + + /* copying the incumbent solution in the refinement + one */ + array_copy(1, csa->ncols +1, xstar, xref); + err = do_refine(csa, csa->lp_ref, csa->ncols, + csa->ckind, xref, &tlim, tref_lim, verbose); + if (!err) { + double zref = objval(csa->ncols, xref, + csa->true_obj); + if (((zrefdir == GLP_MIN)) || + ((zref>zz) && (csa->dir == GLP_MAX))) { + zz = zref; + /* copying the refinement solution in the + incumbent one */ + array_copy(1, csa->ncols +1, xref, xstar); + } + } + } + zstar = zz; + tela = elapsed_time(csa); + if (verbose) { + xprintf(">>>>> it: %3d: mip = %e; elapsed time " + "%3.1lf sec.s\n", niter,zstar,tela); + } + } + } + } + +done: + tela = elapsed_time(csa); + glp_mem_usage(NULL, NULL, NULL, &tpeak); + if (verbose) { + xprintf("Time used: %3.1lf. Memory used: %2.1lf Mb\n", + tela,(double)tpeak/1048576); + } + + + /* Exporting solution and obj val */ + *zfinal = zstar; + + for (i=1; i < (csa->ncols + 1); i++) { + xfinal[i]=xstar[i]; + } + + /* Freeing allocated memory */ + tfree(xref); + tfree(xstar); + deallocate(csa, refine); + + return 0; +} + +/**********************************************************************/ +static void callback(glp_tree *tree, void *info){ +/**********************************************************************/ + struct csa *csa = info; + switch(glp_ios_reason(tree)) { + case GLP_IHEUR: + glp_ios_heur_sol(tree, csa->startsol); + break; + default: break; + } +} + +/**********************************************************************/ +static void get_info(struct csa *csa, glp_prob *lp) +/**********************************************************************/ +{ + int i; + + /* Storing helpful info of the problem */ + + csa->ckind = talloc(csa->ncols+1, int); +#if 0 /* by mao */ + memset(csa->ckind, 0, sizeof(int)*(csa->ncols+1)); +#endif + csa->clb = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->clb, 0, sizeof(double)*(csa->ncols+1)); +#endif + csa->cub = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->cub, 0, sizeof(double)*(csa->ncols+1)); +#endif + csa->true_obj = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(csa->true_obj, 0, sizeof(double)*(csa->ncols+1)); +#endif + for( i = 1 ; i < (csa->ncols + 1); i++ ) { + csa->ckind[i] = glp_get_col_kind(lp, i); + csa->clb[i] = glp_get_col_lb(lp, i); + csa->cub[i] = glp_get_col_ub(lp, i); + csa->true_obj[i] = glp_get_obj_coef(lp, i); + } + csa->true_obj[0] = glp_get_obj_coef(lp, 0); +} + +/**********************************************************************/ +static int is_integer(struct csa *csa) +/**********************************************************************/ +{ + int i; + csa->integer_obj = TRUE; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if (fabs(csa->true_obj[i]) > INT_MAX ) { + csa->integer_obj = FALSE; + } + if (fabs(csa->true_obj[i]) <= INT_MAX) { + double tmp, rem; + if (fabs(csa->true_obj[i]) - floor(fabs(csa->true_obj[i])) + < 0.5) { + tmp = floor(fabs(csa->true_obj[i])); + } + else { + tmp = ceil(fabs(csa->true_obj[i])); + } + rem = fabs(csa->true_obj[i]) - tmp; + rem = fabs(rem); + if (rem > EPS) { + csa->integer_obj = FALSE; + } + + } + } + return csa->integer_obj; +} + +/**********************************************************************/ +static void check_integrality(struct csa *csa) +/**********************************************************************/ +{ + /* + Checking if the problem has binary, integer or continuos variables. + integer_obj is TRUE if the problem has no continuous variables + and all the obj coefficients are integer (and < INT_MAX). + */ + + int i; + csa->integer_obj = is_integer(csa); + csa->b_vars_exist = FALSE; + csa->i_vars_exist = FALSE; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( csa->ckind[i] == GLP_IV ){ + csa->i_vars_exist = TRUE; + continue; + } + if ( csa->ckind[i] == GLP_BV ){ + csa->b_vars_exist =TRUE; + continue; + } + csa->integer_obj = FALSE; + } +} + +/**********************************************************************/ +static int check_ref(struct csa *csa, glp_prob *lp, double *xref) +/**********************************************************************/ +{ + /* + checking if the problem has continuos or integer variables. If so, + refinement is prepared. + */ + int refine = FALSE; + int i; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( csa->ckind[i] != GLP_BV) { + refine = TRUE; + break; + } + } + + /* possibly creating a mip clone for refinement only */ + if ( refine ) { + csa->lp_ref = glp_create_prob(); + glp_copy_prob(csa->lp_ref, lp, GLP_ON); + } + + return refine; +} + +/**********************************************************************/ +static double second(void) +/**********************************************************************/ +{ +#if 0 /* by mao */ + return ((double)clock()/(double)CLOCKS_PER_SEC); +#else + return xtime() / 1000.0; +#endif +} + +/**********************************************************************/ +static int add_cutoff(struct csa *csa, glp_prob *lp) +/**********************************************************************/ +{ + /* + Adding a cutoff constraint to set an upper bound (in case of + minimaztion) on the obj value of the next solution, i.e., the next + value of the true obj function that we would like to find + */ + + /* store non-zero coefficients in the objective function */ + int *obj_index = talloc(csa->ncols+1, int); +#if 0 /* by mao */ + memset(obj_index, 0, sizeof(int)*(csa->ncols+1)); +#endif + double *obj_value = talloc(csa->ncols+1, double); +#if 0 /* by mao */ + memset(obj_value, 0, sizeof(double)*(csa->ncols+1)); +#endif + int obj_nzcnt = 0; + int i, irow; + const char *rowname; + for ( i = 1; i < (csa->ncols + 1); i++ ) { + if ( fabs(csa->true_obj[i]) > EPS ) { + obj_nzcnt++; + obj_index[obj_nzcnt] = i; + obj_value[obj_nzcnt] = csa->true_obj[i]; + } + } + + irow = glp_add_rows(lp, 1); + rowname = "Cutoff"; + glp_set_row_name(lp, irow, rowname); + if (csa->dir == GLP_MIN) { + /* minimization problem */ + glp_set_row_bnds(lp, irow, GLP_UP, MAXVAL, MAXVAL); + } + else { + /* maximization problem */ + glp_set_row_bnds(lp, irow, GLP_LO, MINVAL, MINVAL); + } + + glp_set_mat_row(lp, irow, obj_nzcnt, obj_index, obj_value); + + tfree(obj_index); + tfree(obj_value); + + return irow; +} + +/**********************************************************************/ +static void get_sol(struct csa *csa, glp_prob *lp, double *xstar) +/**********************************************************************/ +{ + /* Retrieving and storing the coefficients of the solution */ + + int i; + for (i = 1; i < (csa->ncols +1); i++) { + xstar[i] = glp_mip_col_val(lp, i); + } +} + +/**********************************************************************/ +static double elapsed_time(struct csa *csa) +/**********************************************************************/ +{ + double tela = second() - csa->GLOtstart; + if ( tela < 0 ) tela += TDAY; + return(tela); +} + +/**********************************************************************/ +static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, + int *ckind, double *clb, double *cub) +/**********************************************************************/ + +/* + Redefine the lp objective function obj as the distance-to-integrality + (Hamming distance) from xtilde (the incumbent feasible solution), wrt + to binary vars only + */ + +{ + int j; + double *delta = talloc(ncols+1, double); +#if 0 /* by mao */ + memset(delta, 0, sizeof(double)*(ncols+1)); +#endif + + for ( j = 1; j < (ncols +1); j++ ) { + delta[j] = 0.0; + /* skip continuous variables */ + if ( ckind[j] == GLP_CV ) continue; + + /* skip integer variables that have been fixed */ + if ( cub[j]-clb[j] < 0.5 ) continue; + + /* binary variable */ + if ( ckind[j] == GLP_BV ) { + if ( xtilde[j] > 0.5 ) { + delta[j] = -1.0; + } + else { + delta[j] = 1.0; + } + } + } + + /* changing the obj coeff. for all variables, including continuous + ones */ + for ( j = 1; j < (ncols +1); j++ ) { + glp_set_obj_coef(lp, j, delta[j]); + } + glp_set_obj_coef(lp, 0, 0.0); + + tfree(delta); +} + +/**********************************************************************/ +static double update_cutoff(struct csa *csa, glp_prob *lp, + double zstar, int cutoff_row, + double rel_impr) +/**********************************************************************/ +{ + /* + Updating the cutoff constraint with the value we would like to + find during the next optimization + */ + double cutoff; + zstar -= csa->true_obj[0]; + if (csa->dir == GLP_MIN) { + cutoff = zstar - compute_delta(csa, zstar, rel_impr); + glp_set_row_bnds(lp, cutoff_row, GLP_UP, cutoff, cutoff); + } + else { + cutoff = zstar + compute_delta(csa, zstar, rel_impr); + glp_set_row_bnds(lp, cutoff_row, GLP_LO, cutoff, cutoff); + } + + return cutoff; +} + +/**********************************************************************/ +static double compute_delta(struct csa *csa, double z, double rel_impr) +/**********************************************************************/ +{ + /* Computing the offset for the next best solution */ + + double delta = rel_impr * fabs(z); + if ( csa->integer_obj ) delta = ceil(delta); + + return(delta); +} + +/**********************************************************************/ +static double objval(int ncols, double *x, double *true_obj) +/**********************************************************************/ +{ + /* Computing the true cost of x (using the original obj coeff.s) */ + + int j; + double z = 0.0; + for ( j = 1; j < (ncols +1); j++ ) { + z += x[j] * true_obj[j]; + } + return z + true_obj[0]; +} + +/**********************************************************************/ +static void array_copy(int begin, int end, double *source, + double *destination) +/**********************************************************************/ +{ + int i; + for (i = begin; i < end; i++) { + destination[i] = source[i]; + } +} +/**********************************************************************/ +static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, + int *ckind, double *xref, int *tlim, int tref_lim, + int verbose) +/**********************************************************************/ +{ + /* + Refinement is applied when the variables of the problem are not + all binary. Binary variables are fixed to their value and + remaining ones are optimized. If there are only continuos + variables (in addition to those binary) the problem becomes just + an LP. Otherwise, it remains a MIP but of smaller size. + */ + + int j, tout; + double refineStart = second(); + double val, tela, tlimit; + + if ( glp_get_num_cols(lp_ref) != ncols ) { + if (verbose) { + xprintf("Error in Proxy refinement: "); + xprintf("wrong number of columns (%d vs %d).\n", + ncols, glp_get_num_cols(lp_ref)); + } + return 1; + } + + val = -1.0; + + /* fixing all binary variables to their current value in xref */ + for ( j = 1; j < (ncols + 1); j++ ) { + if ( ckind[j] == GLP_BV ) { + val = 0.0; + if ( xref[j] > 0.5 ) val = 1.0; + glp_set_col_bnds(lp_ref, j, GLP_FX, val, val); + } + } + + /* re-optimizing (refining) if some bound has been changed */ + if ( val > -1.0 ) { + glp_iocp parm_ref; + glp_smcp parm_ref_lp; + int err, status; + + glp_init_iocp(&parm_ref); + parm_ref.presolve = GLP_ON; + glp_init_smcp(&parm_ref_lp); + /* + If there are no general integer variable the problem becomes + an LP (after fixing the binary variables) and can be solved + quickly. Otherwise the problem is still a MIP problem and a + timelimit has to be set. + */ + parm_ref.tm_lim = tref_lim; + if (parm_ref.tm_lim > *tlim) { + parm_ref.tm_lim = *tlim; + } + parm_ref_lp.tm_lim = parm_ref.tm_lim; +#ifdef PROXY_DEBUG + xprintf("***** REFINING *****\n"); +#endif + tout = glp_term_out(GLP_OFF); + if (csa->i_vars_exist == TRUE) { + err = glp_intopt(lp_ref, &parm_ref); + } + else { + err = glp_simplex(lp_ref, &parm_ref_lp); + } + glp_term_out(tout); + + if (csa->i_vars_exist == TRUE) { + status = glp_mip_status(lp_ref); + } + else { + status = glp_get_status(lp_ref); + } + +#if 1 /* 29/II-2016 by mao as reported by Chris */ + switch (status) + { case GLP_OPT: + case GLP_FEAS: + break; + default: + status = GLP_UNDEF; + break; + } +#endif + +#ifdef PROXY_DEBUG + xprintf("STATUS REFINING = %d\n",status); +#endif + if (status == GLP_UNDEF) { + if (err == GLP_ETMLIM) { +#ifdef PROXY_DEBUG + xprintf("Time limit exceeded on Proxy refining.\n"); +#endif + return 1; + } + } + for( j = 1 ; j < (ncols + 1); j++ ){ + if (ckind[j] != GLP_BV) { + if (csa->i_vars_exist == TRUE) { + xref[j] = glp_mip_col_val(lp_ref, j); + } + else{ + xref[j] = glp_get_col_prim(lp_ref, j); + } + } + } + } + tela = second() - refineStart; +#ifdef PROXY_DEBUG + xprintf("REFINE TELA = %3.1lf\n",tela*1000); +#endif + return 0; +} +/**********************************************************************/ +static void deallocate(struct csa *csa, int refine) +/**********************************************************************/ +{ + /* Deallocating routine */ + + if (refine) { + glp_delete_prob(csa->lp_ref); + } + + tfree(csa->ckind); + tfree(csa->clb); + tfree(csa->cub); + tfree(csa->true_obj); + +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.h b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.h new file mode 100644 index 000000000..a91e36f2d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy.h @@ -0,0 +1,36 @@ +/* proxy.h (proximity search heuristic algorithm) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Author: Giorgio Sartor <0gioker0@gmail.com>. +* +* Copyright (C) 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef PROXY_H +#define PROXY_H + +#define proxy _glp_proxy +int proxy(glp_prob *lp, double *zstar, double *xstar, + const double initsol[], double rel_impr, int tlim, + int verbose); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy1.c b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy1.c new file mode 100644 index 000000000..5f9850d42 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/proxy/proxy1.c @@ -0,0 +1,88 @@ +/* proxy1.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013, 2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "ios.h" +#include "proxy.h" + +void ios_proxy_heur(glp_tree *T) +{ glp_prob *prob; + int j, status; + double *xstar, zstar; + /* this heuristic is applied only once on the root level */ + if (!(T->curr->level == 0 && T->curr->solved == 1)) + goto done; + prob = glp_create_prob(); + glp_copy_prob(prob, T->mip, 0); + xstar = xcalloc(1+prob->n, sizeof(double)); + for (j = 1; j <= prob->n; j++) + xstar[j] = 0.0; + if (T->mip->mip_stat != GLP_FEAS) + status = proxy(prob, &zstar, xstar, NULL, 0.0, + T->parm->ps_tm_lim, 1); + else + { double *xinit = xcalloc(1+prob->n, sizeof(double)); + for (j = 1; j <= prob->n; j++) + xinit[j] = T->mip->col[j]->mipx; + status = proxy(prob, &zstar, xstar, xinit, 0.0, + T->parm->ps_tm_lim, 1); + xfree(xinit); + } + if (status == 0) +#if 0 /* 17/III-2016 */ + glp_ios_heur_sol(T, xstar); +#else + { /* sometimes the proxy heuristic reports a wrong solution, so + * make sure that the solution is really integer feasible */ + int i, feas1, feas2, ae_ind, re_ind; + double ae_max, re_max; + glp_copy_prob(prob, T->mip, 0); + for (j = 1; j <= prob->n; j++) + prob->col[j]->mipx = xstar[j]; + for (i = 1; i <= prob->m; i++) + { GLPROW *row; + GLPAIJ *aij; + row = prob->row[i]; + row->mipx = 0.0; + for (aij = row->ptr; aij != NULL; aij = aij->r_next) + row->mipx += aij->val * aij->col->mipx; + } + glp_check_kkt(prob, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, + &re_max, &re_ind); + feas1 = (re_max <= 1e-6); + glp_check_kkt(prob, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, + &re_max, &re_ind); + feas2 = (re_max <= 1e-6); + if (feas1 && feas2) + glp_ios_heur_sol(T, xstar); + else + xprintf("WARNING: PROXY HEURISTIC REPORTED WRONG SOLUTION; " + "SOLUTION REJECTED\n"); + } +#endif + xfree(xstar); + glp_delete_prob(prob); +done: return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/simplex.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/simplex.h new file mode 100644 index 000000000..9a5acdb20 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/simplex.h @@ -0,0 +1,39 @@ +/* simplex.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SIMPLEX_H +#define SIMPLEX_H + +#include "prob.h" + +#define spx_primal _glp_spx_primal +int spx_primal(glp_prob *P, const glp_smcp *parm); +/* driver to the primal simplex method */ + +#define spy_dual _glp_spy_dual +int spy_dual(glp_prob *P, const glp_smcp *parm); +/* driver to the dual simplex method */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.c new file mode 100644 index 000000000..3570a18c9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.c @@ -0,0 +1,265 @@ +/* spxat.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxat.h" + +/*********************************************************************** +* spx_alloc_at - allocate constraint matrix in sparse row-wise format +* +* This routine allocates the memory for arrays needed to represent the +* constraint matrix in sparse row-wise format. */ + +void spx_alloc_at(SPXLP *lp, SPXAT *at) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + at->ptr = talloc(1+m+1, int); + at->ind = talloc(1+nnz, int); + at->val = talloc(1+nnz, double); + at->work = talloc(1+n, double); + return; +} + +/*********************************************************************** +* spx_build_at - build constraint matrix in sparse row-wise format +* +* This routine builds sparse row-wise representation of the constraint +* matrix A using its sparse column-wise representation stored in the +* lp object, and stores the result in the at object. */ + +void spx_build_at(SPXLP *lp, SPXAT *at) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *AT_ptr = at->ptr; + int *AT_ind = at->ind; + double *AT_val = at->val; + int i, k, ptr, end, pos; + /* calculate AT_ptr[i] = number of non-zeros in i-th row */ + memset(&AT_ptr[1], 0, m * sizeof(int)); + for (k = 1; k <= n; k++) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + AT_ptr[A_ind[ptr]]++; + } + /* set AT_ptr[i] to position after last element in i-th row */ + AT_ptr[1]++; + for (i = 2; i <= m; i++) + AT_ptr[i] += AT_ptr[i-1]; + xassert(AT_ptr[m] == nnz+1); + AT_ptr[m+1] = nnz+1; + /* build row-wise representation and re-arrange AT_ptr[i] */ + for (k = n; k >= 1; k--) + { /* copy elements from k-th column to corresponding rows */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { pos = --AT_ptr[A_ind[ptr]]; + AT_ind[pos] = k; + AT_val[pos] = A_val[ptr]; + } + } + xassert(AT_ptr[1] == 1); + return; +} + +/*********************************************************************** +* spx_at_prod - compute product y := y + s * A'* x +* +* This routine computes the product: +* +* y := y + s * A'* x, +* +* where A' is a matrix transposed to the mxn-matrix A of constraint +* coefficients, x is a m-vector, s is a scalar, y is a n-vector. +* +* The routine uses the row-wise representation of the matrix A and +* computes the product as a linear combination: +* +* y := y + s * (A'[1] * x[1] + ... + A'[m] * x[m]), +* +* where A'[i] is i-th row of A, 1 <= i <= m. */ + +void spx_at_prod(SPXLP *lp, SPXAT *at, double y[/*1+n*/], double s, + const double x[/*1+m*/]) +{ int m = lp->m; + int *AT_ptr = at->ptr; + int *AT_ind = at->ind; + double *AT_val = at->val; + int i, ptr, end; + double t; + for (i = 1; i <= m; i++) + { if (x[i] != 0.0) + { /* y := y + s * (i-th row of A) * x[i] */ + t = s * x[i]; + ptr = AT_ptr[i]; + end = AT_ptr[i+1]; + for (; ptr < end; ptr++) + y[AT_ind[ptr]] += AT_val[ptr] * t; + } + } + return; +} + +/*********************************************************************** +* spx_nt_prod1 - compute product y := y + s * N'* x +* +* This routine computes the product: +* +* y := y + s * N'* x, +* +* where N' is a matrix transposed to the mx(n-m)-matrix N composed +* from non-basic columns of the constraint matrix A, x is a m-vector, +* s is a scalar, y is (n-m)-vector. +* +* If the flag ign is non-zero, the routine ignores the input content +* of the array y assuming that y = 0. */ + +void spx_nt_prod1(SPXLP *lp, SPXAT *at, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + double *work = at->work; + int j, k; + for (k = 1; k <= n; k++) + work[k] = 0.0; + if (!ign) + { for (j = 1; j <= n-m; j++) + work[head[m+j]] = y[j]; + } + spx_at_prod(lp, at, work, s, x); + for (j = 1; j <= n-m; j++) + y[j] = work[head[m+j]]; + return; +} + +/*********************************************************************** +* spx_eval_trow1 - compute i-th row of simplex table +* +* This routine computes i-th row of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= i <= m, using representation of +* the constraint matrix A in row-wise format. +* +* The vector rho = (rho[j]), which is i-th row of the basis inverse +* inv(B), should be previously computed with the routine spx_eval_rho. +* It is assumed that elements of this vector are stored in the array +* locations rho[1], ..., rho[m]. +* +* There exist two ways to compute the simplex table row. +* +* 1. T[i,j], j = 1,...,n-m, is computed as inner product: +* +* m +* T[i,j] = - sum a[i,k] * rho[i], +* i=1 +* +* where N[j] = A[k] is a column of the constraint matrix corresponding +* to non-basic variable xN[j]. The estimated number of operations in +* this case is: +* +* n1 = (n - m) * (nnz(A) / n), +* +* (n - m) is the number of columns of N, nnz(A) / n is the average +* number of non-zeros in one column of A and, therefore, of N. +* +* 2. The simplex table row is computed as part of a linear combination +* of rows of A with coefficients rho[i] != 0. The estimated number +* of operations in this case is: +* +* n2 = nnz(rho) * (nnz(A) / m), +* +* where nnz(rho) is the number of non-zeros in the vector rho, +* nnz(A) / m is the average number of non-zeros in one row of A. +* +* If n1 < n2, the routine computes the simples table row using the +* first way (like the routine spx_eval_trow). Otherwise, the routine +* uses the second way calling the routine spx_nt_prod1. +* +* On exit components of the simplex table row are stored in the array +* locations trow[1], ... trow[n-m]. */ + +void spx_eval_trow1(SPXLP *lp, SPXAT *at, const double rho[/*1+m*/], + double trow[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int i, j, nnz_rho; + double cnt1, cnt2; + /* determine nnz(rho) */ + nnz_rho = 0; + for (i = 1; i <= m; i++) + { if (rho[i] != 0.0) + nnz_rho++; + } + /* estimate the number of operations for both ways */ + cnt1 = (double)(n - m) * ((double)nnz / (double)n); + cnt2 = (double)nnz_rho * ((double)nnz / (double)m); + /* compute i-th row of simplex table */ + if (cnt1 < cnt2) + { /* as inner products */ + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *head = lp->head; + int k, ptr, end; + double tij; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* compute t[i,j] = - N'[j] * pi */ + tij = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tij -= A_val[ptr] * rho[A_ind[ptr]]; + trow[j] = tij; + } + } + else + { /* as linear combination */ + spx_nt_prod1(lp, at, trow, 1, -1.0, rho); + } + return; +} + +/*********************************************************************** +* spx_free_at - deallocate constraint matrix in sparse row-wise format +* +* This routine deallocates the memory used for arrays of the program +* object at. */ + +void spx_free_at(SPXLP *lp, SPXAT *at) +{ xassert(lp == lp); + tfree(at->ptr); + tfree(at->ind); + tfree(at->val); + tfree(at->work); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.h new file mode 100644 index 000000000..98d5b0033 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxat.h @@ -0,0 +1,80 @@ +/* spxat.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXAT_H +#define SPXAT_H + +#include "spxlp.h" + +typedef struct SPXAT SPXAT; + +struct SPXAT +{ /* mxn-matrix A of constraint coefficients in sparse row-wise + * format */ + int *ptr; /* int ptr[1+m+1]; */ + /* ptr[0] is not used; + * ptr[i], 1 <= i <= m, is starting position of i-th row in + * arrays ind and val; note that ptr[1] is always 1; + * ptr[m+1] indicates the position after the last element in + * arrays ind and val, i.e. ptr[m+1] = nnz+1, where nnz is the + * number of non-zero elements in matrix A; + * the length of i-th row (the number of non-zero elements in + * that row) can be calculated as ptr[i+1] - ptr[i] */ + int *ind; /* int ind[1+nnz]; */ + /* column indices */ + double *val; /* double val[1+nnz]; */ + /* non-zero element values */ + double *work; /* double work[1+n]; */ + /* working array */ +}; + +#define spx_alloc_at _glp_spx_alloc_at +void spx_alloc_at(SPXLP *lp, SPXAT *at); +/* allocate constraint matrix in sparse row-wise format */ + +#define spx_build_at _glp_spx_build_at +void spx_build_at(SPXLP *lp, SPXAT *at); +/* build constraint matrix in sparse row-wise format */ + +#define spx_at_prod _glp_spx_at_prod +void spx_at_prod(SPXLP *lp, SPXAT *at, double y[/*1+n*/], double s, + const double x[/*1+m*/]); +/* compute product y := y + s * A'* x */ + +#define spx_nt_prod1 _glp_spx_nt_prod1 +void spx_nt_prod1(SPXLP *lp, SPXAT *at, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]); +/* compute product y := y + s * N'* x */ + +#define spx_eval_trow1 _glp_spx_eval_trow1 +void spx_eval_trow1(SPXLP *lp, SPXAT *at, const double rho[/*1+m*/], + double trow[/*1+n-m*/]); +/* compute i-th row of simplex table */ + +#define spx_free_at _glp_spx_free_at +void spx_free_at(SPXLP *lp, SPXAT *at); +/* deallocate constraint matrix in sparse row-wise format */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.c new file mode 100644 index 000000000..c60ccabc9 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.c @@ -0,0 +1,381 @@ +/* spxchuzc.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxchuzc.h" + +/*********************************************************************** +* spx_chuzc_sel - select eligible non-basic variables +* +* This routine selects eligible non-basic variables xN[j], whose +* reduced costs d[j] have "wrong" sign, i.e. changing such xN[j] in +* feasible direction improves (decreases) the objective function. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Non-basic variable xN[j] is considered eligible if: +* +* d[j] <= -eps[j] and xN[j] can increase +* +* d[j] >= +eps[j] and xN[j] can decrease +* +* for +* +* eps[j] = tol + tol1 * |cN[j]|, +* +* where cN[j] is the objective coefficient at xN[j], tol and tol1 are +* specified tolerances. +* +* On exit the routine stores indices j of eligible non-basic variables +* xN[j] to the array locations list[1], ..., list[num] and returns the +* number of such variables 0 <= num <= n-m. (If the parameter list is +* specified as NULL, no indices are stored.) */ + +int spx_chuzc_sel(SPXLP *lp, const double d[/*1+n-m*/], double tol, + double tol1, int list[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, num; + double ck, eps; + num = 0; + /* walk thru list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + { /* xN[j] is fixed variable; skip it */ + continue; + } + /* determine absolute tolerance eps[j] */ + ck = c[k]; + eps = tol + tol1 * (ck >= 0.0 ? +ck : -ck); + /* check if xN[j] is eligible */ + if (d[j] <= -eps) + { /* xN[j] should be able to increase */ + if (flag[j]) + { /* but its upper bound is active */ + continue; + } + } + else if (d[j] >= +eps) + { /* xN[j] should be able to decrease */ + if (!flag[j] && l[k] != -DBL_MAX) + { /* but its lower bound is active */ + continue; + } + } + else /* -eps < d[j] < +eps */ + { /* xN[j] does not affect the objective function within the + * specified tolerance */ + continue; + } + /* xN[j] is eligible non-basic variable */ + num++; + if (list != NULL) + list[num] = j; + } + return num; +} + +/*********************************************************************** +* spx_chuzc_std - choose non-basic variable (Dantzig's rule) +* +* This routine chooses most eligible non-basic variable xN[q] +* according to Dantzig's ("standard") rule: +* +* d[q] = max |d[j]|, +* j in J +* +* where J <= {1, ..., n-m} is the set of indices of eligible non-basic +* variables, d[j] is the reduced cost of non-basic variable xN[j] in +* the current basis. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Indices of eligible non-basic variables j in J should be placed in +* the array locations list[1], ..., list[num], where num = |J| > 0 is +* the total number of such variables. +* +* On exit the routine returns q, the index of the non-basic variable +* xN[q] chosen. */ + +int spx_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], int num, + const int list[]) +{ int m = lp->m; + int n = lp->n; + int j, q, t; + double abs_dj, abs_dq; + xassert(0 < num && num <= n-m); + q = 0, abs_dq = -1.0; + for (t = 1; t <= num; t++) + { j = list[t]; + abs_dj = (d[j] >= 0.0 ? +d[j] : -d[j]); + if (abs_dq < abs_dj) + q = j, abs_dq = abs_dj; + } + xassert(q != 0); + return q; +} + +/*********************************************************************** +* spx_alloc_se - allocate pricing data block +* +* This routine allocates the memory for arrays used in the pricing +* data block. */ + +void spx_alloc_se(SPXLP *lp, SPXSE *se) +{ int m = lp->m; + int n = lp->n; + se->valid = 0; + se->refsp = talloc(1+n, char); + se->gamma = talloc(1+n-m, double); + se->work = talloc(1+m, double); + return; +} + +/*********************************************************************** +* spx_reset_refsp - reset reference space +* +* This routine resets (re-initializes) the reference space composing +* it from variables which are non-basic in the current basis, and sets +* all weights gamma[j] to 1. */ + +void spx_reset_refsp(SPXLP *lp, SPXSE *se) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + int j, k; + se->valid = 1; + memset(&refsp[1], 0, n * sizeof(char)); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + refsp[k] = 1; + gamma[j] = 1.0; + } + return; +} + +/*********************************************************************** +* spx_eval_gamma_j - compute projected steepest edge weight directly +* +* This routine computes projected steepest edge weight gamma[j], +* 1 <= j <= n-m, for the current basis directly with the formula: +* +* m +* gamma[j] = delta[j] + sum eta[i] * T[i,j]**2, +* i=1 +* +* where T[i,j] is element of the current simplex table, and +* +* ( 1, if xB[i] is in the reference space +* eta[i] = { +* ( 0, otherwise +* +* ( 1, if xN[j] is in the reference space +* delta[j] = { +* ( 0, otherwise +* +* NOTE: For testing/debugging only. */ + +double spx_eval_gamma_j(SPXLP *lp, SPXSE *se, int j) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *tcol = se->work; + int i, k; + double gamma_j; + xassert(se->valid); + xassert(1 <= j && j <= n-m); + k = head[m+j]; /* x[k] = xN[j] */ + gamma_j = (refsp[k] ? 1.0 : 0.0); + spx_eval_tcol(lp, j, tcol); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (refsp[k]) + gamma_j += tcol[i] * tcol[i]; + } + return gamma_j; +} + +/*********************************************************************** +* spx_chuzc_pse - choose non-basic variable (projected steepest edge) +* +* This routine chooses most eligible non-basic variable xN[q] +* according to the projected steepest edge method: +* +* d[q]**2 d[j]**2 +* -------- = max -------- , +* gamma[q] j in J gamma[j] +* +* where J <= {1, ..., n-m} is the set of indices of eligible non-basic +* variable, d[j] is the reduced cost of non-basic variable xN[j] in +* the current basis, gamma[j] is the projected steepest edge weight. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Indices of eligible non-basic variables j in J should be placed in +* the array locations list[1], ..., list[num], where num = |J| > 0 is +* the total number of such variables. +* +* On exit the routine returns q, the index of the non-basic variable +* xN[q] chosen. */ + +int spx_chuzc_pse(SPXLP *lp, SPXSE *se, const double d[/*1+n-m*/], + int num, const int list[]) +{ int m = lp->m; + int n = lp->n; + double *gamma = se->gamma; + int j, q, t; + double best, temp; + xassert(se->valid); + xassert(0 < num && num <= n-m); + q = 0, best = -1.0; + for (t = 1; t <= num; t++) + { j = list[t]; + /* FIXME */ + if (gamma[j] < DBL_EPSILON) + temp = 0.0; + else + temp = (d[j] * d[j]) / gamma[j]; + if (best < temp) + q = j, best = temp; + } + xassert(q != 0); + return q; +} + +/*********************************************************************** +* spx_update_gamma - update projected steepest edge weights exactly +* +* This routine updates the vector gamma = (gamma[j]) of projected +* steepest edge weights exactly, for the adjacent basis. +* +* On entry to the routine the content of the se object should be valid +* and should correspond to the current basis. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* For details about the formulae used see the program documentation. +* +* The routine also computes the relative error: +* +* e = |gamma[q] - gamma'[q]| / (1 + |gamma[q]|), +* +* where gamma'[q] is the weight for xN[q] on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may reset the reference space, since other weights also may +* be inaccurate.) */ + +double spx_update_gamma(SPXLP *lp, SPXSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + double *u = se->work; + int i, j, k, ptr, end; + double gamma_q, delta_q, e, r, s, t1, t2; + xassert(se->valid); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* compute gamma[q] in current basis more accurately; also + * compute auxiliary vector u */ + k = head[m+q]; /* x[k] = xN[q] */ + gamma_q = delta_q = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (refsp[k]) + { gamma_q += tcol[i] * tcol[i]; + u[i] = tcol[i]; + } + else + u[i] = 0.0; + } + bfd_btran(lp->bfd, u); + /* compute relative error in gamma[q] */ + e = fabs(gamma_q - gamma[q]) / (1.0 + gamma_q); + /* compute new gamma[q] */ + gamma[q] = gamma_q / (tcol[p] * tcol[p]); + /* compute new gamma[j] for all j != q */ + for (j = 1; j <= n-m; j++) + { if (j == q) + continue; + if (-1e-9 < trow[j] && trow[j] < +1e-9) + { /* T[p,j] is close to zero; gamma[j] is not changed */ + continue; + } + /* compute r[j] = T[p,j] / T[p,q] */ + r = trow[j] / tcol[p]; + /* compute inner product s[j] = N'[j] * u, where N[j] = A[k] + * is constraint matrix column corresponding to xN[j] */ + s = 0.0; + k = head[m+j]; /* x[k] = xN[j] */ + ptr = lp->A_ptr[k]; + end = lp->A_ptr[k+1]; + for (; ptr < end; ptr++) + s += lp->A_val[ptr] * u[lp->A_ind[ptr]]; + /* compute new gamma[j] */ + t1 = gamma[j] + r * (r * gamma_q + s + s); + t2 = (refsp[k] ? 1.0 : 0.0) + delta_q * r * r; + gamma[j] = (t1 >= t2 ? t1 : t2); + } + return e; +} + +/*********************************************************************** +* spx_free_se - deallocate pricing data block +* +* This routine deallocates the memory used for arrays in the pricing +* data block. */ + +void spx_free_se(SPXLP *lp, SPXSE *se) +{ xassert(lp == lp); + tfree(se->refsp); + tfree(se->gamma); + tfree(se->work); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.h new file mode 100644 index 000000000..c09cca9aa --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzc.h @@ -0,0 +1,85 @@ +/* spxchuzc.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXCHUZC_H +#define SPXCHUZC_H + +#include "spxlp.h" + +#define spx_chuzc_sel _glp_spx_chuzc_sel +int spx_chuzc_sel(SPXLP *lp, const double d[/*1+n-m*/], double tol, + double tol1, int list[/*1+n-m*/]); +/* select eligible non-basic variables */ + +#define spx_chuzc_std _glp_spx_chuzc_std +int spx_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], int num, + const int list[]); +/* choose non-basic variable (Dantzig's rule) */ + +typedef struct SPXSE SPXSE; + +struct SPXSE +{ /* projected steepest edge and Devex pricing data block */ + int valid; + /* content validity flag */ + char *refsp; /* char refsp[1+n]; */ + /* refsp[0] is not used; + * refsp[k], 1 <= k <= n, is the flag meaning that variable x[k] + * is in the reference space */ + double *gamma; /* double gamma[1+n-m]; */ + /* gamma[0] is not used; + * gamma[j], 1 <= j <= n-m, is the weight for reduced cost d[j] + * of non-basic variable xN[j] in the current basis */ + double *work; /* double work[1+m]; */ + /* working array */ +}; + +#define spx_alloc_se _glp_spx_alloc_se +void spx_alloc_se(SPXLP *lp, SPXSE *se); +/* allocate pricing data block */ + +#define spx_reset_refsp _glp_spx_reset_refsp +void spx_reset_refsp(SPXLP *lp, SPXSE *se); +/* reset reference space */ + +#define spx_eval_gamma_j _glp_spx_eval_gamma_j +double spx_eval_gamma_j(SPXLP *lp, SPXSE *se, int j); +/* compute projeted steepest edge weight directly */ + +#define spx_chuzc_pse _glp_spx_chuzc_pse +int spx_chuzc_pse(SPXLP *lp, SPXSE *se, const double d[/*1+n-m*/], + int num, const int list[]); +/* choose non-basic variable (projected steepest edge) */ + +#define spx_update_gamma _glp_spx_update_gamma +double spx_update_gamma(SPXLP *lp, SPXSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update projected steepest edge weights exactly */ + +#define spx_free_se _glp_spx_free_se +void spx_free_se(SPXLP *lp, SPXSE *se); +/* deallocate pricing data block */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.c new file mode 100644 index 000000000..8bef77ba2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.c @@ -0,0 +1,594 @@ +/* spxchuzr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxchuzr.h" + +/*********************************************************************** +* spx_chuzr_std - choose basic variable (textbook ratio test) +* +* This routine implements an improved textbook ratio test to choose +* basic variable xB[p]. +* +* The parameter phase specifies the search phase: +* +* 1 - searching for feasible basic solution. In this case the routine +* uses artificial bounds of basic variables that correspond to +* breakpoints of the penalty function: +* +* ( lB[i], if cB[i] = 0 +* ( +* lB'[i] = { uB[i], if cB[i] > 0 +* ( +* ( -inf, if cB[i] < 0 +* +* ( uB[i], if cB[i] = 0 +* ( +* uB'[i] = { +inf, if cB[i] > 0 +* ( +* ( lB[i], if cB[i] < 0 +* +* where lB[i] and uB[i] are original bounds of variable xB[i], +* cB[i] is the penalty (objective) coefficient of that variable. +* +* 2 - searching for optimal basic solution. In this case the routine +* uses original bounds of basic variables. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* The parameter 1 <= q <= n-m specifies the index of non-basic +* variable xN[q] chosen. +* +* The parameter s specifies the direction in which xN[q] changes: +* s = +1.0 means xN[q] increases, and s = -1.0 means xN[q] decreases. +* (Thus, the corresponding ray parameter is theta = s (xN[q] - f[q]), +* where f[q] is the active bound of xN[q] in the current basis.) +* +* Elements of q-th simplex table column T[q] = (t[i,q]) corresponding +* to non-basic variable xN[q] should be placed in the array locations +* tcol[1], ..., tcol[m]. +* +* The parameter tol_piv specifies a tolerance for elements of the +* simplex table column T[q]. If |t[i,q]| < tol_piv, basic variable +* xB[i] is skipped, i.e. it is assumed that it does not depend on the +* ray parameter theta. +* +* The parameters tol and tol1 specify tolerances used to increase the +* choice freedom by simulating an artificial degeneracy as follows. +* If beta[i] <= lB[i] + delta[i], where delta[i] = tol + tol1 |lB[i]|, +* it is assumed that beta[i] is exactly the same as lB[i]. Similarly, +* if beta[i] >= uB[i] - delta[i], where delta[i] = tol + tol1 |uB[i]|, +* it is assumed that beta[i] is exactly the same as uB[i]. +* +* The routine determines the index 1 <= p <= m of basic variable xB[p] +* that reaches its (lower or upper) bound first on increasing the ray +* parameter theta, stores the bound flag (0 - lower bound or fixed +* value, 1 - upper bound) to the location pointed to by the pointer +* p_flag, and returns the index p. If non-basic variable xN[q] is +* double-bounded and reaches its opposite bound first, the routine +* returns (-1). And if the ray parameter may increase unlimitedly, the +* routine returns zero. +* +* Should note that the bound flag stored to the location pointed to by +* p_flag corresponds to the original (not artficial) bound of variable +* xB[p] and defines the active bound flag lp->flag[q] to be set in the +* adjacent basis for that basic variable. */ + +int spx_chuzr_std(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, i_flag, k, p; + double alfa, biga, delta, lk, uk, teta, teta_min; + xassert(phase == 1 || phase == 2); + xassert(1 <= q && q <= n-m); + xassert(s == +1.0 || s == -1.0); + /* determine initial teta_min */ + k = head[m+q]; /* x[k] = xN[q] */ + if (l[k] == -DBL_MAX || u[k] == +DBL_MAX) + { /* xN[q] has no opposite bound */ + p = 0, *p_flag = 0, teta_min = DBL_MAX, biga = 0.0; + } + else + { /* xN[q] have both lower and upper bounds */ + p = -1, *p_flag = 0, teta_min = fabs(l[k] - u[k]), biga = 1.0; + } + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + i_flag = 1; + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + i_flag = 0; + } + /* determine teta on which xB[i] reaches its lower bound */ + delta = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] <= lk + delta) + teta = 0.0; + else + teta = (lk - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + i_flag = 0; + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + i_flag = 1; + } + /* determine teta on which xB[i] reaches its upper bound */ + delta = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] >= uk - delta) + teta = 0.0; + else + teta = (uk - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + /* choose basic variable xB[p] for which teta is minimal */ + xassert(teta >= 0.0); + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta_min > teta || (teta_min == teta && biga < alfa)) + p = i, *p_flag = i_flag, teta_min = teta, biga = alfa; + } + /* if xB[p] is fixed variable, adjust its bound flag */ + if (p > 0) + { k = head[p]; + if (l[k] == u[k]) + *p_flag = 0; + } + return p; +} + +/*********************************************************************** +* spx_chuzr_harris - choose basic variable (Harris' ratio test) +* +* This routine implements Harris' ratio test to choose basic variable +* xB[p]. +* +* All the parameters, except tol and tol1, as well as the returned +* value have the same meaning as for the routine spx_chuzr_std (see +* above). +* +* The parameters tol and tol1 specify tolerances on bound violations +* for basic variables. For the lower bound of basic variable xB[i] the +* tolerance is delta[i] = tol + tol1 |lB[i]|, and for the upper bound +* the tolerance is delta[i] = tol + tol1 |uB[i]|. */ + +int spx_chuzr_harris(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, i_flag, k, p; + double alfa, biga, delta, lk, uk, teta, teta_min; + xassert(phase == 1 || phase == 2); + xassert(1 <= q && q <= n-m); + xassert(s == +1.0 || s == -1.0); + /*--------------------------------------------------------------*/ + /* first pass: determine teta_min for relaxed bounds */ + /*--------------------------------------------------------------*/ + teta_min = DBL_MAX; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + } + /* determine teta on which xB[i] reaches its relaxed lower + * bound */ + delta = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk) + teta = - delta / alfa; + else + teta = ((lk - delta) - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + } + /* determine teta on which xB[i] reaches its relaxed upper + * bound */ + delta = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk) + teta = + delta / alfa; + else + teta = ((uk + delta) - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + xassert(teta >= 0.0); + if (teta_min > teta) + teta_min = teta; + } + /*--------------------------------------------------------------*/ + /* second pass: choose basic variable xB[p] */ + /*--------------------------------------------------------------*/ + k = head[m+q]; /* x[k] = xN[q] */ + if (l[k] != -DBL_MAX && u[k] != +DBL_MAX) + { /* xN[q] has both lower and upper bounds */ + if (fabs(l[k] - u[k]) <= teta_min) + { /* and reaches its opposite bound */ + p = -1, *p_flag = 0; + goto done; + } + } + if (teta_min == DBL_MAX) + { /* teta may increase unlimitedly */ + p = 0, *p_flag = 0; + goto done; + } + /* nothing is chosen so far */ + p = 0, *p_flag = 0, biga = 0.0; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + i_flag = 1; + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + i_flag = 0; + } + /* determine teta on which xB[i] reaches its lower bound */ + teta = (lk - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + i_flag = 0; + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + i_flag = 1; + } + /* determine teta on which xB[i] reaches its upper bound */ + teta = (uk - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + /* choose basic variable for which teta is not greater than + * teta_min determined for relaxed bounds and which has best + * (largest in magnitude) pivot */ + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta <= teta_min && biga < alfa) + p = i, *p_flag = i_flag, biga = alfa; + } + /* something must be chosen */ + xassert(1 <= p && p <= m); + /* if xB[p] is fixed variable, adjust its bound flag */ + k = head[p]; + if (l[k] == u[k]) + *p_flag = 0; +done: return p; +} + +#if 1 /* 22/VI-2017 */ +/*********************************************************************** +* spx_ls_eval_bp - determine penalty function break points +* +* This routine determines break points of the penalty function (which +* is the sum of primal infeasibilities). +* +* The parameters lp, beta, q, dq, tcol, and tol_piv have the same +* meaning as for the routine spx_chuzr_std (see above). +* +* The routine stores the break-points determined to the array elements +* bp[1], ..., bp[nbp] in *arbitrary* order, where 0 <= nbp <= 2*m+1 is +* the number of break-points returned by the routine on exit. */ + +int spx_ls_eval_bp(SPXLP *lp, const double beta[/*1+m*/], + int q, double dq, const double tcol[/*1+m*/], double tol_piv, + SPXBP bp[/*1+2*m+1*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k, nbp; + double s, alfa; + xassert(1 <= q && q <= n-m); + xassert(dq != 0.0); + s = (dq < 0.0 ? +1.0 : -1.0); + nbp = 0; + /* if chosen non-basic variable xN[q] is double-bounded, include + * it in the list, because it can cross its opposite bound */ + k = head[m+q]; /* x[k] = xN[q] */ + if (l[k] != -DBL_MAX && u[k] != +DBL_MAX) + { nbp++; + bp[nbp].i = 0; + xassert(l[k] < u[k]); /* xN[q] cannot be fixed */ + bp[nbp].teta = u[k] - l[k]; + bp[nbp].dc = s; + } + /* build the list of all basic variables xB[i] that can cross + * their bound(s) for the ray parameter 0 <= teta < teta_max */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + xassert(l[k] <= u[k]); + /* determine alfa such that (delta xB[i]) = alfa * teta */ + alfa = s * tcol[i]; + if (alfa >= +tol_piv) + { /* xB[i] increases on increasing teta */ + if (l[k] == u[k]) + { /* xB[i] is fixed at lB[i] = uB[i] */ + if (c[k] <= 0.0) + { /* increasing xB[i] can cross its fixed value lB[i], + * because currently xB[i] <= lB[i] */ + nbp++; + bp[nbp].i = +i; + bp[nbp].teta = (l[k] - beta[i]) / alfa; + /* if xB[i] > lB[i] then cB[i] = +1 */ + bp[nbp].dc = +1.0 - c[k]; + } + } + else + { if (l[k] != -DBL_MAX && c[k] < 0.0) + { /* increasing xB[i] can cross its lower bound lB[i], + * because currently xB[i] < lB[i] */ + nbp++; + bp[nbp].i = +i; + bp[nbp].teta = (l[k] - beta[i]) / alfa; + bp[nbp].dc = +1.0; + } + if (u[k] != +DBL_MAX && c[k] <= 0.0) + { /* increasing xB[i] can cross its upper bound uB[i], + * because currently xB[i] does not violate it */ + nbp++; + bp[nbp].i = -i; + bp[nbp].teta = (u[k] - beta[i]) / alfa; + bp[nbp].dc = +1.0; + } + } + } + else if (alfa <= -tol_piv) + { /* xB[i] decreases on increasing teta */ + if (l[k] == u[k]) + { /* xB[i] is fixed at lB[i] = uB[i] */ + if (c[k] >= 0.0) + { /* decreasing xB[i] can cross its fixed value lB[i], + * because currently xB[i] >= lB[i] */ + nbp++; + bp[nbp].i = +i; + bp[nbp].teta = (l[k] - beta[i]) / alfa; + /* if xB[i] < lB[i] then cB[i] = -1 */ + bp[nbp].dc = -1.0 - c[k]; + } + } + else + { if (l[k] != -DBL_MAX && c[k] >= 0.0) + { /* decreasing xB[i] can cross its lower bound lB[i], + * because currently xB[i] does not violate it */ + nbp++; + bp[nbp].i = +i; + bp[nbp].teta = (l[k] - beta[i]) / alfa; + bp[nbp].dc = -1.0; + } + if (u[k] != +DBL_MAX && c[k] > 0.0) + { /* decreasing xB[i] can cross its upper bound uB[i], + * because currently xB[i] > uB[i] */ + nbp++; + bp[nbp].i = -i; + bp[nbp].teta = (u[k] - beta[i]) / alfa; + bp[nbp].dc = -1.0; + } + } + } + else + { /* xB[i] does not depend on teta within a tolerance */ + continue; + } + /* teta < 0 may happen only due to round-off errors when the + * current value of xB[i] is *close* to its (lower or upper) + * bound; in this case we replace teta by exact zero */ + if (bp[nbp].teta < 0.0) + bp[nbp].teta = 0.0; + } + xassert(nbp <= 2*m+1); + return nbp; +} +#endif + +#if 1 /* 22/VI-2017 */ +/*********************************************************************** +* spx_ls_select_bp - select and process penalty function break points +* +* This routine selects a next portion of the penalty function break +* points and processes them. +* +* On entry to the routine it is assumed that break points bp[1], ..., +* bp[num] are already processed, and slope is the penalty function +* slope to the right of the last processed break point bp[num]. +* (Initially, when num = 0, slope should be specified as -fabs(d[q]), +* where d[q] is the reduced cost of chosen non-basic variable xN[q].) +* +* The routine selects break points among bp[num+1], ..., bp[nbp], for +* which teta <= teta_lim, and moves these break points to the array +* elements bp[num+1], ..., bp[num1], where num <= num1 <= 2*m+1 is the +* new number of processed break points returned by the routine on +* exit. Then the routine sorts the break points by ascending teta and +* computes the change of the penalty function relative to its value at +* teta = 0. +* +* On exit the routine also replaces the parameter slope with a new +* value that corresponds to the new last break-point bp[num1]. */ + +static int CDECL fcmp(const void *v1, const void *v2) +{ const SPXBP *p1 = v1, *p2 = v2; + if (p1->teta < p2->teta) + return -1; + else if (p1->teta > p2->teta) + return +1; + else + return 0; +} + +int spx_ls_select_bp(SPXLP *lp, const double tcol[/*1+m*/], + int nbp, SPXBP bp[/*1+m+m+1*/], int num, double *slope, double + teta_lim) +{ int m = lp->m; + int i, t, num1; + double teta, dz; + xassert(0 <= num && num <= nbp && nbp <= m+m+1); + /* select a new portion of break points */ + num1 = num; + for (t = num+1; t <= nbp; t++) + { if (bp[t].teta <= teta_lim) + { /* move break point to the beginning of the new portion */ + num1++; + i = bp[num1].i, teta = bp[num1].teta, dz = bp[num1].dc; + bp[num1].i = bp[t].i, bp[num1].teta = bp[t].teta, + bp[num1].dc = bp[t].dc; + bp[t].i = i, bp[t].teta = teta, bp[t].dc = dz; + } + } + /* sort new break points bp[num+1], ..., bp[num1] by ascending + * the ray parameter teta */ + if (num1 - num > 1) + qsort(&bp[num+1], num1 - num, sizeof(SPXBP), fcmp); + /* calculate the penalty function change at the new break points + * selected */ + for (t = num+1; t <= num1; t++) + { /* calculate the penalty function change relative to its value + * at break point bp[t-1] */ + dz = (*slope) * (bp[t].teta - (t == 1 ? 0.0 : bp[t-1].teta)); + /* calculate the penalty function change relative to its value + * at teta = 0 */ + bp[t].dz = (t == 1 ? 0.0 : bp[t-1].dz) + dz; + /* calculate a new slope of the penalty function to the right + * of the current break point bp[t] */ + i = (bp[t].i >= 0 ? bp[t].i : -bp[t].i); + xassert(0 <= i && i <= m); + if (i == 0) + *slope += fabs(1.0 * bp[t].dc); + else + *slope += fabs(tcol[i] * bp[t].dc); + } + return num1; +} +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.h new file mode 100644 index 000000000..3ec900503 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxchuzr.h @@ -0,0 +1,77 @@ +/* spxchuzr.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXCHUZR_H +#define SPXCHUZR_H + +#include "spxlp.h" + +#define spx_chuzr_std _glp_spx_chuzr_std +int spx_chuzr_std(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1); +/* choose basic variable (textbook ratio test) */ + +#define spx_chuzr_harris _glp_spx_chuzr_harris +int spx_chuzr_harris(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1); +/* choose basic variable (Harris' ratio test) */ + +#if 1 /* 22/VI-2017 */ +typedef struct SPXBP SPXBP; + +struct SPXBP +{ /* penalty function (sum of infeasibilities) break point */ + int i; + /* basic variable xB[i], 1 <= i <= m, that intersects its bound + * at this break point + * i > 0 if xB[i] intersects its lower bound (or fixed value) + * i < 0 if xB[i] intersects its upper bound + * i = 0 if xN[q] intersects its opposite bound */ + double teta; + /* ray parameter value, teta >= 0, at this break point */ + double dc; + /* increment of the penalty function coefficient cB[i] at this + * break point */ + double dz; + /* increment, z[t] - z[0], of the penalty function at this break + * point */ +}; + +#define spx_ls_eval_bp _glp_spx_ls_eval_bp +int spx_ls_eval_bp(SPXLP *lp, const double beta[/*1+m*/], + int q, double dq, const double tcol[/*1+m*/], double tol_piv, + SPXBP bp[/*1+2*m+1*/]); +/* determine penalty function break points */ + +#define spx_ls_select_bp _glp_spx_ls_select_bp +int spx_ls_select_bp(SPXLP *lp, const double tcol[/*1+m*/], + int nbp, SPXBP bp[/*1+m+m+1*/], int num, double *slope, double + teta_lim); +/* select and process penalty function break points */ +#endif + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.c new file mode 100644 index 000000000..90ce26363 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.c @@ -0,0 +1,819 @@ +/* spxlp.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxlp.h" + +/*********************************************************************** +* spx_factorize - compute factorization of current basis matrix +* +* This routine computes factorization of the current basis matrix B. +* +* If the factorization has been successfully computed, the routine +* validates it and returns zero. Otherwise, the routine invalidates +* the factorization and returns the code provided by the factorization +* driver (bfd_factorize). */ + +static int jth_col(void *info, int j, int ind[], double val[]) +{ /* provide column B[j] */ + SPXLP *lp = info; + int m = lp->m; + int *A_ptr = lp->A_ptr; + int *head = lp->head; + int k, ptr, len; + xassert(1 <= j && j <= m); + k = head[j]; /* x[k] = xB[j] */ + ptr = A_ptr[k]; + len = A_ptr[k+1] - ptr; + memcpy(&ind[1], &lp->A_ind[ptr], len * sizeof(int)); + memcpy(&val[1], &lp->A_val[ptr], len * sizeof(double)); + return len; +} + +int spx_factorize(SPXLP *lp) +{ int ret; + ret = bfd_factorize(lp->bfd, lp->m, jth_col, lp); + lp->valid = (ret == 0); + return ret; +} + +/*********************************************************************** +* spx_eval_beta - compute current values of basic variables +* +* This routine computes vector beta = (beta[i]) of current values of +* basic variables xB = (xB[i]). (Factorization of the current basis +* matrix should be valid.) +* +* First the routine computes a modified vector of right-hand sides: +* +* n-m +* y = b - N * f = b - sum N[j] * f[j], +* j=1 +* +* where b = (b[i]) is the original vector of right-hand sides, N is +* a matrix composed from columns of the original constraint matrix A, +* which (columns) correspond to non-basic variables, f = (f[j]) is the +* vector of active bounds of non-basic variables xN = (xN[j]), +* N[j] = A[k] is a column of matrix A corresponding to non-basic +* variable xN[j] = x[k], f[j] is current active bound lN[j] = l[k] or +* uN[j] = u[k] of non-basic variable xN[j] = x[k]. The matrix-vector +* product N * f is computed as a linear combination of columns of N, +* so if f[j] = 0, column N[j] can be skipped. +* +* Then the routine performs FTRAN to compute the vector beta: +* +* beta = inv(B) * y. +* +* On exit the routine stores components of the vector beta to array +* locations beta[1], ..., beta[m]. */ + +void spx_eval_beta(SPXLP *lp, double beta[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, ptr, end; + double fj, *y; + /* compute y = b - N * xN */ + /* y := b */ + y = beta; + memcpy(&y[1], &b[1], m * sizeof(double)); + /* y := y - N * f */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* f[j] := active bound of xN[j] */ + fj = flag[j] ? u[k] : l[k]; + if (fj == 0.0 || fj == -DBL_MAX) + { /* either xN[j] has zero active bound or it is unbounded; + * in the latter case its value is assumed to be zero */ + continue; + } + /* y := y - N[j] * f[j] */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + y[A_ind[ptr]] -= A_val[ptr] * fj; + } + /* compute beta = inv(B) * y */ + xassert(lp->valid); + bfd_ftran(lp->bfd, beta); + return; +} + +/*********************************************************************** +* spx_eval_obj - compute current value of objective function +* +* This routine computes the value of the objective function in the +* current basic solution: +* +* z = cB'* beta + cN'* f + c[0] = +* +* m n-m +* = sum cB[i] * beta[i] + sum cN[j] * f[j] + c[0], +* i=1 j=1 +* +* where cB = (cB[i]) is the vector of objective coefficients at basic +* variables, beta = (beta[i]) is the vector of current values of basic +* variables, cN = (cN[j]) is the vector of objective coefficients at +* non-basic variables, f = (f[j]) is the vector of current active +* bounds of non-basic variables, c[0] is the constant term of the +* objective function. +* +* It as assumed that components of the vector beta are stored in the +* array locations beta[1], ..., beta[m]. */ + +double spx_eval_obj(SPXLP *lp, const double beta[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k; + double fj, z; + /* compute z = cB'* beta + cN'* f + c0 */ + /* z := c0 */ + z = c[0]; + /* z := z + cB'* beta */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + z += c[k] * beta[i]; + } + /* z := z + cN'* f */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* f[j] := active bound of xN[j] */ + fj = flag[j] ? u[k] : l[k]; + if (fj == 0.0 || fj == -DBL_MAX) + { /* either xN[j] has zero active bound or it is unbounded; + * in the latter case its value is assumed to be zero */ + continue; + } + z += c[k] * fj; + } + return z; +} + +/*********************************************************************** +* spx_eval_pi - compute simplex multipliers in current basis +* +* This routine computes vector pi = (pi[i]) of simplex multipliers in +* the current basis. (Factorization of the current basis matrix should +* be valid.) +* +* The vector pi is computed by performing BTRAN: +* +* pi = inv(B') * cB, +* +* where cB = (cB[i]) is the vector of objective coefficients at basic +* variables xB = (xB[i]). +* +* On exit components of vector pi are stored in the array locations +* pi[1], ..., pi[m]. */ + +void spx_eval_pi(SPXLP *lp, double pi[/*1+m*/]) +{ int m = lp->m; + double *c = lp->c; + int *head = lp->head; + int i; + double *cB; + /* construct cB */ + cB = pi; + for (i = 1; i <= m; i++) + cB[i] = c[head[i]]; + /* compute pi = inv(B) * cB */ + bfd_btran(lp->bfd, pi); + return; +} + +/*********************************************************************** +* spx_eval_dj - compute reduced cost of j-th non-basic variable +* +* This routine computes reduced cost d[j] of non-basic variable +* xN[j] = x[k], 1 <= j <= n-m, in the current basic solution: +* +* d[j] = c[k] - A'[k] * pi, +* +* where c[k] is the objective coefficient at x[k], A[k] is k-th column +* of the constraint matrix, pi is the vector of simplex multipliers in +* the current basis. +* +* It as assumed that components of the vector pi are stored in the +* array locations pi[1], ..., pi[m]. */ + +double spx_eval_dj(SPXLP *lp, const double pi[/*1+m*/], int j) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int k, ptr, end; + double dj; + xassert(1 <= j && j <= n-m); + k = lp->head[m+j]; /* x[k] = xN[j] */ + /* dj := c[k] */ + dj = lp->c[k]; + /* dj := dj - A'[k] * pi */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + dj -= A_val[ptr] * pi[A_ind[ptr]]; + return dj; +} + +/*********************************************************************** +* spx_eval_tcol - compute j-th column of simplex table +* +* This routine computes j-th column of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= j <= n-m. (Factorization of the +* current basis matrix should be valid.) +* +* The simplex table column is computed by performing FTRAN: +* +* tcol = - inv(B) * N[j], +* +* where B is the current basis matrix, N[j] = A[k] is a column of the +* constraint matrix corresponding to non-basic variable xN[j] = x[k]. +* +* On exit components of the simplex table column are stored in the +* array locations tcol[1], ... tcol[m]. */ + +void spx_eval_tcol(SPXLP *lp, int j, double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *head = lp->head; + int i, k, ptr, end; + xassert(1 <= j && j <= n-m); + k = head[m+j]; /* x[k] = xN[j] */ + /* compute tcol = - inv(B) * N[j] */ + for (i = 1; i <= m; i++) + tcol[i] = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tcol[A_ind[ptr]] = -A_val[ptr]; + bfd_ftran(lp->bfd, tcol); + return; +} + +/*********************************************************************** +* spx_eval_rho - compute i-th row of basis matrix inverse +* +* This routine computes i-th row of the matrix inv(B), where B is +* the current basis matrix, 1 <= i <= m. (Factorization of the current +* basis matrix should be valid.) +* +* The inverse row is computed by performing BTRAN: +* +* rho = inv(B') * e[i], +* +* where e[i] is i-th column of unity matrix. +* +* On exit components of the row are stored in the array locations +* row[1], ..., row[m]. */ + +void spx_eval_rho(SPXLP *lp, int i, double rho[/*1+m*/]) +{ int m = lp->m; + int j; + xassert(1 <= i && i <= m); + /* compute rho = inv(B') * e[i] */ + for (j = 1; j <= m; j++) + rho[j] = 0.0; + rho[i] = 1.0; + bfd_btran(lp->bfd, rho); + return; +} + +#if 1 /* 31/III-2016 */ +void spx_eval_rho_s(SPXLP *lp, int i, FVS *rho) +{ /* sparse version of spx_eval_rho */ + int m = lp->m; + xassert(1 <= i && i <= m); + /* compute rho = inv(B') * e[i] */ + xassert(rho->n == m); + fvs_clear_vec(rho); + rho->nnz = 1; + rho->ind[1] = i; + rho->vec[i] = 1.0; + bfd_btran_s(lp->bfd, rho); + return; +} +#endif + +/*********************************************************************** +* spx_eval_tij - compute element T[i,j] of simplex table +* +* This routine computes element T[i,j] of the current simplex table +* T = - inv(B) * N, 1 <= i <= m, 1 <= j <= n-m, with the following +* formula: +* +* T[i,j] = - N'[j] * rho, (1) +* +* where N[j] = A[k] is a column of the constraint matrix corresponding +* to non-basic variable xN[j] = x[k], rho is i-th row of the inverse +* matrix inv(B). +* +* It as assumed that components of the inverse row rho = (rho[j]) are +* stored in the array locations rho[1], ..., rho[m]. */ + +double spx_eval_tij(SPXLP *lp, const double rho[/*1+m*/], int j) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int k, ptr, end; + double tij; + xassert(1 <= j && j <= n-m); + k = lp->head[m+j]; /* x[k] = xN[j] */ + /* compute t[i,j] = - N'[j] * pi */ + tij = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tij -= A_val[ptr] * rho[A_ind[ptr]]; + return tij; +} + +/*********************************************************************** +* spx_eval_trow - compute i-th row of simplex table +* +* This routine computes i-th row of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= i <= m. +* +* Elements of the row T[i] = (T[i,j]), j = 1, ..., n-m, are computed +* directly with the routine spx_eval_tij. +* +* The vector rho = (rho[j]), which is i-th row of the basis inverse +* inv(B), should be previously computed with the routine spx_eval_rho. +* It is assumed that elements of this vector are stored in the array +* locations rho[1], ..., rho[m]. +* +* On exit components of the simplex table row are stored in the array +* locations trow[1], ... trow[n-m]. +* +* NOTE: For testing/debugging only. */ + +void spx_eval_trow(SPXLP *lp, const double rho[/*1+m*/], double + trow[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + int j; + for (j = 1; j <= n-m; j++) + trow[j] = spx_eval_tij(lp, rho, j); + return; +} + +/*********************************************************************** +* spx_update_beta - update values of basic variables +* +* This routine updates the vector beta = (beta[i]) of values of basic +* variables xB = (xB[i]) for the adjacent basis. +* +* On entry to the routine components of the vector beta in the current +* basis should be placed in array locations beta[1], ..., beta[m]. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. The special +* case p < 0 means that non-basic variable xN[q] goes from its current +* active bound to opposite one in the adjacent basis. +* +* If the flag p_flag is set, the active bound of xB[p] in the adjacent +* basis is set to its upper bound. (In this case xB[p] should have its +* upper bound and should not be fixed.) +* +* The parameter 1 <= q <= n-m specifies non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis (if 1 <= p <= m), +* or goes to its opposite bound (if p < 0). (In the latter case xN[q] +* should have both lower and upper bounds and should not be fixed.) +* +* It is assumed that the array tcol contains elements of q-th (pivot) +* column T[q] of the simple table in locations tcol[1], ..., tcol[m]. +* (This column should be computed for the current basis.) +* +* First, the routine determines the increment of basic variable xB[p] +* in the adjacent basis (but only if 1 <= p <= m): +* +* ( - beta[p], if -inf < xB[p] < +inf +* ( +* delta xB[p] = { lB[p] - beta[p], if p_flag = 0 +* ( +* ( uB[p] - beta[p], if p_flag = 1 +* +* where beta[p] is the value of xB[p] in the current basis, lB[p] and +* uB[p] are its lower and upper bounds. Then, the routine determines +* the increment of non-basic variable xN[q] in the adjacent basis: +* +* ( delta xB[p] / T[p,q], if 1 <= p <= m +* ( +* delta xN[q] = { uN[q] - lN[q], if p < 0 and f[q] = lN[q] +* ( +* ( lN[q] - uN[q], if p < 0 and f[q] = uN[q] +* +* where T[p,q] is the pivot element of the simplex table, f[q] is the +* active bound of xN[q] in the current basis. +* +* If 1 <= p <= m, in the adjacent basis xN[q] becomes xB[p], so: +* +* new beta[p] = f[q] + delta xN[q]. +* +* Values of other basic variables xB[i] for 1 <= i <= m, i != p, are +* updated as follows: +* +* new beta[i] = beta[i] + T[i,q] * delta xN[q]. +* +* On exit the routine stores updated components of the vector beta to +* the same locations, where the input vector beta was stored. */ + +void spx_update_beta(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int i, k; + double delta_p, delta_q; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n-m); + /* xN[q] should be double-bounded variable */ + k = head[m+q]; /* x[k] = xN[q] */ + xassert(l[k] != -DBL_MAX && u[k] != +DBL_MAX && l[k] != u[k]); + /* determine delta xN[q] */ + if (flag[q]) + { /* xN[q] goes from its upper bound to its lower bound */ + delta_q = l[k] - u[k]; + } + else + { /* xN[q] goes from its lower bound to its upper bound */ + delta_q = u[k] - l[k]; + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* determine delta xB[p] */ + k = head[p]; /* x[k] = xB[p] */ + if (p_flag) + { /* xB[p] goes to its upper bound */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + delta_p = u[k] - beta[p]; + } + else if (l[k] == -DBL_MAX) + { /* unbounded xB[p] becomes non-basic (unusual case) */ + xassert(u[k] == +DBL_MAX); + delta_p = 0.0 - beta[p]; + } + else + { /* xB[p] goes to its lower bound or becomes fixed */ + delta_p = l[k] - beta[p]; + } + /* determine delta xN[q] */ + delta_q = delta_p / tcol[p]; + /* compute new beta[p], which is the value of xN[q] in the + * adjacent basis */ + k = head[m+q]; /* x[k] = xN[q] */ + if (flag[q]) + { /* xN[q] has its upper bound active */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + beta[p] = u[k] + delta_q; + } + else if (l[k] == -DBL_MAX) + { /* xN[q] is non-basic unbounded variable */ + xassert(u[k] == +DBL_MAX); + beta[p] = 0.0 + delta_q; + } + else + { /* xN[q] has its lower bound active or is fixed (latter + * case is unusual) */ + beta[p] = l[k] + delta_q; + } + } + /* compute new beta[i] for all i != p */ + for (i = 1; i <= m; i++) + { if (i != p) + beta[i] += tcol[i] * delta_q; + } + return; +} + +#if 1 /* 30/III-2016 */ +void spx_update_beta_s(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const FVS *tcol) +{ /* sparse version of spx_update_beta */ + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int nnz = tcol->nnz; + int *ind = tcol->ind; + double *vec = tcol->vec; + int i, k; + double delta_p, delta_q; + xassert(tcol->n == m); + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ +#if 0 /* 11/VI-2017 */ + /* FIXME: not tested yet */ + xassert(0); +#endif + xassert(1 <= q && q <= n-m); + /* xN[q] should be double-bounded variable */ + k = head[m+q]; /* x[k] = xN[q] */ + xassert(l[k] != -DBL_MAX && u[k] != +DBL_MAX && l[k] != u[k]); + /* determine delta xN[q] */ + if (flag[q]) + { /* xN[q] goes from its upper bound to its lower bound */ + delta_q = l[k] - u[k]; + } + else + { /* xN[q] goes from its lower bound to its upper bound */ + delta_q = u[k] - l[k]; + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* determine delta xB[p] */ + k = head[p]; /* x[k] = xB[p] */ + if (p_flag) + { /* xB[p] goes to its upper bound */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + delta_p = u[k] - beta[p]; + } + else if (l[k] == -DBL_MAX) + { /* unbounded xB[p] becomes non-basic (unusual case) */ + xassert(u[k] == +DBL_MAX); + delta_p = 0.0 - beta[p]; + } + else + { /* xB[p] goes to its lower bound or becomes fixed */ + delta_p = l[k] - beta[p]; + } + /* determine delta xN[q] */ + delta_q = delta_p / vec[p]; + /* compute new beta[p], which is the value of xN[q] in the + * adjacent basis */ + k = head[m+q]; /* x[k] = xN[q] */ + if (flag[q]) + { /* xN[q] has its upper bound active */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + beta[p] = u[k] + delta_q; + } + else if (l[k] == -DBL_MAX) + { /* xN[q] is non-basic unbounded variable */ + xassert(u[k] == +DBL_MAX); + beta[p] = 0.0 + delta_q; + } + else + { /* xN[q] has its lower bound active or is fixed (latter + * case is unusual) */ + beta[p] = l[k] + delta_q; + } + } + /* compute new beta[i] for all i != p */ + for (k = 1; k <= nnz; k++) + { i = ind[k]; + if (i != p) + beta[i] += vec[i] * delta_q; + } + return; +} +#endif + +/*********************************************************************** +* spx_update_d - update reduced costs of non-basic variables +* +* This routine updates the vector d = (d[j]) of reduced costs of +* non-basic variables xN = (xN[j]) for the adjacent basis. +* +* On entry to the routine components of the vector d in the current +* basis should be placed in locations d[1], ..., d[n-m]. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* First, the routine computes more accurate reduced cost d[q] in the +* current basis using q-th column of the simplex table: +* +* n-m +* d[q] = cN[q] + sum t[i,q] * cB[i], +* i=1 +* +* where cN[q] and cB[i] are objective coefficients at variables xN[q] +* and xB[i], resp. The routine also computes the relative error: +* +* e = |d[q] - d'[q]| / (1 + |d[q]|), +* +* where d'[q] is the reduced cost of xN[q] on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may compute the reduced costs directly, since other reduced +* costs also may be inaccurate.) +* +* In the adjacent basis xB[p] becomes xN[q], so: +* +* new d[q] = d[q] / T[p,q], +* +* where T[p,q] is the pivot element of the simplex table (it is taken +* from column T[q] as more accurate). Reduced costs of other non-basic +* variables xN[j] for 1 <= j <= n-m, j != q, are updated as follows: +* +* new d[j] = d[j] + T[p,j] * new d[q]. +* +* On exit the routine stores updated components of the vector d to the +* same locations, where the input vector d was stored. */ + +double spx_update_d(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + int *head = lp->head; + int i, j, k; + double dq, e; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in current basis more accurately */ + k = head[m+q]; /* x[k] = xN[q] */ + dq = c[k]; + for (i = 1; i <= m; i++) + dq += tcol[i] * c[head[i]]; + /* compute relative error in d[q] */ + e = fabs(dq - d[q]) / (1.0 + fabs(dq)); + /* compute new d[q], which is the reduced cost of xB[p] in the + * adjacent basis */ + d[q] = (dq /= tcol[p]); + /* compute new d[j] for all j != q */ + for (j = 1; j <= n-m; j++) + { if (j != q) + d[j] -= trow[j] * dq; + } + return e; +} + +#if 1 /* 30/III-2016 */ +double spx_update_d_s(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const FVS *trow, const FVS *tcol) +{ /* sparse version of spx_update_d */ + int m = lp->m; + int n = lp->n; + double *c = lp->c; + int *head = lp->head; + int trow_nnz = trow->nnz; + int *trow_ind = trow->ind; + double *trow_vec = trow->vec; + int tcol_nnz = tcol->nnz; + int *tcol_ind = tcol->ind; + double *tcol_vec = tcol->vec; + int i, j, k; + double dq, e; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + xassert(trow->n == n-m); + xassert(tcol->n == m); + /* compute d[q] in current basis more accurately */ + k = head[m+q]; /* x[k] = xN[q] */ + dq = c[k]; + for (k = 1; k <= tcol_nnz; k++) + { i = tcol_ind[k]; + dq += tcol_vec[i] * c[head[i]]; + } + /* compute relative error in d[q] */ + e = fabs(dq - d[q]) / (1.0 + fabs(dq)); + /* compute new d[q], which is the reduced cost of xB[p] in the + * adjacent basis */ + d[q] = (dq /= tcol_vec[p]); + /* compute new d[j] for all j != q */ + for (k = 1; k <= trow_nnz; k++) + { j = trow_ind[k]; + if (j != q) + d[j] -= trow_vec[j] * dq; + } + return e; +} +#endif + +/*********************************************************************** +* spx_change_basis - change current basis to adjacent one +* +* This routine changes the current basis to the adjacent one making +* necessary changes in lp->head and lp->flag members. +* +* The parameters p, p_flag, and q have the same meaning as for the +* routine spx_update_beta. */ + +void spx_change_basis(SPXLP *lp, int p, int p_flag, int q) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int k; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n-m); + /* xN[q] should be double-bounded variable */ + k = head[m+q]; /* x[k] = xN[q] */ + xassert(l[k] != -DBL_MAX && u[k] != +DBL_MAX && l[k] != u[k]); + /* change active bound flag */ + flag[q] = 1 - flag[q]; + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(p_flag == 0 || p_flag == 1); + xassert(1 <= q && q <= n-m); + k = head[p]; /* xB[p] = x[k] */ + if (p_flag) + { /* xB[p] goes to its upper bound */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + } + /* swap xB[p] and xN[q] in the basis */ + head[p] = head[m+q], head[m+q] = k; + /* and set active bound flag for new xN[q] */ + lp->flag[q] = p_flag; + } + return; +} + +/*********************************************************************** +* spx_update_invb - update factorization of basis matrix +* +* This routine updates factorization of the basis matrix B when i-th +* column of B is replaced by k-th column of the constraint matrix A. +* +* The parameter 1 <= i <= m specifies the number of column of matrix B +* to be replaced by a new column. +* +* The parameter 1 <= k <= n specifies the number of column of matrix A +* to be used for replacement. +* +* If the factorization has been successfully updated, the routine +* validates it and returns zero. Otherwise, the routine invalidates +* the factorization and returns the code provided by the factorization +* driver (bfd_update). */ + +int spx_update_invb(SPXLP *lp, int i, int k) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int ptr, len, ret; + xassert(1 <= i && i <= m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + len = A_ptr[k+1] - ptr; + ret = bfd_update(lp->bfd, i, len, &A_ind[ptr-1], &A_val[ptr-1]); + lp->valid = (ret == 0); + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.h new file mode 100644 index 000000000..29a135fec --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxlp.h @@ -0,0 +1,234 @@ +/* spxlp.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXLP_H +#define SPXLP_H + +#include "bfd.h" + +/*********************************************************************** +* The structure SPXLP describes LP problem and its current basis. +* +* It is assumed that LP problem has the following formulation (this is +* so called "working format"): +* +* z = c'* x + c0 -> min (1) +* +* A * x = b (2) +* +* l <= x <= u (3) +* +* where: +* +* x = (x[k]) is a n-vector of variables; +* +* z is an objective function; +* +* c = (c[k]) is a n-vector of objective coefficients; +* +* c0 is a constant term of the objective function; +* +* A = (a[i,k]) is a mxn-matrix of constraint coefficients; +* +* b = (b[i]) is a m-vector of right-hand sides; +* +* l = (l[k]) is a n-vector of lower bounds of variables; +* +* u = (u[k]) is a n-vector of upper bounds of variables. +* +* If variable x[k] has no lower (upper) bound, it is formally assumed +* that l[k] = -inf (u[k] = +inf). Variable having no bounds is called +* free (unbounded) variable. If l[k] = u[k], variable x[k] is assumed +* to be fixed. +* +* It is also assumed that matrix A has full row rank: rank(A) = m, +* i.e. all its rows are linearly independent, so m <= n. +* +* The (current) basis is defined by an appropriate permutation matrix +* P of order n such that: +* +* ( xB ) +* P * x = ( ), (4) +* ( xN ) +* +* where xB = (xB[i]) is a m-vector of basic variables, xN = (xN[j]) is +* a (n-m)-vector of non-basic variables. If a non-basic variable xN[j] +* has both lower and upper bounds, there is used an additional flag to +* indicate which bound is active. +* +* From (2) and (4) it follows that: +* +* A * P'* P * x = b <=> B * xB + N * xN = b, (5) +* +* where P' is a matrix transposed to P, and +* +* A * P' = (B | N). (6) +* +* Here B is the basis matrix, which is a square non-singular matrix +* of order m composed from columns of matrix A that correspond to +* basic variables xB, and N is a mx(n-m) matrix composed from columns +* of matrix A that correspond to non-basic variables xN. */ + +typedef struct SPXLP SPXLP; + +struct SPXLP +{ /* LP problem data and its (current) basis */ + int m; + /* number of equality constraints, m > 0 */ + int n; + /* number of variables, n >= m */ + int nnz; + /* number of non-zeros in constraint matrix A */ + /*--------------------------------------------------------------*/ + /* mxn-matrix A of constraint coefficients in sparse column-wise + * format */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + /* A_ptr[0] is not used; + * A_ptr[k], 1 <= k <= n, is starting position of k-th column in + * arrays A_ind and A_val; note that A_ptr[1] is always 1; + * A_ptr[n+1] indicates the position after the last element in + * arrays A_ind and A_val, i.e. A_ptr[n+1] = nnz+1, where nnz is + * the number of non-zero elements in matrix A; + * the length of k-th column (the number of non-zero elements in + * that column) can be calculated as A_ptr[k+1] - A_ptr[k] */ + int *A_ind; /* int A_ind[1+nnz]; */ + /* row indices */ + double *A_val; /* double A_val[1+nnz]; */ + /* non-zero element values (constraint coefficients) */ + /*--------------------------------------------------------------*/ + /* principal vectors of LP formulation */ + double *b; /* double b[1+m]; */ + /* b[0] is not used; + * b[i], 1 <= i <= m, is the right-hand side of i-th equality + * constraint */ + double *c; /* double c[1+n]; */ + /* c[0] is the constant term of the objective function; + * c[k], 1 <= k <= n, is the objective function coefficient at + * variable x[k] */ + double *l; /* double l[1+n]; */ + /* l[0] is not used; + * l[k], 1 <= k <= n, is the lower bound of variable x[k]; + * if x[k] has no lower bound, l[k] = -DBL_MAX */ + double *u; /* double u[1+n]; */ + /* u[0] is not used; + * u[k], 1 <= k <= n, is the upper bound of variable u[k]; + * if x[k] has no upper bound, u[k] = +DBL_MAX; + * note that l[k] = u[k] means that x[k] is fixed variable */ + /*--------------------------------------------------------------*/ + /* LP basis */ + int *head; /* int head[1+n]; */ + /* basis header, which is permutation matrix P (4): + * head[0] is not used; + * head[i] = k means that xB[i] = x[k], 1 <= i <= m; + * head[m+j] = k, means that xN[j] = x[k], 1 <= j <= n-m */ + char *flag; /* char flag[1+n-m]; */ + /* flags of non-basic variables: + * flag[0] is not used; + * flag[j], 1 <= j <= n-m, indicates that non-basic variable + * xN[j] is non-fixed and has its upper bound active */ + /*--------------------------------------------------------------*/ + /* basis matrix B of order m stored in factorized form */ + int valid; + /* factorization validity flag */ + BFD *bfd; + /* driver to factorization of the basis matrix */ +}; + +#define spx_factorize _glp_spx_factorize +int spx_factorize(SPXLP *lp); +/* compute factorization of current basis matrix */ + +#define spx_eval_beta _glp_spx_eval_beta +void spx_eval_beta(SPXLP *lp, double beta[/*1+m*/]); +/* compute values of basic variables */ + +#define spx_eval_obj _glp_spx_eval_obj +double spx_eval_obj(SPXLP *lp, const double beta[/*1+m*/]); +/* compute value of objective function */ + +#define spx_eval_pi _glp_spx_eval_pi +void spx_eval_pi(SPXLP *lp, double pi[/*1+m*/]); +/* compute simplex multipliers */ + +#define spx_eval_dj _glp_spx_eval_dj +double spx_eval_dj(SPXLP *lp, const double pi[/*1+m*/], int j); +/* compute reduced cost of j-th non-basic variable */ + +#define spx_eval_tcol _glp_spx_eval_tcol +void spx_eval_tcol(SPXLP *lp, int j, double tcol[/*1+m*/]); +/* compute j-th column of simplex table */ + +#define spx_eval_rho _glp_spx_eval_rho +void spx_eval_rho(SPXLP *lp, int i, double rho[/*1+m*/]); +/* compute i-th row of basis matrix inverse */ + +#if 1 /* 31/III-2016 */ +#define spx_eval_rho_s _glp_spx_eval_rho_s +void spx_eval_rho_s(SPXLP *lp, int i, FVS *rho); +/* sparse version of spx_eval_rho */ +#endif + +#define spx_eval_tij _glp_spx_eval_tij +double spx_eval_tij(SPXLP *lp, const double rho[/*1+m*/], int j); +/* compute element T[i,j] of simplex table */ + +#define spx_eval_trow _glp_spx_eval_trow +void spx_eval_trow(SPXLP *lp, const double rho[/*1+m*/], double + trow[/*1+n-m*/]); +/* compute i-th row of simplex table */ + +#define spx_update_beta _glp_spx_update_beta +void spx_update_beta(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const double tcol[/*1+m*/]); +/* update values of basic variables */ + +#if 1 /* 30/III-2016 */ +#define spx_update_beta_s _glp_spx_update_beta_s +void spx_update_beta_s(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const FVS *tcol); +/* sparse version of spx_update_beta */ +#endif + +#define spx_update_d _glp_spx_update_d +double spx_update_d(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update reduced costs of non-basic variables */ + +#if 1 /* 30/III-2016 */ +#define spx_update_d_s _glp_spx_update_d_s +double spx_update_d_s(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const FVS *trow, const FVS *tcol); +/* sparse version of spx_update_d */ +#endif + +#define spx_change_basis _glp_spx_change_basis +void spx_change_basis(SPXLP *lp, int p, int p_flag, int q); +/* change current basis to adjacent one */ + +#define spx_update_invb _glp_spx_update_invb +int spx_update_invb(SPXLP *lp, int i, int k); +/* update factorization of basis matrix */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.c new file mode 100644 index 000000000..7eaac8529 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.c @@ -0,0 +1,303 @@ +/* spxnt.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxnt.h" + +/*********************************************************************** +* spx_alloc_nt - allocate matrix N in sparse row-wise format +* +* This routine allocates the memory for arrays needed to represent the +* matrix N composed of non-basic columns of the constraint matrix A. */ + +void spx_alloc_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int nnz = lp->nnz; + nt->ptr = talloc(1+m, int); + nt->len = talloc(1+m, int); + nt->ind = talloc(1+nnz, int); + nt->val = talloc(1+nnz, double); + return; +} + +/*********************************************************************** +* spx_init_nt - initialize row pointers for matrix N +* +* This routine initializes (sets up) row pointers for the matrix N +* using column-wise representation of the constraint matrix A. +* +* This routine needs to be called only once. */ + +void spx_init_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int i, k, ptr, end; + /* calculate NT_len[i] = maximal number of non-zeros in i-th row + * of N = number of non-zeros in i-th row of A */ + memset(&NT_len[1], 0, m * sizeof(int)); + for (k = 1; k <= n; k++) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + NT_len[A_ind[ptr]]++; + } + /* initialize row pointers NT_ptr[i], i = 1,...,n-m */ + NT_ptr[1] = 1; + for (i = 2; i <= m; i++) + NT_ptr[i] = NT_ptr[i-1] + NT_len[i-1]; + xassert(NT_ptr[m] + NT_len[m] == nnz+1); + return; +} + +/*********************************************************************** +* spx_nt_add_col - add column N[j] = A[k] to matrix N +* +* This routine adds elements of column N[j] = A[k], 1 <= j <= n-m, +* 1 <= k <= n, to the row-wise represntation of the matrix N. It is +* assumed (with no check) that elements of the specified column are +* missing in the row-wise represntation of N. */ + +void spx_nt_add_col(SPXLP *lp, SPXNT *nt, int j, int k) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, ptr, end, pos; + xassert(1 <= j && j <= n-m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { i = A_ind[ptr]; + /* add element N[i,j] = A[i,k] to i-th row of matrix N */ + pos = NT_ptr[i] + (NT_len[i]++); + if (i < m) + xassert(pos < NT_ptr[i+1]); + else + xassert(pos <= nnz); + NT_ind[pos] = j; + NT_val[pos] = A_val[ptr]; + } + return; +} + +/*********************************************************************** +* spx_build_nt - build matrix N for current basis +* +* This routine builds the row-wise represntation of the matrix N +* for the current basis by adding columns of the constraint matrix A +* corresponding to non-basic variables. */ + +void spx_build_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + int *NT_len = nt->len; + int j, k; + /* N := 0 */ + memset(&NT_len[1], 0, m * sizeof(int)); + /* add non-basic columns N[j] = A[k] */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + spx_nt_add_col(lp, nt, j, k); + } + return; +} + +/*********************************************************************** +* spx_nt_del_col - remove column N[j] = A[k] from matrix N +* +* This routine removes elements of column N[j] = A[k], 1 <= j <= n-m, +* 1 <= k <= n, from the row-wise representation of the matrix N. It is +* assumed (with no check) that elements of the specified column are +* present in the row-wise representation of N. */ + +void spx_nt_del_col(SPXLP *lp, SPXNT *nt, int j, int k) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, ptr, end, ptr1, end1; + xassert(1 <= j && j <= n-m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { i = A_ind[ptr]; + /* find element N[i,j] = A[i,k] in i-th row of matrix N */ + ptr1 = NT_ptr[i]; + end1 = ptr1 + NT_len[i]; + for (; NT_ind[ptr1] != j; ptr1++) + /* nop */; + xassert(ptr1 < end1); + /* and remove it from i-th row element list */ + NT_len[i]--; + NT_ind[ptr1] = NT_ind[end1-1]; + NT_val[ptr1] = NT_val[end1-1]; + } + return; +} + +/*********************************************************************** +* spx_update_nt - update matrix N for adjacent basis +* +* This routine updates the row-wise represntation of matrix N for +* the adjacent basis, where column N[q], 1 <= q <= n-m, is replaced by +* column B[p], 1 <= p <= m, of the current basis matrix B. */ + +void spx_update_nt(SPXLP *lp, SPXNT *nt, int p, int q) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* remove old column N[q] corresponding to variable xN[q] */ + spx_nt_del_col(lp, nt, q, head[m+q]); + /* add new column N[q] corresponding to variable xB[p] */ + spx_nt_add_col(lp, nt, q, head[p]); + return; +} + +/*********************************************************************** +* spx_nt_prod - compute product y := y + s * N'* x +* +* This routine computes the product: +* +* y := y + s * N'* x, +* +* where N' is a matrix transposed to the mx(n-m)-matrix N composed +* from non-basic columns of the constraint matrix A, x is a m-vector, +* s is a scalar, y is (n-m)-vector. +* +* If the flag ign is non-zero, the routine ignores the input content +* of the array y assuming that y = 0. +* +* The routine uses the row-wise representation of the matrix N and +* computes the product as a linear combination: +* +* y := y + s * (N'[1] * x[1] + ... + N'[m] * x[m]), +* +* where N'[i] is i-th row of N, 1 <= i <= m. */ + +void spx_nt_prod(SPXLP *lp, SPXNT *nt, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, j, ptr, end; + double t; + if (ign) + { /* y := 0 */ + for (j = 1; j <= n-m; j++) + y[j] = 0.0; + } + for (i = 1; i <= m; i++) + { if (x[i] != 0.0) + { /* y := y + s * (i-th row of N) * x[i] */ + t = s * x[i]; + ptr = NT_ptr[i]; + end = ptr + NT_len[i]; + for (; ptr < end; ptr++) + y[NT_ind[ptr]] += NT_val[ptr] * t; + } + } + return; +} + +#if 1 /* 31/III-2016 */ +void spx_nt_prod_s(SPXLP *lp, SPXNT *nt, FVS *y, int ign, double s, + const FVS *x, double eps) +{ /* sparse version of spx_nt_prod */ + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int *x_ind = x->ind; + double *x_vec = x->vec; + int *y_ind = y->ind; + double *y_vec = y->vec; + int i, j, k, nnz, ptr, end; + double t; + xassert(x->n == lp->m); + xassert(y->n == lp->n-lp->m); + if (ign) + { /* y := 0 */ + fvs_clear_vec(y); + } + nnz = y->nnz; + for (k = x->nnz; k >= 1; k--) + { i = x_ind[k]; + /* y := y + s * (i-th row of N) * x[i] */ + t = s * x_vec[i]; + ptr = NT_ptr[i]; + end = ptr + NT_len[i]; + for (; ptr < end; ptr++) + { j = NT_ind[ptr]; + if (y_vec[j] == 0.0) + y_ind[++nnz] = j; + y_vec[j] += NT_val[ptr] * t; + /* don't forget about numeric cancellation */ + if (y_vec[j] == 0.0) + y_vec[j] = DBL_MIN; + } + } + y->nnz = nnz; + fvs_adjust_vec(y, eps); + return; +} +#endif + +/*********************************************************************** +* spx_free_nt - deallocate matrix N in sparse row-wise format +* +* This routine deallocates the memory used for arrays of the program +* object nt. */ + +void spx_free_nt(SPXLP *lp, SPXNT *nt) +{ xassert(lp == lp); + tfree(nt->ptr); + tfree(nt->len); + tfree(nt->ind); + tfree(nt->val); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.h new file mode 100644 index 000000000..857917b8d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxnt.h @@ -0,0 +1,96 @@ +/* spxnt.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXNT_H +#define SPXNT_H + +#include "spxlp.h" + +typedef struct SPXNT SPXNT; + +struct SPXNT +{ /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format */ + int *ptr; /* int ptr[1+m]; */ + /* ptr[0] is not used; + * ptr[i], 1 <= i <= m, is starting position of i-th row in + * arrays ind and val; note that ptr[1] is always 1; + * these starting positions are set up *once* as if they would + * correspond to rows of matrix A stored without gaps, i.e. + * ptr[i+1] - ptr[i] is the number of non-zeros in i-th (i < m) + * row of matrix A, and (nnz+1) - ptr[m] is the number of + * non-zero in m-th (last) row of matrix A, where nnz is the + * total number of non-zeros in matrix A */ + int *len; /* int len[1+m]; */ + /* len[0] is not used; + * len[i], 1 <= i <= m, is the number of non-zeros in i-th row + * of current matrix N */ + int *ind; /* int ind[1+nnz]; */ + /* column indices */ + double *val; /* double val[1+nnz]; */ + /* non-zero element values */ +}; + +#define spx_alloc_nt _glp_spx_alloc_nt +void spx_alloc_nt(SPXLP *lp, SPXNT *nt); +/* allocate matrix N in sparse row-wise format */ + +#define spx_init_nt _glp_spx_init_nt +void spx_init_nt(SPXLP *lp, SPXNT *nt); +/* initialize row pointers for matrix N */ + +#define spx_nt_add_col _glp_spx_nt_add_col +void spx_nt_add_col(SPXLP *lp, SPXNT *nt, int j, int k); +/* add column N[j] = A[k] */ + +#define spx_build_nt _glp_spx_build_nt +void spx_build_nt(SPXLP *lp, SPXNT *nt); +/* build matrix N for current basis */ + +#define spx_nt_del_col _glp_spx_nt_del_col +void spx_nt_del_col(SPXLP *lp, SPXNT *nt, int j, int k); +/* remove column N[j] = A[k] from matrix N */ + +#define spx_update_nt _glp_spx_update_nt +void spx_update_nt(SPXLP *lp, SPXNT *nt, int p, int q); +/* update matrix N for adjacent basis */ + +#define spx_nt_prod _glp_spx_nt_prod +void spx_nt_prod(SPXLP *lp, SPXNT *nt, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]); +/* compute product y := y + s * N'* x */ + +#if 1 /* 31/III-2016 */ +#define spx_nt_prod_s _glp_spx_nt_prod_s +void spx_nt_prod_s(SPXLP *lp, SPXNT *nt, FVS *y, int ign, double s, + const FVS *x, double eps); +/* sparse version of spx_nt_prod */ +#endif + +#define spx_free_nt _glp_spx_free_nt +void spx_free_nt(SPXLP *lp, SPXNT *nt); +/* deallocate matrix N in sparse row-wise format */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprim.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprim.c new file mode 100644 index 000000000..e1cdfb5ab --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprim.c @@ -0,0 +1,1860 @@ +/* spxprim.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#if 1 /* 18/VII-2017 */ +#define SCALE_Z 1 +#endif + +#include "env.h" +#include "simplex.h" +#include "spxat.h" +#include "spxnt.h" +#include "spxchuzc.h" +#include "spxchuzr.h" +#include "spxprob.h" + +#define CHECK_ACCURACY 0 +/* (for debugging) */ + +struct csa +{ /* common storage area */ + SPXLP *lp; + /* LP problem data and its (current) basis; this LP has m rows + * and n columns */ + int dir; + /* original optimization direction: + * +1 - minimization + * -1 - maximization */ +#if SCALE_Z + double fz; + /* factor used to scale original objective */ +#endif + double *orig_c; /* double orig_c[1+n]; */ + /* copy of original objective coefficients */ + double *orig_l; /* double orig_l[1+n]; */ + /* copy of original lower bounds */ + double *orig_u; /* double orig_u[1+n]; */ + /* copy of original upper bounds */ + SPXAT *at; + /* mxn-matrix A of constraint coefficients, in sparse row-wise + * format (NULL if not used) */ + SPXNT *nt; + /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format (NULL if not used) */ + int phase; + /* search phase: + * 0 - not determined yet + * 1 - searching for primal feasible solution + * 2 - searching for optimal solution */ + double *beta; /* double beta[1+m]; */ + /* beta[i] is a primal value of basic variable xB[i] */ + int beta_st; + /* status of the vector beta: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + double *d; /* double d[1+n-m]; */ + /* d[j] is a reduced cost of non-basic variable xN[j] */ + int d_st; + /* status of the vector d: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + SPXSE *se; + /* projected steepest edge and Devex pricing data block (NULL if + * not used) */ + int num; + /* number of eligible non-basic variables */ + int *list; /* int list[1+n-m]; */ + /* list[1], ..., list[num] are indices j of eligible non-basic + * variables xN[j] */ + int q; + /* xN[q] is a non-basic variable chosen to enter the basis */ +#if 0 /* 11/VI-2017 */ + double *tcol; /* double tcol[1+m]; */ +#else + FVS tcol; /* FVS tcol[1:m]; */ +#endif + /* q-th (pivot) column of the simplex table */ +#if 1 /* 23/VI-2017 */ + SPXBP *bp; /* SPXBP bp[1+2*m+1]; */ + /* penalty function break points */ +#endif + int p; + /* xB[p] is a basic variable chosen to leave the basis; + * p = 0 means that no basic variable reaches its bound; + * p < 0 means that non-basic variable xN[q] reaches its opposite + * bound before any basic variable */ + int p_flag; + /* if this flag is set, the active bound of xB[p] in the adjacent + * basis should be set to the upper bound */ +#if 0 /* 11/VI-2017 */ + double *trow; /* double trow[1+n-m]; */ +#else + FVS trow; /* FVS trow[1:n-m]; */ +#endif + /* p-th (pivot) row of the simplex table */ +#if 0 /* 09/VII-2017 */ + double *work; /* double work[1+m]; */ + /* working array */ +#else + FVS work; /* FVS work[1:m]; */ + /* working vector */ +#endif + int p_stat, d_stat; + /* primal and dual solution statuses */ + /*--------------------------------------------------------------*/ + /* control parameters (see struct glp_smcp) */ + int msg_lev; + /* message level */ +#if 0 /* 23/VI-2017 */ + int harris; + /* ratio test technique: + * 0 - textbook ratio test + * 1 - Harris' two pass ratio test */ +#else + int r_test; + /* ratio test technique: + * GLP_RT_STD - textbook ratio test + * GLP_RT_HAR - Harris' two pass ratio test + * GLP_RT_FLIP - long-step ratio test (only for phase I) */ +#endif + double tol_bnd, tol_bnd1; + /* primal feasibility tolerances */ + double tol_dj, tol_dj1; + /* dual feasibility tolerances */ + double tol_piv; + /* pivot tolerance */ + int it_lim; + /* iteration limit */ + int tm_lim; + /* time limit, milliseconds */ + int out_frq; +#if 0 /* 15/VII-2017 */ + /* display output frequency, iterations */ +#else + /* display output frequency, milliseconds */ +#endif + int out_dly; + /* display output delay, milliseconds */ + /*--------------------------------------------------------------*/ + /* working parameters */ + double tm_beg; + /* time value at the beginning of the search */ + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + * basis changes (including the case when a non-basic variable + * jumps to its opposite bound) */ + int it_dpy; + /* simplex iteration count at most recent display output */ +#if 1 /* 15/VII-2017 */ + double tm_dpy; + /* time value at most recent display output */ +#endif + int inv_cnt; + /* basis factorization count since most recent display output */ +#if 1 /* 01/VII-2017 */ + int degen; + /* count of successive degenerate iterations; this count is used + * to detect stalling */ +#endif +#if 1 /* 23/VI-2017 */ + int ns_cnt, ls_cnt; + /* normal and long-step iteration counts */ +#endif +}; + +/*********************************************************************** +* set_penalty - set penalty function coefficients +* +* This routine sets up objective coefficients of the penalty function, +* which is the sum of primal infeasibilities, as follows: +* +* if beta[i] < l[k] - eps1, set c[k] = -1, +* +* if beta[i] > u[k] + eps2, set c[k] = +1, +* +* otherwise, set c[k] = 0, +* +* where beta[i] is current value of basic variable xB[i] = x[k], l[k] +* and u[k] are original bounds of x[k], and +* +* eps1 = tol + tol1 * |l[k]|, +* +* eps2 = tol + tol1 * |u[k]|. +* +* The routine returns the number of non-zero objective coefficients, +* which is the number of basic variables violating their bounds. Thus, +* if the value returned is zero, the current basis is primal feasible +* within the specified tolerances. */ + +static int set_penalty(struct csa *csa, double tol, double tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, count = 0; + double t, eps; + /* reset objective coefficients */ + for (k = 0; k <= n; k++) + c[k] = 0.0; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* check lower bound */ + if ((t = l[k]) != -DBL_MAX) + { eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] < t - eps) + { /* lower bound is violated */ + c[k] = -1.0, count++; + } + } + /* check upper bound */ + if ((t = u[k]) != +DBL_MAX) + { eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] > t + eps) + { /* upper bound is violated */ + c[k] = +1.0, count++; + } + } + } + return count; +} + +/*********************************************************************** +* check_feas - check primal feasibility of basic solution +* +* This routine checks if the specified values of all basic variables +* beta = (beta[i]) are within their bounds. +* +* Let l[k] and u[k] be original bounds of basic variable xB[i] = x[k]. +* The actual bounds of x[k] are determined as follows: +* +* 1) if phase = 1 and c[k] < 0, x[k] violates its lower bound, so its +* actual bounds are artificial: -inf < x[k] <= l[k]; +* +* 2) if phase = 1 and c[k] > 0, x[k] violates its upper bound, so its +* actual bounds are artificial: u[k] <= x[k] < +inf; +* +* 3) in all other cases (if phase = 1 and c[k] = 0, or if phase = 2) +* actual bounds are original: l[k] <= x[k] <= u[k]. +* +* The parameters tol and tol1 are bound violation tolerances. The +* actual bounds l'[k] and u'[k] are considered as non-violated within +* the specified tolerance if +* +* l'[k] - eps1 <= beta[i] <= u'[k] + eps2, +* +* where eps1 = tol + tol1 * |l'[k]|, eps2 = tol + tol1 * |u'[k]|. +* +* The routine returns one of the following codes: +* +* 0 - solution is feasible (no actual bounds are violated); +* +* 1 - solution is infeasible, however, only artificial bounds are +* violated (this is possible only if phase = 1); +* +* 2 - solution is infeasible and at least one original bound is +* violated. */ + +static int check_feas(struct csa *csa, int phase, double tol, double + tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, orig, ret = 0; + double lk, uk, eps; + xassert(phase == 1 || phase == 2); + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine actual bounds of x[k] */ + if (phase == 1 && c[k] < 0.0) + { /* -inf < x[k] <= l[k] */ + lk = -DBL_MAX, uk = l[k]; + orig = 0; /* artificial bounds */ + } + else if (phase == 1 && c[k] > 0.0) + { /* u[k] <= x[k] < +inf */ + lk = u[k], uk = +DBL_MAX; + orig = 0; /* artificial bounds */ + } + else + { /* l[k] <= x[k] <= u[k] */ + lk = l[k], uk = u[k]; + orig = 1; /* original bounds */ + } + /* check actual lower bound */ + if (lk != -DBL_MAX) + { eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* actual lower bound is violated */ + if (orig) + { ret = 2; + break; + } + ret = 1; + } + } + /* check actual upper bound */ + if (uk != +DBL_MAX) + { eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* actual upper bound is violated */ + if (orig) + { ret = 2; + break; + } + ret = 1; + } + } + } + return ret; +} + +/*********************************************************************** +* adjust_penalty - adjust penalty function coefficients +* +* On searching for primal feasible solution it may happen that some +* basic variable xB[i] = x[k] has non-zero objective coefficient c[k] +* indicating that xB[i] violates its lower (if c[k] < 0) or upper (if +* c[k] > 0) original bound, but due to primal degenarcy the violation +* is close to zero. +* +* This routine identifies such basic variables and sets objective +* coefficients at these variables to zero that allows avoiding zero- +* step simplex iterations. +* +* The parameters tol and tol1 are bound violation tolerances. The +* original bounds l[k] and u[k] are considered as non-violated within +* the specified tolerance if +* +* l[k] - eps1 <= beta[i] <= u[k] + eps2, +* +* where beta[i] is value of basic variable xB[i] = x[k] in the current +* basis, eps1 = tol + tol1 * |l[k]|, eps2 = tol + tol1 * |u[k]|. +* +* The routine returns the number of objective coefficients which were +* set to zero. */ + +#if 0 +static int adjust_penalty(struct csa *csa, double tol, double tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, count = 0; + double t, eps; + xassert(csa->phase == 1); + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (c[k] < 0.0) + { /* x[k] violates its original lower bound l[k] */ + xassert((t = l[k]) != -DBL_MAX); + eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] >= t - eps) + { /* however, violation is close to zero */ + c[k] = 0.0, count++; + } + } + else if (c[k] > 0.0) + { /* x[k] violates its original upper bound u[k] */ + xassert((t = u[k]) != +DBL_MAX); + eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] <= t + eps) + { /* however, violation is close to zero */ + c[k] = 0.0, count++; + } + } + } + return count; +} +#else +static int adjust_penalty(struct csa *csa, int num, const int + ind[/*1+num*/], double tol, double tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, t, cnt = 0; + double lk, uk, eps; + xassert(csa->phase == 1); + /* walk thru the specified list of basic variables */ + for (t = 1; t <= num; t++) + { i = ind[t]; + xassert(1 <= i && i <= m); + k = head[i]; /* x[k] = xB[i] */ + if (c[k] < 0.0) + { /* x[k] violates its original lower bound */ + lk = l[k]; + xassert(lk != -DBL_MAX); + eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] >= lk - eps) + { /* however, violation is close to zero */ + c[k] = 0.0, cnt++; + } + } + else if (c[k] > 0.0) + { /* x[k] violates its original upper bound */ + uk = u[k]; + xassert(uk != +DBL_MAX); + eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] <= uk + eps) + { /* however, violation is close to zero */ + c[k] = 0.0, cnt++; + } + } + } + return cnt; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_vec - compute maximal relative error between two vectors +* +* This routine computes and returns maximal relative error between +* n-vectors x and y: +* +* err_max = max |x[i] - y[i]| / (1 + |x[i]|). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_vec(int n, const double x[], const double y[]) +{ int i; + double err, err_max; + err_max = 0.0; + for (i = 1; i <= n; i++) + { err = fabs(x[i] - y[i]) / (1.0 + fabs(x[i])); + if (err_max < err) + err_max = err; + } + return err_max; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_beta - compute maximal relative error in vector beta +* +* This routine computes and returns maximal relative error in vector +* of values of basic variables beta = (beta[i]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_beta(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double err, *beta; + beta = talloc(1+m, double); + spx_eval_beta(lp, beta); + err = err_in_vec(m, beta, csa->beta); + tfree(beta); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_d - compute maximal relative error in vector d +* +* This routine computes and returns maximal relative error in vector +* of reduced costs of non-basic variables d = (d[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_d(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int j; + double err, *pi, *d; + pi = talloc(1+m, double); + d = talloc(1+n-m, double); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + err = err_in_vec(n-m, d, csa->d); + tfree(pi); + tfree(d); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_gamma - compute maximal relative error in vector gamma +* +* This routine computes and returns maximal relative error in vector +* of projected steepest edge weights gamma = (gamma[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_gamma(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + SPXSE *se = csa->se; + int j; + double err, *gamma; + xassert(se != NULL); + gamma = talloc(1+n-m, double); + for (j = 1; j <= n-m; j++) + gamma[j] = spx_eval_gamma_j(lp, se, j); + err = err_in_vec(n-m, gamma, se->gamma); + tfree(gamma); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* check_accuracy - check accuracy of basic solution components +* +* This routine checks accuracy of current basic solution components. +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static void check_accuracy(struct csa *csa) +{ double e_beta, e_d, e_gamma; + e_beta = err_in_beta(csa); + e_d = err_in_d(csa); + if (csa->se == NULL) + e_gamma = 0.; + else + e_gamma = err_in_gamma(csa); + xprintf("e_beta = %10.3e; e_d = %10.3e; e_gamma = %10.3e\n", + e_beta, e_d, e_gamma); + xassert(e_beta <= 1e-5 && e_d <= 1e-5 && e_gamma <= 1e-3); + return; +} +#endif + +/*********************************************************************** +* choose_pivot - choose xN[q] and xB[p] +* +* Given the list of eligible non-basic variables this routine first +* chooses non-basic variable xN[q]. This choice is always possible, +* because the list is assumed to be non-empty. Then the routine +* computes q-th column T[*,q] of the simplex table T[i,j] and chooses +* basic variable xB[p]. If the pivot T[p,q] is small in magnitude, +* the routine attempts to choose another xN[q] and xB[p] in order to +* avoid badly conditioned adjacent bases. */ + +#if 1 /* 17/III-2016 */ +#define MIN_RATIO 0.0001 + +static int choose_pivot(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *beta = csa->beta; + double *d = csa->d; + SPXSE *se = csa->se; + int *list = csa->list; +#if 0 /* 09/VII-2017 */ + double *tcol = csa->work; +#else + double *tcol = csa->work.vec; +#endif + double tol_piv = csa->tol_piv; + int try, nnn, /*i,*/ p, p_flag, q, t; + double big, /*temp,*/ best_ratio; +#if 1 /* 23/VI-2017 */ + double *c = lp->c; + int *head = lp->head; + SPXBP *bp = csa->bp; + int nbp, t_best, ret, k; + double dz_best; +#endif + xassert(csa->beta_st); + xassert(csa->d_st); +more: /* initial number of eligible non-basic variables */ + nnn = csa->num; + /* nothing has been chosen so far */ + csa->q = 0; + best_ratio = 0.0; +#if 0 /* 23/VI-2017 */ + try = 0; +#else + try = ret = 0; +#endif +try: /* choose non-basic variable xN[q] */ + xassert(nnn > 0); + try++; + if (se == NULL) + { /* Dantzig's rule */ + q = spx_chuzc_std(lp, d, nnn, list); + } + else + { /* projected steepest edge */ + q = spx_chuzc_pse(lp, se, d, nnn, list); + } + xassert(1 <= q && q <= n-m); + /* compute q-th column of the simplex table */ + spx_eval_tcol(lp, q, tcol); +#if 0 + /* big := max(1, |tcol[1]|, ..., |tcol[m]|) */ + big = 1.0; + for (i = 1; i <= m; i++) + { temp = tcol[i]; + if (temp < 0.0) + temp = - temp; + if (big < temp) + big = temp; + } +#else + /* this still puzzles me */ + big = 1.0; +#endif + /* choose basic variable xB[p] */ +#if 1 /* 23/VI-2017 */ + if (csa->phase == 1 && csa->r_test == GLP_RT_FLIP && try <= 2) + { /* long-step ratio test */ + int t, num, num1; + double slope, teta_lim; + /* determine penalty function break points */ + nbp = spx_ls_eval_bp(lp, beta, q, d[q], tcol, tol_piv, bp); + if (nbp < 2) + goto skip; + /* set initial slope */ + slope = - fabs(d[q]); + /* estimate initial teta_lim */ + teta_lim = DBL_MAX; + for (t = 1; t <= nbp; t++) + { if (teta_lim > bp[t].teta) + teta_lim = bp[t].teta; + } + xassert(teta_lim >= 0.0); + if (teta_lim < 1e-3) + teta_lim = 1e-3; + /* nothing has been chosen so far */ + t_best = 0, dz_best = 0.0, num = 0; + /* choose appropriate break point */ + while (num < nbp) + { /* select and process a new portion of break points */ + num1 = spx_ls_select_bp(lp, tcol, nbp, bp, num, &slope, + teta_lim); + for (t = num+1; t <= num1; t++) + { int i = (bp[t].i >= 0 ? bp[t].i : -bp[t].i); + xassert(0 <= i && i <= m); + if (i == 0 || fabs(tcol[i]) / big >= MIN_RATIO) + { if (dz_best > bp[t].dz) + t_best = t, dz_best = bp[t].dz; + } +#if 0 + if (i == 0) + { /* do not consider further break points beyond this + * point, where xN[q] reaches its opposite bound; + * in principle (see spx_ls_eval_bp), this break + * point should be the last one, however, due to + * round-off errors there may be other break points + * with the same teta beyond this one */ + slope = +1.0; + } +#endif + } + if (slope > 0.0) + { /* penalty function starts increasing */ + break; + } + /* penalty function continues decreasing */ + num = num1; + teta_lim += teta_lim; + } + if (dz_best == 0.0) + goto skip; + /* the choice has been made */ + xassert(1 <= t_best && t_best <= num1); + if (t_best == 1) + { /* the very first break point was chosen; it is reasonable + * to use the short-step ratio test */ + goto skip; + } + csa->q = q; + memcpy(&csa->tcol.vec[1], &tcol[1], m * sizeof(double)); + fvs_gather_vec(&csa->tcol, DBL_EPSILON); + if (bp[t_best].i == 0) + { /* xN[q] goes to its opposite bound */ + csa->p = -1; + csa->p_flag = 0; + best_ratio = 1.0; + } + else if (bp[t_best].i > 0) + { /* xB[p] leaves the basis and goes to its lower bound */ + csa->p = + bp[t_best].i; + xassert(1 <= csa->p && csa->p <= m); + csa->p_flag = 0; + best_ratio = fabs(tcol[csa->p]) / big; + } + else + { /* xB[p] leaves the basis and goes to its upper bound */ + csa->p = - bp[t_best].i; + xassert(1 <= csa->p && csa->p <= m); + csa->p_flag = 1; + best_ratio = fabs(tcol[csa->p]) / big; + } +#if 0 + xprintf("num1 = %d; t_best = %d; dz = %g\n", num1, t_best, + bp[t_best].dz); +#endif + ret = 1; + goto done; +skip: ; + } +#endif +#if 0 /* 23/VI-2017 */ + if (!csa->harris) +#else + if (csa->r_test == GLP_RT_STD) +#endif + { /* textbook ratio test */ + p = spx_chuzr_std(lp, csa->phase, beta, q, + d[q] < 0.0 ? +1. : -1., tcol, &p_flag, tol_piv, + .30 * csa->tol_bnd, .30 * csa->tol_bnd1); + } + else + { /* Harris' two-pass ratio test */ + p = spx_chuzr_harris(lp, csa->phase, beta, q, + d[q] < 0.0 ? +1. : -1., tcol, &p_flag , tol_piv, + .50 * csa->tol_bnd, .50 * csa->tol_bnd1); + } + if (p <= 0) + { /* primal unboundedness or special case */ + csa->q = q; +#if 0 /* 11/VI-2017 */ + memcpy(&csa->tcol[1], &tcol[1], m * sizeof(double)); +#else + memcpy(&csa->tcol.vec[1], &tcol[1], m * sizeof(double)); + fvs_gather_vec(&csa->tcol, DBL_EPSILON); +#endif + csa->p = p; + csa->p_flag = p_flag; + best_ratio = 1.0; + goto done; + } + /* either keep previous choice or accept new choice depending on + * which one is better */ + if (best_ratio < fabs(tcol[p]) / big) + { csa->q = q; +#if 0 /* 11/VI-2017 */ + memcpy(&csa->tcol[1], &tcol[1], m * sizeof(double)); +#else + memcpy(&csa->tcol.vec[1], &tcol[1], m * sizeof(double)); + fvs_gather_vec(&csa->tcol, DBL_EPSILON); +#endif + csa->p = p; + csa->p_flag = p_flag; + best_ratio = fabs(tcol[p]) / big; + } + /* check if the current choice is acceptable */ + if (best_ratio >= MIN_RATIO || nnn == 1 || try == 5) + goto done; + /* try to choose other xN[q] and xB[p] */ + /* find xN[q] in the list */ + for (t = 1; t <= nnn; t++) + if (list[t] == q) break; + xassert(t <= nnn); + /* move xN[q] to the end of the list */ + list[t] = list[nnn], list[nnn] = q; + /* and exclude it from consideration */ + nnn--; + /* repeat the choice */ + goto try; +done: /* the choice has been made */ +#if 1 /* FIXME: currently just to avoid badly conditioned basis */ + if (best_ratio < .001 * MIN_RATIO) + { /* looks like this helps */ + if (bfd_get_count(lp->bfd) > 0) + return -1; + /* didn't help; last chance to improve the choice */ + if (tol_piv == csa->tol_piv) + { tol_piv *= 1000.; + goto more; + } + } +#endif +#if 0 /* 23/VI-2017 */ + return 0; +#else /* FIXME */ + if (ret) + { /* invalidate dual basic solution components */ + csa->d_st = 0; + /* change penalty function coefficients at basic variables for + * all break points preceding the chosen one */ + for (t = 1; t < t_best; t++) + { int i = (bp[t].i >= 0 ? bp[t].i : -bp[t].i); + xassert(0 <= i && i <= m); + if (i == 0) + { /* xN[q] crosses its opposite bound */ + xassert(1 <= csa->q && csa->q <= n-m); + k = head[m+csa->q]; + } + else + { /* xB[i] crosses its (lower or upper) bound */ + k = head[i]; /* x[k] = xB[i] */ + } + c[k] += bp[t].dc; + xassert(c[k] == 0.0 || c[k] == +1.0 || c[k] == -1.0); + } + } + return ret; +#endif +} +#endif + +/*********************************************************************** +* play_bounds - play bounds of primal variables +* +* This routine is called after the primal values of basic variables +* beta[i] were updated and the basis was changed to the adjacent one. +* +* It is assumed that before updating all the primal values beta[i] +* were strongly feasible, so in the adjacent basis beta[i] remain +* feasible within a tolerance, i.e. if some beta[i] violates its lower +* or upper bound, the violation is insignificant. +* +* If some beta[i] violates its lower or upper bound, this routine +* changes (perturbs) the bound to remove such violation, i.e. to make +* all beta[i] strongly feasible. Otherwise, if beta[i] has a feasible +* value, this routine attempts to reduce (or remove) perturbation of +* corresponding lower/upper bound keeping strong feasibility. */ + +/* FIXME: what to do if l[k] = u[k]? */ + +/* FIXME: reduce/remove perturbation if x[k] becomes non-basic? */ + +static void play_bounds(struct csa *csa, int all) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *orig_l = csa->orig_l; + double *orig_u = csa->orig_u; + double *beta = csa->beta; +#if 0 /* 11/VI-2017 */ + const double *tcol = csa->tcol; /* was used to update beta */ +#else + const double *tcol = csa->tcol.vec; +#endif + int i, k; + xassert(csa->phase == 1 || csa->phase == 2); + /* primal values beta = (beta[i]) should be valid */ + xassert(csa->beta_st); + /* walk thru the list of basic variables xB = (xB[i]) */ + for (i = 1; i <= m; i++) + { if (all || tcol[i] != 0.0) + { /* beta[i] has changed in the adjacent basis */ + k = head[i]; /* x[k] = xB[i] */ + if (csa->phase == 1 && c[k] < 0.0) + { /* -inf < xB[i] <= lB[i] (artificial bounds) */ + if (beta[i] < l[k] - 1e-9) + continue; + /* restore actual bounds */ + c[k] = 0.0; + csa->d_st = 0; /* since c[k] = cB[i] has changed */ + } + if (csa->phase == 1 && c[k] > 0.0) + { /* uB[i] <= xB[i] < +inf (artificial bounds) */ + if (beta[i] > u[k] + 1e-9) + continue; + /* restore actual bounds */ + c[k] = 0.0; + csa->d_st = 0; /* since c[k] = cB[i] has changed */ + } + /* lB[i] <= xB[i] <= uB[i] */ + if (csa->phase == 1) + xassert(c[k] == 0.0); + if (l[k] != -DBL_MAX) + { /* xB[i] has lower bound */ + if (beta[i] < l[k]) + { /* strong feasibility means xB[i] >= lB[i] */ +#if 0 /* 11/VI-2017 */ + l[k] = beta[i]; +#else + l[k] = beta[i] - 1e-9; +#endif + } + else if (l[k] < orig_l[k]) + { /* remove/reduce perturbation of lB[i] */ + if (beta[i] >= orig_l[k]) + l[k] = orig_l[k]; + else + l[k] = beta[i]; + } + } + if (u[k] != +DBL_MAX) + { /* xB[i] has upper bound */ + if (beta[i] > u[k]) + { /* strong feasibility means xB[i] <= uB[i] */ +#if 0 /* 11/VI-2017 */ + u[k] = beta[i]; +#else + u[k] = beta[i] + 1e-9; +#endif + } + else if (u[k] > orig_u[k]) + { /* remove/reduce perturbation of uB[i] */ + if (beta[i] <= orig_u[k]) + u[k] = orig_u[k]; + else + u[k] = beta[i]; + } + } + } + } + return; +} + +static void remove_perturb(struct csa *csa) +{ /* remove perturbation */ + SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *orig_l = csa->orig_l; + double *orig_u = csa->orig_u; + int j, k; + /* restore original bounds of variables */ + memcpy(l, orig_l, (1+n) * sizeof(double)); + memcpy(u, orig_u, (1+n) * sizeof(double)); + /* adjust flags of fixed non-basic variables, because in the + * perturbed problem such variables might be changed to double- + * bounded type */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + flag[j] = 0; + } + /* removing perturbation changes primal solution components */ + csa->phase = csa->beta_st = 0; +#if 1 + if (csa->msg_lev >= GLP_MSG_ALL) + xprintf("Removing LP perturbation [%d]...\n", + csa->it_cnt); +#endif + return; +} + +/*********************************************************************** +* sum_infeas - compute sum of primal infeasibilities +* +* This routine compute the sum of primal infeasibilities, which is the +* current penalty function value. */ + +static double sum_infeas(SPXLP *lp, const double beta[/*1+m*/]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k; + double sum = 0.0; + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (l[k] != -DBL_MAX && beta[i] < l[k]) + sum += l[k] - beta[i]; + if (u[k] != +DBL_MAX && beta[i] > u[k]) + sum += beta[i] - u[k]; + } + return sum; +} + +/*********************************************************************** +* display - display search progress +* +* This routine displays some information about the search progress +* that includes: +* +* search phase; +* +* number of simplex iterations performed by the solver; +* +* original objective value; +* +* sum of (scaled) primal infeasibilities; +* +* number of infeasibilities (phase I) or non-optimalities (phase II); +* +* number of basic factorizations since last display output. */ + +static void display(struct csa *csa, int spec) +{ int nnn, k; + double obj, sum, *save, *save1; +#if 1 /* 15/VII-2017 */ + double tm_cur; +#endif + /* check if the display output should be skipped */ + if (csa->msg_lev < GLP_MSG_ON) goto skip; +#if 1 /* 15/VII-2017 */ + tm_cur = xtime(); +#endif + if (csa->out_dly > 0 && +#if 0 /* 15/VII-2017 */ + 1000.0 * xdifftime(xtime(), csa->tm_beg) < csa->out_dly) +#else + 1000.0 * xdifftime(tm_cur, csa->tm_beg) < csa->out_dly) +#endif + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; +#if 0 /* 15/VII-2017 */ + if (!spec && csa->it_cnt % csa->out_frq != 0) goto skip; +#else + if (!spec && + 1000.0 * xdifftime(tm_cur, csa->tm_dpy) < csa->out_frq) + goto skip; +#endif + /* compute original objective value */ + save = csa->lp->c; + csa->lp->c = csa->orig_c; + obj = csa->dir * spx_eval_obj(csa->lp, csa->beta); + csa->lp->c = save; +#if SCALE_Z + obj *= csa->fz; +#endif + /* compute sum of (scaled) primal infeasibilities */ +#if 1 /* 01/VII-2017 */ + save = csa->lp->l; + save1 = csa->lp->u; + csa->lp->l = csa->orig_l; + csa->lp->u = csa->orig_u; +#endif + sum = sum_infeas(csa->lp, csa->beta); +#if 1 /* 01/VII-2017 */ + csa->lp->l = save; + csa->lp->u = save1; +#endif + /* compute number of infeasibilities/non-optimalities */ + switch (csa->phase) + { case 1: + nnn = 0; + for (k = 1; k <= csa->lp->n; k++) + if (csa->lp->c[k] != 0.0) nnn++; + break; + case 2: + xassert(csa->d_st); + nnn = spx_chuzc_sel(csa->lp, csa->d, csa->tol_dj, + csa->tol_dj1, NULL); + break; + default: + xassert(csa != csa); + } + /* display search progress */ + xprintf("%c%6d: obj = %17.9e inf = %11.3e (%d)", + csa->phase == 2 ? '*' : ' ', csa->it_cnt, obj, sum, nnn); + if (csa->inv_cnt) + { /* number of basis factorizations performed */ + xprintf(" %d", csa->inv_cnt); + csa->inv_cnt = 0; + } +#if 1 /* 23/VI-2017 */ + if (csa->phase == 1 && csa->r_test == GLP_RT_FLIP) + { /*xprintf(" %d,%d", csa->ns_cnt, csa->ls_cnt);*/ + if (csa->ns_cnt + csa->ls_cnt) + xprintf(" %d%%", + (100 * csa->ls_cnt) / (csa->ns_cnt + csa->ls_cnt)); + csa->ns_cnt = csa->ls_cnt = 0; + } +#endif + xprintf("\n"); + csa->it_dpy = csa->it_cnt; +#if 1 /* 15/VII-2017 */ + csa->tm_dpy = tm_cur; +#endif +skip: return; +} + +/*********************************************************************** +* spx_primal - driver to the primal simplex method +* +* This routine is a driver to the two-phase primal simplex method. +* +* On exit this routine returns one of the following codes: +* +* 0 LP instance has been successfully solved. +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +static int primal_simplex(struct csa *csa) +{ /* primal simplex method main logic routine */ + SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + int *head = lp->head; + SPXAT *at = csa->at; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPXSE *se = csa->se; + int *list = csa->list; +#if 0 /* 11/VI-2017 */ + double *tcol = csa->tcol; + double *trow = csa->trow; +#endif +#if 0 /* 09/VII-2017 */ + double *pi = csa->work; + double *rho = csa->work; +#else + double *pi = csa->work.vec; + double *rho = csa->work.vec; +#endif + int msg_lev = csa->msg_lev; + double tol_bnd = csa->tol_bnd; + double tol_bnd1 = csa->tol_bnd1; + double tol_dj = csa->tol_dj; + double tol_dj1 = csa->tol_dj1; + int perturb = -1; + /* -1 = perturbation is not used, but enabled + * 0 = perturbation is not used and disabled + * +1 = perturbation is being used */ + int j, refct, ret; +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (!lp->valid) + { double cond; + ret = spx_factorize(lp); + csa->inv_cnt++; + if (ret != 0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + /* check condition of the basis matrix */ + cond = bfd_condest(lp->bfd); + if (cond > 1.0 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: basis matrix is singular to working prec" + "ision (cond = %.3g)\n", cond); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + if (cond > 0.001 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: basis matrix is ill-conditioned (cond " + "= %.3g)\n", cond); + } + /* invalidate basic solution components */ + csa->beta_st = csa->d_st = 0; + } + /* compute values of basic variables beta = (beta[i]) */ + if (!csa->beta_st) + { spx_eval_beta(lp, beta); + csa->beta_st = 1; /* just computed */ + /* determine the search phase, if not determined yet */ + if (!csa->phase) + { if (set_penalty(csa, 0.97 * tol_bnd, 0.97 * tol_bnd1)) + { /* current basic solution is primal infeasible */ + /* start to minimize the sum of infeasibilities */ + csa->phase = 1; + } + else + { /* current basic solution is primal feasible */ + /* start to minimize the original objective function */ + csa->phase = 2; + memcpy(c, csa->orig_c, (1+n) * sizeof(double)); + } + /* working objective coefficients have been changed, so + * invalidate reduced costs */ + csa->d_st = 0; + } + /* make sure that the current basic solution remains primal + * feasible (or pseudo-feasible on phase I) */ + if (perturb <= 0) + { if (check_feas(csa, csa->phase, tol_bnd, tol_bnd1)) + { /* excessive bound violations due to round-off errors */ +#if 1 /* 01/VII-2017 */ + if (perturb < 0) + { if (msg_lev >= GLP_MSG_ALL) + xprintf("Perturbing LP to avoid instability [%d].." + ".\n", csa->it_cnt); + perturb = 1; + goto loop; + } +#endif + if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (primal simpl" + "ex, phase %s)\n", csa->phase == 1 ? "I" : "II"); + /* restart the search */ + lp->valid = 0; + csa->phase = 0; + goto loop; + } + if (csa->phase == 1) + { int i, cnt; + for (i = 1; i <= m; i++) + csa->tcol.ind[i] = i; + cnt = adjust_penalty(csa, m, csa->tcol.ind, + 0.99 * tol_bnd, 0.99 * tol_bnd1); + if (cnt) + { /*xprintf("*** cnt = %d\n", cnt);*/ + csa->d_st = 0; + } + } + } + else + { /* FIXME */ + play_bounds(csa, 1); + } + } + /* at this point the search phase is determined */ + xassert(csa->phase == 1 || csa->phase == 2); + /* compute reduced costs of non-basic variables d = (d[j]) */ + if (!csa->d_st) + { spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->d_st = 1; /* just computed */ + } + /* reset the reference space, if necessary */ + if (se != NULL && !se->valid) + spx_reset_refsp(lp, se), refct = 1000; + /* at this point the basis factorization and all basic solution + * components are valid */ + xassert(lp->valid && csa->beta_st && csa->d_st); +#if CHECK_ACCURACY + /* check accuracy of current basic solution components (only for + * debugging) */ + check_accuracy(csa); +#endif + /* check if the iteration limit has been exhausted */ + if (csa->it_cnt - csa->it_beg >= csa->it_lim) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + csa->p_stat = (csa->phase == 2 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = GLP_EITLIM; + goto fini; + } + /* check if the time limit has been exhausted */ + if (1000.0 * xdifftime(xtime(), csa->tm_beg) >= csa->tm_lim) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + csa->p_stat = (csa->phase == 2 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = GLP_ETMLIM; + goto fini; + } + /* display the search progress */ + display(csa, 0); + /* select eligible non-basic variables */ + switch (csa->phase) + { case 1: + csa->num = spx_chuzc_sel(lp, d, 1e-8, 0.0, list); + break; + case 2: + csa->num = spx_chuzc_sel(lp, d, tol_dj, tol_dj1, list); + break; + default: + xassert(csa != csa); + } + /* check for optimality */ + if (csa->num == 0) + { if (perturb > 0 && csa->phase == 2) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + /* current basis is optimal */ + display(csa, 1); + switch (csa->phase) + { case 1: + /* check for primal feasibility */ + if (!check_feas(csa, 2, tol_bnd, tol_bnd1)) + { /* feasible solution found; switch to phase II */ + memcpy(c, csa->orig_c, (1+n) * sizeof(double)); + csa->phase = 2; + csa->d_st = 0; + goto loop; + } + /* no feasible solution exists */ +#if 1 /* 09/VII-2017 */ + /* FIXME: remove perturbation */ +#endif + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); + csa->p_stat = GLP_NOFEAS; + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = 0; + goto fini; + case 2: + /* optimal solution found */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL LP SOLUTION FOUND\n"); + csa->p_stat = csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* choose xN[q] and xB[p] */ +#if 0 /* 23/VI-2017 */ +#if 0 /* 17/III-2016 */ + choose_pivot(csa); +#else + if (choose_pivot(csa) < 0) + { lp->valid = 0; + goto loop; + } +#endif +#else + ret = choose_pivot(csa); + if (ret < 0) + { lp->valid = 0; + goto loop; + } + if (ret == 0) + csa->ns_cnt++; + else + csa->ls_cnt++; +#endif + /* check for unboundedness */ + if (csa->p == 0) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + switch (csa->phase) + { case 1: + /* this should never happen */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: primal simplex failed\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + case 2: + /* primal unboundedness detected */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS UNBOUNDED PRIMAL SOLUTION\n"); + csa->p_stat = GLP_FEAS; + csa->d_stat = GLP_NOFEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } +#if 1 /* 01/VII-2017 */ + /* check for stalling */ + if (csa->p > 0) + { int k; + xassert(1 <= csa->p && csa->p <= m); + k = head[csa->p]; /* x[k] = xB[p] */ + if (lp->l[k] != lp->u[k]) + { if (csa->p_flag) + { /* xB[p] goes to its upper bound */ + xassert(lp->u[k] != +DBL_MAX); + if (fabs(beta[csa->p] - lp->u[k]) >= 1e-6) + { csa->degen = 0; + goto skip1; + } + } + else if (lp->l[k] == -DBL_MAX) + { /* unusual case */ + goto skip1; + } + else + { /* xB[p] goes to its lower bound */ + xassert(lp->l[k] != -DBL_MAX); + if (fabs(beta[csa->p] - lp->l[k]) >= 1e-6) + { csa->degen = 0; + goto skip1; + } + } + /* degenerate iteration has been detected */ + csa->degen++; + if (perturb < 0 && csa->degen >= 200) + { if (msg_lev >= GLP_MSG_ALL) + xprintf("Perturbing LP to avoid stalling [%d]...\n", + csa->it_cnt); + perturb = 1; + } +skip1: ; + } + } +#endif + /* update values of basic variables for adjacent basis */ +#if 0 /* 11/VI-2017 */ + spx_update_beta(lp, beta, csa->p, csa->p_flag, csa->q, tcol); +#else + spx_update_beta_s(lp, beta, csa->p, csa->p_flag, csa->q, + &csa->tcol); +#endif + csa->beta_st = 2; + /* p < 0 means that xN[q] jumps to its opposite bound */ + if (csa->p < 0) + goto skip; + /* xN[q] enters and xB[p] leaves the basis */ + /* compute p-th row of inv(B) */ + spx_eval_rho(lp, csa->p, rho); + /* compute p-th (pivot) row of the simplex table */ +#if 0 /* 11/VI-2017 */ + if (at != NULL) + spx_eval_trow1(lp, at, rho, trow); + else + spx_nt_prod(lp, nt, trow, 1, -1.0, rho); +#else + if (at != NULL) + spx_eval_trow1(lp, at, rho, csa->trow.vec); + else + spx_nt_prod(lp, nt, csa->trow.vec, 1, -1.0, rho); + fvs_gather_vec(&csa->trow, DBL_EPSILON); +#endif + /* FIXME: tcol[p] and trow[q] should be close to each other */ +#if 0 /* 26/V-2017 by cmatraki */ + xassert(trow[csa->q] != 0.0); +#else + if (csa->trow.vec[csa->q] == 0.0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: trow[q] = 0.0\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } +#endif + /* update reduced costs of non-basic variables for adjacent + * basis */ +#if 1 /* 23/VI-2017 */ + /* dual solution may be invalidated due to long step */ + if (csa->d_st) +#endif +#if 0 /* 11/VI-2017 */ + if (spx_update_d(lp, d, csa->p, csa->q, trow, tcol) <= 1e-9) +#else + if (spx_update_d_s(lp, d, csa->p, csa->q, &csa->trow, &csa->tcol) + <= 1e-9) +#endif + { /* successful updating */ + csa->d_st = 2; + if (csa->phase == 1) + { /* adjust reduced cost of xN[q] in adjacent basis, since + * its penalty coefficient changes (see below) */ + d[csa->q] -= c[head[csa->p]]; + } + } + else + { /* new reduced costs are inaccurate */ + csa->d_st = 0; + } + if (csa->phase == 1) + { /* xB[p] leaves the basis replacing xN[q], so set its penalty + * coefficient to zero */ + c[head[csa->p]] = 0.0; + } + /* update steepest edge weights for adjacent basis, if used */ + if (se != NULL) + { if (refct > 0) +#if 0 /* 11/VI-2017 */ + { if (spx_update_gamma(lp, se, csa->p, csa->q, trow, tcol) + <= 1e-3) +#else /* FIXME: spx_update_gamma_s */ + { if (spx_update_gamma(lp, se, csa->p, csa->q, csa->trow.vec, + csa->tcol.vec) <= 1e-3) +#endif + { /* successful updating */ + refct--; + } + else + { /* new weights are inaccurate; reset reference space */ + se->valid = 0; + } + } + else + { /* too many updates; reset reference space */ + se->valid = 0; + } + } + /* update matrix N for adjacent basis, if used */ + if (nt != NULL) + spx_update_nt(lp, nt, csa->p, csa->q); +skip: /* change current basis header to adjacent one */ + spx_change_basis(lp, csa->p, csa->p_flag, csa->q); + /* and update factorization of the basis matrix */ + if (csa->p > 0) + spx_update_invb(lp, csa->p, head[csa->p]); +#if 1 + if (perturb <= 0) + { if (csa->phase == 1) + { int cnt; + /* adjust penalty function coefficients */ + cnt = adjust_penalty(csa, csa->tcol.nnz, csa->tcol.ind, + 0.99 * tol_bnd, 0.99 * tol_bnd1); + if (cnt) + { /* some coefficients were changed, so invalidate reduced + * costs of non-basic variables */ + /*xprintf("... cnt = %d\n", cnt);*/ + csa->d_st = 0; + } + } + } + else + { /* FIXME */ + play_bounds(csa, 0); + } +#endif + /* simplex iteration complete */ + csa->it_cnt++; + goto loop; +fini: /* restore original objective function */ + memcpy(c, csa->orig_c, (1+n) * sizeof(double)); + /* compute reduced costs of non-basic variables and determine + * solution dual status, if necessary */ + if (csa->p_stat != GLP_UNDEF && csa->d_stat == GLP_UNDEF) + { xassert(ret != GLP_EFAIL); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->num = spx_chuzc_sel(lp, d, tol_dj, tol_dj1, NULL); + csa->d_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + } + return ret; +} + +int spx_primal(glp_prob *P, const glp_smcp *parm) +{ /* driver to the primal simplex method */ + struct csa csa_, *csa = &csa_; + SPXLP lp; + SPXAT at; + SPXNT nt; + SPXSE se; + int ret, *map, *daeh; +#if SCALE_Z + int i, j, k; +#endif + /* build working LP and its initial basis */ + memset(csa, 0, sizeof(struct csa)); + csa->lp = &lp; + spx_init_lp(csa->lp, P, parm->excl); + spx_alloc_lp(csa->lp); + map = talloc(1+P->m+P->n, int); + spx_build_lp(csa->lp, P, parm->excl, parm->shift, map); + spx_build_basis(csa->lp, P, map); + switch (P->dir) + { case GLP_MIN: + csa->dir = +1; + break; + case GLP_MAX: + csa->dir = -1; + break; + default: + xassert(P != P); + } +#if SCALE_Z + csa->fz = 0.0; + for (k = 1; k <= csa->lp->n; k++) + { double t = fabs(csa->lp->c[k]); + if (csa->fz < t) + csa->fz = t; + } + if (csa->fz <= 1000.0) + csa->fz = 1.0; + else + csa->fz /= 1000.0; + /*xprintf("csa->fz = %g\n", csa->fz);*/ + for (k = 0; k <= csa->lp->n; k++) + csa->lp->c[k] /= csa->fz; +#endif + csa->orig_c = talloc(1+csa->lp->n, double); + memcpy(csa->orig_c, csa->lp->c, (1+csa->lp->n) * sizeof(double)); +#if 1 /*PERTURB*/ + csa->orig_l = talloc(1+csa->lp->n, double); + memcpy(csa->orig_l, csa->lp->l, (1+csa->lp->n) * sizeof(double)); + csa->orig_u = talloc(1+csa->lp->n, double); + memcpy(csa->orig_u, csa->lp->u, (1+csa->lp->n) * sizeof(double)); +#else + csa->orig_l = csa->orig_u = NULL; +#endif + switch (parm->aorn) + { case GLP_USE_AT: + /* build matrix A in row-wise format */ + csa->at = &at; + csa->nt = NULL; + spx_alloc_at(csa->lp, csa->at); + spx_build_at(csa->lp, csa->at); + break; + case GLP_USE_NT: + /* build matrix N in row-wise format for initial basis */ + csa->at = NULL; + csa->nt = &nt; + spx_alloc_nt(csa->lp, csa->nt); + spx_init_nt(csa->lp, csa->nt); + spx_build_nt(csa->lp, csa->nt); + break; + default: + xassert(parm != parm); + } + /* allocate and initialize working components */ + csa->phase = 0; + csa->beta = talloc(1+csa->lp->m, double); + csa->beta_st = 0; + csa->d = talloc(1+csa->lp->n-csa->lp->m, double); + csa->d_st = 0; + switch (parm->pricing) + { case GLP_PT_STD: + csa->se = NULL; + break; + case GLP_PT_PSE: + csa->se = &se; + spx_alloc_se(csa->lp, csa->se); + break; + default: + xassert(parm != parm); + } + csa->list = talloc(1+csa->lp->n-csa->lp->m, int); +#if 0 /* 11/VI-2017 */ + csa->tcol = talloc(1+csa->lp->m, double); + csa->trow = talloc(1+csa->lp->n-csa->lp->m, double); +#else + fvs_alloc_vec(&csa->tcol, csa->lp->m); + fvs_alloc_vec(&csa->trow, csa->lp->n-csa->lp->m); +#endif +#if 1 /* 23/VI-2017 */ + csa->bp = NULL; +#endif +#if 0 /* 09/VII-2017 */ + csa->work = talloc(1+csa->lp->m, double); +#else + fvs_alloc_vec(&csa->work, csa->lp->m); +#endif + /* initialize control parameters */ + csa->msg_lev = parm->msg_lev; +#if 0 /* 23/VI-2017 */ + switch (parm->r_test) + { case GLP_RT_STD: + csa->harris = 0; + break; + case GLP_RT_HAR: +#if 1 /* 16/III-2016 */ + case GLP_RT_FLIP: + /* FIXME */ + /* currently for primal simplex GLP_RT_FLIP is equivalent + * to GLP_RT_HAR */ +#endif + csa->harris = 1; + break; + default: + xassert(parm != parm); + } +#else + switch (parm->r_test) + { case GLP_RT_STD: + case GLP_RT_HAR: + break; + case GLP_RT_FLIP: + csa->bp = talloc(1+2*csa->lp->m+1, SPXBP); + break; + default: + xassert(parm != parm); + } + csa->r_test = parm->r_test; +#endif + csa->tol_bnd = parm->tol_bnd; + csa->tol_bnd1 = .001 * parm->tol_bnd; + csa->tol_dj = parm->tol_dj; + csa->tol_dj1 = .001 * parm->tol_dj; + csa->tol_piv = parm->tol_piv; + csa->it_lim = parm->it_lim; + csa->tm_lim = parm->tm_lim; + csa->out_frq = parm->out_frq; + csa->out_dly = parm->out_dly; + /* initialize working parameters */ + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = P->it_cnt; + csa->it_dpy = -1; +#if 1 /* 15/VII-2017 */ + csa->tm_dpy = 0.0; +#endif + csa->inv_cnt = 0; +#if 1 /* 01/VII-2017 */ + csa->degen = 0; +#endif +#if 1 /* 23/VI-2017 */ + csa->ns_cnt = csa->ls_cnt = 0; +#endif + /* try to solve working LP */ + ret = primal_simplex(csa); + /* return basis factorization back to problem object */ + P->valid = csa->lp->valid; + P->bfd = csa->lp->bfd; + /* set solution status */ + P->pbs_stat = csa->p_stat; + P->dbs_stat = csa->d_stat; + /* if the solver failed, do not store basis header and basic + * solution components to problem object */ + if (ret == GLP_EFAIL) + goto skip; + /* convert working LP basis to original LP basis and store it to + * problem object */ + daeh = talloc(1+csa->lp->n, int); + spx_store_basis(csa->lp, P, map, daeh); + /* compute simplex multipliers for final basic solution found by + * the solver */ +#if 0 /* 09/VII-2017 */ + spx_eval_pi(csa->lp, csa->work); +#else + spx_eval_pi(csa->lp, csa->work.vec); +#endif + /* convert working LP solution to original LP solution and store + * it into the problem object */ +#if SCALE_Z + for (i = 1; i <= csa->lp->m; i++) + csa->work.vec[i] *= csa->fz; + for (j = 1; j <= csa->lp->n-csa->lp->m; j++) + csa->d[j] *= csa->fz; +#endif +#if 0 /* 09/VII-2017 */ + spx_store_sol(csa->lp, P, SHIFT, map, daeh, csa->beta, csa->work, + csa->d); +#else + spx_store_sol(csa->lp, P, parm->shift, map, daeh, csa->beta, + csa->work.vec, csa->d); +#endif + tfree(daeh); + /* save simplex iteration count */ + P->it_cnt = csa->it_cnt; + /* report auxiliary/structural variable causing unboundedness */ + P->some = 0; + if (csa->p_stat == GLP_FEAS && csa->d_stat == GLP_NOFEAS) + { int k, kk; + /* xN[q] = x[k] causes unboundedness */ + xassert(1 <= csa->q && csa->q <= csa->lp->n - csa->lp->m); + k = csa->lp->head[csa->lp->m + csa->q]; + xassert(1 <= k && k <= csa->lp->n); + /* convert to number of original variable */ + for (kk = 1; kk <= P->m + P->n; kk++) + { if (abs(map[kk]) == k) + { P->some = kk; + break; + } + } + xassert(P->some != 0); + } +skip: /* deallocate working objects and arrays */ + spx_free_lp(csa->lp); + tfree(map); + tfree(csa->orig_c); +#if 1 /*PERTURB*/ + tfree(csa->orig_l); + tfree(csa->orig_u); +#endif + if (csa->at != NULL) + spx_free_at(csa->lp, csa->at); + if (csa->nt != NULL) + spx_free_nt(csa->lp, csa->nt); + tfree(csa->beta); + tfree(csa->d); + if (csa->se != NULL) + spx_free_se(csa->lp, csa->se); + tfree(csa->list); +#if 0 /* 11/VI-2017 */ + tfree(csa->tcol); + tfree(csa->trow); +#else + fvs_free_vec(&csa->tcol); + fvs_free_vec(&csa->trow); +#endif +#if 1 /* 23/VI-2017 */ + if (csa->bp != NULL) + tfree(csa->bp); +#endif +#if 0 /* 09/VII-2017 */ + tfree(csa->work); +#else + fvs_free_vec(&csa->work); +#endif + /* return to calling program */ + return ret; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.c new file mode 100644 index 000000000..4bebe2e74 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.c @@ -0,0 +1,679 @@ +/* spxprob.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxprob.h" + +/*********************************************************************** +* spx_init_lp - initialize working LP object +* +* This routine determines the number of equality constraints m, the +* number of variables n, and the number of non-zero elements nnz in +* the constraint matrix for the working LP, which corresponds to the +* original LP, and stores these dimensions to the working LP object. +* (The working LP object should be allocated by the calling routine.) +* +* If the flag excl is set, the routine assumes that non-basic fixed +* variables will be excluded from the working LP. */ + +void spx_init_lp(SPXLP *lp, glp_prob *P, int excl) +{ int i, j, m, n, nnz; + m = P->m; + xassert(m > 0); + n = 0; + nnz = P->nnz; + xassert(P->valid); + /* scan rows of original LP */ + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if (excl && row->stat == GLP_NS) + { /* skip non-basic fixed auxiliary variable */ + /* nop */ + } + else + { /* include auxiliary variable in working LP */ + n++; + nnz++; /* unity column */ + } + } + /* scan columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (excl && col->stat == GLP_NS) + { /* skip non-basic fixed structural variable */ + GLPAIJ *aij; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + nnz--; + } + else + { /* include structural variable in working LP */ + n++; + } + } + /* initialize working LP data block */ + memset(lp, 0, sizeof(SPXLP)); + lp->m = m; + xassert(n > 0); + lp->n = n; + lp->nnz = nnz; + return; +} + +/*********************************************************************** +* spx_alloc_lp - allocate working LP arrays +* +* This routine allocates the memory for all arrays in the working LP +* object. */ + +void spx_alloc_lp(SPXLP *lp) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + lp->A_ptr = talloc(1+n+1, int); + lp->A_ind = talloc(1+nnz, int); + lp->A_val = talloc(1+nnz, double); + lp->b = talloc(1+m, double); + lp->c = talloc(1+n, double); + lp->l = talloc(1+n, double); + lp->u = talloc(1+n, double); + lp->head = talloc(1+n, int); + lp->flag = talloc(1+n-m, char); + return; +} + +/*********************************************************************** +* spx_build_lp - convert original LP to working LP +* +* This routine converts components (except the current basis) of the +* original LP to components of the working LP and perform scaling of +* these components. Also, if the original LP is maximization, the +* routine changes the signs of the objective coefficients and constant +* term to opposite ones. +* +* If the flag excl is set, original non-basic fixed variables are +* *not* included in the working LP. Otherwise, all (auxiliary and +* structural) original variables are included in the working LP. Note +* that this flag should have the same value as it has in a call to the +* routine spx_init_lp. +* +* If the flag shift is set, the routine shift bounds of variables +* included in the working LP to make at least one bound to be zero. +* If a variable has both lower and upper bounds, the bound having +* smaller magnitude is shifted to zero. +* +* On exit the routine stores information about correspondence between +* numbers of variables in the original and working LPs to the array +* map, which should have 1+P->m+P->n locations (location [0] is not +* used), where P->m is the numbers of rows and P->n is the number of +* columns in the original LP: +* +* map[i] = +k, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP corresponds to variable x[k] of the working LP; +* +* map[i] = -k, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP corresponds to variable x[k] of the working LP, and +* the upper bound of that variable was shifted to zero; +* +* map[i] = 0, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP was excluded from the working LP; +* +* map[P->m+j], 1 <= j <= P->n, has the same sense as above, however, +* for j-th structural variable of the original LP. */ + +void spx_build_lp(SPXLP *lp, glp_prob *P, int excl, int shift, + int map[/*1+P->m+P->n*/]) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + double *b = lp->b; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int i, j, k, kk, ptr, end; + double dir, delta; + /* working LP is always minimization */ + switch (P->dir) + { case GLP_MIN: + dir = +1.0; + break; + case GLP_MAX: + dir = -1.0; + break; + default: + xassert(P != P); + } + /* initialize constant term of the objective */ + c[0] = dir * P->c0; + k = 0; /* number of variable in working LP */ + ptr = 1; /* current available position in A_ind/A_val */ + /* process rows of original LP */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if (excl && row->stat == GLP_NS) + { /* i-th auxiliary variable is non-basic and fixed */ + /* substitute its scaled value in working LP */ + xassert(row->type == GLP_FX); + map[i] = 0; + b[i] = - row->lb * row->rii; + } + else + { /* include i-th auxiliary variable in working LP */ + map[i] = ++k; + /* setup k-th column of working constraint matrix which is + * i-th column of unity matrix */ + A_ptr[k] = ptr; + A_ind[ptr] = i; + A_val[ptr] = 1.0; + ptr++; + /* initialize right-hand side of i-th equality constraint + * and setup zero objective coefficient at variable x[k] */ + b[i] = c[k] = 0.0; + /* setup scaled bounds of variable x[k] */ + switch (row->type) + { case GLP_FR: + l[k] = -DBL_MAX, u[k] = +DBL_MAX; + break; + case GLP_LO: + l[k] = row->lb * row->rii, u[k] = +DBL_MAX; + break; + case GLP_UP: + l[k] = -DBL_MAX, u[k] = row->ub * row->rii; + break; + case GLP_DB: + l[k] = row->lb * row->rii, u[k] = row->ub * row->rii; + xassert(l[k] != u[k]); + break; + case GLP_FX: + l[k] = u[k] = row->lb * row->rii; + break; + default: + xassert(row != row); + } + } + } + /* process columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + GLPAIJ *aij; + if (excl && col->stat == GLP_NS) + { /* j-th structural variable is non-basic and fixed */ + /* substitute its scaled value in working LP */ + xassert(col->type == GLP_FX); + map[m+j] = 0; + if (col->lb != 0.0) + { /* (note that sjj scale factor is cancelled) */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + b[aij->row->i] += + (aij->row->rii * aij->val) * col->lb; + c[0] += (dir * col->coef) * col->lb; + } + } + else + { /* include j-th structural variable in working LP */ + map[m+j] = ++k; + /* setup k-th column of working constraint matrix which is + * scaled j-th column of original constraint matrix (-A) */ + A_ptr[k] = ptr; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { A_ind[ptr] = aij->row->i; + A_val[ptr] = - aij->row->rii * aij->val * col->sjj; + ptr++; + } + /* setup scaled objective coefficient at variable x[k] */ + c[k] = dir * col->coef * col->sjj; + /* setup scaled bounds of variable x[k] */ + switch (col->type) + { case GLP_FR: + l[k] = -DBL_MAX, u[k] = +DBL_MAX; + break; + case GLP_LO: + l[k] = col->lb / col->sjj, u[k] = +DBL_MAX; + break; + case GLP_UP: + l[k] = -DBL_MAX, u[k] = col->ub / col->sjj; + break; + case GLP_DB: + l[k] = col->lb / col->sjj, u[k] = col->ub / col->sjj; + xassert(l[k] != u[k]); + break; + case GLP_FX: + l[k] = u[k] = col->lb / col->sjj; + break; + default: + xassert(col != col); + } + } + } + xassert(k == n); + xassert(ptr == nnz+1); + A_ptr[n+1] = ptr; + /* shift bounds of all variables of working LP (optionally) */ + if (shift) + { for (kk = 1; kk <= m+P->n; kk++) + { k = map[kk]; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + /* shift bounds of variable x[k] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + { /* x[k] is unbounded variable */ + delta = 0.0; + } + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + { /* shift lower bound to zero */ + delta = l[k]; + l[k] = 0.0; + } + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + { /* shift upper bound to zero */ + map[kk] = -k; + delta = u[k]; + u[k] = 0.0; + } + else if (l[k] != u[k]) + { /* x[k] is double bounded variable */ + if (fabs(l[k]) <= fabs(u[k])) + { /* shift lower bound to zero */ + delta = l[k]; + l[k] = 0.0, u[k] -= delta; + } + else + { /* shift upper bound to zero */ + map[kk] = -k; + delta = u[k]; + l[k] -= delta, u[k] = 0.0; + } + xassert(l[k] != u[k]); + } + else + { /* shift fixed value to zero */ + delta = l[k]; + l[k] = u[k] = 0.0; + } + /* substitute x[k] = x'[k] + delta into all constraints + * and the objective function of working LP */ + if (delta != 0.0) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + b[A_ind[ptr]] -= A_val[ptr] * delta; + c[0] += c[k] * delta; + } + } + } + return; +} + +/*********************************************************************** +* spx_build_basis - convert original LP basis to working LP basis +* +* This routine converts the current basis of the original LP to +* corresponding initial basis of the working LP, and moves the basis +* factorization driver from the original LP object to the working LP +* object. +* +* The array map should contain information provided by the routine +* spx_build_lp. */ + +void spx_build_basis(SPXLP *lp, glp_prob *P, const int map[]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k, ii, jj; + /* original basis factorization should be valid that guarantees + * the basis is correct */ + xassert(P->m == m); + xassert(P->valid); + /* initialize basis header for working LP */ + memset(&head[1], 0, m * sizeof(int)); + jj = 0; + /* scan rows of original LP */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + /* determine ordinal number of x[k] in working LP */ + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + xassert(1 <= k && k <= n); + if (row->stat == GLP_BS) + { /* x[k] is basic variable xB[ii] */ + ii = row->bind; + xassert(1 <= ii && ii <= m); + xassert(head[ii] == 0); + head[ii] = k; + } + else + { /* x[k] is non-basic variable xN[jj] */ + jj++; + head[m+jj] = k; + flag[jj] = (row->stat == GLP_NU); + } + } + /* scan columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + /* determine ordinal number of x[k] in working LP */ + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + xassert(1 <= k && k <= n); + if (col->stat == GLP_BS) + { /* x[k] is basic variable xB[ii] */ + ii = col->bind; + xassert(1 <= ii && ii <= m); + xassert(head[ii] == 0); + head[ii] = k; + } + else + { /* x[k] is non-basic variable xN[jj] */ + jj++; + head[m+jj] = k; + flag[jj] = (col->stat == GLP_NU); + } + } + xassert(m+jj == n); + /* acquire basis factorization */ + lp->valid = 1; + lp->bfd = P->bfd; + P->valid = 0; + P->bfd = NULL; + return; +} + +/*********************************************************************** +* spx_store_basis - convert working LP basis to original LP basis +* +* This routine converts the current working LP basis to corresponding +* original LP basis. This operations includes determining and setting +* statuses of all rows (auxiliary variables) and columns (structural +* variables), and building the basis header. +* +* The array map should contain information provided by the routine +* spx_build_lp. +* +* On exit the routine fills the array daeh. This array should have +* 1+lp->n locations (location [0] is not used) and contain the inverse +* of the working basis header lp->head, i.e. head[k'] = k means that +* daeh[k] = k'. */ + +void spx_store_basis(SPXLP *lp, glp_prob *P, const int map[], + int daeh[/*1+n*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k, kk; + /* determine inverse of working basis header */ + for (kk = 1; kk <= n; kk++) + daeh[head[kk]] = kk; + /* set row statuses */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed auxiliary variable was excluded */ + xassert(row->type == GLP_FX); + row->stat = GLP_NS; + row->bind = 0; + } + else + { /* auxiliary variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + P->head[kk] = i; + row->stat = GLP_BS; + row->bind = kk; + } + else + { /* x[k] = xN[kk-m] */ + switch (row->type) + { case GLP_FR: + row->stat = GLP_NF; + break; + case GLP_LO: + row->stat = GLP_NL; + break; + case GLP_UP: + row->stat = GLP_NU; + break; + case GLP_DB: + row->stat = (flag[kk-m] ? GLP_NU : GLP_NL); + break; + case GLP_FX: + row->stat = GLP_NS; + break; + default: + xassert(row != row); + } + row->bind = 0; + } + } + } + /* set column statuses */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed structural variable was excluded */ + xassert(col->type == GLP_FX); + col->stat = GLP_NS; + col->bind = 0; + } + else + { /* structural variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + P->head[kk] = m+j; + col->stat = GLP_BS; + col->bind = kk; + } + else + { /* x[k] = xN[kk-m] */ + switch (col->type) + { case GLP_FR: + col->stat = GLP_NF; + break; + case GLP_LO: + col->stat = GLP_NL; + break; + case GLP_UP: + col->stat = GLP_NU; + break; + case GLP_DB: + col->stat = (flag[kk-m] ? GLP_NU : GLP_NL); + break; + case GLP_FX: + col->stat = GLP_NS; + break; + default: + xassert(col != col); + } + col->bind = 0; + } + } + } + return; +} + +/*********************************************************************** +* spx_store_sol - convert working LP solution to original LP solution +* +* This routine converts the current basic solution of the working LP +* (values of basic variables, simplex multipliers, reduced costs of +* non-basic variables) to corresponding basic solution of the original +* LP (values and reduced costs of auxiliary and structural variables). +* This conversion includes unscaling all basic solution components, +* computing reduced costs of excluded non-basic variables, recovering +* unshifted values of basic variables, changing the signs of reduced +* costs (if the original LP is maximization), and computing the value +* of the objective function. +* +* The flag shift should have the same value as it has in a call to the +* routine spx_build_lp. +* +* The array map should contain information provided by the routine +* spx_build_lp. +* +* The array daeh should contain information provided by the routine +* spx_store_basis. +* +* The arrays beta, pi, and d should contain basic solution components +* for the working LP: +* +* array locations beta[1], ..., beta[m] should contain values of basic +* variables beta = (beta[i]); +* +* array locations pi[1], ..., pi[m] should contain simplex multipliers +* pi = (pi[i]); +* +* array locations d[1], ..., d[n-m] should contain reduced costs of +* non-basic variables d = (d[j]). */ + +void spx_store_sol(SPXLP *lp, glp_prob *P, int shift, + const int map[], const int daeh[], const double beta[], + const double pi[], const double d[]) +{ int m = lp->m; + char *flag = lp->flag; + int i, j, k, kk; + double dir; + /* working LP is always minimization */ + switch (P->dir) + { case GLP_MIN: + dir = +1.0; + break; + case GLP_MAX: + dir = -1.0; + break; + default: + xassert(P != P); + } + /* compute row solution components */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed auxiliary variable was excluded */ + xassert(row->type == GLP_FX); + row->prim = row->lb; + /* compute reduced cost d[k] = c[k] - A'[k] * pi as if x[k] + * would be non-basic in working LP */ + row->dual = - dir * pi[i] * row->rii; + } + else + { /* auxiliary variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + row->prim = beta[kk] / row->rii; + if (shift) + row->prim += (map[i] < 0 ? row->ub : row->lb); + row->dual = 0.0; + } + else + { /* x[k] = xN[kk-m] */ + row->prim = (flag[kk-m] ? row->ub : row->lb); + row->dual = (dir * d[kk-m]) * row->rii; + } + } + } + /* compute column solution components and objective value */ + P->obj_val = P->c0; + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed structural variable was excluded */ + GLPAIJ *aij; + double dk; + xassert(col->type == GLP_FX); + col->prim = col->lb; + /* compute reduced cost d[k] = c[k] - A'[k] * pi as if x[k] + * would be non-basic in working LP */ + /* (note that sjj scale factor is cancelled) */ + dk = dir * col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + dk += (aij->row->rii * aij->val) * pi[aij->row->i]; + col->dual = dir * dk; + } + else + { /* structural variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + col->prim = beta[kk] * col->sjj; + if (shift) + col->prim += (map[m+j] < 0 ? col->ub : col->lb); + col->dual = 0.0; + } + else + { /* x[k] = xN[kk-m] */ + col->prim = (flag[kk-m] ? col->ub : col->lb); + col->dual = (dir * d[kk-m]) / col->sjj; + } + } + P->obj_val += col->coef * col->prim; + } + return; +} + +/*********************************************************************** +* spx_free_lp - deallocate working LP arrays +* +* This routine deallocates the memory used for arrays of the working +* LP object. */ + +void spx_free_lp(SPXLP *lp) +{ tfree(lp->A_ptr); + tfree(lp->A_ind); + tfree(lp->A_val); + tfree(lp->b); + tfree(lp->c); + tfree(lp->l); + tfree(lp->u); + tfree(lp->head); + tfree(lp->flag); + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.h new file mode 100644 index 000000000..b7d87fa72 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spxprob.h @@ -0,0 +1,64 @@ +/* spxprob.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXPROB_H +#define SPXPROB_H + +#include "prob.h" +#include "spxlp.h" + +#define spx_init_lp _glp_spx_init_lp +void spx_init_lp(SPXLP *lp, glp_prob *P, int excl); +/* initialize working LP object */ + +#define spx_alloc_lp _glp_spx_alloc_lp +void spx_alloc_lp(SPXLP *lp); +/* allocate working LP arrays */ + +#define spx_build_lp _glp_spx_build_lp +void spx_build_lp(SPXLP *lp, glp_prob *P, int excl, int shift, + int map[/*1+P->m+P->n*/]); +/* convert original LP to working LP */ + +#define spx_build_basis _glp_spx_build_basis +void spx_build_basis(SPXLP *lp, glp_prob *P, const int map[]); +/* convert original LP basis to working LP basis */ + +#define spx_store_basis _glp_spx_store_basis +void spx_store_basis(SPXLP *lp, glp_prob *P, const int map[], + int daeh[/*1+n*/]); +/* convert working LP basis to original LP basis */ + +#define spx_store_sol _glp_spx_store_sol +void spx_store_sol(SPXLP *lp, glp_prob *P, int shift, + const int map[], const int daeh[], const double beta[], + const double pi[], const double d[]); +/* convert working LP solution to original LP solution */ + +#define spx_free_lp _glp_spx_free_lp +void spx_free_lp(SPXLP *lp); +/* deallocate working LP arrays */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.c new file mode 100644 index 000000000..b92212988 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.c @@ -0,0 +1,567 @@ +/* spychuzc.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2018 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spychuzc.h" + +/*********************************************************************** +* spy_chuzc_std - choose non-basic variable (dual textbook ratio test) +* +* This routine implements an improved dual textbook ratio test to +* choose non-basic variable xN[q]. +* +* Current reduced costs of non-basic variables should be placed in the +* array locations d[1], ..., d[n-m]. Note that d[j] is a value of dual +* basic variable lambdaN[j] in the current basis. +* +#if 0 (* 14/III-2016 *) +* The parameter s specifies the sign of bound violation for basic +* variable xB[p] chosen: s = +1.0 means that xB[p] violates its lower +* bound, so dual non-basic variable lambdaB[p] = lambda^+B[p] +* increases, and s = -1.0 means that xB[p] violates its upper bound, +* so dual non-basic variable lambdaB[p] = lambda^-B[p] decreases. +* (Thus, the dual ray parameter theta = s * lambdaB[p] >= 0.) +#else +* The parameter r specifies the bound violation for basic variable +* xB[p] chosen: +* +* r = lB[p] - beta[p] > 0 means that xB[p] violates its lower bound, +* so dual non-basic variable lambdaB[p] = lambda^+B[p] increases; and +* +* r = uB[p] - beta[p] < 0 means that xB[p] violates its upper bound, +* so dual non-basic variable lambdaB[p] = lambda^-B[p] decreases. +* +* (Note that r is the dual reduced cost of lambdaB[p].) +#endif +* +* Elements of p-th simplex table row t[p] = (t[p,j]) corresponding +* to basic variable xB[p] should be placed in the array locations +* trow[1], ..., trow[n-m]. +* +* The parameter tol_piv specifies a tolerance for elements of the +* simplex table row t[p]. If |t[p,j]| < tol_piv, dual basic variable +* lambdaN[j] is skipped, i.e. it is assumed that it does not depend on +* the dual ray parameter theta. +* +* The parameters tol and tol1 specify tolerances used to increase the +* choice freedom by simulating an artificial degeneracy as follows. +* If lambdaN[j] = lambda^+N[j] >= 0 and d[j] <= +delta[j], or if +* lambdaN[j] = lambda^-N[j] <= 0 and d[j] >= -delta[j], where +* delta[j] = tol + tol1 * |cN[j]|, cN[j] is objective coefficient at +* xN[j], then it is assumed that reduced cost d[j] is equal to zero. +* +* The routine determines the index 1 <= q <= n-m of non-basic variable +* xN[q], for which corresponding dual basic variable lambda^+N[j] or +* lambda^-N[j] reaches its zero bound first on increasing the dual ray +* parameter theta, and returns p on exit. And if theta may increase +* unlimitedly, the routine returns zero. */ + +int spy_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], +#if 0 /* 14/III-2016 */ + double s, const double trow[/*1+n-m*/], double tol_piv, +#else + double r, const double trow[/*1+n-m*/], double tol_piv, +#endif + double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, q; + double alfa, biga, delta, teta, teta_min; +#if 0 /* 14/III-2016 */ + xassert(s == +1.0 || s == -1.0); +#else + double s; + xassert(r != 0.0); + s = (r > 0.0 ? +1.0 : -1.0); +#endif + /* nothing is chosen so far */ + q = 0, teta_min = DBL_MAX, biga = 0.0; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches zero */ + teta = (d[j] < +delta ? 0.0 : d[j] / alfa); + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches zero */ + teta = (d[j] > -delta ? 0.0 : d[j] / alfa); + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + /* choose non-basic variable xN[q] by corresponding dual basic + * variable lambdaN[q] for which theta is minimal */ + xassert(teta >= 0.0); + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta_min > teta || (teta_min == teta && biga < alfa)) + q = j, teta_min = teta, biga = alfa; + } + return q; +} + +/*********************************************************************** +* spy_chuzc_harris - choose non-basic var. (dual Harris' ratio test) +* +* This routine implements dual Harris' ratio test to choose non-basic +* variable xN[q]. +* +* All the parameters, except tol and tol1, as well as the returned +* value have the same meaning as for the routine spx_chuzr_std (see +* above). +* +* The parameters tol and tol1 specify tolerances on zero bound +* violations for reduced costs of non-basic variables. For reduced +* cost d[j] the tolerance is delta[j] = tol + tol1 |cN[j]|, where +* cN[j] is objective coefficient at non-basic variable xN[j]. */ + +int spy_chuzc_harris(SPXLP *lp, const double d[/*1+n-m*/], +#if 0 /* 14/III-2016 */ + double s, const double trow[/*1+n-m*/], double tol_piv, +#else + double r, const double trow[/*1+n-m*/], double tol_piv, +#endif + double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, q; + double alfa, biga, delta, teta, teta_min; +#if 0 /* 14/III-2016 */ + xassert(s == +1.0 || s == -1.0); +#else + double s; + xassert(r != 0.0); + s = (r > 0.0 ? +1.0 : -1.0); +#endif + /*--------------------------------------------------------------*/ + /* first pass: determine teta_min for relaxed bounds */ + /*--------------------------------------------------------------*/ + teta_min = DBL_MAX; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches -delta */ + teta = ((d[j] < 0.0 ? 0.0 : d[j]) + delta) / alfa; + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches +delta */ + teta = ((d[j] > 0.0 ? 0.0 : d[j]) - delta) / alfa; + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + xassert(teta >= 0.0); + if (teta_min > teta) + teta_min = teta; + } + /*--------------------------------------------------------------*/ + /* second pass: choose non-basic variable xN[q] */ + /*--------------------------------------------------------------*/ + if (teta_min == DBL_MAX) + { /* theta may increase unlimitedly */ + q = 0; + goto done; + } + /* nothing is chosen so far */ + q = 0, biga = 0.0; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + /* determine theta on which lambdaN[j] reaches zero */ + teta = d[j] / alfa; + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + /* determine theta on which lambdaN[j] reaches zero */ + teta = d[j] / alfa; + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + /* choose non-basic variable for which theta is not greater + * than theta_min determined for relaxed bounds and which has + * best (largest in magnitude) pivot */ + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta <= teta_min && biga < alfa) + q = j, biga = alfa; + } + /* something must be chosen */ + xassert(1 <= q && q <= n-m); +done: return q; +} + +#if 0 /* 23/III-2016 */ +/*********************************************************************** +* spy_eval_bp - determine dual objective function break-points +* +* This routine determines the dual objective function break-points. +* +* The parameters lp, d, r, trow, and tol_piv have the same meaning as +* for the routine spx_chuzc_std (see above). +* +* On exit the routine stores the break-points determined to the array +* elements bp[1], ..., bp[num], where 0 <= num <= n-m is the number of +* break-points returned by the routine. +* +* The break-points stored in the array bp are ordered by ascending +* the ray parameter teta >= 0. The break-points numbered 1, ..., num-1 +* always correspond to non-basic non-fixed variables xN[j] of primal +* LP having both lower and upper bounds while the last break-point +* numbered num may correspond to a non-basic variable having only one +* lower or upper bound, if such variable prevents further increasing +* of the ray parameter teta. Besides, the routine includes in the +* array bp only the break-points that correspond to positive increment +* of the dual objective. */ + +static int CDECL fcmp(const void *v1, const void *v2) +{ const SPYBP *p1 = v1, *p2 = v2; + if (p1->teta < p2->teta) + return -1; + else if (p1->teta > p2->teta) + return +1; + else + return 0; +} + +int spy_eval_bp(SPXLP *lp, const double d[/*1+n-m*/], + double r, const double trow[/*1+n-m*/], double tol_piv, + SPYBP bp[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, j_max, k, t, nnn, num; + double s, alfa, teta, teta_max, dz, v; + xassert(r != 0.0); + s = (r > 0.0 ? +1.0 : -1.0); + /* build the list of all dual basic variables lambdaN[j] that + * can reach zero on increasing the ray parameter teta >= 0 */ + num = 0; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + /* determine teta[j] on which lambdaN[j] reaches zero */ + teta = (d[j] < 0.0 ? 0.0 : d[j] / alfa); + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + /* determine teta[j] on which lambdaN[j] reaches zero */ + teta = (d[j] > 0.0 ? 0.0 : d[j] / alfa); + } + else + { /* lambdaN[j] cannot reach zero on increasing teta */ + continue; + } + /* add lambdaN[j] to the list */ + num++; + bp[num].j = j; + bp[num].teta = teta; + } + if (num == 0) + { /* dual unboundedness */ + goto done; + } + /* determine "blocking" dual basic variable lambdaN[j_max] that + * prevents increasing teta more than teta_max */ + j_max = 0, teta_max = DBL_MAX; + for (t = 1; t <= num; t++) + { j = bp[t].j; + k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX || u[k] == +DBL_MAX) + { /* lambdaN[j] cannot intersect zero */ + if (j_max == 0 + || teta_max > bp[t].teta + || (teta_max == bp[t].teta + && fabs(trow[j_max]) < fabs(trow[j]))) + j_max = j, teta_max = bp[t].teta; + } + } + /* keep in the list only dual basic variables lambdaN[j] that + * correspond to primal double-bounded variables xN[j] and whose + * teta[j] is not greater than teta_max */ + nnn = 0; + for (t = 1; t <= num; t++) + { j = bp[t].j; + k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] != -DBL_MAX && u[k] != +DBL_MAX + && bp[t].teta <= teta_max) + { nnn++; + bp[nnn].j = j; + bp[nnn].teta = bp[t].teta; + } + } + num = nnn; + /* sort break-points by ascending teta[j] */ + qsort(&bp[1], num, sizeof(SPYBP), fcmp); + /* add lambdaN[j_max] to the end of the list */ + if (j_max != 0) + { xassert(num < n-m); + num++; + bp[num].j = j_max; + bp[num].teta = teta_max; + } + /* compute increments of the dual objective at all break-points + * (relative to its value at teta = 0) */ + dz = 0.0; /* dual objective increment */ + v = fabs(r); /* dual objective slope d zeta / d teta */ + for (t = 1; t <= num; t++) + { /* compute increment at current break-point */ + dz += v * (bp[t].teta - (t == 1 ? 0.0 : bp[t-1].teta)); + if (dz < 0.001) + { /* break-point with non-positive increment reached */ + num = t - 1; + break; + } + bp[t].dz = dz; + /* compute next slope on the right to current break-point */ + if (t < num) + { j = bp[t].j; + k = head[m+j]; /* x[k] = xN[j] */ + xassert(-DBL_MAX < l[k] && l[k] < u[k] && u[k] < +DBL_MAX); + v -= fabs(trow[j]) * (u[k] - l[k]); + } + } +done: return num; +} +#endif + +/*********************************************************************** +* spy_ls_eval_bp - determine dual objective function break-points +* +* This routine determines the dual objective function break-points. +* +* The parameters lp, d, r, trow, and tol_piv have the same meaning as +* for the routine spx_chuzc_std (see above). +* +* The routine stores the break-points determined to the array elements +* bp[1], ..., bp[nbp] in *arbitrary* order, where 0 <= nbp <= n-m is +* the number of break-points returned by the routine on exit. */ + +int spy_ls_eval_bp(SPXLP *lp, const double d[/*1+n-m*/], + double r, const double trow[/*1+n-m*/], double tol_piv, + SPYBP bp[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, t, nnn, nbp; + double s, alfa, teta, teta_max; + xassert(r != 0.0); + s = (r > 0.0 ? +1.0 : -1.0); + /* build the list of all dual basic variables lambdaN[j] that + * can reach zero on increasing the ray parameter teta >= 0 */ + nnn = 0, teta_max = DBL_MAX; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + /* determine teta[j] on which lambdaN[j] reaches zero */ + teta = (d[j] < 0.0 ? 0.0 : d[j] / alfa); + /* if xN[j] has no upper bound, lambdaN[j] cannot become + * negative and thereby blocks further increasing teta */ + if (u[k] == +DBL_MAX && teta_max > teta) + teta_max = teta; + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + /* determine teta[j] on which lambdaN[j] reaches zero */ + teta = (d[j] > 0.0 ? 0.0 : d[j] / alfa); + /* if xN[j] has no lower bound, lambdaN[j] cannot become + * positive and thereby blocks further increasing teta */ + if (l[k] == -DBL_MAX && teta_max > teta) + teta_max = teta; + } + else + { /* lambdaN[j] cannot reach zero on increasing teta */ + continue; + } + /* add lambdaN[j] to the list */ + nnn++; + bp[nnn].j = j; + bp[nnn].teta = teta; + } + /* remove from the list all dual basic variables lambdaN[j], for + * which teta[j] > teta_max */ + nbp = 0; + for (t = 1; t <= nnn; t++) + { if (bp[t].teta <= teta_max + 1e-6) + { nbp++; + bp[nbp].j = bp[t].j; + bp[nbp].teta = bp[t].teta; + } + } + return nbp; +} + +/*********************************************************************** +* spy_ls_select_bp - select and process dual objective break-points +* +* This routine selects a next portion of the dual objective function +* break-points and processes them. +* +* On entry to the routine it is assumed that break-points bp[1], ..., +* bp[num] are already processed, and slope is the dual objective slope +* to the right of the last processed break-point bp[num]. (Initially, +* when num = 0, slope should be specified as fabs(r), where r has the +* same meaning as above.) +* +* The routine selects break-points among bp[num+1], ..., bp[nbp], for +* which teta <= teta_lim, and moves these break-points to the array +* elements bp[num+1], ..., bp[num1], where num <= num1 <= n-m is the +* new number of processed break-points returned by the routine on +* exit. Then the routine sorts these break-points by ascending teta +* and computes the change of the dual objective function relative to +* its value at teta = 0. +* +* On exit the routine also replaces the parameter slope with a new +* value that corresponds to the new last break-point bp[num1]. */ + +static int CDECL fcmp(const void *v1, const void *v2) +{ const SPYBP *p1 = v1, *p2 = v2; + if (p1->teta < p2->teta) + return -1; + else if (p1->teta > p2->teta) + return +1; + else + return 0; +} + +int spy_ls_select_bp(SPXLP *lp, const double trow[/*1+n-m*/], + int nbp, SPYBP bp[/*1+n-m*/], int num, double *slope, double + teta_lim) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int j, k, t, num1; + double teta, dz; + xassert(0 <= num && num <= nbp && nbp <= n-m); + /* select a new portion of break-points */ + num1 = num; + for (t = num+1; t <= nbp; t++) + { if (bp[t].teta <= teta_lim) + { /* move break-point to the beginning of the new portion */ + num1++; + j = bp[num1].j, teta = bp[num1].teta; + bp[num1].j = bp[t].j, bp[num1].teta = bp[t].teta; + bp[t].j = j, bp[t].teta = teta; + } + } + /* sort new break-points bp[num+1], ..., bp[num1] by ascending + * the ray parameter teta */ + if (num1 - num > 1) + qsort(&bp[num+1], num1 - num, sizeof(SPYBP), fcmp); + /* calculate the dual objective change at the new break-points */ + for (t = num+1; t <= num1; t++) + { /* calculate the dual objective change relative to its value + * at break-point bp[t-1] */ + if (*slope == -DBL_MAX) + dz = -DBL_MAX; + else + dz = (*slope) * + (bp[t].teta - (t == 1 ? 0.0 : bp[t-1].teta)); + /* calculate the dual objective change relative to its value + * at teta = 0 */ + if (dz == -DBL_MAX) + bp[t].dz = -DBL_MAX; + else + bp[t].dz = (t == 1 ? 0.0 : bp[t-1].dz) + dz; + /* calculate a new slope of the dual objective to the right of + * the current break-point bp[t] */ + if (*slope != -DBL_MAX) + { j = bp[t].j; + k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX || u[k] == +DBL_MAX) + *slope = -DBL_MAX; /* blocking break-point reached */ + else + { xassert(l[k] < u[k]); + *slope -= fabs(trow[j]) * (u[k] - l[k]); + } + } + } + return num1; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.h new file mode 100644 index 000000000..8aa45a072 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzc.h @@ -0,0 +1,85 @@ +/* spychuzc.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2016 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPYCHUZC_H +#define SPYCHUZC_H + +#include "spxlp.h" + +#define spy_chuzc_std _glp_spy_chuzc_std +int spy_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], +#if 0 /* 14/III-2016 */ + double s, const double trow[/*1+n-m*/], double tol_piv, +#else + double r, const double trow[/*1+n-m*/], double tol_piv, +#endif + double tol, double tol1); +/* choose non-basic variable (dual textbook ratio test) */ + +#define spy_chuzc_harris _glp_spy_chuzc_harris +int spy_chuzc_harris(SPXLP *lp, const double d[/*1+n-m*/], +#if 0 /* 14/III-2016 */ + double s, const double trow[/*1+n-m*/], double tol_piv, +#else + double r, const double trow[/*1+n-m*/], double tol_piv, +#endif + double tol, double tol1); +/* choose non-basic variable (dual Harris' ratio test) */ + +typedef struct SPYBP SPYBP; + +struct SPYBP +{ /* dual objective function break point */ + int j; + /* dual basic variable lambdaN[j], 1 <= j <= n-m, that intersects + * zero at this break point */ + double teta; + /* ray parameter value, teta[j] >= 0, at this break point */ + double dz; + /* increment, zeta[j] - zeta[0], of the dual objective function + * at this break point */ +}; + +#if 0 /* 23/III-2016 */ +#define spy_eval_bp _glp_spy_eval_bp +int spy_eval_bp(SPXLP *lp, const double d[/*1+n-m*/], + double r, const double trow[/*1+n-m*/], double tol_piv, + SPYBP bp[/*1+n-m*/]); +/* determine dual objective function break-points */ +#endif + +#define spy_ls_eval_bp _glp_spy_ls_eval_bp +int spy_ls_eval_bp(SPXLP *lp, const double d[/*1+n-m*/], + double r, const double trow[/*1+n-m*/], double tol_piv, + SPYBP bp[/*1+n-m*/]); +/* determine dual objective function break-points */ + +#define spy_ls_select_bp _glp_spy_ls_select_bp +int spy_ls_select_bp(SPXLP *lp, const double trow[/*1+n-m*/], + int nbp, SPYBP bp[/*1+n-m*/], int num, double *slope, double + teta_lim); +/* select and process dual objective break-points */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.c new file mode 100644 index 000000000..63079c178 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.c @@ -0,0 +1,483 @@ +/* spychuzr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spychuzr.h" + +/*********************************************************************** +* spy_chuzr_sel - select eligible basic variables +* +* This routine selects eligible basic variables xB[i], whose value +* beta[i] violates corresponding lower lB[i] or upper uB[i] bound. +* Positive bound violation rp[i] = lb[i] - beta[i] > 0 is the reduced +* cost of non-basic dual variable lambda^+B[i] >= 0, so increasing it +* increases the dual objective. Similarly, negative bound violation +* rn[i] = ub[i] - beta[i] < 0 is the reduced cost of non-basic dual +* variable lambda^-B[i] <= 0, so decreasing it also increases the dual +* objective. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Basic variable xB[i] is considered eligible, if: +* +* beta[i] <= lB[i] - eps1[i], or +* +* beta[i] >= uB[i] + eps2[i], +* +* for +* +* eps1[i] = tol + tol1 * |lB[i]|, +* +* eps2[i] = tol + tol2 * |uB[i]|, +* +* where lB[i] and uB[i] are, resp., lower and upper bounds of xB[i], +* tol and tol1 are specified tolerances. +* +* On exit the routine stores indices i of eligible basic variables +* xB[i] to the array locations list[1], ..., list[num] and returns the +* number of such variables 0 <= num <= m. (If the parameter list is +* specified as NULL, no indices are stored.) */ + +int spy_chuzr_sel(SPXLP *lp, const double beta[/*1+m*/], double tol, + double tol1, int list[/*1+m*/]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k, num; + double lk, uk, eps; + num = 0; + /* walk thru list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + lk = l[k], uk = u[k]; + /* check if xB[i] is eligible */ + if (beta[i] < lk) + { /* determine absolute tolerance eps1[i] */ + eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* lower bound is violated */ + num++; + if (list != NULL) + list[num] = i; + } + } + else if (beta[i] > uk) + { /* determine absolute tolerance eps2[i] */ + eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* upper bound is violated */ + num++; + if (list != NULL) + list[num] = i; + } + } + } + return num; +} + +/*********************************************************************** +* spy_chuzr_std - choose basic variable (dual Dantzig's rule) +* +* This routine chooses most eligible basic variable xB[p] according +* to dual Dantzig's ("standard") rule: +* +* r[p] = max |r[i]|, +* i in I +* +* ( lB[i] - beta[i], if beta[i] < lB[i] +* ( +* r[i] = { 0, if lB[i] <= beta[i] <= uB[i] +* ( +* ( uB[i] - beta[i], if beta[i] > uB[i] +* +* where I <= {1, ..., m} is the set of indices of eligible basic +* variables, beta[i] is current value of xB[i], lB[i] and uB[i] are, +* resp., lower and upper bounds of xB[i], r[i] is bound violation. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Indices of eligible basic variables i in I should be placed in the +* array locations list[1], ..., list[num], where num = |J| > 0 is the +* total number of such variables. +* +* On exit the routine returns p, the index of the basic variable xB[p] +* chosen. */ + +int spy_chuzr_std(SPXLP *lp, const double beta[/*1+m*/], int num, + const int list[]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k, p, t; + double abs_ri, abs_rp; + xassert(0 < num && num <= m); + p = 0, abs_rp = -1.0; + for (t = 1; t <= num; t++) + { i = list[t]; + k = head[i]; /* x[k] = xB[i] */ + if (beta[i] < l[k]) + abs_ri = l[k] - beta[i]; + else if (beta[i] > u[k]) + abs_ri = beta[i] - u[k]; + else + xassert(t != t); + if (abs_rp < abs_ri) + p = i, abs_rp = abs_ri; + } + xassert(p != 0); + return p; +} + +/*********************************************************************** +* spy_alloc_se - allocate dual pricing data block +* +* This routine allocates the memory for arrays used in the dual +* pricing data block. */ + +void spy_alloc_se(SPXLP *lp, SPYSE *se) +{ int m = lp->m; + int n = lp->n; +#if 1 /* 30/III-2016 */ + int i; +#endif + se->valid = 0; + se->refsp = talloc(1+n, char); + se->gamma = talloc(1+m, double); + se->work = talloc(1+m, double); +#if 1 /* 30/III-2016 */ + se->u.n = m; + se->u.nnz = 0; + se->u.ind = talloc(1+m, int); + se->u.vec = talloc(1+m, double); + for (i = 1; i <= m; i++) + se->u.vec[i] = 0.0; +#endif + return; +} + +/*********************************************************************** +* spy_reset_refsp - reset dual reference space +* +* This routine resets (re-initializes) the dual reference space +* composing it from dual variables which are non-basic (corresponding +* to basic primal variables) in the current basis, and sets all +* weights gamma[i] to 1. */ + +void spy_reset_refsp(SPXLP *lp, SPYSE *se) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + int i, k; + se->valid = 1; + memset(&refsp[1], 0, n * sizeof(char)); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + refsp[k] = 1; + gamma[i] = 1.0; + } + return; +} + +/*********************************************************************** +* spy_eval_gamma_i - compute dual proj. steepest edge weight directly +* +* This routine computes dual projected steepest edge weight gamma[i], +* 1 <= i <= m, for the current basis directly with the formula: +* +* n-m +* gamma[i] = delta[i] + sum eta[j] * T[i,j]**2, +* j=1 +* +* where T[i,j] is element of the current simplex table, and +* +* ( 1, if lambdaN[j] is in the reference space +* eta[j] = { +* ( 0, otherwise +* +* ( 1, if lambdaB[i] is in the reference space +* delta[i] = { +* ( 0, otherwise +* +* Dual basic variable lambdaN[j] corresponds to primal non-basic +* variable xN[j], and dual non-basic variable lambdaB[j] corresponds +* to primal basic variable xB[i]. +* +* NOTE: For testing/debugging only. */ + +double spy_eval_gamma_i(SPXLP *lp, SPYSE *se, int i) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *rho = se->work; + int j, k; + double gamma_i, t_ij; + xassert(se->valid); + xassert(1 <= i && i <= m); + k = head[i]; /* x[k] = xB[i] */ + gamma_i = (refsp[k] ? 1.0 : 0.0); + spx_eval_rho(lp, i, rho); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (refsp[k]) + { t_ij = spx_eval_tij(lp, rho, j); + gamma_i += t_ij * t_ij; + } + } + return gamma_i; +} + +/*********************************************************************** +* spy_chuzr_pse - choose basic variable (dual projected steepest edge) +* +* This routine chooses most eligible basic variable xB[p] according +* to the dual projected steepest edge method: +* +* r[p]**2 r[i]**2 +* -------- = max -------- , +* gamma[p] i in I gamma[i] +* +* ( lB[i] - beta[i], if beta[i] < lB[i] +* ( +* r[i] = { 0, if lB[i] <= beta[i] <= uB[i] +* ( +* ( uB[i] - beta[i], if beta[i] > uB[i] +* +* where I <= {1, ..., m} is the set of indices of eligible basic +* variables, beta[i] is current value of xB[i], lB[i] and uB[i] are, +* resp., lower and upper bounds of xB[i], r[i] is bound violation. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Indices of eligible basic variables i in I should be placed in the +* array locations list[1], ..., list[num], where num = |J| > 0 is the +* total number of such variables. +* +* On exit the routine returns p, the index of the basic variable xB[p] +* chosen. */ + +int spy_chuzr_pse(SPXLP *lp, SPYSE *se, const double beta[/*1+m*/], + int num, const int list[]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *gamma = se->gamma; + int i, k, p, t; + double best, ri, temp; + xassert(0 < num && num <= m); + p = 0, best = -1.0; + for (t = 1; t <= num; t++) + { i = list[t]; + k = head[i]; /* x[k] = xB[i] */ + if (beta[i] < l[k]) + ri = l[k] - beta[i]; + else if (beta[i] > u[k]) + ri = u[k] - beta[i]; + else + xassert(t != t); + /* FIXME */ + if (gamma[i] < DBL_EPSILON) + temp = 0.0; + else + temp = (ri * ri) / gamma[i]; + if (best < temp) + p = i, best = temp; + } + xassert(p != 0); + return p; +} + +/*********************************************************************** +* spy_update_gamma - update dual proj. steepest edge weights exactly +* +* This routine updates the vector gamma = (gamma[i]) of dual projected +* steepest edge weights exactly, for the adjacent basis. +* +* On entry to the routine the content of the se object should be valid +* and should correspond to the current basis. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* For details about the formulae used see the program documentation. +* +* The routine also computes the relative error: +* +* e = |gamma[p] - gamma'[p]| / (1 + |gamma[p]|), +* +* where gamma'[p] is the weight for lambdaB[p] (which is dual +* non-basic variable corresponding to xB[p]) on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may reset the reference space, since other weights also may +* be inaccurate.) */ + +double spy_update_gamma(SPXLP *lp, SPYSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + double *u = se->work; + int i, j, k, ptr, end; + double gamma_p, delta_p, e, r, t1, t2; + xassert(se->valid); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* compute gamma[p] in current basis more accurately; also + * compute auxiliary vector u */ + k = head[p]; /* x[k] = xB[p] */ + gamma_p = delta_p = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + u[i] = 0.0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (refsp[k] && trow[j] != 0.0) + { gamma_p += trow[j] * trow[j]; + /* u := u + T[p,j] * N[j], where N[j] = A[k] is constraint + * matrix column corresponding to xN[j] */ + ptr = lp->A_ptr[k]; + end = lp->A_ptr[k+1]; + for (; ptr < end; ptr++) + u[lp->A_ind[ptr]] += trow[j] * lp->A_val[ptr]; + } + } + bfd_ftran(lp->bfd, u); + /* compute relative error in gamma[p] */ + e = fabs(gamma_p - gamma[p]) / (1.0 + gamma_p); + /* compute new gamma[p] */ + gamma[p] = gamma_p / (tcol[p] * tcol[p]); + /* compute new gamma[i] for all i != p */ + for (i = 1; i <= m; i++) + { if (i == p) + continue; + /* compute r[i] = T[i,q] / T[p,q] */ + r = tcol[i] / tcol[p]; + /* compute new gamma[i] */ + t1 = gamma[i] + r * (r * gamma_p + u[i] + u[i]); + k = head[i]; /* x[k] = xB[i] */ + t2 = (refsp[k] ? 1.0 : 0.0) + delta_p * r * r; + gamma[i] = (t1 >= t2 ? t1 : t2); + } + return e; +} + +#if 1 /* 30/III-2016 */ +double spy_update_gamma_s(SPXLP *lp, SPYSE *se, int p, int q, + const FVS *trow, const FVS *tcol) +{ /* sparse version of spy_update_gamma */ + int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + double *u = se->work; + int trow_nnz = trow->nnz; + int *trow_ind = trow->ind; + double *trow_vec = trow->vec; + int tcol_nnz = tcol->nnz; + int *tcol_ind = tcol->ind; + double *tcol_vec = tcol->vec; + int i, j, k, t, ptr, end; + double gamma_p, delta_p, e, r, t1, t2; + xassert(se->valid); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* compute gamma[p] in current basis more accurately; also + * compute auxiliary vector u */ + k = head[p]; /* x[k] = xB[p] */ + gamma_p = delta_p = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + u[i] = 0.0; + for (t = 1; t <= trow_nnz; t++) + { j = trow_ind[t]; + k = head[m+j]; /* x[k] = xN[j] */ + if (refsp[k]) + { gamma_p += trow_vec[j] * trow_vec[j]; + /* u := u + T[p,j] * N[j], where N[j] = A[k] is constraint + * matrix column corresponding to xN[j] */ + ptr = lp->A_ptr[k]; + end = lp->A_ptr[k+1]; + for (; ptr < end; ptr++) + u[lp->A_ind[ptr]] += trow_vec[j] * lp->A_val[ptr]; + } + } + bfd_ftran(lp->bfd, u); + /* compute relative error in gamma[p] */ + e = fabs(gamma_p - gamma[p]) / (1.0 + gamma_p); + /* compute new gamma[p] */ + gamma[p] = gamma_p / (tcol_vec[p] * tcol_vec[p]); + /* compute new gamma[i] for all i != p */ + for (t = 1; t <= tcol_nnz; t++) + { i = tcol_ind[t]; + if (i == p) + continue; + /* compute r[i] = T[i,q] / T[p,q] */ + r = tcol_vec[i] / tcol_vec[p]; + /* compute new gamma[i] */ + t1 = gamma[i] + r * (r * gamma_p + u[i] + u[i]); + k = head[i]; /* x[k] = xB[i] */ + t2 = (refsp[k] ? 1.0 : 0.0) + delta_p * r * r; + gamma[i] = (t1 >= t2 ? t1 : t2); + } + return e; +} +#endif + +/*********************************************************************** +* spy_free_se - deallocate dual pricing data block +* +* This routine deallocates the memory used for arrays in the dual +* pricing data block. */ + +void spy_free_se(SPXLP *lp, SPYSE *se) +{ xassert(lp == lp); + tfree(se->refsp); + tfree(se->gamma); + tfree(se->work); +#if 1 /* 30/III-2016 */ + tfree(se->u.ind); + tfree(se->u.vec); +#endif + return; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.h b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.h new file mode 100644 index 000000000..31f01b78a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spychuzr.h @@ -0,0 +1,97 @@ +/* spychuzr.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPYCHUZR_H +#define SPYCHUZR_H + +#include "spxlp.h" + +#define spy_chuzr_sel _glp_spy_chuzr_sel +int spy_chuzr_sel(SPXLP *lp, const double beta[/*1+m*/], double tol, + double tol1, int list[/*1+m*/]); +/* select eligible basic variables */ + +#define spy_chuzr_std _glp_spy_chuzr_std +int spy_chuzr_std(SPXLP *lp, const double beta[/*1+m*/], int num, + const int list[]); +/* choose basic variable (dual Dantzig's rule) */ + +typedef struct SPYSE SPYSE; + +struct SPYSE +{ /* dual projected steepest edge and Devex pricing data block */ + int valid; + /* content validity flag */ + char *refsp; /* char refsp[1+n]; */ + /* refsp[0] is not used; + * refsp[k], 1 <= k <= n, is the flag meaning that dual variable + * lambda[k] is in the dual reference space */ + double *gamma; /* double gamma[1+m]; */ + /* gamma[0] is not used; + * gamma[i], 1 <= i <= m, is the weight for reduced cost r[i] + * of dual non-basic variable lambdaB[j] in the current basis + * (r[i] is bound violation for basic variable xB[i]) */ + double *work; /* double work[1+m]; */ + /* working array */ +#if 1 /* 30/III-2016 */ + FVS u; /* FVS u[1:m]; */ + /* working vector */ +#endif +}; + +#define spy_alloc_se _glp_spy_alloc_se +void spy_alloc_se(SPXLP *lp, SPYSE *se); +/* allocate dual pricing data block */ + +#define spy_reset_refsp _glp_spy_reset_refsp +void spy_reset_refsp(SPXLP *lp, SPYSE *se); +/* reset dual reference space */ + +#define spy_eval_gamma_i _glp_spy_eval_gamma_i +double spy_eval_gamma_i(SPXLP *lp, SPYSE *se, int i); +/* compute dual projected steepest edge weight directly */ + +#define spy_chuzr_pse _glp_spy_chuzr_pse +int spy_chuzr_pse(SPXLP *lp, SPYSE *se, const double beta[/*1+m*/], + int num, const int list[]); +/* choose basic variable (dual projected steepest edge) */ + +#define spy_update_gamma _glp_spy_update_gamma +double spy_update_gamma(SPXLP *lp, SPYSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update dual projected steepest edge weights exactly */ + +#if 1 /* 30/III-2016 */ +#define spy_update_gamma_s _glp_spy_update_gamma_s +double spy_update_gamma_s(SPXLP *lp, SPYSE *se, int p, int q, + const FVS *trow, const FVS *tcol); +/* sparse version of spy_update_gamma */ +#endif + +#define spy_free_se _glp_spy_free_se +void spy_free_se(SPXLP *lp, SPYSE *se); +/* deallocate dual pricing data block */ + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spydual.c b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spydual.c new file mode 100644 index 000000000..89d98db9b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/simplex/spydual.c @@ -0,0 +1,2101 @@ +/* spydual.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015-2017 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#if 1 /* 18/VII-2017 */ +#define SCALE_Z 1 +#endif + +#include "env.h" +#include "simplex.h" +#include "spxat.h" +#include "spxnt.h" +#include "spxprob.h" +#include "spychuzc.h" +#include "spychuzr.h" +#if 0 /* 11/VI-2017 */ +#if 1 /* 29/III-2016 */ +#include "fvs.h" +#endif +#endif + +#define CHECK_ACCURACY 0 +/* (for debugging) */ + +struct csa +{ /* common storage area */ + SPXLP *lp; + /* LP problem data and its (current) basis; this LP has m rows + * and n columns */ + int dir; + /* original optimization direction: + * +1 - minimization + * -1 - maximization */ +#if SCALE_Z + double fz; + /* factor used to scale original objective */ +#endif + double *orig_b; /* double orig_b[1+m]; */ + /* copy of original right-hand sides */ + double *orig_c; /* double orig_c[1+n]; */ + /* copy of original objective coefficients */ + double *orig_l; /* double orig_l[1+n]; */ + /* copy of original lower bounds */ + double *orig_u; /* double orig_u[1+n]; */ + /* copy of original upper bounds */ + SPXAT *at; + /* mxn-matrix A of constraint coefficients, in sparse row-wise + * format (NULL if not used) */ + SPXNT *nt; + /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format (NULL if not used) */ + int phase; + /* search phase: + * 0 - not determined yet + * 1 - searching for dual feasible solution + * 2 - searching for optimal solution */ + double *beta; /* double beta[1+m]; */ + /* beta[i] is primal value of basic variable xB[i] */ + int beta_st; + /* status of the vector beta: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + double *d; /* double d[1+n-m]; */ + /* d[j] is reduced cost of non-basic variable xN[j] */ + int d_st; + /* status of the vector d: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + SPYSE *se; + /* dual projected steepest edge and Devex pricing data block + * (NULL if not used) */ +#if 0 /* 30/III-2016 */ + int num; + /* number of eligible basic variables */ + int *list; /* int list[1+m]; */ + /* list[1], ..., list[num] are indices i of eligible basic + * variables xB[i] */ +#else + FVS r; /* FVS r[1:m]; */ + /* vector of primal infeasibilities */ + /* r->nnz = num; r->ind = list */ + /* vector r has the same status as vector beta (see above) */ +#endif + int p; + /* xB[p] is a basic variable chosen to leave the basis */ +#if 0 /* 29/III-2016 */ + double *trow; /* double trow[1+n-m]; */ +#else + FVS trow; /* FVS trow[1:n-m]; */ +#endif + /* p-th (pivot) row of the simplex table */ +#if 1 /* 16/III-2016 */ + SPYBP *bp; /* SPYBP bp[1+n-m]; */ + /* dual objective break-points */ +#endif + int q; + /* xN[q] is a non-basic variable chosen to enter the basis */ +#if 0 /* 29/III-2016 */ + double *tcol; /* double tcol[1+m]; */ +#else + FVS tcol; /* FVS tcol[1:m]; */ +#endif + /* q-th (pivot) column of the simplex table */ + double *work; /* double work[1+m]; */ + /* working array */ + double *work1; /* double work1[1+n-m]; */ + /* another working array */ +#if 0 /* 11/VI-2017 */ +#if 1 /* 31/III-2016 */ + FVS wrow; /* FVS wrow[1:n-m]; */ + FVS wcol; /* FVS wcol[1:m]; */ + /* working sparse vectors */ +#endif +#endif + int p_stat, d_stat; + /* primal and dual solution statuses */ + /*--------------------------------------------------------------*/ + /* control parameters (see struct glp_smcp) */ + int msg_lev; + /* message level */ + int dualp; + /* if this flag is set, report failure in case of instability */ +#if 0 /* 16/III-2016 */ + int harris; + /* dual ratio test technique: + * 0 - textbook ratio test + * 1 - Harris' two pass ratio test */ +#else + int r_test; + /* dual ratio test technique: + * GLP_RT_STD - textbook ratio test + * GLP_RT_HAR - Harris' two pass ratio test + * GLP_RT_FLIP - long-step (flip-flop) ratio test */ +#endif + double tol_bnd, tol_bnd1; + /* primal feasibility tolerances */ + double tol_dj, tol_dj1; + /* dual feasibility tolerances */ + double tol_piv; + /* pivot tolerance */ + double obj_lim; + /* objective limit */ + int it_lim; + /* iteration limit */ + int tm_lim; + /* time limit, milliseconds */ + int out_frq; +#if 0 /* 15/VII-2017 */ + /* display output frequency, iterations */ +#else + /* display output frequency, milliseconds */ +#endif + int out_dly; + /* display output delay, milliseconds */ + /*--------------------------------------------------------------*/ + /* working parameters */ + double tm_beg; + /* time value at the beginning of the search */ + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + * basis changes */ + int it_dpy; + /* simplex iteration count at most recent display output */ +#if 1 /* 15/VII-2017 */ + double tm_dpy; + /* time value at most recent display output */ +#endif + int inv_cnt; + /* basis factorization count since most recent display output */ +#if 1 /* 11/VII-2017 */ + int degen; + /* count of successive degenerate iterations; this count is used + * to detect stalling */ +#endif +#if 1 /* 23/III-2016 */ + int ns_cnt, ls_cnt; + /* normal and long-step iteration count */ +#endif +}; + +/*********************************************************************** +* check_flags - check correctness of active bound flags +* +* This routine checks that flags specifying active bounds of all +* non-basic variables are correct. +* +* NOTE: It is important to note that if bounds of variables have been +* changed, active bound flags should be corrected accordingly. */ + +static void check_flags(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + xassert(!flag[j]); + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + xassert(!flag[j]); + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + xassert(flag[j]); + else if (l[k] == u[k]) + xassert(!flag[j]); + } + return; +} + +/*********************************************************************** +* set_art_bounds - set artificial right-hand sides and bounds +* +* This routine sets artificial right-hand sides and artificial bounds +* for all variables to minimize the sum of dual infeasibilities on +* phase I. Given current reduced costs d = (d[j]) this routine also +* sets active artificial bounds of non-basic variables to provide dual +* feasibility (this is always possible because all variables have both +* lower and upper artificial bounds). */ + +static void set_art_bounds(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int i, j, k; +#if 1 /* 31/III-2016: FIXME */ + /* set artificial right-hand sides */ + for (i = 1; i <= m; i++) + b[i] = 0.0; + /* set artificial bounds depending on types of variables */ + for (k = 1; k <= n; k++) + { if (csa->orig_l[k] == -DBL_MAX && csa->orig_u[k] == +DBL_MAX) + { /* force free variables to enter the basis */ + l[k] = -1e3, u[k] = +1e3; + } + else if (csa->orig_l[k] != -DBL_MAX && csa->orig_u[k] == +DBL_MAX) + l[k] = 0.0, u[k] = +1.0; + else if (csa->orig_l[k] == -DBL_MAX && csa->orig_u[k] != +DBL_MAX) + l[k] = -1.0, u[k] = 0.0; + else + l[k] = u[k] = 0.0; + } +#endif + /* set active artificial bounds for non-basic variables */ + xassert(csa->d_st == 1); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + flag[j] = (l[k] != u[k] && d[j] < 0.0); + } + /* invalidate values of basic variables, since active bounds of + * non-basic variables have been changed */ + csa->beta_st = 0; + return; +} + +/*********************************************************************** +* set_orig_bounds - restore original right-hand sides and bounds +* +* This routine restores original right-hand sides and original bounds +* for all variables. This routine also sets active original bounds for +* non-basic variables; for double-bounded non-basic variables current +* reduced costs d = (d[j]) are used to decide which bound (lower or +* upper) should be made active. */ + +static void set_orig_bounds(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int j, k; + /* restore original right-hand sides */ + memcpy(b, csa->orig_b, (1+m) * sizeof(double)); + /* restore original bounds of all variables */ + memcpy(l, csa->orig_l, (1+n) * sizeof(double)); + memcpy(u, csa->orig_u, (1+n) * sizeof(double)); + /* set active original bounds for non-basic variables */ + xassert(csa->d_st == 1); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + flag[j] = 0; + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + flag[j] = 0; + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + flag[j] = 1; + else if (l[k] != u[k]) + flag[j] = (d[j] < 0.0); + else + flag[j] = 0; + } + /* invalidate values of basic variables, since active bounds of + * non-basic variables have been changed */ + csa->beta_st = 0; + return; +} + +/*********************************************************************** +* check_feas - check dual feasibility of basic solution +* +* This routine checks that reduced costs of all non-basic variables +* d = (d[j]) have correct signs. +* +* Reduced cost d[j] is considered as having correct sign within the +* specified tolerance depending on status of non-basic variable xN[j] +* if one of the following conditions is met: +* +* xN[j] is free -eps <= d[j] <= +eps +* +* xN[j] has its lower bound active d[j] >= -eps +* +* xN[j] has its upper bound active d[j] <= +eps +* +* xN[j] is fixed d[j] has any value +* +* where eps = tol + tol1 * |cN[j]|, cN[j] is the objective coefficient +* at xN[j]. (See also the routine spx_chuzc_sel.) +* +* The flag recov allows the routine to recover dual feasibility by +* changing active bounds of non-basic variables. (For example, if +* xN[j] has its lower bound active and d[j] < -eps, the feasibility +* can be recovered by making xN[j] active on its upper bound.) +* +* If the basic solution is dual feasible, the routine returns zero. +* If the basic solution is dual infeasible, but its dual feasibility +* can be recovered (or has been recovered, if the flag recov is set), +* the routine returns a negative value. Otherwise, the routine returns +* the number j of some non-basic variable xN[j], whose reduced cost +* d[j] is dual infeasible and cannot be recovered. */ + +static int check_feas(struct csa *csa, double tol, double tol1, + int recov) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int j, k, ret = 0; + double eps; + /* reduced costs should be just computed */ + xassert(csa->d_st == 1); + /* walk thru list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + { /* xN[j] is fixed variable; skip it */ + continue; + } + /* determine absolute tolerance eps[j] */ + eps = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* check dual feasibility of xN[j] */ + if (d[j] > +eps) + { /* xN[j] should have its lower bound active */ + if (l[k] == -DBL_MAX || flag[j]) + { /* but it either has no lower bound or its lower bound + * is inactive */ + if (l[k] == -DBL_MAX) + { /* cannot recover, since xN[j] has no lower bound */ + ret = j; + break; + } + /* recovering is possible */ + if (recov) + flag[j] = 0; + ret = -1; + } + } + else if (d[j] < -eps) + { /* xN[j] should have its upper bound active */ + if (!flag[j]) + { /* but it either has no upper bound or its upper bound + * is inactive */ + if (u[k] == +DBL_MAX) + { /* cannot recover, since xN[j] has no upper bound */ + ret = j; + break; + } + /* recovering is possible */ + if (recov) + flag[j] = 1; + ret = -1; + } + } + } + if (recov && ret) + { /* invalidate values of basic variables, since active bounds + * of non-basic variables have been changed */ + csa->beta_st = 0; + } + return ret; +} + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_vec - compute maximal relative error between two vectors +* +* This routine computes and returns maximal relative error between +* n-vectors x and y: +* +* err_max = max |x[i] - y[i]| / (1 + |x[i]|). +* +* NOTE: This routine is intended only for debugging purposes. */ + +static double err_in_vec(int n, const double x[], const double y[]) +{ int i; + double err, err_max; + err_max = 0.0; + for (i = 1; i <= n; i++) + { err = fabs(x[i] - y[i]) / (1.0 + fabs(x[i])); + if (err_max < err) + err_max = err; + } + return err_max; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_beta - compute maximal relative error in vector beta +* +* This routine computes and returns maximal relative error in vector +* of values of basic variables beta = (beta[i]). +* +* NOTE: This routine is intended only for debugging purposes. */ + +static double err_in_beta(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double err, *beta; + beta = talloc(1+m, double); + spx_eval_beta(lp, beta); + err = err_in_vec(m, beta, csa->beta); + tfree(beta); + return err; +} +#endif + +#if CHECK_ACCURACY +static double err_in_r(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int i, k; + double err, *r; + r = talloc(1+m, double); + for (i = 1; i <= m; i++) + { k = lp->head[i]; + if (csa->beta[i] < lp->l[k]) + r[i] = lp->l[k] - csa->beta[i]; + else if (csa->beta[i] > lp->u[k]) + r[i] = lp->u[k] - csa->beta[i]; + else + r[i] = 0.0; + +if (fabs(r[i] - csa->r.vec[i]) > 1e-6) +printf("i = %d; r = %g; csa->r = %g\n", i, r[i], csa->r.vec[i]); + + + } + err = err_in_vec(m, r, csa->r.vec); + tfree(r); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_d - compute maximal relative error in vector d +* +* This routine computes and returns maximal relative error in vector +* of reduced costs of non-basic variables d = (d[j]). +* +* NOTE: This routine is intended only for debugging purposes. */ + +static double err_in_d(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int j; + double err, *pi, *d; + pi = talloc(1+m, double); + d = talloc(1+n-m, double); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + err = err_in_vec(n-m, d, csa->d); + tfree(pi); + tfree(d); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_gamma - compute maximal relative error in vector gamma +* +* This routine computes and returns maximal relative error in vector +* of projected steepest edge weights gamma = (gamma[j]). +* +* NOTE: This routine is intended only for debugging purposes. */ + +static double err_in_gamma(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + SPYSE *se = csa->se; + int i; + double err, *gamma; + xassert(se != NULL); +gamma = talloc(1+m, double); + for (i = 1; i <= m; i++) + gamma[i] = spy_eval_gamma_i(lp, se, i); + err = err_in_vec(m, gamma, se->gamma); + tfree(gamma); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* check_accuracy - check accuracy of basic solution components +* +* This routine checks accuracy of current basic solution components. +* +* NOTE: This routine is intended only for debugging purposes. */ + +static void check_accuracy(struct csa *csa) +{ double e_beta, e_r, e_d, e_gamma; + e_beta = err_in_beta(csa); + e_r = err_in_r(csa); + e_d = err_in_d(csa); + if (csa->se == NULL) + e_gamma = 0.; + else + e_gamma = err_in_gamma(csa); + xprintf("e_beta = %10.3e; e_r = %10.3e; e_d = %10.3e; e_gamma = %" + "10.3e\n", e_beta, e_r, e_d, e_gamma); + xassert(e_beta <= 1e-5 && e_d <= 1e-5 && e_gamma <= 1e-3); + return; +} +#endif + +#if 1 /* 30/III-2016 */ +static +void spy_eval_r(SPXLP *lp, const double beta[/*1+m*/], double tol, + double tol1, FVS *r) +{ /* this routine computes the vector of primal infeasibilities: + * + * ( lB[i] - beta[i] > 0, if beta[i] < lb[i] + * r[i] = { 0, if lb[i] <= beta[i] <= ub[i] + * ( ub[i] - beta[i] < 0, if beta[i] > ub[i] + * + * (this routine replaces spy_chuzr_sel) */ + int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int *ind = r->ind; + double *vec = r->vec; + int i, k, nnz = 0; + double lk, uk, eps; + xassert(r->n == m); + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { vec[i] = 0.0; + k = head[i]; /* x[k] = xB[i] */ + lk = l[k], uk = u[k]; + /* check primal feasibility */ + if (beta[i] < lk) + { /* determine absolute tolerance eps1[i] */ + eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* lower bound is violated */ + ind[++nnz] = i; + vec[i] = lk - beta[i]; + } + } + else if (beta[i] > uk) + { /* determine absolute tolerance eps2[i] */ + eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* upper bound is violated */ + ind[++nnz] = i; + vec[i] = uk - beta[i]; + } + } + } + r->nnz = nnz; + return; +} +#endif + +/*********************************************************************** +* choose_pivot - choose xB[p] and xN[q] +* +* Given the list of eligible basic variables this routine first +* chooses basic variable xB[p]. This choice is always possible, +* because the list is assumed to be non-empty. Then the routine +* computes p-th row T[p,*] of the simplex table T[i,j] and chooses +* non-basic variable xN[q]. If the pivot T[p,q] is small in magnitude, +* the routine attempts to choose another xB[p] and xN[q] in order to +* avoid badly conditioned adjacent bases. +* +* If the normal choice was made, the routine returns zero. Otherwise, +* if the long-step choice was made, the routine returns non-zero. */ + +#ifdef TIMING /* 31/III-2016 */ + +#include "choose_pivot.c" + +#else + +#define MIN_RATIO 0.0001 + +static int choose_pivot(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + SPXAT *at = csa->at; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPYSE *se = csa->se; +#if 0 /* 30/III-2016 */ + int *list = csa->list; +#else + int *list = csa->r.ind; +#endif + double *rho = csa->work; + double *trow = csa->work1; + SPYBP *bp = csa->bp; + double tol_piv = csa->tol_piv; + int try, nnn, j, k, p, q, t, t_best, nbp, ret; + double big, temp, r, best_ratio, dz_best; + xassert(csa->beta_st); + xassert(csa->d_st); +more: /* initial number of eligible basic variables */ +#if 0 /* 30/III-2016 */ + nnn = csa->num; +#else + nnn = csa->r.nnz; +#endif + /* nothing has been chosen so far */ + csa->p = 0; + best_ratio = 0.0; + try = ret = 0; +try: /* choose basic variable xB[p] */ + xassert(nnn > 0); + try++; + if (se == NULL) + { /* dual Dantzig's rule */ + p = spy_chuzr_std(lp, beta, nnn, list); + } + else + { /* dual projected steepest edge */ + p = spy_chuzr_pse(lp, se, beta, nnn, list); + } + xassert(1 <= p && p <= m); + /* compute p-th row of inv(B) */ + spx_eval_rho(lp, p, rho); + /* compute p-th row of the simplex table */ + if (at != NULL) + spx_eval_trow1(lp, at, rho, trow); + else + spx_nt_prod(lp, nt, trow, 1, -1.0, rho); +#if 1 /* 23/III-2016 */ + /* big := max(1, |trow[1]|, ..., |trow[n-m]|) */ + big = 1.0; + for (j = 1; j <= n-m; j++) + { temp = trow[j]; + if (temp < 0.0) + temp = - temp; + if (big < temp) + big = temp; + } +#else + /* this still puzzles me */ + big = 1.0; +#endif + /* choose non-basic variable xN[q] */ + k = head[p]; /* x[k] = xB[p] */ + xassert(beta[p] < l[k] || beta[p] > u[k]); + r = beta[p] < l[k] ? l[k] - beta[p] : u[k] - beta[p]; + if (csa->r_test == GLP_RT_FLIP && try <= 2) + { /* long-step ratio test */ +#if 0 /* 23/III-2016 */ + /* determine dual objective break-points */ + nbp = spy_eval_bp(lp, d, r, trow, tol_piv, bp); + if (nbp <= 1) + goto skip; + /* choose appropriate break-point */ + t_best = 0, dz_best = -DBL_MAX; + for (t = 1; t <= nbp; t++) + { if (fabs(trow[bp[t].j]) / big >= MIN_RATIO) + { if (dz_best < bp[t].dz) + t_best = t, dz_best = bp[t].dz; + } + } + if (t_best == 0) + goto skip; +#else + int t, num, num1; + double slope, teta_lim; + /* determine dual objective break-points */ + nbp = spy_ls_eval_bp(lp, d, r, trow, tol_piv, bp); + if (nbp < 2) + goto skip; + /* set initial slope */ + slope = fabs(r); + /* estimate initial teta_lim */ + teta_lim = DBL_MAX; + for (t = 1; t <= nbp; t++) + { if (teta_lim > bp[t].teta) + teta_lim = bp[t].teta; + } + xassert(teta_lim >= 0.0); + if (teta_lim < 1e-6) + teta_lim = 1e-6; + /* nothing has been chosen so far */ + t_best = 0, dz_best = 0.0, num = 0; + /* choose appropriate break-point */ + while (num < nbp) + { /* select and process a new portion of break-points */ + num1 = spy_ls_select_bp(lp, trow, nbp, bp, num, &slope, + teta_lim); + for (t = num+1; t <= num1; t++) + { if (fabs(trow[bp[t].j]) / big >= MIN_RATIO) + { if (dz_best < bp[t].dz) + t_best = t, dz_best = bp[t].dz; + } + } + if (slope < 0.0) + { /* the dual objective starts decreasing */ + break; + } + /* the dual objective continues increasing */ + num = num1; + teta_lim += teta_lim; + } + if (dz_best == 0.0) + goto skip; + xassert(1 <= t_best && t_best <= num1); +#endif + /* the choice has been made */ + csa->p = p; +#if 0 /* 29/III-2016 */ + memcpy(&csa->trow[1], &trow[1], (n-m) * sizeof(double)); +#else + memcpy(&csa->trow.vec[1], &trow[1], (n-m) * sizeof(double)); + fvs_gather_vec(&csa->trow, DBL_EPSILON); +#endif + csa->q = bp[t_best].j; + best_ratio = fabs(trow[bp[t_best].j]) / big; +#if 0 + xprintf("num = %d; t_best = %d; dz = %g\n", num, t_best, + bp[t_best].dz); +#endif + ret = 1; + goto done; +skip: ; + } + if (csa->r_test == GLP_RT_STD) + { /* textbook dual ratio test */ + q = spy_chuzc_std(lp, d, r, trow, tol_piv, + .30 * csa->tol_dj, .30 * csa->tol_dj1); + } + else + { /* Harris' two-pass dual ratio test */ + q = spy_chuzc_harris(lp, d, r, trow, tol_piv, + .35 * csa->tol_dj, .35 * csa->tol_dj1); + } + if (q == 0) + { /* dual unboundedness */ + csa->p = p; +#if 0 /* 29/III-2016 */ + memcpy(&csa->trow[1], &trow[1], (n-m) * sizeof(double)); +#else + memcpy(&csa->trow.vec[1], &trow[1], (n-m) * sizeof(double)); + fvs_gather_vec(&csa->trow, DBL_EPSILON); +#endif + csa->q = q; + best_ratio = 1.0; + goto done; + } + /* either keep previous choice or accept new choice depending on + * which one is better */ + if (best_ratio < fabs(trow[q]) / big) + { csa->p = p; +#if 0 /* 29/III-2016 */ + memcpy(&csa->trow[1], &trow[1], (n-m) * sizeof(double)); +#else + memcpy(&csa->trow.vec[1], &trow[1], (n-m) * sizeof(double)); + fvs_gather_vec(&csa->trow, DBL_EPSILON); +#endif + csa->q = q; + best_ratio = fabs(trow[q]) / big; + } + /* check if the current choice is acceptable */ + if (best_ratio >= MIN_RATIO || nnn == 1 || try == 5) + goto done; + /* try to choose other xB[p] and xN[q] */ + /* find xB[p] in the list */ + for (t = 1; t <= nnn; t++) + if (list[t] == p) break; + xassert(t <= nnn); + /* move xB[p] to the end of the list */ + list[t] = list[nnn], list[nnn] = p; + /* and exclude it from consideration */ + nnn--; + /* repeat the choice */ + goto try; +done: /* the choice has been made */ +#if 1 /* FIXME: currently just to avoid badly conditioned basis */ + if (best_ratio < .001 * MIN_RATIO) + { /* looks like this helps */ + if (bfd_get_count(lp->bfd) > 0) + return -1; + /* didn't help; last chance to improve the choice */ + if (tol_piv == csa->tol_piv) + { tol_piv *= 1000.; + goto more; + } + } +#endif +#if 1 /* FIXME */ + if (ret) + { /* invalidate basic solution components */ +#if 0 /* 28/III-2016 */ + csa->beta_st = csa->d_st = 0; +#else + /* dual solution remains valid */ + csa->beta_st = 0; +#endif + /* set double-bounded non-basic variables to opposite bounds + * for all break-points preceding the chosen one */ + for (t = 1; t < t_best; t++) + { k = head[m + bp[t].j]; + xassert(-DBL_MAX < l[k] && l[k] < u[k] && u[k] < +DBL_MAX); + lp->flag[bp[t].j] = !(lp->flag[bp[t].j]); + } + } +#endif + return ret; +} + +#endif + +/*********************************************************************** +* play_coef - play objective coefficients +* +* This routine is called after the reduced costs d[j] was updated and +* the basis was changed to the adjacent one. +* +* It is assumed that before updating all the reduced costs d[j] were +* strongly feasible, so in the adjacent basis d[j] remain feasible +* within a tolerance, i.e. if some d[j] violates its zero bound, the +* violation is insignificant. +* +* If some d[j] violates its zero bound, the routine changes (perturbs) +* objective coefficient cN[j] to provide d[j] = 0, i.e. to make all +* d[j] strongly feasible. Otherwise, if d[j] has a feasible value, the +* routine attempts to reduce (or remove) perturbation in cN[j] by +* shifting d[j] to its zero bound keeping strong feasibility. */ + +static void play_coef(struct csa *csa, int all) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *orig_c = csa->orig_c; + double *d = csa->d; + const double *trow = csa->trow.vec; + /* this vector was used to update d = (d[j]) */ + int j, k; + static const double eps = 1e-9; + /* reduced costs d = (d[j]) should be valid */ + xassert(csa->d_st); + /* walk thru the list of non-basic variables xN = (xN[j]) */ + for (j = 1; j <= n-m; j++) + { if (all || trow[j] != 0.0) + { /* d[j] has changed in the adjacent basis */ + k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + { /* xN[j] is fixed variable */ + /* d[j] may have any sign */ + } + else if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + { /* xN[j] is free (unbounded) variable */ + /* strong feasibility means d[j] = 0 */ + c[k] -= d[j], d[j] = 0.0; + /* in this case dual degeneracy is not critical, since + * if xN[j] enters the basis, it never leaves it */ + } + else if (!flag[j]) + { /* xN[j] has its lower bound active */ + xassert(l[k] != -DBL_MAX); + /* first, we remove current perturbation to provide + * c[k] = orig_c[k] */ + d[j] -= c[k] - orig_c[k], c[k] = orig_c[k]; + /* strong feasibility means d[j] >= 0, but we provide + * d[j] >= +eps to prevent dual degeneracy */ + if (d[j] < +eps) + c[k] -= d[j] - eps, d[j] = +eps; + } + else + { /* xN[j] has its upper bound active */ + xassert(u[k] != +DBL_MAX); + /* similarly, we remove current perturbation to provide + * c[k] = orig_c[k] */ + d[j] -= c[k] - orig_c[k], c[k] = orig_c[k]; + /* strong feasibility means d[j] <= 0, but we provide + * d[j] <= -eps to prevent dual degeneracy */ + if (d[j] > -eps) + c[k] -= d[j] + eps, d[j] = -eps; + } + } + } + return; +} + +#if 1 /* 11/VII-2017 */ +static void remove_perturb(struct csa *csa) +{ /* remove perturbation */ + SPXLP *lp = csa->lp; + int n = lp->n; + double *c = lp->c; + double *orig_c = csa->orig_c; + memcpy(c, orig_c, (1+n) * sizeof(double)); + /* removing perturbation changes dual solution components */ + csa->phase = csa->d_st = 0; +#if 1 + if (csa->msg_lev >= GLP_MSG_ALL) + xprintf("Removing LP perturbation [%d]...\n", + csa->it_cnt); +#endif + return; +} +#endif + +/*********************************************************************** +* display - display search progress +* +* This routine displays some information about the search progress +* that includes: +* +* search phase; +* +* number of simplex iterations performed by the solver; +* +* original objective value (only on phase II); +* +* sum of (scaled) dual infeasibilities for original bounds; +* +* number of dual infeasibilities (phase I) or primal infeasibilities +* (phase II); +* +* number of basic factorizations since last display output. */ + +static void display(struct csa *csa, int spec) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + double *l = csa->orig_l; /* original lower bounds */ + double *u = csa->orig_u; /* original upper bounds */ + double *beta = csa->beta; + double *d = csa->d; + int j, k, nnn; + double sum; +#if 1 /* 15/VII-2017 */ + double tm_cur; +#endif + /* check if the display output should be skipped */ + if (csa->msg_lev < GLP_MSG_ON) goto skip; +#if 1 /* 15/VII-2017 */ + tm_cur = xtime(); +#endif + if (csa->out_dly > 0 && +#if 0 /* 15/VII-2017 */ + 1000.0 * xdifftime(xtime(), csa->tm_beg) < csa->out_dly) +#else + 1000.0 * xdifftime(tm_cur, csa->tm_beg) < csa->out_dly) +#endif + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; +#if 0 /* 15/VII-2017 */ + if (!spec && csa->it_cnt % csa->out_frq != 0) goto skip; +#else + if (!spec && + 1000.0 * xdifftime(tm_cur, csa->tm_dpy) < csa->out_frq) + goto skip; +#endif + /* display search progress depending on search phase */ + switch (csa->phase) + { case 1: + /* compute sum and number of (scaled) dual infeasibilities + * for original bounds */ + sum = 0.0, nnn = 0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (d[j] > 0.0) + { /* xN[j] should have lower bound */ + if (l[k] == -DBL_MAX) + { sum += d[j]; + if (d[j] > +1e-7) + nnn++; + } + } + else if (d[j] < 0.0) + { /* xN[j] should have upper bound */ + if (u[k] == +DBL_MAX) + { sum -= d[j]; + if (d[j] < -1e-7) + nnn++; + } + } + } + /* on phase I variables have artificial bounds which are + * meaningless for original LP, so corresponding objective + * function value is also meaningless */ +#if 0 /* 27/III-2016 */ + xprintf(" %6d: %23s inf = %11.3e (%d)", + csa->it_cnt, "", sum, nnn); +#else + xprintf(" %6d: sum = %17.9e inf = %11.3e (%d)", + csa->it_cnt, lp->c[0] - spx_eval_obj(lp, beta), + sum, nnn); +#endif + break; + case 2: + /* compute sum of (scaled) dual infeasibilities */ + sum = 0.0, nnn = 0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (d[j] > 0.0) + { /* xN[j] should have its lower bound active */ + if (l[k] == -DBL_MAX || flag[j]) + sum += d[j]; + } + else if (d[j] < 0.0) + { /* xN[j] should have its upper bound active */ + if (l[k] != u[k] && !flag[j]) + sum -= d[j]; + } + } + /* compute number of primal infeasibilities */ + nnn = spy_chuzr_sel(lp, beta, csa->tol_bnd, csa->tol_bnd1, + NULL); + xprintf("#%6d: obj = %17.9e inf = %11.3e (%d)", +#if SCALE_Z + csa->it_cnt, + (double)csa->dir * csa->fz * spx_eval_obj(lp, beta), +#else + csa->it_cnt, (double)csa->dir * spx_eval_obj(lp, beta), +#endif + sum, nnn); + break; + default: + xassert(csa != csa); + } + if (csa->inv_cnt) + { /* number of basis factorizations performed */ + xprintf(" %d", csa->inv_cnt); + csa->inv_cnt = 0; + } +#if 1 /* 23/III-2016 */ + if (csa->r_test == GLP_RT_FLIP) + { /*xprintf(" %d,%d", csa->ns_cnt, csa->ls_cnt);*/ + if (csa->ns_cnt + csa->ls_cnt) + xprintf(" %d%%", + (100 * csa->ls_cnt) / (csa->ns_cnt + csa->ls_cnt)); + csa->ns_cnt = csa->ls_cnt = 0; + } +#endif + xprintf("\n"); + csa->it_dpy = csa->it_cnt; +#if 1 /* 15/VII-2017 */ + csa->tm_dpy = tm_cur; +#endif +skip: return; +} + +#if 1 /* 31/III-2016 */ +static +void spy_update_r(SPXLP *lp, int p, int q, const double beta[/*1+m*/], + const FVS *tcol, double tol, double tol1, FVS *r) +{ /* update vector r of primal infeasibilities */ + /* it is assumed that xB[p] leaves the basis, xN[q] enters the + * basis, and beta corresponds to the adjacent basis (i.e. this + * routine should be called after spx_update_beta) */ + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int *tcol_ind = tcol->ind; + int *ind = r->ind; + double *vec = r->vec; + int i, k, t, nnz; + double lk, uk, ri, eps; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + nnz = r->nnz; + for (t = tcol->nnz; t >= 1; t--) + { i = tcol_ind[t]; + /* xB[i] changes in the adjacent basis to beta[i], so only + * r[i] should be updated */ + if (i == p) + k = head[m+q]; /* x[k] = new xB[p] = old xN[q] */ + else + k = head[i]; /* x[k] = new xB[i] = old xB[i] */ + lk = l[k], uk = u[k]; + /* determine new value of r[i]; see spy_eval_r */ + ri = 0.0; + if (beta[i] < lk) + { /* determine absolute tolerance eps1[i] */ + eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* lower bound is violated */ + ri = lk - beta[i]; + } + } + else if (beta[i] > uk) + { /* determine absolute tolerance eps2[i] */ + eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* upper bound is violated */ + ri = uk - beta[i]; + } + } + if (ri == 0.0) + { if (vec[i] != 0.0) + vec[i] = DBL_MIN; /* will be removed */ + } + else + { if (vec[i] == 0.0) + ind[++nnz] = i; + vec[i] = ri; + } + + } + r->nnz = nnz; + /* remove zero elements */ + fvs_adjust_vec(r, DBL_MIN + DBL_MIN); + return; +} +#endif + +/*********************************************************************** +* spy_dual - driver to the dual simplex method +* +* This routine is a driver to the two-phase dual simplex method. +* +* On exit this routine returns one of the following codes: +* +* 0 LP instance has been successfully solved. +* +* GLP_EOBJLL +* Objective lower limit has been reached (maximization). +* +* GLP_EOBJUL +* Objective upper limit has been reached (minimization). +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +static int dual_simplex(struct csa *csa) +{ /* dual simplex method main logic routine */ + SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPYSE *se = csa->se; +#if 0 /* 30/III-2016 */ + int *list = csa->list; +#endif +#if 0 /* 31/III-2016 */ + double *trow = csa->trow; + double *tcol = csa->tcol; +#endif + double *pi = csa->work; + int msg_lev = csa->msg_lev; + double tol_bnd = csa->tol_bnd; + double tol_bnd1 = csa->tol_bnd1; + double tol_dj = csa->tol_dj; + double tol_dj1 = csa->tol_dj1; + int j, k, p_flag, refct, ret; + int perturb = -1; + /* -1 = perturbation is not used, but enabled + * 0 = perturbation is not used and disabled + * +1 = perturbation is being used */ +#if 1 /* 27/III-2016 */ + int instab = 0; /* instability count */ +#endif +#ifdef TIMING + double t_total = timer(); /* total time */ + double t_fact = 0.0; /* computing factorization */ + double t_rtest = 0.0; /* performing ratio test */ + double t_pivcol = 0.0; /* computing pivot column */ + double t_upd1 = 0.0; /* updating primal values */ + double t_upd2 = 0.0; /* updating dual values */ + double t_upd3 = 0.0; /* updating se weights */ + double t_upd4 = 0.0; /* updating matrix N */ + double t_upd5 = 0.0; /* updating factorization */ + double t_start; +#endif + check_flags(csa); +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (!lp->valid) + { double cond; +#ifdef TIMING + t_start = timer(); +#endif + ret = spx_factorize(lp); +#ifdef TIMING + t_fact += timer() - t_start; +#endif + csa->inv_cnt++; + if (ret != 0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + /* check condition of the basis matrix */ + cond = bfd_condest(lp->bfd); + if (cond > 1.0 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: basis matrix is singular to working prec" + "ision (cond = %.3g)\n", cond); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + if (cond > 0.001 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: basis matrix is ill-conditioned (cond " + "= %.3g)\n", cond); + } + /* invalidate basic solution components */ + csa->beta_st = csa->d_st = 0; + } + /* compute reduced costs of non-basic variables d = (d[j]) */ + if (!csa->d_st) + { spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->d_st = 1; /* just computed */ + /* determine the search phase, if not determined yet (this is + * performed only once at the beginning of the search for the + * original bounds) */ + if (!csa->phase) + { j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1); + if (j > 0) + { /* initial basic solution is dual infeasible and cannot + * be recovered */ + /* start to search for dual feasible solution */ + set_art_bounds(csa); + csa->phase = 1; + } + else + { /* initial basic solution is either dual feasible or its + * dual feasibility has been recovered */ + /* start to search for optimal solution */ + csa->phase = 2; + } + } + /* make sure that current basic solution is dual feasible */ +#if 1 /* 11/VII-2017 */ + if (perturb <= 0) + { if (check_feas(csa, tol_dj, tol_dj1, 0)) + { /* dual feasibility is broken due to excessive round-off + * errors */ + if (perturb < 0) + { if (msg_lev >= GLP_MSG_ALL) + xprintf("Perturbing LP to avoid instability [%d].." + ".\n", csa->it_cnt); + perturb = 1; + goto loop; + } + if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (dual simplex" + ", phase %s)\n", csa->phase == 1 ? "I" : "II"); + instab++; + if (csa->dualp && instab >= 10) + { /* do not continue the search; report failure */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: dual simplex failed due to exces" + "sive numerical instability\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = -1; /* special case of GLP_EFAIL */ + goto fini; + } + /* try to recover dual feasibility */ + j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1); + if (j > 0) + { /* dual feasibility cannot be recovered (this may + * happen only on phase II) */ + xassert(csa->phase == 2); + /* restart to search for dual feasible solution */ + set_art_bounds(csa); + csa->phase = 1; + } + } + } + else + { /* FIXME */ + play_coef(csa, 1); + } + } +#endif + /* at this point the search phase is determined */ + xassert(csa->phase == 1 || csa->phase == 2); + /* compute values of basic variables beta = (beta[i]) */ + if (!csa->beta_st) + { spx_eval_beta(lp, beta); +#if 1 /* 31/III-2016 */ + /* also compute vector r of primal infeasibilities */ + switch (csa->phase) + { case 1: + spy_eval_r(lp, beta, 1e-8, 0.0, &csa->r); + break; + case 2: + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); + break; + default: + xassert(csa != csa); + } +#endif + csa->beta_st = 1; /* just computed */ + } + /* reset the dual reference space, if necessary */ + if (se != NULL && !se->valid) + spy_reset_refsp(lp, se), refct = 1000; + /* at this point the basis factorization and all basic solution + * components are valid */ + xassert(lp->valid && csa->beta_st && csa->d_st); +#ifdef GLP_DEBUG + check_flags(csa); +#endif +#if CHECK_ACCURACY + /* check accuracy of current basic solution components (only for + * debugging) */ + check_accuracy(csa); +#endif + /* check if the objective limit has been reached */ + if (csa->phase == 2 && csa->obj_lim != DBL_MAX + && spx_eval_obj(lp, beta) >= csa->obj_lim) + { +#if 1 /* 26/V-2017 by mao */ + if (perturb > 0) + { /* remove perturbation */ + /* [Should note that perturbing of objective coefficients + * implemented in play_coef is equivalent to *relaxing* of + * (zero) bounds of dual variables, so the perturbed + * objective is always better (*greater*) that the original + * one at the same basic point.] */ + remove_perturb(csa); + perturb = 0; + } +#endif + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("OBJECTIVE %s LIMIT REACHED; SEARCH TERMINATED\n", + csa->dir > 0 ? "UPPER" : "LOWER"); +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); +#else + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); + csa->p_stat = (csa->r.nnz == 0 ? GLP_FEAS : GLP_INFEAS); +#endif + csa->d_stat = GLP_FEAS; + ret = (csa->dir > 0 ? GLP_EOBJUL : GLP_EOBJLL); + goto fini; + } + /* check if the iteration limit has been exhausted */ + if (csa->it_cnt - csa->it_beg >= csa->it_lim) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + if (csa->phase == 1) + { set_orig_bounds(csa); + check_flags(csa); + spx_eval_beta(lp, beta); + } +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); +#else + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); + csa->p_stat = (csa->r.nnz == 0 ? GLP_FEAS : GLP_INFEAS); +#endif + csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS); + ret = GLP_EITLIM; + goto fini; + } + /* check if the time limit has been exhausted */ + if (1000.0 * xdifftime(xtime(), csa->tm_beg) >= csa->tm_lim) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + if (csa->phase == 1) + { set_orig_bounds(csa); + check_flags(csa); + spx_eval_beta(lp, beta); + } +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); +#else + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); + csa->p_stat = (csa->r.nnz == 0 ? GLP_FEAS : GLP_INFEAS); +#endif + csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS); + ret = GLP_ETMLIM; + goto fini; + } + /* display the search progress */ + display(csa, 0); + /* select eligible basic variables */ +#if 0 /* 31/III-2016; not needed because r is valid */ + switch (csa->phase) + { case 1: +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, 1e-8, 0.0, list); +#else + spy_eval_r(lp, beta, 1e-8, 0.0, &csa->r); +#endif + break; + case 2: +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); +#else + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); +#endif + break; + default: + xassert(csa != csa); + } +#endif + /* check for optimality */ +#if 0 /* 30/III-2016 */ + if (csa->num == 0) +#else + if (csa->r.nnz == 0) +#endif + { if (perturb > 0 && csa->phase == 2) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + /* current basis is optimal */ + display(csa, 1); + switch (csa->phase) + { case 1: + /* check for dual feasibility */ + set_orig_bounds(csa); + check_flags(csa); + if (check_feas(csa, tol_dj, tol_dj1, 0) == 0) + { /* dual feasible solution found; switch to phase II */ + csa->phase = 2; + xassert(!csa->beta_st); + goto loop; + } +#if 1 /* 26/V-2017 by cmatraki */ + if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + goto loop; + } +#endif + /* no dual feasible solution exists */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n"); + spx_eval_beta(lp, beta); +#if 0 /* 30/III-2016 */ + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, + list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); +#else + spy_eval_r(lp, beta, tol_bnd, tol_bnd1, &csa->r); + csa->p_stat = (csa->r.nnz == 0 ? GLP_FEAS : GLP_INFEAS); +#endif + csa->d_stat = GLP_NOFEAS; + ret = 0; + goto fini; + case 2: + /* optimal solution found */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL LP SOLUTION FOUND\n"); + csa->p_stat = csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* choose xB[p] and xN[q] */ +#if 0 /* 23/III-2016 */ + choose_pivot(csa); +#else +#ifdef TIMING + t_start = timer(); +#endif +#if 1 /* 31/III-2016 */ + ret = choose_pivot(csa); +#endif +#ifdef TIMING + t_rtest += timer() - t_start; +#endif + if (ret < 0) + { lp->valid = 0; + goto loop; + } + if (ret == 0) + csa->ns_cnt++; + else + csa->ls_cnt++; +#endif + /* check for dual unboundedness */ + if (csa->q == 0) + { if (perturb > 0) + { /* remove perturbation */ + remove_perturb(csa); + perturb = 0; + } + if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + switch (csa->phase) + { case 1: + /* this should never happen */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: dual simplex failed\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + case 2: + /* dual unboundedness detected */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); + csa->p_stat = GLP_NOFEAS; + csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* compute q-th column of the simplex table */ +#ifdef TIMING + t_start = timer(); +#endif +#if 0 /* 31/III-2016 */ + spx_eval_tcol(lp, csa->q, tcol); +#else + spx_eval_tcol(lp, csa->q, csa->tcol.vec); + fvs_gather_vec(&csa->tcol, DBL_EPSILON); +#endif +#ifdef TIMING + t_pivcol += timer() - t_start; +#endif + /* FIXME: tcol[p] and trow[q] should be close to each other */ +#if 0 /* 26/V-2017 by cmatraki */ + xassert(csa->tcol.vec[csa->p] != 0.0); +#else + if (csa->tcol.vec[csa->p] == 0.0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: tcol[p] = 0.0\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } +#endif + /* update values of basic variables for adjacent basis */ + k = head[csa->p]; /* x[k] = xB[p] */ + p_flag = (l[k] != u[k] && beta[csa->p] > u[k]); +#if 0 /* 16/III-2016 */ + spx_update_beta(lp, beta, csa->p, p_flag, csa->q, tcol); + csa->beta_st = 2; +#else + /* primal solution may be invalidated due to long step */ +#ifdef TIMING + t_start = timer(); +#endif + if (csa->beta_st) +#if 0 /* 30/III-2016 */ + { spx_update_beta(lp, beta, csa->p, p_flag, csa->q, tcol); +#else + { spx_update_beta_s(lp, beta, csa->p, p_flag, csa->q, + &csa->tcol); + /* also update vector r of primal infeasibilities */ + /*fvs_check_vec(&csa->r);*/ + switch (csa->phase) + { case 1: + spy_update_r(lp, csa->p, csa->q, beta, &csa->tcol, + 1e-8, 0.0, &csa->r); + break; + case 2: + spy_update_r(lp, csa->p, csa->q, beta, &csa->tcol, + tol_bnd, tol_bnd1, &csa->r); + break; + default: + xassert(csa != csa); + } + /*fvs_check_vec(&csa->r);*/ +#endif + csa->beta_st = 2; + } +#ifdef TIMING + t_upd1 += timer() - t_start; +#endif +#endif +#if 1 /* 11/VII-2017 */ + /* check for stalling */ + { int k; + xassert(1 <= csa->p && csa->p <= m); + xassert(1 <= csa->q && csa->q <= n-m); + /* FIXME: recompute d[q]; see spx_update_d */ + k = head[m+csa->q]; /* x[k] = xN[q] */ + if (!(lp->l[k] == -DBL_MAX && lp->u[k] == +DBL_MAX)) + { if (fabs(d[csa->q]) >= 1e-6) + { csa->degen = 0; + goto skip1; + } + /* degenerate iteration has been detected */ + csa->degen++; + if (perturb < 0 && csa->degen >= 200) + { if (msg_lev >= GLP_MSG_ALL) + xprintf("Perturbing LP to avoid stalling [%d]...\n", + csa->it_cnt); + perturb = 1; + } +skip1: ; + } + } +#endif + /* update reduced costs of non-basic variables for adjacent + * basis */ +#if 1 /* 28/III-2016 */ + xassert(csa->d_st); +#endif +#ifdef TIMING + t_start = timer(); +#endif +#if 0 /* 30/III-2016 */ + if (spx_update_d(lp, d, csa->p, csa->q, trow, tcol) <= 1e-9) +#else + if (spx_update_d_s(lp, d, csa->p, csa->q, &csa->trow, &csa->tcol) + <= 1e-9) +#endif + { /* successful updating */ + csa->d_st = 2; + } + else + { /* new reduced costs are inaccurate */ + csa->d_st = 0; + } +#ifdef TIMING + t_upd2 += timer() - t_start; +#endif + /* update steepest edge weights for adjacent basis, if used */ +#ifdef TIMING + t_start = timer(); +#endif + if (se != NULL) + { if (refct > 0) +#if 0 /* 30/III-2016 */ + { if (spy_update_gamma(lp, se, csa->p, csa->q, trow, tcol) + <= 1e-3) +#else + { if (spy_update_gamma_s(lp, se, csa->p, csa->q, &csa->trow, + &csa->tcol) <= 1e-3) +#endif + { /* successful updating */ + refct--; + } + else + { /* new weights are inaccurate; reset reference space */ + se->valid = 0; + } + } + else + { /* too many updates; reset reference space */ + se->valid = 0; + } + } +#ifdef TIMING + t_upd3 += timer() - t_start; +#endif +#ifdef TIMING + t_start = timer(); +#endif + /* update matrix N for adjacent basis, if used */ + if (nt != NULL) + spx_update_nt(lp, nt, csa->p, csa->q); +#ifdef TIMING + t_upd4 += timer() - t_start; +#endif + /* change current basis header to adjacent one */ + spx_change_basis(lp, csa->p, p_flag, csa->q); + /* and update factorization of the basis matrix */ +#ifdef TIMING + t_start = timer(); +#endif +#if 0 /* 16/III-2016 */ + if (csa->p > 0) +#endif + spx_update_invb(lp, csa->p, head[csa->p]); +#ifdef TIMING + t_upd5 += timer() - t_start; +#endif + if (perturb > 0 && csa->d_st) + play_coef(csa, 0); + /* dual simplex iteration complete */ + csa->it_cnt++; + goto loop; +fini: +#ifdef TIMING + t_total = timer() - t_total; + xprintf("Total time = %10.3f\n", t_total); + xprintf("Factorization = %10.3f\n", t_fact); + xprintf("Ratio test = %10.3f\n", t_rtest); + xprintf("Pivot column = %10.3f\n", t_pivcol); + xprintf("Updating beta = %10.3f\n", t_upd1); + xprintf("Updating d = %10.3f\n", t_upd2); + xprintf("Updating gamma = %10.3f\n", t_upd3); + xprintf("Updating N = %10.3f\n", t_upd4); + xprintf("Updating inv(B) = %10.3f\n", t_upd5); +#endif + return ret; +} + +int spy_dual(glp_prob *P, const glp_smcp *parm) +{ /* driver to the dual simplex method */ + struct csa csa_, *csa = &csa_; + SPXLP lp; + SPXAT at; + SPXNT nt; + SPYSE se; + int ret, *map, *daeh; +#if SCALE_Z + int i, j, k; +#endif + /* build working LP and its initial basis */ + memset(csa, 0, sizeof(struct csa)); + csa->lp = &lp; + spx_init_lp(csa->lp, P, parm->excl); + spx_alloc_lp(csa->lp); + map = talloc(1+P->m+P->n, int); + spx_build_lp(csa->lp, P, parm->excl, parm->shift, map); + spx_build_basis(csa->lp, P, map); + switch (P->dir) + { case GLP_MIN: + csa->dir = +1; + break; + case GLP_MAX: + csa->dir = -1; + break; + default: + xassert(P != P); + } +#if SCALE_Z + csa->fz = 0.0; + for (k = 1; k <= csa->lp->n; k++) + { double t = fabs(csa->lp->c[k]); + if (csa->fz < t) + csa->fz = t; + } + if (csa->fz <= 1000.0) + csa->fz = 1.0; + else + csa->fz /= 1000.0; + /*xprintf("csa->fz = %g\n", csa->fz);*/ + for (k = 0; k <= csa->lp->n; k++) + csa->lp->c[k] /= csa->fz; +#endif + csa->orig_b = talloc(1+csa->lp->m, double); + memcpy(csa->orig_b, csa->lp->b, (1+csa->lp->m) * sizeof(double)); + csa->orig_c = talloc(1+csa->lp->n, double); + memcpy(csa->orig_c, csa->lp->c, (1+csa->lp->n) * sizeof(double)); + csa->orig_l = talloc(1+csa->lp->n, double); + memcpy(csa->orig_l, csa->lp->l, (1+csa->lp->n) * sizeof(double)); + csa->orig_u = talloc(1+csa->lp->n, double); + memcpy(csa->orig_u, csa->lp->u, (1+csa->lp->n) * sizeof(double)); + switch (parm->aorn) + { case GLP_USE_AT: + /* build matrix A in row-wise format */ + csa->at = &at; + csa->nt = NULL; + spx_alloc_at(csa->lp, csa->at); + spx_build_at(csa->lp, csa->at); + break; + case GLP_USE_NT: + /* build matrix N in row-wise format for initial basis */ + csa->at = NULL; + csa->nt = &nt; + spx_alloc_nt(csa->lp, csa->nt); + spx_init_nt(csa->lp, csa->nt); + spx_build_nt(csa->lp, csa->nt); + break; + default: + xassert(parm != parm); + } + /* allocate and initialize working components */ + csa->phase = 0; + csa->beta = talloc(1+csa->lp->m, double); + csa->beta_st = 0; + csa->d = talloc(1+csa->lp->n-csa->lp->m, double); + csa->d_st = 0; + switch (parm->pricing) + { case GLP_PT_STD: + csa->se = NULL; + break; + case GLP_PT_PSE: + csa->se = &se; + spy_alloc_se(csa->lp, csa->se); + break; + default: + xassert(parm != parm); + } +#if 0 /* 30/III-2016 */ + csa->list = talloc(1+csa->lp->m, int); + csa->trow = talloc(1+csa->lp->n-csa->lp->m, double); + csa->tcol = talloc(1+csa->lp->m, double); +#else + fvs_alloc_vec(&csa->r, csa->lp->m); + fvs_alloc_vec(&csa->trow, csa->lp->n-csa->lp->m); + fvs_alloc_vec(&csa->tcol, csa->lp->m); +#endif +#if 1 /* 16/III-2016 */ + csa->bp = NULL; +#endif + csa->work = talloc(1+csa->lp->m, double); + csa->work1 = talloc(1+csa->lp->n-csa->lp->m, double); +#if 0 /* 11/VI-2017 */ +#if 1 /* 31/III-2016 */ + fvs_alloc_vec(&csa->wrow, csa->lp->n-csa->lp->m); + fvs_alloc_vec(&csa->wcol, csa->lp->m); +#endif +#endif + /* initialize control parameters */ + csa->msg_lev = parm->msg_lev; + csa->dualp = (parm->meth == GLP_DUALP); +#if 0 /* 16/III-2016 */ + switch (parm->r_test) + { case GLP_RT_STD: + csa->harris = 0; + break; + case GLP_RT_HAR: + csa->harris = 1; + break; + default: + xassert(parm != parm); + } +#else + switch (parm->r_test) + { case GLP_RT_STD: + case GLP_RT_HAR: + break; + case GLP_RT_FLIP: + csa->bp = talloc(1+csa->lp->n-csa->lp->m, SPYBP); + break; + default: + xassert(parm != parm); + } + csa->r_test = parm->r_test; +#endif + csa->tol_bnd = parm->tol_bnd; + csa->tol_bnd1 = .001 * parm->tol_bnd; + csa->tol_dj = parm->tol_dj; + csa->tol_dj1 = .001 * parm->tol_dj; +#if 0 + csa->tol_dj1 = 1e-9 * parm->tol_dj; +#endif + csa->tol_piv = parm->tol_piv; + switch (P->dir) + { case GLP_MIN: + csa->obj_lim = + parm->obj_ul; + break; + case GLP_MAX: + csa->obj_lim = - parm->obj_ll; + break; + default: + xassert(parm != parm); + } +#if SCALE_Z + if (csa->obj_lim != DBL_MAX) + csa->obj_lim /= csa->fz; +#endif + csa->it_lim = parm->it_lim; + csa->tm_lim = parm->tm_lim; + csa->out_frq = parm->out_frq; + csa->out_dly = parm->out_dly; + /* initialize working parameters */ + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = P->it_cnt; + csa->it_dpy = -1; +#if 1 /* 15/VII-2017 */ + csa->tm_dpy = 0.0; +#endif + csa->inv_cnt = 0; +#if 1 /* 11/VII-2017 */ + csa->degen = 0; +#endif +#if 1 /* 23/III-2016 */ + csa->ns_cnt = csa->ls_cnt = 0; +#endif + /* try to solve working LP */ + ret = dual_simplex(csa); + /* return basis factorization back to problem object */ + P->valid = csa->lp->valid; + P->bfd = csa->lp->bfd; + /* set solution status */ + P->pbs_stat = csa->p_stat; + P->dbs_stat = csa->d_stat; + /* if the solver failed, do not store basis header and basic + * solution components to problem object */ + if (ret == GLP_EFAIL) + goto skip; + /* convert working LP basis to original LP basis and store it to + * problem object */ + daeh = talloc(1+csa->lp->n, int); + spx_store_basis(csa->lp, P, map, daeh); + /* compute simplex multipliers for final basic solution found by + * the solver */ + spx_eval_pi(csa->lp, csa->work); + /* convert working LP solution to original LP solution and store + * it to problem object */ +#if SCALE_Z + for (i = 1; i <= csa->lp->m; i++) + csa->work[i] *= csa->fz; + for (j = 1; j <= csa->lp->n-csa->lp->m; j++) + csa->d[j] *= csa->fz; +#endif + spx_store_sol(csa->lp, P, parm->shift, map, daeh, csa->beta, + csa->work, csa->d); + tfree(daeh); + /* save simplex iteration count */ + P->it_cnt = csa->it_cnt; + /* report auxiliary/structural variable causing unboundedness */ + P->some = 0; + if (csa->p_stat == GLP_NOFEAS && csa->d_stat == GLP_FEAS) + { int k, kk; + /* xB[p] = x[k] causes dual unboundedness */ + xassert(1 <= csa->p && csa->p <= csa->lp->m); + k = csa->lp->head[csa->p]; + xassert(1 <= k && k <= csa->lp->n); + /* convert to number of original variable */ + for (kk = 1; kk <= P->m + P->n; kk++) + { if (abs(map[kk]) == k) + { P->some = kk; + break; + } + } + xassert(P->some != 0); + } +skip: /* deallocate working objects and arrays */ + spx_free_lp(csa->lp); + tfree(map); + tfree(csa->orig_b); + tfree(csa->orig_c); + tfree(csa->orig_l); + tfree(csa->orig_u); + if (csa->at != NULL) + spx_free_at(csa->lp, csa->at); + if (csa->nt != NULL) + spx_free_nt(csa->lp, csa->nt); + tfree(csa->beta); + tfree(csa->d); + if (csa->se != NULL) + spy_free_se(csa->lp, csa->se); +#if 0 /* 30/III-2016 */ + tfree(csa->list); + tfree(csa->trow); +#else + fvs_free_vec(&csa->r); + fvs_free_vec(&csa->trow); +#endif +#if 1 /* 16/III-2016 */ + if (csa->bp != NULL) + tfree(csa->bp); +#endif +#if 0 /* 29/III-2016 */ + tfree(csa->tcol); +#else + fvs_free_vec(&csa->tcol); +#endif + tfree(csa->work); + tfree(csa->work1); +#if 0 /* 11/VI-2017 */ +#if 1 /* 31/III-2016 */ + fvs_free_vec(&csa->wrow); + fvs_free_vec(&csa->wcol); +#endif +#endif + /* return to calling program */ + return ret >= 0 ? ret : GLP_EFAIL; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/README b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/README new file mode 100644 index 000000000..2796312f1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/README @@ -0,0 +1,45 @@ +NOTE: Files in this subdirectory are NOT part of the GLPK package, but + are used with GLPK. + + The original code was modified according to GLPK requirements by + Andrew Makhorin . + + The following files were rewritten: + gzguts.h, zconf.h, zutil.h. + + The following files were added: + zio.h, zio.c. + + Other files were not changed. +************************************************************************ +zlib general purpose compression library +version 1.2.5, April 19th, 2010 + +Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + +The data format used by the zlib library is described by RFCs (Request +for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate +format) and rfc1952.txt (gzip format). diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/adler32.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/adler32.c new file mode 100644 index 000000000..65ad6a5ad --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/compress.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/compress.c new file mode 100644 index 000000000..ea4dfbe9d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/compress.c @@ -0,0 +1,80 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.c new file mode 100644 index 000000000..91be372d2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.h new file mode 100644 index 000000000..8053b6117 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.c new file mode 100644 index 000000000..5c4022f3d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.c @@ -0,0 +1,1834 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://www.ietf.org/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +#ifndef NO_DUMMY_DECL +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ +#endif + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->wrap == 2 || + (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + return Z_STREAM_ERROR; + + s = strm->state; + if (s->wrap) + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > s->w_size) { + length = s->w_size; + dictionary += dictLength - length; /* use the tail of the dictionary */ + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (strm->state->wrap != 2) return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + strm->state->bi_valid = bits; + strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_BLOCK); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = good_length; + s->max_lazy_match = max_lazy; + s->nice_match = nice_length; + s->max_chain_length = max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + Bytef *str; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (strm == Z_NULL || strm->state == Z_NULL) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the header */ + if (s->status == INIT_STATE) { +#ifdef GZIP + if (s->wrap == 2) { + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + else +#endif + { + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + } + } +#ifdef GZIP + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + + while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) + break; + } + put_byte(s, s->gzhead->extra[s->gzindex]); + s->gzindex++; + } + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (s->gzindex == s->gzhead->extra_len) { + s->gzindex = 0; + s->status = NAME_STATE; + } + } + else + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) { + s->gzindex = 0; + s->status = COMMENT_STATE; + } + } + else + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + uInt beg = s->pending; /* start of bytes to update crc */ + int val; + + do { + if (s->pending == s->pending_buf_size) { + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + flush_pending(strm); + beg = s->pending; + if (s->pending == s->pending_buf_size) { + val = 1; + break; + } + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + if (s->gzhead->hcrc && s->pending > beg) + strm->adler = crc32(strm->adler, s->pending_buf + beg, + s->pending - beg); + if (val == 0) + s->status = HCRC_STATE; + } + else + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) + flush_pending(strm); + if (s->pending + 2 <= s->pending_buf_size) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + } + } + else + s->status = BUSY_STATE; + } +#endif + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && + status != EXTRA_STATE && + status != NAME_STATE && + status != COMMENT_STATE && + status != HCRC_STATE && + status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy(dest, source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy(ds, ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, strm->next_in, len); + } +#endif + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest encodable run. + */ + if (s->lookahead < MAX_MATCH) { + fill_window(s); + if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (int)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.h new file mode 100644 index 000000000..cbf0d1ea5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzclose.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzclose.c new file mode 100644 index 000000000..caeb99a31 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzguts.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzguts.h new file mode 100644 index 000000000..9d01ac7b7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzguts.h @@ -0,0 +1,74 @@ +/* gzguts.h (zlib internal header definitions for gz* operations) */ + +/* Modified by Andrew Makhorin , April 2011 */ + +/* Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef GZGUTS_H +#define GZGUTS_H + +#define ZLIB_INTERNAL + +#include +#include +#include +#include +#include +#include "zio.h" +#include "zlib.h" + +#define local static + +#define zstrerror() strerror(errno) + +#define GZBUFSIZE 8192 + +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 + +#define LOOK 0 +#define COPY 1 +#define GZIP 2 + +typedef struct +{ int mode; + int fd; + char *path; + z_off64_t pos; + unsigned size; + unsigned want; + unsigned char *in; + unsigned char *out; + unsigned char *next; + unsigned have; + int eof; + z_off64_t start; + z_off64_t raw; + int how; + int direct; + int level; + int strategy; + z_off64_t skip; + int seek; + int err; + char *msg; + z_stream strm; +} gz_state; + +typedef gz_state *gz_statep; + +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); + +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzlib.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzlib.c new file mode 100644 index 000000000..603e60ed5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzlib.c @@ -0,0 +1,537 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const char *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + if (state->mode == GZ_READ) { /* for reading ... */ + state->have = 0; /* no output data available */ + state->eof = 0; /* not at end of file */ + state->how = LOOK; /* look for gzip header */ + state->direct = 1; /* default for empty file */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gz_statep state; + + /* allocate gzFile structure to return */ + state = malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* save the path name for error messages */ + state->path = malloc(strlen(path) + 1); + if (state->path == NULL) { + free(state); + return NULL; + } + strcpy(state->path, path); + + /* open the file with the appropriate mode (or just use fd) */ + state->fd = fd != -1 ? fd : + open(path, +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | ( + state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))), + 0666); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) + state->mode = GZ_WRITE; /* simplify later checks */ + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; + sprintf(path, "", fd); /* for debugging */ + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if (size == 0) + return -1; + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->pos + offset >= state->raw) { + ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + if (ret == -1) + return -1; + state->have = 0; + state->eof = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->pos += offset; + return state->pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? + (unsigned)offset : state->have; + state->have -= n; + state->next += n; + state->pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? + (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->msg == NULL ? "" : state->msg; +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) + state->eof = 0; + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, save as static string */ + if (err == Z_MEM_ERROR) { + state->msg = (char *)msg; + return; + } + + /* construct error message with path */ + if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + state->err = Z_MEM_ERROR; + state->msg = (char *)"out of memory"; + return; + } + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); + return; +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzread.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzread.c new file mode 100644 index 000000000..548201ab0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzread.c @@ -0,0 +1,653 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_next4 OF((gz_statep, unsigned long *)); +local int gz_head OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_make OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + + *have = 0; + do { + ret = read(state->fd, buf + *have, len - *have); + if (ret <= 0) + break; + *have += ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + gz_avail() assumes that strm->avail_in == 0. */ +local int gz_avail(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->err != Z_OK) + return -1; + if (state->eof == 0) { + if (gz_load(state, state->in, state->size, + (unsigned *)&(strm->avail_in)) == -1) + return -1; + strm->next_in = state->in; + } + return 0; +} + +/* Get next byte from input, or -1 if end or error. */ +#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ + (strm->avail_in == 0 ? -1 : \ + (strm->avail_in--, *(strm->next_in)++))) + +/* Get a four-byte little-endian integer and return 0 on success and the value + in *ret. Otherwise -1 is returned and *ret is not modified. */ +local int gz_next4(state, ret) + gz_statep state; + unsigned long *ret; +{ + int ch; + unsigned long val; + z_streamp strm = &(state->strm); + + val = NEXT(); + val += (unsigned)NEXT() << 8; + val += (unsigned long)NEXT() << 16; + ch = NEXT(); + if (ch == -1) + return -1; + val += (unsigned long)ch << 24; + *ret = val; + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->have must be zero. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression, and the gzip header will be skipped so + that the next available input data is the raw deflate stream. If direct + copying, then leftover input data from the input buffer will be copied to + the output buffer. In that case, all further file reads will be directly to + either the output buffer or a user buffer. If decompressing, the inflate + state and the check value will be initialized. gz_head() will return 0 on + success or -1 on failure. Failures may include read errors or gzip header + errors. */ +local int gz_head(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + int flags; + unsigned len; + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get some data in the input buffer */ + if (strm->avail_in == 0) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for the gzip magic header bytes 31 and 139 */ + if (strm->next_in[0] == 31) { + strm->avail_in--; + strm->next_in++; + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in && strm->next_in[0] == 139) { + /* we have a gzip header, woo hoo! */ + strm->avail_in--; + strm->next_in++; + + /* skip rest of header */ + if (NEXT() != 8) { /* compression method */ + gz_error(state, Z_DATA_ERROR, "unknown compression method"); + return -1; + } + flags = NEXT(); + if (flags & 0xe0) { /* reserved flag bits */ + gz_error(state, Z_DATA_ERROR, "unknown header flags set"); + return -1; + } + NEXT(); /* modification time */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); /* extra flags */ + NEXT(); /* operating system */ + if (flags & 4) { /* extra field */ + len = (unsigned)NEXT(); + len += (unsigned)NEXT() << 8; + while (len--) + if (NEXT() < 0) + break; + } + if (flags & 8) /* file name */ + while (NEXT() > 0) + ; + if (flags & 16) /* comment */ + while (NEXT() > 0) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + /* an unexpected end of file is not checked for here -- it will be + noticed on the first request for uncompressed data */ + + /* set up for decompression */ + inflateReset(strm); + strm->adler = crc32(0L, Z_NULL, 0); + state->how = GZIP; + state->direct = 0; + return 0; + } + else { + /* not a gzip file -- save first byte (31) and fall to raw i/o */ + state->out[0] = 31; + state->have = 1; + } + } + + /* doing raw i/o, save start of raw data for seeking, copy any leftover + input to output -- this assumes that the output buffer is larger than + the input buffer, which also assures space for gzungetc() */ + state->raw = state->pos; + state->next = state->out; + if (strm->avail_in) { + memcpy(state->next + state->have, strm->next_in, strm->avail_in); + state->have += strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + If the end of the compressed data is reached, then verify the gzip trailer + check value and length (modulo 2^32). state->have and state->next are set + to point to the just decompressed data, and the crc is updated. If the + trailer is verified, state->how is reset to LOOK to look for the next gzip + stream or raw data, once state->have is depleted. Returns 0 on success, -1 + on failure. Failures may include invalid compressed data or a failed gzip + trailer verification. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret; + unsigned had; + unsigned long crc, len; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output and crc check value */ + state->have = had - strm->avail_out; + state->next = strm->next_out - state->have; + strm->adler = crc32(strm->adler, state->next, state->have); + + /* check gzip trailer if at end of deflate stream */ + if (ret == Z_STREAM_END) { + if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { + gz_error(state, Z_DATA_ERROR, "unexpected end of file"); + return -1; + } + if (crc != strm->adler) { + gz_error(state, Z_DATA_ERROR, "incorrect data check"); + return -1; + } + if (len != (strm->total_out & 0xffffffffL)) { + gz_error(state, Z_DATA_ERROR, "incorrect length check"); + return -1; + } + state->how = LOOK; /* ready for next stream, once have is 0 (leave + state->direct unchanged to remember how) */ + } + + /* good decompression */ + return 0; +} + +/* Make data and put in the output buffer. Assumes that state->have == 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for (and skipped if found) to determine wither to copy or decompress. + Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY + or GZIP unless the end of the input file has been reached and all data has + been processed. */ +local int gz_make(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + if (state->how == LOOK) { /* look for gzip header */ + if (gz_head(state) == -1) + return -1; + if (state->have) /* got some data from gz_head() */ + return 0; + } + if (state->how == COPY) { /* straight copy */ + if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) + return -1; + state->next = state->out; + } + else if (state->how == GZIP) { /* decompress */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->have) { + n = GT_OFF(state->have) || (z_off64_t)state->have > len ? + (unsigned)len : state->have; + state->have -= n; + state->next += n; + state->pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + unsigned got, n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return -1; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* first just try copying data from the output buffer */ + if (state->have) { + n = state->have > len ? len : state->have; + memcpy(buf, state->next, n); + state->next += n; + state->have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && strm->avail_in == 0) + break; + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || len < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_make(state) == -1) + return -1; + continue; /* no progress yet -- go back to memcpy() above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, buf, len, &n) == -1) + return -1; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + strm->avail_out = len; + strm->next_out = buf; + if (gz_decomp(state) == -1) + return -1; + n = state->have; + state->have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->pos += n; + } while (len); + + /* return number of bytes read into user buffer (will fit in int) */ + return (int)got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->have) { + state->have--; + state->pos++; + return *(state->next)++; + } + + /* nothing there -- try gzread() */ + ret = gzread(file, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->have == 0) { + state->have = 1; + state->next = state->out + (state->size << 1) - 1; + state->next[0] = c; + state->pos--; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->have == (state->size << 1)) { + gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->next == state->out) { + unsigned char *src = state->out + state->have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->next = dest; + } + state->have++; + state->next--; + state->next[0] = c; + state->pos--; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || state->err != Z_OK) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->have == 0) { + if (gz_make(state) == -1) + return NULL; /* error */ + if (state->have == 0) { /* end of file */ + if (buf == str) /* got bupkus */ + return NULL; + break; /* got something -- return it */ + } + } + + /* look for end-of-line in current output buffer */ + n = state->have > left ? left : state->have; + eol = memchr(state->next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->next, n); + state->have -= n; + state->next += n; + state->pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* found end-of-line or out of space -- terminate string and return it */ + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return 0; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->how == LOOK && state->have == 0) + (void)gz_head(state); + + /* return 1 if reading direct, 0 if decompressing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzwrite.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzwrite.c new file mode 100644 index 000000000..13c5558e0 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/gzwrite.c @@ -0,0 +1,531 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004, 2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on failure or 0 on success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input and output buffers */ + state->in = malloc(state->want); + state->out = malloc(state->want); + if (state->in == NULL || state->out == NULL) { + if (state->out != NULL) + free(state->out); + if (state->in != NULL) + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + 15 + 16, 8, state->strategy); + if (ret != Z_OK) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer */ + strm->avail_out = state->size; + strm->next_out = state->out; + state->next = strm->next_out; + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file, otherwise 0. + flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, + then the deflate() state is reset to start a new gzip stream. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, got; + unsigned have; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + have = (unsigned)(strm->next_out - state->next); + if (have && ((got = write(state->fd, state->next, have)) < 0 || + (unsigned)got != have)) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + } + state->next = strm->next_out; + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on error, 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + unsigned put = len; + unsigned n; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids the flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + return 0; + } + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + if (strm->avail_in == 0) + strm->next_in = state->in; + n = state->size - strm->avail_in; + if (n > len) + n = len; + memcpy(strm->next_in + strm->avail_in, buf, n); + strm->avail_in += n; + state->pos += n; + buf = (char *)buf + n; + len -= n; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + strm->avail_in = len; + strm->next_in = (voidp)buf; + state->pos += len; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } + + /* input was all buffered or compressed (put will fit in int) */ + return (int)put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (strm->avail_in < state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + strm->next_in[strm->avail_in++] = c; + state->pos++; + return c; + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = c; + if (gzwrite(file, buf, 1) != 1) + return -1; + return c; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + unsigned len; + + /* write string */ + len = (unsigned)strlen(str); + ret = gzwrite(file, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#ifdef STDC +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +{ + int size, len; + gz_statep state; + z_streamp strm; + va_list va; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; + va_start(va, format); +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(state->in, format, va); + va_end(va); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = vsprintf((char *)state->in, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(state->in, size, format, va); + va_end(va); + len = strlen(state->in); +# else + len = vsnprintf((char *)(state->in), size, format, va); + va_end(va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#else /* !STDC */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + int size, len; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* do the printf() into the input buffer, put length in len */ + size = (int)(state->size); + state->in[size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (state->in[len] == 0) break; +# else + len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(state->in); +# else + len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + return 0; + + /* update buffer and position, defer compression until needed */ + strm->avail_in = (unsigned)len; + strm->next_in = state->in; + state->pos += len; + return len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* compress remaining data with requested flush */ + gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = 0; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + ret += gz_zero(state, state->skip); + } + + /* flush, free memory, and close file */ + ret += gz_comp(state, Z_FINISH); + (void)deflateEnd(&(state->strm)); + free(state->out); + free(state->in); + gz_error(state, Z_OK, NULL); + free(state->path); + ret += close(state->fd); + free(state); + return ret ? Z_ERRNO : Z_OK; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.c new file mode 100644 index 000000000..2f1d60b43 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.h new file mode 100644 index 000000000..e5c1aa4ca --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffixed.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffixed.h new file mode 100644 index 000000000..75ed4b597 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.c new file mode 100644 index 000000000..a8431abea --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.h new file mode 100644 index 000000000..95f4986d4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.c new file mode 100644 index 000000000..11e9c52ac --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.h new file mode 100644 index 000000000..baa53a0b1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.c new file mode 100644 index 000000000..56e9bb1c1 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.h new file mode 100644 index 000000000..d35639d82 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/uncompr.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/uncompr.c new file mode 100644 index 000000000..ad98be3a5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zconf.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zconf.h new file mode 100644 index 000000000..af6a4f0fe --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zconf.h @@ -0,0 +1,168 @@ +/* zconf.h (configuration of the zlib compression library) */ + +/* Modified by Andrew Makhorin , April 2011 */ + +/* Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* (file adler32.c) */ +#define adler32 _glp_zlib_adler32 +#define adler32_combine _glp_zlib_adler32_combine +#define adler32_combine64 _glp_zlib_adler32_combine64 + +/* (file compress.c) */ +#define compress2 _glp_zlib_compress2 +#define compress _glp_zlib_compress +#define compressBound _glp_zlib_compressBound + +/* (file crc32.c) */ +#define get_crc_table _glp_zlib_get_crc_table +#define crc32 _glp_zlib_crc32 +#define crc32_combine _glp_zlib_crc32_combine +#define crc32_combine64 _glp_zlib_crc32_combine64 + +/* (file deflate.c) */ +#define deflateInit_ _glp_zlib_deflateInit_ +#define deflateInit2_ _glp_zlib_deflateInit2_ +#define deflateSetDictionary _glp_zlib_deflateSetDictionary +#define deflateReset _glp_zlib_deflateReset +#define deflateSetHeader _glp_zlib_deflateSetHeader +#define deflatePrime _glp_zlib_deflatePrime +#define deflateParams _glp_zlib_deflateParams +#define deflateTune _glp_zlib_deflateTune +#define deflateBound _glp_zlib_deflateBound +#define deflate _glp_zlib_deflate +#define deflateEnd _glp_zlib_deflateEnd +#define deflateCopy _glp_zlib_deflateCopy +#define deflate_copyright _glp_zlib_deflate_copyright + +/* (file gzclose.c) */ +#define gzclose _glp_zlib_gzclose + +/* (file gzlib.c) */ +#define gzopen _glp_zlib_gzopen +#define gzopen64 _glp_zlib_gzopen64 +#define gzdopen _glp_zlib_gzdopen +#define gzbuffer _glp_zlib_gzbuffer +#define gzrewind _glp_zlib_gzrewind +#define gzseek64 _glp_zlib_gzseek64 +#define gzseek _glp_zlib_gzseek +#define gztell64 _glp_zlib_gztell64 +#define gztell _glp_zlib_gztell +#define gzoffset64 _glp_zlib_gzoffset64 +#define gzoffset _glp_zlib_gzoffset +#define gzeof _glp_zlib_gzeof +#define gzerror _glp_zlib_gzerror +#define gzclearerr _glp_zlib_gzclearerr +#define gz_error _glp_zlib_gz_error + +/* (file gzread.c) */ +#define gzread _glp_zlib_gzread +#define gzgetc _glp_zlib_gzgetc +#define gzungetc _glp_zlib_gzungetc +#define gzgets _glp_zlib_gzgets +#define gzdirect _glp_zlib_gzdirect +#define gzclose_r _glp_zlib_gzclose_r + +/* (file gzwrite.c) */ +#define gzwrite _glp_zlib_gzwrite +#define gzputc _glp_zlib_gzputc +#define gzputs _glp_zlib_gzputs +#define gzprintf _glp_zlib_gzprintf +#define gzflush _glp_zlib_gzflush +#define gzsetparams _glp_zlib_gzsetparams +#define gzclose_w _glp_zlib_gzclose_w + +/* (file infback.c) */ +#define inflateBackInit_ _glp_zlib_inflateBackInit_ +#define inflateBack _glp_zlib_inflateBack +#define inflateBackEnd _glp_zlib_inflateBackEnd + +/* (file inffast.c) */ +#define inflate_fast _glp_zlib_inflate_fast + +/* (file inflate.c) */ +#define inflateReset _glp_zlib_inflateReset +#define inflateReset2 _glp_zlib_inflateReset2 +#define inflateInit2_ _glp_zlib_inflateInit2_ +#define inflateInit_ _glp_zlib_inflateInit_ +#define inflatePrime _glp_zlib_inflatePrime +#define inflate _glp_zlib_inflate +#define inflateEnd _glp_zlib_inflateEnd +#define inflateSetDictionary _glp_zlib_inflateSetDictionary +#define inflateGetHeader _glp_zlib_inflateGetHeader +#define inflateSync _glp_zlib_inflateSync +#define inflateSyncPoint _glp_zlib_inflateSyncPoint +#define inflateCopy _glp_zlib_inflateCopy +#define inflateUndermine _glp_zlib_inflateUndermine +#define inflateMark _glp_zlib_inflateMark + +/* (file inftrees.c) */ +#define inflate_table _glp_zlib_inflate_table +#define inflate_copyright _glp_zlib_inflate_copyright + +/* (file trees.c) */ +#define _tr_init _glp_zlib_tr_init +#define _tr_stored_block _glp_zlib_tr_stored_block +#define _tr_align _glp_zlib_tr_align +#define _tr_flush_block _glp_zlib_tr_flush_block +#define _tr_tally _glp_zlib_tr_tally +#define _dist_code _glp_zlib_dist_code +#define _length_code _glp_zlib_length_code + +/* (file uncompr.c) */ +#define uncompress _glp_zlib_uncompress + +/* (file zutil.c) */ +#define zlibVersion _glp_zlib_zlibVersion +#define zlibCompileFlags _glp_zlib_zlibCompileFlags +#define zError _glp_zlib_zError +#define zcalloc _glp_zlib_zcalloc +#define zcfree _glp_zlib_zcfree +#define z_errmsg _glp_zlib_z_errmsg + +#define STDC 1 + +#define MAX_MEM_LEVEL 9 + +#define MAX_WBITS 15 + +#define OF(args) args + +#define ZEXTERN extern +#define ZEXPORT +#define ZEXPORTVA + +#define FAR + +typedef unsigned char Byte; +typedef unsigned int uInt; +typedef unsigned long uLong; + +typedef Byte Bytef; +typedef char charf; +typedef int intf; +typedef uInt uIntf; +typedef uLong uLongf; + +typedef void const *voidpc; +typedef void *voidpf; +typedef void *voidp; + +#define z_off_t long + +#define z_off64_t z_off_t + +#define NO_vsnprintf 1 + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.c new file mode 100644 index 000000000..a55b258a7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.c @@ -0,0 +1,92 @@ +/* zio.c (simulation of non-standard low-level i/o functions) */ + +/* Written by Andrew Makhorin , April 2011 + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* (reserved for copyright notice) */ + +#include +#include +#include "zio.h" + +static FILE *file[FOPEN_MAX]; +static int initialized = 0; + +static void initialize(void) +{ int fd; + assert(!initialized); + file[0] = stdin; + file[1] = stdout; + file[2] = stderr; + for (fd = 3; fd < FOPEN_MAX; fd++) + file[fd] = NULL; + initialized = 1; + return; +} + +int open(const char *path, int oflag, ...) +{ FILE *fp; + int fd; + if (!initialized) initialize(); + /* see file gzlib.c, function gz_open */ + if (oflag == O_RDONLY) + fp = fopen(path, "rb"); + else if (oflag == (O_WRONLY | O_CREAT | O_TRUNC)) + fp = fopen(path, "wb"); + else if (oflag == (O_WRONLY | O_CREAT | O_APPEND)) + fp = fopen(path, "ab"); + else + assert(oflag != oflag); + if (fp == NULL) + return -1; + for (fd = 0; fd < FOPEN_MAX; fd++) + if (file[fd] == NULL) break; + assert(fd < FOPEN_MAX); + file[fd] = fp; + return fd; +} + +long read(int fd, void *buf, unsigned long nbyte) +{ unsigned long count; + if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + count = fread(buf, 1, nbyte, file[fd]); + if (ferror(file[fd])) + return -1; + return count; +} + +long write(int fd, const void *buf, unsigned long nbyte) +{ unsigned long count; + if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + count = fwrite(buf, 1, nbyte, file[fd]); + if (count != nbyte) + return -1; + if (fflush(file[fd]) != 0) + return -1; + return count; +} + +long lseek(int fd, long offset, int whence) +{ if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + if (fseek(file[fd], offset, whence) != 0) + return -1; + return ftell(file[fd]); +} + +int close(int fd) +{ if (!initialized) initialize(); + assert(0 <= fd && fd < FOPEN_MAX); + assert(file[fd] != NULL); + fclose(file[fd]); + file[fd] = NULL; + return 0; +} + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.h new file mode 100644 index 000000000..1626c4ae4 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zio.h @@ -0,0 +1,37 @@ +/* zio.h (simulation of non-standard low-level i/o functions) */ + +/* Written by Andrew Makhorin , April 2011 + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZIO_H +#define ZIO_H + +#define O_RDONLY 0x00 +#define O_WRONLY 0x01 +#define O_CREAT 0x10 +#define O_TRUNC 0x20 +#define O_APPEND 0x30 + +#define open _glp_zlib_open +int open(const char *path, int oflag, ...); + +#define read _glp_zlib_read +long read(int fd, void *buf, unsigned long nbyte); + +#define write _glp_zlib_write +long write(int fd, const void *buf, unsigned long nbyte); + +#define lseek _glp_zlib_lseek +long lseek(int fd, long offset, int whence); + +#define close _glp_zlib_close +int close(int fd); + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zlib.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zlib.h new file mode 100644 index 000000000..bfbba83e8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.c b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.c new file mode 100644 index 000000000..898ed345b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.h b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.h new file mode 100644 index 000000000..737bd38f5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/src/zlib/zutil.h @@ -0,0 +1,93 @@ +/* zutil.h (internal interface of the zlib compression library) */ + +/* Modified by Andrew Makhorin , April 2011 */ + +/* Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in + * zlib.h */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL + +#include "zlib.h" + +#include +#include +#include + +#define local static + +typedef unsigned char uch; +typedef uch uchf; +typedef unsigned short ush; +typedef ush ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm, err) \ + return (strm->msg = (char *)ERR_MSG(err), (err)) + +#define DEF_WBITS MAX_WBITS + +#if MAX_MEM_LEVEL >= 8 +#define DEF_MEM_LEVEL 8 +#else +#define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 + +#define MIN_MATCH 3 +#define MAX_MATCH 258 + +#define PRESET_DICT 0x20 + +#define OS_CODE 0x03 /* assume Unix */ + +#define HAVE_MEMCPY 1 +#define zmemcpy memcpy +#define zmemzero(dest, len) memset(dest, 0, len) + +#ifdef DEBUG +#include +extern int ZLIB_INTERNAL z_verbose; +extern void ZLIB_INTERNAL z_error OF((char *m)); +#define Assert(cond, msg) { if(!(cond)) z_error(msg); } +#define Trace(x) { if (z_verbose >= 0) fprintf x; } +#define Tracev(x) { if (z_verbose > 0) fprintf x; } +#define Tracevv(x) {if (z_verbose > 1) fprintf x; } +#define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x; } +#define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x; } +#else +#define Assert(cond, msg) +#define Trace(x) +#define Tracev(x) +#define Tracevv(x) +#define Tracec(c, x) +#define Tracecv(c, x) +#endif + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) \ + (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) { if (p) ZFREE(s, p); } + +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10.bat new file mode 100755 index 000000000..b0f693446 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_DLL.bat new file mode 100755 index 000000000..e66f5cb39 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_stdcall_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_stdcall_DLL.bat new file mode 100755 index 000000000..3e3d51087 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC10_stdcall_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_stdcall_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_stdcall_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14.bat new file mode 100755 index 000000000..02bb9add3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14_DLL.bat new file mode 100755 index 000000000..baf4b112b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC14_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9.bat new file mode 100755 index 000000000..9c5e8f83d --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars32.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9_DLL.bat new file mode 100755 index 000000000..f334c04af --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Build_GLPK_with_VC9_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars32.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC new file mode 100644 index 000000000..9c962ba36 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC @@ -0,0 +1,251 @@ +## Build GLPK with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\api \ +/I..\src\bflib \ +/I..\src\colamd \ +/I..\src\draft \ +/I..\src\env \ +/I..\src\intopt \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\mpl \ +/I..\src\npp \ +/I..\src\proxy \ +/I..\src\simplex \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi + +OBJSET = \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\api\advbas.obj \ +..\src\api\asnhall.obj \ +..\src\api\asnlp.obj \ +..\src\api\asnokalg.obj \ +..\src\api\ckasn.obj \ +..\src\api\ckcnf.obj \ +..\src\api\cplex.obj \ +..\src\api\cpp.obj \ +..\src\api\cpxbas.obj \ +..\src\api\graph.obj \ +..\src\api\gridgen.obj \ +..\src\api\intfeas1.obj \ +..\src\api\maxffalg.obj \ +..\src\api\maxflp.obj \ +..\src\api\mcflp.obj \ +..\src\api\mcfokalg.obj \ +..\src\api\mcfrelax.obj \ +..\src\api\minisat1.obj \ +..\src\api\mpl.obj \ +..\src\api\mps.obj \ +..\src\api\netgen.obj \ +..\src\api\npp.obj \ +..\src\api\pript.obj \ +..\src\api\prmip.obj \ +..\src\api\prob1.obj \ +..\src\api\prob2.obj \ +..\src\api\prob3.obj \ +..\src\api\prob4.obj \ +..\src\api\prob5.obj \ +..\src\api\prrngs.obj \ +..\src\api\prsol.obj \ +..\src\api\rdasn.obj \ +..\src\api\rdcc.obj \ +..\src\api\rdcnf.obj \ +..\src\api\rdipt.obj \ +..\src\api\rdmaxf.obj \ +..\src\api\rdmcf.obj \ +..\src\api\rdmip.obj \ +..\src\api\rdprob.obj \ +..\src\api\rdsol.obj \ +..\src\api\rmfgen.obj \ +..\src\api\strong.obj \ +..\src\api\topsort.obj \ +..\src\api\weak.obj \ +..\src\api\wcliqex.obj \ +..\src\api\wrasn.obj \ +..\src\api\wrcc.obj \ +..\src\api\wrcnf.obj \ +..\src\api\wript.obj \ +..\src\api\wrmaxf.obj \ +..\src\api\wrmcf.obj \ +..\src\api\wrmip.obj \ +..\src\api\wrprob.obj \ +..\src\api\wrsol.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\colamd\colamd.obj \ +..\src\draft\bfd.obj \ +..\src\draft\bfx.obj \ +..\src\draft\glpapi06.obj \ +..\src\draft\glpapi07.obj \ +..\src\draft\glpapi08.obj \ +..\src\draft\glpapi09.obj \ +..\src\draft\glpapi10.obj \ +..\src\draft\glpapi12.obj \ +..\src\draft\glpapi13.obj \ +..\src\draft\glphbm.obj \ +..\src\draft\glpios01.obj \ +..\src\draft\glpios02.obj \ +..\src\draft\glpios03.obj \ +..\src\draft\glpios07.obj \ +..\src\draft\glpios09.obj \ +..\src\draft\glpios11.obj \ +..\src\draft\glpios12.obj \ +..\src\draft\glpipm.obj \ +..\src\draft\glpmat.obj \ +..\src\draft\glprgr.obj \ +..\src\draft\glpscl.obj \ +..\src\draft\glpspm.obj \ +..\src\draft\glpssx01.obj \ +..\src\draft\glpssx02.obj \ +..\src\draft\lux.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdc.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\intopt\cfg.obj \ +..\src\intopt\cfg1.obj \ +..\src\intopt\cfg2.obj \ +..\src\intopt\clqcut.obj \ +..\src\intopt\covgen.obj \ +..\src\intopt\fpump.obj \ +..\src\intopt\gmicut.obj \ +..\src\intopt\gmigen.obj \ +..\src\intopt\mirgen.obj \ +..\src\intopt\spv.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\avl.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dimacs.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\fvs.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\ks.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\mt1.obj \ +..\src\misc\mygmp.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\mpl\mpl1.obj \ +..\src\mpl\mpl2.obj \ +..\src\mpl\mpl3.obj \ +..\src\mpl\mpl4.obj \ +..\src\mpl\mpl5.obj \ +..\src\mpl\mpl6.obj \ +..\src\mpl\mplsql.obj \ +..\src\npp\npp1.obj \ +..\src\npp\npp2.obj \ +..\src\npp\npp3.obj \ +..\src\npp\npp4.obj \ +..\src\npp\npp5.obj \ +..\src\npp\npp6.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk.lib glpsol.exe + +glpk.lib: $(OBJSET) + lib.exe /out:glpk.lib \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\api\*.obj \ + ..\src\bflib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\draft\*.obj \ + ..\src\env\*.obj \ + ..\src\intopt\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\mpl\*.obj \ + ..\src\npp\*.obj \ + ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ + ..\src\zlib\*.obj + +glpsol.exe: ..\examples\glpsol.obj glpk.lib + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_DLL b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_DLL new file mode 100644 index 000000000..55b212116 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_DLL @@ -0,0 +1,252 @@ +## Build GLPK DLL with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\api \ +/I..\src\bflib \ +/I..\src\colamd \ +/I..\src\draft \ +/I..\src\env \ +/I..\src\intopt \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\mpl \ +/I..\src\npp \ +/I..\src\proxy \ +/I..\src\simplex \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi + +OBJSET = \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\api\advbas.obj \ +..\src\api\asnhall.obj \ +..\src\api\asnlp.obj \ +..\src\api\asnokalg.obj \ +..\src\api\ckasn.obj \ +..\src\api\ckcnf.obj \ +..\src\api\cplex.obj \ +..\src\api\cpp.obj \ +..\src\api\cpxbas.obj \ +..\src\api\graph.obj \ +..\src\api\gridgen.obj \ +..\src\api\intfeas1.obj \ +..\src\api\maxffalg.obj \ +..\src\api\maxflp.obj \ +..\src\api\mcflp.obj \ +..\src\api\mcfokalg.obj \ +..\src\api\mcfrelax.obj \ +..\src\api\minisat1.obj \ +..\src\api\mpl.obj \ +..\src\api\mps.obj \ +..\src\api\netgen.obj \ +..\src\api\npp.obj \ +..\src\api\pript.obj \ +..\src\api\prmip.obj \ +..\src\api\prob1.obj \ +..\src\api\prob2.obj \ +..\src\api\prob3.obj \ +..\src\api\prob4.obj \ +..\src\api\prob5.obj \ +..\src\api\prrngs.obj \ +..\src\api\prsol.obj \ +..\src\api\rdasn.obj \ +..\src\api\rdcc.obj \ +..\src\api\rdcnf.obj \ +..\src\api\rdipt.obj \ +..\src\api\rdmaxf.obj \ +..\src\api\rdmcf.obj \ +..\src\api\rdmip.obj \ +..\src\api\rdprob.obj \ +..\src\api\rdsol.obj \ +..\src\api\rmfgen.obj \ +..\src\api\strong.obj \ +..\src\api\topsort.obj \ +..\src\api\weak.obj \ +..\src\api\wcliqex.obj \ +..\src\api\wrasn.obj \ +..\src\api\wrcc.obj \ +..\src\api\wrcnf.obj \ +..\src\api\wript.obj \ +..\src\api\wrmaxf.obj \ +..\src\api\wrmcf.obj \ +..\src\api\wrmip.obj \ +..\src\api\wrprob.obj \ +..\src\api\wrsol.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\colamd\colamd.obj \ +..\src\draft\bfd.obj \ +..\src\draft\bfx.obj \ +..\src\draft\glpapi06.obj \ +..\src\draft\glpapi07.obj \ +..\src\draft\glpapi08.obj \ +..\src\draft\glpapi09.obj \ +..\src\draft\glpapi10.obj \ +..\src\draft\glpapi12.obj \ +..\src\draft\glpapi13.obj \ +..\src\draft\glphbm.obj \ +..\src\draft\glpios01.obj \ +..\src\draft\glpios02.obj \ +..\src\draft\glpios03.obj \ +..\src\draft\glpios07.obj \ +..\src\draft\glpios09.obj \ +..\src\draft\glpios11.obj \ +..\src\draft\glpios12.obj \ +..\src\draft\glpipm.obj \ +..\src\draft\glpmat.obj \ +..\src\draft\glprgr.obj \ +..\src\draft\glpscl.obj \ +..\src\draft\glpspm.obj \ +..\src\draft\glpssx01.obj \ +..\src\draft\glpssx02.obj \ +..\src\draft\lux.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdc.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\intopt\cfg.obj \ +..\src\intopt\cfg1.obj \ +..\src\intopt\cfg2.obj \ +..\src\intopt\clqcut.obj \ +..\src\intopt\covgen.obj \ +..\src\intopt\fpump.obj \ +..\src\intopt\gmicut.obj \ +..\src\intopt\gmigen.obj \ +..\src\intopt\mirgen.obj \ +..\src\intopt\spv.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\avl.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dimacs.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\fvs.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\ks.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\mt1.obj \ +..\src\misc\mygmp.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\mpl\mpl1.obj \ +..\src\mpl\mpl2.obj \ +..\src\mpl\mpl3.obj \ +..\src\mpl\mpl4.obj \ +..\src\mpl\mpl5.obj \ +..\src\mpl\mpl6.obj \ +..\src\mpl\mplsql.obj \ +..\src\npp\npp1.obj \ +..\src\npp\npp2.obj \ +..\src\npp\npp3.obj \ +..\src\npp\npp4.obj \ +..\src\npp\npp5.obj \ +..\src\npp\npp6.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk_4_65.dll glpsol.exe + +glpk_4_65.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_65.dll \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\api\*.obj \ + ..\src\bflib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\draft\*.obj \ + ..\src\env\*.obj \ + ..\src\intopt\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\mpl\*.obj \ + ..\src\npp\*.obj \ + ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ + ..\src\zlib\*.obj \ + glpk_4_65.def + +glpsol.exe: ..\examples\glpsol.obj glpk_4_65.dll + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk_4_65.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_stdcall_DLL b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_stdcall_DLL new file mode 100644 index 000000000..b5cd14203 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/Makefile_VC_stdcall_DLL @@ -0,0 +1,253 @@ +## Build GLPK DLL with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\api \ +/I..\src\bflib \ +/I..\src\colamd \ +/I..\src\draft \ +/I..\src\env \ +/I..\src\intopt \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\mpl \ +/I..\src\npp \ +/I..\src\proxy \ +/I..\src\simplex \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi \ +/Gz + +OBJSET = \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\api\advbas.obj \ +..\src\api\asnhall.obj \ +..\src\api\asnlp.obj \ +..\src\api\asnokalg.obj \ +..\src\api\ckasn.obj \ +..\src\api\ckcnf.obj \ +..\src\api\cplex.obj \ +..\src\api\cpp.obj \ +..\src\api\cpxbas.obj \ +..\src\api\graph.obj \ +..\src\api\gridgen.obj \ +..\src\api\intfeas1.obj \ +..\src\api\maxffalg.obj \ +..\src\api\maxflp.obj \ +..\src\api\mcflp.obj \ +..\src\api\mcfokalg.obj \ +..\src\api\mcfrelax.obj \ +..\src\api\minisat1.obj \ +..\src\api\mpl.obj \ +..\src\api\mps.obj \ +..\src\api\netgen.obj \ +..\src\api\npp.obj \ +..\src\api\pript.obj \ +..\src\api\prmip.obj \ +..\src\api\prob1.obj \ +..\src\api\prob2.obj \ +..\src\api\prob3.obj \ +..\src\api\prob4.obj \ +..\src\api\prob5.obj \ +..\src\api\prrngs.obj \ +..\src\api\prsol.obj \ +..\src\api\rdasn.obj \ +..\src\api\rdcc.obj \ +..\src\api\rdcnf.obj \ +..\src\api\rdipt.obj \ +..\src\api\rdmaxf.obj \ +..\src\api\rdmcf.obj \ +..\src\api\rdmip.obj \ +..\src\api\rdprob.obj \ +..\src\api\rdsol.obj \ +..\src\api\rmfgen.obj \ +..\src\api\strong.obj \ +..\src\api\topsort.obj \ +..\src\api\weak.obj \ +..\src\api\wcliqex.obj \ +..\src\api\wrasn.obj \ +..\src\api\wrcc.obj \ +..\src\api\wrcnf.obj \ +..\src\api\wript.obj \ +..\src\api\wrmaxf.obj \ +..\src\api\wrmcf.obj \ +..\src\api\wrmip.obj \ +..\src\api\wrprob.obj \ +..\src\api\wrsol.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\colamd\colamd.obj \ +..\src\draft\bfd.obj \ +..\src\draft\bfx.obj \ +..\src\draft\glpapi06.obj \ +..\src\draft\glpapi07.obj \ +..\src\draft\glpapi08.obj \ +..\src\draft\glpapi09.obj \ +..\src\draft\glpapi10.obj \ +..\src\draft\glpapi12.obj \ +..\src\draft\glpapi13.obj \ +..\src\draft\glphbm.obj \ +..\src\draft\glpios01.obj \ +..\src\draft\glpios02.obj \ +..\src\draft\glpios03.obj \ +..\src\draft\glpios07.obj \ +..\src\draft\glpios09.obj \ +..\src\draft\glpios11.obj \ +..\src\draft\glpios12.obj \ +..\src\draft\glpipm.obj \ +..\src\draft\glpmat.obj \ +..\src\draft\glprgr.obj \ +..\src\draft\glpscl.obj \ +..\src\draft\glpspm.obj \ +..\src\draft\glpssx01.obj \ +..\src\draft\glpssx02.obj \ +..\src\draft\lux.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdc.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\intopt\cfg.obj \ +..\src\intopt\cfg1.obj \ +..\src\intopt\cfg2.obj \ +..\src\intopt\clqcut.obj \ +..\src\intopt\covgen.obj \ +..\src\intopt\fpump.obj \ +..\src\intopt\gmicut.obj \ +..\src\intopt\gmigen.obj \ +..\src\intopt\mirgen.obj \ +..\src\intopt\spv.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\avl.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dimacs.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\fvs.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\ks.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\mt1.obj \ +..\src\misc\mygmp.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\mpl\mpl1.obj \ +..\src\mpl\mpl2.obj \ +..\src\mpl\mpl3.obj \ +..\src\mpl\mpl4.obj \ +..\src\mpl\mpl5.obj \ +..\src\mpl\mpl6.obj \ +..\src\mpl\mplsql.obj \ +..\src\npp\npp1.obj \ +..\src\npp\npp2.obj \ +..\src\npp\npp3.obj \ +..\src\npp\npp4.obj \ +..\src\npp\npp5.obj \ +..\src\npp\npp6.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk_4_65_stdcall.dll glpsol.exe + +glpk_4_65_stdcall.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_65_stdcall.dll \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\api\*.obj \ + ..\src\bflib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\draft\*.obj \ + ..\src\env\*.obj \ + ..\src\intopt\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\mpl\*.obj \ + ..\src\npp\*.obj \ + ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ + ..\src\zlib\*.obj \ + glpk_4_65_stdcall.def + +glpsol.exe: ..\examples\glpsol.obj glpk_4_65_stdcall.dll + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk_4_65_stdcall.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/config_VC b/WebAPP/SOLVERs/GLPK/glpk/w32/config_VC new file mode 100644 index 000000000..c8f7c48c5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/config_VC @@ -0,0 +1,16 @@ +/* GLPK configuration file (Microsoft Visual Studio Express) */ + +#define __WOE__ 1 + +#define TLS __declspec(thread) +/* thread local storage-class specifier for reentrancy */ + +#define ODBC_DLNAME "odbc32.dll" +/* ODBC shared library name if this feature is enabled */ + +#if 0 +#define MYSQL_DLNAME "libmysql.dll" +/* MySQL shared library name if this feature is enabled */ +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65.def b/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65.def new file mode 100644 index 000000000..9efaf9b8a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65.def @@ -0,0 +1,234 @@ +LIBRARY glpk_4_65 +VERSION 4.65 +DESCRIPTION "GNU Linear Programming Kit" +EXPORTS +glp_create_prob +glp_set_prob_name +glp_set_obj_name +glp_set_obj_dir +glp_add_rows +glp_add_cols +glp_set_row_name +glp_set_col_name +glp_set_row_bnds +glp_set_col_bnds +glp_set_obj_coef +glp_set_mat_row +glp_set_mat_col +glp_load_matrix +glp_check_dup +glp_sort_matrix +glp_del_rows +glp_del_cols +glp_copy_prob +glp_erase_prob +glp_delete_prob +glp_get_prob_name +glp_get_obj_name +glp_get_obj_dir +glp_get_num_rows +glp_get_num_cols +glp_get_row_name +glp_get_col_name +glp_get_row_type +glp_get_row_lb +glp_get_row_ub +glp_get_col_type +glp_get_col_lb +glp_get_col_ub +glp_get_obj_coef +glp_get_num_nz +glp_get_mat_row +glp_get_mat_col +glp_create_index +glp_find_row +glp_find_col +glp_delete_index +glp_set_rii +glp_set_sjj +glp_get_rii +glp_get_sjj +glp_scale_prob +glp_unscale_prob +glp_set_row_stat +glp_set_col_stat +glp_std_basis +glp_adv_basis +glp_cpx_basis +glp_simplex +glp_exact +glp_init_smcp +glp_get_status +glp_get_prim_stat +glp_get_dual_stat +glp_get_obj_val +glp_get_row_stat +glp_get_row_prim +glp_get_row_dual +glp_get_col_stat +glp_get_col_prim +glp_get_col_dual +glp_get_unbnd_ray +glp_get_it_cnt +glp_set_it_cnt +glp_interior +glp_init_iptcp +glp_ipt_status +glp_ipt_obj_val +glp_ipt_row_prim +glp_ipt_row_dual +glp_ipt_col_prim +glp_ipt_col_dual +glp_set_col_kind +glp_get_col_kind +glp_get_num_int +glp_get_num_bin +glp_intopt +glp_init_iocp +glp_mip_status +glp_mip_obj_val +glp_mip_row_val +glp_mip_col_val +glp_check_kkt +glp_print_sol +glp_read_sol +glp_write_sol +glp_print_ranges +glp_print_ipt +glp_read_ipt +glp_write_ipt +glp_print_mip +glp_read_mip +glp_write_mip +glp_bf_exists +glp_factorize +glp_bf_updated +glp_get_bfcp +glp_set_bfcp +glp_get_bhead +glp_get_row_bind +glp_get_col_bind +glp_ftran +glp_btran +glp_warm_up +glp_eval_tab_row +glp_eval_tab_col +glp_transform_row +glp_transform_col +glp_prim_rtest +glp_dual_rtest +glp_analyze_bound +glp_analyze_coef +glp_npp_alloc_wksp +glp_npp_load_prob +glp_npp_preprocess1 +glp_npp_build_prob +glp_npp_postprocess +glp_npp_obtain_sol +glp_npp_free_wksp +glp_ios_reason +glp_ios_get_prob +glp_ios_tree_size +glp_ios_curr_node +glp_ios_next_node +glp_ios_prev_node +glp_ios_up_node +glp_ios_node_level +glp_ios_node_bound +glp_ios_best_node +glp_ios_mip_gap +glp_ios_node_data +glp_ios_row_attr +glp_ios_pool_size +glp_ios_add_row +glp_ios_del_row +glp_ios_clear_pool +glp_ios_can_branch +glp_ios_branch_upon +glp_ios_select_node +glp_ios_heur_sol +glp_ios_terminate +glp_init_mpscp +glp_read_mps +glp_write_mps +glp_init_cpxcp +glp_read_lp +glp_write_lp +glp_read_prob +glp_write_prob +glp_mpl_alloc_wksp +glp_mpl_init_rand +glp_mpl_read_model +glp_mpl_read_data +glp_mpl_generate +glp_mpl_build_prob +glp_mpl_postsolve +glp_mpl_free_wksp +glp_read_cnfsat +glp_check_cnfsat +glp_write_cnfsat +glp_minisat1 +glp_intfeas1 +glp_init_env +glp_version +glp_config +glp_free_env +glp_puts +glp_printf +glp_vprintf +glp_term_out +glp_term_hook +glp_open_tee +glp_close_tee +glp_error_ +glp_at_error +glp_assert_ +glp_error_hook +glp_alloc +glp_realloc +glp_free +glp_mem_limit +glp_mem_usage +glp_time +glp_difftime +glp_create_graph +glp_set_graph_name +glp_add_vertices +glp_set_vertex_name +glp_add_arc +glp_del_vertices +glp_del_arc +glp_erase_graph +glp_delete_graph +glp_create_v_index +glp_find_vertex +glp_delete_v_index +glp_read_graph +glp_write_graph +glp_mincost_lp +glp_mincost_okalg +glp_mincost_relax4 +glp_maxflow_lp +glp_maxflow_ffalg +glp_check_asnprob +glp_asnprob_lp +glp_asnprob_okalg +glp_asnprob_hall +glp_cpp +glp_read_mincost +glp_write_mincost +glp_read_maxflow +glp_write_maxflow +glp_read_asnprob +glp_write_asnprob +glp_read_ccdata +glp_write_ccdata +glp_netgen +glp_netgen_prob +glp_gridgen +glp_rmfgen +glp_weak_comp +glp_strong_comp +glp_top_sort +glp_wclique_exact +;; end of file ;; diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65_stdcall.def b/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65_stdcall.def new file mode 100644 index 000000000..818e5fedb --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/glpk_4_65_stdcall.def @@ -0,0 +1,234 @@ +LIBRARY glpk_4_65_stdcall +VERSION 4.65 +DESCRIPTION "GNU Linear Programming Kit" +EXPORTS +glp_create_prob +glp_set_prob_name +glp_set_obj_name +glp_set_obj_dir +glp_add_rows +glp_add_cols +glp_set_row_name +glp_set_col_name +glp_set_row_bnds +glp_set_col_bnds +glp_set_obj_coef +glp_set_mat_row +glp_set_mat_col +glp_load_matrix +glp_check_dup +glp_sort_matrix +glp_del_rows +glp_del_cols +glp_copy_prob +glp_erase_prob +glp_delete_prob +glp_get_prob_name +glp_get_obj_name +glp_get_obj_dir +glp_get_num_rows +glp_get_num_cols +glp_get_row_name +glp_get_col_name +glp_get_row_type +glp_get_row_lb +glp_get_row_ub +glp_get_col_type +glp_get_col_lb +glp_get_col_ub +glp_get_obj_coef +glp_get_num_nz +glp_get_mat_row +glp_get_mat_col +glp_create_index +glp_find_row +glp_find_col +glp_delete_index +glp_set_rii +glp_set_sjj +glp_get_rii +glp_get_sjj +glp_scale_prob +glp_unscale_prob +glp_set_row_stat +glp_set_col_stat +glp_std_basis +glp_adv_basis +glp_cpx_basis +glp_simplex +glp_exact +glp_init_smcp +glp_get_status +glp_get_prim_stat +glp_get_dual_stat +glp_get_obj_val +glp_get_row_stat +glp_get_row_prim +glp_get_row_dual +glp_get_col_stat +glp_get_col_prim +glp_get_col_dual +glp_get_unbnd_ray +glp_get_it_cnt +glp_set_it_cnt +glp_interior +glp_init_iptcp +glp_ipt_status +glp_ipt_obj_val +glp_ipt_row_prim +glp_ipt_row_dual +glp_ipt_col_prim +glp_ipt_col_dual +glp_set_col_kind +glp_get_col_kind +glp_get_num_int +glp_get_num_bin +glp_intopt +glp_init_iocp +glp_mip_status +glp_mip_obj_val +glp_mip_row_val +glp_mip_col_val +glp_check_kkt +glp_print_sol +glp_read_sol +glp_write_sol +glp_print_ranges +glp_print_ipt +glp_read_ipt +glp_write_ipt +glp_print_mip +glp_read_mip +glp_write_mip +glp_bf_exists +glp_factorize +glp_bf_updated +glp_get_bfcp +glp_set_bfcp +glp_get_bhead +glp_get_row_bind +glp_get_col_bind +glp_ftran +glp_btran +glp_warm_up +glp_eval_tab_row +glp_eval_tab_col +glp_transform_row +glp_transform_col +glp_prim_rtest +glp_dual_rtest +glp_analyze_bound +glp_analyze_coef +glp_npp_alloc_wksp +glp_npp_load_prob +glp_npp_preprocess1 +glp_npp_build_prob +glp_npp_postprocess +glp_npp_obtain_sol +glp_npp_free_wksp +glp_ios_reason +glp_ios_get_prob +glp_ios_tree_size +glp_ios_curr_node +glp_ios_next_node +glp_ios_prev_node +glp_ios_up_node +glp_ios_node_level +glp_ios_node_bound +glp_ios_best_node +glp_ios_mip_gap +glp_ios_node_data +glp_ios_row_attr +glp_ios_pool_size +glp_ios_add_row +glp_ios_del_row +glp_ios_clear_pool +glp_ios_can_branch +glp_ios_branch_upon +glp_ios_select_node +glp_ios_heur_sol +glp_ios_terminate +glp_init_mpscp +glp_read_mps +glp_write_mps +glp_init_cpxcp +glp_read_lp +glp_write_lp +glp_read_prob +glp_write_prob +glp_mpl_alloc_wksp +glp_mpl_init_rand +glp_mpl_read_model +glp_mpl_read_data +glp_mpl_generate +glp_mpl_build_prob +glp_mpl_postsolve +glp_mpl_free_wksp +glp_read_cnfsat +glp_check_cnfsat +glp_write_cnfsat +glp_minisat1 +glp_intfeas1 +glp_init_env +glp_version +glp_config +glp_free_env +glp_puts +glp_printf +glp_vprintf +glp_term_out +glp_term_hook +glp_open_tee +glp_close_tee +glp_error_ +glp_at_error +glp_assert_ +glp_error_hook +glp_alloc +glp_realloc +glp_free +glp_mem_limit +glp_mem_usage +glp_time +glp_difftime +glp_create_graph +glp_set_graph_name +glp_add_vertices +glp_set_vertex_name +glp_add_arc +glp_del_vertices +glp_del_arc +glp_erase_graph +glp_delete_graph +glp_create_v_index +glp_find_vertex +glp_delete_v_index +glp_read_graph +glp_write_graph +glp_mincost_lp +glp_mincost_okalg +glp_mincost_relax4 +glp_maxflow_lp +glp_maxflow_ffalg +glp_check_asnprob +glp_asnprob_lp +glp_asnprob_okalg +glp_asnprob_hall +glp_cpp +glp_read_mincost +glp_write_mincost +glp_read_maxflow +glp_write_maxflow +glp_read_asnprob +glp_write_asnprob +glp_read_ccdata +glp_write_ccdata +glp_netgen +glp_netgen_prob +glp_gridgen +glp_rmfgen +glp_weak_comp +glp_strong_comp +glp_top_sort +glp_wclique_exact +;; end of file ;; diff --git a/WebAPP/SOLVERs/GLPK/glpk/w32/readme.txt b/WebAPP/SOLVERs/GLPK/glpk/w32/readme.txt new file mode 100644 index 000000000..10daeda4b --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w32/readme.txt @@ -0,0 +1,24 @@ +This directory contains batch files and other stuff which you can use +to build GLPK for 32-bit Windows with the native C/C++ compilers. + +Before running the batch file do the following: + +1. Make sure that you have installed the compiler you are going to use + to build GLPK. + +2. Look into corresponding batch file (just right-click it and choose + 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME + variable specifies correct path to the compiler directory; if not, + make necessary changes. + +To run the batch file just double-click it and wait a bit while the +Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the +MS-DOS window means that all is OK. If you do not see it, something is +wrong. + +Once GLPK has been successfully built, there must appear two files in +this directory: + +glpk.lib, which is the GLPK object library, and + +glpsol.exe, which is the stand-alone GLPK LP/MIP solver. diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10.bat new file mode 100755 index 000000000..8e8a3e1e7 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10_DLL.bat new file mode 100755 index 000000000..0bbe697b3 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC10_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2010 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14.bat new file mode 100755 index 000000000..33bdaeaa2 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14_DLL.bat new file mode 100755 index 000000000..25a6a87d8 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC14_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9.bat new file mode 100755 index 000000000..9a32ef850 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars64.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9_DLL.bat b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9_DLL.bat new file mode 100755 index 000000000..4d7c19719 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/Build_GLPK_with_VC9_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Express 2008 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" + +call %HOME%\bin\vcvars64.bat +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/config_VC b/WebAPP/SOLVERs/GLPK/glpk/w64/config_VC new file mode 100644 index 000000000..c8f7c48c5 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/config_VC @@ -0,0 +1,16 @@ +/* GLPK configuration file (Microsoft Visual Studio Express) */ + +#define __WOE__ 1 + +#define TLS __declspec(thread) +/* thread local storage-class specifier for reentrancy */ + +#define ODBC_DLNAME "odbc32.dll" +/* ODBC shared library name if this feature is enabled */ + +#if 0 +#define MYSQL_DLNAME "libmysql.dll" +/* MySQL shared library name if this feature is enabled */ +#endif + +/* eof */ diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/glpk_4_65.def b/WebAPP/SOLVERs/GLPK/glpk/w64/glpk_4_65.def new file mode 100644 index 000000000..9efaf9b8a --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/glpk_4_65.def @@ -0,0 +1,234 @@ +LIBRARY glpk_4_65 +VERSION 4.65 +DESCRIPTION "GNU Linear Programming Kit" +EXPORTS +glp_create_prob +glp_set_prob_name +glp_set_obj_name +glp_set_obj_dir +glp_add_rows +glp_add_cols +glp_set_row_name +glp_set_col_name +glp_set_row_bnds +glp_set_col_bnds +glp_set_obj_coef +glp_set_mat_row +glp_set_mat_col +glp_load_matrix +glp_check_dup +glp_sort_matrix +glp_del_rows +glp_del_cols +glp_copy_prob +glp_erase_prob +glp_delete_prob +glp_get_prob_name +glp_get_obj_name +glp_get_obj_dir +glp_get_num_rows +glp_get_num_cols +glp_get_row_name +glp_get_col_name +glp_get_row_type +glp_get_row_lb +glp_get_row_ub +glp_get_col_type +glp_get_col_lb +glp_get_col_ub +glp_get_obj_coef +glp_get_num_nz +glp_get_mat_row +glp_get_mat_col +glp_create_index +glp_find_row +glp_find_col +glp_delete_index +glp_set_rii +glp_set_sjj +glp_get_rii +glp_get_sjj +glp_scale_prob +glp_unscale_prob +glp_set_row_stat +glp_set_col_stat +glp_std_basis +glp_adv_basis +glp_cpx_basis +glp_simplex +glp_exact +glp_init_smcp +glp_get_status +glp_get_prim_stat +glp_get_dual_stat +glp_get_obj_val +glp_get_row_stat +glp_get_row_prim +glp_get_row_dual +glp_get_col_stat +glp_get_col_prim +glp_get_col_dual +glp_get_unbnd_ray +glp_get_it_cnt +glp_set_it_cnt +glp_interior +glp_init_iptcp +glp_ipt_status +glp_ipt_obj_val +glp_ipt_row_prim +glp_ipt_row_dual +glp_ipt_col_prim +glp_ipt_col_dual +glp_set_col_kind +glp_get_col_kind +glp_get_num_int +glp_get_num_bin +glp_intopt +glp_init_iocp +glp_mip_status +glp_mip_obj_val +glp_mip_row_val +glp_mip_col_val +glp_check_kkt +glp_print_sol +glp_read_sol +glp_write_sol +glp_print_ranges +glp_print_ipt +glp_read_ipt +glp_write_ipt +glp_print_mip +glp_read_mip +glp_write_mip +glp_bf_exists +glp_factorize +glp_bf_updated +glp_get_bfcp +glp_set_bfcp +glp_get_bhead +glp_get_row_bind +glp_get_col_bind +glp_ftran +glp_btran +glp_warm_up +glp_eval_tab_row +glp_eval_tab_col +glp_transform_row +glp_transform_col +glp_prim_rtest +glp_dual_rtest +glp_analyze_bound +glp_analyze_coef +glp_npp_alloc_wksp +glp_npp_load_prob +glp_npp_preprocess1 +glp_npp_build_prob +glp_npp_postprocess +glp_npp_obtain_sol +glp_npp_free_wksp +glp_ios_reason +glp_ios_get_prob +glp_ios_tree_size +glp_ios_curr_node +glp_ios_next_node +glp_ios_prev_node +glp_ios_up_node +glp_ios_node_level +glp_ios_node_bound +glp_ios_best_node +glp_ios_mip_gap +glp_ios_node_data +glp_ios_row_attr +glp_ios_pool_size +glp_ios_add_row +glp_ios_del_row +glp_ios_clear_pool +glp_ios_can_branch +glp_ios_branch_upon +glp_ios_select_node +glp_ios_heur_sol +glp_ios_terminate +glp_init_mpscp +glp_read_mps +glp_write_mps +glp_init_cpxcp +glp_read_lp +glp_write_lp +glp_read_prob +glp_write_prob +glp_mpl_alloc_wksp +glp_mpl_init_rand +glp_mpl_read_model +glp_mpl_read_data +glp_mpl_generate +glp_mpl_build_prob +glp_mpl_postsolve +glp_mpl_free_wksp +glp_read_cnfsat +glp_check_cnfsat +glp_write_cnfsat +glp_minisat1 +glp_intfeas1 +glp_init_env +glp_version +glp_config +glp_free_env +glp_puts +glp_printf +glp_vprintf +glp_term_out +glp_term_hook +glp_open_tee +glp_close_tee +glp_error_ +glp_at_error +glp_assert_ +glp_error_hook +glp_alloc +glp_realloc +glp_free +glp_mem_limit +glp_mem_usage +glp_time +glp_difftime +glp_create_graph +glp_set_graph_name +glp_add_vertices +glp_set_vertex_name +glp_add_arc +glp_del_vertices +glp_del_arc +glp_erase_graph +glp_delete_graph +glp_create_v_index +glp_find_vertex +glp_delete_v_index +glp_read_graph +glp_write_graph +glp_mincost_lp +glp_mincost_okalg +glp_mincost_relax4 +glp_maxflow_lp +glp_maxflow_ffalg +glp_check_asnprob +glp_asnprob_lp +glp_asnprob_okalg +glp_asnprob_hall +glp_cpp +glp_read_mincost +glp_write_mincost +glp_read_maxflow +glp_write_maxflow +glp_read_asnprob +glp_write_asnprob +glp_read_ccdata +glp_write_ccdata +glp_netgen +glp_netgen_prob +glp_gridgen +glp_rmfgen +glp_weak_comp +glp_strong_comp +glp_top_sort +glp_wclique_exact +;; end of file ;; diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC b/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC new file mode 100644 index 000000000..9c962ba36 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC @@ -0,0 +1,251 @@ +## Build GLPK with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\api \ +/I..\src\bflib \ +/I..\src\colamd \ +/I..\src\draft \ +/I..\src\env \ +/I..\src\intopt \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\mpl \ +/I..\src\npp \ +/I..\src\proxy \ +/I..\src\simplex \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi + +OBJSET = \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\api\advbas.obj \ +..\src\api\asnhall.obj \ +..\src\api\asnlp.obj \ +..\src\api\asnokalg.obj \ +..\src\api\ckasn.obj \ +..\src\api\ckcnf.obj \ +..\src\api\cplex.obj \ +..\src\api\cpp.obj \ +..\src\api\cpxbas.obj \ +..\src\api\graph.obj \ +..\src\api\gridgen.obj \ +..\src\api\intfeas1.obj \ +..\src\api\maxffalg.obj \ +..\src\api\maxflp.obj \ +..\src\api\mcflp.obj \ +..\src\api\mcfokalg.obj \ +..\src\api\mcfrelax.obj \ +..\src\api\minisat1.obj \ +..\src\api\mpl.obj \ +..\src\api\mps.obj \ +..\src\api\netgen.obj \ +..\src\api\npp.obj \ +..\src\api\pript.obj \ +..\src\api\prmip.obj \ +..\src\api\prob1.obj \ +..\src\api\prob2.obj \ +..\src\api\prob3.obj \ +..\src\api\prob4.obj \ +..\src\api\prob5.obj \ +..\src\api\prrngs.obj \ +..\src\api\prsol.obj \ +..\src\api\rdasn.obj \ +..\src\api\rdcc.obj \ +..\src\api\rdcnf.obj \ +..\src\api\rdipt.obj \ +..\src\api\rdmaxf.obj \ +..\src\api\rdmcf.obj \ +..\src\api\rdmip.obj \ +..\src\api\rdprob.obj \ +..\src\api\rdsol.obj \ +..\src\api\rmfgen.obj \ +..\src\api\strong.obj \ +..\src\api\topsort.obj \ +..\src\api\weak.obj \ +..\src\api\wcliqex.obj \ +..\src\api\wrasn.obj \ +..\src\api\wrcc.obj \ +..\src\api\wrcnf.obj \ +..\src\api\wript.obj \ +..\src\api\wrmaxf.obj \ +..\src\api\wrmcf.obj \ +..\src\api\wrmip.obj \ +..\src\api\wrprob.obj \ +..\src\api\wrsol.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\colamd\colamd.obj \ +..\src\draft\bfd.obj \ +..\src\draft\bfx.obj \ +..\src\draft\glpapi06.obj \ +..\src\draft\glpapi07.obj \ +..\src\draft\glpapi08.obj \ +..\src\draft\glpapi09.obj \ +..\src\draft\glpapi10.obj \ +..\src\draft\glpapi12.obj \ +..\src\draft\glpapi13.obj \ +..\src\draft\glphbm.obj \ +..\src\draft\glpios01.obj \ +..\src\draft\glpios02.obj \ +..\src\draft\glpios03.obj \ +..\src\draft\glpios07.obj \ +..\src\draft\glpios09.obj \ +..\src\draft\glpios11.obj \ +..\src\draft\glpios12.obj \ +..\src\draft\glpipm.obj \ +..\src\draft\glpmat.obj \ +..\src\draft\glprgr.obj \ +..\src\draft\glpscl.obj \ +..\src\draft\glpspm.obj \ +..\src\draft\glpssx01.obj \ +..\src\draft\glpssx02.obj \ +..\src\draft\lux.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdc.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\intopt\cfg.obj \ +..\src\intopt\cfg1.obj \ +..\src\intopt\cfg2.obj \ +..\src\intopt\clqcut.obj \ +..\src\intopt\covgen.obj \ +..\src\intopt\fpump.obj \ +..\src\intopt\gmicut.obj \ +..\src\intopt\gmigen.obj \ +..\src\intopt\mirgen.obj \ +..\src\intopt\spv.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\avl.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dimacs.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\fvs.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\ks.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\mt1.obj \ +..\src\misc\mygmp.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\mpl\mpl1.obj \ +..\src\mpl\mpl2.obj \ +..\src\mpl\mpl3.obj \ +..\src\mpl\mpl4.obj \ +..\src\mpl\mpl5.obj \ +..\src\mpl\mpl6.obj \ +..\src\mpl\mplsql.obj \ +..\src\npp\npp1.obj \ +..\src\npp\npp2.obj \ +..\src\npp\npp3.obj \ +..\src\npp\npp4.obj \ +..\src\npp\npp5.obj \ +..\src\npp\npp6.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk.lib glpsol.exe + +glpk.lib: $(OBJSET) + lib.exe /out:glpk.lib \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\api\*.obj \ + ..\src\bflib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\draft\*.obj \ + ..\src\env\*.obj \ + ..\src\intopt\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\mpl\*.obj \ + ..\src\npp\*.obj \ + ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ + ..\src\zlib\*.obj + +glpsol.exe: ..\examples\glpsol.obj glpk.lib + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC_DLL b/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC_DLL new file mode 100644 index 000000000..55b212116 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/makefile_VC_DLL @@ -0,0 +1,252 @@ +## Build GLPK DLL with Microsoft Visual Studio Express ## + +CFLAGS = \ +/I. \ +/I..\src \ +/I..\src\amd \ +/I..\src\api \ +/I..\src\bflib \ +/I..\src\colamd \ +/I..\src\draft \ +/I..\src\env \ +/I..\src\intopt \ +/I..\src\minisat \ +/I..\src\misc \ +/I..\src\mpl \ +/I..\src\npp \ +/I..\src\proxy \ +/I..\src\simplex \ +/I..\src\zlib \ +/DHAVE_CONFIG_H=1 \ +/D_CRT_SECURE_NO_WARNINGS=1 \ +/nologo \ +/W3 \ +/O2 \ +/Zi + +OBJSET = \ +..\src\amd\amd_1.obj \ +..\src\amd\amd_2.obj \ +..\src\amd\amd_aat.obj \ +..\src\amd\amd_control.obj \ +..\src\amd\amd_defaults.obj \ +..\src\amd\amd_dump.obj \ +..\src\amd\amd_info.obj \ +..\src\amd\amd_order.obj \ +..\src\amd\amd_post_tree.obj \ +..\src\amd\amd_postorder.obj \ +..\src\amd\amd_preprocess.obj \ +..\src\amd\amd_valid.obj \ +..\src\api\advbas.obj \ +..\src\api\asnhall.obj \ +..\src\api\asnlp.obj \ +..\src\api\asnokalg.obj \ +..\src\api\ckasn.obj \ +..\src\api\ckcnf.obj \ +..\src\api\cplex.obj \ +..\src\api\cpp.obj \ +..\src\api\cpxbas.obj \ +..\src\api\graph.obj \ +..\src\api\gridgen.obj \ +..\src\api\intfeas1.obj \ +..\src\api\maxffalg.obj \ +..\src\api\maxflp.obj \ +..\src\api\mcflp.obj \ +..\src\api\mcfokalg.obj \ +..\src\api\mcfrelax.obj \ +..\src\api\minisat1.obj \ +..\src\api\mpl.obj \ +..\src\api\mps.obj \ +..\src\api\netgen.obj \ +..\src\api\npp.obj \ +..\src\api\pript.obj \ +..\src\api\prmip.obj \ +..\src\api\prob1.obj \ +..\src\api\prob2.obj \ +..\src\api\prob3.obj \ +..\src\api\prob4.obj \ +..\src\api\prob5.obj \ +..\src\api\prrngs.obj \ +..\src\api\prsol.obj \ +..\src\api\rdasn.obj \ +..\src\api\rdcc.obj \ +..\src\api\rdcnf.obj \ +..\src\api\rdipt.obj \ +..\src\api\rdmaxf.obj \ +..\src\api\rdmcf.obj \ +..\src\api\rdmip.obj \ +..\src\api\rdprob.obj \ +..\src\api\rdsol.obj \ +..\src\api\rmfgen.obj \ +..\src\api\strong.obj \ +..\src\api\topsort.obj \ +..\src\api\weak.obj \ +..\src\api\wcliqex.obj \ +..\src\api\wrasn.obj \ +..\src\api\wrcc.obj \ +..\src\api\wrcnf.obj \ +..\src\api\wript.obj \ +..\src\api\wrmaxf.obj \ +..\src\api\wrmcf.obj \ +..\src\api\wrmip.obj \ +..\src\api\wrprob.obj \ +..\src\api\wrsol.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ +..\src\bflib\fhv.obj \ +..\src\bflib\fhvint.obj \ +..\src\bflib\ifu.obj \ +..\src\bflib\luf.obj \ +..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ +..\src\bflib\sgf.obj \ +..\src\bflib\sva.obj \ +..\src\colamd\colamd.obj \ +..\src\draft\bfd.obj \ +..\src\draft\bfx.obj \ +..\src\draft\glpapi06.obj \ +..\src\draft\glpapi07.obj \ +..\src\draft\glpapi08.obj \ +..\src\draft\glpapi09.obj \ +..\src\draft\glpapi10.obj \ +..\src\draft\glpapi12.obj \ +..\src\draft\glpapi13.obj \ +..\src\draft\glphbm.obj \ +..\src\draft\glpios01.obj \ +..\src\draft\glpios02.obj \ +..\src\draft\glpios03.obj \ +..\src\draft\glpios07.obj \ +..\src\draft\glpios09.obj \ +..\src\draft\glpios11.obj \ +..\src\draft\glpios12.obj \ +..\src\draft\glpipm.obj \ +..\src\draft\glpmat.obj \ +..\src\draft\glprgr.obj \ +..\src\draft\glpscl.obj \ +..\src\draft\glpspm.obj \ +..\src\draft\glpssx01.obj \ +..\src\draft\glpssx02.obj \ +..\src\draft\lux.obj \ +..\src\env\alloc.obj \ +..\src\env\dlsup.obj \ +..\src\env\env.obj \ +..\src\env\error.obj \ +..\src\env\stdc.obj \ +..\src\env\stdout.obj \ +..\src\env\stream.obj \ +..\src\env\time.obj \ +..\src\env\tls.obj \ +..\src\intopt\cfg.obj \ +..\src\intopt\cfg1.obj \ +..\src\intopt\cfg2.obj \ +..\src\intopt\clqcut.obj \ +..\src\intopt\covgen.obj \ +..\src\intopt\fpump.obj \ +..\src\intopt\gmicut.obj \ +..\src\intopt\gmigen.obj \ +..\src\intopt\mirgen.obj \ +..\src\intopt\spv.obj \ +..\src\minisat\minisat.obj \ +..\src\misc\avl.obj \ +..\src\misc\bignum.obj \ +..\src\misc\dimacs.obj \ +..\src\misc\dmp.obj \ +..\src\misc\ffalg.obj \ +..\src\misc\fp2rat.obj \ +..\src\misc\fvs.obj \ +..\src\misc\gcd.obj \ +..\src\misc\jd.obj \ +..\src\misc\keller.obj \ +..\src\misc\ks.obj \ +..\src\misc\mc13d.obj \ +..\src\misc\mc21a.obj \ +..\src\misc\mt1.obj \ +..\src\misc\mygmp.obj \ +..\src\misc\okalg.obj \ +..\src\misc\qmd.obj \ +..\src\misc\relax4.obj \ +..\src\misc\rng.obj \ +..\src\misc\rng1.obj \ +..\src\misc\round2n.obj \ +..\src\misc\str2int.obj \ +..\src\misc\str2num.obj \ +..\src\misc\strspx.obj \ +..\src\misc\strtrim.obj \ +..\src\misc\triang.obj \ +..\src\misc\wclique.obj \ +..\src\misc\wclique1.obj \ +..\src\mpl\mpl1.obj \ +..\src\mpl\mpl2.obj \ +..\src\mpl\mpl3.obj \ +..\src\mpl\mpl4.obj \ +..\src\mpl\mpl5.obj \ +..\src\mpl\mpl6.obj \ +..\src\mpl\mplsql.obj \ +..\src\npp\npp1.obj \ +..\src\npp\npp2.obj \ +..\src\npp\npp3.obj \ +..\src\npp\npp4.obj \ +..\src\npp\npp5.obj \ +..\src\npp\npp6.obj \ +..\src\proxy\proxy.obj \ +..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ +..\src\zlib\adler32.obj \ +..\src\zlib\compress.obj \ +..\src\zlib\crc32.obj \ +..\src\zlib\deflate.obj \ +..\src\zlib\gzclose.obj \ +..\src\zlib\gzlib.obj \ +..\src\zlib\gzread.obj \ +..\src\zlib\gzwrite.obj \ +..\src\zlib\inffast.obj \ +..\src\zlib\inflate.obj \ +..\src\zlib\inftrees.obj \ +..\src\zlib\trees.obj \ +..\src\zlib\uncompr.obj \ +..\src\zlib\zio.obj \ +..\src\zlib\zutil.obj + +.c.obj: + cl.exe $(CFLAGS) /Fo$*.obj /c $*.c + +all: glpk_4_65.dll glpsol.exe + +glpk_4_65.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_65.dll \ + ..\src\*.obj \ + ..\src\amd\*.obj \ + ..\src\api\*.obj \ + ..\src\bflib\*.obj \ + ..\src\colamd\*.obj \ + ..\src\draft\*.obj \ + ..\src\env\*.obj \ + ..\src\intopt\*.obj \ + ..\src\minisat\*.obj \ + ..\src\misc\*.obj \ + ..\src\mpl\*.obj \ + ..\src\npp\*.obj \ + ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ + ..\src\zlib\*.obj \ + glpk_4_65.def + +glpsol.exe: ..\examples\glpsol.obj glpk_4_65.dll + cl.exe $(CFLAGS) /Feglpsol.exe \ + ..\examples\glpsol.obj glpk_4_65.lib + +check: glpsol.exe + .\glpsol.exe --version + .\glpsol.exe --mps ..\examples\murtagh.mps --max + +## eof ## diff --git a/WebAPP/SOLVERs/GLPK/glpk/w64/readme.txt b/WebAPP/SOLVERs/GLPK/glpk/w64/readme.txt new file mode 100644 index 000000000..d5742d964 --- /dev/null +++ b/WebAPP/SOLVERs/GLPK/glpk/w64/readme.txt @@ -0,0 +1,24 @@ +This directory contains batch files and other stuff which you can use +to build GLPK for 64-bit Windows with the native C/C++ compilers. + +Before running the batch file do the following: + +1. Make sure that you have installed the compiler you are going to use + to build GLPK. + +2. Look into corresponding batch file (just right-click it and choose + 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME + variable specifies correct path to the compiler directory; if not, + make necessary changes. + +To run the batch file just double-click it and wait a bit while the +Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the +MS-DOS window means that all is OK. If you do not see it, something is +wrong. + +Once GLPK has been successfully built, there must appear two files in +this directory: + +glpk.lib, which is the GLPK object library, and + +glpsol.exe, which is the stand-alone GLPK LP/MIP solver. diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf10..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index dc1312ab0..000000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/requirementsrtd.txt b/docs/requirementsrtd.txt deleted file mode 100644 index 69cda52ae..000000000 Binary files a/docs/requirementsrtd.txt and /dev/null differ diff --git a/docs/source/_static/configure.png b/docs/source/_static/configure.png deleted file mode 100644 index 4e8703613..000000000 Binary files a/docs/source/_static/configure.png and /dev/null differ diff --git a/docs/source/_static/configure2.png b/docs/source/_static/configure2.png deleted file mode 100644 index ec54c2713..000000000 Binary files a/docs/source/_static/configure2.png and /dev/null differ diff --git a/docs/source/_static/dataentry.png b/docs/source/_static/dataentry.png deleted file mode 100644 index 8e801ad05..000000000 Binary files a/docs/source/_static/dataentry.png and /dev/null differ diff --git a/docs/source/_static/hometab.png b/docs/source/_static/hometab.png deleted file mode 100644 index bdb47fb7d..000000000 Binary files a/docs/source/_static/hometab.png and /dev/null differ diff --git a/docs/source/_static/hometab2.png b/docs/source/_static/hometab2.png deleted file mode 100644 index 070c91538..000000000 Binary files a/docs/source/_static/hometab2.png and /dev/null differ diff --git a/docs/source/_static/hometab3.png b/docs/source/_static/hometab3.png deleted file mode 100644 index f18824afe..000000000 Binary files a/docs/source/_static/hometab3.png and /dev/null differ diff --git a/docs/source/_static/modeldiagram.png b/docs/source/_static/modeldiagram.png deleted file mode 100644 index 749e2bcd3..000000000 Binary files a/docs/source/_static/modeldiagram.png and /dev/null differ diff --git a/docs/source/_static/modeldiagram2.png b/docs/source/_static/modeldiagram2.png deleted file mode 100644 index 94699212a..000000000 Binary files a/docs/source/_static/modeldiagram2.png and /dev/null differ diff --git a/docs/source/_static/muio-logo.png b/docs/source/_static/muio-logo.png deleted file mode 100644 index 031763971..000000000 Binary files a/docs/source/_static/muio-logo.png and /dev/null differ diff --git a/docs/source/_static/parameters.png b/docs/source/_static/parameters.png deleted file mode 100644 index a7329f4ab..000000000 Binary files a/docs/source/_static/parameters.png and /dev/null differ diff --git a/docs/source/_static/results.png b/docs/source/_static/results.png deleted file mode 100644 index 5c9ccf0d6..000000000 Binary files a/docs/source/_static/results.png and /dev/null differ diff --git a/docs/source/_static/runmodel.png b/docs/source/_static/runmodel.png deleted file mode 100644 index 98eea72c9..000000000 Binary files a/docs/source/_static/runmodel.png and /dev/null differ diff --git a/docs/source/_static/viewdata.png b/docs/source/_static/viewdata.png deleted file mode 100644 index f831d44f9..000000000 Binary files a/docs/source/_static/viewdata.png and /dev/null differ diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index ce745e94f..000000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,65 +0,0 @@ -# MUIO documentation build configuration file - -import sys -from pathlib import Path - -# Optional: insert MUIO source path to sys.path if autodoc is used -# sys.path.insert(0, str(Path("../.."))) - -# -- Project information ----------------------------------------------------- -project = 'MUIO: Modelling User Interface for OSeMOSYS' -author = 'MUIO Contributors' -copyright = '2024-2025, MUIO Project' - -# -- General configuration --------------------------------------------------- -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.mathjax', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', - 'sphinx_book_theme', -] - -autosummary_generate = True -todo_include_todos = True -source_suffix = '.rst' -master_doc = 'index' -language = 'en' -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# -- HTML output ------------------------------------------------------------- - -html_theme = "sphinx_book_theme" - -html_theme_options = { - "repository_url": "https://github.com/OSeMOSYS/MUIO", - "use_repository_button": True, - "use_edit_page_button": True, - "path_to_docs": "docs/source", - "home_page_in_toc": True, - "show_navbar_depth": 2, -} - -html_title = 'MUIO Documentation' -html_short_title = 'MUIO' -html_logo = '_static/muio-logo.png' # Ensure this file exists -html_favicon = '_static/favicon.ico' # Optional -html_static_path = ['_static'] - -# -- Options for LaTeX output ------------------------------------------------ -latex_documents = [ - (master_doc, 'MUIO.tex', 'MUIO Documentation', 'MUIO Contributors', 'manual'), -] - -# -- Options for manual page output ------------------------------------------ -man_pages = [ - (master_doc, 'muio', 'MUIO Documentation', [author], 1) -] - -# -- Options for Texinfo output ---------------------------------------------- -texinfo_documents = [ - (master_doc, 'MUIO', 'MUIO Documentation', author, 'MUIO', - 'An interface to build OSeMOSYS energy models.', 'Miscellaneous'), -] - diff --git a/docs/source/contributing/contributing.rst b/docs/source/contributing/contributing.rst deleted file mode 100644 index f4811ac89..000000000 --- a/docs/source/contributing/contributing.rst +++ /dev/null @@ -1,112 +0,0 @@ -########################### -Contributing -########################### - -We warmly welcome anyone interested in MUIO and the broader OSeMOSYS ecosystem! Whether you have ideas, suggestions, bug reports, or would like to contribute improvements, your input is highly valued. - -How You Can Contribute ---------------------------- - -🧠 `Code Contributions`_ - -Help us enhance MUIO by adding new functionalities, fixing bugs, or optimizing model performance. - -📚 `Documentation`_ - -Support the community by expanding or refining the documentation—add new sections, correct errors, or improve clarity for new users. - -📂 `Examples and Use Cases`_ - -Share your modelling examples or country applications. These can be valuable learning tools for others in the community. - - -Code Contributions -------------------- - -Want to suggest a fix or add a feature? Here's a quick and easy workflow: - -1. Fork the repository: Click the “Fork” button on the `MUIO GitHub page `_ - -2. Clone your fork: Copy the link to your fork and run: - -.. code:: bash - - git clone https://github.com//MUIO.git - -3. Make your changes: Create a new branch and make your edits or improvements in the code. - -4. Test your changes: If there are tests, run them locally. If not, just make sure your edits work as expected. - -5. Push and open a pull request: Push your branch to your fork and go to GitHub to open a pull request. - -Documentation -------------------- - -We aim to keep the MUIO documentation clear, helpful, and up to date. If you notice any gaps, outdated content, or unclear explanations, your help in improving it is greatly appreciated. - -How to Contribute to the Docs: - -1. Find something to improve - Spotted a typo, unclear sentence, or missing sections. - -2. Edit directly on GitHub - - - On any documentation page, click the book icon (📖) at the bottom-left corner. - - Then click “Edit on GitHub” – this will take you to the exact source file. - -3. Make your changes - Use GitHub’s built-in editor to edit the file directly. - -4. Propose your edit - Once done, commit the changes and open a pull request. We’ll review and merge it! - - -Examples and Use Cases -------------------- - -Have you built a useful energy model using MUIO? We'd love to include it as an example to help others learn and build faster. Here's how to contribute an example to the documentation: - -✅ What Makes a Good Example? -^^^^^^^^^^^^^^^^^^^^^^ - -We welcome examples that: - -* Use MUIO in real or hypothetical case studies (e.g. countries, regions, sectors). - -* Demonstrate specific features (e.g. multi-regional modelling, transport sector, emissions). - -* Include complete data files, clear naming, and a brief description. - -* Are small enough to run quickly (or include a simplified version). - -🚀 How to Contribute an Example -^^^^^^^^^^^^^^^^^^^^^^ - -1. Prepare your files - - - Organize your example in a folder under ``examples/`` (e.g. ``examples/CountryName/``). - - Include: - - - Model input file (.zip) - - A ``README.md`` describing the model purpose, data source, and assumptions - - *(Optional)* Output plots or summary results - -2. Fork and clone the MUIO repository. - -3. Add your folder under ``/examples``. - If it’s large, consider linking to an external repository or storage (e.g. Zenodo, Figshare). - -4. Add a reference in the documentation - - - Edit the examples section in the documentation (``docs/source/examples.rst``). - - Add a short entry linking to your example folder or external repo. - -5. Create a pull request - Submit your changes with a short description of your example. - -📝 Licensing and Attribution -^^^^^^^^^^^^^^^^^^^^^^ - -* Please include a note in your README.md indicating data sources and your preferred citation (if any). - -* Make sure you have the right to share the data and code you include. diff --git a/docs/source/contributing/support.rst b/docs/source/contributing/support.rst deleted file mode 100644 index 94a4e2c5c..000000000 --- a/docs/source/contributing/support.rst +++ /dev/null @@ -1,18 +0,0 @@ -########################### -Support and Troubleshooting -########################### - -Need help using MUIO or found a bug? There are several ways to reach out and contribute to the improvement of the tool. - -💬 Community Support -++++++++++++++++++++ - -To connect with other MUIO and OSeMOSYS users, ask questions, share updates, or collaborate on projects, you can: -• Join the OSeMOSYS Community via the Energy Modelling Community on `Linkedin `_ -• Participate in discussions on the OSeMOSYS Discourse Forum [Link to be updated soon] - -🐞 Report Bugs or Suggest Features -++++++++++++++++++++++++++++++++++ - -Found a bug? Have an idea for a new feature? Please open an issue on the `GitHub Issue Tracker `_ -Be sure to describe the problem clearly and include steps to reproduce it, if possible. diff --git a/docs/source/examples/demo.rst b/docs/source/examples/demo.rst deleted file mode 100644 index 6fc3c9b5f..000000000 --- a/docs/source/examples/demo.rst +++ /dev/null @@ -1,5 +0,0 @@ -########################### -CLEWs Demo Model -########################### - -Content to be updated soon. \ No newline at end of file diff --git a/docs/source/examples/others.rst b/docs/source/examples/others.rst deleted file mode 100644 index 085211c3d..000000000 --- a/docs/source/examples/others.rst +++ /dev/null @@ -1,5 +0,0 @@ -########################### -Addtional model examples -########################### - -Content to be updated soon. \ No newline at end of file diff --git a/docs/source/getting-started/installation.rst b/docs/source/getting-started/installation.rst deleted file mode 100644 index 1909dfc4e..000000000 --- a/docs/source/getting-started/installation.rst +++ /dev/null @@ -1,20 +0,0 @@ -################ -Installation -################ - -Follow the steps below to install MUIO on a Windows system: - -1. Download the latest version of the user interface from `here `_. - -2. Move the `.exe` file from your downloads folder to a location where you have administrator privileges. For example, you could place it inside `C:\Users\your_name` or any other folder you prefer. - -3. Right-click on `MUIO.exe` and select **Run as administrator**. This will start the installation. It may take several minutes. Once complete, the installation window will close automatically. - -4. The application should open on its own. If it does not, search for **MUIO** in the Windows Start Menu and open it manually. - -5. You should now see the MUIO interface in a new window. - -.. note:: - - If Windows blocks the installer or flags it as unknown, click **More Info** → **Run Anyway** to proceed. - diff --git a/docs/source/getting-started/introduction.rst b/docs/source/getting-started/introduction.rst deleted file mode 100644 index 33d88f03c..000000000 --- a/docs/source/getting-started/introduction.rst +++ /dev/null @@ -1,44 +0,0 @@ -########################################## - Introduction -########################################## - -MUIO is the latest user interface designed for creating OSeMOSYS models, building upon previous interfaces such as MoMani and ClicSand. This all-in-one application enables users to manage input data, customize scenarios, run models, and visualize results—without requiring additional software installations, as it includes all necessary dependencies. - -Purpose -============= -OSeMOSYS is an optimization model used to assess the medium- and long-term evolution of integrated systems, including energy, land, water, and materials. Its modular structure allows for the representation of diverse value chains. For instance, it can model the production chain of synthetic hydrocarbons, incorporating Fischer-Tropsch or methanation processes. -Over the years, OSeMOSYS has evolved in both applicability and adoption across various stakeholders. Some key applications demonstrating its flexibility include: - -* `Power sector capacity expansion planning `_ -* `Transport sector planning `_ -* `Regional energy integration analysis `_ -* `Sector coupling assessment `_ -* `Climate, energy, land, and water systems modeling `_ -* `Economic analysis in energy planning `_ - -Key Outcomes -============= - -OSeMOSYS provides valuable insights, including: - -* Primary energy production per year and per source -* Energy consumption by sector, technology, and year -* Energy production by sector, technology, and year -* Capacity expansion pathways by technology and year -* Investment, operating, and additional costs (e.g., carbon taxes) per sector, technology, and year -* Greenhouse gas emissions trajectories per fuel, sector, technology, and year - -Why Use It? -============= - -OSeMOSYS offers several advantages over similar models: - -* Fast learning curve – The straightforward mathematical formulation and comprehensive training materials facilitate quick adoption. -* Open-source and adaptable – Users can adapt the tool to suit their needs. -* No upfront costs – The software is freely available to anyone, anywhere. -* Large community of practice – Multiple channels exist for collaboration, troubleshooting, and knowledge sharing. - -License -============= - -MUIO is licensed under the open-source Apache License 2.0. diff --git a/docs/source/getting-started/quick-start.rst b/docs/source/getting-started/quick-start.rst deleted file mode 100644 index 08a689649..000000000 --- a/docs/source/getting-started/quick-start.rst +++ /dev/null @@ -1,7 +0,0 @@ -########################### -Quick Start -########################### - -For installation instructions see :doc:`/getting-started/installation`. - -One basic model is described later. \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index 640de2a7a..000000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,117 +0,0 @@ -.. MUIO Documentation documentation master file, created by - sphinx-quickstart on Thu Jun 19 21:16:52 2025. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -MUIO: Modelling User Interface for OSeMOSYS -================================ - -.. image:: https://img.shields.io/github/license/OSeMOSYS/MUIO - :target: LICENSE.txt - :alt: License - -OSeMOSYS stands for "Open Source Energy Modelling System." It is a linear programming model designed for long-term integrated assessment and energy planning. It is particularly useful for informing Nationally Determined Contributions (NDCs), Long-Term Strategies (LTS), and Decarbonization Plans. - -MUIO is a user interface that facilitates data management, model creation, and scenario analysis using OSeMOSYS. - -OSeMOSYS has been applied at various scales, from continental energy systems (such as African Power Pools, South America, and EU28+2) to national, regional, and even village-level models. - -Designed to be cost-free, with a fast learning curve and minimal time commitment, it is accessible to a wide range of users, including developers, modellers, academics, and policymakers. Thanks to its transparency, it is widely used for training and dissemination. - -📖 Explore our latest literature `review `_ on OSeMOSYS applications, enhancements, and future research directions. - -🎓 Join our Open University `course `_ to learn how to build an energy system model from scratch using OSeMOSYS and MUIO. - -This project is maintained by Climate Compatible Growth (CCG) and the United Nations Department of Economic and Social Affairs (UNDESA). - - -Documentation -============= - -**Getting Started** - -* :doc:`/getting-started/introduction` -* :doc:`/getting-started/installation` -* :doc:`/getting-started/quick-start` - -.. toctree:: - :hidden: - :maxdepth: 0 - :caption: Getting Started - - getting-started/introduction - getting-started/installation - getting-started/quick-start - -**Structure of OSeMOSYS in MUIO** - -* :doc:`/structure-osemosys/intro` -* :doc:`/structure-osemosys/sets` -* :doc:`/structure-osemosys/parameters` -* :doc:`/structure-osemosys/variables` -* :doc:`/structure-osemosys/equations` - -.. toctree:: - :hidden: - :maxdepth: 1 - :caption: Structure of OSeMOSYS in MUIO - - structure-osemosys/intro - structure-osemosys/sets - structure-osemosys/parameters - structure-osemosys/variables - structure-osemosys/equations - -**User Guide** - -* :doc:`/user-guide/overview` -* :doc:`/user-guide/creating` - - -.. toctree:: - :hidden: - :maxdepth: 0 - :caption: User Guide - - user-guide/overview - user-guide/creating - -**Examples** - -* :doc:`/examples/demo` -* :doc:`/examples/others` - - -.. toctree:: - :hidden: - :maxdepth: 0 - :caption: Examples - - examples/demo - examples/others - -**Contributing & Support** - -* :doc:`/contributing/contributing` -* :doc:`/contributing/support` - -.. toctree:: - :hidden: - :maxdepth: 0 - :caption: Contributing & Support - - contributing/contributing - contributing/support - -**References** - -* :doc:`/references/citing` -* :doc:`/references/users` - -.. toctree:: - :hidden: - :maxdepth: 0 - :caption: References - - references/citing - references/users diff --git a/docs/source/references/citing.rst b/docs/source/references/citing.rst deleted file mode 100644 index f72050443..000000000 --- a/docs/source/references/citing.rst +++ /dev/null @@ -1,24 +0,0 @@ -########################### -Citing -########################### - -If you use MUIO as part of your research or analysis, we kindly ask that you cite the following reference to acknowledge the framework and support its continued development: - -* Howells, M., Rogner, H., Strachan, N., Heaps, C., Huntington, H., Kypreos, S., Hughes, A., Silveira, S., Decarolis, J., Bazillian, M., & Roehrl, A. (2011). OSeMOSYS : The Open Source Energy Modeling System An introduction to its ethos , structure and development. Energy Policy, 39(10), 5850–5870. https://doi.org/10.1016/j.enpol.2011.06.033 - -Please use the following BibTeX: :: - - @article{Howells2011, - title = {{OSeMOSYS: The Open Source Energy Modeling System: An introduction to its ethos, structure and development}}, - author = {Howells, Mark and Rogner, Hans and Strachan, Neil and Heaps, Craig and Huntington, Hillard and Kypreos, Socrates and Hughes, Anthony and Silveira, Semida and DeCarolis, Joseph and Bazilian, Morgan and Roehrl, Alexander}, - journal = {Energy Policy}, - volume = {39}, - number = {10}, - pages = {5850--5870}, - year = {2011}, - doi = {10.1016/j.enpol.2011.06.033} - } - -You can also cite the software via [DOI to be updated soon]: - -Climate Compatible Growth. (2024). MUIO: Modelling User Interface for OSeMOSYS [Computer software]. GitHub. https://github.com/OSeMOSYS/MUIO \ No newline at end of file diff --git a/docs/source/references/users.rst b/docs/source/references/users.rst deleted file mode 100644 index 1dd1bb0ca..000000000 --- a/docs/source/references/users.rst +++ /dev/null @@ -1,36 +0,0 @@ -########################### -Users -########################### - -OSeMOSYS has been used by universities, research institutes, government agencies, and international organisations as part of their energy system modelling workflows. This list is not exhaustive since OSeMOSYS is open-source, we only know about its use when users share their work or contact the development team. - -Research publications that cite the OSeMOSYS research paper can be found on `Google Scholar `_ - -If you're using OSeMOSYS and would like to be listed, please feel free to reach out via `GitHub Issue Tracker `_ or the OSeMOSYS Discourse Forum [Link to be updated soon] - -Universities and Research Institutes -+++++++++++++++++++++++++++++++++++++ - -* Loughborough University -* KTH Royal Institute of Technology (Sweden) -* Imperial College London -* University College London (UCL) -* University of Cape Town (South Africa) -* University of Mauritius -* Universidad de Costa Rica -* Politecnico di Milano - -Companies, Governmental and Non-Governmental Organisations -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -* UN DESA (Department of Economic and Social Affairs) -* SEforALL (Sustainable Energy for All) -* IRENA (International Renewable Energy Agency) -* ECREEE (ECOWAS Centre for Renewable Energy and Energy Efficiency) - - - - - - - diff --git a/docs/source/structure-osemosys/documents/code/model_organized.txt b/docs/source/structure-osemosys/documents/code/model_organized.txt deleted file mode 100644 index 958b8b4cf..000000000 --- a/docs/source/structure-osemosys/documents/code/model_organized.txt +++ /dev/null @@ -1,336 +0,0 @@ -############### -# Sets # -############### -# -set REGION; -set TECHNOLOGY; -set COMMODITY; -set EMISSION; -set STORAGE; -set YEAR; -set SEASON; -set DAYTYPE; -set DAILYTIMEBRACKET; -set TIMESLICE; -set MODE_OF_OPERATION; -set STORAGEINTRADAY; -set STORAGEINTRAYEAR; -set UDC; -set MODEperTECHNOLOGY{TECHNOLOGY} within MODE_OF_OPERATION; -set MODExTECHNOLOGYperFUELout{COMMODITY} within MODE_OF_OPERATION cross TECHNOLOGY; -set MODExTECHNOLOGYperFUELin{COMMODITY} within MODE_OF_OPERATION cross TECHNOLOGY; -set MODExTECHNOLOGYperSTORAGEto{STORAGE} within MODE_OF_OPERATION cross TECHNOLOGY; -set MODExTECHNOLOGYperSTORAGEfrom{STORAGE} within MODE_OF_OPERATION cross TECHNOLOGY; -set MODExTECHNOLOGYperEMISSION{e in EMISSION} within MODE_OF_OPERATION cross TECHNOLOGY; -set MODExTECHNOLOGYperEMISSIONChange{e in EMISSION} within MODE_OF_OPERATION cross TECHNOLOGY; -# -##################### -# Parameters # -##################### -# -param AccumulatedAnnualDemand{r in REGION, f in COMMODITY, y in YEAR}; -param AnnualEmissionLimit{r in REGION, e in EMISSION, y in YEAR}; -param AvailabilityFactor{r in REGION, t in TECHNOLOGY, y in YEAR}; -param CapacityFactor{r in REGION, t in TECHNOLOGY, l in TIMESLICE, y in YEAR}; -param CapacityOfOneTechnologyUnit{r in REGION, t in TECHNOLOGY, y in YEAR}; -param CapacityToActivityUnit{r in REGION, t in TECHNOLOGY}; -param CapitalCost{r in REGION, t in TECHNOLOGY, y in YEAR}; -param DiscountRate{r in REGION}; -param DiscountRateIdv{r in REGION, t in TECHNOLOGY}; -param EmissionActivityRatio{r in REGION, t in TECHNOLOGY, e in EMISSION, m in MODE_OF_OPERATION, y in YEAR}; -param EmissionsPenalty{r in REGION, e in EMISSION, y in YEAR}; -param FixedCost{r in REGION, t in TECHNOLOGY, y in YEAR}; -param InputActivityRatio{r in REGION, t in TECHNOLOGY, f in COMMODITY, m in MODE_OF_OPERATION, y in YEAR}; -param InputToNewCapacityRatio{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR}; -param InputToTotalCapacityRatio{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR}; -param ModelPeriodEmissionLimit{r in REGION, e in EMISSION}; -param ModelPeriodExogenousEmission{r in REGION, e in EMISSION}; -param OperationalLife{r in REGION, t in TECHNOLOGY}; -param OutputActivityRatio{r in REGION, t in TECHNOLOGY, f in COMMODITY, m in MODE_OF_OPERATION, y in YEAR}; -#param ReserveMargin{r in REGION, y in YEAR}; -#param ReserveMarginTagFuel{r in REGION, f in COMMODITY, y in YEAR}; -#param ReserveMarginTagTechnology{r in REGION, t in TECHNOLOGY, y in YEAR}; -param ResidualCapacity{r in REGION, t in TECHNOLOGY, y in YEAR}; -param SpecifiedAnnualDemand{r in REGION, f in COMMODITY, y in YEAR}; -param SpecifiedDemandProfile{r in REGION, f in COMMODITY, l in TIMESLICE, y in YEAR}; -param TechnologyActivityByModeLowerLimit{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR}; -param TechnologyActivityByModeUpperLimit{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR}; -param TechnologyActivityDecreaseByModeLimit{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR}; -param TechnologyActivityIncreaseByModeLimit{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR}; -param TotalAnnualMaxCapacity{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalAnnualMaxCapacityInvestment{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalAnnualMinCapacity{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalAnnualMinCapacityInvestment{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalTechnologyAnnualActivityLowerLimit{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalTechnologyAnnualActivityUpperLimit{r in REGION, t in TECHNOLOGY, y in YEAR}; -param TotalTechnologyModelPeriodActivityLowerLimit{r in REGION, t in TECHNOLOGY}; -param TotalTechnologyModelPeriodActivityUpperLimit{r in REGION, t in TECHNOLOGY}; -param TradeRoute{r in REGION, rr in REGION, f in COMMODITY, y in YEAR}; -param VariableCost{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR}; -param YearSplit{l in TIMESLICE, y in YEAR}; -param EmissionToActivityChangeRatio{r in REGION, t in TECHNOLOGY, e in EMISSION, m in MODE_OF_OPERATION, y in YEAR}; -param UDCMultiplierTotalCapacity{r in REGION, t in TECHNOLOGY, u in UDC, y in YEAR}; -param UDCMultiplierNewCapacity{r in REGION, t in TECHNOLOGY, u in UDC, y in YEAR}; -param UDCMultiplierActivity{r in REGION, t in TECHNOLOGY, u in UDC, y in YEAR}; -param UDCConstant{r in REGION, u in UDC, y in YEAR}; -param UDCTag{r in REGION, u in UDC}; - -param CapitalRecoveryFactor{r in REGION, t in TECHNOLOGY}; -param PvAnnuity{r in REGION, t in TECHNOLOGY}; -########################Storage added VK -param OperationalLifeStorage{r in REGION, s in STORAGE}; -param CapitalCostStorage{r in REGION, s in STORAGE, y in YEAR}; -param ResidualStorageCapacity{r in REGION, s in STORAGE, y in YEAR}; -param TechnologyToStorage{r in REGION, t in TECHNOLOGY, s in STORAGE, m in MODE_OF_OPERATION}; -param TechnologyFromStorage{r in REGION, t in TECHNOLOGY, s in STORAGE, m in MODE_OF_OPERATION}; - -param StorageLevelStart{r in REGION, s in STORAGE}; -param MinStorageCharge{r in REGION, s in STORAGE, y in YEAR}; - -param Conversionls{l in TIMESLICE, ls in SEASON}; -param Conversionld{l in TIMESLICE, ld in DAYTYPE}; -param Conversionlh{l in TIMESLICE, lh in DAILYTIMEBRACKET}; -param DaySplit{lh in DAILYTIMEBRACKET, y in YEAR}; -param DaysInDayType{ls in SEASON, ld in DAYTYPE, y in YEAR}; -# param DepreciationMethod{r in REGION}, default 2; - -set TIMESLICEofSEASON{ls in SEASON} within TIMESLICE := {l in TIMESLICE : Conversionls[l,ls] = 1}; -set TIMESLICEofDAYTYPE{ld in DAYTYPE} within TIMESLICE := {l in TIMESLICE : Conversionld[l,ld] = 1}; -set TIMESLICEofDAILYTIMEBRACKET{lh in DAILYTIMEBRACKET} within TIMESLICE := {l in TIMESLICE : Conversionlh[l,lh] = 1}; -set TIMESLICEofSDB{ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET} within TIMESLICE := TIMESLICEofSEASON[ls] inter TIMESLICEofDAYTYPE[ld] inter TIMESLICEofDAILYTIMEBRACKET[lh]; - - -# -########################## -# Model Variables # -########################## -# -var AccumulatedNewCapacity{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var AnnualFixedOperatingCost{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var AnnualTechnologyEmission{r in REGION, t in TECHNOLOGY, e in EMISSION, y in YEAR}; -var AnnualTechnologyEmissionByMode{r in REGION, t in TECHNOLOGY, e in EMISSION, m in MODE_OF_OPERATION, y in YEAR}; -var AnnualVariableOperatingCost{r in REGION, t in TECHNOLOGY, y in YEAR}; -var CapitalInvestment{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var Demand{r in REGION, l in TIMESLICE, f in COMMODITY, y in YEAR} >= 0; -var DiscountedSalvageValue{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var InputToNewCapacity{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR} >= 0; -var InputToTotalCapacity{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR} >= 0; -var NewCapacity{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var NumberOfNewTechnologyUnits{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0,integer; -var ProductionByTechnology{r in REGION, l in TIMESLICE, t in TECHNOLOGY, f in COMMODITY, y in YEAR} >= 0; -var RateOfActivity{r in REGION, l in TIMESLICE, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR} >= 0; -var RateOfTotalActivity{r in REGION, t in TECHNOLOGY, l in TIMESLICE, y in YEAR} >= 0; -var SalvageValue{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var TotalAnnualTechnologyActivityByMode{r in REGION, t in TECHNOLOGY, m in MODE_OF_OPERATION, y in YEAR} >= 0; -var TotalCapacityAnnual{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var TotalTechnologyAnnualActivity{r in REGION, t in TECHNOLOGY, y in YEAR} >= 0; -var TotalTechnologyModelPeriodActivity{r in REGION, t in TECHNOLOGY}; -var Trade{r in REGION, rr in REGION, l in TIMESLICE, f in COMMODITY, y in YEAR}; -var EmissionByActivityChange{r in REGION, t in TECHNOLOGY, e in EMISSION, m in MODE_OF_OPERATION, y in YEAR}; -var TechnologyEmissionsPenalty{r in REGION, t in TECHNOLOGY, y in YEAR}; - -######## Storage ############# -# -var NewStorageCapacity{r in REGION, s in STORAGE, y in YEAR} >=0; -var SalvageValueStorage{r in REGION, s in STORAGE, y in YEAR} >=0; -var StorageLevelYearStart{r in REGION, s in STORAGE, y in YEAR} >=0; -var StorageLevelYearFinish{r in REGION, s in STORAGE, y in YEAR} >=0; -var StorageLevelSeasonStart{r in REGION, s in STORAGE, ls in SEASON, y in YEAR} >=0; -var StorageLevelDayTypeStart{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, y in YEAR} >=0; -var StorageLevelDayTypeFinish{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, y in YEAR} >=0; -var RateOfNetStorageActivity{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}; -var NetChargeWithinYear{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}; -var NetChargeWithinDay{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}; -var StorageLowerLimit{r in REGION, s in STORAGE, y in YEAR}>=0; -var StorageUpperLimit{r in REGION, s in STORAGE, y in YEAR} >=0; -var AccumulatedNewStorageCapacity{r in REGION, s in STORAGE, y in YEAR} >=0; -var CapitalInvestmentStorage{r in REGION, s in STORAGE, y in YEAR} >=0; -var DiscountedCapitalInvestmentStorage{r in REGION, s in STORAGE, y in YEAR} >=0; -var DiscountedSalvageValueStorage{r in REGION, s in STORAGE, y in YEAR} >=0; -var TotalDiscountedStorageCost{r in REGION, s in STORAGE, y in YEAR} >=0; -# -###################### -# Objective Function # -###################### -# -minimize cost: sum{r in REGION, t in TECHNOLOGY, y in YEAR} ((((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y])*FixedCost[r,t,y] + sum{m in MODEperTECHNOLOGY[t], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*YearSplit[l,y]*VariableCost[r,t,m,y])/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy)+0.5))+CapitalCost[r,t,y] * NewCapacity[r,t,y] * CapitalRecoveryFactor[r,t] * PvAnnuity[r,t]/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy)))+ -sum{e in EMISSION} (sum{l in TIMESLICE, (m,tt) in MODExTECHNOLOGYperEMISSION[e]: t=tt} EmissionActivityRatio [r, t, e, m, y] * RateOfActivity [r, l, t, m, y] * YearSplit [l, y] + sum{(m,tt) in MODExTECHNOLOGYperEMISSIONChange[e]: t=tt} EmissionByActivityChange[r, t, e, m, y]) -* EmissionsPenalty [r, e, y] / ((1 + DiscountRate [r]) ^ (y - min{yy in YEAR} min(yy) + 0.5)) --DiscountedSalvageValue[r,t,y]) + sum{r in REGION, s in STORAGE, y in YEAR} (CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy)))-DiscountedSalvageValueStorage[r,s,y]); -# -##################### -# Constraints # -##################### -# -######### Capacity Adequacy A ############# -# -s.t. CAa1_TotalNewCapacity{r in REGION, t in TECHNOLOGY, y in YEAR}:AccumulatedNewCapacity[r,t,y] = sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy]; -s.t. CAa2_TotalAnnualCapacity{r in REGION, t in TECHNOLOGY, y in YEAR}: ((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y]) = TotalCapacityAnnual[r,t,y]; -s.t. CAa3_TotalActivityOfEachTechnology{r in REGION, t in TECHNOLOGY, l in TIMESLICE, y in YEAR}: sum{m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y] = RateOfTotalActivity[r,t,l,y]; -s.t. CAa4_Constraint_Capacity{r in REGION, l in TIMESLICE, t in TECHNOLOGY, y in YEAR}: sum{m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y] <= ((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y])*CapacityFactor[r,t,l,y]*CapacityToActivityUnit[r,t]; -s.t. CAa5_TotalNewCapacity{r in REGION, t in TECHNOLOGY, y in YEAR: CapacityOfOneTechnologyUnit[r,t,y]<>0}: CapacityOfOneTechnologyUnit[r,t,y]*NumberOfNewTechnologyUnits[r,t,y] = NewCapacity[r,t,y]; -# -######### Capacity Adequacy B ############# -# -s.t. CAb1_PlannedMaintenance{r in REGION, t in TECHNOLOGY, y in YEAR}: sum{l in TIMESLICE} sum{m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] <= sum{l in TIMESLICE} (((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y])*CapacityFactor[r,t,l,y]*YearSplit[l,y])* AvailabilityFactor[r,t,y]*CapacityToActivityUnit[r,t]; -# -######### Energy Balance A ############# -# -s.t. EBb4_EnergyBalanceEachYear4_ICR{r in REGION, f in COMMODITY, y in YEAR}: sum{(m,t) in MODExTECHNOLOGYperFUELout[f], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*OutputActivityRatio[r,t,f,m,y]*YearSplit[l,y] >= sum{(m,t) in MODExTECHNOLOGYperFUELin[f], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*InputActivityRatio[r,t,f,m,y]*YearSplit[l,y] + sum{l in TIMESLICE, rr in REGION} Trade[r,rr,l,f,y]*TradeRoute[r,rr,f,y] + AccumulatedAnnualDemand[r,f,y] + sum{t in TECHNOLOGY} InputToNewCapacity [r, t, f, y] + sum{t in TECHNOLOGY} InputToTotalCapacity [r, t, f, y]; -s.t. EBa9_EnergyBalanceEachTS3{r in REGION, l in TIMESLICE, f in COMMODITY, y in YEAR}: SpecifiedAnnualDemand[r,f,y]*SpecifiedDemandProfile[r,f,l,y] = Demand[r,l,f,y]; -s.t. EBa10_EnergyBalanceEachTS4{r in REGION, rr in REGION, l in TIMESLICE, f in COMMODITY, y in YEAR}: Trade[r,rr,l,f,y] = -Trade[rr,r,l,f,y]; -s.t. EBa11_EnergyBalanceEachTS5{r in REGION, l in TIMESLICE, f in COMMODITY, y in YEAR}: sum{(m,t) in MODExTECHNOLOGYperFUELout[f]} RateOfActivity[r,l,t,m,y]*OutputActivityRatio[r,t,f,m,y]*YearSplit[l,y] >= SpecifiedAnnualDemand[r,f,y]*SpecifiedDemandProfile[r,f,l,y] + sum{(m,t) in MODExTECHNOLOGYperFUELin[f]} RateOfActivity[r,l,t,m,y]*InputActivityRatio[r,t,f,m,y]*YearSplit[l,y] + sum{rr in REGION} Trade[r,rr,l,f,y]*TradeRoute[r,rr,f,y]; -# -######### Energy Balance B ############# -# -s.t. EBb4_EnergyBalanceEachYear4{r in REGION, f in COMMODITY, y in YEAR}: sum{(m,t) in MODExTECHNOLOGYperFUELout[f], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*OutputActivityRatio[r,t,f,m,y]*YearSplit[l,y] >= sum{(m,t) in MODExTECHNOLOGYperFUELin[f], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*InputActivityRatio[r,t,f,m,y]*YearSplit[l,y] + sum{l in TIMESLICE, rr in REGION} Trade[r,rr,l,f,y]*TradeRoute[r,rr,f,y] + AccumulatedAnnualDemand[r,f,y]; -# -######### Accounting Technology Production/Use ############# -# -s.t. Acc3_AverageAnnualRateOfActivity{r in REGION, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR}: sum{l in TIMESLICE} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] = TotalAnnualTechnologyActivityByMode[r,t,m,y]; -# -######### Storage Equations ############# -# -s.t. S3_NetChargeWithinYear{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: sum{l in TIMESLICE:Conversionls[l,ls]>0&&Conversionld[l,ld]>0&&Conversionlh[l,lh]>0} (sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t]:TechnologyToStorage[r,t,s,m]>0} (RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh]) - (sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t]:TechnologyFromStorage[r,t,s,m]>0} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh])) * YearSplit[l,y] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh] = NetChargeWithinYear[r,s,ls,ld,lh,y]; -s.t. S4_NetChargeWithinDay{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: ((sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], l in TIMESLICE:TechnologyToStorage[r,t,s,m]>0} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh]) - (sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], l in TIMESLICE:TechnologyFromStorage[r,t,s,m]>0} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh])) * DaySplit[lh,y] = NetChargeWithinDay[r,s,ls,ld,lh,y]; -s.t. S9_and_S10_StorageLevelSeasonStart{r in REGION, s in STORAGE, ls in SEASON, y in YEAR}: - if ls = min{lsls in SEASON} min(lsls) - then StorageLevelYearStart[r,s,y] - else StorageLevelSeasonStart[r,s,ls-1,y] + sum{ld in DAYTYPE, lh in DAILYTIMEBRACKET, l in TIMESLICEofSDB[ls-1,ld,lh]} (sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s]} (RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * YearSplit[l,y] - = StorageLevelSeasonStart[r,s,ls,y]; -s.t. S11_and_S12_StorageLevelDayTypeStart{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, y in YEAR}: - if ld = min{ldld in DAYTYPE} min(ldld) - then StorageLevelSeasonStart[r,s,ls,y] - else StorageLevelDayTypeStart[r,s,ls,ld-1,y] + sum{lh in DAILYTIMEBRACKET} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld-1,lh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld-1,lh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lh,y]) * DaysInDayType[ls,ld-1,y] - = StorageLevelDayTypeStart[r,s,ls,ld,y]; -s.t. S14_RateOfNetStorageActivity{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: (sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], l in TIMESLICE:TechnologyToStorage[r,t,s,m]>0} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh]) - (sum{t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], l in TIMESLICE:TechnologyFromStorage[r,t,s,m]>0} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m] * Conversionls[l,ls] * Conversionld[l,ld] * Conversionlh[l,lh]) = RateOfNetStorageActivity[r,s,ls,ld,lh,y]; -s.t. S30_StorageLevelYearStart2{r in REGION, s in STORAGE, y in YEAR,l in TIMESLICE}: StorageLevelYearStart[r,s,y] = 0; -s.t. S39_StorageIntraday{r in REGION, s in STORAGEINTRADAY, ls in SEASON, ld in DAYTYPE, y in YEAR}: sum{lh in DAILYTIMEBRACKET} (NetChargeWithinDay[r,s,ls,ld,lh,y])=0; -s.t. S39_StorageIntrayear{r in REGION, s in STORAGEINTRAYEAR, y in YEAR}: sum{ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET} (NetChargeWithinYear[r,s,ls,ld,lh,y])=0; -# -########## Storage Constraints ############# -# -#v.k. SC1_LowerLimit_BeginningOfDailyTimeBracketOfFirstInstanceOfDayTypeInFirstWeekConstraint = SC1_LLBDFIFW -#v.k. SC1_UpperLimit_BeginningOfDailyTimeBracketOfFirstInstanceOfDayTypeInFirstWeekConstraint = SC1_ULBDFIFW - -#v.k. SC2_LowerLimit_EndOfDailyTimeBracketOfLastInstanceOfDayTypeInFirstWeekConstraint = SC2_LLEDLIFW -#v.k. SC2_UpperLimit_EndOfDailyTimeBracketOfLastInstanceOfDayTypeInFirstWeekConstraint = SC2_ULEDLIFW - -#v.k. SC3_LowerLimit_EndOfDailyTimeBracketOfLastInstanceOfDayTypeInLastWeekConstraint = SC3_LLEDLILW -#v.k. SC3_UpperLimit_EndOfDailyTimeBracketOfLastInstanceOfDayTypeInLastWeekConstraint = SC3_ULEDLILW - -#v.k. SC4_LowerLimit_BeginningOfDailyTimeBracketOfFirstInstanceOfDayTypeInLastWeekConstraint = SC4_LLBDFILW -#v.k. SC4_UpperLimit_BeginningOfDailyTimeBracketOfFirstInstanceOfDayTypeInLastWeekConstraint = SC4_ULBDFILW - -s.t. SC1_LLBDFIFW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: - 0 <= (StorageLevelDayTypeStart[r,s,ls,ld,y]+sum{lhlh in DAILYTIMEBRACKET:lh-lhlh>0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-MinStorageCharge[r,s,y]*(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]); -s.t. SC1_ULBDFIFW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: - (StorageLevelDayTypeStart[r,s,ls,ld,y]+sum{lhlh in DAILYTIMEBRACKET:lh-lhlh>0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]) <= 0; -s.t. SC2_LLEDLIFW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: 0 <= if ld > min{ldld in DAYTYPE} min(ldld) then (StorageLevelDayTypeStart[r,s,ls,ld,y]-sum{lhlh in DAILYTIMEBRACKET:lh-lhlh<0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-MinStorageCharge[r,s,y]*(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]); -s.t. SC2_ULEDLIFW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: if ld > min{ldld in DAYTYPE} min(ldld) then (StorageLevelDayTypeStart[r,s,ls,ld,y]-sum{lhlh in DAILYTIMEBRACKET:lh-lhlh<0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]) <= 0; -s.t. SC3_LLEDLILW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: 0 <= (StorageLevelDayTypeFinish[r,s,ls,ld,y] - sum{lhlh in DAILYTIMEBRACKET:lh-lhlh<0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-MinStorageCharge[r,s,y]*(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]); -s.t. SC3_ULEDLILW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: (StorageLevelDayTypeFinish[r,s,ls,ld,y] - sum{lhlh in DAILYTIMEBRACKET:lh-lhlh<0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]) <= 0; -s.t. SC4_LLBDFILW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: 0 <= if ld > min{ldld in DAYTYPE} min(ldld) then (StorageLevelDayTypeFinish[r,s,ls,ld-1,y]+sum{lhlh in DAILYTIMEBRACKET:lh-lhlh>0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-MinStorageCharge[r,s,y]*(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]); -s.t. SC4_ULBDFILW{r in REGION, s in STORAGE, ls in SEASON, ld in DAYTYPE, lh in DAILYTIMEBRACKET, y in YEAR}: if ld > min{ldld in DAYTYPE} min(ldld) then (StorageLevelDayTypeFinish[r,s,ls,ld-1,y]+sum{lhlh in DAILYTIMEBRACKET:lh-lhlh>0} (((sum{(m,t) in MODExTECHNOLOGYperSTORAGEto[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyToStorage[r,t,s,m]) - (sum{(m,t) in MODExTECHNOLOGYperSTORAGEfrom[s], l in TIMESLICEofSDB[ls,ld,lhlh]} RateOfActivity[r,l,t,m,y] * TechnologyFromStorage[r,t,s,m])) * DaySplit[lhlh,y]))-(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]) <= 0; -# -######### Storage Investments ############# -# -s.t. SI2_StorageLowerLimit{r in REGION, s in STORAGE, y in YEAR}: MinStorageCharge[r,s,y]*(sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y]) = StorageLowerLimit[r,s,y]; -s.t. SI3_TotalNewStorage{r in REGION, s in STORAGE, y in YEAR}: sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]=AccumulatedNewStorageCapacity[r,s,y]; -s.t. SI4_UndiscountedCapitalInvestmentStorage{r in REGION, s in STORAGE, y in YEAR}: CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y] = CapitalInvestmentStorage[r,s,y]; -s.t. SI6_SalvageValueStorageAtEndOfPeriod1{r in REGION, s in STORAGE, y in YEAR: (y+OperationalLifeStorage[r,s]-1) <= (max{yy in YEAR} max(yy))}: 0 = SalvageValueStorage[r,s,y]; -s.t. SI7_SalvageValueStorageAtEndOfPeriod2{r in REGION, s in STORAGE, y in YEAR: (y+OperationalLifeStorage[r,s]-1) > (max{yy in YEAR} max(yy))}: CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]*(1-(max{yy in YEAR} max(yy) - y+1)/OperationalLifeStorage[r,s]) = SalvageValueStorage[r,s,y]; -s.t. SI9_SalvageValueStorageDiscountedToStartYear{r in REGION, s in STORAGE, y in YEAR}: SalvageValueStorage[r,s,y]/((1+DiscountRate[r])^(max{yy in YEAR} max(yy)-min{yy in YEAR} min(yy)+1)) = DiscountedSalvageValueStorage[r,s,y]; - -# 20240625 vk ta DepreciationMethod default 2 -#s.t. SI7_SalvageValueStorageAtEndOfPeriod2{r in REGION, s in STORAGE, y in YEAR: (DepreciationMethod[r]=1 && (y+OperationalLifeStorage[r,s]-1) > (max{yy in YEAR} max(yy)) && DiscountRate[r]=0) || (DepreciationMethod[r]=2 && (y+OperationalLifeStorage[r,s]-1) > (max{yy in YEAR} max(yy)))}: CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]*(1-(max{yy in YEAR} max(yy) - y+1)/OperationalLifeStorage[r,s]) = SalvageValueStorage[r,s,y]; -#s.t. SI8_SalvageValueStorageAtEndOfPeriod3{r in REGION, s in STORAGE, y in YEAR: DepreciationMethod[r]=1 && (y+OperationalLifeStorage[r,s]-1) > (max{yy in YEAR} max(yy)) && DiscountRate[r]>0}: CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]*(1-(((1+DiscountRate[r])^(max{yy in YEAR} max(yy) - y+1)-1)/((1+DiscountRate[r])^OperationalLifeStorage[r,s]-1))) = SalvageValueStorage[r,s,y]; - -#s.t. SI1_StorageUpperLimit{r in REGION, s in STORAGE, y in YEAR}: sum{yy in YEAR: y-yy < OperationalLifeStorage[r,s] && y-yy>=0} NewStorageCapacity[r,s,yy]+ResidualStorageCapacity[r,s,y] = StorageUpperLimit[r,s,y]; - -#s.t. SI5_DiscountingCapitalInvestmentStorage{r in REGION, s in STORAGE, y in YEAR}: CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy))) = DiscountedCapitalInvestmentStorage[r,s,y]; - -#s.t. SI10_TotalDiscountedCostByStorage{r in REGION, s in STORAGE, y in YEAR}: (CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy)))-CapitalCostStorage[r,s,y] * NewStorageCapacity[r,s,y]/((1+DiscountRate[r])^(y-min{yy in YEAR} min(yy)))) = TotalDiscountedStorageCost[r,s,y]; -# -######### Capital Costs ############# -# -s.t. CC1_UndiscountedCapitalInvestment{r in REGION, t in TECHNOLOGY, y in YEAR}: CapitalCost[r,t,y] * NewCapacity[r,t,y] = CapitalInvestment[r,t,y]; -# -######### Salvage Value ############# -# -s.t. SV1_SalvageValueAtEndOfPeriod1{r in REGION, t in TECHNOLOGY, y in YEAR: (y + OperationalLife[r,t]-1) > (max{yy in YEAR} max(yy)) && DiscountRate[r]=0}: SalvageValue[r,t,y] = CapitalCost[r,t,y]*NewCapacity[r,t,y]*CapitalRecoveryFactor[r,t] * PvAnnuity[r,t]*(1-(((1+DiscountRate[r])^(max{yy in YEAR} max(yy) - y+1)-1)/((1+DiscountRate[r])^OperationalLife[r,t]-1))); -s.t. SV2_SalvageValueAtEndOfPeriod2{r in REGION, t in TECHNOLOGY, y in YEAR: (y + OperationalLife[r,t]-1) > (max{yy in YEAR} max(yy)) && DiscountRate[r]>0}: SalvageValue[r,t,y] = CapitalCost[r,t,y]*NewCapacity[r,t,y]*CapitalRecoveryFactor[r,t] * PvAnnuity[r,t]*(1-(max{yy in YEAR} max(yy) - y+1)/OperationalLife[r,t]); -s.t. SV3_SalvageValueAtEndOfPeriod3{r in REGION, t in TECHNOLOGY, y in YEAR: (y + OperationalLife[r,t]-1) <= (max{yy in YEAR} max(yy))}: SalvageValue[r,t,y] = 0; -s.t. SV4_SalvageValueDiscountedToStartYear{r in REGION, t in TECHNOLOGY, y in YEAR}: DiscountedSalvageValue[r,t,y] = SalvageValue[r,t,y]/((1+DiscountRate[r])^(1+max{yy in YEAR} max(yy)-min{yy in YEAR} min(yy))); -# -######### Operating Costs ############# -# -s.t. OC1_OperatingCostsVariable{r in REGION, t in TECHNOLOGY, y in YEAR}: sum{m in MODEperTECHNOLOGY[t], l in TIMESLICE} RateOfActivity[r,l,t,m,y]*YearSplit[l,y]*VariableCost[r,t,m,y] = AnnualVariableOperatingCost[r,t,y]; -s.t. OC2_OperatingCostsFixedAnnual{r in REGION, t in TECHNOLOGY, y in YEAR}: ((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y])*FixedCost[r,t,y] = AnnualFixedOperatingCost[r,t,y]; -# -######### Total Capacity Constraints ############## -# -s.t. TCC1_TotalAnnualMaxCapacityConstraint{r in REGION, t in TECHNOLOGY, y in YEAR}: ((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y]) <= TotalAnnualMaxCapacity[r,t,y]; -s.t. TCC2_TotalAnnualMinCapacityConstraint{r in REGION, t in TECHNOLOGY, y in YEAR: TotalAnnualMinCapacity[r,t,y]>0}: ((sum{yy in YEAR: y-yy < OperationalLife[r,t] && y-yy>=0} NewCapacity[r,t,yy])+ ResidualCapacity[r,t,y]) >= TotalAnnualMinCapacity[r,t,y]; -# -######### New Capacity Constraints ############## -# -s.t. NCC1_TotalAnnualMaxNewCapacityConstraint{r in REGION, t in TECHNOLOGY, y in YEAR}: NewCapacity[r,t,y] <= TotalAnnualMaxCapacityInvestment[r,t,y]; -s.t. NCC2_TotalAnnualMinNewCapacityConstraint{r in REGION, t in TECHNOLOGY, y in YEAR: TotalAnnualMinCapacityInvestment[r,t,y]>0}: NewCapacity[r,t,y] >= TotalAnnualMinCapacityInvestment[r,t,y]; -# -######### Annual Activity Constraints ############## -# -s.t. AAC1_TotalAnnualTechnologyActivity{r in REGION, t in TECHNOLOGY, y in YEAR}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] = TotalTechnologyAnnualActivity[r,t,y]; -s.t. AAC2_TotalAnnualTechnologyActivityUpperLimit{r in REGION, t in TECHNOLOGY, y in YEAR}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] <= TotalTechnologyAnnualActivityUpperLimit[r,t,y] ; -s.t. AAC3_TotalAnnualTechnologyActivityLowerLimit{r in REGION, t in TECHNOLOGY, y in YEAR: TotalTechnologyAnnualActivityLowerLimit[r,t,y]>0}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t]} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] >= TotalTechnologyAnnualActivityLowerLimit[r,t,y] ; -# -######### Total Activity Constraints ############## -# -s.t. TAC1_TotalModelHorizonTechnologyActivity{r in REGION, t in TECHNOLOGY}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t], y in YEAR} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] = TotalTechnologyModelPeriodActivity[r,t]; -s.t. TAC2_TotalModelHorizonTechnologyActivityUpperLimit{r in REGION, t in TECHNOLOGY}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t], y in YEAR} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] <= TotalTechnologyModelPeriodActivityUpperLimit[r,t] ; -s.t. TAC3_TotalModelHorizonTechnologyActivityLowerLimit{r in REGION, t in TECHNOLOGY: TotalTechnologyModelPeriodActivityLowerLimit[r,t]>0}: sum{l in TIMESLICE, m in MODEperTECHNOLOGY[t], y in YEAR} RateOfActivity[r,l,t,m,y]*YearSplit[l,y] >= TotalTechnologyModelPeriodActivityLowerLimit[r,t] ; -# -######### Emissions Accounting ############## -# -# TN Modified 2024 Jan -s.t. E1_AnnualEmissionProductionByMode{r in REGION, e in EMISSION, (m, t) in MODExTECHNOLOGYperEMISSION[e], y in YEAR}: EmissionActivityRatio[r,t,e,m,y]*sum{l in TIMESLICE} RateOfActivity[r,l,t,m,y]*YearSplit[l,y]=AnnualTechnologyEmissionByMode[r,t,e,m,y]; -s.t. E2_AnnualEmissionProduction{r in REGION, t in TECHNOLOGY, e in EMISSION, y in YEAR}: - sum{l in TIMESLICE, (m, tt) in MODExTECHNOLOGYperEMISSION[e]: t=tt} EmissionActivityRatio[r,t,e,m,y]*RateOfActivity[r,l,t,m,y]*YearSplit[l,y] - + sum{(m,tt) in MODExTECHNOLOGYperEMISSIONChange[e]: t=tt}EmissionByActivityChange[r, t, e, m, y] - = AnnualTechnologyEmission[r,t,e,y]; -s.t. E5_EmissionsPenaltyByTechnology{r in REGION, t in TECHNOLOGY, y in YEAR}: sum{e in EMISSION} (sum{l in TIMESLICE, (m,tt) in MODExTECHNOLOGYperEMISSION[e]: t=tt} EmissionActivityRatio [r, t, e, m, y] * RateOfActivity [r, l, t, m, y] * YearSplit [l, y] + sum{(m,tt) in MODExTECHNOLOGYperEMISSIONChange[e]: t=tt} EmissionByActivityChange[r, t, e, m, y])* EmissionsPenalty [r, e, y] = TechnologyEmissionsPenalty [r, t, y]; -s.t. E8_AnnualEmissionsLimit{r in REGION, e in EMISSION, y in YEAR}: sum{l in TIMESLICE, (m,t) in MODExTECHNOLOGYperEMISSION[e]} EmissionActivityRatio [r, t, e, m, y] * RateOfActivity [r, l, t, m, y] * YearSplit [l, y] + sum{(m,t) in MODExTECHNOLOGYperEMISSIONChange[e]} EmissionByActivityChange[r, t, e, m, y] <= AnnualEmissionLimit [r, e, y]; -s.t. E9_ModelPeriodEmissionsLimit{r in REGION, e in EMISSION}: sum{(m,t) in MODExTECHNOLOGYperEMISSION[e], y in YEAR, l in TIMESLICE} EmissionActivityRatio [r, t, e, m, y] * RateOfActivity [r, l, t, m, y] * YearSplit [l, y] + sum{(m,t) in MODExTECHNOLOGYperEMISSIONChange[e], y in YEAR} EmissionByActivityChange[r, t, e, m, y] <= ModelPeriodEmissionLimit [r, e]; -s.t. E10_InterYearActivityEmissionChange{r in REGION, e in EMISSION, (m, t) in MODExTECHNOLOGYperEMISSIONChange[e], y in YEAR, yy in YEAR: y-yy==1 && y > min{yyy in YEAR} min(yyy)}: (TotalAnnualTechnologyActivityByMode[r, t, m, y]-TotalAnnualTechnologyActivityByMode[r, t, m, yy]) * EmissionToActivityChangeRatio[r, t, e, m, y] = EmissionByActivityChange[r, t, e, m, y]; -s.t. E11_InterYearActivityEmissionChange{r in REGION, e in EMISSION, (m, t) in MODExTECHNOLOGYperEMISSIONChange[e], y in YEAR, yy in YEAR: y == min{yyy in YEAR} min(yyy)}: 0 = EmissionByActivityChange[r, t, e, m, y]; -# -######### InputToCapacityRatios ############## -# -s.t. INC1_InputToNewCapacity{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR: InputToNewCapacityRatio [r, t, f, y] <> 0}: InputToNewCapacityRatio [r, t, f, y] * NewCapacity [r, t, y] = InputToNewCapacity [r, t, f, y]; -s.t. ITC1_InputToTotalCapacity{r in REGION, t in TECHNOLOGY, f in COMMODITY, y in YEAR: InputToTotalCapacityRatio [r, t, f, y] <> 0}: InputToTotalCapacityRatio [r, t, f, y] * TotalCapacityAnnual [r, t, y] = InputToTotalCapacity [r, t, f, y]; -# -######### Mode-specific Constraints ############## -# -s.t. LU1_TechnologyActivityByModeUL{r in REGION, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR: TechnologyActivityByModeUpperLimit[r,t,m,y] <> 0}: TotalAnnualTechnologyActivityByMode[r,t,m,y] <= TechnologyActivityByModeUpperLimit[r,t,m,y]; -s.t. LU2_TechnologyActivityByModeLL{r in REGION, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR}: TotalAnnualTechnologyActivityByMode[r,t,m,y] >= TechnologyActivityByModeLowerLimit[r,t,m,y]; -s.t. LU3_TechnologyActivityIncreaseByMode{r in REGION, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR, yy in YEAR: y-yy == 1 && TechnologyActivityIncreaseByModeLimit[r,t,m,yy] <> 0}: TotalAnnualTechnologyActivityByMode[r,t,m,y] <= (1 + TechnologyActivityIncreaseByModeLimit[r,t,m,yy]) * TotalAnnualTechnologyActivityByMode[r,t,m,yy]; -s.t. LU4_TechnologyActivityDecreaseByMode{r in REGION, t in TECHNOLOGY, m in MODEperTECHNOLOGY[t], y in YEAR, yy in YEAR: y-yy == 1 && TechnologyActivityDecreaseByModeLimit[r,t,m,yy] <> 0}: TotalAnnualTechnologyActivityByMode[r,t,m,y] >= (1 - TechnologyActivityDecreaseByModeLimit[r,t,m,yy]) * TotalAnnualTechnologyActivityByMode[r,t,m,yy]; -# -######### User-defined Constraints ############## -# -s.t. UDC1_UserDefinedConstraintInequality{r in REGION, u in UDC, y in YEAR: UDCTag[r,u] = 0}: -sum{t in TECHNOLOGY}UDCMultiplierTotalCapacity[r,t,u,y]*TotalCapacityAnnual[r,t,y] + -sum{t in TECHNOLOGY}UDCMultiplierNewCapacity[r,t,u,y]*NewCapacity[r,t,y] + -sum{t in TECHNOLOGY}UDCMultiplierActivity[r,t,u,y]*TotalTechnologyAnnualActivity[r,t,y] <= UDCConstant[r,u,y]; -s.t. UDC2_UserDefinedConstraintEquality{r in REGION, u in UDC, y in YEAR: UDCTag[r,u] = 1}: -sum{t in TECHNOLOGY}UDCMultiplierTotalCapacity[r,t,u,y]*TotalCapacityAnnual[r,t,y] + -sum{t in TECHNOLOGY}UDCMultiplierNewCapacity[r,t,u,y]*NewCapacity[r,t,y] + -sum{t in TECHNOLOGY}UDCMultiplierActivity[r,t,u,y]*TotalTechnologyAnnualActivity[r,t,y] = UDCConstant[r,u,y]; -# -##################### -# -solve; -# -##################### -# -end; diff --git a/docs/source/structure-osemosys/equations.rst b/docs/source/structure-osemosys/equations.rst deleted file mode 100644 index 37b57f70f..000000000 --- a/docs/source/structure-osemosys/equations.rst +++ /dev/null @@ -1,167 +0,0 @@ -########################### -Equations -########################### - -The OSeMOSYS code is organized into blocks of equations, consisting of a single objective function and multiple constraints. This modular structure enables users to add or remove specific functionalities as needed. Its flexibility makes OSeMOSYS suitable for a wide variety of applications, accommodating different scales, levels of complexity, and analytical goals. - -Objective function ----------------------------- -This equation represents the overall objective of the model. The default in OSeMOSYS is to minimise the total system cost, over the entire model period. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 156-159 - -Capacity Adequacy A ----------------------------- -Used to first calculate total capacity of each technology for each year based on existing capacity from before the model period (*ResidualCapacity*), *AccumulatedNewCapacity* during the modelling period, and *NewCapacity* installed in each year. It is then ensured that this Capacity is sufficient to meet the *RateOfTotalActivity* in each TimeSlice and Year. An additional constraint based on the size, or capacity, of each unit of a Technology is included (*CapacityOfOneTechnologyUnit*). This stipulates that the capacity of certain Technology can only be a multiple of the user-defined *CapacityOfOneTechnologyUnit*. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 167-171 - -NOTE: OSeMOSYS uses Mixed Integer Programming to solve models that define *CapacityOfTechnologyUnit*. Using this parameter is likely to increase the model computation time. - -Capacity Adequacy B ----------------------------- -Ensures that adequate capacity of technologies is present to at least meet the average annual demand. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 175 - -Energy Balance A ----------------------------- -Ensures that demand for each commodity is met in each TimeSlice. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 179-182 - -Energy Balance B ----------------------------- -Ensures that demand for each commodity is met in each Year. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 186 - -Accounting Technology Production/Use ---------------------------------------------- -Accounting equation used to generate a specific intermediate variables: *TotalAnnualTechnologyActivityByMode*. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 190 - -Storage Equations ----------------------------- -This block of equations governs the charging, discharging, and accounting of energy storage systems across multiple time dimensions (season, day type, and time slice) within the model. It ensures energy balance consistency and temporal linkage in storage behavior. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 194-209 - -Storage Constraints ---------------------------------- -This block of equations defines the operational and capacity boundaries for energy storage systems throughout their time resolution ensuring that storage levels remain within physically and technically feasible limits over seasons, day types, and time brackets. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 225-234 - -Storage Investments ----------------------------- -Calculates the total discounted capital costs expenditure for each storage technology in each year. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 238-243 - -Capital Costs --------------------- -Calculates the total undiscounted capital cost expenditure for each technology in each year. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 257 - -Salvage Value --------------------- -Calculates the fraction of the initial capital cost that can be recouped at the end of a technologies operational life. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 261-264 - -Operating Costs --------------------- -Calculates the total variable and fixed operating costs for each technology, in each year. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 268-269 - -Total Capacity Constraints ----------------------------------------- -Ensures that the total capacity of each technology in each year is greater than and less than the user-defined parameters *TotalAnnualMinCapacityInvestment* and *TotalAnnualMaxCapacityInvestment* respectively. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 273-274 - -New Capacity Constraints ------------------------------------ -Ensures that the new capacity of each technology installed in each year is greater than and less than the user-defined parameters *TotalAnnualMinCapacityInvestment* and *TotalAnnualMaxCapacityInvestment* respectively. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 278-279 - -Annual Activity Constraints ------------------------------------------ -Ensures that the total activity of each technology over each year is greater than and less than the user-defined parameters *TotalTechnologyAnnualActivityLowerLimit* and *TotalTechnologyAnnualActivityUpperLimit* respectively. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 283-285 - -Total Activity Constraints -------------------------------------------------- -Ensures that the total activity of each technology over the entire model period is greater than and less than the user-defined parameters *TotalTechnologyModelPeriodActivityLowerLimit* and *TotalTechnologyModelPeriodActivityUpperLimit* respectively. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 289-291 - -Emissions Accounting -------------------------------------------- -Calculates the annual and model period emissions from each technology, for each type of emission. It also calculates the total associated emission penalties, if any. Finally, it ensures that emissions are maintained before stipulated limits that may be defined for each year and/or the entire model period. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 296-305 - -Input To Capacity Ratios -------------------------------------------- -This block defines the technical input requirements associated with the installed or newly added capacity of each technology. These equations ensure that the use of input commodities is proportional to the capacity available or added in the model year, enforcing design-specific efficiency or conversion rates. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 309-310 - -Mode-specific Constraints -------------------------------------------- -This block of constraints governs the total annual activity levels of technologies operating in different modes of operation (e.g., cogeneration modes). These constraints allow the model to control how technologies behave not just in total, but also within each of their defined modes. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 314-317 - -User-defined Constraints -------------------------------------------- -This block introduces a flexible framework for modeling custom constraints that reflect user-defined relationships between technology capacities, new investments, and activity levels. These constraints allow model users to encode additional system rules, targets, or boundaries without modifying the model’s core structure. - -.. literalinclude:: documents/code/model_organized.txt - :language: ampl - :lines: 321-328 \ No newline at end of file diff --git a/docs/source/structure-osemosys/intro.rst b/docs/source/structure-osemosys/intro.rst deleted file mode 100644 index 5f39babe1..000000000 --- a/docs/source/structure-osemosys/intro.rst +++ /dev/null @@ -1,9 +0,0 @@ -########################### -Mathematical model -########################### - -As previously discussed, MUIO serves as an interface for creating and operating OSeMOSYS models. Behind the scenes, -the mathematical model includes the sets, parameters, variables, and equations used in the optimization process. -These elements are commonly referred around linear programming models (further explanation can be found `here `_). -The following sections describe the structure of this mathematical model, with examples provided to illustrate the use of each component. - diff --git a/docs/source/structure-osemosys/parameters.rst b/docs/source/structure-osemosys/parameters.rst deleted file mode 100644 index e99aafd6b..000000000 --- a/docs/source/structure-osemosys/parameters.rst +++ /dev/null @@ -1,380 +0,0 @@ -########################### -Parameters -########################### - -Parameters are user-defined numerical inputs to the model. While the model structure defined by the sets typically remains fixed across scenarios, it is common practice to adjust parameter values for scenario analysis or sensitivity studies. Each parameter is associated with one or more sets. For instance, **CapitalCost[r,t,y]** indicates that capital cost varies by region (r), technology (t), and year (y). The information below provides a list and brief description of the parameters included in the version of OSeMOSYS in MUIO. - -Global Parameters ------------------ - -Discount rate [Region] -+++++++++++++ - -In present value analysis, the discount rate [Region] represents the time preference rate used to “discount” future cash flows into their present value. The concept of time value of money recognizes that a dollar received in the future is worth less than a dollar received today due to factors such as opportunity cost and risk. Therefore, to compare costs and benefits occurring at different points in time, they need to be adjusted to their present value. The discount rate parameter sets this rate of time preference and is used to determine the equivalent value in today’s money of future costs and benefits. -A higher discount rate indicates a higher opportunity cost or a higher required return, which means that future cash flows are worth less in present value terms. Conversely, a lower discount rate means that future cash flows are worth more in present value. -The discount rate is expressed as a fraction (i.e. it will have a value between 0 and 1) and reflects the relevant time preference or opportunity cost of capital. - -Discount rate ldv [Region, Technology] -+++++++++++++ - -The Discount rate ldv [Region, Technology] parameter can be used to specify a technology specific discount rate. It can be set when the user wants a discount rate that is different from the general time preference rate (specified with the Discount rate parameter) to be applied to a technology. For technologies with a technology specific discount rate, the investment will be annualized based on the rate set by the Discount rate ldv parameter and the present value of the resulting series of annual payments will be calculated based on the general time preference rate (Discount rate parameter). -This parameter can for instance be used to adjust for differences in the perceived risk of investment in a technology. For instance, a lower discount rate might be applied for renewable power generation technologies that sell electricity on power purchasing agreements or have access to concessional finance sources, than fossil fuel technologies selling electricity in open markets and are subject to environmental regulation risks. -The Discount rate Idv is expressed as a fraction (i.e. it will have a value between 0 and 1). - -Year Split [Region, Year, Timeslice] -+++++++++++++ -The Year Split [Region, Year, Time-slice] parameter is used to set the duration of each time slice (sub-annual time increment of the model). It is a time-dependent parameter and is specified as a fraction of the total year for each time-slice in each year (i.e. it will have a value between 0 and 1). -For example, if a time-slice represents peak demand (demand during the hour of the day when demand is highest) in one season of the year (e.g. summer) and that season lasts 3 months (i.e. a quarter of the year), then the Year Split for that time slice would be 0.25 (duration of the season as a share of the full year – i.e. 3 months out of 12 months) times 1/24 (proportional duration of the peak hour over as a share of a day – i.e. 1 hour out of 24 hours) , which equals 0.0104. -The summation of the Year Split over one year should be equal to 1 (except for small rounding errors). - -Capital Recovery Factor [Region, Technology] -+++++++++++++ - -The Capital Recovery Factor [Region, Technology] parameter is used to convert a lump-sum capital investment into an equivalent annualized cost over the operational lifetime of a technology. It ensures that capital costs are appropriately distributed over the years during which the asset is used, aligning them with the model’s annual accounting framework. It is calculated in a post-processing step in MUIO. - -PV Annuity [Region, Technology] -+++++++++++++ - -The PV Annuity [Region, Technology] parameter is used to discount recurring annual costs (like Operation & Maintenance) over a technology’s lifetime, bringing them to a present value equivalent at the time of investment. It is calculated in a post-processing step in MUIO. - -Demand Parameters ------------------ - -Accumulated Annual Demand [Region, Year, Commodity] -+++++++++++++ - -OSeMOSYS models are “demand driven” meaning that the objective is to meet user specified demands at the lowest possible cost. Needs for investment and operation of facilities designed to produce a specific commodity are driven by the level of demand for that commodity. -The Accumulated Annual Demand [Region, Year, Commodity] parameter is one of two alternative parameters used to specify such demands (the other being Specified Annual Demand). It is typically used for commodity demands where the exact timing of the supply and demand are not important (e.g. if the commodity is easy to store). This can for instance be used to specify demand for grains. Grains are typically harvested at certain times of the year but consumed throughout the year. The fact that the production and consumption happen at different times of the year does not matter because storage in silos, warehouses or pantries is readily available and cheap. -Accumulated Annual Demand is specified per commodity and can vary from year to year, It sets the level of demand and is specified in the units of the commodity in question. It typically increases over time with rising population and incomes. When the Accumulated Annual Demand is set for a certain commodity, a Specified Annual Demand should not be set for that same commodity. - -Specified Annual Demand [Region, Year, Commodity] -+++++++++++++ - -The Specified Annual Demand [Region, Year, Commodity] parameters is one of two alternative parameters used to specify such demands (the other being Accumulated Annual Demand). It is typically used for commodity demands where the exact timing of the supply and demand is important. This would in particular apply to electricity where supply and demands need to be balanced in real time to ensure reliability and quality of power supply. -Specified Annual Demand is set per commodity and can vary from year to year. It sets the level of demand and is specified in the units of the commodity in question. It typically increases over time with rising population and incomes. It needs to be paired with the Specified Demand Profile parameter which is used to allocate the demand to each time slice. -When the Specified Annual Demand is set for a certain commodity, an Accumulated Annual Demand should not be set for that same commodity. - -Specified Demand Profile [Region, Year, Commodity, Timeslice] -+++++++++++++ - -The Specified Demand Profile [Region, Year, Commodity, Time slice] parameter is used to describe the variation in Specified Annual Demand across different times of the year. More specifically, it sets the share of demand that occurs in each time slice, specified as a fraction of the total demand in that year (a number between 0 and 1). The summation of the Specified Demand Profile over one year should be equal to 1 (except for small rounding errors). -The Specified Demand Profile is set per commodity and can vary from year to year. It needs to be paired with the Specified Annual Demand which is used to set the total demand level. - -Performance Parameters ------------------ - -Availability Factor [Region, Year, Technology] -+++++++++++++ - -The Availability Factor [Region, Year, Technology] parameter is typically used to model the operational constraints or limitations of a particular technology (e.g. to account for time a technology needs to be offline for maintenance or for overall energy availability constraints). It represents the average available capacity as a fraction of the total design capacity. -For example, if a gas-fired power plant has planned maintenance scheduled for 500 hours in a year (approximately 6% of the total year), then the average available capacity is 94% of the total. This is represented by an availability factor of 0.94. -Similarly, if a hydroelectric power plant only has water inflow to produce 60% of the theoretical maximum output of the plant, this can be represented as an availability factor of 0.6. -The Availability Factor is specified for each technology in each year. - -Capacity Factor [Region, Year, Technology, Timeslice] -+++++++++++++ - -The Capacity Factor [Region, Year, Technology, Time slice] parameter is typically used to model seasonal operational constraints or limitations of a particular technology (e.g. to account for time a technology needs to be offline for maintenance or for overall energy availability constraints). It represents the average available capacity as a fraction of the total design capacity for each time slice. It is similar to the Availability Factor parameter but is applied when there are factors outside the control of the operator that impact the technology availability across seasons or time of day. -For example, consider representation of a solar photovoltaic panel in a simple model with one time-slice representing daytime and another time slice representing nighttime. It will generate power during the day power when the sun shines (let us say 50% of design capacity on an average day), but not during the night (battery storage can be represented separately). The Capacity Factor should in this case be set to 0.5 (50%) during the day time-slice and 0 for the night time slice. -The Capacity Factor is specified for each technology, in each time slice in each year. Note that the default value is set to 1, which would mean no seasonal dependencies. For any technology that has no externally induced differences in availability over the course of a year, the default value can therefore be left as is and no data entry is needed. - -Capacity To Activity Unit [Region, Technology] -+++++++++++++ - -The CapacityToActivityUnit [Region, Technology] parameter is used to define the relationship between the capacity of a technology and the activity unit associated with it. It represents the maximum amount of activity that can be performed by a technology if one unit of capacity works at full load for a full year. -For example, if the capacity of a power plant is measured in megawatts (MW) and the activity is measured in terajoules (TJ), the CapacityToActivityUnit parameter will specify how many terajoules one megawatt of capacity can generate in one year (i.e. TJ/MW). -CapacityToActivityUnit is time-independent and defined for each technology. It is specified in the applicable ratio of units of activity and capacity for that technology. - -Input Activity Ratio [Region, Year, Technology, Commodity, Mode of Operation] -+++++++++++++ - -The InputActivityRatio [Region, Year, Technology, Commodity, Mode of Operation] parameter is used to specify how much of an input is needed to support the Activity of a Technology. It specifies how many units of input are needed for each unit of activity. -As an example, consider a natural gas fired power station with a conversion efficiency is 50%. The input to the plant is natural gas and the Activity represents electricity generated. This means that for every unit of electricity generated, 2 units (1/50%) of natural gas are needed. Consequently, the InputActivityRatio should be set to 2 in this case. -The unit of this parameter depends on the units chosen for the input commodity and for the Activity units chosen for the technology. -The InputActivityRatio is specified for each technology/commodity combination. If a technology has 2 or more inputs, then one InputActivityRatio is needed for each pairing. The parameter is time dependent and can vary from year to year. - -Input To New Capacity Ratio [Region, Year, Technology, Commodity] -+++++++++++++ - -The InputToNewCapacityRatio [Region, Year, Technology, Commodity] parameter is used to specify how much of an input is needed to support investment in a Technology. It specifies how many units of input are needed for each unit of new capacity added. This parameter can for instance be used to represent the amount of materials used in the construction of new facilities. -As an example, consider a scenario where a new 2MW wind turbine would require 300 tonnes of steel. The InputToNewCapacityRatio would be the number of tonnes of steel required for each MW of capacity (300 tonnes/2MW = 150 tonnes/MW). -The InputToNewCapacityRatio is specified for each technology/commodity combination. The parameter is time dependent and can vary from year to year. - -Input To Total Capacity Ratio [Region, Year, Technology, Commodity] -+++++++++++++ - -The InputToTotalCapacityRatio [Region, Year, Technology, Commodity] parameter is used to specify how much of an input is needed for ongoing support to maintaining capacity of a Technology. It specifies how many units of input are needed for each unit of total capacity installed. -This parameter can for instance be used to represent the amount of land a technology occupies. As an example, consider a 50 MW solar PV installation that covers 1.5 square kms. The ratio of input (land) to capacity is 1.5/50=0.03, which means that the InputToTotalCapacityRatio parameter should be set to 0.03 square kms per MW. -The InputToTotalCapacityRatio is specified for each technology/commodity combination. The parameter is time dependent and can vary from year to year. - -Output Activity Ratio [Region, Year, Technology, Commodity, Mode of Operation] -+++++++++++++ - -The OutputActivityRatio [Region, Year, Technology, Commodity, Mode of Operation] parameter is used to specify how much output is generated from the Activity of a Technology. It specifies how many units of output are produced for each unit of activity. -As an example, consider maize cultivation. The Activity of the maize cultivation could represent how much land is planted with maize (measured in hectares), while the output would be the number of tonnes of maize produced. If 1,000 hectares of maize cultivation yield 4,500 tonnes, then the ratio of output to activity is 4.5 (4,500/1,000). Consequently, the OutputActivityRatio should be set to 4.5 tonnes per hectare in this case. -The unit of this parameter depends on the units chosen for the output commodity and the activity units set for the technology. -The OutputActivityRatio is specified for each technology/commodity combination. If a technology has 2 or more outputs, then one OutputActivityRatio is needed for each pairing. The parameter is time dependent and can vary from year to year. - -Operational Life [Region, Technology] -+++++++++++++ - -The OperationalLife [Region, Technology] parameter is used to define the lifespan of a technology or system. It represents the number of years a technology or system can be operational before it is decommissioned or needs to be replaced. -The OperationalLife [Region, Technology] parameter is time-independent and defined for each technology. It is specified in number of years. - -Residual Capacity [Region, Year, Technology] -+++++++++++++ - -The Residual Capacity [Region, Year, Technology] parameter represents capacity installed prior to the model period and can be used to specify any existing capital stock available in the base year if the analysis. -Residual Capacity is specified in units of capacity for each technology and should be entered for each year the capital stock is expected to remain available. If capacity is expected to be retired during the model horizon the value provided for this parameter should be reduced accordingly. - -Costing Parameters ------------------ - -Capital Cost [Region, Year, Technology] -+++++++++++++ - -The Capital Cost [Region, Year, Technology] parameter is used to specify the investment cost associated with the construction or installation of a technology. It represents the initial investment required to acquire, construct or expand new technology capacity. -Capital Cost is defined for each technology or infrastructure component in the OSeMOSYS model and represents the cost per unit of capacity. It includes expenses such as equipment, construction, engineering, installation, land acquisition, and any other costs associated with the capital investment. - -Fixed Cost [Region, Year, Technology] -+++++++++++++ - -The Fixed Cost [Region, Year, Technology] parameter is used to specify any costs incurred to keep technology available and operational. It can include items such as salaries, rent, property taxes and insurance amongst others. All operational costs that are independent of the level of Activity (utilization) of the technology should be included. Any costs that vary with the level of Activity such as inputs and other consumables should be specified under the Variable Cost parameter. -Fixed Costs are specified on a per unit of capacity basis (e.g. $/kW) and can change from year to year. - -Variable Cost [Region, Year, Technology, Mode of Operation] -+++++++++++++ - -The Variable Cost [Region, Year, Technology, Mode of Operation] parameter is used to specify any costs incurred to operate a technology. It can include items such as inputs and other consumables amongst others. All operational costs that are dependent on the level of Activity (utilization) of the technology should be included. Any operational costs that are independent of the level of Activity such as salaries, rent, property taxes and insurance etc. should be specified under the Fixed Cost parameter. -Variable Costs are specified on a per unit of activity basis (e.g. $/GJ) and can change from year to year or between different modes of operation. - -Emissions penalty [Region, Emission, Year] -+++++++++++++ - -The emissions penalty [Region, Emission, Year] parameter is used to assign a cost to the release of an emission. It can represent an actual charge such as a tax or penalty, or an external cost that is not formally monetized. A negative value can be used to represent a credit or subsidy. -The AnnualEmissionLimit parameter is defined for each emission and can be changed from year to year. It is specified in currency units per unit of emission (e.g. $/tonne). - -Storage Parameters ------------------ - -Operational Life Storage [Region, Storage] -+++++++++++++ - -The Operational Life Storage [Region, Storage] parameter is used to define the lifespan of a storage asset. It represents the number of years a storage can be operational before it is decommissioned or needs to be replaced. The OperationalLife parameter is time-independent and defined for each storage. It is specified in number of years. - -Capital Cost Storage [Region, Storage, Year] -+++++++++++++ - -The Capital Cost Storage [Region, Year, Storage] parameter is used to specify the investment cost associated with the construction or installation of a storage facility. It represents the initial investment required to acquire, construct or expand storage capacity. Capital Cost Storage is defined for each storage and represents the cost per unit of storage capacity. It includes expenses such as equipment, construction, engineering, installation, land acquisition, and any other costs associated with the capital investment. - -Residual Storage Capacity [Region, Storage, Year] -+++++++++++++ - -The Residual Capacity [Region, Year, Storage] parameter represents storage capacity installed prior to the model period and can be used to specify any existing capital stock available in the base year of the analysis. Residual Capacity is specified in units of capacity for each storage and should be entered for each year the capital stock is expected to remain available. If capacity is expected to be retired during the model horizon the value provided for this parameter should be reduced accordingly. - -Technology To Storage [Region, Technology, Storage, Mode of Operation] -+++++++++++++ - -The Technology To Storage [Region, Technology, Storage, Mode of Operation] parameter is a tag to identify technologies that provide input to storage. It is set to 1 when the link exists and to 0 when there is no link. For example, a utility scale battery may use electricity provided by the transmission grid as input. In this case a value of 1 should be provided for the combination of the transmission grid technology and the battery storage. Technology To Storage is dimensionless and can be provided for each region, technology, storage and mode of operation. It should be set to either 0 (no link) or 1 (link exists). - -Technology from Storage [Region, Technology, Storage, Mode of Operation] -+++++++++++++ - -The Technology from Storage [Region, Technology, Storage, Mode of Operation] parameter is a tag to identify technologies that receive the output from a storage. It is set to 1 when the link exists and to 0 when there is no link. For example, a utility scale battery may provide electricity for distribution to final users. In this case a value of 1 should be provided for the combination of the distribution grid technology and the battery storage. Technology from Storage is dimensionless and can be provided for each region, technology, storage and mode of operation. It should be set to either 0 (no link) or 1 (link exists). - -Storage Level Start [Region, Storage] -+++++++++++++ - -The Storage Level Start [Region, Storage] is used to specify the storage level at the start of the first period. The parameter value is expressed in relation to the maximum capacity of the storage system and given as a fraction (e.g. 0.5 to indicate a storage that is half-full at the start of the model period). - -Min storage charge [Region, Year, Storage] -+++++++++++++ - -The Min storage charge [Region, Year, Storage] parameter is used to specify a lower limit on the amount of storage at any given time. This can for instance be used to represent a storage dam, where a certain minimum water level should be maintained at all times or to restrict the operation of a battery to ensure that it is never fully depleted. The parameter value is expressed in relation to the maximum capacity of the storage system and given as a fraction (e.g. 0.2 to indicate a that the storage level should not drop below 20% of maximum capacity). It is provided for each year for each storage asset in the model. - -Conversion ls [Timeslice, Season] -+++++++++++++ - -Binary parameter linking one TimeSlice to a certain Season. It has value 0 if the TimeSlice does not pertain to the specific season, 1 if it does. - -Conversion ld [Timeslice, DayType] -+++++++++++++ - -Binary parameter linking one TimeSlice to a certain DayType. It has value 0 if the TimeSlice does not pertain to the specific DayType, 1 if it does. - -Conversion lh [Timeslice, DailyTimeBracket] -+++++++++++++ - -Binary parameter linking one TimeSlice to a certain DaylyTimeBracket. It has value 0 if the TimeSlice does not pertain to the specific DaylyTimeBracket, 1 if it does. - -Day Split [Region, Year, Timeslice] -+++++++++++++ - -The Day Split [Region, Year, Timeslice] parameter is used to set the duration of an individual occurrence of each time slice (sub-annual time increment of the model). It is a time-dependent parameter and is specified as a fraction of the total year for each time-slice in each year (i.e. it will have a value between 0 and 1). The parameter is only used in the representation of storage. -For example, if a time-slice represents peak demand (demand during the hour of the day when demand is highest) then the parameter should be set to 1/8760 = 0.000114 (8760 is the number of hours in a year), while if it represents the base load period (e.g. 9pm to 6am = 9 hours) then it should be set to 9/8760 = 0.001027. The DaySplit parameter is provided for each timeslice and can change from year to year. - -Days In Day Type [Region, Year, Season, Daytype] -+++++++++++++ - -The Days In Day Type [Region, Year, Season, Daytype] is used to specify the number of sequential days in a single occurrence of a day type. For example, if a day type represents weekdays the parameter value should be set to 5, while for a day type representing a weekend it should be set to 2. It is specified for each daytype in each season. It can change from year to year although this would only be applicable in special circumstances when the user wishes to change the time representation at a point within the model horizon. - -Capacity Parameters ------------------ - -Capacity Of One Technology Unit [Region, Year, Technology] -+++++++++++++ - -The Capacity Of One Technology Unit [Region, Year, Technology] parameter can be used to ensure that capacity additions only occur in discrete increments. This is typically used for large facilities of a specific design where there is little or no flexibility to scale the size of the investment to needs. -For example, a technology can be used to represent a specific hydropower site and design, which should either be built in full or not at all. This is in contrast to a wind farm for instance, which can be scaled to virtually any size. If the user wants to represent a 500MW hydropower plant, a value of 500 could be provided for the Capacity Of One Technology Unit, to ensure that only investment of 500MW at a time is possible. Investment in multiples of 500MW (e.g. 1,000 MW, 1,500 MW etc.) would still be possible, so if the user wants to avoid this, the Total Annual Max capacity parameter can be used to limit total investment. -Note that use of this parameter can impact solution times considerably as the optimization problem is no longer linear. - -Total Annual Max capacity [Region, Year, Technology] -+++++++++++++ - -Total Annual Max capacity [Region, Year, Technology] parameter is specified when there is an upper restriction on the overall capacity of a particular technology. It establishes a maximum limit on the total capacity within a year. This could for instance be used to ensure that a hydro powerplant representing a specific site does not exceed the estimated potential for that site. -Total Annual Max capacity is specified in units of capacity of the relevant technology and can change from year to year. - -Total Annual Max capacity investment [Region, Year, Technology] -+++++++++++++ - -Total Annual Max capacity investment [Region, Year, Technology] parameter is specified when there is a limitation on how quickly the capacity of a specific technology can be expanded. It sets a direct upper bound on new capacity installations in a year. This could for instance be used restrict investment in rooftop solar to what the domestic industry is currently capable of installing (e.g. due to limitations on skilled labor to install panels) -Total Annual Max capacity investment is specified in units of capacity of the relevant technology and can change from year to year. - -Annual min capacity [Region, Year, Technology] -+++++++++++++ - -Annual min capacity [Region, Year, Technology] parameter is specified when there is a minimum requirement for the overall capacity of a particular technology. It establishes a lower limit on the total capacity within a year. This could for instance be used to enforce a regulatory requirement (e.g. impose a certain target for total installed wind capacity in a given year). -Annual min capacity is specified in units of capacity of the relevant technology and can change from year to year. - -Annual min capacity investment [Region, Year, Technology] -+++++++++++++ - -Annual min capacity investment [Region, Year, Technology] parameter is specified when there is a minimum requirement for investment in a technology in a given year. It sets a lower bound on total capacity installations in a year. This could for instance be used to ensure the construction of a plant for which the commitment to invest has already been made (e.g. a facility that is already under construction but not expected to be operational until a future year). -Annual min capacity investment is specified in units of capacity of the relevant technology and can change from year to year. - -Activity Parameters ------------------ - -Technology Annual Activity by Mode Lower Limit [Region, Year, Technology, Mode of Operation] -+++++++++++++ - -Technology Annual Activity by Mode Lower Limit [Region, Year, Technology, Mode of Operation] parameter is specified when there is a clear lower restriction on the overall operation of a particular technology. It establishes a lower limit on the total activity of a technology within a year for each mode of operation. This could for instance be used to ensure that the operation of any “must-run” facilities is within requirements, or if there are legal mandates requiring a certain minimum output (e.g. a goal of producing a certain level of biofuels in a given year). -Technology Annual Activity by Mode Lower Limit is specified in units of activity of the relevant technology and can change from year to year. - -Technology Annual Activity by Mode Upper Limit [Region, Year, Technology, Mode of Operation] -+++++++++++++ - -Technology Annual Activity by Mode Upper Limit [Region, Year, Technology, Mode of Operation] parameter is specified when there is a clear maximum restriction on the overall operation of a particular technology. It establishes an upper limit on the total activity of a technology within a year for each mode of operation. This could for instance be used to ensure that certain renewable flow (e.g. fresh water) stay below sustainable extraction levels or that mandated maximum allowable output restrictions are observed. -Technology Annual Activity by mode Upper Limit is specified in units of activity of the relevant technology and can change from year to year. - -Technology Activity Decrease By Mode Limit [Region, Year, Technology, Mode of Operation] -+++++++++++++ - -Technology Activity Decrease By Mode Limit [Region, Year, Technology, Mode of Operation] parameter is used to ensure that the activity of a technology does not decrease by more than a certain share each year. For example, a parameter value of 0.05 would indicate that activity could only drop by 5% from one year to the next. This can be used to represent market friction, when it is thought that market actors will not be quick to abandon a technology. -Technology Activity Decrease By Mode Limit is time dependent and can change from year to year. - -Technology Activity Increase By Mode Limit [Region, Year, Technology, Mode of Operation] -+++++++++++++ - -Technology Activity Increase By Mode Limit [Region, Year, Technology, Mode of Operation] parameter is used to ensure that the activity of a technology does not increase by more than a certain share each year. For example, a parameter value of 0.1 would indicate that activity could only increase by 10% from one year to the next. This can be used to represent market friction, when it is thought that the rate of market adoption will be limited to a certain growth rate. -Technology Activity Increase By Mode Limit is time dependent and can change from year to year. - -Total Technology Annual Activity Lower Limit [Region, Year, Technology] -+++++++++++++ - -Total Technology Annual Activity Lower Limit [Region, Year, Technology] parameter is specified when there is a clear lower restriction on the overall operation of a particular technology. It establishes a lower limit on the total activity (from all modes of operation) within a year. This could for instance be used to ensure that the operation of any “must-run” facilities is within requirements, or if there are legal mandates requiring a certain minimum output (e.g. a goal of producing a certain level of biofuels in a given year). -Total Technology Annual Activity Lower Limit is specified in units of activity of the relevant technology and can change from year to year. - -Total Technology Annual Activity Upper Limit [Region, Year, Technology] -+++++++++++++ - -Total Technology Annual Activity Upper Limit [Region, Year, Technology] parameter is specified when there is a clear maximum restriction on the overall operation of a particular technology. It establishes an upper limit on the total activity (from all modes of operation) within a year. This could for instance be used to ensure that certain renewable flows (e.g. fresh water) stay below sustainable extraction levels or that mandated maximum allowable output restrictions are observed. -Total Technology Annual Activity Upper Limit is specified in units of activity of the relevant technology and can change from year to year. - -Total Technology Model Period Activity Lower Limit [Region, Technology] -+++++++++++++ - -The Total Technology Model Period Activity Lower Limit [Region, Technology] parameter is used to impose a minimum level of cumulative activity for a technology over the entire model horizon (i.e. all model years) and all modes of operation. The sum of activity for the technology over all model years must be greater than the specified amount. -The Total Technology Model Period Activity Lower Limit parameter is time-independent and defined for each technology. It is specified in the applicable units of activity for that technology. - -Total Technology Model Period Activity Upper Limit [Region, Technology] -+++++++++++++ - -The Total Technology Model Period Activity Upper Limit [Region, Technology] parameter is used to impose a maximum level of cumulative activity for a technology over the entire model horizon (i.e. all model years) and all modes of operation. The sum of activity for the technology over all model years must be less than the specified amount. -This parameter can for instance be used to represent the total extent of an exhaustible resource, such as an oil reservoir or a coal deposit. In this case the parameter value should be set equal to the estimated recoverable reserve of the resource, beyond which further extraction would not be possible. -The Total Technology Model Period Activity Upper Limit parameter is time-independent and defined for each technology. It is specified in the applicable units of activity for that technology. - -UDC Parameters ------------------ -User-defined Constraints (UDCs) can be used to specify relationships between model variables. They can be created as either equalities or inequalities and consist of a constant (representing the right-hand side of the equation or inequality) and a set of multipliers for different variables (Capacity, New Capacity and Activity representing the left-hand side). -.. math:: - - \sum_{t} \left( - \text{UDC\_Multiplier\_New\_Capacity}_t \cdot \text{New\_Capacity}_t + - \text{UDC\_Multiplier\_Total\_Capacity}_t \cdot \text{Total\_Capacity}_t + - \text{UDC\_Multiplier\_Activity}_t \cdot \text{Activity}_t - \right) \leq \text{UDC\_Constant} - -UDC Multiplier Activity [Region, Year, Technology, Constraint] -+++++++++++++ - -The UDC Multiplier Activity sets a technology specific value that will be multiplied with Activity for each technology on the left-hand side of the equality/inequality as shown in the equation below, where t represents the technology and n is the total number of technologies. -For example, if the user wishes to set a target of 40% renewable power generation as a share of total power generation, the UDC constant can be set to 0, a value of 0.4 can be specified for the UDC Multiplier Activity for all non-renewable power generation technologies and a value of -0.6 (1-0.4) can be specified for all renewable technologies. This means that the left-hand side of the equation should equal the target value (40%) times total generation minus total renewable generation, which will need to be less than the UDC constant value (zero) so that renewable generation is always higher than 40% of total generation. Note the transposition (the negative 0.4) that has taken place because renewable generation is also part of total generation. -The UDC multipliers are constraint, year and technology specific, so that a technology that is included in more than one constraint can have different multiplier values for each constraint, technologies in the same constraint can have different multiplier values and that the multiplier values can vary from year to year. - -UDC Multiplier New Capacity [Region, Year, Technology, Constraint] -+++++++++++++ - -The UDC Multiplier New Capacity sets a technology specific value that will be multiplied with New Capacity for each technology on the left-hand side of the equality/inequality as shown in the equation below, where t represents the technology and n is the total number of technologies. -For example, if the user wishes to restrict the total investment in total wind power capacity to 500MW per year, the UDC constant can be set to 500 and a value of 1 can be specified for the UDC Multiplier New Capacity for all wind power technologies (and zero for everything else). This means that the left-hand side of the equation should equal total new capacity and will be restricted by the inequality to always remain below or equal to the UDC constant value. -The UDC multipliers are constraint, year and technology specific, so that a technology that is included in more than one constraint can have different multiplier values for each constraint, technologies in the same constraint can have different multiplier values and that the multiplier values can vary from year to year. - -UDC Total Capacity [Region, Year, Technology, Constraint] -+++++++++++++ - -The UDC Multiplier Total Capacity sets a technology specific value that will be multiplied with Total Capacity for each technology on the left-hand side of the equality/inequality as shown in the equation below, where t represents the technology and n is the total number of technologies. -For example, if the user wishes to restrict the total hydropower capacity to 2000MW per year, the UDC constant can be set to 2000 and a value of 1 can be specified for the UDC Multiplier Total Capacity for all hydro power technologies (and zero for everything else). This means that the left-hand side of the equation should equal total capacity of hydro power technologies and will be restricted by the inequality to always remain below or equal to the UDC constant value. -The UDC multipliers are constraint, year and technology specific, so that a technology that is included in more than one constraint can have different multiplier values for each constraint, technologies in the same constraint can have different multiplier values and that the multiplier values can vary from year to year. - -UDC Constant [Region, Year, Constraint] -+++++++++++++ - -The UDC Constant sets the right-hand side value of inequality or equality as per the equation below, where t represents the technology and n is the total number of technologies. -For example, if the user wishes to restrict the total investment in total wind power capacity to 500MW per year, the UDC constant can be set to 500 and a value of 1 can be specified for the UDC Multiplier New Capacity for all wind power technologies (and zero for everything else). This means that the left-hand side of the equation should equal total new capacity and will be restricted by the inequality to always remain below or equal to the UDC constant value. -The UDC multipliers are constraint, year and technology specific, so that a technology that is included in more than one constraint can have different multiplier values for each constraint, technologies in the same constraint can have different multiplier values and that the multiplier values can vary from year to year. - -UDC Tag [Region, Constraint] -+++++++++++++ - -This parameter specifies whether the constraint is defined as an equality or an inequality. - -Emission Parameters ------------------ - -Emission Activity Ratio [Region, Year, Technology, Emission, Mode of operation] -+++++++++++++ - -The Emission Activity Ratio [Region, Year, Technology, Emission, Mode of operation] is used to set an emission factor for a technology. It defines the relationship between the activity of a technology and its emissions, by indicating how many emission units are released for every unit of activity. -For example, the combustion of 1 GJ of natural gas will release 50.2 tonnes of CO2 into the atmosphere. If a natural gas fired power plant has an efficiency of 50% then 2 GJ of natural gas is needed to generate 1 GJ of electricity. The Emission Activity Ratio is the ratio of emissions (2*50.2=100.4 tonnes CO2) to activity (1 GJ of generated electricity) and should be set to 100.4 (t CO2/GJ). -Emission Activity Ratio is technology and emission specific and can change from year to year and between modes of operation. - -AnnualEmissionLimit [Region, Emission, Year] -+++++++++++++ - -The AnnualEmissionLimit [Region, Emission, Year] parameter is used to set an upper limit on emissions in a particular year. It will set a total maximum allowable cap on emissions that cannot be exceeded. -This parameter can for instance be used to model carbon mitigation scenarios. GHG mitigation goals are often specified as a target in a specific year (e.g. 30% reductions by 2030) and this parameter can be used to represent this. -The AnnualEmissionLimit parameter is defined for each emission and can be changed from year to year. It is specified in the applicable units of that emission. - -Model Period Emission Limit [Region, Emission] -+++++++++++++ - -The parameter Model Period Emission Limit [Region, Emission] parameter is used to set a cumulative limit on emissions over the entire model horizon (i.e. all years). -The parameter can for instance be used to model carbon mitigation scenarios and carbon budgets. Since climate change impacts are ultimately determined by total cumulative greenhouse gas emission (GHG), reducing total emissions over time is more important than reaching an emission target for a given year. This parameter therefore lets users directly limit GHG impacts on climate, while allowing for the emission reduction pathway to be optimized. -The ModelPeriodEmissionLimit parameter is time-independent and defined for each emission. It is specified in the applicable units of that emission. - -Emission To Activity Change Ratio [Region, Year, Technology, Emission, Mode of Operation] -+++++++++++++ - -The Emission To Activity Change Ratio [Region, year, technology, emission, mode of operation] is an emission factor applied to the change in Activity of a technology from one year to the next. It specifies how many units of emission are released for every unit of change in activity compared to the previous year. -This parameter can for instance be used to model land-use change emission. A decrease in forested area for example, would be evident in the reduction in activity (land coverage) of the technology representing forests. By providing this ratio (i.e. the carbon stored per unit of forested area) the emissions associated with the loss of forests can be calculated. Since land is a carbon sink, the emission Emission To Activity Change Ratio will usually be negative. -Emission To Activity Change Ratio is technology and emission specific and can change from year to year and between modes of operation. diff --git a/docs/source/structure-osemosys/sets.rst b/docs/source/structure-osemosys/sets.rst deleted file mode 100644 index 0a5892f51..000000000 --- a/docs/source/structure-osemosys/sets.rst +++ /dev/null @@ -1,92 +0,0 @@ -Sets -================================= - -The ‘sets’ in OSeMOSYS define the structural elements of the model, which are generally independent of specific scenarios being analyzed. They establish the time domain and its granularity, the spatial coverage, the technologies, and the energy carriers (commodities) included in the system, among other elements. These sets serve as the foundation for indexing variables and parameters. -For example, when a variable is indexed by the set YEAR, it is represented as variablename[y], meaning it is computed for each year listed in the YEAR set. Similarly, other variables and parameters are defined over relevant sets to structure the relationships between technologies, fuels, storage, emissions, and time periods. The sets of OSeMOSYS in MUIO are presented in the below. - -REGION [r] -~~~~~~~~~~~~~~ -It defines the regions to be modelled, such as different countries. For each region, the supply-demand balance for all commodities is ensured, including trade with other regions. In some cases, it may be computationally more efficient to model multiple countries within the same region and differentiate them using ad hoc commodities and technologies. In MUIO, this set is not available, so the second approach should be used for multi-regional modelling. - -TECHNOLOGY [t] -~~~~~~~~~~~~~~ -It includes any element of the integrated system that changes a commodity from one form to another, uses it or supplies it. All system components are set up as a ‘technology’ in OSeMOSYS. As the model is an abstraction, the modeller is free to interpret the role of a technology at will, where relevant. It may for example represent a single real technology (such as a power plant) or can represent a heavily aggregated collection of technologies (such as the stock of several million light bulbs) or may even simply be a ‘dummy technology’, perhaps used for accounting purposes. - -COMMODITY [f] -~~~~~~~~~~~~~~ -It includes any commodity, fuel, service, or proxy that enters or exits technologies. These can be aggregated groups, individual flows, or artificially separated, depending on the analysis requirements. For example, a commodity could be electricity from power plants, land for crop cultivation, or water for public consumption. - -EMISSION [e] -~~~~~~~~~~~~~~ -It includes any type of emissions that may result from the operation of the defined technologies. Typical examples include atmospheric emissions of greenhouse gases, such as CO₂. - -STORAGE [s] -~~~~~~~~~~~~~~ -It includes storage facilities in the model, such as dams in a hydropower system or large-scale batteries in the electricity network. - -YEAR [y] -~~~~~~~~~~~~~~ -It represents the model's time frame and includes all years considered in the study. For example: 2021, 2022, …, 2050. - -SEASON [ls] -~~~~~~~~~~~~~~ -It provides a sequential numerical indication of the seasons accounted for in the model (e.g., winter, intermediate, summer) and their order. This set is required when storage facilities are included in the model. - -DAYTYPE [ld] -~~~~~~~~~~~~~~ -It provides a sequential numerical indication of the day types considered in the model (e.g., workday, weekend) and their order. This set is required when storage facilities are included in the model. - -DAILYTIMEBRACKET [lh] -~~~~~~~~~~~~~~ -It provides a sequential numerical indication of how the day is divided into parts (e.g., night, morning, afternoon, evening) and their order. This set is required when storage facilities are included in the model. - -TIMESLICE [l] -~~~~~~~~~~~~~~ -It defines the temporal resolution of the model by splitting each modelled year into representative time slices. This approach, common in several energy system modelling tools (e.g., MESSAGE, MARKAL, TIMES), allows for separate assessment of high- and low-demand periods, particularly for commodities that are costly to store. -While it is possible to create 8,760 time slices to represent each hour of the year, this approach is often computationally intensive. To optimize efficiency, time slices are typically grouped. The annual demand may be divided into aggregate seasons (e.g., summer, winter, intermediate), which can then be further subdivided into day types (e.g., workdays, weekends) and, if necessary, into finer time intervals (e.g., day and night) based on demand variations. - -MODE_OF_OPERATION [m] -~~~~~~~~~~~~~~ -This defines the number of operational modes a technology can have. If a technology can use various input or output commodities and choose among different combinations (i.e., any linear combination) of these inputs or outputs, each combination can be considered a separate mode of operation. For example, a combined heat and power (CHP) plant may operate in one mode to produce heat and in another mode to generate electricity. - -STORAGEINTRADAY [s] -~~~~~~~~~~~~~~ -It is a subset of STORAGE that includes storage technologies capable of charging and discharging within a single day (i.e., short-duration storage). This typically includes batteries and other fast-response storage systems. - -STORAGEINTRAYEAR [s] -~~~~~~~~~~~~~~ -It is subset of STORAGE that includes storage technologies capable of storing energy over long periods, typically across multiple days, weeks, or even seasons. This is also referred to as long-duration or seasonal storage, such as pumped hydro storage and hydrogen storage. - -UDC [u] -~~~~~~~~~~~~~~ -The set UDC (User Defined Constraints) allows users to introduce custom constraints beyond the standard OSeMOSYS equations. This adds flexibility to tailor the model for specific policy, technical, or economic constraints that aren't explicitly included in the default formulation. For example, UDCs can represent a reserve margin in a power system or enforce a specific renewable energy target in a sector. - -MODEperTECHNOLOGY{TECHNOLOGY} within MODE_OF_OPERATION -~~~~~~~~~~~~~~ -It defines the operational modes available for each technology. This means that not every technology will use all possible modes, but only a subset relevant to its function. - -MODExTECHNOLOGYperFUELout{COMMODITY} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies and their modes of operation can produce specific commodities (fuels, electricity, heat, etc.) as outputs. This ensures that not every technology-mode combination produces all fuels, but only a subset relevant to the system. - -MODExTECHNOLOGYperFUELin{COMMODITY} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies and their modes of operation require specific commodities (fuels, electricity, heat, etc.) as inputs. This ensures that only appropriate fuel inputs are assigned to each technology and mode. - -MODExTECHNOLOGYperSTORAGEto{STORAGE} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies and their modes of operation can store/charge energy into specific storage technologies. This ensures that only relevant technologies and modes can charge energy, preventing incorrect assignments. - -MODExTECHNOLOGYperSTORAGEfrom{STORAGE} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies and their modes of operation can extract/discharge energy from specific storage technologies. This ensures that only relevant technologies and modes can discharge energy from storage, preventing incorrect assignments. - -MODExTECHNOLOGYperEMISSION{e in EMISSION} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies (in specific modes of operation) emit specific emissions. This ensures that only technologies that actually produce emissions are assigned them, preventing incorrect emission accounting. - -MODExTECHNOLOGYperEMISSIONChange{e in EMISSION} within MODE_OF_OPERATION cross TECHNOLOGY -~~~~~~~~~~~~~~ -It defines which technologies (in specific modes of operation) can reduce or sequester specific emissions. This ensures that only relevant technologies and modes are assigned emission reduction capabilities, preventing incorrect accounting of emission reductions. - - diff --git a/docs/source/structure-osemosys/variables.rst b/docs/source/structure-osemosys/variables.rst deleted file mode 100644 index 9af944277..000000000 --- a/docs/source/structure-osemosys/variables.rst +++ /dev/null @@ -1,229 +0,0 @@ -########################### -Variables -########################### - -The variables represent the outputs generated by the model. Like the parameters, they are also functions of elements belonging to one or more sets. The following subsections provide a list and brief description of all the variables computed by the OSeMOSYS code. In MUIO, only a selection of these variables (marked with an asterisk) is available for visualization. However, the complete set of variables can be downloaded and plotted externally, based on the modeller’s requirements. - -Demand Variables ------------------ - -Demand [Region, Timeslice, Commodity, Year] -+++++++++++++ - -Demand for one commodity in one time slice. Domain: >= 0 - - -Costing Variables ------------------ - -Annual Fixed Operating Cost [Region, Technology, Year] -+++++++++++++ - -Annual fixed operating cost of technology t. Derived from the variable TotalCapacityAnnual and the parameter FixedCost. Domain: >= 0 - -Annual Variable Operating Cost [Region, Technology, Year] -+++++++++++++ - -Annual variable operating cost of technology t. Derived from the variable TotalAnnualTechnologyActivityByMode and the parameter VariableCost. No restrictions on the domain. - -Capital Investment [Region, Technology, Year] -+++++++++++++ - -Undiscounted investment in new capacity of technology t. It is a function of the variable NewCapacity and the parameter CapitalCost. Domain: >= 0 - -SalvageValue [Region, Technology, Year] -+++++++++++++ - -Salvage value of technology t in year y, as a function of the parameter OperationalLife. Domain: >= 0 - -Discounted Salvage Value [Region, Technology, Year] -+++++++++++++ - -Salvage value of technology t, discounted through the parameter DiscountRate. Domain: >= 0 - -Technology Emissions Penalty [Region, Technology, Year] -+++++++++++++ - -Total undiscounted annual cost of all emissions generated by technology t. It is a function of the AnnualTechnologyEmission and the parameter EmissionPenalty. No restrictions on the domain. - - -Storage Variables ------------------ - -New Storage Capacity [Region, Storage, Year] -+++++++++++++ - -Capacity of newly installed storage in year y. Domain: >= 0 - -Salvage Value Storage [Region, Storage, Year] -+++++++++++++ - -Salvage value of storage facility s in year y, as a function of the parameter OperationalLifeStorage. Domain: >= 0 - -Storage Level Year Start [Region, Storage, Year] -+++++++++++++ - -Level of stored commodity in storage facility s in the first time step of year y. Domain: >= 0 - -Storage Level Year Finish [Region, Storage, Year] -+++++++++++++ - -Level of stored commodity in storage facility s in the last time step of year y. Domain: >= 0 - -Storage Level Season Start [Region, Storage, Season, Year] -+++++++++++++ - -Level of stored commodity in storage facility s in the first time step of season ls. Domain: >= 0 - -Storage Level Day Type Start [Region, Storage, Season, Daytype, Year] -+++++++++++++ - -Level of stored commodity in storage facility s in the first time step of daytype ld. Domain: >= 0 - -Storage Level Day Type Finish [Region, Storage, Season, Daytype, Year] -+++++++++++++ - -Level of stored commodity in storage facility s in the last time step of daytype ld. Domain: >= 0 - -Rate Of Net Storage Activity [Region, Storage, Season, Daytype, Dailytimebracket, Year] -+++++++++++++ - -Net charging/discharging rate within the intraday time bracket. No restrictions on the domain. - -Net Charge Within Year [Region, Storage, Season, Daytype, Dailytimebracket, Year] -+++++++++++++ - -Net quantity of commodity charged to storage facility s in year y. It is a function of the variable RateOfNetStorageActivity and it can be negative. No restrictions on the domain. - -Net Charge Within Day [Region, Storage, Season, Daytype, Dailytimebracket, Year] -+++++++++++++ - -Net quantity of commodity charged to storage facility s in daytype ld. It is a function of the variable RateOfNetStorageActivity and can be negative. No restrictions on the domain. - -Storage Lower Limit [Region, Storage, Year] -+++++++++++++ - -Minimum allowed level of stored commodity in storage facility s, as a function of the storage capacity and the user-defined MinStorageCharge ratio. Domain: >= 0 - -Storage Upper Limit [Region, Storage, Year] -+++++++++++++ - -Maximum allowed level of stored commodity in storage facility s. It corresponds to the total existing capacity of storage facility s (summing newly installed and pre-existing capacities). Domain: >= 0 - -Accumulated New Storage Capacity [Region, Storage, Year] -+++++++++++++ - -Cumulative capacity of newly installed storage from the beginning of the time domain to year y. Domain: >= 0 - -Capital Investment Storage [Region, Storage, Year] -+++++++++++++ - -Undiscounted investment in new capacity for storage facility s. Derived from the NewStorageCapacity and the parameter CapitalCostStorage. Domain: >= 0 - -Discounted Capital Investment Storage [Region, Storage, Year] -+++++++++++++ - -Investment in new capacity for storage facility s, discounted through the parameter DiscountRate. Domain: >= 0 - -Discounted Salvage Value Storage [Region, Storage, Year] -+++++++++++++ - -Salvage value of storage facility s, discounted through the parameter DiscountRate. Domain: >= 0 - -Total Discounted Storage Cost [Region, Storage, Year] -+++++++++++++ - -Difference between the discounted capital investment in new storage facilities and the salvage value in year y. Domain: >= 0 - - -Capacity Variables ------------------ - -Accumulated New Capacity [Region, Technology, Year] -+++++++++++++ - -Cumulative newly installed capacity of technology t from the beginning of the time domain to year y. Domain: >= 0 - -New Capacity [Region, Technology, Year] -+++++++++++++ - -Newly installed capacity of technology t in year y. Domain: >= 0 - -NumberOfNewTechnologyUnits [Region, Technology, Year] -+++++++++++++ - -Number of newly installed units of technology t in year y, as a function of the parameter CapacityOfOneTechnologyUnit. Domain: ≥ 0, integer - -Total Capacity Annual [Region, Technology, Year] -+++++++++++++ - -Total existing capacity of technology t in year y (sum of cumulative newly installed and pre-existing capacity). Domain: >= 0 - - -Activity Variables ------------------ - -Rate Of Activity [Region, Timeslice, Technology, Mode, Year] -+++++++++++++ - -Intermediate variable. It represents the activity of technology t in one mode of operation and in time slice l, if the latter lasted the whole year. Domain: ≥ 0 - -Rate Of Total Activity [Region, Technology, Timeslice, Year] -+++++++++++++ - -Sum of the RateOfActivity of a technology over the modes of operation. Domain: ≥ 0 - -Production By Technology [Region, Timeslice, Technology, Commodity, Year] -+++++++++++++ - -Production of commodity f by technology t in time slice l. Domain: ≥ 0 - -Total Annual Technology Activity By Mode [Region, Technology, Mode_of_Operation, Year] -+++++++++++++ - -Annual activity of technology t in mode of operation m. Domain: >= 0 - -Total Technology Annual Activity [Region, Technology, Year] -+++++++++++++ - -Total annual activity of technology t. Domain: >= 0 - -Total Technology Model Period Activity [Region, Technology] -+++++++++++++ - -Sum of the TotalTechnologyAnnualActivity over the years of the modelled period. Domain: >= 0 - -Trade [Region, Region, Timeslice, Commodity, Year] -+++++++++++++ - -Quantity of commodity f traded between region r and rr in time slice l. No restrictions on the domain. - -Input To New Capacity [Region, Technology, Commodity, Year] -+++++++++++++ - -Total input commodity required for new capacity installation. It is a function of the variable NewCapacity and the parameter InputToNewCapacityRatio . Domain: >= 0 - -Input To Total Capacity [Region, Technology, Commodity, Year] -+++++++++++++ - -Total input commodity needed to support the total installed capacity. Derived from the variable TotalCapacityAnnual and the parameter InputToTotalCapacityRatio. Domain: >= 0 - - -Emission Variables ------------------ - -Annual Technology Emission By Mode [Region, Technology, Emission, Mode of Operation, Year] -+++++++++++++ - -Annual emission of agent e by technology t in mode of operation m. Derived from the variable RateOfActivity and the parameter EmissionActivityRatio. No restrictions on the domain. - -Annual Technology Emission [Region, Technology, Emission, Year] -+++++++++++++ - -Sum of the variable AnnualTechnologyEmissionByMode over the modes of operation. No restrictions on the domain. - -Emission By Activity Change [Region, Technology, Emission, Mode_of_Operation, Year] -+++++++++++++ - -Emission changes due to inter-annual activity variation. No restrictions on the domain. - diff --git a/docs/source/user-guide/creating.rst b/docs/source/user-guide/creating.rst deleted file mode 100644 index c16ccf21c..000000000 --- a/docs/source/user-guide/creating.rst +++ /dev/null @@ -1,47 +0,0 @@ -########################### -Creating a Model in MUIO -########################### - -MUIO serves as an effective tool to streamline the process of creating your first model with OSeMOSYS. For a step-by-step guide on how to do this, please watch our YouTube video, where we demonstrate how to build a simple energy model using MUIO. -[Link to be updated soon]. - -If you’re interested in learning how to build a complete energy system model from scratch, we invite you to join the free and open online course offered by The Open University. This course provides a comprehensive curriculum with lectures and hands-on exercises, guiding you through the entire modelling process using MUIO. - -If you're interested in specific topics, you can explore individual lectures based on your area of interest, as outlined in the table below. - -To join the course, please visit the following link: `OU course `_ - -+-------------+-----------------------------------------------------------------------------------------------------------+ -| Lecture ID | Lecture name | -+=============+===========================================================================================================+ -| 1 | Energy system modelling for energy planning and sustainable development | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 2 | Basics of energy system modelling | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 3 | Naming convention and time representation | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 4 | Energy demands and their representation | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 5 | Primary energy supply | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 6 | Fossil fuel power plants, distribution and transmission | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 7 | Biomass, geothermal, hydro and nuclear power plants (non-variable low-emission technologies) | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 8 | Solar and wind power plants, off-grid technologies | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 9 | Energy storage modelling | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 10 | Emissions and capacity reserve representation | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 11 | Residential, commercial and public sectors modelling | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 12 | Industrial sector modelling | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 13 | Transport sector modelling | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 14 | Model calibration | -+-------------+-----------------------------------------------------------------------------------------------------------+ -| 15 | Scenario design | -+-------------+-----------------------------------------------------------------------------------------------------------+ - diff --git a/docs/source/user-guide/overview.rst b/docs/source/user-guide/overview.rst deleted file mode 100644 index 4551b8a98..000000000 --- a/docs/source/user-guide/overview.rst +++ /dev/null @@ -1,131 +0,0 @@ -########################### -Overview of MUIO -########################### - -Home tab -+++++++++++++ - -Once the software is installed on your desktop computer, you can open it, and the Home tab will appear. Here, you’ll find a list of all available models. If you are a new user, the only model initially available will be the default one, called CLEWs demo. - -For each model, you have five options: - -1. Description of the model – Provides a general overview of the model. -2. Configure model – Allows you to modify the model’s structure and parameters. -3. Backup model – Downloads a copy of the model to your computer. -4. Copy model – Creates a duplicate of the model. -5. Delete model – Removes the model from the list. - -.. image:: ../_static/hometab.png - :alt: Hometab - :width: 700px - :align: center - -In the Home tab, you also have two additional options for uploading models: -1. Restore model – Allows you to upload a model in the MUIO-specific format, such as those created using the Backup model option described earlier. -2. Import model – Enables you to upload a model in an Excel-based format (e.g., a CLICSAND file) using otoole. For more information, please visit: `CCG Youtube channel `_ - -.. image:: ../_static/hometab2.png - :alt: Hometab2 - :width: 700px - :align: center - -To select a model, either click on its name in the list or use the Select Model option in the top menu bar. - -.. image:: ../_static/hometab3.png - :alt: Hometab3 - :width: 700px - :align: center - -Parameters and variables -+++++++++++++ - -It displays a list of model parameters and variables, along with their associated sets, default values, and guidance on unit specification. You can update the default values and units as needed to suit the requirements of your modelling work. - -.. image:: ../_static/parameters.png - :alt: Parameters - :width: 700px - :align: center - -Configure model -+++++++++++++ - -If no model is selected, the Configure model option allows you to create a new one. In this case, simply enter a model name and click Save new model. - -.. image:: ../_static/configure.png - :alt: Configure - :width: 700px - :align: center - -Once a model is created or selected, you can create or edit any of its set components (e.g., timeslices, years, commodities, technologies, etc.). In this module, you will build the structure of your model by navigating through each of the available tabs. There are nine tabs in total that you can modify: - -1. Model Data – Define the number of modes of operation and the currency unit, as well as the name and description of your model. -2. Time Sets – Define the temporal resolution of your model in terms of years and timeslices. If you are working with storage technologies, you can also create seasons, day types, and daily time brackets. -3. Commodities – Define the various commodities or fuels used in your model. -4. Emissions – Define the types of emissions included in your model. -5. Technology Groups – An optional feature that allows you to categorize technologies. -6. Technologies – Define the technologies to be included in your model. -7. Constraints – Define any User-Defined Constraints (UDCs), if applicable. -8. Scenarios – Set up different scenarios within one model to modify specific parameters for different cases. - -.. image:: ../_static/configure2.png - :alt: Configure2 - :width: 700px - :align: center - -Data entry -+++++++++++++ - -In this tab, you can enter parameter data. When selected, a list of available parameters is displayed. The search function allows you to quickly filter and locate the desired parameter(s). Once selected, you can input the corresponding data for the chosen parameter. Additionally, options in the upper right corner allow you to save data, adjust the number of decimal places, or export the grid to an Excel file. - -.. image:: ../_static/dataentry.png - :alt: Dataentry - :width: 700px - :align: center - -Model diagram -+++++++++++++ - -Displays the Reference Energy System (RES) represented in the model. Two viewing options are available: - -1. Dynamic – Allows user input to customize what information is displayed and how it is presented. -2. Simple – A static view showing the RES as boxes and lines. - -.. image:: ../_static/modeldiagram.png - :alt: Modeldiagram - :width: 700px - :align: center - -.. image:: ../_static/modeldiagram2.png - :alt: Modeldiagram2 - :width: 700px - :align: center - -View data -+++++++++++++ - -This tab enables you to view all parameter data entered for a specific technology, commodity, or emission. It is especially useful for quickly identifying potential data entry errors and for facilitating model debugging. - -.. image:: ../_static/viewdata.png - :alt: Viewdata - :width: 700px - :align: center - -Running a model -+++++++++++++ - -In the Run tab, you can create a case to execute, which functions as an instance of the model. Within a case, you can select one or more scenarios that represent variations in specific parameters. - -.. image:: ../_static/runmodel.png - :alt: Runmodel - :width: 700px - :align: center - -Results visualization -+++++++++++++ - -In this tab, you can display model results (output variables) for executed cases. Users can customize the chart or table layout, apply filters, and further tailor the results view to their needs using pivot table functionality. - -.. image:: ../_static/results.png - :alt: Results - :width: 700px - :align: center \ No newline at end of file diff --git a/env.yml b/env.yml new file mode 100644 index 000000000..a22535c0a --- /dev/null +++ b/env.yml @@ -0,0 +1,13 @@ +name: muio +channels: + - defaults + - bioconda + - conda-forge +dependencies: + - python<=3.11 # see PR 213 + - pip>=24.0 + - snakemake>=8 + - glpk>=5.0 + - flask_cors + - boto3 + - waitress \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index f1a065dda..652871000 100644 Binary files a/requirements.txt and b/requirements.txt differ